diff --git a/Makefile b/Makefile index ebca3de..cc7b1bb 100644 --- a/Makefile +++ b/Makefile @@ -10,8 +10,8 @@ include $(DEVKITARM)/base_rules IPL_LOAD_ADDR := 0x40003000 LPVERSION_MAJOR := 1 -LPVERSION_MINOR := 8 -LPVERSION_BUGFX := 5 +LPVERSION_MINOR := 9 +LPVERSION_BUGFX := 0 ################################################################################ @@ -40,8 +40,13 @@ CUSTOMDEFINES := -DIPL_LOAD_ADDR=$(IPL_LOAD_ADDR) CUSTOMDEFINES += -DLP_VER_MJ=$(LPVERSION_MAJOR) -DLP_VER_MN=$(LPVERSION_MINOR) -DLP_VER_BF=$(LPVERSION_BUGFX) CUSTOMDEFINES += -DGFX_INC=$(GFX_INC) -DFFCFG_INC=$(FFCFG_INC) +# 0: UART_A, 1: UART_B. +#CUSTOMDEFINES += -DDEBUG_UART_PORT=0 + +#CUSTOMDEFINES += -DDEBUG + ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork -CFLAGS = $(ARCH) -O2 -nostdlib -ffunction-sections -fno-inline -fdata-sections -fomit-frame-pointer -std=gnu11 -Wall $(CUSTOMDEFINES) +CFLAGS = $(ARCH) -Os -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -std=gnu11 -Wall $(CUSTOMDEFINES) LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defsym=IPL_LOAD_ADDR=$(IPL_LOAD_ADDR) ################################################################################ diff --git a/bdk/gfx/di.c b/bdk/gfx/di.c index 1549e7b..9d95349 100644 --- a/bdk/gfx/di.c +++ b/bdk/gfx/di.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2019 CTCaer + * Copyright (c) 2018-2020 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,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -34,7 +35,7 @@ extern volatile nyx_storage_t *nyx_str; static u32 _display_id = 0; -void display_end(); +static void _display_panel_and_hw_end(bool no_panel_deinit); static void _display_dsi_wait(u32 timeout, u32 off, u32 mask) { @@ -53,91 +54,309 @@ static void _display_dsi_send_cmd(u8 cmd, u32 param, u32 wait) usleep(wait); } +static void _display_dsi_read_rx_fifo(u32 *data) +{ + u32 fifo_count = DSI(_DSIREG(DSI_STATUS)) & DSI_STATUS_RX_FIFO_SIZE; + 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, 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; + + // 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) + ; + } + + // 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); + + // 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); + + // 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; + _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) + { + // 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; + + case GEN_1_BYTE_SHORT_RD_RES: + case DCS_1_BYTE_SHORT_RD_RES: + memcpy(data, &fifo[2], 1); + break; + + case GEN_2_BYTE_SHORT_RD_RES: + case DCS_2_BYTE_SHORT_RD_RES: + memcpy(data, &fifo[2], 2); + break; + case ACK_ERROR_RES: + default: + res = 1; + break; + } + } + + // Disable host cmd packets during video and restore host control. + if (video_enabled) + { + // 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; + 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; + } + + return res; +} + +void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled) +{ + u32 host_control; + u32 fifo32[DSI_STATUS_RX_FIFO_SIZE] = {0}; + u8 *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; + host_control = DSI(_DSIREG(DSI_HOST_CONTROL)); + + // Enable host transfer trigger. + DSI(_DSIREG(DSI_HOST_CONTROL)) |= DSI_HOST_CONTROL_TX_TRIG_HOST; + + switch (len) + { + case 0: + _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, cmd, 0); + break; + + case 1: + _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE_PARAM, cmd | (*(u8 *)data << 8), 0); + break; + + default: + 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++) + DSI(_DSIREG(DSI_WR_DATA)) = fifo32[i]; + DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST; + break; + } + + // 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; + DSI(_DSIREG(DSI_HOST_CONTROL)) = host_control; +} + void display_init() { // Check if display is already initialized. - if (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) & 0x18000000) - display_end(); + if (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) & BIT(CLK_L_DISP1)) + _display_panel_and_hw_end(true); - // Power on. + // Get Chip ID. + bool tegra_t210 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210; + + // T210B01: Power on SD2 regulator for supplying LD0. + if (!tegra_t210) + { + // Set SD2 regulator voltage. + max77620_regulator_set_voltage(REGULATOR_SD2, 1325000); + + // Set slew rate and enable SD2 regulator. + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD2_CFG, (1 << MAX77620_SD_SR_SHIFT) | MAX77620_SD_CFG1_FSRADE_SD_ENABLE); + max77620_regulator_enable(REGULATOR_SD2, 1); + + } + + // Enable power to display panel controller. max77620_regulator_set_volt_and_flags(REGULATOR_LDO0, 1200000, MAX77620_POWER_MODE_NORMAL); // Configure to 1.2V. - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO7, MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH | MAX77620_CNFG_GPIO_DRV_PUSHPULL); + if (tegra_t210) + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO7, + MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH | MAX77620_CNFG_GPIO_DRV_PUSHPULL); // T210: LD0 -> GPIO7 -> Display panel. // Enable Display Interface specific clocks. - CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = 0x1010000; // Clear reset DSI, MIPI_CAL. - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = 0x1010000; // Set enable clock DSI, MIPI_CAL. + 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) = 0x18000000; // Clear reset DISP1, HOST1X. - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = 0x18000000; // Set enable clock DISP1, HOST1X. + 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_CLK_ENB_X_SET) = 0x20000; // Set enable clock UART_FST_MIPI_CAL. + 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) = 0x80000; // Set enable clock DSIA_LP. - CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP) = 10; // Set PLLP_OUT and div 6 (68MHz). + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_SET) = BIT(CLK_W_DSIA_LP); + CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP) = 10; // Set PLLP_OUT and div 6 (68MHz). - // Disable deep power down. - PMC(APBDEV_PMC_IO_DPD_REQ) = 0x40000000; - PMC(APBDEV_PMC_IO_DPD2_REQ) = 0x40000000; + // 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; - // Config LCD and Backlight pins. - PINMUX_AUX(PINMUX_AUX_NFC_EN) &= ~PINMUX_TRISTATE; // PULL_DOWN - PINMUX_AUX(PINMUX_AUX_NFC_INT) &= ~PINMUX_TRISTATE; // PULL_DOWN + // 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 - PINMUX_AUX(PINMUX_AUX_LCD_RST) &= ~PINMUX_TRISTATE; // PULL_DOWN + PINMUX_AUX(PINMUX_AUX_LCD_BL_EN) &= ~PINMUX_TRISTATE; // PULL_DOWN - // Set Backlight +-5V pins mode and direction + // 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); - // Enable Backlight power. - gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_HIGH); // Backlight +5V enable. + // 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); // Backlight -5V enable. + gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_HIGH); // LCD -5V enable. usleep(10000); - // Configure Backlight pins (PWM, EN, RST). + // 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); - gpio_write(GPIO_PORT_V, GPIO_PIN_1, GPIO_HIGH); // Enable Backlight EN. + + // Enable Backlight power. + gpio_write(GPIO_PORT_V, GPIO_PIN_1, GPIO_HIGH); // Power up supply regulator for display interface. MIPI_CAL(_DSIREG(MIPI_CAL_MIPI_BIAS_PAD_CFG2)) = 0; + if (!tegra_t210) + { + MIPI_CAL(_DSIREG(MIPI_CAL_MIPI_BIAS_PAD_CFG0)) = 0; + 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): 96 MHz. CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div; - CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0x20; // PLLD_SETUP. - CLOCK(CLK_RST_CONTROLLER_PLLD_MISC) = 0x2D0AAA; // PLLD_ENABLE_CLK. + + 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. + } + + // Setup Display Interface initial window configuration. + exec_cfg((u32 *)DISPLAY_A_BASE, _display_dc_setup_win_config, 94); // Setup display communication interfaces. - exec_cfg((u32 *)DISPLAY_A_BASE, _display_dc_setup_win_config, 94); - exec_cfg((u32 *)DSI_BASE, _display_dsi_init_config, 61); + exec_cfg((u32 *)DSI_BASE, _display_dsi_init_config_part1, 8); + 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); + 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); usleep(10000); - // Enable Backlight Reset. + // Enable LCD Reset. gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_HIGH); usleep(60000); - // Setups DSI packet configuration and request display id. + // Setup DSI device takeover timeout. DSI(_DSIREG(DSI_BTA_TIMING)) = 0x50204; + +#if 0 + // Get Display ID. + _display_id = 0xCCCCCC; + display_dsi_read(MIPI_DCS_GET_DISPLAY_ID, 3, &_display_id, DSI_VIDEO_DISABLED); +#else + // Set reply size. _display_dsi_send_cmd(MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, 3, 0); _display_dsi_wait(250000, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO); + // Request register read. _display_dsi_send_cmd(MIPI_DSI_DCS_READ, MIPI_DCS_GET_DISPLAY_ID, 0); _display_dsi_wait(250000, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO); + // Transfer bus control to device for transmitting the reply. DSI(_DSIREG(DSI_HOST_CONTROL)) = DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_IMM_BTA | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC; _display_dsi_wait(150000, _DSIREG(DSI_HOST_CONTROL), DSI_HOST_CONTROL_IMM_BTA); + // Wait a bit for the reply. usleep(5000); - // MIPI_DCS_GET_DISPLAY_ID reply is a long read, size 3 u32. + // MIPI_DCS_GET_DISPLAY_ID reply is a long read, size 3 x u32. for (u32 i = 0; i < 3; i++) - _display_id = DSI(_DSIREG(DSI_RD_DATA)); // Skip ack and msg type info and get the payload (display id). - + _display_id = DSI(_DSIREG(DSI_RD_DATA)) & 0xFFFFFF; // Skip ack and msg type info and get the payload (display id). +#endif // Save raw Display ID to Nyx storage. nyx_str->info.disp_id = _display_id; @@ -154,47 +373,82 @@ void display_init() exec_cfg((u32 *)DSI_BASE, _display_init_config_jdi, 43); _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 180000); break; + case PANEL_INL_P062CCA_AZ1: case PANEL_AUO_A062TAN01: _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 180000); + + // Unlock extension cmds. DSI(_DSIREG(DSI_WR_DATA)) = 0x439; // MIPI_DSI_DCS_LONG_WRITE: 4 bytes. - DSI(_DSIREG(DSI_WR_DATA)) = 0x9483FFB9; // Enable extension cmd. (Pass: FF 83 94). + DSI(_DSIREG(DSI_WR_DATA)) = 0x9483FFB9; // MIPI_DCS_PRIV_SET_EXTC. (Pass: FF 83 94). DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST; usleep(5000); + + // Set Power control. DSI(_DSIREG(DSI_WR_DATA)) = 0x739; // MIPI_DSI_DCS_LONG_WRITE: 7 bytes. if (_display_id == PANEL_INL_P062CCA_AZ1) - DSI(_DSIREG(DSI_WR_DATA)) = 0x751548B1; // Set Power control. (Not deep standby, BT5 / XDK, VRH gamma volt adj 53 / x40). - else - DSI(_DSIREG(DSI_WR_DATA)) = 0x711148B1; // Set Power control. (Not deep standby, BT1 / XDK, VRH gamma volt adj 49 / x40). + DSI(_DSIREG(DSI_WR_DATA)) = 0x751548B1; // MIPI_DCS_PRIV_SET_POWER_CONTROL. (Not deep standby, BT5 / XDK, VRH gamma volt adj 53 / x40). + else // PANEL_AUO_A062TAN01. + DSI(_DSIREG(DSI_WR_DATA)) = 0x711148B1; // MIPI_DCS_PRIV_SET_POWER_CONTROL. (Not deep standby, BT1 / XDK, VRH gamma volt adj 49 / x40). DSI(_DSIREG(DSI_WR_DATA)) = 0x143209; // (NVRH gamma volt adj 9, Amplifier current small / x30, FS0 freq Fosc/80 / FS1 freq Fosc/32). DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST; usleep(5000); break; - case PANEL_INL_P062CCA_AZ2: - case PANEL_AUO_A062TAN02: + + case PANEL_INL_2J055IA_27A: + case PANEL_AUO_A055TAN01: + case PANEL_V40_55_UNK: default: // Allow spare part displays to work. _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 120000); break; } + // 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): 460.8 MHz. + plld_div = (1 << 20) | (24 << 11) | 1; // DIVM: 1, DIVN: 24, DIVP: 1. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 230.4 MHz. CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div; - CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0x20; - CLOCK(CLK_RST_CONTROLLER_PLLD_MISC) = 0x2DFC00; // Use new PLLD_SDM_DIN. + + 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. - exec_cfg((u32 *)DSI_BASE, _display_dsi_packet_config, 21); - DISPLAY_A(_DIREG(DC_DISP_DISP_CLOCK_CONTROL)) = 4; // PCD1 | div3. + 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: 230.4 / 3 / 1 = 76.8 MHz. 60 Hz. + 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); usleep(10000); // Calibrate display communication pads. - exec_cfg((u32 *)MIPI_CAL_BASE, _display_mipi_pad_cal_config, 6); - exec_cfg((u32 *)DSI_BASE, _display_dsi_pad_cal_config, 4); - exec_cfg((u32 *)MIPI_CAL_BASE, _display_mipi_apply_dsi_cal_config, 16); + 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); + for (u32 i = 0; i < loops; i++) + { + // Set MIPI bias pad config. + MIPI_CAL(_DSIREG(MIPI_CAL_MIPI_BIAS_PAD_CFG2)) = 0x10010; + MIPI_CAL(_DSIREG(MIPI_CAL_MIPI_BIAS_PAD_CFG1)) = tegra_t210 ? 0x300 : 0; + + // 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); + } + 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); + } + + // Set the rest of MIPI cal offsets and apply calibration. + exec_cfg((u32 *)MIPI_CAL_BASE, _display_mipi_apply_dsi_cal_config, 12); + } usleep(10000); // Enable video display controller. @@ -205,9 +459,9 @@ 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. + PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN; // Enable PWM and set it to 25KHz PFM. 29.5KHz is stock. - PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & 0xFFFFFFFC) | 1; // PWM clock source. + 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. } @@ -245,15 +499,22 @@ void display_backlight_brightness(u32 brightness, u32 step_delay) PWM(PWM_CONTROLLER_PWM_CSR_0) = 0; } -void display_end() +static void _display_panel_and_hw_end(bool no_panel_deinit) { + if (no_panel_deinit) + goto skip_panel_deinit; + display_backlight_brightness(0, 1000); + // Enable host cmd packets during video. DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = DSI_CMD_PKT_VID_ENABLE; - DSI(_DSIREG(DSI_WR_DATA)) = 0x2805; // MIPI_DCS_SET_DISPLAY_OFF + // Blank display. + DSI(_DSIREG(DSI_WR_DATA)) = (MIPI_DCS_SET_DISPLAY_OFF << 8) | MIPI_DSI_DCS_SHORT_WRITE; + + // 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; // Disable host cmd packet. + DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 0; // De-initialize video controller. exec_cfg((u32 *)DISPLAY_A_BASE, _display_video_disp_controller_disable_config, 17); @@ -266,59 +527,82 @@ void display_end() case PANEL_JDI_XXX062M: exec_cfg((u32 *)DSI_BASE, _display_deinit_config_jdi, 22); break; + case PANEL_AUO_A062TAN01: exec_cfg((u32 *)DSI_BASE, _display_deinit_config_auo, 37); break; - case PANEL_INL_P062CCA_AZ2: - case PANEL_AUO_A062TAN02: - DSI(_DSIREG(DSI_WR_DATA)) = 0x439; // MIPI_DSI_DCS_LONG_WRITE: 4 bytes. - DSI(_DSIREG(DSI_WR_DATA)) = 0x9483FFB9; // Enable extension cmd. (Pass: FF 83 94). + + case PANEL_INL_2J055IA_27A: + case PANEL_AUO_A055TAN01: + case PANEL_V40_55_UNK: + // 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). DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST; usleep(5000); - // Set Power. - DSI(_DSIREG(DSI_WR_DATA)) = 0xB39; // MIPI_DSI_DCS_LONG_WRITE: 11 bytes. - if (_display_id == PANEL_INL_P062CCA_AZ2) - DSI(_DSIREG(DSI_WR_DATA)) = 0x751548B1; // Set Power control. (Not deep standby, BT5 / XDK, VRH gamma volt adj 53 / x40). - else - DSI(_DSIREG(DSI_WR_DATA)) = 0x711148B1; // Set Power control. (Not deep standby, BT1 / XDK, VRH gamma volt adj 49 / x40). - // Set Power control. (NVRH gamma volt adj 9, Amplifier current small / x30, FS0 freq Fosc/80 / FS1 freq Fosc/32, Enter standby / PON / VCOMG). - DSI(_DSIREG(DSI_WR_DATA)) = 0x71143209; - DSI(_DSIREG(DSI_WR_DATA)) = 0x114D31; // Set Power control. (Unknown). + + // Set Power control. + DSI(_DSIREG(DSI_WR_DATA)) = 0xB39; // MIPI_DSI_DCS_LONG_WRITE: 11 bytes. + if (_display_id == PANEL_INL_2J055IA_27A) + 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. + 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) + { + // (NVRH gamma volt adj 9, Amplifier current small / x30, FS0 freq Fosc/80 / FS1 freq Fosc/32, Enter standby / PON / VCOMG). + DSI(_DSIREG(DSI_WR_DATA)) = 0x71143209; + DSI(_DSIREG(DSI_WR_DATA)) = 0x114D31; // (Unknown). + } + else // PANEL_V40_55_UNK. + { + // (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; + DSI(_DSIREG(DSI_WR_DATA)) = 0x004C31; // (Unknown). + } DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST; usleep(5000); break; + case PANEL_INL_P062CCA_AZ1: default: break; } + // Blank - powerdown. _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_ENTER_SLEEP_MODE, 50000); - // Disable display and backlight pins. - gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_LOW); //Backlight Reset disable. +skip_panel_deinit: + // Disable LCD power pins. + gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_LOW); // LCD Reset disable. usleep(10000); - - gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_LOW); //Backlight -5V disable. + gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_LOW); // LCD -5V disable. usleep(10000); - - gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_LOW); //Backlight +5V disable. + gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_LOW); // LCD +5V disable. usleep(10000); // Disable Display Interface specific clocks. - CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = 0x1010000; // Set reset clock DSI, MIPI_CAL. - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_CLR) = 0x1010000; // Clear enable clock DSI, MIPI_CAL. - CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = 0x18000000; // Set reset DISP1, HOST1X. - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = 0x18000000; // Clear enable DISP1, HOST1X. + 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); // 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_POWER_CONTROL)) = 0; - // Switch to automatic function mode. + // Switch LCD PWM backlight pin to special function mode and enable PWM0 mode. 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) & 0xFFFFFFFC)| 1; + PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & ~PINMUX_FUNC_MASK) | 1; // Set PWM0 mode. +} + +void display_end() { _display_panel_and_hw_end(false); }; + +u16 display_get_decoded_lcd_id() +{ + return _display_id; } void display_color_screen(u32 color) @@ -378,7 +662,7 @@ u32 *display_init_framebuffer_log() void display_activate_console() { - DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = WINDOW_D_SELECT; // Select window C. + 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; @@ -399,7 +683,7 @@ void display_activate_console() void display_deactivate_console() { - DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = WINDOW_D_SELECT; // Select window C. + DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = WINDOW_D_SELECT; // Select window D. for (u32 i = 0xFFFF; i > 0xFF7F; i--) { diff --git a/bdk/gfx/di.h b/bdk/gfx/di.h index 2723de0..e304fb6 100644 --- a/bdk/gfx/di.h +++ b/bdk/gfx/di.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2019 CTCaer + * Copyright (c) 2018-2020 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -21,6 +21,9 @@ #include #include +#define DSI_VIDEO_DISABLED 0 +#define DSI_VIDEO_ENABLED 1 + /*! Display registers. */ #define _DIREG(reg) ((reg) * 4) @@ -42,11 +45,11 @@ #define DC_CMD_GENERAL_INCR_SYNCPT 0x00 #define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL 0x01 -#define SYNCPT_CNTRL_NO_STALL (1 << 8) -#define SYNCPT_CNTRL_SOFT_RESET (1 << 0) +#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 (1 << 8) +#define SYNCPT_VSYNC_ENABLE BIT(8) #define DC_CMD_DISPLAY_COMMAND_OPTION0 0x031 @@ -57,42 +60,43 @@ #define DISP_CTRL_MODE_MASK (3 << 5) #define DC_CMD_DISPLAY_POWER_CONTROL 0x36 -#define PW0_ENABLE (1 << 0) -#define PW1_ENABLE (1 << 2) -#define PW2_ENABLE (1 << 4) -#define PW3_ENABLE (1 << 6) -#define PW4_ENABLE (1 << 8) -#define PM0_ENABLE (1 << 16) -#define PM1_ENABLE (1 << 18) +#define PW0_ENABLE BIT(0) +#define PW1_ENABLE BIT(2) +#define PW2_ENABLE BIT(4) +#define PW3_ENABLE BIT(6) +#define PW4_ENABLE BIT(8) +#define PM0_ENABLE BIT(16) +#define PM1_ENABLE BIT(18) #define DC_CMD_INT_STATUS 0x37 #define DC_CMD_INT_MASK 0x38 #define DC_CMD_INT_ENABLE 0x39 +#define DC_CMD_INT_FRAME_END_INT BIT(1) #define DC_CMD_STATE_ACCESS 0x40 -#define READ_MUX (1 << 0) -#define WRITE_MUX (1 << 2) +#define READ_MUX BIT(0) +#define WRITE_MUX BIT(2) #define DC_CMD_STATE_CONTROL 0x41 -#define GENERAL_ACT_REQ (1 << 0) -#define WIN_A_ACT_REQ (1 << 1) -#define WIN_B_ACT_REQ (1 << 2) -#define WIN_C_ACT_REQ (1 << 3) -#define WIN_D_ACT_REQ (1 << 4) -#define CURSOR_ACT_REQ (1 << 7) -#define GENERAL_UPDATE (1 << 8) -#define WIN_A_UPDATE (1 << 9) -#define WIN_B_UPDATE (1 << 10) -#define WIN_C_UPDATE (1 << 11) -#define WIN_D_UPDATE (1 << 12) -#define CURSOR_UPDATE (1 << 15) -#define NC_HOST_TRIG (1 << 24) +#define GENERAL_ACT_REQ BIT(0) +#define WIN_A_ACT_REQ BIT(1) +#define WIN_B_ACT_REQ BIT(2) +#define WIN_C_ACT_REQ BIT(3) +#define WIN_D_ACT_REQ BIT(4) +#define CURSOR_ACT_REQ BIT(7) +#define GENERAL_UPDATE BIT(8) +#define WIN_A_UPDATE BIT(9) +#define WIN_B_UPDATE BIT(10) +#define WIN_C_UPDATE BIT(11) +#define WIN_D_UPDATE BIT(12) +#define CURSOR_UPDATE BIT(15) +#define NC_HOST_TRIG BIT(24) #define DC_CMD_DISPLAY_WINDOW_HEADER 0x42 -#define WINDOW_A_SELECT (1 << 4) -#define WINDOW_B_SELECT (1 << 5) -#define WINDOW_C_SELECT (1 << 6) -#define WINDOW_D_SELECT (1 << 7) +#define WINDOW_A_SELECT BIT(4) +#define WINDOW_B_SELECT BIT(5) +#define WINDOW_C_SELECT BIT(6) +#define WINDOW_D_SELECT BIT(7) #define DC_CMD_REG_ACT_CONTROL 0x043 @@ -125,12 +129,13 @@ // DC_DISP shadowed registers. #define DC_DISP_DISP_WIN_OPTIONS 0x402 -#define HDMI_ENABLE (1 << 30) -#define DSI_ENABLE (1 << 29) -#define SOR1_TIMING_CYA (1 << 27) -#define SOR1_ENABLE (1 << 26) -#define SOR_ENABLE (1 << 25) -#define CURSOR_ENABLE (1 << 16) +#define CURSOR_ENABLE BIT(16) +#define SOR_ENABLE BIT(25) +#define SOR1_ENABLE BIT(26) +#define SOR1_TIMING_CYA BIT(27) +#define DSI_ENABLE BIT(29) +#define HDMI_ENABLE BIT(30) + #define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403 #define DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER 0x404 @@ -142,6 +147,7 @@ #define DC_DISP_FRONT_PORCH 0x40A #define DC_DISP_DISP_CLOCK_CONTROL 0x42E +#define SHIFT_CLK_DIVIDER(x) ((x) & 0xff) #define PIXEL_CLK_DIVIDER_PCD1 (0 << 8) #define PIXEL_CLK_DIVIDER_PCD1H (1 << 8) #define PIXEL_CLK_DIVIDER_PCD2 (2 << 8) @@ -155,7 +161,6 @@ #define PIXEL_CLK_DIVIDER_PCD18 (10 << 8) #define PIXEL_CLK_DIVIDER_PCD24 (11 << 8) #define PIXEL_CLK_DIVIDER_PCD13 (12 << 8) -#define SHIFT_CLK_DIVIDER(x) ((x) & 0xff) #define DC_DISP_DISP_INTERFACE_CONTROL 0x42F #define DISP_DATA_FORMAT_DF1P1C (0 << 0) @@ -189,8 +194,8 @@ #define BASE_COLOR_SIZE_888 (8 << 0) #define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431 -#define SC1_H_QUALIFIER_NONE (1 << 16) -#define SC0_H_QUALIFIER_NONE (1 << 0) +#define SC0_H_QUALIFIER_NONE BIT(0) +#define SC1_H_QUALIFIER_NONE BIT(16) #define DC_DISP_DATA_ENABLE_OPTIONS 0x432 #define DE_SELECT_ACTIVE_BLANK (0 << 0) @@ -217,6 +222,7 @@ #define CURSOR_SIZE_128 (2 << 24) #define CURSOR_SIZE_256 (3 << 24) #define DC_DISP_CURSOR_POSITION 0x440 +#define DC_DISP_BLEND_BACKGROUND_COLOR 0x4E4 #define DC_DISP_CURSOR_START_ADDR_HI 0x4EC #define DC_DISP_BLEND_CURSOR_CONTROL 0x4F1 #define CURSOR_BLEND_2BIT (0 << 24) @@ -247,12 +253,12 @@ // 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 (1 << 0) -#define V_DIRECTION (1 << 2) -#define SCAN_COLUMN (1 << 4) -#define COLOR_EXPAND (1 << 6) -#define CSC_ENABLE (1 << 18) -#define WIN_ENABLE (1 << 30) +#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 DC_WIN_BUFFER_CONTROL 0x702 #define BUFFER_CONTROL_HOST 0 @@ -358,6 +364,10 @@ /*! Display serial interface registers. */ #define _DSIREG(reg) ((reg) * 4) +#define DSI_INCR_SYNCPT_CNTRL 0x1 +#define DSI_INCR_SYNCPT_SOFT_RESET BIT(0) +#define DSI_INCR_SYNCPT_NO_STALL BIT(8) + #define DSI_RD_DATA 0x9 #define DSI_WR_DATA 0xA @@ -369,39 +379,42 @@ #define DSI_INT_MASK 0xE #define DSI_HOST_CONTROL 0xF -#define DSI_HOST_CONTROL_FIFO_RESET (1 << 21) -#define DSI_HOST_CONTROL_CRC_RESET (1 << 20) +#define DSI_HOST_CONTROL_ECC BIT(0) +#define DSI_HOST_CONTROL_CS BIT(1) +#define DSI_HOST_CONTROL_PKT_BTA BIT(2) +#define DSI_HOST_CONTROL_IMM_BTA BIT(3) +#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_SOL (0 << 12) #define DSI_HOST_CONTROL_TX_TRIG_FIFO (1 << 12) #define DSI_HOST_CONTROL_TX_TRIG_HOST (2 << 12) -#define DSI_HOST_CONTROL_RAW (1 << 6) -#define DSI_HOST_CONTROL_HS (1 << 5) -#define DSI_HOST_CONTROL_FIFO_SEL (1 << 4) -#define DSI_HOST_CONTROL_IMM_BTA (1 << 3) -#define DSI_HOST_CONTROL_PKT_BTA (1 << 2) -#define DSI_HOST_CONTROL_CS (1 << 1) -#define DSI_HOST_CONTROL_ECC (1 << 0) +#define DSI_HOST_CONTROL_CRC_RESET BIT(20) +#define DSI_HOST_CONTROL_FIFO_RESET BIT(21) #define DSI_CONTROL 0x10 -#define DSI_CONTROL_HS_CLK_CTRL (1 << 20) -#define DSI_CONTROL_CHANNEL(c) (((c) & 0x3) << 16) -#define DSI_CONTROL_FORMAT(f) (((f) & 0x3) << 12) -#define DSI_CONTROL_TX_TRIG(x) (((x) & 0x3) << 8) -#define DSI_CONTROL_LANES(n) (((n) & 0x3) << 4) -#define DSI_CONTROL_DCS_ENABLE (1 << 3) +#define DSI_CONTROL_HOST_ENABLE BIT(0) +#define DSI_CONTROL_VIDEO_ENABLE BIT(1) #define DSI_CONTROL_SOURCE(s) (((s) & 0x1) << 2) -#define DSI_CONTROL_VIDEO_ENABLE (1 << 1) -#define DSI_CONTROL_HOST_ENABLE (1 << 0) +#define DSI_CONTROL_DCS_ENABLE BIT(3) +#define DSI_CONTROL_LANES(n) (((n) & 0x3) << 4) +#define DSI_CONTROL_TX_TRIG(x) (((x) & 0x3) << 8) +#define DSI_CONTROL_FORMAT(f) (((f) & 0x3) << 12) +#define DSI_CONTROL_CHANNEL(c) (((c) & 0x3) << 16) +#define DSI_CONTROL_HS_CLK_CTRL BIT(20) #define DSI_SOL_DELAY 0x11 #define DSI_MAX_THRESHOLD 0x12 #define DSI_TRIGGER 0x13 -#define DSI_TRIGGER_HOST (1 << 1) -#define DSI_TRIGGER_VIDEO (1 << 0) +#define DSI_TRIGGER_VIDEO BIT(0) +#define DSI_TRIGGER_HOST BIT(1) #define DSI_TX_CRC 0x14 + #define DSI_STATUS 0x15 +#define DSI_STATUS_RX_FIFO_SIZE 0x1F + #define DSI_INIT_SEQ_CONTROL 0x1A #define DSI_INIT_SEQ_DATA_0 0x1B #define DSI_INIT_SEQ_DATA_1 0x1C @@ -430,36 +443,53 @@ #define DSI_BTA_TIMING 0x3F #define DSI_TIMEOUT_0 0x44 -#define DSI_TIMEOUT_LRX(x) (((x) & 0xffff) << 16) #define DSI_TIMEOUT_HTX(x) (((x) & 0xffff) << 0) +#define DSI_TIMEOUT_LRX(x) (((x) & 0xffff) << 16) #define DSI_TIMEOUT_1 0x45 -#define DSI_TIMEOUT_PR(x) (((x) & 0xffff) << 16) #define DSI_TIMEOUT_TA(x) (((x) & 0xffff) << 0) +#define DSI_TIMEOUT_PR(x) (((x) & 0xffff) << 16) #define DSI_TO_TALLY 0x46 #define DSI_PAD_CONTROL_0 0x4B -#define DSI_PAD_CONTROL_VS1_PULLDN_CLK (1 << 24) -#define DSI_PAD_CONTROL_VS1_PULLDN(x) (((x) & 0xf) << 16) -#define DSI_PAD_CONTROL_VS1_PDIO_CLK (1 << 8) +#define DSI_PAD_CONTROL_VS1_PDIO_CLK BIT(8) #define DSI_PAD_CONTROL_VS1_PDIO(x) (((x) & 0xf) << 0) +#define DSI_PAD_CONTROL_VS1_PULLDN_CLK BIT(24) +#define DSI_PAD_CONTROL_VS1_PULLDN(x) (((x) & 0xf) << 16) #define DSI_PAD_CONTROL_CD 0x4C #define DSI_VIDEO_MODE_CONTROL 0x4E #define DSI_CMD_PKT_VID_ENABLE 1 +#define DSI_DSI_LINE_TYPE(x) ((x) << 1) #define DSI_PAD_CONTROL_1 0x4F #define DSI_PAD_CONTROL_2 0x50 #define DSI_PAD_CONTROL_3 0x51 -#define DSI_PAD_PREEMP_PD_CLK(x) (((x) & 0x3) << 12) -#define DSI_PAD_PREEMP_PU_CLK(x) (((x) & 0x3) << 8) -#define DSI_PAD_PREEMP_PD(x) (((x) & 0x3) << 4) #define DSI_PAD_PREEMP_PU(x) (((x) & 0x3) << 0) +#define DSI_PAD_PREEMP_PD(x) (((x) & 0x3) << 4) +#define DSI_PAD_PREEMP_PU_CLK(x) (((x) & 0x3) << 8) +#define DSI_PAD_PREEMP_PD_CLK(x) (((x) & 0x3) << 12) #define DSI_PAD_CONTROL_4 0x52 +#define DSI_PAD_CONTROL_5_B01 0x53 +#define DSI_PAD_CONTROL_6_B01 0x54 +#define DSI_PAD_CONTROL_7_B01 0x55 #define DSI_INIT_SEQ_DATA_15 0x5F +#define DSI_INIT_SEQ_DATA_15_B01 0x62 + +/*! DSI packet defines */ +#define DSI_ESCAPE_CMD 0x87 +#define DSI_ACK_NO_ERR 0x84 + +#define ACK_ERROR_RES 0x02 +#define GEN_LONG_RD_RES 0x1A +#define DCS_LONG_RD_RES 0x1C +#define GEN_1_BYTE_SHORT_RD_RES 0x11 +#define DCS_1_BYTE_SHORT_RD_RES 0x21 +#define GEN_2_BYTE_SHORT_RD_RES 0x12 +#define DCS_2_BYTE_SHORT_RD_RES 0x22 /*! MIPI registers. */ #define MIPI_CAL_MIPI_CAL_CTRL (0x00 / 0x4) @@ -483,25 +513,168 @@ #define MIPI_CAL_DSID_MIPI_CAL_CONFIG_2 (0x74 / 0x4) /*! MIPI CMDs. */ -#define MIPI_DSI_DCS_SHORT_WRITE 0x05 -#define MIPI_DSI_DCS_READ 0x06 -#define MIPI_DSI_DCS_SHORT_WRITE_PARAM 0x15 +#define MIPI_DSI_V_SYNC_START 0x01 +#define MIPI_DSI_COLOR_MODE_OFF 0x02 +#define MIPI_DSI_END_OF_TRANSMISSION 0x08 +#define MIPI_DSI_NULL_PACKET 0x09 +#define MIPI_DSI_V_SYNC_END 0x11 +#define MIPI_DSI_COLOR_MODE_ON 0x12 +#define MIPI_DSI_BLANKING_PACKET 0x19 +#define MIPI_DSI_H_SYNC_START 0x21 +#define MIPI_DSI_SHUTDOWN_PERIPHERAL 0x22 +#define MIPI_DSI_H_SYNC_END 0x31 +#define MIPI_DSI_TURN_ON_PERIPHERAL 0x32 #define MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE 0x37 -#define MIPI_DSI_DCS_LONG_WRITE 0x39 + +#define MIPI_DSI_DCS_SHORT_WRITE 0x05 +#define MIPI_DSI_DCS_READ 0x06 +#define MIPI_DSI_DCS_SHORT_WRITE_PARAM 0x15 +#define MIPI_DSI_DCS_LONG_WRITE 0x39 + +#define MIPI_DSI_GENERIC_LONG_WRITE 0x29 +#define MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM 0x03 +#define MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM 0x13 +#define MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM 0x23 +#define MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM 0x04 +#define MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM 0x14 +#define MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM 0x24 /*! MIPI DCS CMDs. */ -#define MIPI_DCS_GET_DISPLAY_ID 0x04 -#define MIPI_DCS_ENTER_SLEEP_MODE 0x10 -#define MIPI_DCS_EXIT_SLEEP_MODE 0x11 -#define MIPI_DCS_SET_DISPLAY_ON 0x29 +#define MIPI_DCS_NOP 0x00 +#define MIPI_DCS_SOFT_RESET 0x01 +#define MIPI_DCS_GET_COMPRESSION_MODE 0x03 +#define MIPI_DCS_GET_DISPLAY_ID 0x04 +#define MIPI_DCS_GET_DISPLAY_ID1 0xDA // GET_DISPLAY_ID Byte0, Module Manufacturer ID. +#define MIPI_DCS_GET_DISPLAY_ID2 0xDB // GET_DISPLAY_ID Byte1, Module/Driver Version ID. +#define MIPI_DCS_GET_DISPLAY_ID3 0xDC // GET_DISPLAY_ID Byte2, Module/Driver ID. +#define MIPI_DCS_GET_NUM_ERRORS 0x05 +#define MIPI_DCS_GET_RED_CHANNEL 0x06 +#define MIPI_DCS_GET_GREEN_CHANNEL 0x07 +#define MIPI_DCS_GET_BLUE_CHANNEL 0x08 +#define MIPI_DCS_GET_DISPLAY_STATUS 0x09 +#define MIPI_DCS_GET_POWER_MODE 0x0A +#define MIPI_DCS_GET_ADDRESS_MODE 0x0B +#define MIPI_DCS_GET_PIXEL_FORMAT 0x0C +#define MIPI_DCS_GET_DISPLAY_MODE 0x0D +#define MIPI_DCS_GET_SIGNAL_MODE 0x0E +#define MIPI_DCS_GET_DIAGNOSTIC_RESULT 0x0F +#define MIPI_DCS_ENTER_SLEEP_MODE 0x10 +#define MIPI_DCS_EXIT_SLEEP_MODE 0x11 +#define MIPI_DCS_ENTER_PARTIAL_MODE 0x12 +#define MIPI_DCS_ENTER_NORMAL_MODE 0x13 +#define MIPI_DCS_EXIT_INVERT_MODE 0x20 +#define MIPI_DCS_ENTER_INVERT_MODE 0x21 +#define MIPI_DCS_ALL_PIXELS_OFF 0x22 +#define MIPI_DCS_ALL_PIXELS_ON 0x23 +#define MIPI_DCS_SET_CONTRAST 0x25 // VCON in 40mV steps. 7-bit integer. +#define MIPI_DCS_SET_GAMMA_CURVE 0x26 +#define MIPI_DCS_SET_DISPLAY_OFF 0x28 +#define MIPI_DCS_SET_DISPLAY_ON 0x29 +#define MIPI_DCS_SET_COLUMN_ADDRESS 0x2A +#define MIPI_DCS_SET_PAGE_ADDRESS 0x2B +#define MIPI_DCS_WRITE_MEMORY_START 0x2C +#define MIPI_DCS_WRITE_LUT 0x2D // 24-bit: 192 bytes. +#define MIPI_DCS_READ_MEMORY_START 0x2E +#define MIPI_DCS_SET_PARTIAL_ROWS 0x30 +#define MIPI_DCS_SET_PARTIAL_COLUMNS 0x31 +#define MIPI_DCS_SET_SCROLL_AREA 0x33 +#define MIPI_DCS_SET_TEAR_OFF 0x34 +#define MIPI_DCS_SET_TEAR_ON 0x35 +#define MIPI_DCS_SET_ADDRESS_MODE 0x36 +#define MIPI_DCS_SET_SCROLL_START 0x37 +#define MIPI_DCS_EXIT_IDLE_MODE 0x38 +#define MIPI_DCS_ENTER_IDLE_MODE 0x39 +#define MIPI_DCS_SET_PIXEL_FORMAT 0x3A +#define MIPI_DCS_WRITE_MEMORY_CONTINUE 0x3C +#define MIPI_DCS_READ_MEMORY_CONTINUE 0x3E +#define MIPI_DCS_GET_3D_CONTROL 0x3F +#define MIPI_DCS_SET_VSYNC_TIMING 0x40 +#define MIPI_DCS_SET_TEAR_SCANLINE 0x44 +#define MIPI_DCS_GET_SCANLINE 0x45 +#define MIPI_DCS_SET_TEAR_SCANLINE_WIDTH 0x46 +#define MIPI_DCS_GET_SCANLINE_WIDTH 0x47 +#define MIPI_DCS_SET_BRIGHTNESS 0x51 // DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL. +#define MIPI_DCS_GET_BRIGHTNESS 0x52 +#define MIPI_DCS_SET_CONTROL_DISPLAY 0x53 +#define MIPI_DCS_GET_CONTROL_DISPLAY 0x54 +#define MIPI_DCS_SET_CABC_VALUE 0x55 +#define MIPI_DCS_GET_CABC_VALUE 0x56 +#define MIPI_DCS_SET_CABC_MIN_BRI 0x5E +#define MIPI_DCS_GET_CABC_MIN_BRI 0x5F +#define MIPI_DCS_READ_DDB_START 0xA1 +#define MIPI_DCS_READ_DDB_CONTINUE 0xA8 + +/*! MIPI DCS Panel Private CMDs. */ +#define MIPI_DCS_PRIV_UNK_A0 0xA0 +#define MIPI_DCS_PRIV_SET_POWER_CONTROL 0xB1 +#define MIPI_DCS_PRIV_SET_EXTC 0xB9 +#define MIPI_DCS_PRIV_UNK_BD 0xBD +#define MIPI_DCS_PRIV_UNK_D5 0xD5 +#define MIPI_DCS_PRIV_UNK_D6 0xD6 +#define MIPI_DCS_PRIV_UNK_D8 0xD8 +#define MIPI_DCS_PRIV_UNK_D9 0xD9 + +/*! MIPI DCS CMD Defines. */ +#define DCS_POWER_MODE_DISPLAY_ON BIT(2) +#define DCS_POWER_MODE_NORMAL_MODE BIT(3) +#define DCS_POWER_MODE_SLEEP_MODE BIT(4) +#define DCS_POWER_MODE_PARTIAL_MODE BIT(5) +#define DCS_POWER_MODE_IDLE_MODE BIT(6) + +#define DCS_ADDRESS_MODE_V_FLIP BIT(0) +#define DCS_ADDRESS_MODE_H_FLIP BIT(1) +#define DCS_ADDRESS_MODE_LATCH_RL BIT(2) // Latch Data Order. +#define DCS_ADDRESS_MODE_BGR_COLOR BIT(3) +#define DCS_ADDRESS_MODE_LINE_ORDER BIT(4) // Line Refresh Order. +#define DCS_ADDRESS_MODE_SWAP_XY BIT(5) // Page/Column Addressing Reverse Order. +#define DCS_ADDRESS_MODE_MIRROR_X BIT(6) // Column Address Order. +#define DCS_ADDRESS_MODE_MIRROR_Y BIT(7) // Page Address Order. +#define DCS_ADDRESS_MODE_ROTATION_MASK (0xF << 4) +#define DCS_ADDRESS_MODE_ROTATION_90 (DCS_ADDRESS_MODE_SWAP_XY | DCS_ADDRESS_MODE_LINE_ORDER) +#define DCS_ADDRESS_MODE_ROTATION_180 (DCS_ADDRESS_MODE_MIRROR_X | DCS_ADDRESS_MODE_LINE_ORDER) +#define DCS_ADDRESS_MODE_ROTATION_270 (DCS_ADDRESS_MODE_SWAP_XY) + +#define DCS_GAMMA_CURVE_NONE 0 +#define DCS_GAMMA_CURVE_GC0_1_8 BIT(0) +#define DCS_GAMMA_CURVE_GC1_2_5 BIT(1) +#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_BACKLIGHT_CTRL BIT(2) +#define DCS_CONTROL_DISPLAY_DIMMING_CTRL BIT(3) +#define DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL BIT(5) /* Switch Panels: + * + * 6.2" panels for Icosa and Iowa skus: * [10] 81 [26]: JDI LPM062M326A * [10] 96 [09]: JDI LAM062M109A * [20] 93 [0F]: InnoLux P062CCA-AZ1 (Rev A1) - * [20] XX [10]: InnoLux P062CCA-AZ2 [UNCONFIRMED ID] + * [20] 95 [0F]: InnoLux P062CCA-AZ2 * [30] 94 [0F]: AUO A062TAN01 (59.06A33.001) - * [30] XX [10]: AUO A062TAN02 (59.06A33.002) [UNCONFIRMED ID] + * [30] 95 [0F]: AUO A062TAN02 (59.06A33.002) + * + * 5.5" panels for Hoag skus: + * [20] 94 [10]: InnoLux 2J055IA-27A (Rev B1) + * [30] XX [10]: AUO A055TAN01 (59.05A30.001) [UNCONFIRMED ID] + * [40] XX [10]: Vendor 40 [UNCONFIRMED ID] + */ + +/* Display ID Decoding: + * + * byte0: Vendor + * byte1: Model + * byte2: Board + * + * Vendors: + * 10h: Japan Display Inc. + * 20h: InnoLux Corporation + * 30h: AU Optronics + * 40h: Unknown1 + * + * Boards, Panel Size: + * 0Fh: Icosa/Iowa, 6.2" + * 10h: Hoag, 5.5" */ enum @@ -511,14 +684,18 @@ enum PANEL_JDI_LPM062M326A = 0x2610, PANEL_INL_P062CCA_AZ1 = 0x0F20, PANEL_AUO_A062TAN01 = 0x0F30, - PANEL_INL_P062CCA_AZ2 = 0x1020, - PANEL_AUO_A062TAN02 = 0x1030 + PANEL_INL_2J055IA_27A = 0x1020, + PANEL_AUO_A055TAN01 = 0x1030, + PANEL_V40_55_UNK = 0x1040 }; void display_init(); void display_backlight_pwm_init(); void display_end(); +/*! Get Display panel ID. */ +u16 display_get_decoded_lcd_id(); + /*! Show one single color on the display. */ void display_color_screen(u32 color); @@ -537,4 +714,7 @@ 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); + #endif diff --git a/bdk/gfx/di.inl b/bdk/gfx/di.inl index ef3b1b0..f98c5c7 100644 --- a/bdk/gfx/di.inl +++ b/bdk/gfx/di.inl @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert -* Copyright (c) 2018-2019 CTCaer +* Copyright (c) 2018-2020 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,7 +20,7 @@ static const cfg_op_t _display_dc_setup_win_config[94] = { {DC_CMD_STATE_ACCESS, 0}, {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, - {DC_CMD_REG_ACT_CONTROL, 0x54}, + {DC_CMD_REG_ACT_CONTROL, 0x54}, // Select H counter for win A/B/C. {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, @@ -96,16 +96,16 @@ static const cfg_op_t _display_dc_setup_win_config[94] = { {DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C}, {DC_COM_PIN_OUTPUT_POLARITY(1), 0x1000000}, {DC_COM_PIN_OUTPUT_POLARITY(3), 0}, - {0x4E4, 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}, - {0x716, 0x10000FF}, + {DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF}, {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, - {0x716, 0x10000FF}, + {DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF}, {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, - {0x716, 0x10000FF}, + {DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF}, {DC_CMD_DISPLAY_COMMAND_OPTION0, 0}, {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, {DC_WIN_WIN_OPTIONS, 0}, @@ -120,7 +120,7 @@ static const cfg_op_t _display_dc_setup_win_config[94] = { }; //DSI Init config. -static const cfg_op_t _display_dsi_init_config[61] = { +static const cfg_op_t _display_dsi_init_config_part1[8] = { {DSI_WR_DATA, 0}, {DSI_INT_ENABLE, 0}, {DSI_INT_STATUS, 0}, @@ -128,8 +128,9 @@ static const cfg_op_t _display_dsi_init_config[61] = { {DSI_INIT_SEQ_DATA_0, 0}, {DSI_INIT_SEQ_DATA_1, 0}, {DSI_INIT_SEQ_DATA_2, 0}, - {DSI_INIT_SEQ_DATA_3, 0}, - {DSI_INIT_SEQ_DATA_15, 0}, + {DSI_INIT_SEQ_DATA_3, 0} +}; +static const cfg_op_t _display_dsi_init_config_part2[14] = { {DSI_DCS_CMDS, 0}, {DSI_PKT_SEQ_0_LO, 0}, {DSI_PKT_SEQ_1_LO, 0}, @@ -143,7 +144,18 @@ static const cfg_op_t _display_dsi_init_config[61] = { {DSI_PKT_SEQ_3_HI, 0}, {DSI_PKT_SEQ_4_HI, 0}, {DSI_PKT_SEQ_5_HI, 0}, - {DSI_CONTROL, 0}, + {DSI_CONTROL, 0} +}; +static const cfg_op_t _display_dsi_init_config_part3_t210b01[7] = { + {DSI_PAD_CONTROL_1, 0}, + {DSI_PAD_CONTROL_2, 0}, + {DSI_PAD_CONTROL_3, 0}, + {DSI_PAD_CONTROL_4, 0}, + {DSI_PAD_CONTROL_5_B01, 0}, + {DSI_PAD_CONTROL_6_B01, 0}, + {DSI_PAD_CONTROL_7_B01, 0} +}; +static const cfg_op_t _display_dsi_init_config_part4[10] = { {DSI_PAD_CONTROL_CD, 0}, {DSI_SOL_DELAY, 0x18}, {DSI_MAX_THRESHOLD, 0x1E0}, @@ -153,8 +165,9 @@ static const cfg_op_t _display_dsi_init_config[61] = { {DSI_PKT_LEN_2_3, 0}, {DSI_PKT_LEN_4_5, 0}, {DSI_PKT_LEN_6_7, 0}, - {DSI_PAD_CONTROL_1, 0}, - {DSI_PHY_TIMING_0, 0x6070601}, + {DSI_PAD_CONTROL_1, 0} +}; +static const cfg_op_t _display_dsi_init_config_part5[12] = { {DSI_PHY_TIMING_1, 0x40A0E05}, {DSI_PHY_TIMING_2, 0x30109}, {DSI_BTA_TIMING, 0x190A14}, @@ -166,8 +179,9 @@ static const cfg_op_t _display_dsi_init_config[61] = { {DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, {DSI_POWER_CONTROL, 0}, {DSI_POWER_CONTROL, 0}, - {DSI_PAD_CONTROL_1, 0}, - {DSI_PHY_TIMING_0, 0x6070601}, + {DSI_PAD_CONTROL_1, 0} +}; +static const cfg_op_t _display_dsi_init_config_part6[14] = { {DSI_PHY_TIMING_1, 0x40A0E05}, {DSI_PHY_TIMING_2, 0x30118}, {DSI_BTA_TIMING, 0x190A14}, @@ -187,12 +201,12 @@ static const cfg_op_t _display_dsi_init_config[61] = { //DSI panel config. static const cfg_op_t _display_init_config_jdi[43] = { {DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes. - {DSI_WR_DATA, 0x9483FFB9}, // Enable extension cmd. (Pass: FF 83 94). + {DSI_WR_DATA, 0x9483FFB9}, // MIPI_DCS_PRIV_SET_EXTC. (Pass: FF 83 94). {DSI_TRIGGER, DSI_TRIGGER_HOST}, - {DSI_WR_DATA, 0x00BD15}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 0x0BD. + {DSI_WR_DATA, 0x00BD15}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 0 to 0xBD. {DSI_TRIGGER, DSI_TRIGGER_HOST}, {DSI_WR_DATA, 0x1939}, // MIPI_DSI_DCS_LONG_WRITE: 25 bytes. - {DSI_WR_DATA, 0xAAAAAAD8}, + {DSI_WR_DATA, 0xAAAAAAD8}, // Register: 0xD8. {DSI_WR_DATA, 0xAAAAAAEB}, {DSI_WR_DATA, 0xAAEBAAAA}, {DSI_WR_DATA, 0xAAAAAAAA}, @@ -200,10 +214,10 @@ static const cfg_op_t _display_init_config_jdi[43] = { {DSI_WR_DATA, 0xAAEBAAAA}, {DSI_WR_DATA, 0xAA}, {DSI_TRIGGER, DSI_TRIGGER_HOST}, - {DSI_WR_DATA, 0x01BD15}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 0x1BD. + {DSI_WR_DATA, 0x01BD15}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 1 to 0xBD. {DSI_TRIGGER, DSI_TRIGGER_HOST}, {DSI_WR_DATA, 0x2739}, // MIPI_DSI_DCS_LONG_WRITE: 39 bytes. - {DSI_WR_DATA, 0xFFFFFFD8}, + {DSI_WR_DATA, 0xFFFFFFD8}, // Register: 0xD8. {DSI_WR_DATA, 0xFFFFFFFF}, {DSI_WR_DATA, 0xFFFFFFFF}, {DSI_WR_DATA, 0xFFFFFFFF}, @@ -214,27 +228,25 @@ static const cfg_op_t _display_init_config_jdi[43] = { {DSI_WR_DATA, 0xFFFFFFFF}, {DSI_WR_DATA, 0xFFFFFF}, {DSI_TRIGGER, DSI_TRIGGER_HOST}, - {DSI_WR_DATA, 0x02BD15}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 0x2BD. + {DSI_WR_DATA, 0x02BD15}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 2 to 0xBD. {DSI_TRIGGER, DSI_TRIGGER_HOST}, {DSI_WR_DATA, 0xF39}, // MIPI_DSI_DCS_LONG_WRITE: 15 bytes. - {DSI_WR_DATA, 0xFFFFFFD8}, + {DSI_WR_DATA, 0xFFFFFFD8}, // Register: 0xD8. {DSI_WR_DATA, 0xFFFFFFFF}, {DSI_WR_DATA, 0xFFFFFFFF}, {DSI_WR_DATA, 0xFFFFFF}, {DSI_TRIGGER, DSI_TRIGGER_HOST}, - {DSI_WR_DATA, 0x00BD15}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 0x0BD. + {DSI_WR_DATA, 0x00BD15}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 0 to 0xBD. {DSI_TRIGGER, DSI_TRIGGER_HOST}, - {DSI_WR_DATA, 0x06D915}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 0x6D9. + {DSI_WR_DATA, 0x06D915}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 6 to 0xD9. {DSI_TRIGGER, DSI_TRIGGER_HOST}, {DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes. - {DSI_WR_DATA, 0x000000B9}, // Disable extension cmd. + {DSI_WR_DATA, 0x000000B9}, // MIPI_DCS_PRIV_SET_EXTC. Disable. {DSI_TRIGGER, DSI_TRIGGER_HOST} }; //DSI packet config. -static const cfg_op_t _display_dsi_packet_config[21] = { - {DSI_PAD_CONTROL_1, 0}, - {DSI_PHY_TIMING_0, 0x6070601}, +static const cfg_op_t _display_dsi_packet_config[19] = { {DSI_PHY_TIMING_1, 0x40A0E05}, {DSI_PHY_TIMING_2, 0x30172}, {DSI_BTA_TIMING, 0x190A14}, @@ -253,7 +265,7 @@ static const cfg_op_t _display_dsi_packet_config[21] = { {DSI_PKT_LEN_2_3, 0x87001A2}, {DSI_PKT_LEN_4_5, 0x190}, {DSI_PKT_LEN_6_7, 0x190}, - {DSI_HOST_CONTROL, 0}, + {DSI_HOST_CONTROL, 0} }; //DSI mode config. @@ -271,29 +283,44 @@ static const cfg_op_t _display_dsi_mode_config[10] = { }; //MIPI CAL config. -static const cfg_op_t _display_mipi_pad_cal_config[6] = { +static const cfg_op_t _display_mipi_pad_cal_config[4] = { {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}, - {MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0x10010}, - {MIPI_CAL_MIPI_BIAS_PAD_CFG1, 0x300} + {MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0} }; //DSI config. -static const cfg_op_t _display_dsi_pad_cal_config[4] = { +static const cfg_op_t _display_dsi_pad_cal_config_t210[4] = { {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}, + {DSI_PAD_CONTROL_5_B01, 0x77777}, + {DSI_PAD_CONTROL_6_B01, 0x1111}, + {DSI_PAD_CONTROL_7_B01, 0} +}; //MIPI CAL config. -static const cfg_op_t _display_mipi_apply_dsi_cal_config[16] = { +static const cfg_op_t _display_mipi_dsi_cal_offsets_config_t210[4] = { {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}, + {MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0x200002} +}; +static const cfg_op_t _display_mipi_dsi_cal_offsets_config_t210b01[4] = { + {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] = { {MIPI_CAL_CILA_MIPI_CAL_CONFIG, 0}, {MIPI_CAL_CILB_MIPI_CAL_CONFIG, 0}, {MIPI_CAL_CILC_MIPI_CAL_CONFIG, 0}, @@ -372,16 +399,16 @@ static const cfg_op_t _display_video_disp_controller_enable_config[113] = { {DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C}, {DC_COM_PIN_OUTPUT_POLARITY(1), 0x1000000}, {DC_COM_PIN_OUTPUT_POLARITY(3), 0}, - {0x4E4, 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}, - {0x716, 0x10000FF}, + {DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF}, {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, - {0x716, 0x10000FF}, + {DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF}, {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, - {0x716, 0x10000FF}, + {DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF}, {DC_CMD_DISPLAY_COMMAND_OPTION0, 0}, {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, {DC_WIN_WIN_OPTIONS, 0}, @@ -394,14 +421,37 @@ static const cfg_op_t _display_video_disp_controller_enable_config[113] = { {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}, - /* Set Display timings */ + + /* 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, (1 << 16)}, // h_ref_to_sync = 0, v_ref_to_sync = 1. + {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 be above the DC_DISP_ACTIVE cmd. + {DC_DISP_FRONT_PORCH, 0xA0088}, // Sources say that this should happen before DC_DISP_ACTIVE cmd. /* End of Display timings */ + {DC_DISP_SHIFT_CLOCK_OPTIONS, SC1_H_QUALIFIER_NONE | SC0_H_QUALIFIER_NONE}, {DC_COM_PIN_OUTPUT_ENABLE(1), 0}, {DC_DISP_DATA_ENABLE_OPTIONS, DE_SELECT_ACTIVE | DE_CONTROL_NORMAL}, @@ -477,10 +527,10 @@ static const cfg_op_t _display_dsi_timing_deinit_config[16] = { //DSI config (if ver == 0x10). static const cfg_op_t _display_deinit_config_jdi[22] = { {DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes. - {DSI_WR_DATA, 0x9483FFB9}, // Enable extension cmd. (Pass: FF 83 94). + {DSI_WR_DATA, 0x9483FFB9}, // MIPI_DCS_PRIV_SET_EXTC. (Pass: FF 83 94). {DSI_TRIGGER, DSI_TRIGGER_HOST}, {DSI_WR_DATA, 0x2139}, // MIPI_DSI_DCS_LONG_WRITE: 33 bytes. - {DSI_WR_DATA, 0x191919D5}, + {DSI_WR_DATA, 0x191919D5}, // Register: 0xD5. {DSI_WR_DATA, 0x19191919}, {DSI_WR_DATA, 0x19191919}, {DSI_WR_DATA, 0x19191919}, @@ -491,21 +541,21 @@ static const cfg_op_t _display_deinit_config_jdi[22] = { {DSI_WR_DATA, 0x19}, {DSI_TRIGGER, DSI_TRIGGER_HOST}, {DSI_WR_DATA, 0xB39}, // MIPI_DSI_DCS_LONG_WRITE: 11 bytes. - {DSI_WR_DATA, 0x4F0F41B1}, // Set Power control. + {DSI_WR_DATA, 0x4F0F41B1}, // MIPI_DCS_PRIV_SET_POWER_CONTROL. {DSI_WR_DATA, 0xF179A433}, {DSI_WR_DATA, 0x002D81}, {DSI_TRIGGER, DSI_TRIGGER_HOST}, {DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes. - {DSI_WR_DATA, 0x000000B9}, // Disable extension cmd. + {DSI_WR_DATA, 0x000000B9}, // MIPI_DCS_PRIV_SET_EXTC. Disable. {DSI_TRIGGER, DSI_TRIGGER_HOST} }; static const cfg_op_t _display_deinit_config_auo[37] = { {DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes. - {DSI_WR_DATA, 0x9483FFB9}, // Enable extension cmd. (Pass: FF 83 94). + {DSI_WR_DATA, 0x9483FFB9}, // MIPI_DCS_PRIV_SET_EXTC. (Pass: FF 83 94). {DSI_TRIGGER, DSI_TRIGGER_HOST}, {DSI_WR_DATA, 0x2C39}, // MIPI_DSI_DCS_LONG_WRITE: 44 bytes. - {DSI_WR_DATA, 0x191919D5}, + {DSI_WR_DATA, 0x191919D5}, // Register: 0xD5. {DSI_WR_DATA, 0x19191919}, {DSI_WR_DATA, 0x19191919}, {DSI_WR_DATA, 0x19191919}, @@ -518,7 +568,7 @@ static const cfg_op_t _display_deinit_config_auo[37] = { {DSI_WR_DATA, 0x19191919}, {DSI_TRIGGER, DSI_TRIGGER_HOST}, {DSI_WR_DATA, 0x2C39}, // MIPI_DSI_DCS_LONG_WRITE: 44 bytes. - {DSI_WR_DATA, 0x191919D6}, + {DSI_WR_DATA, 0x191919D6}, // Register: 0xD6. {DSI_WR_DATA, 0x19191919}, {DSI_WR_DATA, 0x19191919}, {DSI_WR_DATA, 0x19191919}, @@ -531,13 +581,13 @@ static const cfg_op_t _display_deinit_config_auo[37] = { {DSI_WR_DATA, 0x19191919}, {DSI_TRIGGER, DSI_TRIGGER_HOST}, {DSI_WR_DATA, 0xB39}, // MIPI_DSI_DCS_LONG_WRITE: 11 bytes. - {DSI_WR_DATA, 0x711148B1}, // Set Power control. (Not deep standby, BT1 / XDK, VRH gamma volt adj 49 / x40). - // Set Power control. (NVRH gamma volt adj 9, Amplifier current small / x30, FS0 freq Fosc/80 / FS1 freq Fosc/32, Enter standby / PON / VCOMG). + {DSI_WR_DATA, 0x711148B1}, // MIPI_DCS_PRIV_SET_POWER_CONTROL. (Not deep standby, BT1 / XDK, VRH gamma volt adj 49 / x40). + // (NVRH gamma volt adj 9, Amplifier current small / x30, FS0 freq Fosc/80 / FS1 freq Fosc/32, Enter standby / PON / VCOMG). {DSI_WR_DATA, 0x71143209}, - {DSI_WR_DATA, 0x114D31}, // Set Power control. (Unknown). + {DSI_WR_DATA, 0x114D31}, // (Unknown). {DSI_TRIGGER, DSI_TRIGGER_HOST}, {DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes. - {DSI_WR_DATA, 0x000000B9}, // Disable extension cmd. + {DSI_WR_DATA, 0x000000B9}, // MIPI_DCS_PRIV_SET_EXTC. Disable. {DSI_TRIGGER, DSI_TRIGGER_HOST} }; diff --git a/bdk/input/als.c b/bdk/input/als.c index 99749e2..97d6432 100644 --- a/bdk/input/als.c +++ b/bdk/input/als.c @@ -103,7 +103,8 @@ u8 als_init(als_table_t *als_val) i2c_init(I2C_2); max77620_regulator_set_volt_and_flags(REGULATOR_LDO6, 2900000, MAX77620_POWER_MODE_NORMAL); - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_LDO6_CFG2, 0xD8 | MAX77620_LDO_CFG2_ADE_MASK); + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_LDO6_CFG2, + (MAX77620_POWER_MODE_NORMAL << MAX77620_LDO_POWER_MODE_SHIFT | (3 << 3) | MAX77620_LDO_CFG2_ADE_ENABLE)); u8 id = i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(0x12)); i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_SPEC(BH1730_SPECCMD_RESET), 0); diff --git a/bdk/input/als.h b/bdk/input/als.h index ad31e42..09adcb6 100644 --- a/bdk/input/als.h +++ b/bdk/input/als.h @@ -45,8 +45,8 @@ #define BH1730_DATA1LOW_REG 0x16 #define BH1730_DATA1HIGH_REG 0x17 -#define BH1730_ADDR(reg) (BH1730_CMD_MAGIC | BH1730_CMD_SETADDR | reg) -#define BH1730_SPEC(cmd) (BH1730_CMD_MAGIC | BH1730_CMD_SPECCMD | cmd) +#define BH1730_ADDR(reg) (BH1730_CMD_MAGIC | BH1730_CMD_SETADDR | (reg)) +#define BH1730_SPEC(cmd) (BH1730_CMD_MAGIC | BH1730_CMD_SPECCMD | (cmd)) typedef struct _als_table_t { diff --git a/bdk/input/joycon.c b/bdk/input/joycon.c index 2db1aa6..9a3e11a 100644 --- a/bdk/input/joycon.c +++ b/bdk/input/joycon.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -33,32 +34,32 @@ // For disabling driver when logging is enabled. #include -#define JC_WIRED_CMD 0x91 -#define JC_WIRED_HID 0x92 -#define JC_WIRED_INIT_REPLY 0x94 -#define JC_INIT_HANDSHAKE 0xA5 +#define JC_WIRED_CMD 0x91 +#define JC_WIRED_HID 0x92 +#define JC_WIRED_INIT_REPLY 0x94 +#define JC_INIT_HANDSHAKE 0xA5 -#define JC_WIRED_CMD_MAC 0x01 -#define JC_WIRED_CMD_10 0x10 +#define JC_WIRED_CMD_MAC 0x01 +#define JC_WIRED_CMD_10 0x10 -#define JC_HID_OUTPUT_RPT 0x01 -#define JC_HID_RUMBLE_RPT 0x10 +#define JC_HID_OUTPUT_RPT 0x01 +#define JC_HID_RUMBLE_RPT 0x10 -#define JC_HID_INPUT_RPT 0x30 -#define JC_HID_SUBMCD_RPT 0x21 +#define JC_HID_INPUT_RPT 0x30 +#define JC_HID_SUBMCD_RPT 0x21 #define JC_HID_SUBCMD_HCI_STATE 0x06 -#define HCI_STATE_SLEEP 0x00 -#define HCI_STATE_RECONNECT 0x01 -#define HCI_STATE_PAIR 0x02 -#define HCI_STATE_HOME 0x04 +#define HCI_STATE_SLEEP 0x00 +#define HCI_STATE_RECONNECT 0x01 +#define HCI_STATE_PAIR 0x02 +#define HCI_STATE_HOME 0x04 #define JC_HID_SUBCMD_SPI_READ 0x10 -#define SPI_READ_OFFSET 0x20 +#define SPI_READ_OFFSET 0x20 #define JC_HID_SUBCMD_RUMBLE_CTL 0x48 #define JC_HID_SUBCMD_SND_RUMBLE 0xFF #define JC_BTN_MASK_L 0xFF2900 // 0xFFE900: with charge status. -#define JC_BTN_MASK_R 0x76FF +#define JC_BTN_MASK_R 0x0056FF #define JC_ID_L 1 #define JC_ID_R 2 @@ -206,7 +207,7 @@ static u16 jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, u8 *data, u out->uart_hdr.magic[1] = 0x01; out->uart_hdr.magic[2] = 0x3; - out->uart_hdr.total_size_lsb = 7; + out->uart_hdr.total_size_lsb = sizeof(jc_wired_hdr_t) - sizeof(jc_uart_hdr_t); out->uart_hdr.total_size_msb = 0; out->cmd = wired_cmd; @@ -523,6 +524,9 @@ 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) + return NULL; + bt_conn = &jc_gamepad.bt_conn_l; memset(bt_conn->host_mac, 0, 6); memset(bt_conn->ltk, 0, 16); @@ -812,7 +816,10 @@ void jc_init_hw() jc_l.uart = UART_C; jc_r.uart = UART_B; -#if (LV_LOG_PRINTF != 1) + if (fuse_read_hw_type() == FUSE_NX_HW_TYPE_HOAG) + return; + +#ifndef DEBUG_UART_PORT jc_power_supply(UART_C, true); jc_power_supply(UART_B, true); diff --git a/bdk/input/touch.c b/bdk/input/touch.c index eef61ec..f24b53a 100644 --- a/bdk/input/touch.c +++ b/bdk/input/touch.c @@ -361,7 +361,7 @@ int touch_power_on() // Enables LDO6 for touchscreen VDD/AVDD supply max77620_regulator_set_volt_and_flags(REGULATOR_LDO6, 2900000, MAX77620_POWER_MODE_NORMAL); i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_LDO6_CFG2, - MAX77620_LDO_CFG2_ADE_ENABLE | (3 << 3) | (MAX77620_POWER_MODE_NORMAL << MAX77620_LDO_POWER_MODE_SHIFT)); + (MAX77620_POWER_MODE_NORMAL << MAX77620_LDO_POWER_MODE_SHIFT | (3 << 3) | MAX77620_LDO_CFG2_ADE_ENABLE)); // Configure touchscreen GPIO. PINMUX_AUX(PINMUX_AUX_DAP4_SCLK) = PINMUX_PULL_DOWN | 1; diff --git a/bdk/libs/compr/lz.c b/bdk/libs/compr/lz.c index a17c6e4..94b64c6 100644 --- a/bdk/libs/compr/lz.c +++ b/bdk/libs/compr/lz.c @@ -125,7 +125,7 @@ static int _LZ_ReadVarSize( unsigned int * x, const unsigned char * buf ) * insize - Number of input bytes. *************************************************************************/ -void LZ_Uncompress( const unsigned char *in, unsigned char *out, +unsigned int LZ_Uncompress( const unsigned char *in, unsigned char *out, unsigned int insize ) { unsigned char marker, symbol; @@ -134,7 +134,7 @@ void LZ_Uncompress( const unsigned char *in, unsigned char *out, /* Do we have anything to uncompress? */ if( insize < 1 ) { - return; + return 0; } /* Get marker symbol from input stream */ @@ -176,4 +176,6 @@ void LZ_Uncompress( const unsigned char *in, unsigned char *out, } } while( inpos < insize ); + + return outpos; } diff --git a/bdk/libs/compr/lz.h b/bdk/libs/compr/lz.h index 6f31b4a..ef67055 100644 --- a/bdk/libs/compr/lz.h +++ b/bdk/libs/compr/lz.h @@ -41,7 +41,7 @@ extern "C" { * Function prototypes *************************************************************************/ -void LZ_Uncompress( const unsigned char *in, unsigned char *out, +unsigned int LZ_Uncompress( const unsigned char *in, unsigned char *out, unsigned int insize ); diff --git a/bdk/libs/compr/lz4.c b/bdk/libs/compr/lz4.c new file mode 100644 index 0000000..ddea3d8 --- /dev/null +++ b/bdk/libs/compr/lz4.c @@ -0,0 +1,1672 @@ +/* + LZ4 - Fast LZ compression algorithm + Copyright (C) 2011-2017, Yann Collet. + + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - LZ4 homepage : http://www.lz4.org + - LZ4 source repository : https://github.com/lz4/lz4 +*/ + + +/*-************************************ +* Tuning parameters +**************************************/ +/* + * ACCELERATION_DEFAULT : + * Select "acceleration" for LZ4_compress_fast() when parameter value <= 0 + */ +#define ACCELERATION_DEFAULT 1 + + +/*-************************************ +* Dependency +**************************************/ +#define LZ4_STATIC_LINKING_ONLY +#include "lz4.h" +/* see also "memory routines" below */ + + +/*-************************************ +* Compiler Options +**************************************/ +#ifndef LZ4_FORCE_INLINE +# ifdef _MSC_VER /* Visual Studio */ +# define LZ4_FORCE_INLINE static __forceinline +# else +# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ +# ifdef __GNUC__ +# define LZ4_FORCE_INLINE static inline __attribute__((always_inline)) +# else +# define LZ4_FORCE_INLINE static inline +# endif +# else +# define LZ4_FORCE_INLINE static +# endif /* __STDC_VERSION__ */ +# endif /* _MSC_VER */ +#endif /* LZ4_FORCE_INLINE */ + +/* LZ4_FORCE_O2_GCC_PPC64LE and LZ4_FORCE_O2_INLINE_GCC_PPC64LE + * Gcc on ppc64le generates an unrolled SIMDized loop for LZ4_wildCopy, + * together with a simple 8-byte copy loop as a fall-back path. + * However, this optimization hurts the decompression speed by >30%, + * because the execution does not go to the optimized loop + * for typical compressible data, and all of the preamble checks + * before going to the fall-back path become useless overhead. + * This optimization happens only with the -O3 flag, and -O2 generates + * a simple 8-byte copy loop. + * With gcc on ppc64le, all of the LZ4_decompress_* and LZ4_wildCopy + * functions are annotated with __attribute__((optimize("O2"))), + * and also LZ4_wildCopy is forcibly inlined, so that the O2 attribute + * of LZ4_wildCopy does not affect the compression speed. + */ +#if defined(__PPC64__) && defined(__LITTLE_ENDIAN__) && defined(__GNUC__) +# define LZ4_FORCE_O2_GCC_PPC64LE __attribute__((optimize("O2"))) +# define LZ4_FORCE_O2_INLINE_GCC_PPC64LE __attribute__((optimize("O2"))) LZ4_FORCE_INLINE +#else +# define LZ4_FORCE_O2_GCC_PPC64LE +# define LZ4_FORCE_O2_INLINE_GCC_PPC64LE static +#endif + +#if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__) +# define expect(expr,value) (__builtin_expect ((expr),(value)) ) +#else +# define expect(expr,value) (expr) +#endif + +#define likely(expr) expect((expr) != 0, 1) +#define unlikely(expr) expect((expr) != 0, 0) + + +/*-************************************ +* Memory routines +**************************************/ +#include /* malloc, calloc, free */ +#define ALLOC(s) malloc(s) +#define ALLOC_AND_ZERO(s) calloc(1,s) +#define FREEMEM free +#include /* memset, memcpy */ +#define MEM_INIT memset + + +/*-************************************ +* Basic Types +**************************************/ +typedef uint16_t U16; +typedef uint32_t U32; +typedef int32_t S32; +typedef uint64_t U64; +typedef uintptr_t uptrval; +typedef size_t reg_t; /* 32-bits in x32 mode */ + +/*-************************************ +* Reading and writing into memory +**************************************/ +static unsigned LZ4_isLittleEndian(void) +{ + const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */ + return one.c[0]; +} + +static U16 LZ4_read16(const void* memPtr) +{ + U16 val; memcpy(&val, memPtr, sizeof(val)); return val; +} + +static U32 LZ4_read32(const void* memPtr) +{ + U32 val; memcpy(&val, memPtr, sizeof(val)); return val; +} + +static reg_t LZ4_read_ARCH(const void* memPtr) +{ + reg_t val; memcpy(&val, memPtr, sizeof(val)); return val; +} + +static void LZ4_write16(void* memPtr, U16 value) +{ + memcpy(memPtr, &value, sizeof(value)); +} + +static void LZ4_write32(void* memPtr, U32 value) +{ + memcpy(memPtr, &value, sizeof(value)); +} + +static U16 LZ4_readLE16(const void* memPtr) +{ + if (LZ4_isLittleEndian()) { + return LZ4_read16(memPtr); + } else { + const BYTE* p = (const BYTE*)memPtr; + return (U16)((U16)p[0] + (p[1]<<8)); + } +} + +static void LZ4_writeLE16(void* memPtr, U16 value) +{ + if (LZ4_isLittleEndian()) { + LZ4_write16(memPtr, value); + } else { + BYTE* p = (BYTE*)memPtr; + p[0] = (BYTE) value; + p[1] = (BYTE)(value>>8); + } +} + +/* customized variant of memcpy, which can overwrite up to 8 bytes beyond dstEnd */ +LZ4_FORCE_O2_INLINE_GCC_PPC64LE +void LZ4_wildCopy(void* dstPtr, const void* srcPtr, void* dstEnd) +{ + BYTE* d = (BYTE*)dstPtr; + const BYTE* s = (const BYTE*)srcPtr; + BYTE* const e = (BYTE*)dstEnd; + + do { memcpy(d,s,8); d+=8; s+=8; } while (d=2) +# include +static int g_debuglog_enable = 1; +# define DEBUGLOG(l, ...) { \ + if ((g_debuglog_enable) && (l<=LZ4_DEBUG)) { \ + fprintf(stderr, __FILE__ ": "); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, " \n"); \ + } } +#else +# define DEBUGLOG(l, ...) {} /* disabled */ +#endif + + +/*-************************************ +* Common functions +**************************************/ +static unsigned LZ4_NbCommonBytes (reg_t val) +{ + if (LZ4_isLittleEndian()) { + if (sizeof(val)==8) { + return (__builtin_ctzll((U64)val) >> 3); + } else /* 32 bits */ { + return (__builtin_ctz((U32)val) >> 3); + } + } else /* Big Endian CPU */ { + if (sizeof(val)==8) { /* 64-bits */ + return (__builtin_clzll((U64)val) >> 3); + } else /* 32 bits */ { + return (__builtin_clz((U32)val) >> 3); + } + } +} + +#define STEPSIZE sizeof(reg_t) +LZ4_FORCE_INLINE +unsigned LZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit) +{ + const BYTE* const pStart = pIn; + + if (likely(pIn < pInLimit-(STEPSIZE-1))) { + reg_t const diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn); + if (!diff) { + pIn+=STEPSIZE; pMatch+=STEPSIZE; + } else { + return LZ4_NbCommonBytes(diff); + } } + + while (likely(pIn < pInLimit-(STEPSIZE-1))) { + reg_t const diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn); + if (!diff) { pIn+=STEPSIZE; pMatch+=STEPSIZE; continue; } + pIn += LZ4_NbCommonBytes(diff); + return (unsigned)(pIn - pStart); + } + + if ((STEPSIZE==8) && (pIn<(pInLimit-3)) && (LZ4_read32(pMatch) == LZ4_read32(pIn))) { pIn+=4; pMatch+=4; } + if ((pIn<(pInLimit-1)) && (LZ4_read16(pMatch) == LZ4_read16(pIn))) { pIn+=2; pMatch+=2; } + if ((pIn compression run slower on incompressible data */ + + +/*-************************************ +* Local Structures and types +**************************************/ +typedef enum { notLimited = 0, limitedOutput = 1 } limitedOutput_directive; +typedef enum { clearedTable = 0, byPtr, byU32, byU16 } tableType_t; + +/** + * This enum distinguishes several different modes of accessing previous + * content in the stream. + * + * - noDict : There is no preceding content. + * - withPrefix64k : Table entries up to ctx->dictSize before the current blob + * blob being compressed are valid and refer to the preceding + * content (of length ctx->dictSize), which is available + * contiguously preceding in memory the content currently + * being compressed. + * - usingExtDict : Like withPrefix64k, but the preceding content is somewhere + * else in memory, starting at ctx->dictionary with length + * ctx->dictSize. + * - usingDictCtx : Like usingExtDict, but everything concerning the preceding + * content is in a separate context, pointed to by + * ctx->dictCtx. ctx->dictionary, ctx->dictSize, and table + * entries in the current context that refer to positions + * preceding the beginning of the current compression are + * ignored. Instead, ctx->dictCtx->dictionary and ctx->dictCtx + * ->dictSize describe the location and size of the preceding + * content, and matches are found by looking in the ctx + * ->dictCtx->hashTable. + */ +typedef enum { noDict = 0, withPrefix64k, usingExtDict, usingDictCtx } dict_directive; +typedef enum { noDictIssue = 0, dictSmall } dictIssue_directive; + +typedef enum { endOnOutputSize = 0, endOnInputSize = 1 } endCondition_directive; +typedef enum { full = 0, partial = 1 } earlyEnd_directive; + + +/*-************************************ +* Local Utils +**************************************/ +int LZ4_versionNumber (void) { return LZ4_VERSION_NUMBER; } +const char* LZ4_versionString(void) { return LZ4_VERSION_STRING; } +int LZ4_compressBound(int isize) { return LZ4_COMPRESSBOUND(isize); } +int LZ4_sizeofState() { return LZ4_STREAMSIZE; } + + +/*-****************************** +* Compression functions +********************************/ +static U32 LZ4_hash4(U32 sequence, tableType_t const tableType) +{ + if (tableType == byU16) + return ((sequence * 2654435761U) >> ((MINMATCH*8)-(LZ4_HASHLOG+1))); + else + return ((sequence * 2654435761U) >> ((MINMATCH*8)-LZ4_HASHLOG)); +} + +static U32 LZ4_hash5(U64 sequence, tableType_t const tableType) +{ + static const U64 prime5bytes = 889523592379ULL; + static const U64 prime8bytes = 11400714785074694791ULL; + const U32 hashLog = (tableType == byU16) ? LZ4_HASHLOG+1 : LZ4_HASHLOG; + if (LZ4_isLittleEndian()) + return (U32)(((sequence << 24) * prime5bytes) >> (64 - hashLog)); + else + return (U32)(((sequence >> 24) * prime8bytes) >> (64 - hashLog)); +} + +LZ4_FORCE_INLINE U32 LZ4_hashPosition(const void* const p, tableType_t const tableType) +{ + if ((sizeof(reg_t)==8) && (tableType != byU16)) return LZ4_hash5(LZ4_read_ARCH(p), tableType); + return LZ4_hash4(LZ4_read32(p), tableType); +} + +static void LZ4_putIndexOnHash(U32 idx, U32 h, void* tableBase, tableType_t const tableType) +{ + switch (tableType) + { + default: /* fallthrough */ + case clearedTable: /* fallthrough */ + case byPtr: { /* illegal! */ return; } + case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = idx; return; } + case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = (U16)idx; return; } + } +} + +static void LZ4_putPositionOnHash(const BYTE* p, U32 h, void* tableBase, tableType_t const tableType, const BYTE* srcBase) +{ + switch (tableType) + { + case clearedTable: { /* illegal! */ return; } + case byPtr: { const BYTE** hashTable = (const BYTE**)tableBase; hashTable[h] = p; return; } + case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = (U32)(p-srcBase); return; } + case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = (U16)(p-srcBase); return; } + } +} + +LZ4_FORCE_INLINE void LZ4_putPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase) +{ + U32 const h = LZ4_hashPosition(p, tableType); + LZ4_putPositionOnHash(p, h, tableBase, tableType, srcBase); +} + +/* LZ4_getIndexOnHash() : + * Index of match position registered in hash table. + * hash position must be calculated by using base+index, or dictBase+index. + * Assumption 1 : only valid if tableType == byU32 or byU16. + * Assumption 2 : h is presumed valid (within limits of hash table) + */ +static U32 LZ4_getIndexOnHash(U32 h, const void* tableBase, tableType_t tableType) +{ + LZ4_STATIC_ASSERT(LZ4_MEMORY_USAGE > 2); + if (tableType == byU32) { const U32* const hashTable = (const U32*) tableBase; return hashTable[h]; } + if (tableType == byU16) { const U16* const hashTable = (const U16*) tableBase; return hashTable[h]; } + return 0; /* forbidden case */ +} + +static const BYTE* LZ4_getPositionOnHash(U32 h, const void* tableBase, tableType_t tableType, const BYTE* srcBase) +{ + if (tableType == byPtr) { const BYTE* const* hashTable = (const BYTE* const*) tableBase; return hashTable[h]; } + if (tableType == byU32) { const U32* const hashTable = (const U32*) tableBase; return hashTable[h] + srcBase; } + { const U16* const hashTable = (const U16*) tableBase; return hashTable[h] + srcBase; } /* default, to ensure a return */ +} + +LZ4_FORCE_INLINE const BYTE* LZ4_getPosition(const BYTE* p, const void* tableBase, tableType_t tableType, const BYTE* srcBase) +{ + U32 const h = LZ4_hashPosition(p, tableType); + return LZ4_getPositionOnHash(h, tableBase, tableType, srcBase); +} + +LZ4_FORCE_INLINE void LZ4_prepareTable( + LZ4_stream_t_internal* const cctx, + const int inputSize, + const tableType_t tableType) { + /* If the table hasn't been used, it's guaranteed to be zeroed out, and is + * therefore safe to use no matter what mode we're in. Otherwise, we figure + * out if it's safe to leave as is or whether it needs to be reset. + */ + if (cctx->tableType != clearedTable) { + if (cctx->tableType != tableType + || (tableType == byU16 && cctx->currentOffset + inputSize >= 0xFFFFU) + || (tableType == byU32 && cctx->currentOffset > 1 GB) + || tableType == byPtr + || inputSize >= 4 KB) + { + DEBUGLOG(4, "LZ4_prepareTable: Resetting table in %p", cctx); + MEM_INIT(cctx->hashTable, 0, LZ4_HASHTABLESIZE); + cctx->currentOffset = 0; + cctx->tableType = clearedTable; + } else { + DEBUGLOG(4, "LZ4_prepareTable: Re-use hash table (no reset)"); + } + } + + /* Adding a gap, so all previous entries are > MAX_DISTANCE back, is faster + * than compressing without a gap. However, compressing with + * currentOffset == 0 is faster still, so we preserve that case. + */ + if (cctx->currentOffset != 0 && tableType == byU32) { + DEBUGLOG(5, "LZ4_prepareTable: adding 64KB to currentOffset"); + cctx->currentOffset += 64 KB; + } + + /* Finally, clear history */ + cctx->dictCtx = NULL; + cctx->dictionary = NULL; + cctx->dictSize = 0; +} + +/** LZ4_compress_generic() : + inlined, to ensure branches are decided at compilation time */ +LZ4_FORCE_INLINE int LZ4_compress_generic( + LZ4_stream_t_internal* const cctx, + const char* const source, + char* const dest, + const int inputSize, + const int maxOutputSize, + const limitedOutput_directive outputLimited, + const tableType_t tableType, + const dict_directive dictDirective, + const dictIssue_directive dictIssue, + const U32 acceleration) +{ + const BYTE* ip = (const BYTE*) source; + + U32 const startIndex = cctx->currentOffset; + const BYTE* base = (const BYTE*) source - startIndex; + const BYTE* lowLimit; + + const LZ4_stream_t_internal* dictCtx = (const LZ4_stream_t_internal*) cctx->dictCtx; + const BYTE* const dictionary = + dictDirective == usingDictCtx ? dictCtx->dictionary : cctx->dictionary; + const U32 dictSize = + dictDirective == usingDictCtx ? dictCtx->dictSize : cctx->dictSize; + const U32 dictDelta = (dictDirective == usingDictCtx) ? startIndex - dictCtx->currentOffset : 0; /* make indexes in dictCtx comparable with index in current context */ + + int const maybe_extMem = (dictDirective == usingExtDict) || (dictDirective == usingDictCtx); + U32 const prefixIdxLimit = startIndex - dictSize; /* used when dictDirective == dictSmall */ + const BYTE* const dictEnd = dictionary + dictSize; + const BYTE* anchor = (const BYTE*) source; + const BYTE* const iend = ip + inputSize; + const BYTE* const mflimitPlusOne = iend - MFLIMIT + 1; + const BYTE* const matchlimit = iend - LASTLITERALS; + + /* the dictCtx currentOffset is indexed on the start of the dictionary, + * while a dictionary in the current context precedes the currentOffset */ + const BYTE* dictBase = dictDirective == usingDictCtx ? + dictionary + dictSize - dictCtx->currentOffset : /* is it possible that dictCtx->currentOffset != dictCtx->dictSize ? Yes if the dictionary context is not reset */ + dictionary + dictSize - startIndex; + + BYTE* op = (BYTE*) dest; + BYTE* const olimit = op + maxOutputSize; + + U32 offset = 0; + U32 forwardH; + + DEBUGLOG(5, "LZ4_compress_generic: srcSize=%i, tableType=%u", inputSize, tableType); + /* Init conditions */ + if ((U32)inputSize > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported inputSize, too large (or negative) */ + + lowLimit = (const BYTE*)source - (dictDirective == withPrefix64k ? dictSize : 0); + + if ((tableType == byU16) && (inputSize>=LZ4_64Klimit)) return 0; /* Size too large (not within 64K limit) */ + + /* Update context state */ + if (dictDirective == usingDictCtx) { + /* Subsequent linked blocks can't use the dictionary. */ + /* Instead, they use the block we just compressed. */ + cctx->dictCtx = NULL; + cctx->dictSize = (U32)inputSize; + } else { + cctx->dictSize += (U32)inputSize; + } + cctx->currentOffset += (U32)inputSize; + cctx->tableType = tableType; + + if (inputSizehashTable, tableType, base); + ip++; forwardH = LZ4_hashPosition(ip, tableType); + + /* Main Loop */ + for ( ; ; ) { + const BYTE* match; + BYTE* token; + + /* Find a match */ + if (tableType == byPtr) { + const BYTE* forwardIp = ip; + unsigned step = 1; + unsigned searchMatchNb = acceleration << LZ4_skipTrigger; + do { + U32 const h = forwardH; + ip = forwardIp; + forwardIp += step; + step = (searchMatchNb++ >> LZ4_skipTrigger); + + if (unlikely(forwardIp > mflimitPlusOne)) goto _last_literals; + + match = LZ4_getPositionOnHash(h, cctx->hashTable, tableType, base); + forwardH = LZ4_hashPosition(forwardIp, tableType); + LZ4_putPositionOnHash(ip, h, cctx->hashTable, tableType, base); + + } while ( (match+MAX_DISTANCE < ip) + || (LZ4_read32(match) != LZ4_read32(ip)) ); + + } else { /* byU32, byU16 */ + + const BYTE* forwardIp = ip; + unsigned step = 1; + unsigned searchMatchNb = acceleration << LZ4_skipTrigger; + do { + U32 const h = forwardH; + U32 const current = (U32)(forwardIp - base); + U32 matchIndex = LZ4_getIndexOnHash(h, cctx->hashTable, tableType); + ip = forwardIp; + forwardIp += step; + step = (searchMatchNb++ >> LZ4_skipTrigger); + + if (unlikely(forwardIp > mflimitPlusOne)) goto _last_literals; + + if (dictDirective == usingDictCtx) { + if (matchIndex < startIndex) { + /* there was no match, try the dictionary */ + matchIndex = LZ4_getIndexOnHash(h, dictCtx->hashTable, byU32); + match = dictBase + matchIndex; + matchIndex += dictDelta; /* make dictCtx index comparable with current context */ + lowLimit = dictionary; + } else { + match = base + matchIndex; + lowLimit = (const BYTE*)source; + } + } else if (dictDirective==usingExtDict) { + if (matchIndex < startIndex) { + DEBUGLOG(7, "extDict candidate: matchIndex=%5u < startIndex=%5u", matchIndex, startIndex); + match = dictBase + matchIndex; + lowLimit = dictionary; + } else { + match = base + matchIndex; + lowLimit = (const BYTE*)source; + } + } else { /* single continuous memory segment */ + match = base + matchIndex; + } + forwardH = LZ4_hashPosition(forwardIp, tableType); + LZ4_putIndexOnHash(current, h, cctx->hashTable, tableType); + + if ((dictIssue == dictSmall) && (matchIndex < prefixIdxLimit)) continue; /* match outside of valid area */ + if ((tableType != byU16) && (current - matchIndex > MAX_DISTANCE)) continue; /* too far - note: works even if matchIndex overflows */ + + if (LZ4_read32(match) == LZ4_read32(ip)) { + if (maybe_extMem) offset = current - matchIndex; + break; /* match found */ + } + + } while(1); + } + + /* Catch up */ + while (((ip>anchor) & (match > lowLimit)) && (unlikely(ip[-1]==match[-1]))) { ip--; match--; } + + /* Encode Literals */ + { unsigned const litLength = (unsigned)(ip - anchor); + token = op++; + if ((outputLimited) && /* Check output buffer overflow */ + (unlikely(op + litLength + (2 + 1 + LASTLITERALS) + (litLength/255) > olimit))) + return 0; + if (litLength >= RUN_MASK) { + int len = (int)litLength-RUN_MASK; + *token = (RUN_MASK<= 255 ; len-=255) *op++ = 255; + *op++ = (BYTE)len; + } + else *token = (BYTE)(litLength< matchlimit) limit = matchlimit; + matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, limit); + ip += MINMATCH + matchCode; + if (ip==limit) { + unsigned const more = LZ4_count(limit, (const BYTE*)source, matchlimit); + matchCode += more; + ip += more; + } + DEBUGLOG(6, " with matchLength=%u starting in extDict", matchCode+MINMATCH); + } else { + matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit); + ip += MINMATCH + matchCode; + DEBUGLOG(6, " with matchLength=%u", matchCode+MINMATCH); + } + + if ( outputLimited && /* Check output buffer overflow */ + (unlikely(op + (1 + LASTLITERALS) + (matchCode>>8) > olimit)) ) + return 0; + if (matchCode >= ML_MASK) { + *token += ML_MASK; + matchCode -= ML_MASK; + LZ4_write32(op, 0xFFFFFFFF); + while (matchCode >= 4*255) { + op+=4; + LZ4_write32(op, 0xFFFFFFFF); + matchCode -= 4*255; + } + op += matchCode / 255; + *op++ = (BYTE)(matchCode % 255); + } else + *token += (BYTE)(matchCode); + } + + anchor = ip; + + /* Test end of chunk */ + if (ip >= mflimitPlusOne) break; + + /* Fill table */ + LZ4_putPosition(ip-2, cctx->hashTable, tableType, base); + + /* Test next position */ + if (tableType == byPtr) { + + match = LZ4_getPosition(ip, cctx->hashTable, tableType, base); + LZ4_putPosition(ip, cctx->hashTable, tableType, base); + if ( (match+MAX_DISTANCE >= ip) + && (LZ4_read32(match) == LZ4_read32(ip)) ) + { token=op++; *token=0; goto _next_match; } + + } else { /* byU32, byU16 */ + + U32 const h = LZ4_hashPosition(ip, tableType); + U32 const current = (U32)(ip-base); + U32 matchIndex = LZ4_getIndexOnHash(h, cctx->hashTable, tableType); + if (dictDirective == usingDictCtx) { + if (matchIndex < startIndex) { + /* there was no match, try the dictionary */ + matchIndex = LZ4_getIndexOnHash(h, dictCtx->hashTable, byU32); + match = dictBase + matchIndex; + lowLimit = dictionary; /* required for match length counter */ + matchIndex += dictDelta; + } else { + match = base + matchIndex; + lowLimit = (const BYTE*)source; /* required for match length counter */ + } + } else if (dictDirective==usingExtDict) { + if (matchIndex < startIndex) { + match = dictBase + matchIndex; + lowLimit = dictionary; /* required for match length counter */ + } else { + match = base + matchIndex; + lowLimit = (const BYTE*)source; /* required for match length counter */ + } + } else { /* single memory segment */ + match = base + matchIndex; + } + LZ4_putIndexOnHash(current, h, cctx->hashTable, tableType); + if ( ((dictIssue==dictSmall) ? (matchIndex >= prefixIdxLimit) : 1) + && ((tableType==byU16) ? 1 : (current - matchIndex <= MAX_DISTANCE)) + && (LZ4_read32(match) == LZ4_read32(ip)) ) { + token=op++; + *token=0; + if (maybe_extMem) offset = current - matchIndex; + DEBUGLOG(6, "seq.start:%i, literals=%u, match.start:%i", (int)(anchor-(const BYTE*)source), 0, (int)(ip-(const BYTE*)source)); + goto _next_match; + } + } + + /* Prepare next loop */ + forwardH = LZ4_hashPosition(++ip, tableType); + + } + +_last_literals: + /* Encode Last Literals */ + { size_t const lastRun = (size_t)(iend - anchor); + if ( (outputLimited) && /* Check output buffer overflow */ + ((op - (BYTE*)dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize) ) + return 0; + if (lastRun >= RUN_MASK) { + size_t accumulator = lastRun - RUN_MASK; + *op++ = RUN_MASK << ML_BITS; + for(; accumulator >= 255 ; accumulator-=255) *op++ = 255; + *op++ = (BYTE) accumulator; + } else { + *op++ = (BYTE)(lastRun<internal_donotuse; + if (acceleration < 1) acceleration = ACCELERATION_DEFAULT; + LZ4_resetStream((LZ4_stream_t*)state); + if (maxOutputSize >= LZ4_compressBound(inputSize)) { + if (inputSize < LZ4_64Klimit) { + return LZ4_compress_generic(ctx, source, dest, inputSize, 0, notLimited, byU16, noDict, noDictIssue, acceleration); + } else { + const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)source > MAX_DISTANCE)) ? byPtr : byU32; + return LZ4_compress_generic(ctx, source, dest, inputSize, 0, notLimited, tableType, noDict, noDictIssue, acceleration); + } + } else { + if (inputSize < LZ4_64Klimit) {; + return LZ4_compress_generic(ctx, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration); + } else { + const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)source > MAX_DISTANCE)) ? byPtr : byU32; + return LZ4_compress_generic(ctx, source, dest, inputSize, maxOutputSize, limitedOutput, tableType, noDict, noDictIssue, acceleration); + } + } +} + +/** + * LZ4_compress_fast_extState_fastReset() : + * A variant of LZ4_compress_fast_extState(). + * + * Using this variant avoids an expensive initialization step. It is only safe + * to call if the state buffer is known to be correctly initialized already + * (see comment in lz4.h on LZ4_resetStream_fast() for a definition of + * "correctly initialized"). + */ +int LZ4_compress_fast_extState_fastReset(void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration) +{ + LZ4_stream_t_internal* ctx = &((LZ4_stream_t*)state)->internal_donotuse; + if (acceleration < 1) acceleration = ACCELERATION_DEFAULT; + + if (dstCapacity >= LZ4_compressBound(srcSize)) { + if (srcSize < LZ4_64Klimit) { + const tableType_t tableType = byU16; + LZ4_prepareTable(ctx, srcSize, tableType); + if (ctx->currentOffset) { + return LZ4_compress_generic(ctx, src, dst, srcSize, 0, notLimited, tableType, noDict, dictSmall, acceleration); + } else { + return LZ4_compress_generic(ctx, src, dst, srcSize, 0, notLimited, tableType, noDict, noDictIssue, acceleration); + } + } else { + const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)src > MAX_DISTANCE)) ? byPtr : byU32; + LZ4_prepareTable(ctx, srcSize, tableType); + return LZ4_compress_generic(ctx, src, dst, srcSize, 0, notLimited, tableType, noDict, noDictIssue, acceleration); + } + } else { + if (srcSize < LZ4_64Klimit) { + const tableType_t tableType = byU16; + LZ4_prepareTable(ctx, srcSize, tableType); + if (ctx->currentOffset) { + return LZ4_compress_generic(ctx, src, dst, srcSize, dstCapacity, limitedOutput, tableType, noDict, dictSmall, acceleration); + } else { + return LZ4_compress_generic(ctx, src, dst, srcSize, dstCapacity, limitedOutput, tableType, noDict, noDictIssue, acceleration); + } + } else { + const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)src > MAX_DISTANCE)) ? byPtr : byU32; + LZ4_prepareTable(ctx, srcSize, tableType); + return LZ4_compress_generic(ctx, src, dst, srcSize, dstCapacity, limitedOutput, tableType, noDict, noDictIssue, acceleration); + } + } +} + + +int LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) +{ + int result; + LZ4_stream_t ctx; + LZ4_stream_t* const ctxPtr = &ctx; + result = LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration); + + return result; +} + + +int LZ4_compress_default(const char* source, char* dest, int inputSize, int maxOutputSize) +{ + return LZ4_compress_fast(source, dest, inputSize, maxOutputSize, 1); +} + + +/* hidden debug function */ +/* strangely enough, gcc generates faster code when this function is uncommented, even if unused */ +int LZ4_compress_fast_force(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) +{ + LZ4_stream_t ctx; + LZ4_resetStream(&ctx); + + if (inputSize < LZ4_64Klimit) + return LZ4_compress_generic(&ctx.internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration); + else + return LZ4_compress_generic(&ctx.internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, sizeof(void*)==8 ? byU32 : byPtr, noDict, noDictIssue, acceleration); +} + + +/*-****************************** +* *_destSize() variant +********************************/ + +static int LZ4_compress_destSize_generic( + LZ4_stream_t_internal* const ctx, + const char* const src, + char* const dst, + int* const srcSizePtr, + const int targetDstSize, + const tableType_t tableType) +{ + const BYTE* ip = (const BYTE*) src; + const BYTE* base = (const BYTE*) src; + const BYTE* lowLimit = (const BYTE*) src; + const BYTE* anchor = ip; + const BYTE* const iend = ip + *srcSizePtr; + const BYTE* const mflimit = iend - MFLIMIT; + const BYTE* const matchlimit = iend - LASTLITERALS; + + BYTE* op = (BYTE*) dst; + BYTE* const oend = op + targetDstSize; + BYTE* const oMaxLit = op + targetDstSize - 2 /* offset */ - 8 /* because 8+MINMATCH==MFLIMIT */ - 1 /* token */; + BYTE* const oMaxMatch = op + targetDstSize - (LASTLITERALS + 1 /* token */); + BYTE* const oMaxSeq = oMaxLit - 1 /* token */; + + U32 forwardH; + + + /* Init conditions */ + if (targetDstSize < 1) return 0; /* Impossible to store anything */ + if ((U32)*srcSizePtr > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size, too large (or negative) */ + if ((tableType == byU16) && (*srcSizePtr>=LZ4_64Klimit)) return 0; /* Size too large (not within 64K limit) */ + if (*srcSizePtrhashTable, tableType, base); + ip++; forwardH = LZ4_hashPosition(ip, tableType); + + /* Main Loop */ + for ( ; ; ) { + const BYTE* match; + BYTE* token; + + /* Find a match */ + { const BYTE* forwardIp = ip; + unsigned step = 1; + unsigned searchMatchNb = 1 << LZ4_skipTrigger; + + do { + U32 h = forwardH; + ip = forwardIp; + forwardIp += step; + step = (searchMatchNb++ >> LZ4_skipTrigger); + + if (unlikely(forwardIp > mflimit)) goto _last_literals; + + match = LZ4_getPositionOnHash(h, ctx->hashTable, tableType, base); + forwardH = LZ4_hashPosition(forwardIp, tableType); + LZ4_putPositionOnHash(ip, h, ctx->hashTable, tableType, base); + + } while ( ((tableType==byU16) ? 0 : (match + MAX_DISTANCE < ip)) + || (LZ4_read32(match) != LZ4_read32(ip)) ); + } + + /* Catch up */ + while ((ip>anchor) && (match > lowLimit) && (unlikely(ip[-1]==match[-1]))) { ip--; match--; } + + /* Encode Literal length */ + { unsigned litLength = (unsigned)(ip - anchor); + token = op++; + if (op + ((litLength+240)/255) + litLength > oMaxLit) { + /* Not enough space for a last match */ + op--; + goto _last_literals; + } + if (litLength>=RUN_MASK) { + unsigned len = litLength - RUN_MASK; + *token=(RUN_MASK<= 255 ; len-=255) *op++ = 255; + *op++ = (BYTE)len; + } + else *token = (BYTE)(litLength< oMaxMatch) { + /* Match description too long : reduce it */ + matchLength = (15-1) + (oMaxMatch-op) * 255; + } + ip += MINMATCH + matchLength; + + if (matchLength>=ML_MASK) { + *token += ML_MASK; + matchLength -= ML_MASK; + while (matchLength >= 255) { matchLength-=255; *op++ = 255; } + *op++ = (BYTE)matchLength; + } + else *token += (BYTE)(matchLength); + } + + anchor = ip; + + /* Test end of block */ + if (ip > mflimit) break; + if (op > oMaxSeq) break; + + /* Fill table */ + LZ4_putPosition(ip-2, ctx->hashTable, tableType, base); + + /* Test next position */ + match = LZ4_getPosition(ip, ctx->hashTable, tableType, base); + LZ4_putPosition(ip, ctx->hashTable, tableType, base); + if ( (match+MAX_DISTANCE>=ip) + && (LZ4_read32(match)==LZ4_read32(ip)) ) + { token=op++; *token=0; goto _next_match; } + + /* Prepare next loop */ + forwardH = LZ4_hashPosition(++ip, tableType); + } + +_last_literals: + /* Encode Last Literals */ + { size_t lastRunSize = (size_t)(iend - anchor); + if (op + 1 /* token */ + ((lastRunSize+240)/255) /* litLength */ + lastRunSize /* literals */ > oend) { + /* adapt lastRunSize to fill 'dst' */ + lastRunSize = (oend-op) - 1; + lastRunSize -= (lastRunSize+240)/255; + } + ip = anchor + lastRunSize; + + if (lastRunSize >= RUN_MASK) { + size_t accumulator = lastRunSize - RUN_MASK; + *op++ = RUN_MASK << ML_BITS; + for(; accumulator >= 255 ; accumulator-=255) *op++ = 255; + *op++ = (BYTE) accumulator; + } else { + *op++ = (BYTE)(lastRunSize<= LZ4_compressBound(*srcSizePtr)) { /* compression success is guaranteed */ + return LZ4_compress_fast_extState(state, src, dst, *srcSizePtr, targetDstSize, 1); + } else { + if (*srcSizePtr < LZ4_64Klimit) { + return LZ4_compress_destSize_generic(&state->internal_donotuse, src, dst, srcSizePtr, targetDstSize, byU16); + } else { + tableType_t const tableType = ((sizeof(void*)==4) && ((uptrval)src > MAX_DISTANCE)) ? byPtr : byU32; + return LZ4_compress_destSize_generic(&state->internal_donotuse, src, dst, srcSizePtr, targetDstSize, tableType); + } } +} + + +int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize) +{ + LZ4_stream_t ctxBody; + LZ4_stream_t* ctx = &ctxBody; + + int result = LZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize); + + return result; +} + + + +/*-****************************** +* Streaming functions +********************************/ + +LZ4_stream_t* LZ4_createStream(void) +{ + LZ4_stream_t* lz4s = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t)); + LZ4_STATIC_ASSERT(LZ4_STREAMSIZE >= sizeof(LZ4_stream_t_internal)); /* A compilation error here means LZ4_STREAMSIZE is not large enough */ + DEBUGLOG(4, "LZ4_createStream %p", lz4s); + if (lz4s == NULL) return NULL; + LZ4_resetStream(lz4s); + return lz4s; +} + +void LZ4_resetStream (LZ4_stream_t* LZ4_stream) +{ + DEBUGLOG(5, "LZ4_resetStream (ctx:%p)", LZ4_stream); + MEM_INIT(LZ4_stream, 0, sizeof(LZ4_stream_t)); +} + +void LZ4_resetStream_fast(LZ4_stream_t* ctx) { + LZ4_prepareTable(&(ctx->internal_donotuse), 0, byU32); +} + +int LZ4_freeStream (LZ4_stream_t* LZ4_stream) +{ + if (!LZ4_stream) return 0; /* support free on NULL */ + DEBUGLOG(5, "LZ4_freeStream %p", LZ4_stream); + FREEMEM(LZ4_stream); + return (0); +} + + +#define HASH_UNIT sizeof(reg_t) +int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize) +{ + LZ4_stream_t_internal* dict = &LZ4_dict->internal_donotuse; + const tableType_t tableType = byU32; + const BYTE* p = (const BYTE*)dictionary; + const BYTE* const dictEnd = p + dictSize; + const BYTE* base; + + DEBUGLOG(4, "LZ4_loadDict (%i bytes from %p into %p)", dictSize, dictionary, LZ4_dict); + + LZ4_prepareTable(dict, 0, tableType); + + /* We always increment the offset by 64 KB, since, if the dict is longer, + * we truncate it to the last 64k, and if it's shorter, we still want to + * advance by a whole window length so we can provide the guarantee that + * there are only valid offsets in the window, which allows an optimization + * in LZ4_compress_fast_continue() where it uses noDictIssue even when the + * dictionary isn't a full 64k. */ + + if ((dictEnd - p) > 64 KB) p = dictEnd - 64 KB; + base = dictEnd - 64 KB - dict->currentOffset; + dict->dictionary = p; + dict->dictSize = (U32)(dictEnd - p); + dict->currentOffset += 64 KB; + dict->tableType = tableType; + + if (dictSize < (int)HASH_UNIT) { + return 0; + } + + while (p <= dictEnd-HASH_UNIT) { + LZ4_putPosition(p, dict->hashTable, tableType, base); + p+=3; + } + + return dict->dictSize; +} + +void LZ4_attach_dictionary(LZ4_stream_t *working_stream, const LZ4_stream_t *dictionary_stream) { + if (dictionary_stream != NULL) { + /* If the current offset is zero, we will never look in the + * external dictionary context, since there is no value a table + * entry can take that indicate a miss. In that case, we need + * to bump the offset to something non-zero. + */ + if (working_stream->internal_donotuse.currentOffset == 0) { + working_stream->internal_donotuse.currentOffset = 64 KB; + } + working_stream->internal_donotuse.dictCtx = &(dictionary_stream->internal_donotuse); + } else { + working_stream->internal_donotuse.dictCtx = NULL; + } +} + + +static void LZ4_renormDictT(LZ4_stream_t_internal* LZ4_dict, int nextSize) +{ + if (LZ4_dict->currentOffset + nextSize > 0x80000000) { /* potential ptrdiff_t overflow (32-bits mode) */ + /* rescale hash table */ + U32 const delta = LZ4_dict->currentOffset - 64 KB; + const BYTE* dictEnd = LZ4_dict->dictionary + LZ4_dict->dictSize; + int i; + DEBUGLOG(4, "LZ4_renormDictT"); + for (i=0; ihashTable[i] < delta) LZ4_dict->hashTable[i]=0; + else LZ4_dict->hashTable[i] -= delta; + } + LZ4_dict->currentOffset = 64 KB; + if (LZ4_dict->dictSize > 64 KB) LZ4_dict->dictSize = 64 KB; + LZ4_dict->dictionary = dictEnd - LZ4_dict->dictSize; + } +} + + +int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) +{ + const tableType_t tableType = byU32; + LZ4_stream_t_internal* streamPtr = &LZ4_stream->internal_donotuse; + const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize; + + if (streamPtr->initCheck) return 0; /* Uninitialized structure detected */ + LZ4_renormDictT(streamPtr, inputSize); /* avoid index overflow */ + if (acceleration < 1) acceleration = ACCELERATION_DEFAULT; + + /* Check overlapping input/dictionary space */ + { const BYTE* sourceEnd = (const BYTE*) source + inputSize; + if ((sourceEnd > streamPtr->dictionary) && (sourceEnd < dictEnd)) { + streamPtr->dictSize = (U32)(dictEnd - sourceEnd); + if (streamPtr->dictSize > 64 KB) streamPtr->dictSize = 64 KB; + if (streamPtr->dictSize < 4) streamPtr->dictSize = 0; + streamPtr->dictionary = dictEnd - streamPtr->dictSize; + } + } + + /* prefix mode : source data follows dictionary */ + if (dictEnd == (const BYTE*)source) { + if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset)) + return LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, tableType, withPrefix64k, dictSmall, acceleration); + else + return LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, tableType, withPrefix64k, noDictIssue, acceleration); + } + + /* external dictionary mode */ + { int result; + if (streamPtr->dictCtx) { + /* We depend here on the fact that dictCtx'es (produced by + * LZ4_loadDict) guarantee that their tables contain no references + * to offsets between dictCtx->currentOffset - 64 KB and + * dictCtx->currentOffset - dictCtx->dictSize. This makes it safe + * to use noDictIssue even when the dict isn't a full 64 KB. + */ + if (inputSize > 4 KB) { + /* For compressing large blobs, it is faster to pay the setup + * cost to copy the dictionary's tables into the active context, + * so that the compression loop is only looking into one table. + */ + memcpy(streamPtr, streamPtr->dictCtx, sizeof(LZ4_stream_t)); + result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, tableType, usingExtDict, noDictIssue, acceleration); + } else { + result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, tableType, usingDictCtx, noDictIssue, acceleration); + } + } else { + if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset)) { + result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, tableType, usingExtDict, dictSmall, acceleration); + } else { + result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, tableType, usingExtDict, noDictIssue, acceleration); + } + } + streamPtr->dictionary = (const BYTE*)source; + streamPtr->dictSize = (U32)inputSize; + return result; + } +} + + +/* Hidden debug function, to force-test external dictionary mode */ +int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char* dest, int srcSize) +{ + LZ4_stream_t_internal* streamPtr = &LZ4_dict->internal_donotuse; + int result; + + LZ4_renormDictT(streamPtr, srcSize); + + if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset)) { + result = LZ4_compress_generic(streamPtr, source, dest, srcSize, 0, notLimited, byU32, usingExtDict, dictSmall, 1); + } else { + result = LZ4_compress_generic(streamPtr, source, dest, srcSize, 0, notLimited, byU32, usingExtDict, noDictIssue, 1); + } + + streamPtr->dictionary = (const BYTE*)source; + streamPtr->dictSize = (U32)srcSize; + + return result; +} + + +/*! LZ4_saveDict() : + * If previously compressed data block is not guaranteed to remain available at its memory location, + * save it into a safer place (char* safeBuffer). + * Note : you don't need to call LZ4_loadDict() afterwards, + * dictionary is immediately usable, you can therefore call LZ4_compress_fast_continue(). + * Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error. + */ +int LZ4_saveDict (LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize) +{ + LZ4_stream_t_internal* const dict = &LZ4_dict->internal_donotuse; + const BYTE* const previousDictEnd = dict->dictionary + dict->dictSize; + + if ((U32)dictSize > 64 KB) dictSize = 64 KB; /* useless to define a dictionary > 64 KB */ + if ((U32)dictSize > dict->dictSize) dictSize = dict->dictSize; + + memmove(safeBuffer, previousDictEnd - dictSize, dictSize); + + dict->dictionary = (const BYTE*)safeBuffer; + dict->dictSize = (U32)dictSize; + + return dictSize; +} + + + +/*-***************************** +* Decompression functions +*******************************/ +/*! LZ4_decompress_generic() : + * This generic decompression function covers all use cases. + * It shall be instantiated several times, using different sets of directives. + * Note that it is important for performance that this function really get inlined, + * in order to remove useless branches during compilation optimization. + */ +LZ4_FORCE_O2_GCC_PPC64LE +LZ4_FORCE_INLINE int LZ4_decompress_generic( + const char* const src, + char* const dst, + int srcSize, + int outputSize, /* If endOnInput==endOnInputSize, this value is `dstCapacity` */ + + int endOnInput, /* endOnOutputSize, endOnInputSize */ + int partialDecoding, /* full, partial */ + int targetOutputSize, /* only used if partialDecoding==partial */ + int dict, /* noDict, withPrefix64k, usingExtDict */ + const BYTE* const lowPrefix, /* always <= dst, == dst when no prefix */ + const BYTE* const dictStart, /* only if dict==usingExtDict */ + const size_t dictSize /* note : = 0 if noDict */ + ) +{ + const BYTE* ip = (const BYTE*) src; + const BYTE* const iend = ip + srcSize; + + BYTE* op = (BYTE*) dst; + BYTE* const oend = op + outputSize; + BYTE* cpy; + BYTE* oexit = op + targetOutputSize; + + const BYTE* const dictEnd = (const BYTE*)dictStart + dictSize; + const unsigned inc32table[8] = {0, 1, 2, 1, 0, 4, 4, 4}; + const int dec64table[8] = {0, 0, 0, -1, -4, 1, 2, 3}; + + const int safeDecode = (endOnInput==endOnInputSize); + const int checkOffset = ((safeDecode) && (dictSize < (int)(64 KB))); + + + /* Special cases */ + if ((partialDecoding) && (oexit > oend-MFLIMIT)) oexit = oend-MFLIMIT; /* targetOutputSize too high => just decode everything */ + if ((endOnInput) && (unlikely(outputSize==0))) return ((srcSize==1) && (*ip==0)) ? 0 : -1; /* Empty output buffer */ + if ((!endOnInput) && (unlikely(outputSize==0))) return (*ip==0?1:-1); + + /* Main Loop : decode sequences */ + while (1) { + size_t length; + const BYTE* match; + size_t offset; + + unsigned const token = *ip++; + + /* shortcut for common case : + * in most circumstances, we expect to decode small matches (<= 18 bytes) separated by few literals (<= 14 bytes). + * this shortcut was tested on x86 and x64, where it improves decoding speed. + * it has not yet been benchmarked on ARM, Power, mips, etc. */ + if (((ip + 14 /*maxLL*/ + 2 /*offset*/ <= iend) + & (op + 14 /*maxLL*/ + 18 /*maxML*/ <= oend)) + & ((token < (15<> ML_BITS; + size_t const off = LZ4_readLE16(ip+ll); + const BYTE* const matchPtr = op + ll - off; /* pointer underflow risk ? */ + if ((off >= 8) /* do not deal with overlapping matches */ & (matchPtr >= lowPrefix)) { + size_t const ml = (token & ML_MASK) + MINMATCH; + memcpy(op, ip, 16); op += ll; ip += ll + 2 /*offset*/; + memcpy(op + 0, matchPtr + 0, 8); + memcpy(op + 8, matchPtr + 8, 8); + memcpy(op +16, matchPtr +16, 2); + op += ml; + continue; + } + } + + /* decode literal length */ + if ((length=(token>>ML_BITS)) == RUN_MASK) { + unsigned s; + do { + s = *ip++; + length += s; + } while ( likely(endOnInput ? ip(partialDecoding?oexit:oend-MFLIMIT)) || (ip+length>iend-(2+1+LASTLITERALS))) ) + || ((!endOnInput) && (cpy>oend-WILDCOPYLENGTH)) ) + { + if (partialDecoding) { + if (cpy > oend) goto _output_error; /* Error : write attempt beyond end of output buffer */ + if ((endOnInput) && (ip+length > iend)) goto _output_error; /* Error : read attempt beyond end of input buffer */ + } else { + if ((!endOnInput) && (cpy != oend)) goto _output_error; /* Error : block decoding must stop exactly there */ + if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) goto _output_error; /* Error : input must be consumed */ + } + memcpy(op, ip, length); + ip += length; + op += length; + break; /* Necessarily EOF, due to parsing restrictions */ + } + LZ4_wildCopy(op, ip, cpy); + ip += length; op = cpy; + + /* get offset */ + offset = LZ4_readLE16(ip); ip+=2; + match = op - offset; + if ((checkOffset) && (unlikely(match + dictSize < lowPrefix))) goto _output_error; /* Error : offset outside buffers */ + LZ4_write32(op, (U32)offset); /* costs ~1%; silence an msan warning when offset==0 */ + + /* get matchlength */ + length = token & ML_MASK; + if (length == ML_MASK) { + unsigned s; + do { + s = *ip++; + if ((endOnInput) && (ip > iend-LASTLITERALS)) goto _output_error; + length += s; + } while (s==255); + if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)op)) goto _output_error; /* overflow detection */ + } + length += MINMATCH; + + /* check external dictionary */ + if ((dict==usingExtDict) && (match < lowPrefix)) { + if (unlikely(op+length > oend-LASTLITERALS)) goto _output_error; /* doesn't respect parsing restriction */ + + if (length <= (size_t)(lowPrefix-match)) { + /* match can be copied as a single segment from external dictionary */ + memmove(op, dictEnd - (lowPrefix-match), length); + op += length; + } else { + /* match encompass external dictionary and current block */ + size_t const copySize = (size_t)(lowPrefix-match); + size_t const restSize = length - copySize; + memcpy(op, dictEnd - copySize, copySize); + op += copySize; + if (restSize > (size_t)(op-lowPrefix)) { /* overlap copy */ + BYTE* const endOfMatch = op + restSize; + const BYTE* copyFrom = lowPrefix; + while (op < endOfMatch) *op++ = *copyFrom++; + } else { + memcpy(op, lowPrefix, restSize); + op += restSize; + } } + continue; + } + + /* copy match within block */ + cpy = op + length; + if (unlikely(offset<8)) { + op[0] = match[0]; + op[1] = match[1]; + op[2] = match[2]; + op[3] = match[3]; + match += inc32table[offset]; + memcpy(op+4, match, 4); + match -= dec64table[offset]; + } else { memcpy(op, match, 8); match+=8; } + op += 8; + + if (unlikely(cpy>oend-12)) { + BYTE* const oCopyLimit = oend-(WILDCOPYLENGTH-1); + if (cpy > oend-LASTLITERALS) goto _output_error; /* Error : last LASTLITERALS bytes must be literals (uncompressed) */ + if (op < oCopyLimit) { + LZ4_wildCopy(op, match, oCopyLimit); + match += oCopyLimit - op; + op = oCopyLimit; + } + while (op16) LZ4_wildCopy(op+8, match+8, cpy); + } + op = cpy; /* correction */ + } + + /* end of decoding */ + if (endOnInput) + return (int) (((char*)op)-dst); /* Nb of output bytes decoded */ + else + return (int) (((const char*)ip)-src); /* Nb of input bytes read */ + + /* Overflow error detected */ +_output_error: + return (int) (-(((const char*)ip)-src))-1; +} + + +LZ4_FORCE_O2_GCC_PPC64LE +int LZ4_decompress_safe(const char* source, char* dest, int compressedSize, int maxDecompressedSize) +{ + return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, full, 0, noDict, (BYTE*)dest, NULL, 0); +} + +LZ4_FORCE_O2_GCC_PPC64LE +int LZ4_decompress_safe_partial(const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize) +{ + return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, partial, targetOutputSize, noDict, (BYTE*)dest, NULL, 0); +} + +LZ4_FORCE_O2_GCC_PPC64LE +int LZ4_decompress_fast(const char* source, char* dest, int originalSize) +{ + return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k, (BYTE*)(dest - 64 KB), NULL, 64 KB); +} + + +/*===== streaming decompression functions =====*/ + +LZ4_streamDecode_t* LZ4_createStreamDecode(void) +{ + LZ4_streamDecode_t* lz4s = (LZ4_streamDecode_t*) ALLOC_AND_ZERO(sizeof(LZ4_streamDecode_t)); + return lz4s; +} + +int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream) +{ + if (!LZ4_stream) return 0; /* support free on NULL */ + FREEMEM(LZ4_stream); + return 0; +} + +/*! + * LZ4_setStreamDecode() : + * Use this function to instruct where to find the dictionary. + * This function is not necessary if previous data is still available where it was decoded. + * Loading a size of 0 is allowed (same effect as no dictionary). + * Return : 1 if OK, 0 if error + */ +int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize) +{ + LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse; + lz4sd->prefixSize = (size_t) dictSize; + lz4sd->prefixEnd = (const BYTE*) dictionary + dictSize; + lz4sd->externalDict = NULL; + lz4sd->extDictSize = 0; + return 1; +} + +/* +*_continue() : + These decoding functions allow decompression of multiple blocks in "streaming" mode. + Previously decoded blocks must still be available at the memory position where they were decoded. + If it's not possible, save the relevant part of decoded data into a safe buffer, + and indicate where it stands using LZ4_setStreamDecode() +*/ +LZ4_FORCE_O2_GCC_PPC64LE +int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxOutputSize) +{ + LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse; + int result; + + if (lz4sd->prefixEnd == (BYTE*)dest) { + result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, + endOnInputSize, full, 0, + usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize); + if (result <= 0) return result; + lz4sd->prefixSize += result; + lz4sd->prefixEnd += result; + } else { + lz4sd->extDictSize = lz4sd->prefixSize; + lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize; + result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, + endOnInputSize, full, 0, + usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize); + if (result <= 0) return result; + lz4sd->prefixSize = result; + lz4sd->prefixEnd = (BYTE*)dest + result; + } + + return result; +} + +LZ4_FORCE_O2_GCC_PPC64LE +int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize) +{ + LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse; + int result; + + if (lz4sd->prefixEnd == (BYTE*)dest) { + result = LZ4_decompress_generic(source, dest, 0, originalSize, + endOnOutputSize, full, 0, + usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize); + if (result <= 0) return result; + lz4sd->prefixSize += originalSize; + lz4sd->prefixEnd += originalSize; + } else { + lz4sd->extDictSize = lz4sd->prefixSize; + lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize; + result = LZ4_decompress_generic(source, dest, 0, originalSize, + endOnOutputSize, full, 0, + usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize); + if (result <= 0) return result; + lz4sd->prefixSize = originalSize; + lz4sd->prefixEnd = (BYTE*)dest + originalSize; + } + + return result; +} + + +/* +Advanced decoding functions : +*_usingDict() : + These decoding functions work the same as "_continue" ones, + the dictionary must be explicitly provided within parameters +*/ + +LZ4_FORCE_O2_GCC_PPC64LE +LZ4_FORCE_INLINE int LZ4_decompress_usingDict_generic(const char* source, char* dest, int compressedSize, int maxOutputSize, int safe, const char* dictStart, int dictSize) +{ + if (dictSize==0) + return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest, NULL, 0); + if (dictStart+dictSize == dest) { + if (dictSize >= (int)(64 KB - 1)) + return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, withPrefix64k, (BYTE*)dest-64 KB, NULL, 0); + return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest-dictSize, NULL, 0); + } + return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize); +} + +LZ4_FORCE_O2_GCC_PPC64LE +int LZ4_decompress_safe_usingDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize) +{ + return LZ4_decompress_usingDict_generic(source, dest, compressedSize, maxOutputSize, 1, dictStart, dictSize); +} + +LZ4_FORCE_O2_GCC_PPC64LE +int LZ4_decompress_fast_usingDict(const char* source, char* dest, int originalSize, const char* dictStart, int dictSize) +{ + return LZ4_decompress_usingDict_generic(source, dest, 0, originalSize, 0, dictStart, dictSize); +} + +/* debug function */ +LZ4_FORCE_O2_GCC_PPC64LE +int LZ4_decompress_safe_forceExtDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize) +{ + return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize); +} + + +/*=************************************************* +* Obsolete Functions +***************************************************/ +/* obsolete compression functions */ +int LZ4_compress_limitedOutput(const char* source, char* dest, int inputSize, int maxOutputSize) { return LZ4_compress_default(source, dest, inputSize, maxOutputSize); } +int LZ4_compress(const char* source, char* dest, int inputSize) { return LZ4_compress_default(source, dest, inputSize, LZ4_compressBound(inputSize)); } +int LZ4_compress_limitedOutput_withState (void* state, const char* src, char* dst, int srcSize, int dstSize) { return LZ4_compress_fast_extState(state, src, dst, srcSize, dstSize, 1); } +int LZ4_compress_withState (void* state, const char* src, char* dst, int srcSize) { return LZ4_compress_fast_extState(state, src, dst, srcSize, LZ4_compressBound(srcSize), 1); } +int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_stream, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_fast_continue(LZ4_stream, src, dst, srcSize, maxDstSize, 1); } +int LZ4_compress_continue (LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize) { return LZ4_compress_fast_continue(LZ4_stream, source, dest, inputSize, LZ4_compressBound(inputSize), 1); } + +/* +These function names are deprecated and should no longer be used. +They are only provided here for compatibility with older user programs. +- LZ4_uncompress is totally equivalent to LZ4_decompress_fast +- LZ4_uncompress_unknownOutputSize is totally equivalent to LZ4_decompress_safe +*/ +int LZ4_uncompress (const char* source, char* dest, int outputSize) { return LZ4_decompress_fast(source, dest, outputSize); } +int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize) { return LZ4_decompress_safe(source, dest, isize, maxOutputSize); } + +/* Obsolete Streaming functions */ + +int LZ4_sizeofStreamState() { return LZ4_STREAMSIZE; } + +int LZ4_resetStreamState(void* state, char* inputBuffer) +{ + (void)inputBuffer; + LZ4_resetStream((LZ4_stream_t*)state); + return 0; +} + +void* LZ4_create (char* inputBuffer) +{ + (void)inputBuffer; + return LZ4_createStream(); +} + +char* LZ4_slideInputBuffer (void* state) +{ + /* avoid const char * -> char * conversion warning */ + return (char *)(uptrval)((LZ4_stream_t*)state)->internal_donotuse.dictionary; +} + +/* Obsolete streaming decompression functions */ + +int LZ4_decompress_safe_withPrefix64k(const char* source, char* dest, int compressedSize, int maxOutputSize) +{ + return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, withPrefix64k, (BYTE*)dest - 64 KB, NULL, 64 KB); +} + +int LZ4_decompress_fast_withPrefix64k(const char* source, char* dest, int originalSize) +{ + return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k, (BYTE*)dest - 64 KB, NULL, 64 KB); +} + +#endif /* LZ4_COMMONDEFS_ONLY */ diff --git a/bdk/libs/compr/lz4.h b/bdk/libs/compr/lz4.h new file mode 100644 index 0000000..0dfa19e --- /dev/null +++ b/bdk/libs/compr/lz4.h @@ -0,0 +1,569 @@ +/* + * LZ4 - Fast LZ compression algorithm + * Header File + * Copyright (C) 2011-2017, Yann Collet. + + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - LZ4 homepage : http://www.lz4.org + - LZ4 source repository : https://github.com/lz4/lz4 +*/ +#if defined (__cplusplus) +extern "C" { +#endif + +#ifndef LZ4_H_2983827168210 +#define LZ4_H_2983827168210 + +/* --- Dependency --- */ +#include /* size_t */ + + +/** + Introduction + + LZ4 is lossless compression algorithm, providing compression speed at 400 MB/s per core, + scalable with multi-cores CPU. It features an extremely fast decoder, with speed in + multiple GB/s per core, typically reaching RAM speed limits on multi-core systems. + + The LZ4 compression library provides in-memory compression and decompression functions. + Compression can be done in: + - a single step (described as Simple Functions) + - a single step, reusing a context (described in Advanced Functions) + - unbounded multiple steps (described as Streaming compression) + + lz4.h provides block compression functions. It gives full buffer control to user. + Decompressing an lz4-compressed block also requires metadata (such as compressed size). + Each application is free to encode such metadata in whichever way it wants. + + An additional format, called LZ4 frame specification (doc/lz4_Frame_format.md), + take care of encoding standard metadata alongside LZ4-compressed blocks. + If your application requires interoperability, it's recommended to use it. + A library is provided to take care of it, see lz4frame.h. +*/ + +/*^*************************************************************** +* Export parameters +*****************************************************************/ +/* +* LZ4_DLL_EXPORT : +* Enable exporting of functions when building a Windows DLL +* LZ4LIB_VISIBILITY : +* Control library symbols visibility. +*/ +#ifndef LZ4LIB_VISIBILITY +# if defined(__GNUC__) && (__GNUC__ >= 4) +# define LZ4LIB_VISIBILITY __attribute__ ((visibility ("default"))) +# else +# define LZ4LIB_VISIBILITY +# endif +#endif +#if defined(LZ4_DLL_EXPORT) && (LZ4_DLL_EXPORT==1) +# define LZ4LIB_API __declspec(dllexport) LZ4LIB_VISIBILITY +#elif defined(LZ4_DLL_IMPORT) && (LZ4_DLL_IMPORT==1) +# define LZ4LIB_API __declspec(dllimport) LZ4LIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/ +#else +# define LZ4LIB_API LZ4LIB_VISIBILITY +#endif + +/*------ Version ------*/ +#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */ +#define LZ4_VERSION_MINOR 8 /* for new (non-breaking) interface capabilities */ +#define LZ4_VERSION_RELEASE 2 /* for tweaks, bug-fixes, or development */ + +#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE) + +#define LZ4_LIB_VERSION LZ4_VERSION_MAJOR.LZ4_VERSION_MINOR.LZ4_VERSION_RELEASE +#define LZ4_QUOTE(str) #str +#define LZ4_EXPAND_AND_QUOTE(str) LZ4_QUOTE(str) +#define LZ4_VERSION_STRING LZ4_EXPAND_AND_QUOTE(LZ4_LIB_VERSION) + +LZ4LIB_API int LZ4_versionNumber (void); /**< library version number; useful to check dll version */ +LZ4LIB_API const char* LZ4_versionString (void); /**< library version string; unseful to check dll version */ + + +/*-************************************ +* Tuning parameter +**************************************/ +/*! + * LZ4_MEMORY_USAGE : + * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.) + * Increasing memory usage improves compression ratio + * Reduced memory usage may improve speed, thanks to cache effect + * Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache + */ +#ifndef LZ4_MEMORY_USAGE +# define LZ4_MEMORY_USAGE 14 +#endif + +/*-************************************ +* Simple Functions +**************************************/ +/*! LZ4_compress_default() : + Compresses 'srcSize' bytes from buffer 'src' + into already allocated 'dst' buffer of size 'dstCapacity'. + Compression is guaranteed to succeed if 'dstCapacity' >= LZ4_compressBound(srcSize). + It also runs faster, so it's a recommended setting. + If the function cannot compress 'src' into a more limited 'dst' budget, + compression stops *immediately*, and the function result is zero. + Note : as a consequence, 'dst' content is not valid. + Note 2 : This function is protected against buffer overflow scenarios (never writes outside 'dst' buffer, nor read outside 'source' buffer). + srcSize : max supported value is LZ4_MAX_INPUT_SIZE. + dstCapacity : size of buffer 'dst' (which must be already allocated) + return : the number of bytes written into buffer 'dst' (necessarily <= dstCapacity) + or 0 if compression fails */ +LZ4LIB_API int LZ4_compress_default(const char* src, char* dst, int srcSize, int dstCapacity); + +/*! LZ4_decompress_safe() : + compressedSize : is the exact complete size of the compressed block. + dstCapacity : is the size of destination buffer, which must be already allocated. + return : the number of bytes decompressed into destination buffer (necessarily <= dstCapacity) + If destination buffer is not large enough, decoding will stop and output an error code (negative value). + If the source stream is detected malformed, the function will stop decoding and return a negative result. + This function is protected against malicious data packets. +*/ +LZ4LIB_API int LZ4_decompress_safe (const char* src, char* dst, int compressedSize, int dstCapacity); + + +/*-************************************ +* Advanced Functions +**************************************/ +#define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */ +#define LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16) + +/*! +LZ4_compressBound() : + Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible) + This function is primarily useful for memory allocation purposes (destination buffer size). + Macro LZ4_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example). + Note that LZ4_compress_default() compresses faster when dstCapacity is >= LZ4_compressBound(srcSize) + inputSize : max supported value is LZ4_MAX_INPUT_SIZE + return : maximum output size in a "worst case" scenario + or 0, if input size is incorrect (too large or negative) +*/ +LZ4LIB_API int LZ4_compressBound(int inputSize); + +/*! +LZ4_compress_fast() : + Same as LZ4_compress_default(), but allows selection of "acceleration" factor. + The larger the acceleration value, the faster the algorithm, but also the lesser the compression. + It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed. + An acceleration value of "1" is the same as regular LZ4_compress_default() + Values <= 0 will be replaced by ACCELERATION_DEFAULT (currently == 1, see lz4.c). +*/ +LZ4LIB_API int LZ4_compress_fast (const char* src, char* dst, int srcSize, int dstCapacity, int acceleration); + + +/*! +LZ4_compress_fast_extState() : + Same compression function, just using an externally allocated memory space to store compression state. + Use LZ4_sizeofState() to know how much memory must be allocated, + and allocate it on 8-bytes boundaries (using malloc() typically). + Then, provide it as 'void* state' to compression function. +*/ +LZ4LIB_API int LZ4_sizeofState(void); +LZ4LIB_API int LZ4_compress_fast_extState (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration); + + +/*! +LZ4_compress_destSize() : + Reverse the logic : compresses as much data as possible from 'src' buffer + into already allocated buffer 'dst' of size 'targetDestSize'. + This function either compresses the entire 'src' content into 'dst' if it's large enough, + or fill 'dst' buffer completely with as much data as possible from 'src'. + *srcSizePtr : will be modified to indicate how many bytes where read from 'src' to fill 'dst'. + New value is necessarily <= old value. + return : Nb bytes written into 'dst' (necessarily <= targetDestSize) + or 0 if compression fails +*/ +LZ4LIB_API int LZ4_compress_destSize (const char* src, char* dst, int* srcSizePtr, int targetDstSize); + + +/*! +LZ4_decompress_fast() : **unsafe!** +This function is a bit faster than LZ4_decompress_safe(), +but doesn't provide any security guarantee. + originalSize : is the uncompressed size to regenerate + Destination buffer must be already allocated, and its size must be >= 'originalSize' bytes. + return : number of bytes read from source buffer (== compressed size). + If the source stream is detected malformed, the function stops decoding and return a negative result. + note : This function respects memory boundaries for *properly formed* compressed data. + However, it does not provide any protection against malicious input. + It also doesn't know 'src' size, and implies it's >= compressed size. + Use this function in trusted environment **only**. +*/ +LZ4LIB_API int LZ4_decompress_fast (const char* src, char* dst, int originalSize); + +/*! +LZ4_decompress_safe_partial() : + This function decompress a compressed block of size 'srcSize' at position 'src' + into destination buffer 'dst' of size 'dstCapacity'. + The function will decompress a minimum of 'targetOutputSize' bytes, and stop after that. + However, it's not accurate, and may write more than 'targetOutputSize' (but always <= dstCapacity). + @return : the number of bytes decoded in the destination buffer (necessarily <= dstCapacity) + Note : this number can also be < targetOutputSize, if compressed block contains less data. + Therefore, always control how many bytes were decoded. + If source stream is detected malformed, function returns a negative result. + This function is protected against malicious data packets. +*/ +LZ4LIB_API int LZ4_decompress_safe_partial (const char* src, char* dst, int srcSize, int targetOutputSize, int dstCapacity); + + +/*-********************************************* +* Streaming Compression Functions +***********************************************/ +typedef union LZ4_stream_u LZ4_stream_t; /* incomplete type (defined later) */ + +/*! LZ4_createStream() and LZ4_freeStream() : + * LZ4_createStream() will allocate and initialize an `LZ4_stream_t` structure. + * LZ4_freeStream() releases its memory. + */ +LZ4LIB_API LZ4_stream_t* LZ4_createStream(void); +LZ4LIB_API int LZ4_freeStream (LZ4_stream_t* streamPtr); + +/*! LZ4_resetStream() : + * An LZ4_stream_t structure can be allocated once and re-used multiple times. + * Use this function to start compressing a new stream. + */ +LZ4LIB_API void LZ4_resetStream (LZ4_stream_t* streamPtr); + +/*! LZ4_loadDict() : + * Use this function to load a static dictionary into LZ4_stream_t. + * Any previous data will be forgotten, only 'dictionary' will remain in memory. + * Loading a size of 0 is allowed, and is the same as reset. + * @return : dictionary size, in bytes (necessarily <= 64 KB) + */ +LZ4LIB_API int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize); + +/*! LZ4_compress_fast_continue() : + * Compress 'src' content using data from previously compressed blocks, for better compression ratio. + * 'dst' buffer must be already allocated. + * If dstCapacity >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster. + * + * Important : The previous 64KB of compressed data is assumed to remain present and unmodified in memory! + * + * Special 1 : When input is a double-buffer, they can have any size, including < 64 KB. + * Make sure that buffers are separated by at least one byte. + * This way, each block only depends on previous block. + * Special 2 : If input buffer is a ring-buffer, it can have any size, including < 64 KB. + * + * @return : size of compressed block + * or 0 if there is an error (typically, cannot fit into 'dst'). + * After an error, the stream status is invalid, it can only be reset or freed. + */ +LZ4LIB_API int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration); + +/*! LZ4_saveDict() : + * If last 64KB data cannot be guaranteed to remain available at its current memory location, + * save it into a safer place (char* safeBuffer). + * This is schematically equivalent to a memcpy() followed by LZ4_loadDict(), + * but is much faster, because LZ4_saveDict() doesn't need to rebuild tables. + * @return : saved dictionary size in bytes (necessarily <= maxDictSize), or 0 if error. + */ +LZ4LIB_API int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int maxDictSize); + + +/*-********************************************** +* Streaming Decompression Functions +* Bufferless synchronous API +************************************************/ +typedef union LZ4_streamDecode_u LZ4_streamDecode_t; /* incomplete type (defined later) */ + +/*! LZ4_createStreamDecode() and LZ4_freeStreamDecode() : + * creation / destruction of streaming decompression tracking structure. + * A tracking structure can be re-used multiple times sequentially. */ +LZ4LIB_API LZ4_streamDecode_t* LZ4_createStreamDecode(void); +LZ4LIB_API int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream); + +/*! LZ4_setStreamDecode() : + * An LZ4_streamDecode_t structure can be allocated once and re-used multiple times. + * Use this function to start decompression of a new stream of blocks. + * A dictionary can optionnally be set. Use NULL or size 0 for a reset order. + * @return : 1 if OK, 0 if error + */ +LZ4LIB_API int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize); + +/*! LZ4_decompress_*_continue() : + * These decoding functions allow decompression of consecutive blocks in "streaming" mode. + * A block is an unsplittable entity, it must be presented entirely to a decompression function. + * Decompression functions only accept one block at a time. + * The last 64KB of previously decoded data *must* remain available and unmodified at the memory position where they were decoded. + * If less than 64KB of data has been decoded all the data must be present. + * + * Special : if application sets a ring buffer for decompression, it must respect one of the following conditions : + * - Exactly same size as encoding buffer, with same update rule (block boundaries at same positions) + * In which case, the decoding & encoding ring buffer can have any size, including very small ones ( < 64 KB). + * - Larger than encoding buffer, by a minimum of maxBlockSize more bytes. + * maxBlockSize is implementation dependent. It's the maximum size of any single block. + * In which case, encoding and decoding buffers do not need to be synchronized, + * and encoding ring buffer can have any size, including small ones ( < 64 KB). + * - _At least_ 64 KB + 8 bytes + maxBlockSize. + * In which case, encoding and decoding buffers do not need to be synchronized, + * and encoding ring buffer can have any size, including larger than decoding buffer. + * Whenever these conditions are not possible, save the last 64KB of decoded data into a safe buffer, + * and indicate where it is saved using LZ4_setStreamDecode() before decompressing next block. +*/ +LZ4LIB_API int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* src, char* dst, int srcSize, int dstCapacity); +LZ4LIB_API int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* src, char* dst, int originalSize); + + +/*! LZ4_decompress_*_usingDict() : + * These decoding functions work the same as + * a combination of LZ4_setStreamDecode() followed by LZ4_decompress_*_continue() + * They are stand-alone, and don't need an LZ4_streamDecode_t structure. + */ +LZ4LIB_API int LZ4_decompress_safe_usingDict (const char* src, char* dst, int srcSize, int dstCapcity, const char* dictStart, int dictSize); +LZ4LIB_API int LZ4_decompress_fast_usingDict (const char* src, char* dst, int originalSize, const char* dictStart, int dictSize); + + +/*^********************************************** + * !!!!!! STATIC LINKING ONLY !!!!!! + ***********************************************/ + +/*-************************************ + * Unstable declarations + ************************************** + * Declarations in this section should be considered unstable. + * Use at your own peril, etc., etc. + * They may be removed in the future. + * Their signatures may change. + **************************************/ + +#ifdef LZ4_STATIC_LINKING_ONLY + +/*! LZ4_resetStream_fast() : + * When an LZ4_stream_t is known to be in a internally coherent state, + * it can often be prepared for a new compression with almost no work, only + * sometimes falling back to the full, expensive reset that is always required + * when the stream is in an indeterminate state (i.e., the reset performed by + * LZ4_resetStream()). + * + * LZ4_streams are guaranteed to be in a valid state when: + * - returned from LZ4_createStream() + * - reset by LZ4_resetStream() + * - memset(stream, 0, sizeof(LZ4_stream_t)) + * - the stream was in a valid state and was reset by LZ4_resetStream_fast() + * - the stream was in a valid state and was then used in any compression call + * that returned success + * - the stream was in an indeterminate state and was used in a compression + * call that fully reset the state (LZ4_compress_fast_extState()) and that + * returned success + */ +LZ4LIB_API void LZ4_resetStream_fast (LZ4_stream_t* streamPtr); + +/*! LZ4_compress_fast_extState_fastReset() : + * A variant of LZ4_compress_fast_extState(). + * + * Using this variant avoids an expensive initialization step. It is only safe + * to call if the state buffer is known to be correctly initialized already + * (see above comment on LZ4_resetStream_fast() for a definition of "correctly + * initialized"). From a high level, the difference is that this function + * initializes the provided state with a call to LZ4_resetStream_fast() while + * LZ4_compress_fast_extState() starts with a call to LZ4_resetStream(). + */ +LZ4LIB_API int LZ4_compress_fast_extState_fastReset (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration); + +/*! LZ4_attach_dictionary() : + * This is an experimental API that allows for the efficient use of a + * static dictionary many times. + * + * Rather than re-loading the dictionary buffer into a working context before + * each compression, or copying a pre-loaded dictionary's LZ4_stream_t into a + * working LZ4_stream_t, this function introduces a no-copy setup mechanism, + * in which the working stream references the dictionary stream in-place. + * + * Several assumptions are made about the state of the dictionary stream. + * Currently, only streams which have been prepared by LZ4_loadDict() should + * be expected to work. + * + * Alternatively, the provided dictionary stream pointer may be NULL, in which + * case any existing dictionary stream is unset. + * + * If a dictionary is provided, it replaces any pre-existing stream history. + * The dictionary contents are the only history that can be referenced and + * logically immediately precede the data compressed in the first subsequent + * compression call. + * + * The dictionary will only remain attached to the working stream through the + * first compression call, at the end of which it is cleared. The dictionary + * stream (and source buffer) must remain in-place / accessible / unchanged + * through the completion of the first compression call on the stream. + */ +LZ4LIB_API void LZ4_attach_dictionary(LZ4_stream_t *working_stream, const LZ4_stream_t *dictionary_stream); + +#endif + +/*-************************************ + * Private definitions + ************************************** + * Do not use these definitions. + * They are exposed to allow static allocation of `LZ4_stream_t` and `LZ4_streamDecode_t`. + * Using these definitions will expose code to API and/or ABI break in future versions of the library. + **************************************/ +#define LZ4_HASHLOG (LZ4_MEMORY_USAGE-2) +#define LZ4_HASHTABLESIZE (1 << LZ4_MEMORY_USAGE) +#define LZ4_HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */ + +#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) +#include + +typedef struct LZ4_stream_t_internal LZ4_stream_t_internal; +struct LZ4_stream_t_internal { + uint32_t hashTable[LZ4_HASH_SIZE_U32]; + uint32_t currentOffset; + uint16_t initCheck; + uint16_t tableType; + const uint8_t* dictionary; + const LZ4_stream_t_internal* dictCtx; + uint32_t dictSize; +}; + +typedef struct { + const uint8_t* externalDict; + size_t extDictSize; + const uint8_t* prefixEnd; + size_t prefixSize; +} LZ4_streamDecode_t_internal; + +#else + +typedef struct LZ4_stream_t_internal LZ4_stream_t_internal; +struct LZ4_stream_t_internal { + unsigned int hashTable[LZ4_HASH_SIZE_U32]; + unsigned int currentOffset; + unsigned short initCheck; + unsigned short tableType; + const unsigned char* dictionary; + const LZ4_stream_t_internal* dictCtx; + unsigned int dictSize; +}; + +typedef struct { + const unsigned char* externalDict; + size_t extDictSize; + const unsigned char* prefixEnd; + size_t prefixSize; +} LZ4_streamDecode_t_internal; + +#endif + +/*! + * LZ4_stream_t : + * information structure to track an LZ4 stream. + * init this structure before first use. + * note : only use in association with static linking ! + * this definition is not API/ABI safe, + * it may change in a future version ! + */ +#define LZ4_STREAMSIZE_U64 ((1 << (LZ4_MEMORY_USAGE-3)) + 4) +#define LZ4_STREAMSIZE (LZ4_STREAMSIZE_U64 * sizeof(unsigned long long)) +union LZ4_stream_u { + unsigned long long table[LZ4_STREAMSIZE_U64]; + LZ4_stream_t_internal internal_donotuse; +} ; /* previously typedef'd to LZ4_stream_t */ + + +/*! + * LZ4_streamDecode_t : + * information structure to track an LZ4 stream during decompression. + * init this structure using LZ4_setStreamDecode (or memset()) before first use + * note : only use in association with static linking ! + * this definition is not API/ABI safe, + * and may change in a future version ! + */ +#define LZ4_STREAMDECODESIZE_U64 4 +#define LZ4_STREAMDECODESIZE (LZ4_STREAMDECODESIZE_U64 * sizeof(unsigned long long)) +union LZ4_streamDecode_u { + unsigned long long table[LZ4_STREAMDECODESIZE_U64]; + LZ4_streamDecode_t_internal internal_donotuse; +} ; /* previously typedef'd to LZ4_streamDecode_t */ + + +/*-************************************ +* Obsolete Functions +**************************************/ + +/*! Deprecation warnings + Should deprecation warnings be a problem, + it is generally possible to disable them, + typically with -Wno-deprecated-declarations for gcc + or _CRT_SECURE_NO_WARNINGS in Visual. + Otherwise, it's also possible to define LZ4_DISABLE_DEPRECATE_WARNINGS */ +#ifdef LZ4_DISABLE_DEPRECATE_WARNINGS +# define LZ4_DEPRECATED(message) /* disable deprecation warnings */ +#else +# define LZ4_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) +# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */ +# define LZ4_DEPRECATED(message) [[deprecated(message)]] +# elif (LZ4_GCC_VERSION >= 405) || defined(__clang__) +# define LZ4_DEPRECATED(message) __attribute__((deprecated(message))) +# elif (LZ4_GCC_VERSION >= 301) +# define LZ4_DEPRECATED(message) __attribute__((deprecated)) +# elif defined(_MSC_VER) +# define LZ4_DEPRECATED(message) __declspec(deprecated(message)) +# else +# pragma message("WARNING: You need to implement LZ4_DEPRECATED for this compiler") +# define LZ4_DEPRECATED(message) +# endif +#endif /* LZ4_DISABLE_DEPRECATE_WARNINGS */ + +/* Obsolete compression functions */ +LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress (const char* source, char* dest, int sourceSize); +LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress_limitedOutput (const char* source, char* dest, int sourceSize, int maxOutputSize); +LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize); +LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize); +LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize); +LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize); + +/* Obsolete decompression functions */ +LZ4_DEPRECATED("use LZ4_decompress_fast() instead") LZ4LIB_API int LZ4_uncompress (const char* source, char* dest, int outputSize); +LZ4_DEPRECATED("use LZ4_decompress_safe() instead") LZ4LIB_API int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize); + +/* Obsolete streaming functions; degraded functionality; do not use! + * + * In order to perform streaming compression, these functions depended on data + * that is no longer tracked in the state. They have been preserved as well as + * possible: using them will still produce a correct output. However, they don't + * actually retain any history between compression calls. The compression ratio + * achieved will therefore be no better than compressing each chunk + * independently. + */ +LZ4_DEPRECATED("Use LZ4_createStream() instead") LZ4LIB_API void* LZ4_create (char* inputBuffer); +LZ4_DEPRECATED("Use LZ4_createStream() instead") LZ4LIB_API int LZ4_sizeofStreamState(void); +LZ4_DEPRECATED("Use LZ4_resetStream() instead") LZ4LIB_API int LZ4_resetStreamState(void* state, char* inputBuffer); +LZ4_DEPRECATED("Use LZ4_saveDict() instead") LZ4LIB_API char* LZ4_slideInputBuffer (void* state); + +/* Obsolete streaming decoding functions */ +LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead") LZ4LIB_API int LZ4_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize); +LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") LZ4LIB_API int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize); + +#endif /* LZ4_H_2983827168210 */ + + +#if defined (__cplusplus) +} +#endif diff --git a/bdk/libs/fatfs/diskio.h b/bdk/libs/fatfs/diskio.h index 977124c..6959fb4 100644 --- a/bdk/libs/fatfs/diskio.h +++ b/bdk/libs/fatfs/diskio.h @@ -40,6 +40,7 @@ DSTATUS disk_status (BYTE pdrv); DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count); DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count); DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); +DRESULT disk_set_info (BYTE pdrv, BYTE cmd, void *buff); /* Disk Status Bits (DSTATUS) */ @@ -54,6 +55,7 @@ DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); /* Generic command (Used by FatFs) */ #define CTRL_SYNC 0 /* Complete pending write process (needed at FF_FS_READONLY == 0) */ #define GET_SECTOR_COUNT 1 /* Get media size (needed at FF_USE_MKFS == 1) */ +#define SET_SECTOR_COUNT 1 /* Set media size (needed at FF_USE_MKFS == 1) */ #define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */ #define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */ #define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */ diff --git a/bdk/libs/fatfs/ff.c b/bdk/libs/fatfs/ff.c index 7217103..9035f35 100644 --- a/bdk/libs/fatfs/ff.c +++ b/bdk/libs/fatfs/ff.c @@ -38,8 +38,10 @@ #include "ff.h" /* Declarations of FatFs API */ #include "diskio.h" /* Declarations of device I/O functions */ +#include -#define EFSPRINTF(text, ...) +#define EFSPRINTF(text, ...) print_error(); gfx_printf("%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF); +//#define EFSPRINTF(...) /*-------------------------------------------------------------------------- @@ -530,7 +532,7 @@ static WCHAR LfnBuf[FF_MAX_LFN + 1]; /* LFN working buffer */ #define FREE_NAMBUF() ff_memfree(lfn) #endif #define LEAVE_MKFS(res) { if (!work) ff_memfree(buf); return res; } -#define MAX_MALLOC 0x4000 /* Must be >=FF_MAX_SS */ +#define MAX_MALLOC 0x8000 /* Must be >=FF_MAX_SS */ #else #error Wrong setting of FF_USE_LFN @@ -590,6 +592,16 @@ static const BYTE DbcTbl[] = MKCVTBL(TBL_DC, FF_CODE_PAGE); ---------------------------------------------------------------------------*/ +/*-----------------------------------------------------------------------*/ +/* Print error header */ +/*-----------------------------------------------------------------------*/ + +void print_error() +{ + gfx_printf("\n\n\n%k[FatFS] Error: %k", 0xFFFFFF00, 0xFFFFFFFF); +} + + /*-----------------------------------------------------------------------*/ /* Load/Store multi-byte word in the FAT structure */ /*-----------------------------------------------------------------------*/ @@ -3894,11 +3906,11 @@ FRESULT f_read ( -#ifdef FF_FASTFS +#if FF_FASTFS && FF_USE_FASTSEEK /*-----------------------------------------------------------------------*/ /* Fast Read Aligned Sized File Without a Cache */ /*-----------------------------------------------------------------------*/ -#if FF_USE_FASTSEEK + FRESULT f_read_fast ( FIL* fp, /* Pointer to the file object */ const void* buff, /* Pointer to the data to be written */ @@ -3909,12 +3921,13 @@ FRESULT f_read_fast ( FATFS *fs; UINT csize_bytes; DWORD clst; - DWORD wbytes; - UINT count; + UINT count = 0; FSIZE_t work_sector = 0; FSIZE_t sector_base = 0; BYTE *wbuff = (BYTE*)buff; + // TODO support sector reading inside a cluster + res = validate(&fp->obj, &fs); /* Check validity of the file object */ if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) { EFSPRINTF("FOV"); @@ -3926,17 +3939,6 @@ FRESULT f_read_fast ( if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ csize_bytes = fs->csize * SS(fs); - DWORD csect = (UINT)((fp->fptr / SS(fs)) & (fs->csize - 1)); /* Sector offset in the cluster */ - - /* If inside a cluster, read the sectors and align to cluster. */ - if (csect) { - wbytes = MIN(btr, (fs->csize - csect) * SS(fs)); - f_read(fp, wbuff, wbytes, (void *)0); - wbuff += wbytes; - btr -= wbytes; - if (!btr) - goto out; - } if (!fp->fptr) { /* On the top of the file? */ clst = fp->obj.sclust; /* Follow from the origin */ @@ -3944,22 +3946,15 @@ FRESULT f_read_fast ( if (fp->cltbl) clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ else { EFSPRINTF("CLTBL"); ABORT(fs, FR_CLTBL_NO_INIT); } } - if (clst < 2) { EFSPRINTF("CCHK"); ABORT(fs, FR_INT_ERR); } else if (clst == 0xFFFFFFFF) { EFSPRINTF("DSKC"); ABORT(fs, FR_DISK_ERR); } fp->clust = clst; /* Set working cluster */ - wbytes = MIN(btr, csize_bytes); sector_base = clst2sect(fs, fp->clust); - count = wbytes / SS(fs); - fp->fptr += wbytes; - btr -= wbytes; - - if (!btr) { /* Final cluster/sectors read. */ - if (disk_read(fs->pdrv, wbuff, sector_base, count) != RES_OK) ABORT(fs, FR_DISK_ERR); - goto out; - } + count += fs->csize; + btr -= csize_bytes; + fp->fptr += csize_bytes; while (btr) { clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ @@ -3970,29 +3965,29 @@ FRESULT f_read_fast ( fp->clust = clst; work_sector = clst2sect(fs, fp->clust); - wbytes = MIN(btr, csize_bytes); - if ((work_sector - sector_base) == count) count += wbytes / SS(fs); + if ((work_sector - sector_base) == count) count += fs->csize; else { if (disk_read(fs->pdrv, wbuff, sector_base, count) != RES_OK) ABORT(fs, FR_DISK_ERR); wbuff += count * SS(fs); sector_base = work_sector; - count = wbytes / SS(fs); + count = fs->csize; } - fp->fptr += wbytes; - btr -= wbytes; + fp->fptr += MIN(btr, csize_bytes); + btr -= MIN(btr, csize_bytes); + + // TODO: what about if data is smaller than cluster? + // Must read-write back that cluster. if (!btr) { /* Final cluster/sectors read. */ if (disk_read(fs->pdrv, wbuff, sector_base, count) != RES_OK) ABORT(fs, FR_DISK_ERR); } } -out: LEAVE_FF(fs, FR_OK); } #endif -#endif @@ -4136,11 +4131,11 @@ FRESULT f_write ( -#ifdef FF_FASTFS +#if FF_FASTFS && FF_USE_FASTSEEK /*-----------------------------------------------------------------------*/ /* Fast Write Aligned Sized File Without a Cache */ /*-----------------------------------------------------------------------*/ -#if FF_USE_FASTSEEK + FRESULT f_write_fast ( FIL* fp, /* Pointer to the file object */ const void* buff, /* Pointer to the data to be written */ @@ -4151,11 +4146,12 @@ FRESULT f_write_fast ( FATFS *fs; UINT csize_bytes; DWORD clst; - DWORD wbytes; - UINT count; + UINT count = 0; FSIZE_t work_sector = 0; FSIZE_t sector_base = 0; - BYTE *wbuff = (BYTE*)buff; + const BYTE *wbuff = (const BYTE*)buff; + + // TODO support sector writing inside a cluster res = validate(&fp->obj, &fs); /* Check validity of the file object */ if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) { @@ -4170,19 +4166,6 @@ FRESULT f_write_fast ( } csize_bytes = fs->csize * SS(fs); - DWORD csect = (UINT)((fp->fptr / SS(fs)) & (fs->csize - 1)); /* Sector offset in the cluster */ - - /* If inside a cluster, write the sectors and align to cluster. */ - if (csect) { - wbytes = MIN(btw, (fs->csize - csect) * SS(fs)); - f_write(fp, wbuff, wbytes, (void *)0); - /* Ensure flushing of it. FatFS is not notified for next write if raw. */ - f_sync(fp); - wbuff += wbytes; - btw -= wbytes; - if (!btw) - goto out; - } if (!fp->fptr) { /* On the top of the file? */ clst = fp->obj.sclust; /* Follow from the origin */ @@ -4192,57 +4175,49 @@ FRESULT f_write_fast ( } if (clst < 2) { EFSPRINTF("CCHK"); ABORT(fs, FR_INT_ERR); } - else if (clst == 0xFFFFFFFF) { EFSPRINTF("DSKC"); ABORT(fs, FR_DISK_ERR); } + else if (clst == 0xFFFFFFFF) { EFSPRINTF("DERR"); ABORT(fs, FR_DISK_ERR); } fp->clust = clst; /* Set working cluster */ - wbytes = MIN(btw, csize_bytes); sector_base = clst2sect(fs, fp->clust); - count = wbytes / SS(fs); - fp->fptr += wbytes; - btw -= wbytes; - - if (!btw) { /* Final cluster/sectors write. */ - if (disk_write(fs->pdrv, wbuff, sector_base, count) != RES_OK) ABORT(fs, FR_DISK_ERR); - fp->flag &= (BYTE)~FA_DIRTY; - goto out; - } + count += fs->csize; + btw -= csize_bytes; + fp->fptr += csize_bytes; while (btw) { clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ if (clst < 2) { EFSPRINTF("CCHK2"); ABORT(fs, FR_INT_ERR); } - else if (clst == 0xFFFFFFFF) { EFSPRINTF("DSKC"); ABORT(fs, FR_DISK_ERR); } + else if (clst == 0xFFFFFFFF) { EFSPRINTF("DERR"); ABORT(fs, FR_DISK_ERR); } fp->clust = clst; work_sector = clst2sect(fs, fp->clust); - wbytes = MIN(btw, csize_bytes); - if ((work_sector - sector_base) == count) count += wbytes / SS(fs); + if ((work_sector - sector_base) == count) count += fs->csize; else { if (disk_write(fs->pdrv, wbuff, sector_base, count) != RES_OK) ABORT(fs, FR_DISK_ERR); wbuff += count * SS(fs); sector_base = work_sector; - count = wbytes / SS(fs); + count = fs->csize; } - fp->fptr += wbytes; - btw -= wbytes; + fp->fptr += MIN(btw, csize_bytes); + btw -= MIN(btw, csize_bytes); + // what about if data is smaller than cluster? + // Probably must read-write back that cluster. if (!btw) { /* Final cluster/sectors write. */ if (disk_write(fs->pdrv, wbuff, sector_base, count) != RES_OK) ABORT(fs, FR_DISK_ERR); fp->flag &= (BYTE)~FA_DIRTY; } } -out: fp->flag |= FA_MODIFIED; /* Set file change flag */ LEAVE_FF(fs, FR_OK); } #endif -#endif @@ -4703,8 +4678,7 @@ FRESULT f_lseek ( -#ifdef FF_FASTFS -#if FF_USE_FASTSEEK +#if FF_FASTFS && FF_USE_FASTSEEK /*-----------------------------------------------------------------------*/ /* Seek File Read/Write Pointer */ /*-----------------------------------------------------------------------*/ @@ -4712,24 +4686,25 @@ FRESULT f_lseek ( DWORD *f_expand_cltbl ( FIL* fp, /* Pointer to the file object */ UINT tblsz, /* Size of table */ - DWORD *tbl, /* Table pointer */ FSIZE_t ofs /* File pointer from top of file */ ) { if (fp->flag & FA_WRITE) f_lseek(fp, ofs); /* Expand file if write is enabled */ - fp->cltbl = (DWORD *)tbl; - fp->cltbl[0] = tblsz; + if (!fp->cltbl) { /* Allocate memory for cluster link table */ + fp->cltbl = (DWORD *)ff_memalloc(tblsz); + fp->cltbl[0] = tblsz; + } if (f_lseek(fp, CREATE_LINKMAP)) { /* Create cluster link table */ - fp->cltbl = (void *)0; + ff_memfree(fp->cltbl); + fp->cltbl = NULL; EFSPRINTF("CLTBLSZ"); - return (void *)0; + return NULL; } f_lseek(fp, 0); return fp->cltbl; } #endif -#endif @@ -5863,7 +5838,7 @@ FRESULT f_mkfs ( UINT len /* Size of working buffer [byte] */ ) { - const UINT n_fats = 1; /* Number of FATs for FAT/FAT32 volume (1 or 2) */ + const UINT n_fats = 2; /* Number of FATs for FAT/FAT32 volume (1 or 2) */ const UINT n_rootdir = 512; /* Number of root directory entries for FAT volume */ static const WORD cst[] = {1, 4, 16, 64, 256, 512, 0}; /* Cluster size boundary for FAT volume (4Ks unit) */ static const WORD cst32[] = {1, 2, 4, 8, 16, 32, 0}; /* Cluster size boundary for FAT32 volume (128Ks unit) */ @@ -5927,7 +5902,7 @@ FRESULT f_mkfs ( } else { /* Create a single-partition in this function */ if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_vol) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); - b_vol = (opt & FM_SFD) ? 0 : 63; /* Volume start sector */ + b_vol = (opt & FM_SFD) ? 0 : 32768; /* Volume start sector. Align to 16MB */ if (sz_vol < b_vol) LEAVE_MKFS(FR_MKFS_ABORTED); sz_vol -= b_vol; /* Volume size */ } @@ -6151,6 +6126,9 @@ FRESULT f_mkfs ( if (fmt == FS_FAT32) { /* FAT32: Move FAT base */ sz_rsv += n; b_fat += n; } else { /* FAT: Expand FAT size */ + if (n % n_fats) { /* Adjust fractional error if needed */ + n--; sz_rsv++; b_fat++; + } sz_fat += n / n_fats; } @@ -6214,13 +6192,13 @@ FRESULT f_mkfs ( st_word(buf + BPB_BkBootSec32, 6); /* Offset of backup VBR (VBR + 6) */ buf[BS_DrvNum32] = 0x80; /* Drive number (for int13) */ buf[BS_BootSig32] = 0x29; /* Extended boot signature */ - mem_cpy(buf + BS_VolLab32, "NO NAME " "FAT32 ", 19); /* Volume label, FAT signature */ + mem_cpy(buf + BS_VolLab32, "SWITCH SD " "FAT32 ", 19); /* Volume label, FAT signature */ } else { st_dword(buf + BS_VolID, GET_FATTIME()); /* VSN */ st_word(buf + BPB_FATSz16, (WORD)sz_fat); /* FAT size [sector] */ buf[BS_DrvNum] = 0x80; /* Drive number (for int13) */ buf[BS_BootSig] = 0x29; /* Extended boot signature */ - mem_cpy(buf + BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */ + mem_cpy(buf + BS_VolLab, "SWITCH SD " "FAT ", 19); /* Volume label, FAT signature */ } st_word(buf + BS_55AA, 0xAA55); /* Signature (offset is fixed here regardless of sector size) */ if (disk_write(pdrv, buf, b_vol, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it to the VBR sector */ diff --git a/bdk/libs/fatfs/ff.h b/bdk/libs/fatfs/ff.h index 368ad9d..a83cf63 100644 --- a/bdk/libs/fatfs/ff.h +++ b/bdk/libs/fatfs/ff.h @@ -263,10 +263,8 @@ FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a f FRESULT f_close (FIL* fp); /* Close an open file object */ FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from the file */ FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to the file */ -#ifdef FF_FASTFS FRESULT f_read_fast (FIL* fp, const void* buff, UINT btr); /* Fast read data from the file */ FRESULT f_write_fast (FIL* fp, const void* buff, UINT btw); /* Fast write data to the file */ -#endif FRESULT f_lseek (FIL* fp, FSIZE_t ofs); /* Move file pointer of the file object */ FRESULT f_truncate (FIL* fp); /* Truncate the file */ FRESULT f_sync (FIL* fp); /* Flush cached data of the writing file */ @@ -288,9 +286,7 @@ FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get numbe FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */ FRESULT f_setlabel (const TCHAR* label); /* Set volume label */ FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */ -#ifdef FF_FASTFS -DWORD *f_expand_cltbl (FIL* fp, UINT tblsz, DWORD *tbl, FSIZE_t ofs); /* Expand file and populate cluster table */ -#endif +DWORD *f_expand_cltbl (FIL* fp, UINT tblsz, FSIZE_t ofs); /* Expand file and populate cluster table */ FRESULT f_expand (FIL* fp, FSIZE_t fsz, BYTE opt); /* Allocate a contiguous block to the file */ FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */ FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */ diff --git a/bdk/libs/lv_conf.h b/bdk/libs/lv_conf.h index ab7f311..dcc437d 100644 --- a/bdk/libs/lv_conf.h +++ b/bdk/libs/lv_conf.h @@ -155,7 +155,11 @@ /*Log settings*/ -#define USE_LV_LOG 0 /*Enable/disable the log module*/ +#ifdef DEBUG_UART_PORT +# define USE_LV_LOG 1 /*Enable/disable the log module*/ +#else +# define USE_LV_LOG 0 /*Enable/disable the log module*/ +#endif #if USE_LV_LOG /* How important log should be added: * LV_LOG_LEVEL_TRACE A lot of logs to give detailed information diff --git a/bdk/libs/lvgl/lv_misc/lv_log.c b/bdk/libs/lvgl/lv_misc/lv_log.c index bd59cf3..d2db0c7 100644 --- a/bdk/libs/lvgl/lv_misc/lv_log.c +++ b/bdk/libs/lvgl/lv_misc/lv_log.c @@ -67,7 +67,7 @@ void lv_log_add(lv_log_level_t level, const char * file, int line, const char * static const char * lvl_prefix[] = {"Trace", "Info", "Warn", "Error"}; char *log = (char *)malloc(0x1000); s_printf(log, "%s: %s \t(%s #%d)\r\n", lvl_prefix[level], dsc, file, line); - uart_send(UART_B, (u8 *)log, strlen(log) + 1); + uart_send(DEBUG_UART_PORT, (u8 *)log, strlen(log) + 1); //gfx_printf("%s: %s \t(%s #%d)\n", lvl_prefix[level], dsc, file, line); #else if(print_cb) print_cb(level, file, line, dsc); diff --git a/bdk/libs/nx_savedata/allocation_table_storage.c b/bdk/libs/nx_savedata/allocation_table_storage.c index 43cea04..97b2dfb 100644 --- a/bdk/libs/nx_savedata/allocation_table_storage.c +++ b/bdk/libs/nx_savedata/allocation_table_storage.c @@ -38,12 +38,21 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include -void save_allocation_table_storage_init(allocation_table_storage_ctx_t *ctx, substorage *data, allocation_table_ctx_t *table, uint32_t block_size, uint32_t initial_block) { +bool save_allocation_table_storage_init(allocation_table_storage_ctx_t *ctx, substorage *data, allocation_table_ctx_t *table, uint32_t block_size, uint32_t initial_block) { ctx->base_storage = data; ctx->block_size = block_size; ctx->fat = table; ctx->initial_block = initial_block; - ctx->_length = initial_block == 0xFFFFFFFF ? 0 : save_allocation_table_get_list_length(table, initial_block) * block_size; + ctx->_length = 0; + if (initial_block != 0xFFFFFFFF) { + uint32_t list_length = save_allocation_table_get_list_length(table, initial_block); + if (list_length == 0) { + EPRINTF("Allocation table storage init failed!"); + return false; + }; + ctx->_length = list_length * block_size; + } + return true; } uint32_t save_allocation_table_storage_read(allocation_table_storage_ctx_t *ctx, void *buffer, uint64_t offset, uint64_t count) { diff --git a/bdk/libs/nx_savedata/allocation_table_storage.h b/bdk/libs/nx_savedata/allocation_table_storage.h index 86f55cf..6e8d30c 100644 --- a/bdk/libs/nx_savedata/allocation_table_storage.h +++ b/bdk/libs/nx_savedata/allocation_table_storage.h @@ -52,7 +52,7 @@ static ALWAYS_INLINE void save_allocation_table_storage_get_size(allocation_tabl *out_size = ctx->_length; } -void save_allocation_table_storage_init(allocation_table_storage_ctx_t *ctx, substorage *data, allocation_table_ctx_t *table, uint32_t block_size, uint32_t initial_block); +bool save_allocation_table_storage_init(allocation_table_storage_ctx_t *ctx, substorage *data, allocation_table_ctx_t *table, uint32_t block_size, uint32_t initial_block); uint32_t save_allocation_table_storage_read(allocation_table_storage_ctx_t *ctx, void *buffer, uint64_t offset, uint64_t count); uint32_t save_allocation_table_storage_write(allocation_table_storage_ctx_t *ctx, const void *buffer, uint64_t offset, uint64_t count); bool save_allocation_table_storage_set_size(allocation_table_storage_ctx_t *ctx, uint64_t size); diff --git a/bdk/libs/nx_savedata/cached_storage.c b/bdk/libs/nx_savedata/cached_storage.c index 52d38a3..78528a3 100644 --- a/bdk/libs/nx_savedata/cached_storage.c +++ b/bdk/libs/nx_savedata/cached_storage.c @@ -49,7 +49,7 @@ static ALWAYS_INLINE cache_block_t *cache_block_init(cached_storage_ctx_t *ctx) void save_cached_storage_init(cached_storage_ctx_t *ctx, substorage *base_storage, uint32_t block_size, uint32_t cache_size) { memcpy(&ctx->base_storage, base_storage, sizeof(substorage)); ctx->block_size = block_size; - substorage_get_size(base_storage, &ctx->length); + ctx->length = base_storage->length; ctx->cache_size = cache_size; list_init(&ctx->blocks); @@ -69,6 +69,8 @@ static void cache_block_finalize(cache_block_t **block) { } void save_cached_storage_finalize(cached_storage_ctx_t *ctx) { + if (!ctx->blocks.next) + return; LIST_FOREACH_SAFE(curr_block, &ctx->blocks) { cache_block_t *block = CONTAINER_OF(curr_block, cache_block_t, link) ; cache_block_finalize(&block); @@ -76,6 +78,8 @@ void save_cached_storage_finalize(cached_storage_ctx_t *ctx) { } static bool try_get_block_by_value(cached_storage_ctx_t *ctx, uint64_t index, cache_block_t **out_block) { + if (!ctx->blocks.next) + return false; LIST_FOREACH_ENTRY(cache_block_t, block, &ctx->blocks, link) { if (block->index == index) { *out_block = block; diff --git a/bdk/libs/nx_savedata/hierarchical_integrity_verification_storage.c b/bdk/libs/nx_savedata/hierarchical_integrity_verification_storage.c index 4d8153b..d244571 100644 --- a/bdk/libs/nx_savedata/hierarchical_integrity_verification_storage.c +++ b/bdk/libs/nx_savedata/hierarchical_integrity_verification_storage.c @@ -135,7 +135,7 @@ validity_t save_hierarchical_integrity_verification_storage_validate(hierarchica validity_t result = VALIDITY_VALID; integrity_verification_storage_ctx_t *storage = &ctx->integrity_storages[3]; - uint64_t block_size = storage->base_storage.sector_size; + uint32_t block_size = storage->base_storage.sector_size; uint32_t block_count = (uint32_t)(DIV_ROUND_UP(ctx->length, block_size)); uint8_t *buffer = malloc(block_size); @@ -143,7 +143,7 @@ validity_t save_hierarchical_integrity_verification_storage_validate(hierarchica for (unsigned int i = 0; i < block_count; i++) { if (ctx->level_validities[3][i] == VALIDITY_UNCHECKED) { uint64_t storage_size = storage->base_storage.length; - uint32_t to_read = MIN((uint32_t)(storage_size - block_size * i), (uint32_t)block_size); + uint32_t to_read = MIN((uint32_t)(storage_size - block_size * i), block_size); substorage_read(&ctx->data_level->base_storage, buffer, block_size * i, to_read); } if (ctx->level_validities[3][i] == VALIDITY_INVALID) { diff --git a/bdk/libs/nx_savedata/hierarchical_save_file_table.c b/bdk/libs/nx_savedata/hierarchical_save_file_table.c index 0ae9126..0aae473 100644 --- a/bdk/libs/nx_savedata/hierarchical_save_file_table.c +++ b/bdk/libs/nx_savedata/hierarchical_save_file_table.c @@ -207,7 +207,7 @@ void save_hierarchical_file_table_unlink_file_from_parent(hierarchical_save_file return; } prev_index = cur_index; - memcpy(&prev_entry, &cur_entry, sizeof(prev_entry)); + memcpy(&prev_entry, &cur_entry, sizeof(save_table_entry_t)); cur_index = prev_entry.next_sibling; } } @@ -236,7 +236,7 @@ void save_hierarchical_file_table_unlink_directory_from_parent(hierarchical_save return; } prev_index = cur_index; - memcpy(&prev_entry, &cur_entry, sizeof(prev_entry)); + memcpy(&prev_entry, &cur_entry, sizeof(save_table_entry_t)); cur_index = prev_entry.next_sibling; } } diff --git a/bdk/libs/nx_savedata/integrity_verification_storage.c b/bdk/libs/nx_savedata/integrity_verification_storage.c index fc76501..3e5bba7 100644 --- a/bdk/libs/nx_savedata/integrity_verification_storage.c +++ b/bdk/libs/nx_savedata/integrity_verification_storage.c @@ -52,7 +52,7 @@ void save_ivfc_storage_init(integrity_verification_storage_ctx_t *ctx, integrity /* buffer must have size count + 0x20 for salt to by copied in at offset 0. */ static ALWAYS_INLINE void save_ivfc_storage_do_hash(integrity_verification_storage_ctx_t *ctx, uint8_t *out_hash, void *buffer, uint64_t count) { memcpy(buffer, ctx->salt, sizeof(ctx->salt)); - se_calc_sha256(out_hash, buffer, count + sizeof(ctx->salt)); + se_calc_sha256_oneshot(out_hash, buffer, count + sizeof(ctx->salt)); out_hash[0x1F] |= 0x80; } @@ -81,7 +81,7 @@ bool save_ivfc_storage_read(integrity_verification_storage_ctx_t *ctx, void *buf return false; } - uint8_t hash_buffer[0x20] = {0}; + uint8_t hash_buffer[0x20] __attribute__((aligned(4))) = {0}; uint64_t hash_pos = block_index * sizeof(hash_buffer); if (substorage_read(&ctx->hash_storage, hash_buffer, hash_pos, sizeof(hash_buffer)) != sizeof(hash_buffer)) @@ -99,17 +99,16 @@ bool save_ivfc_storage_read(integrity_verification_storage_ctx_t *ctx, void *buf return false; } + memcpy(buffer, data_buffer + 0x20 + (offset % ctx->base_storage.sector_size), count); + if (ctx->integrity_check_level && ctx->block_validities[block_index] != VALIDITY_UNCHECKED) { - memcpy(buffer, data_buffer + 0x20 + (offset % ctx->base_storage.sector_size), count); free(data_buffer); return true; } - uint8_t hash[0x20] = {0}; + uint8_t hash[0x20] __attribute__((aligned(4))) = {0}; save_ivfc_storage_do_hash(ctx, hash, data_buffer, ctx->base_storage.sector_size); - memcpy(buffer, data_buffer + 0x20 + (offset % ctx->base_storage.sector_size), count); free(data_buffer); - if (memcmp(hash_buffer, hash, sizeof(hash_buffer)) == 0) { ctx->block_validities[block_index] = VALIDITY_VALID; } else { @@ -127,7 +126,7 @@ bool save_ivfc_storage_write(integrity_verification_storage_ctx_t *ctx, const vo uint64_t block_index = offset / ctx->base_storage.sector_size; uint64_t hash_pos = block_index * 0x20; - uint8_t hash[0x20] = {0}; + uint8_t hash[0x20] __attribute__((aligned(4))) = {0}; uint8_t *data_buffer = calloc(1, ctx->base_storage.sector_size + 0x20); if (count < ctx->base_storage.sector_size) { if (substorage_read(&ctx->base_storage.base_storage, data_buffer + 0x20, offset - (offset % ctx->base_storage.sector_size), ctx->base_storage.sector_size) != ctx->base_storage.sector_size) { diff --git a/bdk/libs/nx_savedata/remap_storage.c b/bdk/libs/nx_savedata/remap_storage.c index b00c4e1..eedda6f 100644 --- a/bdk/libs/nx_savedata/remap_storage.c +++ b/bdk/libs/nx_savedata/remap_storage.c @@ -102,7 +102,7 @@ uint32_t save_remap_storage_read(remap_storage_ctx_t *ctx, void *buffer, uint64_ } uint64_t in_pos = offset; uint32_t out_pos = 0; - uint32_t remaining = count; + uint32_t remaining = (u32)count; while (remaining) { uint64_t entry_pos = in_pos - entry->entry.virtual_offset; @@ -135,7 +135,7 @@ uint32_t save_remap_storage_write(remap_storage_ctx_t *ctx, const void *buffer, } uint64_t in_pos = offset; uint32_t out_pos = 0; - uint32_t remaining = count; + uint32_t remaining = (u32)count; while (remaining) { uint64_t entry_pos = in_pos - entry->entry.virtual_offset; diff --git a/bdk/libs/nx_savedata/save.c b/bdk/libs/nx_savedata/save.c index 7669e10..b7fea65 100644 --- a/bdk/libs/nx_savedata/save.c +++ b/bdk/libs/nx_savedata/save.c @@ -98,13 +98,13 @@ static bool save_process_header(save_ctx_t *ctx) { ctx->data_ivfc_master = (uint8_t *)&ctx->header + ctx->header.layout.ivfc_master_hash_offset_a; ctx->fat_ivfc_master = (uint8_t *)&ctx->header + ctx->header.layout.fat_ivfc_master_hash_a; - uint8_t hash[0x20]; + uint8_t hash[0x20] __attribute__((aligned(4))); uint32_t hashed_data_offset = sizeof(ctx->header.layout) + sizeof(ctx->header.cmac) + sizeof(ctx->header._0x10); uint32_t hashed_data_size = sizeof(ctx->header) - hashed_data_offset; - se_calc_sha256(hash, (uint8_t *)&ctx->header + hashed_data_offset, hashed_data_size); - ctx->header_hash_validity = memcmp(hash, ctx->header.layout.hash, 0x20) == 0 ? VALIDITY_VALID : VALIDITY_INVALID; + se_calc_sha256_oneshot(hash, (uint8_t *)&ctx->header + hashed_data_offset, hashed_data_size); + ctx->header_hash_validity = memcmp(hash, ctx->header.layout.hash, sizeof(hash)) == 0 ? VALIDITY_VALID : VALIDITY_INVALID; - unsigned char cmac[0x10] = {}; + uint8_t cmac[0x10] __attribute__((aligned(4))); se_aes_key_set(10, ctx->save_mac_key, 0x10); se_aes_cmac(10, cmac, 0x10, &ctx->header.layout, sizeof(ctx->header.layout)); if (memcmp(cmac, &ctx->header.cmac, 0x10) == 0) { @@ -126,14 +126,14 @@ bool save_process(save_ctx_t *ctx) { substorage_init(&ctx->base_storage, &file_storage_vt, ctx->file, 0, f_size(ctx->file)); /* Try to parse Header A. */ if (substorage_read(&ctx->base_storage, &ctx->header, 0, sizeof(ctx->header)) != sizeof(ctx->header)) { - EPRINTF("Failed to read save header!\n"); + EPRINTF("Failed to read save header A!\n"); return false; } if (!save_process_header(ctx) || (ctx->header_hash_validity == VALIDITY_INVALID)) { /* Try to parse Header B. */ if (substorage_read(&ctx->base_storage, &ctx->header, sizeof(ctx->header), sizeof(ctx->header)) != sizeof(ctx->header)) { - EPRINTF("Failed to read save header!\n"); + EPRINTF("Failed to read save header B!\n"); return false; } @@ -143,14 +143,22 @@ bool save_process(save_ctx_t *ctx) { } } + if (ctx->header.layout.version > VERSION_DISF_5) { + EPRINTF("Unsupported save version.\nLibrary must be updated."); + return false; + } + /* Initialize remap storages. */ ctx->data_remap_storage.header = &ctx->header.main_remap_header; ctx->meta_remap_storage.header = &ctx->header.meta_remap_header; + u32 data_remap_entry_size = sizeof(remap_entry_t) * ctx->data_remap_storage.header->map_entry_count; + u32 meta_remap_entry_size = sizeof(remap_entry_t) * ctx->meta_remap_storage.header->map_entry_count; + substorage_init(&ctx->data_remap_storage.base_storage, &file_storage_vt, ctx->file, ctx->header.layout.file_map_data_offset, ctx->header.layout.file_map_data_size); ctx->data_remap_storage.map_entries = calloc(1, sizeof(remap_entry_ctx_t) * ctx->data_remap_storage.header->map_entry_count); - uint8_t *remap_buffer = malloc(MAX(ctx->data_remap_storage.header->map_entry_count, ctx->meta_remap_storage.header->map_entry_count) * sizeof(remap_entry_t)); - if (substorage_read(&ctx->base_storage, remap_buffer, ctx->header.layout.file_map_entry_offset, sizeof(remap_entry_t) * ctx->data_remap_storage.header->map_entry_count) != sizeof(remap_entry_t) * ctx->data_remap_storage.header->map_entry_count) { + uint8_t *remap_buffer = malloc(MAX(data_remap_entry_size, meta_remap_entry_size)); + if (substorage_read(&ctx->base_storage, remap_buffer, ctx->header.layout.file_map_entry_offset, data_remap_entry_size) != data_remap_entry_size) { EPRINTF("Failed to read data remap table!"); free(remap_buffer); return false; @@ -174,10 +182,10 @@ bool save_process(save_ctx_t *ctx) { return false; } - /* Initialize meta remap storage. */ + /* Initialize meta remap storage. */ substorage_init(&ctx->meta_remap_storage.base_storage, &hierarchical_duplex_storage_vt, &ctx->duplex_storage, 0, ctx->duplex_storage.data_layer->_length); ctx->meta_remap_storage.map_entries = calloc(1, sizeof(remap_entry_ctx_t) * ctx->meta_remap_storage.header->map_entry_count); - if (substorage_read(&ctx->base_storage, remap_buffer, ctx->header.layout.meta_map_entry_offset, sizeof(remap_entry_t) * ctx->meta_remap_storage.header->map_entry_count) != sizeof(remap_entry_t) * ctx->meta_remap_storage.header->map_entry_count) { + if (substorage_read(&ctx->base_storage, remap_buffer, ctx->header.layout.meta_map_entry_offset, meta_remap_entry_size) != meta_remap_entry_size) { EPRINTF("Failed to read meta remap table!"); free(remap_buffer); return false; @@ -225,43 +233,69 @@ bool save_process(save_ctx_t *ctx) { } /* Initialize core save filesystem. */ - save_data_file_system_core_init(&ctx->save_filesystem_core, &ctx->core_data_ivfc_storage.base_storage, ctx->fat_storage, &ctx->header.save_header); - - return true; + return save_data_file_system_core_init(&ctx->save_filesystem_core, &ctx->core_data_ivfc_storage.base_storage, ctx->fat_storage, &ctx->header.save_header); } void save_free_contexts(save_ctx_t *ctx) { - for (unsigned int i = 0; i < ctx->data_remap_storage.header->map_segment_count; i++) { - free(ctx->data_remap_storage.segments[i].entries); + if (ctx->data_remap_storage.header) { + for (unsigned int i = 0; i < ctx->data_remap_storage.header->map_segment_count; i++) { + if (ctx->data_remap_storage.segments && ctx->data_remap_storage.segments[i].entries) + free(ctx->data_remap_storage.segments[i].entries); + } } - free(ctx->data_remap_storage.segments); - for (unsigned int i = 0; i < ctx->meta_remap_storage.header->map_segment_count; i++) { - free(ctx->meta_remap_storage.segments[i].entries); + if (ctx->data_remap_storage.segments) + free(ctx->data_remap_storage.segments); + + if (ctx->meta_remap_storage.header) { + for (unsigned int i = 0; i < ctx->meta_remap_storage.header->map_segment_count; i++) { + if (ctx->meta_remap_storage.segments && ctx->meta_remap_storage.segments[i].entries) + free(ctx->meta_remap_storage.segments[i].entries); + } } - free(ctx->meta_remap_storage.segments); - free(ctx->data_remap_storage.map_entries); - free(ctx->meta_remap_storage.map_entries); + if (ctx->meta_remap_storage.segments) + free(ctx->meta_remap_storage.segments); + + if (ctx->data_remap_storage.map_entries) + free(ctx->data_remap_storage.map_entries); + if (ctx->meta_remap_storage.map_entries) + free(ctx->meta_remap_storage.map_entries); + for (unsigned int i = 0; i < 2; i++) { - free(ctx->duplex_storage.layers[i].bitmap.bitmap); - free(ctx->duplex_storage.layers[i].data_a.base_storage.ctx); - free(ctx->duplex_storage.layers[i].data_b.base_storage.ctx); + if (ctx->duplex_storage.layers[i].bitmap.bitmap) + free(ctx->duplex_storage.layers[i].bitmap.bitmap); + if (ctx->duplex_storage.layers[i].data_a.base_storage.ctx) + free(ctx->duplex_storage.layers[i].data_a.base_storage.ctx); + if (ctx->duplex_storage.layers[i].data_b.base_storage.ctx) + free(ctx->duplex_storage.layers[i].data_b.base_storage.ctx); } - free(ctx->duplex_storage.layers[1].bitmap_storage.base_storage.ctx); - free(ctx->journal_storage.map.map_storage); - free(ctx->journal_storage.map.entries); + if (ctx->duplex_storage.layers[1].bitmap_storage.base_storage.ctx) + free(ctx->duplex_storage.layers[1].bitmap_storage.base_storage.ctx); + + if (ctx->journal_storage.map.map_storage) + free(ctx->journal_storage.map.map_storage); + if (ctx->journal_storage.map.entries) + free(ctx->journal_storage.map.entries); + for (unsigned int i = 0; i < 4; i++) { - free(ctx->core_data_ivfc_storage.integrity_storages[i].block_validities); + if (ctx->core_data_ivfc_storage.integrity_storages[i].block_validities) + free(ctx->core_data_ivfc_storage.integrity_storages[i].block_validities); save_cached_storage_finalize(&ctx->core_data_ivfc_storage.levels[i + 1]); } - free(ctx->core_data_ivfc_storage.level_validities); + if (ctx->core_data_ivfc_storage.level_validities) + free(ctx->core_data_ivfc_storage.level_validities); + if (ctx->header.layout.version >= VERSION_DISF_5) { for (unsigned int i = 0; i < 3; i++) { - free(ctx->fat_ivfc_storage.integrity_storages[i].block_validities); + if (ctx->fat_ivfc_storage.integrity_storages[i].block_validities) + free(ctx->fat_ivfc_storage.integrity_storages[i].block_validities); save_cached_storage_finalize(&ctx->fat_ivfc_storage.levels[i + 1]); } } - free(ctx->fat_ivfc_storage.level_validities); - free(ctx->fat_storage); + if (ctx->fat_ivfc_storage.level_validities) + free(ctx->fat_ivfc_storage.level_validities); + + if (ctx->fat_storage) + free(ctx->fat_storage); } static ALWAYS_INLINE bool save_flush(save_ctx_t *ctx) { @@ -292,7 +326,7 @@ bool save_commit(save_ctx_t *ctx) { uint32_t hashed_data_offset = sizeof(ctx->header.layout) + sizeof(ctx->header.cmac) + sizeof(ctx->header._0x10); uint32_t hashed_data_size = sizeof(ctx->header) - hashed_data_offset; uint8_t *header = (uint8_t *)&ctx->header; - se_calc_sha256(ctx->header.layout.hash, header + hashed_data_offset, hashed_data_size); + se_calc_sha256_oneshot(ctx->header.layout.hash, header + hashed_data_offset, hashed_data_size); se_aes_key_set(10, ctx->save_mac_key, 0x10); se_aes_cmac(10, ctx->header.cmac, 0x10, &ctx->header.layout, sizeof(ctx->header.layout)); diff --git a/bdk/libs/nx_savedata/save_data_file.c b/bdk/libs/nx_savedata/save_data_file.c index 0940052..edf85ba 100644 --- a/bdk/libs/nx_savedata/save_data_file.c +++ b/bdk/libs/nx_savedata/save_data_file.c @@ -38,7 +38,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. void save_data_file_init(save_data_file_ctx_t *ctx, allocation_table_storage_ctx_t *base_storage, const char *path, hierarchical_save_file_table_ctx_t *file_table, uint64_t size, open_mode_t mode) { ctx->mode = mode; - memcpy(&ctx->base_storage, base_storage, sizeof(ctx->base_storage)); + memcpy(&ctx->base_storage, base_storage, sizeof(allocation_table_storage_ctx_t)); ctx->path = path; ctx->file_table = file_table; ctx->size = size; diff --git a/bdk/libs/nx_savedata/save_data_file_system_core.c b/bdk/libs/nx_savedata/save_data_file_system_core.c index ccd3a2c..03275cb 100644 --- a/bdk/libs/nx_savedata/save_data_file_system_core.c +++ b/bdk/libs/nx_savedata/save_data_file_system_core.c @@ -41,21 +41,29 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include -static ALWAYS_INLINE void save_data_file_system_core_open_fat_storage(save_data_file_system_core_ctx_t *ctx, allocation_table_storage_ctx_t *storage_ctx, uint32_t block_index) { - save_allocation_table_storage_init(storage_ctx, ctx->base_storage, &ctx->allocation_table, (uint32_t)ctx->header->block_size, block_index); +static ALWAYS_INLINE bool save_data_file_system_core_open_fat_storage(save_data_file_system_core_ctx_t *ctx, allocation_table_storage_ctx_t *storage_ctx, uint32_t block_index) { + return save_allocation_table_storage_init(storage_ctx, ctx->base_storage, &ctx->allocation_table, (uint32_t)ctx->header->block_size, block_index); } -void save_data_file_system_core_init(save_data_file_system_core_ctx_t *ctx, substorage *storage, void *allocation_table, save_fs_header_t *save_fs_header) { +bool save_data_file_system_core_init(save_data_file_system_core_ctx_t *ctx, substorage *storage, void *allocation_table, save_fs_header_t *save_fs_header) { save_allocation_table_init(&ctx->allocation_table, allocation_table, &save_fs_header->fat_header); ctx->header = save_fs_header; ctx->base_storage = storage; save_filesystem_list_ctx_t *dir_table = &ctx->file_table.directory_table; save_filesystem_list_ctx_t *file_table = &ctx->file_table.file_table; - save_data_file_system_core_open_fat_storage(ctx, &dir_table->storage, save_fs_header->fat_header.directory_table_block); - save_data_file_system_core_open_fat_storage(ctx, &file_table->storage, save_fs_header->fat_header.file_table_block); + if (!save_data_file_system_core_open_fat_storage(ctx, &dir_table->storage, save_fs_header->fat_header.directory_table_block)) { + EPRINTF("Failed to init dir table for fs core!"); + return false; + } + if (!save_data_file_system_core_open_fat_storage(ctx, &file_table->storage, save_fs_header->fat_header.file_table_block)) { + EPRINTF("Failed to init file table for fs core!"); + return false; + } save_fs_list_init(dir_table); save_fs_list_init(file_table); + + return true; } bool save_data_file_system_core_create_directory(save_data_file_system_core_ctx_t *ctx, const char *path) { diff --git a/bdk/libs/nx_savedata/save_data_file_system_core.h b/bdk/libs/nx_savedata/save_data_file_system_core.h index 14c4523..3c69cde 100644 --- a/bdk/libs/nx_savedata/save_data_file_system_core.h +++ b/bdk/libs/nx_savedata/save_data_file_system_core.h @@ -66,7 +66,7 @@ static ALWAYS_INLINE void save_data_file_system_core_get_total_space_size(save_d *out_total_space = ctx->header->block_size * ctx->header->block_count; } -void save_data_file_system_core_init(save_data_file_system_core_ctx_t *ctx, substorage *storage, void *allocation_table, save_fs_header_t *save_fs_header); +bool save_data_file_system_core_init(save_data_file_system_core_ctx_t *ctx, substorage *storage, void *allocation_table, save_fs_header_t *save_fs_header); bool save_data_file_system_core_create_directory(save_data_file_system_core_ctx_t *ctx, const char *path); bool save_data_file_system_core_create_file(save_data_file_system_core_ctx_t *ctx, const char *path, uint64_t size); diff --git a/bdk/libs/nx_savedata/storage.c b/bdk/libs/nx_savedata/storage.c index 326f051..69d88b8 100644 --- a/bdk/libs/nx_savedata/storage.c +++ b/bdk/libs/nx_savedata/storage.c @@ -45,11 +45,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include -void storage_init(storage *this, const storage_vt *vt, void *ctx) { - this->vt = vt; - this->ctx = ctx; -} - void substorage_init(substorage *this, const storage_vt *vt, void *ctx, uint64_t offset, uint64_t length) { storage_init(&this->base_storage, vt, ctx); this->offset = offset; diff --git a/bdk/libs/nx_savedata/storage.h b/bdk/libs/nx_savedata/storage.h index 545a26b..5603881 100644 --- a/bdk/libs/nx_savedata/storage.h +++ b/bdk/libs/nx_savedata/storage.h @@ -51,7 +51,10 @@ typedef struct { void *ctx; } storage; -void storage_init(storage *this, const storage_vt *vt, void *ctx); +static void ALWAYS_INLINE storage_init(storage *this, const storage_vt *vt, void *ctx) { + this->vt = vt; + this->ctx = ctx; +} typedef struct { uint64_t offset; diff --git a/bdk/mem/emc.h b/bdk/mem/emc.h index 9be6fe8..ea5420a 100644 --- a/bdk/mem/emc.h +++ b/bdk/mem/emc.h @@ -72,6 +72,7 @@ #define EMC_PDEX2MRR 0xb4 #define EMC_ODT_WRITE 0xb0 #define EMC_WEXT 0xb8 +#define EMC_CTT 0xBC #define EMC_RFC_SLR 0xc0 #define EMC_MRS_WAIT_CNT2 0xc4 #define EMC_MRS_WAIT_CNT 0xc8 @@ -86,8 +87,13 @@ #define EMC_MRR 0xec #define EMC_CMDQ 0xf0 #define EMC_MC2EMCQ 0xf4 +#define EMC_FBIO_TWTM 0xF8 +#define EMC_FBIO_TRATM 0xFC +#define EMC_FBIO_TWATM 0x108 +#define EMC_FBIO_TR2REF 0x10C #define EMC_FBIO_SPARE 0x100 #define EMC_FBIO_CFG5 0x104 +#define EMC_FBIO_CFG6 0x114 #define EMC_CFG_RSV 0x120 #define EMC_ACPD_CONTROL 0x124 #define EMC_MPC 0x128 @@ -211,6 +217,7 @@ #define EMC_AUTO_CAL_CONFIG6 0x5cc #define EMC_AUTO_CAL_CONFIG7 0x574 #define EMC_AUTO_CAL_CONFIG8 0x2dc +#define EMC_AUTO_CAL_CONFIG9 0x42C #define EMC_AUTO_CAL_VREF_SEL_0 0x2f8 #define EMC_AUTO_CAL_VREF_SEL_1 0x300 #define EMC_AUTO_CAL_INTERVAL 0x2a8 @@ -232,7 +239,7 @@ #define EMC_COMP_PAD_SW_CTRL 0x57c #define EMC_REQ_CTRL 0x2b0 #define EMC_EMC_STATUS 0x2b4 -#define EMC_STATUS_MRR_DIVLD (1 << 20) +#define EMC_STATUS_MRR_DIVLD BIT(20) #define EMC_CFG_2 0x2b8 #define EMC_CFG_DIG_DLL 0x2bc #define EMC_CFG_DIG_DLL_PERIOD 0x2c0 @@ -386,6 +393,8 @@ #define EMC_TRAINING_OPT_DQS_IB_VREF_RANK0 0xed4 #define EMC_TRAINING_OPT_DQS_IB_VREF_RANK1 0xed8 #define EMC_TRAINING_DRAMC_TIMING 0xedc +#define EMC_PMACRO_DATA_PI_CTRL 0x110 +#define EMC_PMACRO_CMD_PI_CTRL 0x114 #define EMC_PMACRO_QUSE_DDLL_RANK0_0 0x600 #define EMC_PMACRO_QUSE_DDLL_RANK0_1 0x604 #define EMC_PMACRO_QUSE_DDLL_RANK0_2 0x608 @@ -650,6 +659,7 @@ #define EMC_PMACRO_CMD_PAD_TX_CTRL 0xc60 #define EMC_PMACRO_DATA_PAD_TX_CTRL 0xc64 #define EMC_PMACRO_COMMON_PAD_TX_CTRL 0xc68 +#define EMC_PMACRO_DSR_VTTGEN_CTRL0 0xC6C #define EMC_PMACRO_BRICK_MAPPING_0 0xc80 #define EMC_PMACRO_BRICK_MAPPING_1 0xc84 #define EMC_PMACRO_BRICK_MAPPING_2 0xc88 @@ -662,6 +672,24 @@ #define EMC_PMACRO_DATA_BRICK_CTRL_FDPD 0x31c #define EMC_PMACRO_TRAINING_CTRL_0 0xcf8 #define EMC_PMACRO_TRAINING_CTRL_1 0xcfc +#define EMC_PMACRO_PERBIT_FGCG_CTRL_0 0xD40 +#define EMC_PMACRO_PERBIT_FGCG_CTRL_1 0xD44 +#define EMC_PMACRO_PERBIT_FGCG_CTRL_2 0xD48 +#define EMC_PMACRO_PERBIT_FGCG_CTRL_3 0xD4C +#define EMC_PMACRO_PERBIT_FGCG_CTRL_4 0xD50 +#define EMC_PMACRO_PERBIT_FGCG_CTRL_5 0xD54 +#define EMC_PMACRO_PERBIT_RFU_CTRL_0 0xD60 +#define EMC_PMACRO_PERBIT_RFU_CTRL_1 0xD64 +#define EMC_PMACRO_PERBIT_RFU_CTRL_2 0xD68 +#define EMC_PMACRO_PERBIT_RFU_CTRL_3 0xD6C +#define EMC_PMACRO_PERBIT_RFU_CTRL_4 0xD70 +#define EMC_PMACRO_PERBIT_RFU_CTRL_5 0xD74 +#define EMC_PMACRO_PERBIT_RFU1_CTRL_0 0xD80 +#define EMC_PMACRO_PERBIT_RFU1_CTRL_1 0xD84 +#define EMC_PMACRO_PERBIT_RFU1_CTRL_2 0xD88 +#define EMC_PMACRO_PERBIT_RFU1_CTRL_3 0xD8C +#define EMC_PMACRO_PERBIT_RFU1_CTRL_4 0xD90 +#define EMC_PMACRO_PERBIT_RFU1_CTRL_5 0xD94 #define EMC_PMC_SCRATCH1 0x440 #define EMC_PMC_SCRATCH2 0x444 #define EMC_PMC_SCRATCH3 0x448 @@ -684,10 +712,13 @@ enum typedef struct _emc_mr_data_t { - u8 dev0_ch0; - u8 dev0_ch1; - u8 dev1_ch0; - u8 dev1_ch1; + // Device 0. + u8 rank0_ch0; + u8 rank0_ch1; + + // Device 1. + u8 rank1_ch0; + u8 rank1_ch1; } emc_mr_data_t; #endif diff --git a/bdk/mem/mc.c b/bdk/mem/mc.c index 8a0da1a..cc136dc 100644 --- a/bdk/mem/mc.c +++ b/bdk/mem/mc.c @@ -144,13 +144,12 @@ void mc_disable_ahb_redirect() void mc_enable() { CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) & 0x1FFFFFFF) | 0x40000000; - // Enable EMC clock. - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & 0xFDFFFFFF) | 0x2000000; - // Enable MC clock. - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & 0xFFFFFFFE) | 1; - // Enable EMC DLL clock. - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) & 0xFFFFBFFF) | 0x4000; - CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = 0x2000001; //Clear EMC and MC reset. + // Enable memory clocks. + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & ~BIT(CLK_H_EMC)) | BIT(CLK_H_EMC); + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & ~BIT(CLK_H_MEM)) | BIT(CLK_H_MEM); + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) & ~BIT(CLK_X_EMC_DLL)) | BIT(CLK_X_EMC_DLL); + // Clear clock resets for memory. + CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_EMC) | BIT(CLK_H_MEM); usleep(5); //#ifdef CONFIG_ENABLE_AHB_REDIRECT diff --git a/bdk/mem/mc_t210.h b/bdk/mem/mc_t210.h index 87fe2ca..a7a9877 100644 --- a/bdk/mem/mc_t210.h +++ b/bdk/mem/mc_t210.h @@ -461,6 +461,7 @@ #define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS1 0xc6c #define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS0 0xd08 #define MC_ERR_APB_ASID_UPDATE_STATUS 0x9d0 +#define MC_UNTRANSLATED_REGION_CHECK 0x948 #define MC_DA_CONFIG0 0x9dc // MC_SECURITY_CARVEOUTX_CFG0 @@ -503,14 +504,14 @@ #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_SEND_CFG_TO_GPU (1 << 22) +#define SEC_CARVEOUT_CFG_SEND_CFG_TO_GPU BIT(22) -#define SEC_CARVEOUT_CFG_TZ_GLOBAL_WR_EN_BYPASS_CHECK (1 << 23) -#define SEC_CARVEOUT_CFG_TZ_GLOBAL_RD_EN_BYPASS_CHECK (1 << 24) +#define SEC_CARVEOUT_CFG_TZ_GLOBAL_WR_EN_BYPASS_CHECK BIT(23) +#define SEC_CARVEOUT_CFG_TZ_GLOBAL_RD_EN_BYPASS_CHECK BIT(24) -#define SEC_CARVEOUT_CFG_ALLOW_APERTURE_ID_MISMATCH (1 << 25) -#define SEC_CARVEOUT_CFG_FORCE_APERTURE_ID_MATCH (1 << 26) +#define SEC_CARVEOUT_CFG_ALLOW_APERTURE_ID_MISMATCH BIT(25) +#define SEC_CARVEOUT_CFG_FORCE_APERTURE_ID_MATCH BIT(26) -#define SEC_CARVEOUT_CFG_IS_WPR (1 << 27) +#define SEC_CARVEOUT_CFG_IS_WPR BIT(27) #endif diff --git a/bdk/mem/minerva.c b/bdk/mem/minerva.c index 259c63a..183b633 100644 --- a/bdk/mem/minerva.c +++ b/bdk/mem/minerva.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -37,6 +38,10 @@ u32 minerva_init() minerva_cfg = NULL; mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg; + //!TODO: Not supported on T210B01 yet. + if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01) + return 0; + #ifdef NYX // Set table to nyx storage. mtc_cfg->mtc_table = (emc_table_t *)nyx_str->mtc_table; @@ -48,7 +53,7 @@ u32 minerva_init() u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)mtc_cfg); minerva_cfg = (void *)ep_addr; - return 0; + return !minerva_cfg ? 1 : 0; } else { diff --git a/bdk/mem/sdram.c b/bdk/mem/sdram.c index e58a1eb..aad98db 100644 --- a/bdk/mem/sdram.c +++ b/bdk/mem/sdram.c @@ -20,12 +20,15 @@ #include #include +#include #include +#include #include #include #include #include #include +#include #include #include #include @@ -33,14 +36,25 @@ #define CONFIG_SDRAM_KEEP_ALIVE +//#define CONFIG_SDRAM_COMPRESS_CFG + +typedef struct _sdram_vendor_patch_t +{ + u32 val; + u32 addr:10; + u32 dramid:22; +} sdram_vendor_patch_t; + #ifdef CONFIG_SDRAM_COMPRESS_CFG -#include -#include "sdram_config_lz.inl" + #include + #include "sdram_config_lz.inl" #else -#include "sdram_config.inl" + #include "sdram_config.inl" #endif -static u32 _get_sdram_id() +#include "sdram_config_t210b01.inl" + +static u32 _sdram_get_id() { return ((fuse_read_odm(4) & 0xF8) >> 3); } @@ -85,17 +99,26 @@ 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; - _sdram_req_mrr_data((1 << 31) | (mrx << 16), EMC_CHAN0); - data.dev0_ch0 = EMC(EMC_MRR) & 0xFF; - data.dev0_ch1 = (EMC(EMC_MRR) & 0xFF00 >> 8); - _sdram_req_mrr_data((1 << 30) | (mrx << 16), EMC_CHAN1); - data.dev1_ch0 = EMC(EMC_MRR) & 0xFF; - data.dev1_ch1 = (EMC(EMC_MRR) & 0xFF00 >> 8); + + /* + * When a dram chip has only one rank, then the info from the 2 ranks differs. + * Info not matching is only allowed on different channels. + */ + + // Get Device 0 (Rank 0) info from both dram chips (channels). + _sdram_req_mrr_data(BIT(31) | (mrx << 16), EMC_CHAN0); + 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); return data; } -static void _sdram_config(const sdram_params_t *params) +static void _sdram_config_t210(const sdram_params_t210_t *params) { // Program DPD3/DPD4 regs (coldboot path). // Enable sel_dpd on unused pins. @@ -143,9 +166,10 @@ break_nosleep: if (params->clear_clock2_mc1) CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_CLR) = 0x40000000; // Clear Reset to MC1. - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = 0x2000001; // Enable EMC and MEM clocks. - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = 0x4000; // Enable EMC_DLL clock. - CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = 0x2000001; // Clear EMC and MEM resets. + // Enable and clear reset for memory clocks. + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_EMC) | BIT(CLK_H_MEM); + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = BIT(CLK_X_EMC_DLL); + CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_EMC) | BIT(CLK_H_MEM); // Set pad macros. EMC(EMC_PMACRO_VTTGEN_CTRL_0) = params->emc_pmacro_vttgen_ctrl0; @@ -540,7 +564,7 @@ break_nosleep: EMC(EMC_CFG) = (params->emc_cfg & 0xE) | 0x3C00000; // Patch BootROM. - if (params->boot_rom_patch_control & (1 << 31)) + if (params->boot_rom_patch_control & BIT(31)) { *(vu32 *)(APB_MISC_BASE + params->boot_rom_patch_control * 4) = params->boot_rom_patch_data; MC(MC_TIMING_CONTROL) = 1; // Trigger MC timing update. @@ -695,49 +719,738 @@ break_nosleep: MC(MC_EMEM_CFG_ACCESS_CTRL) = 1; } -#ifndef CONFIG_SDRAM_COMPRESS_CFG -static void _sdram_patch_model_params(u32 dramid, u32 *params) +static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) { - for (u32 i = 0; i < sizeof(sdram_cfg_vendor_patches) / sizeof(sdram_vendor_patch_t); i++) - if (sdram_cfg_vendor_patches[i].dramid & DRAM_ID(dramid)) - params[sdram_cfg_vendor_patches[i].addr] = sdram_cfg_vendor_patches[i].val; + u32 pmc_scratch1 = ~params->emc_pmc_scratch1; + u32 pmc_scratch2 = ~params->emc_pmc_scratch2; + + // Override HW FSM if needed. + if (params->clk_rst_pllm_misc20_override_enable) + CLOCK(CLK_RST_CONTROLLER_PLLM_MISC2) = params->clk_rst_pllm_misc20_override; + + // 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_IO_DPD3_REQ) = (pmc_scratch1 & 0x9FFF) + 0x80000000; + usleep(params->pmc_io_dpd3_req_wait); + + // Disable e_dpd_vttgen. + PMC(APBDEV_PMC_IO_DPD4_REQ) = (pmc_scratch2 & 0x3FFF0000) | 0x80000000; + usleep(params->pmc_io_dpd4_req_wait); + + // Disable e_dpd_bg. + PMC(APBDEV_PMC_IO_DPD4_REQ) = (pmc_scratch2 & 0x1FFF) | 0x80000000; + usleep(1); + + // 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_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; + EMC(EMC_CMD_MAPPING_CMD1_0) = params->emc_cmd_mapping_cmd1_0; + EMC(EMC_CMD_MAPPING_CMD1_1) = params->emc_cmd_mapping_cmd1_1; + EMC(EMC_CMD_MAPPING_CMD1_2) = params->emc_cmd_mapping_cmd1_2; + EMC(EMC_CMD_MAPPING_CMD2_0) = params->emc_cmd_mapping_cmd2_0; + EMC(EMC_CMD_MAPPING_CMD2_1) = params->emc_cmd_mapping_cmd2_1; + EMC(EMC_CMD_MAPPING_CMD2_2) = params->emc_cmd_mapping_cmd2_2; + 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; + + // Program brick mapping. + EMC(EMC_PMACRO_BRICK_MAPPING_0) = params->emc_pmacro_brick_mapping0; + EMC(EMC_PMACRO_BRICK_MAPPING_1) = params->emc_pmacro_brick_mapping1; + EMC(EMC_PMACRO_BRICK_MAPPING_2) = params->emc_pmacro_brick_mapping2; + + // Set pad macros. + EMC(EMC_PMACRO_VTTGEN_CTRL_0) = params->emc_pmacro_vttgen_ctrl0; + EMC(EMC_PMACRO_VTTGEN_CTRL_1) = params->emc_pmacro_vttgen_ctrl1; + EMC(EMC_PMACRO_VTTGEN_CTRL_2) = params->emc_pmacro_vttgen_ctrl2; + + // Set pad macros bias. + EMC(EMC_PMACRO_BG_BIAS_CTRL_0) = params->emc_pmacro_bg_bias_ctrl0; + + // Patch 1 to 3 using BCT spare secure variables. + if (params->emc_bct_spare_secure0) + *(vu32 *)params->emc_bct_spare_secure0 = params->emc_bct_spare_secure1; + if (params->emc_bct_spare_secure2) + *(vu32 *)params->emc_bct_spare_secure2 = params->emc_bct_spare_secure3; + if (params->emc_bct_spare_secure4) + *(vu32 *)params->emc_bct_spare_secure4 = params->emc_bct_spare_secure5; + + EMC(EMC_TIMING_CONTROL) = 1; // Trigger timing update so above writes take place. + 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_DLL) = params->emc_clock_source_dll; + + // Select EMC write mux. + EMC(EMC_DBG) = (params->emc_dbg_write_mux << 1) | params->emc_dbg; + + // Patch 2 using BCT spare variables. + if (params->emc_bct_spare2) + *(vu32 *)params->emc_bct_spare2 = params->emc_bct_spare3; + + // This is required to do any reads from the pad macros. + EMC(EMC_CONFIG_SAMPLE_DELAY) = params->emc_config_sample_delay; + + EMC(EMC_FBIO_CFG8) = params->emc_fbio_cfg8; + + // Set swizzle for Rank 0. + EMC(EMC_SWIZZLE_RANK0_BYTE0) = params->emc_swizzle_rank0_byte0; + EMC(EMC_SWIZZLE_RANK0_BYTE1) = params->emc_swizzle_rank0_byte1; + EMC(EMC_SWIZZLE_RANK0_BYTE2) = params->emc_swizzle_rank0_byte2; + EMC(EMC_SWIZZLE_RANK0_BYTE3) = params->emc_swizzle_rank0_byte3; + // Set swizzle for Rank 1. + EMC(EMC_SWIZZLE_RANK1_BYTE0) = params->emc_swizzle_rank1_byte0; + EMC(EMC_SWIZZLE_RANK1_BYTE1) = params->emc_swizzle_rank1_byte1; + EMC(EMC_SWIZZLE_RANK1_BYTE2) = params->emc_swizzle_rank1_byte2; + EMC(EMC_SWIZZLE_RANK1_BYTE3) = params->emc_swizzle_rank1_byte3; + + // Patch 3 using BCT spare variables. + if (params->emc_bct_spare6) + *(vu32 *)params->emc_bct_spare6 = params->emc_bct_spare7; + + // Set pad controls. + EMC(EMC_XM2COMPPADCTRL) = params->emc_xm2_comp_pad_ctrl; + EMC(EMC_XM2COMPPADCTRL2) = params->emc_xm2_comp_pad_ctrl2; + EMC(EMC_XM2COMPPADCTRL3) = params->emc_xm2_comp_pad_ctrl3; + + // Program Autocal controls with shadowed register fields. + EMC(EMC_AUTO_CAL_CONFIG2) = params->emc_auto_cal_config2; + EMC(EMC_AUTO_CAL_CONFIG3) = params->emc_auto_cal_config3; + EMC(EMC_AUTO_CAL_CONFIG4) = params->emc_auto_cal_config4; + EMC(EMC_AUTO_CAL_CONFIG5) = params->emc_auto_cal_config5; + EMC(EMC_AUTO_CAL_CONFIG6) = params->emc_auto_cal_config6; + 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_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_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_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_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_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; + 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; + + // Program per bit pad macros. + EMC(EMC_PMACRO_PERBIT_FGCG_CTRL_0) = params->emc_pmacro_perbit_fgcg_ctrl0; + EMC(EMC_PMACRO_PERBIT_FGCG_CTRL_1) = params->emc_pmacro_perbit_fgcg_ctrl1; + EMC(EMC_PMACRO_PERBIT_FGCG_CTRL_2) = params->emc_pmacro_perbit_fgcg_ctrl2; + 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_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_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; + EMC(EMC_PMACRO_QUSE_DDLL_RANK0_2) = params->emc_pmacro_quse_ddll_rank0_2; + EMC(EMC_PMACRO_QUSE_DDLL_RANK0_3) = params->emc_pmacro_quse_ddll_rank0_3; + EMC(EMC_PMACRO_QUSE_DDLL_RANK0_4) = params->emc_pmacro_quse_ddll_rank0_4; + EMC(EMC_PMACRO_QUSE_DDLL_RANK0_5) = params->emc_pmacro_quse_ddll_rank0_5; + EMC(EMC_PMACRO_QUSE_DDLL_RANK1_0) = params->emc_pmacro_quse_ddll_rank1_0; + EMC(EMC_PMACRO_QUSE_DDLL_RANK1_1) = params->emc_pmacro_quse_ddll_rank1_1; + EMC(EMC_PMACRO_QUSE_DDLL_RANK1_2) = params->emc_pmacro_quse_ddll_rank1_2; + 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_OB_DDLL_LONG_DQ_RANK0_0) = params->emc_pmacro_ob_ddll_long_dq_rank0_0; + EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1) = params->emc_pmacro_ob_ddll_long_dq_rank0_1; + EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2) = params->emc_pmacro_ob_ddll_long_dq_rank0_2; + EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3) = params->emc_pmacro_ob_ddll_long_dq_rank0_3; + EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_4) = params->emc_pmacro_ob_ddll_long_dq_rank0_4; + EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_5) = params->emc_pmacro_ob_ddll_long_dq_rank0_5; + EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0) = params->emc_pmacro_ob_ddll_long_dq_rank1_0; + EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1) = params->emc_pmacro_ob_ddll_long_dq_rank1_1; + EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2) = params->emc_pmacro_ob_ddll_long_dq_rank1_2; + EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3) = params->emc_pmacro_ob_ddll_long_dq_rank1_3; + EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_4) = params->emc_pmacro_ob_ddll_long_dq_rank1_4; + EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_5) = params->emc_pmacro_ob_ddll_long_dq_rank1_5; + + EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_0) = params->emc_pmacro_ob_ddll_long_dqs_rank0_0; + EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_1) = params->emc_pmacro_ob_ddll_long_dqs_rank0_1; + EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_2) = params->emc_pmacro_ob_ddll_long_dqs_rank0_2; + EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_3) = params->emc_pmacro_ob_ddll_long_dqs_rank0_3; + EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_4) = params->emc_pmacro_ob_ddll_long_dqs_rank0_4; + EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_5) = params->emc_pmacro_ob_ddll_long_dqs_rank0_5; + EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_0) = params->emc_pmacro_ob_ddll_long_dqs_rank1_0; + EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_1) = params->emc_pmacro_ob_ddll_long_dqs_rank1_1; + EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_2) = params->emc_pmacro_ob_ddll_long_dqs_rank1_2; + EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_3) = params->emc_pmacro_ob_ddll_long_dqs_rank1_3; + EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_4) = params->emc_pmacro_ob_ddll_long_dqs_rank1_4; + EMC(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_5) = params->emc_pmacro_ob_ddll_long_dqs_rank1_5; + EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_0) = params->emc_pmacro_ib_ddll_long_dqs_rank0_0; + EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_1) = params->emc_pmacro_ib_ddll_long_dqs_rank0_1; + EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_2) = params->emc_pmacro_ib_ddll_long_dqs_rank0_2; + EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_3) = params->emc_pmacro_ib_ddll_long_dqs_rank0_3; + EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_0) = params->emc_pmacro_ib_ddll_long_dqs_rank1_0; + EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_1) = params->emc_pmacro_ib_ddll_long_dqs_rank1_1; + 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_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; + + // Set DLL periodic offset. + EMC(EMC_PMACRO_DDLL_PERIODIC_OFFSET) = params->emc_pmacro_ddll_periodic_offset; + + // Patch 4 using BCT spare variables. + if (params->emc_bct_spare4) + *(vu32 *)params->emc_bct_spare4 = params->emc_bct_spare5; + + // 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; + if (params->emc_bct_spare_secure8) + *(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_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_CHANNEL_MASK) = params->mc_emem_adr_cfg_channel_mask; + + // Program bank swizzling. + MC(MC_EMEM_ADR_CFG_BANK_MASK_0) = params->mc_emem_adr_cfg_bank_mask0; + MC(MC_EMEM_ADR_CFG_BANK_MASK_1) = params->mc_emem_adr_cfg_bank_mask1; + MC(MC_EMEM_ADR_CFG_BANK_MASK_2) = params->mc_emem_adr_cfg_bank_mask2; + + // Program external memory aperture (base and size). + 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_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_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_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_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_TIMING_CONTROL) = 1; // Trigger MC timing update. + + // Program second-level clock enable overrides. + MC(MC_CLKEN_OVERRIDE) = params->mc_clken_override; + + // Program statistics gathering. + MC(MC_STAT_CONTROL) = params->mc_stat_control; + + // Program SDRAM geometry parameters. + EMC(EMC_ADR_CFG) = params->emc_adr_cfg; + + // Program second-level clock enable overrides. + EMC(EMC_CLKEN_OVERRIDE) = params->emc_clken_override; + + // Program EMC pad auto calibration. + EMC(EMC_PMACRO_AUTOCAL_CFG_0) = params->emc_pmacro_auto_cal_cfg0; + EMC(EMC_PMACRO_AUTOCAL_CFG_1) = params->emc_pmacro_auto_cal_cfg1; + EMC(EMC_PMACRO_AUTOCAL_CFG_2) = params->emc_pmacro_auto_cal_cfg2; + + EMC(EMC_AUTO_CAL_VREF_SEL_0) = params->emc_auto_cal_vref_sel0; + EMC(EMC_AUTO_CAL_VREF_SEL_1) = params->emc_auto_cal_vref_sel1; + + EMC(EMC_AUTO_CAL_INTERVAL) = params->emc_auto_cal_interval; + EMC(EMC_AUTO_CAL_CONFIG) = params->emc_auto_cal_config; + usleep(params->emc_auto_cal_wait); + + // Patch 5 using BCT spare variables. + if (params->emc_bct_spare8) + *(vu32 *)params->emc_bct_spare8 = params->emc_bct_spare9; + + 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_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_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; + + // 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_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_PMACRO_DSR_VTTGEN_CTRL0) = params->emc_pmacro_dsr_vttgen_ctrl0; + + // Set pipe bypass enable bits before sending any DRAM commands. + EMC(EMC_CFG) = (params->emc_cfg & 0xE) | 0x3C00000; + + // BootROM patching is used as a generic patch here. + if (params->boot_rom_patch_control) + { + *(vu32 *)params->boot_rom_patch_control = params->boot_rom_patch_data; + MC(MC_TIMING_CONTROL) = 1; // Trigger MC timing update. + } + + // Patch 7 to 9 using BCT spare secure variables. + if (params->emc_bct_spare_secure12) + *(vu32 *)params->emc_bct_spare_secure12 = params->emc_bct_spare_secure13; + if (params->emc_bct_spare_secure14) + *(vu32 *)params->emc_bct_spare_secure14 = params->emc_bct_spare_secure15; + if (params->emc_bct_spare_secure16) + *(vu32 *)params->emc_bct_spare_secure16 = params->emc_bct_spare_secure17; + + // Release SEL_DPD_CMD. + PMC(APBDEV_PMC_IO_DPD3_REQ) = ((params->emc_pmc_scratch1 & 0x3FFFFFFF) | 0x40000000) & 0xCFFF0000; + usleep(params->pmc_io_dpd3_req_wait); + + // Set transmission pad control parameters. + EMC(EMC_PMACRO_CMD_PAD_TX_CTRL) = params->emc_pmacro_cmd_pad_tx_ctrl; + + // 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_TIMING_CONTROL) = 1; // Trigger timing update so above writes take place. + usleep(params->emc_timing_control_wait); + + // Deassert HOLD_CKE_LOW. + PMC(APBDEV_PMC_DDR_CNTRL) &= 0xFF78007F; + usleep(params->pmc_ddr_ctrl_wait); + + // 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); + } + + 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); + + // 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) + { + // Issue ZQCAL start, device 0. + EMC(EMC_ZQ_CAL) = params->emc_zcal_init_dev0; + 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; + } + } + } + + // Patch 10 to 12 using BCT spare secure variables. + if (params->emc_bct_spare_secure18) + *(vu32 *)params->emc_bct_spare_secure18 = params->emc_bct_spare_secure19; + if (params->emc_bct_spare_secure20) + *(vu32 *)params->emc_bct_spare_secure20 = params->emc_bct_spare_secure21; + if (params->emc_bct_spare_secure22) + *(vu32 *)params->emc_bct_spare_secure22 = params->emc_bct_spare_secure23; + + // Set package and DPD pad control. + 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; + } + + // Patch 7 using BCT spare variables. + if (params->emc_bct_spare12) + *(vu32 *)params->emc_bct_spare12 = params->emc_bct_spare13; + + EMC(EMC_TIMING_CONTROL) = 1; // Trigger timing update so above writes take place. + + if (params->emc_extra_refresh_num) + EMC(EMC_REF) = ((1 << params->emc_extra_refresh_num << 8) - 253) | (params->emc_dev_select << 30); + + // Enable refresh. + 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_FDPD_CTRL_CMD) = params->emc_fdpd_ctrl_cmd; + EMC(EMC_SEL_DPD_CTRL) = params->emc_sel_dpd_ctrl; + + // Write addr swizzle lock bit. + EMC(EMC_FBIO_SPARE) = params->emc_fbio_spare | 2; + + EMC(EMC_TIMING_CONTROL) = 1; // Re-trigger timing to latch power saving functions. + + EMC(EMC_CFG_UPDATE) = params->emc_cfg_update; + + // Enable EMC pipe clock gating. + EMC(EMC_CFG_PIPE_CLK) = params->emc_cfg_pipe_clk; + + // Depending on freqency, enable CMD/CLK fdpd. + EMC(EMC_FDPD_CTRL_CMD_NO_RAMP) = params->emc_fdpd_ctrl_cmd_no_ramp; + + // Set untranslated region requirements. + MC(MC_UNTRANSLATED_REGION_CHECK) = params->mc_untranslated_region_check; + + // 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; + + // Disable write access to a bunch of EMC registers. + MC(MC_EMEM_CFG_ACCESS_CTRL) = 1; + + // Enable arbiter. + SYSREG(AHB_ARBITRATION_XBAR_CTRL) = (SYSREG(AHB_ARBITRATION_XBAR_CTRL) & 0xFFFEFFFF) | (params->ahb_arbitration_xbar_ctrl_meminit_done << 16); +} + +#ifndef CONFIG_SDRAM_COMPRESS_CFG +static void _sdram_patch_model_params_t210(u32 dramid, u32 *params) +{ + for (u32 i = 0; i < ARRAY_SIZE(sdram_cfg_vendor_patches_t210); i++) + if (sdram_cfg_vendor_patches_t210[i].dramid & DRAM_ID(dramid)) + params[sdram_cfg_vendor_patches_t210[i].addr] = sdram_cfg_vendor_patches_t210[i].val; } #endif -sdram_params_t *sdram_get_params() +static void _sdram_patch_model_params_t210b01(u32 dramid, u32 *params) +{ + for (u32 i = 0; i < ARRAY_SIZE(sdram_cfg_vendor_patches_t210b01); i++) + if (sdram_cfg_vendor_patches_t210b01[i].dramid & DRAM_ID2(dramid)) + params[sdram_cfg_vendor_patches_t210b01[i].addr] = sdram_cfg_vendor_patches_t210b01[i].val; +} + +static void *_sdram_get_params_t210() { // Check if id is proper. - u32 dramid = _get_sdram_id(); + u32 dramid = _sdram_get_id(); if (dramid > 6) dramid = 0; #ifdef CONFIG_SDRAM_COMPRESS_CFG + u8 *buf = (u8 *)SDRAM_PARAMS_ADDR; LZ_Uncompress(_dram_cfg_lz, buf, sizeof(_dram_cfg_lz)); - return (sdram_params_t *)&buf[sizeof(sdram_params_t) * dramid]; + return (void *)&buf[sizeof(sdram_params_t210_t) * dramid]; + #else - sdram_params_t *buf = (sdram_params_t *)SDRAM_PARAMS_ADDR; - memcpy(buf, &_dram_cfg_0_samsung_4gb, sizeof(sdram_params_t)); + + u32 *buf = (u32 *)SDRAM_PARAMS_ADDR; + memcpy(buf, &_dram_cfg_0_samsung_4gb, sizeof(sdram_params_t210_t)); + switch (dramid) { - case DRAM_4GB_SAMSUNG_K4F6E304HB_MGCH: - case DRAM_4GB_MICRON_MT53B512M32D2NP_062_WT: + case LPDDR4_ICOSA_4GB_SAMSUNG_K4F6E304HB_MGCH: + case LPDDR4_ICOSA_4GB_MICRON_MT53B512M32D2NP_062_WT: break; - case DRAM_4GB_HYNIX_H9HCNNNBPUMLHR_NLN: - case DRAM_6GB_SAMSUNG_K4FHE3D4HM_MFCH: + case LPDDR4_ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE: + case LPDDR4_ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH: #ifdef CONFIG_SDRAM_COPPER_SUPPORT - case DRAM_4GB_COPPER_SAMSUNG: - case DRAM_4GB_COPPER_HYNIX: - case DRAM_4GB_COPPER_MICRON: + case LPDDR4_COPPER_4GB_SAMSUNG_K4F6E304HB_MGCH: + case LPDDR4_COPPER_4GB_HYNIX_H9HCNNNBPUMLHR_NLE: + case LPDDR4_COPPER_4GB_MICRON_MT53B512M32D2NP_062_WT: #endif - _sdram_patch_model_params(dramid, (u32 *)buf); + _sdram_patch_model_params_t210(dramid, (u32 *)buf); break; } - return buf; + return (void *)buf; + #endif } +void *sdram_get_params_t210b01() +{ + // Check if id is proper. + u32 dramid = _sdram_get_id(); + if (dramid > 27) + dramid = 8; + + u32 *buf = (u32 *)SDRAM_PARAMS_ADDR; + memcpy(buf, &_dram_cfg_08_10_12_14_samsung_hynix_4gb, sizeof(sdram_params_t210b01_t)); + + switch (dramid) + { + case LPDDR4X_IOWA_4GB_SAMSUNG_K4U6E3S4AM_MGCJ: + case LPDDR4X_IOWA_4GB_HYNIX_H9HCNNNBKMMLHR_NME: + case LPDDR4X_HOAG_4GB_SAMSUNG_K4U6E3S4AM_MGCJ: + case LPDDR4X_HOAG_4GB_HYNIX_H9HCNNNBKMMLHR_NME: + break; + + case LPDDR4X_IOWA_4GB_SAMSUNG_X1X2: + case LPDDR4X_IOWA_8GB_SAMSUNG_K4UBE3D4AM_MGCJ: + case LPDDR4X_IOWA_4GB_MICRON_MT53E512M32D2NP_046_WT: + case LPDDR4X_HOAG_8GB_SAMSUNG_K4UBE3D4AM_MGCJ: + case LPDDR4X_HOAG_4GB_MICRON_MT53E512M32D2NP_046_WT: + case LPDDR4X_IOWA_4GB_SAMSUNG_Y: + case LPDDR4X_IOWA_4GB_SAMSUNG_1Y_X: + case LPDDR4X_IOWA_8GB_SAMSUNG_1Y_X: + case LPDDR4X_HOAG_4GB_SAMSUNG_1Y_X: + case LPDDR4X_IOWA_4GB_SAMSUNG_1Y_Y: + case LPDDR4X_IOWA_8GB_SAMSUNG_1Y_Y: + case LPDDR4X_SDS_4GB_SAMSUNG_1Y_A: + case LPDDR4X_SDS_8GB_SAMSUNG_1Y_X: + case LPDDR4X_SDS_4GB_SAMSUNG_1Y_X: + case LPDDR4X_IOWA_4GB_MICRON_1Y_A: + case LPDDR4X_HOAG_4GB_MICRON_1Y_A: + case LPDDR4X_SDS_4GB_MICRON_1Y_A: + _sdram_patch_model_params_t210b01(dramid, (u32 *)buf); + break; + } + return (void *)buf; +} + /* * Function: sdram_get_params_patched * @@ -754,13 +1467,13 @@ sdram_params_t *sdram_get_params() * Note: The modulus in the header must match and validated. */ -sdram_params_t *sdram_get_params_patched() +void *sdram_get_params_patched() { - #define IPATCH_CONFIG(addr, data) (((addr - 0x100000) / 2) << 16 | (data & 0xffff)) - sdram_params_t *sdram_params = sdram_get_params(); + #define IPATCH_CONFIG(addr, data) ((((addr) - 0x100000) / 2) << 16 | ((data) & 0xffff)) + sdram_params_t210_t *sdram_params = _sdram_get_params_t210(); // Disable Warmboot signature check. - sdram_params->boot_rom_patch_control = (1 << 31) | (((IPATCH_BASE + 4) - APB_MISC_BASE) / 4); + sdram_params->boot_rom_patch_control = BIT(31) | (((IPATCH_BASE + 4) - APB_MISC_BASE) / 4); sdram_params->boot_rom_patch_data = IPATCH_CONFIG(0x10459E, 0x2000); /* // Disable SBK lock. @@ -773,15 +1486,14 @@ sdram_params_t *sdram_get_params_patched() sdram_params->emc_bct_spare12 = (IPATCH_BASE + 11 * 4); sdram_params->emc_bct_spare13 = IPATCH_CONFIG(0x100FDE, 0xE320); */ - return sdram_params; + return (void *)sdram_params; } -void sdram_init() +static void _sdram_init_t210() { - const sdram_params_t *params = (const sdram_params_t *)sdram_get_params(); + const sdram_params_t210_t *params = (const sdram_params_t210_t *)_sdram_get_params_t210(); // Set DRAM voltage. - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, 0x05); max77620_regulator_set_voltage(REGULATOR_SD1, 1100000); // VDDP Select. @@ -801,5 +1513,37 @@ void sdram_init() if (params->emc_bct_spare0) *(vu32 *)params->emc_bct_spare0 = params->emc_bct_spare1; - _sdram_config(params); + _sdram_config_t210(params); +} + +static void _sdram_init_t210b01() +{ + const sdram_params_t210b01_t *params = (const sdram_params_t210b01_t *)sdram_get_params_t210b01(); + + // VDDP Select. + PMC(APBDEV_PMC_VDDP_SEL) = params->pmc_vddp_sel; + usleep(params->pmc_vddp_sel_wait); + + // Turn on MEM IO Power. + PMC(APBDEV_PMC_NO_IOPOWER) = params->pmc_no_io_power; + PMC(APBDEV_PMC_REG_SHORT) = params->pmc_reg_short; + + PMC(APBDEV_PMC_DDR_CNTRL) = params->pmc_ddr_ctrl; + + // Patch 1 using BCT spare variables + if (params->emc_bct_spare0) + *(vu32 *)params->emc_bct_spare0 = params->emc_bct_spare1; + + _sdram_config_t210b01(params); +} + +void sdram_init() +{ + // Configure SD regulator for DRAM. + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, 0x05); + + if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210) + _sdram_init_t210(); + else + _sdram_init_t210b01(); } diff --git a/bdk/mem/sdram.h b/bdk/mem/sdram.h index 620c078..77db819 100644 --- a/bdk/mem/sdram.h +++ b/bdk/mem/sdram.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 naehrwert + * Copyright (c) 2020 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 +19,76 @@ #define _SDRAM_H_ #include -#include + +/* + * Tegra X1/X1+ EMC/DRAM Bandwidth Chart: + * + * 40.8 MHz: 0.61 GiB/s + * 68.0 MHz: 1.01 GiB/s + * 102.0 MHz: 1.52 GiB/s + * 204.0 MHz: 3.04 GiB/s <-- Tegra X1/X1+ Init/SC7 Frequency + * 408.0 MHz: 6.08 GiB/s + * 665.6 MHz: 9.92 GiB/s + * 800.0 MHz: 11.92 GiB/s <-- Tegra X1/X1+ Nvidia OS Boot Frequency + * 1065.6 MHz: 15.89 GiB/s + * 1331.2 MHz: 19.84 GiB/s + * 1600.0 MHz: 23.84 GiB/s <-- Tegra X1 Official Max Frequency + * 1862.4 MHz: 27.75 GiB/s <-- Tegra X1+ Official Max Frequency + * 2131.2 MHz: 31.76 GiB/s + * + * Note: BWbits = Hz x bus width x channels = Hz x 64 x 2. + */ + +enum sdram_ids_erista +{ + // LPDDR4 3200Mbps. + LPDDR4_ICOSA_4GB_SAMSUNG_K4F6E304HB_MGCH = 0, + LPDDR4_ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 1, + LPDDR4_ICOSA_4GB_MICRON_MT53B512M32D2NP_062_WT = 2, + LPDDR4_COPPER_4GB_SAMSUNG_K4F6E304HB_MGCH = 3, + LPDDR4_ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH = 4, + LPDDR4_COPPER_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 5, + LPDDR4_COPPER_4GB_MICRON_MT53B512M32D2NP_062_WT = 6, +}; + +enum sdram_ids_mariko +{ + // LPDDR4X 3733Mbps. + LPDDR4X_IOWA_4GB_SAMSUNG_X1X2 = 7, + + LPDDR4X_IOWA_4GB_SAMSUNG_K4U6E3S4AM_MGCJ = 8, + LPDDR4X_IOWA_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 9, + LPDDR4X_IOWA_4GB_HYNIX_H9HCNNNBKMMLHR_NME = 10, + LPDDR4X_IOWA_4GB_MICRON_MT53E512M32D2NP_046_WT = 11, // 4266Mbps. + + LPDDR4X_HOAG_4GB_SAMSUNG_K4U6E3S4AM_MGCJ = 12, + LPDDR4X_HOAG_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 13, + LPDDR4X_HOAG_4GB_HYNIX_H9HCNNNBKMMLHR_NME = 14, + LPDDR4X_HOAG_4GB_MICRON_MT53E512M32D2NP_046_WT = 15, // 4266Mbps. + + // LPDDR4X 4266Mbps? + LPDDR4X_IOWA_4GB_SAMSUNG_Y = 16, + + LPDDR4X_IOWA_4GB_SAMSUNG_1Y_X = 17, + LPDDR4X_IOWA_8GB_SAMSUNG_1Y_X = 18, + LPDDR4X_HOAG_4GB_SAMSUNG_1Y_X = 19, + + LPDDR4X_IOWA_4GB_SAMSUNG_1Y_Y = 20, + LPDDR4X_IOWA_8GB_SAMSUNG_1Y_Y = 21, + + LPDDR4X_SDS_4GB_SAMSUNG_1Y_A = 22, + + LPDDR4X_SDS_8GB_SAMSUNG_1Y_X = 23, + LPDDR4X_SDS_4GB_SAMSUNG_1Y_X = 24, + + LPDDR4X_IOWA_4GB_MICRON_1Y_A = 25, + LPDDR4X_HOAG_4GB_MICRON_1Y_A = 26, + LPDDR4X_SDS_4GB_MICRON_1Y_A = 27 +}; void sdram_init(); -sdram_params_t *sdram_get_params(); -sdram_params_t *sdram_get_params_patched(); +void *sdram_get_params_patched(); +void *sdram_get_params_t210b01(); void sdram_lp0_save_params(const void *params); emc_mr_data_t sdram_read_mrx(emc_mr_t mrx); diff --git a/bdk/mem/sdram_config.inl b/bdk/mem/sdram_config.inl index 42e0555..727ec60 100644 --- a/bdk/mem/sdram_config.inl +++ b/bdk/mem/sdram_config.inl @@ -15,26 +15,11 @@ * along with this program. If not, see . */ -#define DRAM_CFG_SIZE 1896 +#define DRAM_CFG_T210_SIZE 1896 -#define DRAM_ID(x) (1 << (x)) +#define DRAM_ID(x) BIT(x) -#define DRAM_4GB_SAMSUNG_K4F6E304HB_MGCH 0 -#define DRAM_4GB_HYNIX_H9HCNNNBPUMLHR_NLN 1 -#define DRAM_4GB_MICRON_MT53B512M32D2NP_062_WT 2 -#define DRAM_4GB_COPPER_SAMSUNG 3 -#define DRAM_6GB_SAMSUNG_K4FHE3D4HM_MFCH 4 -#define DRAM_4GB_COPPER_HYNIX 5 -#define DRAM_4GB_COPPER_MICRON 6 - -typedef struct _sdram_vendor_patch_t -{ - u32 val; - u16 addr:9; - u16 dramid:7; -} sdram_vendor_patch_t; - -static const sdram_params_t _dram_cfg_0_samsung_4gb = { +static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = { /* Specifies the type of memory device */ .memory_type = MEMORY_TYPE_LPDDR4, @@ -112,7 +97,7 @@ static const sdram_params_t _dram_cfg_0_samsung_4gb = { * DRAM size information * Specifies the value for EMC_ADR_CFG */ - .emc_adr_cfg = 0x00000001, + .emc_adr_cfg = 0x00000001, // 2 populated DRAM Devices. /* * Specifies the time to wait after asserting pin @@ -258,7 +243,7 @@ static const sdram_params_t _dram_cfg_0_samsung_4gb = { .emc_cfg_dig_dll = 0x002C00A0, .emc_cfg_dig_dll_1 = 0x00003701, .emc_cfg_dig_dll_period = 0x00008000, - .emc_dev_select = 0x00000000, + .emc_dev_select = 0x00000000, // Both devices. .emc_sel_dpd_ctrl = 0x00040008, /* Pads trimmer delays */ @@ -505,9 +490,9 @@ static const sdram_params_t _dram_cfg_0_samsung_4gb = { .emc_pmacro_cmd_ctrl2 = 0x0A0A0A0A, /* DRAM size information */ - .mc_emem_adr_cfg = 0x00000001, - .mc_emem_adr_cfg_dev0 = 0x00070302, - .mc_emem_adr_cfg_dev1 = 0x00070302, + .mc_emem_adr_cfg = 0x00000001, // 2 populated DRAM Devices. + .mc_emem_adr_cfg_dev0 = 0x00070302, // Density 512MB. + .mc_emem_adr_cfg_dev1 = 0x00070302, // Density 512MB. .mc_emem_adr_cfg_channel_mask = 0xFFFF2400, .mc_emem_adr_cfg_bank_mask0 = 0x6E574400, .mc_emem_adr_cfg_bank_mask1 = 0x39722800, @@ -516,7 +501,7 @@ static const sdram_params_t _dram_cfg_0_samsung_4gb = { * Specifies the value for MC_EMEM_CFG which holds the external memory * size (in KBytes) */ - .mc_emem_cfg = 0x00001000, + .mc_emem_cfg = 0x00001000, // 4GB total density. /* MC arbitration configuration */ .mc_emem_arb_cfg = 0x08000001, @@ -659,7 +644,7 @@ static const sdram_params_t _dram_cfg_0_samsung_4gb = { .mc_mts_carveout_reg_ctrl = 0x00000000 }; -static const sdram_vendor_patch_t sdram_cfg_vendor_patches[] = { +static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210[] = { // Hynix timing config. { 0x0000000D, 67, DRAM_ID(1) | DRAM_ID(5) }, // emc_r2w. { 0x00000001, 91, DRAM_ID(1) | DRAM_ID(5) }, // emc_puterm_extra. diff --git a/bdk/mem/sdram_config_t210b01.inl b/bdk/mem/sdram_config_t210b01.inl new file mode 100644 index 0000000..983c93a --- /dev/null +++ b/bdk/mem/sdram_config_t210b01.inl @@ -0,0 +1,1002 @@ +/* + * Copyright (c) 2020 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 . + */ + +#define DRAM_CFG_T210B01_SIZE 2104 + +#define DRAM_ID2(x) BIT((x) - 7) + +static const sdram_params_t210b01_t _dram_cfg_08_10_12_14_samsung_hynix_4gb = { + /* Specifies the type of memory device */ + .memory_type = MEMORY_TYPE_LPDDR4, + + /* MC/EMC clock source configuration */ + .pllm_input_divider = 0x00000001, // M div. + .pllm_feedback_divider = 0x00000022, // N div. + .pllm_stable_time = 0x0000012C, + .pllm_setup_control = 0x00000000, + .pllm_post_divider = 0x00000000, // P div. + .pllm_kcp = 0x00000000, + .pllm_kvco = 0x00000000, + + /* Spare BCT params */ + .emc_bct_spare0 = 0x00000000, + .emc_bct_spare1 = 0x00000000, + .emc_bct_spare2 = 0x00000000, + .emc_bct_spare3 = 0x00000000, + .emc_bct_spare4 = 0x00000000, + .emc_bct_spare5 = 0x00000000, + .emc_bct_spare6 = 0x00000000, + .emc_bct_spare7 = 0x00000000, + .emc_bct_spare8 = 0x00000000, + .emc_bct_spare9 = 0x00000000, + .emc_bct_spare10 = 0x00000000, + .emc_bct_spare11 = 0x00000000, + .emc_bct_spare12 = 0x00000000, + .emc_bct_spare13 = 0x00000000, + + .emc_bct_spare_secure0 = 0x00000000, + .emc_bct_spare_secure1 = 0x00000000, + .emc_bct_spare_secure2 = 0x00000000, + .emc_bct_spare_secure3 = 0x00000000, + .emc_bct_spare_secure4 = 0x00000000, + .emc_bct_spare_secure5 = 0x00000000, + .emc_bct_spare_secure6 = 0x00000000, + .emc_bct_spare_secure7 = 0x00000000, + .emc_bct_spare_secure8 = 0x00000000, + .emc_bct_spare_secure9 = 0x00000000, + .emc_bct_spare_secure10 = 0x00000000, + .emc_bct_spare_secure11 = 0x00000000, + .emc_bct_spare_secure12 = 0x00000000, + .emc_bct_spare_secure13 = 0x00000000, + .emc_bct_spare_secure14 = 0x00000000, + .emc_bct_spare_secure15 = 0x00000000, + .emc_bct_spare_secure16 = 0x00000000, + .emc_bct_spare_secure17 = 0x00000000, + .emc_bct_spare_secure18 = 0x00000000, + .emc_bct_spare_secure19 = 0x00000000, + .emc_bct_spare_secure20 = 0x00000000, + .emc_bct_spare_secure21 = 0x00000000, + .emc_bct_spare_secure22 = 0x00000000, + .emc_bct_spare_secure23 = 0x00000000, + + /* EMC clock configuration */ + .emc_clock_source = 0x40188002, + .emc_clock_source_dll = 0x40000000, + + .clk_rst_pllm_misc20_override = 0x00000000, + .clk_rst_pllm_misc20_override_enable = 0x00000000, + + .clear_clock2_mc1 = 0x00000000, + + /* Auto-calibration of EMC pads */ + .emc_auto_cal_interval = 0x001FFFFF, + + .emc_auto_cal_config = 0xA01A51D8, + .emc_auto_cal_config2 = 0x00000000, + .emc_auto_cal_config3 = 0x00880000, + + .emc_auto_cal_config4 = 0x00880000, + .emc_auto_cal_config5 = 0x00001220, + .emc_auto_cal_config6 = 0x00880000, + .emc_auto_cal_config7 = 0x00880000, + .emc_auto_cal_config8 = 0x00880000, + .emc_auto_cal_config9 = 0x00000000, + + .emc_auto_cal_vref_sel0 = 0xB3C5BCBC, + .emc_auto_cal_vref_sel1 = 0x00009E3C, + + .emc_auto_cal_channel = 0xC1E00302, + + .emc_pmacro_auto_cal_cfg0 = 0x04040404, + .emc_pmacro_auto_cal_cfg1 = 0x04040404, + .emc_pmacro_auto_cal_cfg2 = 0x04040404, + + .emc_pmacro_rx_term = 0x3F3F3F3F, + .emc_pmacro_dq_tx_drive = 0x3F3F3F3F, + .emc_pmacro_ca_tx_drive = 0x3F3F3F3F, + .emc_pmacro_cmd_tx_drive = 0x00001220, + .emc_pmacro_auto_cal_common = 0x00000804, + .emc_pmacro_zcrtl = 0x505050, + + /* Specifies the time for the calibration to stabilize (in microseconds) */ + .emc_auto_cal_wait = 0x000001A1, + + .emc_xm2_comp_pad_ctrl = 0x00000030, + .emc_xm2_comp_pad_ctrl2 = 0x16001000, + .emc_xm2_comp_pad_ctrl3 = 0x00901000, + + /* + * DRAM size information + * Specifies the value for EMC_ADR_CFG + */ + .emc_adr_cfg = 0x00000000, // 1 populated DRAM Device. + + /* + * Specifies the time to wait after asserting pin + * CKE (in microseconds) + */ + .emc_pin_program_wait = 0x00000002, + /* Specifies the extra delay before/after pin RESET/CKE command */ + .emc_pin_extra_wait = 0x00000000, + + .emc_pin_gpio_enable = 0x00000003, + .emc_pin_gpio = 0x00000003, + + /* Specifies the extra delay after the first writing of EMC_TIMING_CONTROL */ + .emc_timing_control_wait = 0x0000001E, + + /* Timing parameters required for the SDRAM */ + .emc_rc = 0x0000000D, + .emc_rfc = 0x0000003A, + .emc_rfc_pb = 0x0000001D, + .emc_ref_ctrl2 = 0x00000000, + .emc_rfc_slr = 0x00000000, + .emc_ras = 0x00000009, + .emc_rp = 0x00000004, + .emc_r2r = 0x00000000, + .emc_w2w = 0x00000000, + .emc_r2w = 0x0000000B, + .emc_w2r = 0x0000000D, + .emc_r2p = 0x00000008, + .emc_w2p = 0x0000000B, + .emc_tppd = 0x00000004, + .emc_trtm = 0x00000017, + .emc_twtm = 0x00000015, + .emc_tratm = 0x00000017, + .emc_twatm = 0x0000001B, + .emc_tr2ref = 0x00000000, + .emc_ccdmw = 0x00000020, + .emc_rd_rcd = 0x00000006, + .emc_wr_rcd = 0x00000006, + .emc_rrd = 0x00000006, + .emc_rext = 0x00000003, + .emc_wext = 0x00000000, + .emc_wdv = 0x00000004, + .emc_wdv_chk = 0x00000006, + .emc_wsv = 0x00000002, + .emc_wev = 0x00000000, + .emc_wdv_mask = 0x00000004, + .emc_ws_duration = 0x00000008, + .emc_we_duration = 0x0000000E, + .emc_quse = 0x00000005, + .emc_quse_width = 0x00000006, + .emc_ibdly = 0x00000000, + .emc_obdly = 0x00000000, + .emc_einput = 0x00000002, + .emc_einput_duration = 0x0000000D, + .emc_puterm_extra = 0x00000001, + .emc_puterm_width = 0x80000000, + .emc_qrst = 0x00010000, + .emc_qsafe = 0x00000012, + .emc_rdv = 0x00000018, + .emc_rdv_mask = 0x0000001A, + .emc_rdv_early = 0x00000016, + .emc_rdv_early_mask = 0x00000018, + .emc_qpop = 0x0000000A, + .emc_refresh = 0x00000304, + .emc_burst_refresh_num = 0x00000000, + .emc_prerefresh_req_cnt = 0x000000C1, + .emc_pdex2wr = 0x00000008, + .emc_pdex2rd = 0x00000008, + .emc_pchg2pden = 0x00000003, + .emc_act2pden = 0x0000000A, + .emc_ar2pden = 0x00000003, + .emc_rw2pden = 0x00000014, + .emc_cke2pden = 0x00000005, + .emc_pdex2che = 0x00000002, + .emc_pdex2mrr = 0x0000000D, + .emc_txsr = 0x0000003B, + .emc_txsr_dll = 0x0000003B, + .emc_tcke = 0x00000005, + .emc_tckesr = 0x00000005, + .emc_tpd = 0x00000004, + .emc_tfaw = 0x00000009, + .emc_trpab = 0x00000005, + .emc_tclkstable = 0x00000004, + .emc_tclkstop = 0x00000009, + .emc_trefbw = 0x0000031C, + + /* FBIO configuration values */ + .emc_fbio_cfg5 = 0x9160A00D, + .emc_fbio_cfg7 = 0x00003A3F, + .emc_fbio_cfg8 = 0x0CF30000, + + /* Command mapping for CMD brick 0 */ + .emc_cmd_mapping_cmd0_0 = 0x061B0504, + .emc_cmd_mapping_cmd0_1 = 0x1C070302, + .emc_cmd_mapping_cmd0_2 = 0x05252523, + .emc_cmd_mapping_cmd1_0 = 0x0A091D08, + .emc_cmd_mapping_cmd1_1 = 0x0D1E0B24, + .emc_cmd_mapping_cmd1_2 = 0x0326260C, + .emc_cmd_mapping_cmd2_0 = 0x231C1B02, + .emc_cmd_mapping_cmd2_1 = 0x05070403, + .emc_cmd_mapping_cmd2_2 = 0x02252506, + .emc_cmd_mapping_cmd3_0 = 0x0D1D0B0A, + .emc_cmd_mapping_cmd3_1 = 0x1E090C08, + .emc_cmd_mapping_cmd3_2 = 0x08262624, + .emc_cmd_mapping_byte = 0x9A070624, + + .emc_fbio_spare = 0x00000012, + .emc_cfg_rsv = 0xFF00FF00, + + /* MRS command values */ + .emc_mrs = 0x00000000, + .emc_emrs = 0x00000000, + .emc_emrs2 = 0x00000000, + .emc_emrs3 = 0x00000000, + .emc_mrw1 = 0x88010004, + .emc_mrw2 = 0x88020000, + .emc_mrw3 = 0x880D0000, + .emc_mrw4 = 0xC0000000, + .emc_mrw6 = 0x88033131, + .emc_mrw8 = 0x880B0000, + .emc_mrw9 = 0x8C0E5D5D, + .emc_mrw10 = 0x880C5D5D, + .emc_mrw12 = 0x8C0D0808, + .emc_mrw13 = 0x8C0D0000, + .emc_mrw14 = 0x88161616, + .emc_mrw_extra = 0x88010004, + .emc_warm_boot_mrw_extra = 0x08110000, + .emc_warm_boot_extramode_reg_write_enable = 0x00000001, + .emc_extramode_reg_write_enable = 0x00000000, + .emc_mrw_reset_command = 0x00000000, + .emc_mrw_reset_ninit_wait = 0x00000000, + .emc_mrs_wait_cnt = 0x00CC0010, + .emc_mrs_wait_cnt2 = 0x0033000A, + + /* EMC miscellaneous configurations */ + .emc_cfg = 0xF3200000, + .emc_cfg2 = 0x00110825, + .emc_cfg_pipe = 0x0FFF0000, + .emc_cfg_pipe_clk = 0x00000000, + .emc_fdpd_ctrl_cmd_no_ramp = 0x00000001, + .emc_cfg_update = 0x70000301, + .emc_dbg = 0x01000C00, + .emc_dbg_write_mux = 0x00000001, + .emc_cmd_q = 0x10004408, + .emc_mc2emc_q = 0x06000404, + .emc_dyn_self_ref_control = 0x00000713, + .ahb_arbitration_xbar_ctrl_meminit_done = 0x00000001, + .emc_cfg_dig_dll = 0x002C00A0, + .emc_cfg_dig_dll_1 = 0x000F3701, + .emc_cfg_dig_dll_period = 0x00008000, + .emc_dev_select = 0x00000002, // Dev0 only. + .emc_sel_dpd_ctrl = 0x0004000C, + + /* Pads trimmer delays */ + .emc_fdpd_ctrl_dq = 0x8020221F, + .emc_fdpd_ctrl_cmd = 0x0220F40F, + .emc_pmacro_ib_vref_dq_0 = 0x29292929, + .emc_pmacro_ib_vref_dq_1 = 0x29292929, + .emc_pmacro_ib_vref_dqs_0 = 0x29292929, + .emc_pmacro_ib_vref_dqs_1 = 0x29292929, + .emc_pmacro_ib_rxrt = 0x00000078, + .emc_cfg_pipe1 = 0x0FFF0000, + .emc_cfg_pipe2 = 0x00000000, + + .emc_pmacro_quse_ddll_rank0_0 = 0x00000000, + .emc_pmacro_quse_ddll_rank0_1 = 0x00000000, + .emc_pmacro_quse_ddll_rank0_2 = 0x00000000, + .emc_pmacro_quse_ddll_rank0_3 = 0x00000000, + .emc_pmacro_quse_ddll_rank0_4 = 0x00000000, + .emc_pmacro_quse_ddll_rank0_5 = 0x00000000, + .emc_pmacro_quse_ddll_rank1_0 = 0x00000000, + .emc_pmacro_quse_ddll_rank1_1 = 0x00000000, + .emc_pmacro_quse_ddll_rank1_2 = 0x00000000, + .emc_pmacro_quse_ddll_rank1_3 = 0x00000000, + .emc_pmacro_quse_ddll_rank1_4 = 0x00000000, + .emc_pmacro_quse_ddll_rank1_5 = 0x00000000, + + .emc_pmacro_ob_ddll_long_dq_rank0_0 = 0x00000000, + .emc_pmacro_ob_ddll_long_dq_rank0_1 = 0x00000000, + .emc_pmacro_ob_ddll_long_dq_rank0_2 = 0x00000000, + .emc_pmacro_ob_ddll_long_dq_rank0_3 = 0x00000000, + .emc_pmacro_ob_ddll_long_dq_rank0_4 = 0x000D0016, + .emc_pmacro_ob_ddll_long_dq_rank0_5 = 0x0017000B, + .emc_pmacro_ob_ddll_long_dq_rank1_0 = 0x00000000, + .emc_pmacro_ob_ddll_long_dq_rank1_1 = 0x00000000, + .emc_pmacro_ob_ddll_long_dq_rank1_2 = 0x00000000, + .emc_pmacro_ob_ddll_long_dq_rank1_3 = 0x00000000, + .emc_pmacro_ob_ddll_long_dq_rank1_4 = 0x000D0016, + .emc_pmacro_ob_ddll_long_dq_rank1_5 = 0x0017000B, + + .emc_pmacro_ob_ddll_long_dqs_rank0_0 = 0x00450043, + .emc_pmacro_ob_ddll_long_dqs_rank0_1 = 0x00430045, + .emc_pmacro_ob_ddll_long_dqs_rank0_2 = 0x00470046, + .emc_pmacro_ob_ddll_long_dqs_rank0_3 = 0x00460041, + .emc_pmacro_ob_ddll_long_dqs_rank0_4 = 0x0003000C, + .emc_pmacro_ob_ddll_long_dqs_rank0_5 = 0x000D0000, + .emc_pmacro_ob_ddll_long_dqs_rank1_0 = 0x00450043, + .emc_pmacro_ob_ddll_long_dqs_rank1_1 = 0x00430045, + .emc_pmacro_ob_ddll_long_dqs_rank1_2 = 0x00470046, + .emc_pmacro_ob_ddll_long_dqs_rank1_3 = 0x00460041, + .emc_pmacro_ob_ddll_long_dqs_rank1_4 = 0x0003000C, + .emc_pmacro_ob_ddll_long_dqs_rank1_5 = 0x000D0000, + + .emc_pmacro_ib_ddll_long_dqs_rank0_0 = 0x00280028, + .emc_pmacro_ib_ddll_long_dqs_rank0_1 = 0x00280028, + .emc_pmacro_ib_ddll_long_dqs_rank0_2 = 0x00280028, + .emc_pmacro_ib_ddll_long_dqs_rank0_3 = 0x00280028, + .emc_pmacro_ib_ddll_long_dqs_rank1_0 = 0x00280028, + .emc_pmacro_ib_ddll_long_dqs_rank1_1 = 0x00280028, + .emc_pmacro_ib_ddll_long_dqs_rank1_2 = 0x00280028, + .emc_pmacro_ib_ddll_long_dqs_rank1_3 = 0x00280028, + + .emc_pmacro_ddll_long_cmd_0 = 0x00160016, + .emc_pmacro_ddll_long_cmd_1 = 0x000D000D, + .emc_pmacro_ddll_long_cmd_2 = 0x000B000B, + .emc_pmacro_ddll_long_cmd_3 = 0x00170017, + .emc_pmacro_ddll_long_cmd_4 = 0x00000016, + .emc_pmacro_ddll_short_cmd_0 = 0x00000000, + .emc_pmacro_ddll_short_cmd_1 = 0x00000000, + .emc_pmacro_ddll_short_cmd_2 = 0x00000000, + + .emc_pmacro_ddll_periodic_offset = 0x00000000, + + /* + * Specifies the delay after asserting CKE pin during a WarmBoot0 + * sequence (in microseconds) + */ + .warm_boot_wait = 0x00000001, + + .emc_odt_write = 0x00000000, + + /* Periodic ZQ calibration */ + + /* + * Specifies the value for EMC_ZCAL_INTERVAL + * Value 0 disables ZQ calibration + */ + .emc_zcal_interval = 0x00064000, + .emc_zcal_wait_cnt = 0x000900CC, + .emc_zcal_mrw_cmd = 0x8051004F, + + /* DRAM initialization sequence flow control */ + .emc_mrs_reset_dll = 0x00000000, + .emc_zcal_init_dev0 = 0x80000001, + .emc_zcal_init_dev1 = 0x00000000, + /* + * Specifies the wait time after programming a ZQ initialization + * command (in microseconds) + */ + .emc_zcal_init_wait = 0x00000001, + /* + * Specifies the enable for ZQ calibration at cold boot [bit 0] + * and warm boot [bit 1] + */ + .emc_zcal_warm_cold_boot_enables = 0x00000003, + + /* + * Specifies the MRW command to LPDDR2 for ZQ calibration + * on warmboot + */ + /* Is issued to both devices separately */ + .emc_mrw_lpddr2zcal_warm_boot = 0x040A00AB, + /* + * Specifies the ZQ command to DDR3 for ZQ calibration on warmboot + * Is issued to both devices separately + */ + .emc_zqcal_ddr3_warm_boot = 0x00000011, + .emc_zqcal_lpddr4_warm_boot = 0x00000001, + + /* + * Specifies the wait time for ZQ calibration on warmboot + * (in microseconds) + */ + .emc_zcal_warm_boot_wait = 0x00000001, + /* + * Specifies the enable for DRAM Mode Register programming + * at warm boot + */ + .emc_mrs_warm_boot_enable = 0x00000001, + .emc_mrs_reset_dll_wait = 0x00000000, + .emc_mrs_extra = 0x00000000, + .emc_warm_boot_mrs_extra = 0x00000000, + .emc_emrs_ddr2_dll_enable = 0x00000000, + .emc_mrs_ddr2_dll_reset = 0x00000000, + .emc_emrs_ddr2_ocd_calib = 0x00000000, + /* + * Specifies the wait between initializing DDR and setting OCD + * calibration (in microseconds) + */ + .emc_ddr2_wait = 0x00000000, + .emc_clken_override = 0x00000000, + /* + * Specifies LOG2 of the extra refresh numbers after booting + * Program 0 to disable + */ + .emc_extra_refresh_num = 0x00000002, + .emc_clken_override_allwarm_boot = 0x00000000, + .mc_clken_override_allwarm_boot = 0x00000000, + /* Specifies digital dll period, choosing between 4 to 64 ms */ + .emc_cfg_dig_dll_period_warm_boot = 0x00000003, + + /* Pad controls */ + .pmc_vddp_sel = 0x00000001, + .pmc_vddp_sel_wait = 0x00000002, + .pmc_ddr_cfg = 0x04220100, + .pmc_io_dpd3_req = 0x4FAF9FFF, + .pmc_io_dpd3_req_wait = 0x00000001, + .pmc_io_dpd4_req_wait = 0x00000002, + .pmc_reg_short = 0x00000000, + .pmc_no_io_power = 0x00000000, + .pmc_ddr_ctrl_wait = 0x00000000, + .pmc_ddr_ctrl = 0x0037FF9F, + .emc_acpd_control = 0x00000000, + + .emc_swizzle_rank0_byte0 = 0x76543201, + .emc_swizzle_rank0_byte1 = 0x65324710, + .emc_swizzle_rank0_byte2 = 0x25763410, + .emc_swizzle_rank0_byte3 = 0x25673401, + .emc_swizzle_rank1_byte0 = 0x32647501, + .emc_swizzle_rank1_byte1 = 0x34567201, + .emc_swizzle_rank1_byte2 = 0x56742310, + .emc_swizzle_rank1_byte3 = 0x67324501, + + .emc_txdsrvttgen = 0x00000000, + + .emc_data_brlshft0 = 0x00249249, + .emc_data_brlshft1 = 0x00249249, + + .emc_dqs_brlshft0 = 0x00000000, + .emc_dqs_brlshft1 = 0x00000000, + + .emc_cmd_brlshft0 = 0x00000000, + .emc_cmd_brlshft1 = 0x00000000, + .emc_cmd_brlshft2 = 0x00000012, + .emc_cmd_brlshft3 = 0x00000012, + + .emc_quse_brlshft0 = 0x00000000, + .emc_quse_brlshft1 = 0x00000000, + .emc_quse_brlshft2 = 0x00000000, + .emc_quse_brlshft3 = 0x00000000, + + .emc_dll_cfg0 = 0x1F134120, + .emc_dll_cfg1 = 0x00010014, + + .emc_pmc_scratch1 = 0x4FAF9FFF, + .emc_pmc_scratch2 = 0x7FFFFFFF, + .emc_pmc_scratch3 = 0x4036D71F, + + .emc_pmacro_pad_cfg_ctrl = 0x00000000, + .emc_pmacro_vttgen_ctrl0 = 0x00090000, + .emc_pmacro_vttgen_ctrl1 = 0x00103400, + .emc_pmacro_vttgen_ctrl2 = 0x00000000, + .emc_pmacro_dsr_vttgen_ctrl0 = 0x00000009, + .emc_pmacro_brick_ctrl_rfu1 = 0x00000000, + .emc_pmacro_cmd_brick_ctrl_fdpd = 0x00000000, + .emc_pmacro_brick_ctrl_rfu2 = 0x00000000, + .emc_pmacro_data_brick_ctrl_fdpd = 0x00000000, + .emc_pmacro_bg_bias_ctrl0 = 0x00000000, + .emc_pmacro_data_pad_rx_ctrl = 0x05050003, + .emc_pmacro_cmd_pad_rx_ctrl = 0x05000000, + .emc_pmacro_data_rx_term_mode = 0x00000210, + .emc_pmacro_cmd_rx_term_mode = 0x00002000, + .emc_pmacro_data_pad_tx_ctrl = 0x00000421, + .emc_pmacro_cmd_pad_tx_ctrl = 0x00000000, + + .emc_cfg3 = 0x00000040, + + .emc_pmacro_tx_pwrd0 = 0x10000000, + .emc_pmacro_tx_pwrd1 = 0x00000000, + .emc_pmacro_tx_pwrd2 = 0x00000000, + .emc_pmacro_tx_pwrd3 = 0x00000000, + .emc_pmacro_tx_pwrd4 = 0x00400080, + .emc_pmacro_tx_pwrd5 = 0x00801004, + + .emc_config_sample_delay = 0x00000020, + + .emc_pmacro_brick_mapping0 = 0x28091081, + .emc_pmacro_brick_mapping1 = 0x44A53293, + .emc_pmacro_brick_mapping2 = 0x76678A5B, + + .emc_pmacro_tx_sel_clk_src0 = 0x00000000, + .emc_pmacro_tx_sel_clk_src1 = 0x00000000, + .emc_pmacro_tx_sel_clk_src2 = 0x00000000, + .emc_pmacro_tx_sel_clk_src3 = 0x00000000, + .emc_pmacro_tx_sel_clk_src4 = 0x00000000, + .emc_pmacro_tx_sel_clk_src5 = 0x00000000, + + .emc_pmacro_perbit_fgcg_ctrl0 = 0x00000000, + .emc_pmacro_perbit_fgcg_ctrl1 = 0x00000000, + .emc_pmacro_perbit_fgcg_ctrl2 = 0x00000000, + .emc_pmacro_perbit_fgcg_ctrl3 = 0x00000000, + .emc_pmacro_perbit_fgcg_ctrl4 = 0x00000000, + .emc_pmacro_perbit_fgcg_ctrl5 = 0x00000000, + .emc_pmacro_perbit_rfu_ctrl0 = 0x00000000, + .emc_pmacro_perbit_rfu_ctrl1 = 0x00000000, + .emc_pmacro_perbit_rfu_ctrl2 = 0x00000000, + .emc_pmacro_perbit_rfu_ctrl3 = 0x00000000, + .emc_pmacro_perbit_rfu_ctrl4 = 0x00000000, + .emc_pmacro_perbit_rfu_ctrl5 = 0x00000000, + .emc_pmacro_perbit_rfu1_ctrl0 = 0x00000000, + .emc_pmacro_perbit_rfu1_ctrl1 = 0x00000000, + .emc_pmacro_perbit_rfu1_ctrl2 = 0x00000000, + .emc_pmacro_perbit_rfu1_ctrl3 = 0x00000000, + .emc_pmacro_perbit_rfu1_ctrl4 = 0x00000000, + .emc_pmacro_perbit_rfu1_ctrl5 = 0x00000000, + + .emc_pmacro_data_pi_ctrl = 0x00001010, + .emc_pmacro_cmd_pi_ctrl = 0x00001010, + + .emc_pmacro_ddll_bypass = 0xEF00EF00, + + .emc_pmacro_ddll_pwrd0 = 0x00000000, + .emc_pmacro_ddll_pwrd1 = 0x00000000, + .emc_pmacro_ddll_pwrd2 = 0x1C1C1C1C, + + .emc_pmacro_cmd_ctrl0 = 0x00000000, + .emc_pmacro_cmd_ctrl1 = 0x00000000, + .emc_pmacro_cmd_ctrl2 = 0x00000000, + + /* DRAM size information */ + .mc_emem_adr_cfg = 0x00000000, // 1 populated DRAM Device. + .mc_emem_adr_cfg_dev0 = 0x00080302, // Density 1024MB. + .mc_emem_adr_cfg_dev1 = 0x00080302, // Density 1024MB. + .mc_emem_adr_cfg_channel_mask = 0xFFFF2400, + .mc_emem_adr_cfg_bank_mask0 = 0x6E574400, + .mc_emem_adr_cfg_bank_mask1 = 0x39722800, + .mc_emem_adr_cfg_bank_mask2 = 0x4B9C1000, + /* + * Specifies the value for MC_EMEM_CFG which holds the external memory + * size (in KBytes) + */ + .mc_emem_cfg = 0x00001000, // 4GB total density. + + /* MC arbitration configuration */ + .mc_emem_arb_cfg = 0x08000001, + .mc_emem_arb_outstanding_req = 0x8000004C, + .emc_emem_arb_refpb_hp_ctrl = 0x000A1020, + .emc_emem_arb_refpb_bank_ctrl = 0x80001028, + + .mc_emem_arb_timing_rcd = 0x00000001, + .mc_emem_arb_timing_rp = 0x00000000, + .mc_emem_arb_timing_rc = 0x00000003, + .mc_emem_arb_timing_ras = 0x00000001, + .mc_emem_arb_timing_faw = 0x00000002, + .mc_emem_arb_timing_rrd = 0x00000001, + .mc_emem_arb_timing_rap2pre = 0x00000002, + .mc_emem_arb_timing_wap2pre = 0x00000005, + .mc_emem_arb_timing_r2r = 0x00000001, + .mc_emem_arb_timing_w2w = 0x00000001, + .mc_emem_arb_timing_r2w = 0x00000004, + .mc_emem_arb_timing_w2r = 0x00000005, + .mc_emem_arb_timing_rfcpb = 0x00000007, + + .mc_emem_arb_da_turns = 0x02020000, + .mc_emem_arb_da_covers = 0x00030201, + .mc_emem_arb_misc0 = 0x72A30504, + .mc_emem_arb_misc1 = 0x70000F0F, + .mc_emem_arb_misc2 = 0x00000000, + + .mc_emem_arb_ring1_throttle = 0x001F0000, + .mc_emem_arb_override = 0x10000000, + .mc_emem_arb_override1 = 0x00000000, + .mc_emem_arb_rsv = 0xFF00FF00, + + .mc_da_cfg0 = 0x00000001, + .mc_emem_arb_timing_ccdmw = 0x00000008, + + .mc_clken_override = 0x00008000, + + .mc_stat_control = 0x00000000, + .mc_video_protect_bom = 0xFFF00000, + .mc_video_protect_bom_adr_hi = 0x00000000, + .mc_video_protect_size_mb = 0x00000000, + .mc_video_protect_vpr_override = 0xE4BAC343, + .mc_video_protect_vpr_override1 = 0x06001ED3, // Add SE2, SE2B. + .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, + .mc_video_protect_write_access = 0x00000000, + .mc_sec_carveout_protect_write_access = 0x00000000, + + .mc_generalized_carveout1_bom = 0x00000000, + .mc_generalized_carveout1_bom_hi = 0x00000000, + .mc_generalized_carveout1_size_128kb = 0x00000008, + .mc_generalized_carveout1_access0 = 0x00000000, + .mc_generalized_carveout1_access1 = 0x00000000, + .mc_generalized_carveout1_access2 = 0x00300000, + .mc_generalized_carveout1_access3 = 0x03000000, + .mc_generalized_carveout1_access4 = 0x00000000, + .mc_generalized_carveout1_force_internal_access0 = 0x00000000, + .mc_generalized_carveout1_force_internal_access1 = 0x00000000, + .mc_generalized_carveout1_force_internal_access2 = 0x00000000, + .mc_generalized_carveout1_force_internal_access3 = 0x00000000, + .mc_generalized_carveout1_force_internal_access4 = 0x00000000, + .mc_generalized_carveout1_cfg0 = 0x04000C76, + + .mc_generalized_carveout2_bom = 0x00000000, + .mc_generalized_carveout2_bom_hi = 0x00000000, + .mc_generalized_carveout2_size_128kb = 0x00000002, + .mc_generalized_carveout2_access0 = 0x00000000, + .mc_generalized_carveout2_access1 = 0x00000000, + .mc_generalized_carveout2_access2 = 0x03000000, + .mc_generalized_carveout2_access3 = 0x00000000, + .mc_generalized_carveout2_access4 = 0x00000300, + .mc_generalized_carveout2_force_internal_access0 = 0x00000000, + .mc_generalized_carveout2_force_internal_access1 = 0x00000000, + .mc_generalized_carveout2_force_internal_access2 = 0x00000000, + .mc_generalized_carveout2_force_internal_access3 = 0x00000000, + .mc_generalized_carveout2_force_internal_access4 = 0x00000000, + .mc_generalized_carveout2_cfg0 = 0x0440167E, + + .mc_generalized_carveout3_bom = 0x00000000, + .mc_generalized_carveout3_bom_hi = 0x00000000, + .mc_generalized_carveout3_size_128kb = 0x00000000, + .mc_generalized_carveout3_access0 = 0x00000000, + .mc_generalized_carveout3_access1 = 0x00000000, + .mc_generalized_carveout3_access2 = 0x03000000, + .mc_generalized_carveout3_access3 = 0x00000000, + .mc_generalized_carveout3_access4 = 0x00000300, + .mc_generalized_carveout3_force_internal_access0 = 0x00000000, + .mc_generalized_carveout3_force_internal_access1 = 0x00000000, + .mc_generalized_carveout3_force_internal_access2 = 0x00000000, + .mc_generalized_carveout3_force_internal_access3 = 0x00000000, + .mc_generalized_carveout3_force_internal_access4 = 0x00000000, + .mc_generalized_carveout3_cfg0 = 0x04401E7E, + + .mc_generalized_carveout4_bom = 0x00000000, + .mc_generalized_carveout4_bom_hi = 0x00000000, + .mc_generalized_carveout4_size_128kb = 0x00000008, + .mc_generalized_carveout4_access0 = 0x00000000, + .mc_generalized_carveout4_access1 = 0x00000000, + .mc_generalized_carveout4_access2 = 0x00300000, + .mc_generalized_carveout4_access3 = 0x00000000, + .mc_generalized_carveout4_access4 = 0x000000C0, + .mc_generalized_carveout4_force_internal_access0 = 0x00000000, + .mc_generalized_carveout4_force_internal_access1 = 0x00000000, + .mc_generalized_carveout4_force_internal_access2 = 0x00000000, + .mc_generalized_carveout4_force_internal_access3 = 0x00000000, + .mc_generalized_carveout4_force_internal_access4 = 0x00000000, + .mc_generalized_carveout4_cfg0 = 0x04002446, + + .mc_generalized_carveout5_bom = 0x00000000, + .mc_generalized_carveout5_bom_hi = 0x00000000, + .mc_generalized_carveout5_size_128kb = 0x00000008, + .mc_generalized_carveout5_access0 = 0x00000000, + .mc_generalized_carveout5_access1 = 0x00000000, + .mc_generalized_carveout5_access2 = 0x00300000, + .mc_generalized_carveout5_access3 = 0x00000000, + .mc_generalized_carveout5_access4 = 0x00000000, + .mc_generalized_carveout5_force_internal_access0 = 0x00000000, + .mc_generalized_carveout5_force_internal_access1 = 0x00000000, + .mc_generalized_carveout5_force_internal_access2 = 0x00000000, + .mc_generalized_carveout5_force_internal_access3 = 0x00000000, + .mc_generalized_carveout5_force_internal_access4 = 0x00000000, + .mc_generalized_carveout5_cfg0 = 0x04002C46, + + /* Specifies enable for CA training */ + .emc_ca_training_enable = 0x00000000, + /* Set if bit 6 select is greater than bit 7 select; uses aremc.spec packet SWIZZLE_BIT6_GT_BIT7 */ + .swizzle_rank_byte_encode = 0x000000EC, + + /* Specifies enable and offset for patched boot rom write */ + .boot_rom_patch_control = 0x00000000, + /* Specifies data for patched boot rom write */ + .boot_rom_patch_data = 0x00000000, + + .mc_mts_carveout_bom = 0xFFF00000, + .mc_mts_carveout_adr_hi = 0x00000000, + .mc_mts_carveout_size_mb = 0x00000000, + .mc_mts_carveout_reg_ctrl = 0x00000000, + + /* Specifies the untranslated memory access control */ + .mc_untranslated_region_check = 0x00000000, + + /* Just a place holder for special usage when there is no BCT for certain registers */ + .bct_na = 0x00000000, +}; + +//!TODO Find out what mc_video_protect_gpu_override0 and mc_video_protect_gpu_override1 new bits are. + +static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = { + + // Samsung LPDDR4X 4GB X1X2 for prototype Iowa. + { 0x000E0022, 0x3AC / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dq_rank0_4. + { 0x001B0010, 0x3B0 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dq_rank0_5. + { 0x000E0022, 0x3C4 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dq_rank1_4. + { 0x001B0010, 0x3C8 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dq_rank1_5. + { 0x00490043, 0x3CC / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank0_0. + { 0x00420045, 0x3D0 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank0_1. + { 0x00490047, 0x3D4 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank0_2. + { 0x00460047, 0x3D8 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank0_3. + { 0x00000016, 0x3DC / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank0_4. + { 0x00100000, 0x3E0 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank0_5. + { 0x00490043, 0x3E4 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank1_0. + { 0x00420045, 0x3E8 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank1_1. + { 0x00490047, 0x3EC / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank1_2. + { 0x00460047, 0x3F0 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank1_3. + { 0x00000016, 0x3F4 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank1_4. + { 0x00100000, 0x3F8 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank1_5. + { 0x00220022, 0x41C / 4, DRAM_ID2(7) }, // emc_pmacro_ddll_long_cmd_0. + { 0x000E000E, 0x420 / 4, DRAM_ID2(7) }, // emc_pmacro_ddll_long_cmd_1. + { 0x00100010, 0x424 / 4, DRAM_ID2(7) }, // emc_pmacro_ddll_long_cmd_2. + { 0x001B001B, 0x428 / 4, DRAM_ID2(7) }, // emc_pmacro_ddll_long_cmd_3. + { 0x00000022, 0x42C / 4, DRAM_ID2(7) }, // emc_pmacro_ddll_long_cmd_4. + + // Samsung LPDDR4X 8GB K4UBE3D4AM-MGCJ for SDEV Iowa and Hoag. + { 0x05500000, 0x0D4 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_auto_cal_config2. + { 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_auto_cal_vref_sel0. + { 0x00000001, 0x134 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_adr_cfg. 2 populated DRAM Devices. + { 0x00000006, 0x1CC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_quse. + { 0x00000005, 0x1D0 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_quse_width. + { 0x00000003, 0x1DC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_einput. + { 0x0000000C, 0x1E0 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_einput_duration. + { 0x08010004, 0x2B8 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw1. + { 0x08020000, 0x2BC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw2. + { 0x080D0000, 0x2C0 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw3. + { 0x08033131, 0x2C8 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw6. + { 0x080B0000, 0x2CC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw8. + { 0x0C0E5D5D, 0x2D0 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw9. + { 0x080C5D5D, 0x2D4 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw10. + { 0x0C0D0808, 0x2D8 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw12. + { 0x0C0D0000, 0x2DC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw13. + { 0x08161414, 0x2E0 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw14. + { 0x08010004, 0x2E4 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw_extra. + { 0x00000000, 0x340 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_dev_select. Both devices. + { 0x35353535, 0x350 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_ib_vref_dq_0. + { 0x35353535, 0x354 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_ib_vref_dq_1. + { 0x00100010, 0x3FC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_ib_ddll_long_dqs_rank0_0. + { 0x00100010, 0x400 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_ib_ddll_long_dqs_rank0_1. + { 0x00100010, 0x404 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_ib_ddll_long_dqs_rank0_2. + { 0x00100010, 0x408 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_ib_ddll_long_dqs_rank0_3. + { 0x00100010, 0x40C / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_ib_ddll_long_dqs_rank1_0. + { 0x00100010, 0x410 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_ib_ddll_long_dqs_rank1_1. + { 0x00100010, 0x414 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_ib_ddll_long_dqs_rank1_2. + { 0x00100010, 0x418 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_ib_ddll_long_dqs_rank1_3. + { 0x0051004F, 0x450 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_zcal_mrw_cmd. + { 0x40000001, 0x45C / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_zcal_init_dev1. + { 0x00000000, 0x594 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_tx_pwrd4. + { 0x00001000, 0x598 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_tx_pwrd5. + { 0x00000001, 0x630 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_adr_cfg. 2 populated DRAM Devices. + { 0x00002000, 0x64C / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_cfg. 8GB total density. + { 0x00000002, 0x680 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_arb_timing_r2r. + { 0x02020001, 0x694 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_arb_da_turns. + { 0x2A800000, 0x6DC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_video_protect_gpu_override0. + { 0x00000002, 0x6E0 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_video_protect_gpu_override1. + + // Micron LPDDR4X 4GB MT53D1024M32D1NP-053-WT for Iowa and Hoag. + { 0x05500000, 0x0D4 / 4, DRAM_ID2(11) | DRAM_ID2(15) }, // emc_auto_cal_config2. + { 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(11) | DRAM_ID2(15) }, // emc_auto_cal_vref_sel0. + { 0x88161414, 0x2E0 / 4, DRAM_ID2(11) | DRAM_ID2(15) }, // emc_mrw14. + { 0x80000713, 0x32C / 4, DRAM_ID2(11) | DRAM_ID2(15) }, // emc_dyn_self_ref_control. + { 0x2A800000, 0x6DC / 4, DRAM_ID2(11) | DRAM_ID2(15) }, // mc_video_protect_gpu_override0. + { 0x00000002, 0x6E0 / 4, DRAM_ID2(11) | DRAM_ID2(15) }, // mc_video_protect_gpu_override1. + + // Samsung LPDDR4X 4GB Die-Y for Iowa. + { 0x05500000, 0x0D4 / 4, DRAM_ID2(16) }, // emc_auto_cal_config2. + { 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(16) }, // emc_auto_cal_vref_sel0. + { 0x88161414, 0x2E0 / 4, DRAM_ID2(16) }, // emc_mrw14. + { 0x80000713, 0x32C / 4, DRAM_ID2(16) }, // emc_dyn_self_ref_control. + { 0x32323232, 0x350 / 4, DRAM_ID2(16) }, // emc_pmacro_ib_vref_dq_0. + { 0x32323232, 0x354 / 4, DRAM_ID2(16) }, // emc_pmacro_ib_vref_dq_1. + { 0x000F0018, 0x3AC / 4, DRAM_ID2(16) }, // emc_pmacro_ob_ddll_long_dq_rank0_4. + { 0x000F0018, 0x3C4 / 4, DRAM_ID2(16) }, // emc_pmacro_ob_ddll_long_dq_rank1_4. + { 0x00440048, 0x3CC / 4, DRAM_ID2(16) }, // emc_pmacro_ob_ddll_long_dqs_rank0_0. + { 0x00440045, 0x3D0 / 4, DRAM_ID2(16) }, // emc_pmacro_ob_ddll_long_dqs_rank0_1. + { 0x00470047, 0x3D4 / 4, DRAM_ID2(16) }, // emc_pmacro_ob_ddll_long_dqs_rank0_2. + { 0x0005000D, 0x3DC / 4, DRAM_ID2(16) }, // emc_pmacro_ob_ddll_long_dqs_rank0_4. + { 0x00440048, 0x3E4 / 4, DRAM_ID2(16) }, // emc_pmacro_ob_ddll_long_dqs_rank1_0. + { 0x00440045, 0x3E8 / 4, DRAM_ID2(16) }, // emc_pmacro_ob_ddll_long_dqs_rank1_1. + { 0x00470047, 0x3EC / 4, DRAM_ID2(16) }, // emc_pmacro_ob_ddll_long_dqs_rank1_2. + { 0x0005000D, 0x3F4 / 4, DRAM_ID2(16) }, // emc_pmacro_ob_ddll_long_dqs_rank1_4. + { 0x00780078, 0x3FC / 4, DRAM_ID2(16) }, // emc_pmacro_ib_ddll_long_dqs_rank0_0. + { 0x00780078, 0x400 / 4, DRAM_ID2(16) }, // emc_pmacro_ib_ddll_long_dqs_rank0_1. + { 0x00780078, 0x404 / 4, DRAM_ID2(16) }, // emc_pmacro_ib_ddll_long_dqs_rank0_2. + { 0x00780078, 0x408 / 4, DRAM_ID2(16) }, // emc_pmacro_ib_ddll_long_dqs_rank0_3. + { 0x00780078, 0x40C / 4, DRAM_ID2(16) }, // emc_pmacro_ib_ddll_long_dqs_rank1_0. + { 0x00780078, 0x410 / 4, DRAM_ID2(16) }, // emc_pmacro_ib_ddll_long_dqs_rank1_1. + { 0x00780078, 0x414 / 4, DRAM_ID2(16) }, // emc_pmacro_ib_ddll_long_dqs_rank1_2. + { 0x00780078, 0x418 / 4, DRAM_ID2(16) }, // emc_pmacro_ib_ddll_long_dqs_rank1_3. + { 0x00180018, 0x41C / 4, DRAM_ID2(16) }, // emc_pmacro_ddll_long_cmd_0. + { 0x000F000F, 0x420 / 4, DRAM_ID2(16) }, // emc_pmacro_ddll_long_cmd_1. + { 0x00000018, 0x42C / 4, DRAM_ID2(16) }, // emc_pmacro_ddll_long_cmd_4. + { 0x2A800000, 0x6DC / 4, DRAM_ID2(16) }, // mc_video_protect_gpu_override0. + { 0x00000002, 0x6E0 / 4, DRAM_ID2(16) }, // mc_video_protect_gpu_override1. + + // Samsung LPDDR4X 4GB 10nm-class (1y) Die-X for Iowa, Hoag and SDS. + { 0x05500000, 0x0D4 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_auto_cal_config2. + { 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_auto_cal_vref_sel0. + { 0x00000006, 0x1CC / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_quse. + { 0x00000005, 0x1D0 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_quse_width. + { 0x00000003, 0x1DC / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_einput. + { 0x0000000C, 0x1E0 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_einput_duration. + { 0x88161414, 0x2E0 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_mrw14. + { 0x80000713, 0x32C / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_dyn_self_ref_control. + { 0x2A800000, 0x6DC / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // mc_video_protect_gpu_override0. + { 0x00000002, 0x6E0 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // mc_video_protect_gpu_override1. + + // Samsung LPDDR4X 8GB 10nm-class (1y) Die-X for SDEV Iowa and SDS. + { 0x05500000, 0x0D4 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_auto_cal_config2. + { 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_auto_cal_vref_sel0. + { 0x00000001, 0x134 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_adr_cfg. 2 populated DRAM Devices. + { 0x00000006, 0x1CC / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_quse. + { 0x00000005, 0x1D0 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_quse_width. + { 0x00000003, 0x1DC / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_einput. + { 0x0000000C, 0x1E0 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_einput_duration. + { 0x00000008, 0x24C / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_tfaw. + { 0x08010004, 0x2B8 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw1. + { 0x08020000, 0x2BC / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw2. + { 0x080D0000, 0x2C0 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw3. + { 0x08033131, 0x2C8 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw6. + { 0x080B0000, 0x2CC / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw8. + { 0x0C0E5D5D, 0x2D0 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw9. + { 0x080C5D5D, 0x2D4 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw10. + { 0x0C0D0808, 0x2D8 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw12. + { 0x0C0D0000, 0x2DC / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw13. + { 0x08161414, 0x2E0 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw14. + { 0x08010004, 0x2E4 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw_extra. + { 0x00000000, 0x340 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_dev_select. Both devices. + { 0x0051004F, 0x450 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_zcal_mrw_cmd. + { 0x40000001, 0x45C / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_zcal_init_dev1. + { 0x00000000, 0x594 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_pmacro_tx_pwrd4. + { 0x00001000, 0x598 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_pmacro_tx_pwrd5. + { 0x00000001, 0x630 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_adr_cfg. 2 populated DRAM Devices. + { 0x00002000, 0x64C / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_cfg. 8GB total density. + { 0x00000001, 0x670 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_arb_timing_faw. + { 0x00000002, 0x680 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_arb_timing_r2r. + { 0x02020001, 0x694 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_arb_da_turns. + { 0x2A800000, 0x6DC / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_video_protect_gpu_override0. + { 0x00000002, 0x6E0 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_video_protect_gpu_override1. + + // Samsung LPDDR4X 4GB 10nm-class (1y) Die-Y for Iowa. + { 0x05500000, 0x0D4 / 4, DRAM_ID2(20) }, // emc_auto_cal_config2. + { 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(20) }, // emc_auto_cal_vref_sel0. + { 0x00000008, 0x24C / 4, DRAM_ID2(20) }, // emc_tfaw. + { 0x88161414, 0x2E0 / 4, DRAM_ID2(20) }, // emc_mrw14. + { 0x80000713, 0x32C / 4, DRAM_ID2(20) }, // emc_dyn_self_ref_control. + { 0x000F0018, 0x3AC / 4, DRAM_ID2(20) }, // emc_pmacro_ob_ddll_long_dq_rank0_4. + { 0x000F0018, 0x3C4 / 4, DRAM_ID2(20) }, // emc_pmacro_ob_ddll_long_dq_rank1_4. + { 0x00440048, 0x3CC / 4, DRAM_ID2(20) }, // emc_pmacro_ob_ddll_long_dqs_rank0_0. + { 0x00440045, 0x3D0 / 4, DRAM_ID2(20) }, // emc_pmacro_ob_ddll_long_dqs_rank0_1. + { 0x00470047, 0x3D4 / 4, DRAM_ID2(20) }, // emc_pmacro_ob_ddll_long_dqs_rank0_2. + { 0x0005000D, 0x3DC / 4, DRAM_ID2(20) }, // emc_pmacro_ob_ddll_long_dqs_rank0_4. + { 0x00440048, 0x3E4 / 4, DRAM_ID2(20) }, // emc_pmacro_ob_ddll_long_dqs_rank1_0. + { 0x00440045, 0x3E8 / 4, DRAM_ID2(20) }, // emc_pmacro_ob_ddll_long_dqs_rank1_1. + { 0x00470047, 0x3EC / 4, DRAM_ID2(20) }, // emc_pmacro_ob_ddll_long_dqs_rank1_2. + { 0x0005000D, 0x3F4 / 4, DRAM_ID2(20) }, // emc_pmacro_ob_ddll_long_dqs_rank1_4. + { 0x00180018, 0x41C / 4, DRAM_ID2(20) }, // emc_pmacro_ddll_long_cmd_0. + { 0x000F000F, 0x420 / 4, DRAM_ID2(20) }, // emc_pmacro_ddll_long_cmd_1. + { 0x00000018, 0x42C / 4, DRAM_ID2(20) }, // emc_pmacro_ddll_long_cmd_4. + { 0x00000001, 0x670 / 4, DRAM_ID2(20) }, // mc_emem_arb_timing_faw. + { 0x2A800000, 0x6DC / 4, DRAM_ID2(20) }, // mc_video_protect_gpu_override0. + { 0x00000002, 0x6E0 / 4, DRAM_ID2(20) }, // mc_video_protect_gpu_override1. + + // Samsung LPDDR4X 8GB 10nm-class (1y) Die-Y for SDEV Iowa. + { 0x05500000, 0x0D4 / 4, DRAM_ID2(21) }, // emc_auto_cal_config2. + { 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(21) }, // emc_auto_cal_vref_sel0. + { 0x00000001, 0x134 / 4, DRAM_ID2(21) }, // emc_adr_cfg. 2 populated DRAM Devices. + { 0x00000008, 0x24C / 4, DRAM_ID2(21) }, // emc_tfaw. + { 0x08010004, 0x2B8 / 4, DRAM_ID2(21) }, // emc_mrw1. + { 0x08020000, 0x2BC / 4, DRAM_ID2(21) }, // emc_mrw2. + { 0x080D0000, 0x2C0 / 4, DRAM_ID2(21) }, // emc_mrw3. + { 0x08033131, 0x2C8 / 4, DRAM_ID2(21) }, // emc_mrw6. + { 0x080B0000, 0x2CC / 4, DRAM_ID2(21) }, // emc_mrw8. + { 0x0C0E5D5D, 0x2D0 / 4, DRAM_ID2(21) }, // emc_mrw9. + { 0x080C5D5D, 0x2D4 / 4, DRAM_ID2(21) }, // emc_mrw10. + { 0x0C0D0808, 0x2D8 / 4, DRAM_ID2(21) }, // emc_mrw12. + { 0x0C0D0000, 0x2DC / 4, DRAM_ID2(21) }, // emc_mrw13. + { 0x08161414, 0x2E0 / 4, DRAM_ID2(21) }, // emc_mrw14. + { 0x08010004, 0x2E4 / 4, DRAM_ID2(21) }, // emc_mrw_extra. + { 0x00000000, 0x340 / 4, DRAM_ID2(21) }, // emc_dev_select. Both devices. + { 0x32323232, 0x350 / 4, DRAM_ID2(21) }, // emc_pmacro_ib_vref_dq_0. + { 0x32323232, 0x354 / 4, DRAM_ID2(21) }, // emc_pmacro_ib_vref_dq_1. + { 0x000F0018, 0x3AC / 4, DRAM_ID2(21) }, // emc_pmacro_ob_ddll_long_dq_rank0_4. + { 0x000F0018, 0x3C4 / 4, DRAM_ID2(21) }, // emc_pmacro_ob_ddll_long_dq_rank1_4. + { 0x00440048, 0x3CC / 4, DRAM_ID2(21) }, // emc_pmacro_ob_ddll_long_dqs_rank0_0. + { 0x00440045, 0x3D0 / 4, DRAM_ID2(21) }, // emc_pmacro_ob_ddll_long_dqs_rank0_1. + { 0x00470047, 0x3D4 / 4, DRAM_ID2(21) }, // emc_pmacro_ob_ddll_long_dqs_rank0_2. + { 0x0005000D, 0x3DC / 4, DRAM_ID2(21) }, // emc_pmacro_ob_ddll_long_dqs_rank0_4. + { 0x00440048, 0x3E4 / 4, DRAM_ID2(21) }, // emc_pmacro_ob_ddll_long_dqs_rank1_0. + { 0x00440045, 0x3E8 / 4, DRAM_ID2(21) }, // emc_pmacro_ob_ddll_long_dqs_rank1_1. + { 0x00470047, 0x3EC / 4, DRAM_ID2(21) }, // emc_pmacro_ob_ddll_long_dqs_rank1_2. + { 0x0005000D, 0x3F4 / 4, DRAM_ID2(21) }, // emc_pmacro_ob_ddll_long_dqs_rank1_4. + { 0x00180018, 0x41C / 4, DRAM_ID2(21) }, // emc_pmacro_ddll_long_cmd_0. + { 0x000F000F, 0x420 / 4, DRAM_ID2(21) }, // emc_pmacro_ddll_long_cmd_1. + { 0x00000018, 0x42C / 4, DRAM_ID2(21) }, // emc_pmacro_ddll_long_cmd_4. + { 0x0051004F, 0x450 / 4, DRAM_ID2(21) }, // emc_zcal_mrw_cmd. + { 0x40000001, 0x45C / 4, DRAM_ID2(21) }, // emc_zcal_init_dev1. + { 0x00000000, 0x594 / 4, DRAM_ID2(21) }, // emc_pmacro_tx_pwrd4. + { 0x00001000, 0x598 / 4, DRAM_ID2(21) }, // emc_pmacro_tx_pwrd5. + { 0x00000001, 0x630 / 4, DRAM_ID2(21) }, // mc_emem_adr_cfg. 2 populated DRAM Devices. + { 0x00002000, 0x64C / 4, DRAM_ID2(21) }, // mc_emem_cfg. 8GB total density. + { 0x00000001, 0x670 / 4, DRAM_ID2(21) }, // mc_emem_arb_timing_faw. + { 0x00000002, 0x680 / 4, DRAM_ID2(21) }, // mc_emem_arb_timing_r2r. + { 0x02020001, 0x694 / 4, DRAM_ID2(21) }, // mc_emem_arb_da_turns. + { 0x2A800000, 0x6DC / 4, DRAM_ID2(21) }, // mc_video_protect_gpu_override0. + { 0x00000002, 0x6E0 / 4, DRAM_ID2(21) }, // mc_video_protect_gpu_override1. + + // Samsung LPDDR4X 4GB 10nm-class (1y) Die-A for Unknown SDS. + { 0x05500000, 0x0D4 / 4, DRAM_ID2(22) }, // emc_auto_cal_config2. + { 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(22) }, // emc_auto_cal_vref_sel0. + { 0x00000008, 0x24C / 4, DRAM_ID2(22) }, // emc_tfaw. + { 0x1C041B06, 0x26C / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd0_0. + { 0x02050307, 0x270 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd0_1. + { 0x03252500, 0x274 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd0_2. + { 0x081D1E00, 0x278 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd1_0. + { 0x090C0A0D, 0x27C / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd1_1. + { 0x0526260B, 0x280 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd1_2. + { 0x05030402, 0x284 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd2_0. + { 0x1B1C0600, 0x288 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd2_1. + { 0x07252507, 0x28C / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd2_2. + { 0x0C1D0B0A, 0x290 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd3_0. + { 0x0800090D, 0x294 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd3_1. + { 0x0926261E, 0x298 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd3_2. + { 0x2A080624, 0x29C / 4, DRAM_ID2(22) }, // emc_cmd_mapping_byte. + { 0x88161414, 0x2E0 / 4, DRAM_ID2(22) }, // emc_mrw14. + { 0x80000713, 0x32C / 4, DRAM_ID2(22) }, // emc_dyn_self_ref_control. + { 0x00140010, 0x3AC / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dq_rank0_4. + { 0x0013000B, 0x3B0 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dq_rank0_5. + { 0x00140010, 0x3C4 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dq_rank1_4. + { 0x0013000B, 0x3C8 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dq_rank1_5. + { 0x00450047, 0x3CC / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank0_0. + { 0x004D004F, 0x3D0 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank0_1. + { 0x00460046, 0x3D4 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank0_2. + { 0x00480048, 0x3D8 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank0_3. + { 0x000C0008, 0x3DC / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank0_4. + { 0x000B000C, 0x3E0 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank0_5. + { 0x00450047, 0x3E4 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank1_0. + { 0x004D004F, 0x3E8 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank1_1. + { 0x00460046, 0x3EC / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank1_2. + { 0x00480048, 0x3F0 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank1_3. + { 0x000C0008, 0x3F4 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank1_4. + { 0x000B000C, 0x3F8 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank1_5. + { 0x00100010, 0x41C / 4, DRAM_ID2(22) }, // emc_pmacro_ddll_long_cmd_0. + { 0x00140014, 0x420 / 4, DRAM_ID2(22) }, // emc_pmacro_ddll_long_cmd_1. + { 0x00130013, 0x428 / 4, DRAM_ID2(22) }, // emc_pmacro_ddll_long_cmd_3. + { 0x00000010, 0x42C / 4, DRAM_ID2(22) }, // emc_pmacro_ddll_long_cmd_4. + { 0x40280100, 0x4B4 / 4, DRAM_ID2(22) }, // pmc_ddr_cfg. + { 0x4F9F9FFF, 0x4B8 / 4, DRAM_ID2(22) }, // pmc_io_dpd3_req. + { 0x64032157, 0x4D8 / 4, DRAM_ID2(22) }, // emc_swizzle_rank0_byte0. + { 0x51320467, 0x4DC / 4, DRAM_ID2(22) }, // emc_swizzle_rank0_byte1. + { 0x04735621, 0x4E0 / 4, DRAM_ID2(22) }, // emc_swizzle_rank0_byte2. + { 0x47356012, 0x4E4 / 4, DRAM_ID2(22) }, // emc_swizzle_rank0_byte3. + { 0x12045673, 0x4E8 / 4, DRAM_ID2(22) }, // emc_swizzle_rank1_byte0. + { 0x43657210, 0x4EC / 4, DRAM_ID2(22) }, // emc_swizzle_rank1_byte1. + { 0x65402137, 0x4F0 / 4, DRAM_ID2(22) }, // emc_swizzle_rank1_byte2. + { 0x57302164, 0x4F4 / 4, DRAM_ID2(22) }, // emc_swizzle_rank1_byte3. + { 0x4F9F9FFF, 0x534 / 4, DRAM_ID2(22) }, // emc_pmc_scratch1. + { 0x4033CF1F, 0x53C / 4, DRAM_ID2(22) }, // emc_pmc_scratch3. + { 0x10000000, 0x590 / 4, DRAM_ID2(22) }, // emc_pmacro_tx_pwrd3. + { 0x00030108, 0x594 / 4, DRAM_ID2(22) }, // emc_pmacro_tx_pwrd4. + { 0x01400050, 0x598 / 4, DRAM_ID2(22) }, // emc_pmacro_tx_pwrd5. + { 0x29081081, 0x5A0 / 4, DRAM_ID2(22) }, // emc_pmacro_brick_mapping0. + { 0x54A59332, 0x5A4 / 4, DRAM_ID2(22) }, // emc_pmacro_brick_mapping1. + { 0x87766B4A, 0x5A8 / 4, DRAM_ID2(22) }, // emc_pmacro_brick_mapping2. + { 0x00000001, 0x670 / 4, DRAM_ID2(22) }, // mc_emem_arb_timing_faw. + { 0xE4FACB43, 0x6D4 / 4, DRAM_ID2(22) }, // mc_video_protect_vpr_override. + TSEC, NVENC. + { 0x0600FED3, 0x6D8 / 4, DRAM_ID2(22) }, // mc_video_protect_vpr_override1. + TSECB, TSEC1, TSECB1. + { 0x2A800000, 0x6DC / 4, DRAM_ID2(22) }, // mc_video_protect_gpu_override0. + { 0x00000002, 0x6E0 / 4, DRAM_ID2(22) }, // mc_video_protect_gpu_override1. + { 0x0000009C, 0x814 / 4, DRAM_ID2(22) }, // swizzle_rank_byte_encode. + + // Micron LPDDR4X 4GB 10nm-class (1y) Die-A for Unknown Iowa/Hoag/SDS. + { 0x05500000, 0x0D4 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_auto_cal_config2. + { 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_auto_cal_vref_sel0. + { 0x00000006, 0x1CC / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_quse. + { 0x00000005, 0x1D0 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_quse_width. + { 0x00000003, 0x1DC / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_einput. + { 0x0000000C, 0x1E0 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_einput_duration. + { 0x00000008, 0x24C / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_tfaw. + { 0x88161414, 0x2E0 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_mrw14. + { 0x80000713, 0x32C / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_dyn_self_ref_control. + { 0x00000001, 0x670 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // mc_emem_arb_timing_faw. + { 0x2A800000, 0x6DC / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // mc_video_protect_gpu_override0. + { 0x00000002, 0x6E0 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // mc_video_protect_gpu_override1. +}; diff --git a/bdk/mem/sdram_lp0.c b/bdk/mem/sdram_lp0.c index 2a83c27..1c6e7e3 100644 --- a/bdk/mem/sdram_lp0.c +++ b/bdk/mem/sdram_lp0.c @@ -2,7 +2,7 @@ * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. * Copyright 2014 Google Inc. * Copyright (c) 2018 naehrwert - * Copyright (c) 2018 CTCaer + * Copyright (c) 2018-2020 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,16 +17,7 @@ #include #include #include - -/* - * This function reads SDRAM parameters from the common BCT format and - * writes them into PMC scratch registers (where the BootROM expects them - * on LP0 resume). - */ -void sdram_lp0_save_params(const void *params) -{ - struct sdram_params *sdram = (struct sdram_params *)params; - struct tegra_pmc_regs *pmc = (struct tegra_pmc_regs *)PMC_BASE; +#include #define pack(src, src_bits, dst, dst_bits) { \ u32 mask = 0xffffffff >> (31 - ((1 ? src_bits) - (0 ? src_bits))); \ @@ -46,6 +37,16 @@ void sdram_lp0_save_params(const void *params) /* 32 bits version c macro */ #define c32(value, pmcreg) pmc->pmcreg = value +/* + * This function reads SDRAM parameters from the common BCT format and + * writes them into PMC scratch registers (where the BootROM expects them + * on LP0 resume). + */ +static void _sdram_lp0_save_params_t210(const void *params) +{ + struct sdram_params_t210 *sdram = (struct sdram_params_t210 *)params; + struct tegra_pmc_regs *pmc = (struct tegra_pmc_regs *)PMC_BASE; + //TODO: pkg1.1 (1.X - 3.X) reads them from MC. // Patch carveout parameters. /*sdram->McGeneralizedCarveout1Bom = 0; @@ -1124,3 +1125,414 @@ void sdram_lp0_save_params(const void *params) c32(0, scratch4); s(PllMStableTime, 9:0, scratch4, 9:0); } + +// #pragma GCC diagnostic ignored "-Wparentheses" + +// static void _sdram_lp0_save_params_t210b01(const void *params) +// { +// struct sdram_params_t210b01 *sdram = (struct sdram_params_t210b01 *)params; +// struct tegra_pmc_regs *pmc = (struct tegra_pmc_regs *)PMC_BASE; + +// u32 tmp = 0; + +// sdram->mc_generalized_carveout1_cfg0 = 0; +// sdram->mc_generalized_carveout2_cfg0 = 0; +// sdram->mc_generalized_carveout3_cfg0 = 0; +// sdram->mc_generalized_carveout4_cfg0 = 0; +// sdram->mc_generalized_carveout5_cfg0 = 0; + +// // Patch SDRAM parameters. +// u32 t0 = sdram->emc_swizzle_rank0_byte0 << 5 >> 29 > sdram->emc_swizzle_rank0_byte0 << 1 >> 29; +// u32 t1 = (t0 & 0xFFFFFFEF) | ((sdram->emc_swizzle_rank1_byte0 << 5 >> 29 > sdram->emc_swizzle_rank1_byte0 << 1 >> 29) << 4); +// u32 t2 = (t1 & 0xFFFFFFFD) | ((sdram->emc_swizzle_rank0_byte1 << 5 >> 29 > sdram->emc_swizzle_rank0_byte1 << 1 >> 29) << 1); +// u32 t3 = (t2 & 0xFFFFFFDF) | ((sdram->emc_swizzle_rank1_byte1 << 5 >> 29 > sdram->emc_swizzle_rank1_byte1 << 1 >> 29) << 5); +// u32 t4 = (t3 & 0xFFFFFFFB) | ((sdram->emc_swizzle_rank0_byte2 << 5 >> 29 > sdram->emc_swizzle_rank0_byte2 << 1 >> 29) << 2); +// u32 t5 = (t4 & 0xFFFFFFBF) | ((sdram->emc_swizzle_rank1_byte2 << 5 >> 29 > sdram->emc_swizzle_rank1_byte2 << 1 >> 29) << 6); +// u32 t6 = (t5 & 0xFFFFFFF7) | ((sdram->emc_swizzle_rank0_byte3 << 5 >> 29 > sdram->emc_swizzle_rank0_byte3 << 1 >> 29) << 3); +// u32 t7 = (t6 & 0xFFFFFF7F) | ((sdram->emc_swizzle_rank1_byte3 << 5 >> 29 > sdram->emc_swizzle_rank1_byte3 << 1 >> 29) << 7); +// sdram->swizzle_rank_byte_encode = t7; +// sdram->emc_bct_spare2 = 0x40000DD8; +// sdram->emc_bct_spare3 = t7; + +// s(emc_clock_source, 7:0, scratch6, 15:8); +// s(emc_clock_source_dll, 7:0, scratch6, 23:16); +// s(emc_clock_source, 31:29, scratch6, 26:24); +// s(emc_clock_source_dll, 31:29, scratch6, 29:27); +// s(emc_clock_source_dll, 11:10, scratch6, 31:30); +// pmc->scratch7 = (sdram->emc_rc << 24) | ((sdram->emc_zqcal_lpddr4_warm_boot << 27 >> 31 << 23) | ((sdram->emc_zqcal_lpddr4_warm_boot << 30 >> 31 << 22) | ((sdram->emc_zqcal_lpddr4_warm_boot << 21) & 0x3FFFFF | ((sdram->clk_rst_pllm_misc20_override << 20) & 0x1FFFFF | ((sdram->clk_rst_pllm_misc20_override << 28 >> 31 << 19) | ((sdram->clk_rst_pllm_misc20_override << 27 >> 31 << 18) | ((sdram->clk_rst_pllm_misc20_override << 26 >> 31 << 17) | ((sdram->clk_rst_pllm_misc20_override << 21 >> 31 << 16) | ((sdram->clk_rst_pllm_misc20_override << 20 >> 31 << 15) | ((sdram->clk_rst_pllm_misc20_override << 19 >> 31 << 14) | ((sdram->clk_rst_pllm_misc20_override << 18 >> 31 << 13) | ((sdram->emc_clock_source << 15 >> 31 << 12) | ((sdram->emc_clock_source << 11 >> 31 << 11) | ((sdram->emc_clock_source << 12 >> 31 << 10) | ((sdram->emc_clock_source << 6 >> 31 << 9) | ((sdram->emc_clock_source << 16 >> 31 << 8) | ((32 * sdram->emc_clock_source >> 31 << 7) | ((16 * sdram->emc_clock_source >> 31 << 6) | (16 * (sdram->emc_zqcal_lpddr4_warm_boot >> 30) | (4 * (sdram->clk_rst_pllm_misc20_override << 29 >> 30) | ((sdram->clk_rst_pllm_misc20_override << 22 >> 30) | 4 * (pmc->scratch7 >> 2)) & 0xFFFFFFF3) & 0xFFFFFFCF) & 0xFFFFFFBF) & 0xFFFFFF7F) & 0xFFFFFEFF) & 0xFFFFFDFF) & 0xFFFFFBFF) & 0xFFFFF7FF) & 0xFFFFEFFF) & 0xFFFFDFFF) & 0xFFFFBFFF) & 0xFFFF7FFF) & 0xFFFEFFFF) & 0xFFFDFFFF) & 0xFFFBFFFF) & 0xFFF7FFFF) & 0xFFEFFFFF) & 0xFFDFFFFF) & 0xFFBFFFFF) & 0xFF7FFFFF) & 0xFFFFFF; +// pmc->scratch8 = (sdram->emc_pmacro_bg_bias_ctrl0 << 18 >> 30 << 30) | ((4 * pmc->scratch8) >> 2); +// pmc->scratch14 = ((u8)(sdram->emc_cfg_pipe_clk) << 31) | (2 * (((u8)(sdram->emc_fdpd_ctrl_cmd_no_ramp) << 30) | pmc->scratch14 & 0xBFFFFFFF) >> 1); +// s(emc_qrst, 6:0, scratch15, 26:20); +// s(emc_qrst, 20:16, scratch15, 31:27); +// s(emc_pmacro_cmd_tx_drive, 5:0, scratch16, 25:20); +// s(emc_pmacro_cmd_tx_drive, 13:8, scratch16, 31:26); +// pmc->scratch17 = (16 * sdram->emc_fbio_cfg8 >> 31 << 31) | (2 * ((32 * sdram->emc_fbio_cfg8 >> 31 << 30) | ((sdram->emc_fbio_cfg8 << 6 >> 31 << 29) | ((sdram->emc_fbio_cfg8 << 7 >> 31 << 28) | ((sdram->emc_fbio_cfg8 << 8 >> 31 << 27) | ((sdram->emc_fbio_cfg8 << 9 >> 31 << 26) | ((sdram->emc_fbio_cfg8 << 10 >> 31 << 25) | ((sdram->emc_fbio_cfg8 << 11 >> 31 << 24) | ((sdram->emc_fbio_cfg8 << 12 >> 31 << 23) | ((sdram->emc_fbio_cfg8 << 13 >> 31 << 22) | ((sdram->emc_fbio_cfg8 << 14 >> 31 << 21) | ((sdram->emc_fbio_cfg8 << 15 >> 31 << 20) | pmc->scratch17 & 0xFFEFFFFF) & 0xFFDFFFFF) & 0xFFBFFFFF) & 0xFF7FFFFF) & 0xFEFFFFFF) & 0xFDFFFFFF) & 0xFBFFFFFF) & 0xF7FFFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch18 = ((u16)(sdram->emc_txsr_dll) << 20) | pmc->scratch18 & 0xFFFFF; +// pmc->scratch19 = (sdram->emc_txdsrvttgen << 20) | pmc->scratch19 & 0xFFFFF; +// s32(emc_cfg_rsv, scratch22); +// s32(emc_auto_cal_config, scratch23); +// s32(emc_auto_cal_vref_sel0, scratch24); +// s32(emc_pmacro_brick_ctrl_rfu1, scratch25); +// s32(emc_pmacro_brick_ctrl_rfu2, scratch26); +// s32(emc_pmc_scratch1, scratch27); +// s32(emc_pmc_scratch2, scratch28); +// s32(emc_pmc_scratch3, scratch29); +// pmc->scratch30 = (sdram->emc_pmacro_perbit_rfu_ctrl0 >> 30 << 30) | (4 * ((4 * sdram->emc_pmacro_perbit_rfu_ctrl0 >> 30 << 28) | ((16 * sdram->emc_pmacro_perbit_rfu_ctrl0 >> 30 << 26) | ((sdram->emc_pmacro_perbit_rfu_ctrl0 << 6 >> 30 << 24) | ((sdram->emc_pmacro_perbit_rfu_ctrl0 << 8 >> 30 << 22) | ((sdram->emc_pmacro_perbit_rfu_ctrl0 << 10 >> 30 << 20) | ((sdram->emc_pmacro_perbit_rfu_ctrl0 << 12 >> 30 << 18) | ((sdram->emc_pmacro_perbit_rfu_ctrl0 << 14 >> 30 << 16) | ((sdram->emc_pmacro_perbit_rfu_ctrl0 << 16 >> 30 << 14) | ((sdram->emc_pmacro_perbit_rfu_ctrl0 << 18 >> 30 << 12) | ((sdram->emc_pmacro_perbit_rfu_ctrl0 << 20 >> 30 << 10) | ((sdram->emc_pmacro_perbit_rfu_ctrl0 << 22 >> 30 << 8) | ((sdram->emc_pmacro_perbit_rfu_ctrl0 << 24 >> 30 << 6) | (16 * (sdram->emc_pmacro_perbit_rfu_ctrl0 << 26 >> 30) | (4 * (sdram->emc_pmacro_perbit_rfu_ctrl0 << 28 >> 30) | (sdram->emc_pmacro_perbit_rfu_ctrl0 & 3 | 4 * (pmc->scratch30 >> 2)) & 0xFFFFFFF3) & 0xFFFFFFCF) & 0xFFFFFF3F) & 0xFFFFFCFF) & 0xFFFFF3FF) & 0xFFFFCFFF) & 0xFFFF3FFF) & 0xFFFCFFFF) & 0xFFF3FFFF) & 0xFFCFFFFF) & 0xFF3FFFFF) & 0xFCFFFFFF) & 0xF3FFFFFF) & 0xCFFFFFFF) >> 2); +// pmc->scratch31 = (sdram->emc_pmacro_perbit_rfu_ctrl1 >> 30 << 30) | (4 * ((4 * sdram->emc_pmacro_perbit_rfu_ctrl1 >> 30 << 28) | ((16 * sdram->emc_pmacro_perbit_rfu_ctrl1 >> 30 << 26) | ((sdram->emc_pmacro_perbit_rfu_ctrl1 << 6 >> 30 << 24) | ((sdram->emc_pmacro_perbit_rfu_ctrl1 << 8 >> 30 << 22) | ((sdram->emc_pmacro_perbit_rfu_ctrl1 << 10 >> 30 << 20) | ((sdram->emc_pmacro_perbit_rfu_ctrl1 << 12 >> 30 << 18) | ((sdram->emc_pmacro_perbit_rfu_ctrl1 << 14 >> 30 << 16) | ((sdram->emc_pmacro_perbit_rfu_ctrl1 << 16 >> 30 << 14) | ((sdram->emc_pmacro_perbit_rfu_ctrl1 << 18 >> 30 << 12) | ((sdram->emc_pmacro_perbit_rfu_ctrl1 << 20 >> 30 << 10) | ((sdram->emc_pmacro_perbit_rfu_ctrl1 << 22 >> 30 << 8) | ((sdram->emc_pmacro_perbit_rfu_ctrl1 << 24 >> 30 << 6) | (16 * (sdram->emc_pmacro_perbit_rfu_ctrl1 << 26 >> 30) | (4 * (sdram->emc_pmacro_perbit_rfu_ctrl1 << 28 >> 30) | (sdram->emc_pmacro_perbit_rfu_ctrl1 & 3 | 4 * (pmc->scratch31 >> 2)) & 0xFFFFFFF3) & 0xFFFFFFCF) & 0xFFFFFF3F) & 0xFFFFFCFF) & 0xFFFFF3FF) & 0xFFFFCFFF) & 0xFFFF3FFF) & 0xFFFCFFFF) & 0xFFF3FFFF) & 0xFFCFFFFF) & 0xFF3FFFFF) & 0xFCFFFFFF) & 0xF3FFFFFF) & 0xCFFFFFFF) >> 2); +// pmc->scratch32 = (sdram->emc_pmacro_perbit_rfu_ctrl2 >> 30 << 30) | (4 * ((4 * sdram->emc_pmacro_perbit_rfu_ctrl2 >> 30 << 28) | ((16 * sdram->emc_pmacro_perbit_rfu_ctrl2 >> 30 << 26) | ((sdram->emc_pmacro_perbit_rfu_ctrl2 << 6 >> 30 << 24) | ((sdram->emc_pmacro_perbit_rfu_ctrl2 << 8 >> 30 << 22) | ((sdram->emc_pmacro_perbit_rfu_ctrl2 << 10 >> 30 << 20) | ((sdram->emc_pmacro_perbit_rfu_ctrl2 << 12 >> 30 << 18) | ((sdram->emc_pmacro_perbit_rfu_ctrl2 << 14 >> 30 << 16) | ((sdram->emc_pmacro_perbit_rfu_ctrl2 << 16 >> 30 << 14) | ((sdram->emc_pmacro_perbit_rfu_ctrl2 << 18 >> 30 << 12) | ((sdram->emc_pmacro_perbit_rfu_ctrl2 << 20 >> 30 << 10) | ((sdram->emc_pmacro_perbit_rfu_ctrl2 << 22 >> 30 << 8) | ((sdram->emc_pmacro_perbit_rfu_ctrl2 << 24 >> 30 << 6) | (16 * (sdram->emc_pmacro_perbit_rfu_ctrl2 << 26 >> 30) | (4 * (sdram->emc_pmacro_perbit_rfu_ctrl2 << 28 >> 30) | (sdram->emc_pmacro_perbit_rfu_ctrl2 & 3 | 4 * (pmc->scratch32 >> 2)) & 0xFFFFFFF3) & 0xFFFFFFCF) & 0xFFFFFF3F) & 0xFFFFFCFF) & 0xFFFFF3FF) & 0xFFFFCFFF) & 0xFFFF3FFF) & 0xFFFCFFFF) & 0xFFF3FFFF) & 0xFFCFFFFF) & 0xFF3FFFFF) & 0xFCFFFFFF) & 0xF3FFFFFF) & 0xCFFFFFFF) >> 2); +// pmc->scratch33 = (sdram->emc_pmacro_perbit_rfu_ctrl3 >> 30 << 30) | (4 * ((4 * sdram->emc_pmacro_perbit_rfu_ctrl3 >> 30 << 28) | ((16 * sdram->emc_pmacro_perbit_rfu_ctrl3 >> 30 << 26) | ((sdram->emc_pmacro_perbit_rfu_ctrl3 << 6 >> 30 << 24) | ((sdram->emc_pmacro_perbit_rfu_ctrl3 << 8 >> 30 << 22) | ((sdram->emc_pmacro_perbit_rfu_ctrl3 << 10 >> 30 << 20) | ((sdram->emc_pmacro_perbit_rfu_ctrl3 << 12 >> 30 << 18) | ((sdram->emc_pmacro_perbit_rfu_ctrl3 << 14 >> 30 << 16) | ((sdram->emc_pmacro_perbit_rfu_ctrl3 << 16 >> 30 << 14) | ((sdram->emc_pmacro_perbit_rfu_ctrl3 << 18 >> 30 << 12) | ((sdram->emc_pmacro_perbit_rfu_ctrl3 << 20 >> 30 << 10) | ((sdram->emc_pmacro_perbit_rfu_ctrl3 << 22 >> 30 << 8) | ((sdram->emc_pmacro_perbit_rfu_ctrl3 << 24 >> 30 << 6) | (16 * (sdram->emc_pmacro_perbit_rfu_ctrl3 << 26 >> 30) | (4 * (sdram->emc_pmacro_perbit_rfu_ctrl3 << 28 >> 30) | (sdram->emc_pmacro_perbit_rfu_ctrl3 & 3 | 4 * (pmc->scratch33 >> 2)) & 0xFFFFFFF3) & 0xFFFFFFCF) & 0xFFFFFF3F) & 0xFFFFFCFF) & 0xFFFFF3FF) & 0xFFFFCFFF) & 0xFFFF3FFF) & 0xFFFCFFFF) & 0xFFF3FFFF) & 0xFFCFFFFF) & 0xFF3FFFFF) & 0xFCFFFFFF) & 0xF3FFFFFF) & 0xCFFFFFFF) >> 2); +// pmc->scratch40 = (sdram->emc_pmacro_perbit_rfu_ctrl4 >> 30 << 30) | (4 * ((4 * sdram->emc_pmacro_perbit_rfu_ctrl4 >> 30 << 28) | ((16 * sdram->emc_pmacro_perbit_rfu_ctrl4 >> 30 << 26) | ((sdram->emc_pmacro_perbit_rfu_ctrl4 << 6 >> 30 << 24) | ((sdram->emc_pmacro_perbit_rfu_ctrl4 << 8 >> 30 << 22) | ((sdram->emc_pmacro_perbit_rfu_ctrl4 << 10 >> 30 << 20) | ((sdram->emc_pmacro_perbit_rfu_ctrl4 << 12 >> 30 << 18) | ((sdram->emc_pmacro_perbit_rfu_ctrl4 << 14 >> 30 << 16) | ((sdram->emc_pmacro_perbit_rfu_ctrl4 << 16 >> 30 << 14) | ((sdram->emc_pmacro_perbit_rfu_ctrl4 << 18 >> 30 << 12) | ((sdram->emc_pmacro_perbit_rfu_ctrl4 << 20 >> 30 << 10) | ((sdram->emc_pmacro_perbit_rfu_ctrl4 << 22 >> 30 << 8) | ((sdram->emc_pmacro_perbit_rfu_ctrl4 << 24 >> 30 << 6) | (16 * (sdram->emc_pmacro_perbit_rfu_ctrl4 << 26 >> 30) | (4 * (sdram->emc_pmacro_perbit_rfu_ctrl4 << 28 >> 30) | (sdram->emc_pmacro_perbit_rfu_ctrl4 & 3 | 4 * (pmc->scratch40 >> 2)) & 0xFFFFFFF3) & 0xFFFFFFCF) & 0xFFFFFF3F) & 0xFFFFFCFF) & 0xFFFFF3FF) & 0xFFFFCFFF) & 0xFFFF3FFF) & 0xFFFCFFFF) & 0xFFF3FFFF) & 0xFFCFFFFF) & 0xFF3FFFFF) & 0xFCFFFFFF) & 0xF3FFFFFF) & 0xCFFFFFFF) >> 2); +// pmc->scratch42 = (sdram->emc_pmacro_perbit_rfu_ctrl5 >> 30 << 30) | (4 * ((4 * sdram->emc_pmacro_perbit_rfu_ctrl5 >> 30 << 28) | ((16 * sdram->emc_pmacro_perbit_rfu_ctrl5 >> 30 << 26) | ((sdram->emc_pmacro_perbit_rfu_ctrl5 << 6 >> 30 << 24) | ((sdram->emc_pmacro_perbit_rfu_ctrl5 << 8 >> 30 << 22) | ((sdram->emc_pmacro_perbit_rfu_ctrl5 << 10 >> 30 << 20) | ((sdram->emc_pmacro_perbit_rfu_ctrl5 << 12 >> 30 << 18) | ((sdram->emc_pmacro_perbit_rfu_ctrl5 << 14 >> 30 << 16) | ((sdram->emc_pmacro_perbit_rfu_ctrl5 << 16 >> 30 << 14) | ((sdram->emc_pmacro_perbit_rfu_ctrl5 << 18 >> 30 << 12) | ((sdram->emc_pmacro_perbit_rfu_ctrl5 << 20 >> 30 << 10) | ((sdram->emc_pmacro_perbit_rfu_ctrl5 << 22 >> 30 << 8) | ((sdram->emc_pmacro_perbit_rfu_ctrl5 << 24 >> 30 << 6) | (16 * (sdram->emc_pmacro_perbit_rfu_ctrl5 << 26 >> 30) | (4 * (sdram->emc_pmacro_perbit_rfu_ctrl5 << 28 >> 30) | (sdram->emc_pmacro_perbit_rfu_ctrl5 & 3 | 4 * (pmc->scratch42 >> 2)) & 0xFFFFFFF3) & 0xFFFFFFCF) & 0xFFFFFF3F) & 0xFFFFFCFF) & 0xFFFFF3FF) & 0xFFFFCFFF) & 0xFFFF3FFF) & 0xFFFCFFFF) & 0xFFF3FFFF) & 0xFFCFFFFF) & 0xFF3FFFFF) & 0xFCFFFFFF) & 0xF3FFFFFF) & 0xCFFFFFFF) >> 2); +// pmc->scratch44 = (sdram->mc_emem_arb_da_turns >> 24 << 24) | ((sdram->mc_emem_arb_da_turns >> 16 << 16) | ((sdram->mc_emem_arb_da_turns << 16 >> 24 << 8) | (sdram->mc_emem_arb_da_turns & 0xFF | (pmc->scratch44 >> 8 << 8)) & 0xFFFF00FF) & 0xFF00FFFF) & 0xFFFFFF; +// pmc->scratch64 = ((u16)(sdram->mc_emem_arb_misc2) << 31) | (2 * ((sdram->emc_fbio_spare << 30) | ((sdram->emc_fbio_spare << 24 >> 26 << 24) | ((sdram->emc_fbio_spare << 16 >> 24 << 16) | ((sdram->emc_fbio_spare << 8 >> 24 << 8) | ((sdram->emc_fbio_spare >> 24) | (pmc->scratch64 >> 8 << 8)) & 0xFFFF00FF) & 0xFF00FFFF) & 0xC0FFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch65 = ((u16)(sdram->mc_da_cfg0) << 31 >> 1) | ((2 * sdram->mc_emem_arb_misc0 >> 29 << 27) | ((16 * sdram->mc_emem_arb_misc0 >> 31 << 26) | ((32 * sdram->mc_emem_arb_misc0 >> 26 << 20) | ((sdram->mc_emem_arb_misc0 << 11 >> 27 << 15) | ((sdram->mc_emem_arb_misc0 << 17 >> 25 << 8) | ((u8)sdram->mc_emem_arb_misc0 | (pmc->scratch65 >> 8 << 8)) & 0xFFFF80FF) & 0xFFF07FFF) & 0xFC0FFFFF) & 0xFBFFFFFF) & 0xC7FFFFFF) & 0xBFFFFFFF; +// pmc->scratch66 = (sdram->emc_fdpd_ctrl_cmd >> 30 << 27) | ((4 * sdram->emc_fdpd_ctrl_cmd >> 31 << 26) | ((8 * sdram->emc_fdpd_ctrl_cmd >> 27 << 21) | ((sdram->emc_fdpd_ctrl_cmd << 8 >> 28 << 17) | ((sdram->emc_fdpd_ctrl_cmd << 15 >> 27 << 12) | ((sdram->emc_fdpd_ctrl_cmd << 20 >> 28 << 8) | ((u8)sdram->emc_fdpd_ctrl_cmd | (pmc->scratch66 >> 8 << 8)) & 0xFFFFF0FF) & 0xFFFE0FFF) & 0xFFE1FFFF) & 0xFC1FFFFF) & 0xFBFFFFFF) & 0xE7FFFFFF; +// pmc->scratch67 = ((u8)(sdram->emc_burst_refresh_num) << 28) | ((16 * sdram->emc_auto_cal_config2 >> 30 << 26) | ((sdram->emc_auto_cal_config2 << 6 >> 30 << 24) | ((sdram->emc_auto_cal_config2 << 8 >> 30 << 22) | ((sdram->emc_auto_cal_config2 << 10 >> 30 << 20) | ((sdram->emc_auto_cal_config2 << 12 >> 30 << 18) | ((sdram->emc_auto_cal_config2 << 14 >> 30 << 16) | ((sdram->emc_auto_cal_config2 << 16 >> 30 << 14) | ((sdram->emc_auto_cal_config2 << 18 >> 30 << 12) | ((sdram->emc_auto_cal_config2 << 20 >> 30 << 10) | ((sdram->emc_auto_cal_config2 << 22 >> 30 << 8) | ((sdram->emc_auto_cal_config2 << 24 >> 30 << 6) | (16 * (sdram->emc_auto_cal_config2 << 26 >> 30) | (4 * (sdram->emc_auto_cal_config2 << 28 >> 30) | (sdram->emc_auto_cal_config2 & 3 | 4 * (pmc->scratch67 >> 2)) & 0xFFFFFFF3) & 0xFFFFFFCF) & 0xFFFFFF3F) & 0xFFFFFCFF) & 0xFFFFF3FF) & 0xFFFFCFFF) & 0xFFFF3FFF) & 0xFFFCFFFF) & 0xFFF3FFFF) & 0xFFCFFFFF) & 0xFF3FFFFF) & 0xFCFFFFFF) & 0xF3FFFFFF) & 0xFFFFFFF; +// pmc->scratch68 = ((u8)(sdram->emc_tppd) << 28) | ((sdram->emc_cfg_dig_dll >> 31 << 27) | ((2 * sdram->emc_cfg_dig_dll >> 31 << 26) | ((16 * sdram->emc_cfg_dig_dll >> 31 << 25) | ((sdram->emc_cfg_dig_dll << 6 >> 22 << 15) | ((sdram->emc_cfg_dig_dll << 16 >> 31 << 14) | ((sdram->emc_cfg_dig_dll << 17 >> 31 << 13) | ((sdram->emc_cfg_dig_dll << 18 >> 30 << 11) | ((sdram->emc_cfg_dig_dll << 21 >> 29 << 8) | ((sdram->emc_cfg_dig_dll << 24 >> 30 << 6) | (32 * (sdram->emc_cfg_dig_dll << 26 >> 31) | (16 * (sdram->emc_cfg_dig_dll << 27 >> 31) | (8 * (sdram->emc_cfg_dig_dll << 28 >> 31) | (4 * (sdram->emc_cfg_dig_dll << 29 >> 31) | (2 * (sdram->emc_cfg_dig_dll << 30 >> 31) | (sdram->emc_cfg_dig_dll & 1 | 2 * (pmc->scratch68 >> 1)) & 0xFFFFFFFD) & 0xFFFFFFFB) & 0xFFFFFFF7) & 0xFFFFFFEF) & 0xFFFFFFDF) & 0xFFFFFF3F) & 0xFFFFF8FF) & 0xFFFFE7FF) & 0xFFFFDFFF) & 0xFFFFBFFF) & 0xFE007FFF) & 0xFDFFFFFF) & 0xFBFFFFFF) & 0xF7FFFFFF) & 0xFFFFFFF; +// pmc->scratch69 = (sdram->emc_r2r << 28) | ((sdram->emc_fdpd_ctrl_dq >> 30 << 26) | ((8 * sdram->emc_fdpd_ctrl_dq >> 27 << 21) | ((sdram->emc_fdpd_ctrl_dq << 8 >> 28 << 17) | ((sdram->emc_fdpd_ctrl_dq << 15 >> 27 << 12) | ((sdram->emc_fdpd_ctrl_dq << 20 >> 28 << 8) | ((u8)sdram->emc_fdpd_ctrl_dq | (pmc->scratch69 >> 8 << 8)) & 0xFFFFF0FF) & 0xFFFE0FFF) & 0xFFE1FFFF) & 0xFC1FFFFF) & 0xF3FFFFFF) & 0xFFFFFFF; +// pmc->scratch70 = (sdram->emc_w2w << 28) | ((2 * sdram->emc_pmacro_ib_vref_dq_0 >> 25 << 21) | ((sdram->emc_pmacro_ib_vref_dq_0 << 9 >> 25 << 14) | ((sdram->emc_pmacro_ib_vref_dq_0 << 17 >> 25 << 7) | (sdram->emc_pmacro_ib_vref_dq_0 & 0x7F | (pmc->scratch70 >> 7 << 7)) & 0xFFFFC07F) & 0xFFE03FFF) & 0xF01FFFFF) & 0xFFFFFFF; +// pmc->scratch71 = (sdram->emc_pmacro_vttgen_ctrl0 << 12 >> 28 << 28) | ((2 * sdram->emc_pmacro_ib_vref_dq_1 >> 25 << 21) | ((sdram->emc_pmacro_ib_vref_dq_1 << 9 >> 25 << 14) | ((sdram->emc_pmacro_ib_vref_dq_1 << 17 >> 25 << 7) | ((pmc->scratch71 >> 7 << 7) | sdram->emc_pmacro_ib_vref_dq_1 & 0x7F) & 0xFFFFC07F) & 0xFFE03FFF) & 0xF01FFFFF) & 0xFFFFFFF; +// pmc->scratch72 = (((sdram->emc_pmacro_ib_vref_dqs_0 << 17 >> 25 << 7) | ((pmc->scratch72 >> 7 << 7) | sdram->emc_pmacro_ib_vref_dqs_0 & 0x7F) & 0xFFFFC07F) & 0xFFE03FFF | (sdram->emc_pmacro_ib_vref_dqs_0 << 9 >> 25 << 14)) & 0xF01FFFFF | (2 * sdram->emc_pmacro_ib_vref_dqs_0 >> 25 << 21); +// pmc->scratch73 = (2 * sdram->emc_pmacro_ib_vref_dqs_1 >> 25 << 21) | ((sdram->emc_pmacro_ib_vref_dqs_1 << 9 >> 25 << 14) | ((sdram->emc_pmacro_ib_vref_dqs_1 << 17 >> 25 << 7) | ((pmc->scratch73 >> 7 << 7) | sdram->emc_pmacro_ib_vref_dqs_1 & 0x7F) & 0xFFFFC07F) & 0xFFE03FFF) & 0xF01FFFFF; +// pmc->scratch74 = (2 * sdram->emc_pmacro_ddll_short_cmd_0 >> 25 << 21) | ((sdram->emc_pmacro_ddll_short_cmd_0 << 9 >> 25 << 14) | ((sdram->emc_pmacro_ddll_short_cmd_0 << 17 >> 25 << 7) | (sdram->emc_pmacro_ddll_short_cmd_0 & 0x7F | (pmc->scratch74 >> 7 << 7)) & 0xFFFFC07F) & 0xFFE03FFF) & 0xF01FFFFF; +// pmc->scratch75 = (2 * sdram->emc_pmacro_ddll_short_cmd_1 >> 25 << 21) | ((sdram->emc_pmacro_ddll_short_cmd_1 << 9 >> 25 << 14) | ((sdram->emc_pmacro_ddll_short_cmd_1 << 17 >> 25 << 7) | (sdram->emc_pmacro_ddll_short_cmd_1 & 0x7F | (pmc->scratch75 >> 7 << 7)) & 0xFFFFC07F) & 0xFFE03FFF) & 0xF01FFFFF; +// pmc->scratch76 = (sdram->emc_rp << 26) | ((4 * sdram->emc_dll_cfg0 >> 31 << 25) | ((8 * sdram->emc_dll_cfg0 >> 31 << 24) | ((16 * sdram->emc_dll_cfg0 >> 28 << 20) | ((sdram->emc_dll_cfg0 << 8 >> 28 << 16) | ((sdram->emc_dll_cfg0 << 12 >> 28 << 12) | ((sdram->emc_dll_cfg0 << 16 >> 28 << 8) | ((sdram->emc_dll_cfg0 << 20 >> 24) | (pmc->scratch76 >> 8 << 8)) & 0xFFFFF0FF) & 0xFFFF0FFF) & 0xFFF0FFFF) & 0xFF0FFFFF) & 0xFEFFFFFF) & 0xFDFFFFFF) & 0x3FFFFFF; +// tmp = (sdram->emc_pmacro_tx_pwrd0 << 12 >> 31 << 16) | ((sdram->emc_pmacro_tx_pwrd0 << 13 >> 31 << 15) | ((sdram->emc_pmacro_tx_pwrd0 << 14 >> 31 << 14) | ((sdram->emc_pmacro_tx_pwrd0 << 15 >> 31 << 13) | ((sdram->emc_pmacro_tx_pwrd0 << 18 >> 31 << 12) | ((sdram->emc_pmacro_tx_pwrd0 << 19 >> 31 << 11) | ((sdram->emc_pmacro_tx_pwrd0 << 21 >> 31 << 10) | ((sdram->emc_pmacro_tx_pwrd0 << 22 >> 31 << 9) | ((sdram->emc_pmacro_tx_pwrd0 << 23 >> 31 << 8) | ((sdram->emc_pmacro_tx_pwrd0 << 24 >> 31 << 7) | ((sdram->emc_pmacro_tx_pwrd0 << 25 >> 31 << 6) | (32 * (sdram->emc_pmacro_tx_pwrd0 << 26 >> 31) | (16 * (sdram->emc_pmacro_tx_pwrd0 << 27 >> 31) | (8 * (sdram->emc_pmacro_tx_pwrd0 << 28 >> 31) | (4 * (sdram->emc_pmacro_tx_pwrd0 << 29 >> 31) | (2 * (sdram->emc_pmacro_tx_pwrd0 << 30 >> 31) | (sdram->emc_pmacro_tx_pwrd0 & 1 | 2 * (pmc->scratch77 >> 1)) & 0xFFFFFFFD) & 0xFFFFFFFB) & 0xFFFFFFF7) & 0xFFFFFFEF) & 0xFFFFFFDF) & 0xFFFFFFBF) & 0xFFFFFF7F) & 0xFFFFFEFF) & 0xFFFFFDFF) & 0xFFFFFBFF) & 0xFFFFF7FF) & 0xFFFFEFFF) & 0xFFFFDFFF) & 0xFFFFBFFF) & 0xFFFF7FFF) & 0xFFFEFFFF; +// pmc->scratch77 = (sdram->emc_r2w << 26) | ((4 * sdram->emc_pmacro_tx_pwrd0 >> 31 << 25) | ((8 * sdram->emc_pmacro_tx_pwrd0 >> 31 << 24) | ((32 * sdram->emc_pmacro_tx_pwrd0 >> 31 << 23) | ((sdram->emc_pmacro_tx_pwrd0 << 6 >> 31 << 22) | ((sdram->emc_pmacro_tx_pwrd0 << 7 >> 31 << 21) | ((sdram->emc_pmacro_tx_pwrd0 << 8 >> 31 << 20) | ((sdram->emc_pmacro_tx_pwrd0 << 9 >> 31 << 19) | ((sdram->emc_pmacro_tx_pwrd0 << 10 >> 31 << 18) | ((sdram->emc_pmacro_tx_pwrd0 << 11 >> 31 << 17) | tmp & 0xFFFDFFFF) & 0xFFFBFFFF) & 0xFFF7FFFF) & 0xFFEFFFFF) & 0xFFDFFFFF) & 0xFFBFFFFF) & 0xFF7FFFFF) & 0xFEFFFFFF) & 0xFDFFFFFF) & 0x3FFFFFF; +// tmp = ((8 * sdram->emc_pmacro_tx_pwrd1 >> 31 << 24) | ((32 * sdram->emc_pmacro_tx_pwrd1 >> 31 << 23) | ((sdram->emc_pmacro_tx_pwrd1 << 6 >> 31 << 22) | ((sdram->emc_pmacro_tx_pwrd1 << 7 >> 31 << 21) | ((sdram->emc_pmacro_tx_pwrd1 << 8 >> 31 << 20) | ((sdram->emc_pmacro_tx_pwrd1 << 9 >> 31 << 19) | ((sdram->emc_pmacro_tx_pwrd1 << 10 >> 31 << 18) | ((sdram->emc_pmacro_tx_pwrd1 << 11 >> 31 << 17) | ((sdram->emc_pmacro_tx_pwrd1 << 12 >> 31 << 16) | ((sdram->emc_pmacro_tx_pwrd1 << 13 >> 31 << 15) | ((sdram->emc_pmacro_tx_pwrd1 << 14 >> 31 << 14) | ((sdram->emc_pmacro_tx_pwrd1 << 15 >> 31 << 13) | ((sdram->emc_pmacro_tx_pwrd1 << 18 >> 31 << 12) | ((sdram->emc_pmacro_tx_pwrd1 << 19 >> 31 << 11) | ((sdram->emc_pmacro_tx_pwrd1 << 21 >> 31 << 10) | ((sdram->emc_pmacro_tx_pwrd1 << 22 >> 31 << 9) | ((sdram->emc_pmacro_tx_pwrd1 << 23 >> 31 << 8) | ((sdram->emc_pmacro_tx_pwrd1 << 24 >> 31 << 7) | ((sdram->emc_pmacro_tx_pwrd1 << 25 >> 31 << 6) | (32 * (sdram->emc_pmacro_tx_pwrd1 << 26 >> 31) | (16 * (sdram->emc_pmacro_tx_pwrd1 << 27 >> 31) | (8 * (sdram->emc_pmacro_tx_pwrd1 << 28 >> 31) | (4 * (sdram->emc_pmacro_tx_pwrd1 << 29 >> 31) | (2 * (sdram->emc_pmacro_tx_pwrd1 << 30 >> 31) | (sdram->emc_pmacro_tx_pwrd1 & 1 | 2 * (pmc->scratch78 >> 1)) & 0xFFFFFFFD) & 0xFFFFFFFB) & 0xFFFFFFF7) & 0xFFFFFFEF) & 0xFFFFFFDF) & 0xFFFFFFBF) & 0xFFFFFF7F) & 0xFFFFFEFF) & 0xFFFFFDFF) & 0xFFFFFBFF) & 0xFFFFF7FF) & 0xFFFFEFFF) & 0xFFFFDFFF) & 0xFFFFBFFF) & 0xFFFF7FFF) & 0xFFFEFFFF) & 0xFFFDFFFF) & 0xFFFBFFFF) & 0xFFF7FFFF) & 0xFFEFFFFF) & 0xFFDFFFFF) & 0xFFBFFFFF) & 0xFF7FFFFF) & 0xFEFFFFFF) & 0xFDFFFFFF; +// pmc->scratch78 = (sdram->emc_w2r << 26) | ((4 * sdram->emc_pmacro_tx_pwrd1 >> 31 << 25) | tmp) & 0x3FFFFFF; +// tmp = ((8 * sdram->emc_pmacro_tx_pwrd2 >> 31 << 24) | ((32 * sdram->emc_pmacro_tx_pwrd2 >> 31 << 23) | ((sdram->emc_pmacro_tx_pwrd2 << 6 >> 31 << 22) | ((sdram->emc_pmacro_tx_pwrd2 << 7 >> 31 << 21) | ((sdram->emc_pmacro_tx_pwrd2 << 8 >> 31 << 20) | ((sdram->emc_pmacro_tx_pwrd2 << 9 >> 31 << 19) | ((sdram->emc_pmacro_tx_pwrd2 << 10 >> 31 << 18) | ((sdram->emc_pmacro_tx_pwrd2 << 11 >> 31 << 17) | ((sdram->emc_pmacro_tx_pwrd2 << 12 >> 31 << 16) | ((sdram->emc_pmacro_tx_pwrd2 << 13 >> 31 << 15) | ((sdram->emc_pmacro_tx_pwrd2 << 14 >> 31 << 14) | ((sdram->emc_pmacro_tx_pwrd2 << 15 >> 31 << 13) | ((sdram->emc_pmacro_tx_pwrd2 << 18 >> 31 << 12) | ((sdram->emc_pmacro_tx_pwrd2 << 19 >> 31 << 11) | ((sdram->emc_pmacro_tx_pwrd2 << 21 >> 31 << 10) | ((sdram->emc_pmacro_tx_pwrd2 << 22 >> 31 << 9) | ((sdram->emc_pmacro_tx_pwrd2 << 23 >> 31 << 8) | ((sdram->emc_pmacro_tx_pwrd2 << 24 >> 31 << 7) | ((sdram->emc_pmacro_tx_pwrd2 << 25 >> 31 << 6) | (32 * (sdram->emc_pmacro_tx_pwrd2 << 26 >> 31) | (16 * (sdram->emc_pmacro_tx_pwrd2 << 27 >> 31) | (8 * (sdram->emc_pmacro_tx_pwrd2 << 28 >> 31) | (4 * (sdram->emc_pmacro_tx_pwrd2 << 29 >> 31) | (2 * (sdram->emc_pmacro_tx_pwrd2 << 30 >> 31) | (sdram->emc_pmacro_tx_pwrd2 & 1 | 2 * (pmc->scratch79 >> 1)) & 0xFFFFFFFD) & 0xFFFFFFFB) & 0xFFFFFFF7) & 0xFFFFFFEF) & 0xFFFFFFDF) & 0xFFFFFFBF) & 0xFFFFFF7F) & 0xFFFFFEFF) & 0xFFFFFDFF) & 0xFFFFFBFF) & 0xFFFFF7FF) & 0xFFFFEFFF) & 0xFFFFDFFF) & 0xFFFFBFFF) & 0xFFFF7FFF) & 0xFFFEFFFF) & 0xFFFDFFFF) & 0xFFFBFFFF) & 0xFFF7FFFF) & 0xFFEFFFFF) & 0xFFDFFFFF) & 0xFFBFFFFF) & 0xFF7FFFFF) & 0xFEFFFFFF) & 0xFDFFFFFF; +// pmc->scratch79 = (sdram->emc_r2p << 26) | ((4 * sdram->emc_pmacro_tx_pwrd2 >> 31 << 25) | tmp) & 0x3FFFFFF; +// tmp = (sdram->emc_pmacro_tx_pwrd3 << 23 >> 31 << 8) | ((sdram->emc_pmacro_tx_pwrd3 << 24 >> 31 << 7) | ((sdram->emc_pmacro_tx_pwrd3 << 25 >> 31 << 6) | (32 * (sdram->emc_pmacro_tx_pwrd3 << 26 >> 31) | (16 * (sdram->emc_pmacro_tx_pwrd3 << 27 >> 31) | (8 * (sdram->emc_pmacro_tx_pwrd3 << 28 >> 31) | (4 * (sdram->emc_pmacro_tx_pwrd3 << 29 >> 31) | (2 * (sdram->emc_pmacro_tx_pwrd3 << 30 >> 31) | (sdram->emc_pmacro_tx_pwrd3 & 1 | 2 * (pmc->scratch80 >> 1)) & 0xFFFFFFFD) & 0xFFFFFFFB) & 0xFFFFFFF7) & 0xFFFFFFEF) & 0xFFFFFFDF) & 0xFFFFFFBF) & 0xFFFFFF7F) & 0xFFFFFEFF; +// pmc->scratch80 = ((u8)(sdram->emc_ccdmw) << 26) | ((4 * sdram->emc_pmacro_tx_pwrd3 >> 31 << 25) | ((8 * sdram->emc_pmacro_tx_pwrd3 >> 31 << 24) | ((32 * sdram->emc_pmacro_tx_pwrd3 >> 31 << 23) | ((sdram->emc_pmacro_tx_pwrd3 << 6 >> 31 << 22) | ((sdram->emc_pmacro_tx_pwrd3 << 7 >> 31 << 21) | ((sdram->emc_pmacro_tx_pwrd3 << 8 >> 31 << 20) | ((sdram->emc_pmacro_tx_pwrd3 << 9 >> 31 << 19) | ((sdram->emc_pmacro_tx_pwrd3 << 10 >> 31 << 18) | ((sdram->emc_pmacro_tx_pwrd3 << 11 >> 31 << 17) | ((sdram->emc_pmacro_tx_pwrd3 << 12 >> 31 << 16) | ((sdram->emc_pmacro_tx_pwrd3 << 13 >> 31 << 15) | ((sdram->emc_pmacro_tx_pwrd3 << 14 >> 31 << 14) | ((sdram->emc_pmacro_tx_pwrd3 << 15 >> 31 << 13) | ((sdram->emc_pmacro_tx_pwrd3 << 18 >> 31 << 12) | ((sdram->emc_pmacro_tx_pwrd3 << 19 >> 31 << 11) | ((sdram->emc_pmacro_tx_pwrd3 << 21 >> 31 << 10) | ((sdram->emc_pmacro_tx_pwrd3 << 22 >> 31 << 9) | tmp & 0xFFFFFDFF) & 0xFFFFFBFF) & 0xFFFFF7FF) & 0xFFFFEFFF) & 0xFFFFDFFF) & 0xFFFFBFFF) & 0xFFFF7FFF) & 0xFFFEFFFF) & 0xFFFDFFFF) & 0xFFFBFFFF) & 0xFFF7FFFF) & 0xFFEFFFFF) & 0xFFDFFFFF) & 0xFFBFFFFF) & 0xFF7FFFFF) & 0xFEFFFFFF) & 0xFDFFFFFF) & 0x3FFFFFF; +// tmp = ((8 * sdram->emc_pmacro_tx_pwrd4 >> 31 << 24) | ((32 * sdram->emc_pmacro_tx_pwrd4 >> 31 << 23) | ((sdram->emc_pmacro_tx_pwrd4 << 6 >> 31 << 22) | ((sdram->emc_pmacro_tx_pwrd4 << 7 >> 31 << 21) | ((sdram->emc_pmacro_tx_pwrd4 << 8 >> 31 << 20) | ((sdram->emc_pmacro_tx_pwrd4 << 9 >> 31 << 19) | ((sdram->emc_pmacro_tx_pwrd4 << 10 >> 31 << 18) | ((sdram->emc_pmacro_tx_pwrd4 << 11 >> 31 << 17) | ((sdram->emc_pmacro_tx_pwrd4 << 12 >> 31 << 16) | ((sdram->emc_pmacro_tx_pwrd4 << 13 >> 31 << 15) | ((sdram->emc_pmacro_tx_pwrd4 << 14 >> 31 << 14) | ((sdram->emc_pmacro_tx_pwrd4 << 15 >> 31 << 13) | ((sdram->emc_pmacro_tx_pwrd4 << 18 >> 31 << 12) | ((sdram->emc_pmacro_tx_pwrd4 << 19 >> 31 << 11) | ((sdram->emc_pmacro_tx_pwrd4 << 21 >> 31 << 10) | ((sdram->emc_pmacro_tx_pwrd4 << 22 >> 31 << 9) | ((sdram->emc_pmacro_tx_pwrd4 << 23 >> 31 << 8) | ((sdram->emc_pmacro_tx_pwrd4 << 24 >> 31 << 7) | ((sdram->emc_pmacro_tx_pwrd4 << 25 >> 31 << 6) | (32 * (sdram->emc_pmacro_tx_pwrd4 << 26 >> 31) | (16 * (sdram->emc_pmacro_tx_pwrd4 << 27 >> 31) | (8 * (sdram->emc_pmacro_tx_pwrd4 << 28 >> 31) | (4 * (sdram->emc_pmacro_tx_pwrd4 << 29 >> 31) | (2 * (sdram->emc_pmacro_tx_pwrd4 << 30 >> 31) | (sdram->emc_pmacro_tx_pwrd4 & 1 | 2 * (pmc->scratch81 >> 1)) & 0xFFFFFFFD) & 0xFFFFFFFB) & 0xFFFFFFF7) & 0xFFFFFFEF) & 0xFFFFFFDF) & 0xFFFFFFBF) & 0xFFFFFF7F) & 0xFFFFFEFF) & 0xFFFFFDFF) & 0xFFFFFBFF) & 0xFFFFF7FF) & 0xFFFFEFFF) & 0xFFFFDFFF) & 0xFFFFBFFF) & 0xFFFF7FFF) & 0xFFFEFFFF) & 0xFFFDFFFF) & 0xFFFBFFFF) & 0xFFF7FFFF) & 0xFFEFFFFF) & 0xFFDFFFFF) & 0xFFBFFFFF) & 0xFF7FFFFF) & 0xFEFFFFFF) & 0xFDFFFFFF; +// pmc->scratch81 = ((u8)(sdram->emc_rd_rcd) << 26) | ((4 * sdram->emc_pmacro_tx_pwrd4 >> 31 << 25) | tmp) & 0x3FFFFFF; +// tmp = ((8 * sdram->emc_pmacro_tx_pwrd5 >> 31 << 24) | ((32 * sdram->emc_pmacro_tx_pwrd5 >> 31 << 23) | ((sdram->emc_pmacro_tx_pwrd5 << 6 >> 31 << 22) | ((sdram->emc_pmacro_tx_pwrd5 << 7 >> 31 << 21) | ((sdram->emc_pmacro_tx_pwrd5 << 8 >> 31 << 20) | ((sdram->emc_pmacro_tx_pwrd5 << 9 >> 31 << 19) | ((sdram->emc_pmacro_tx_pwrd5 << 10 >> 31 << 18) | ((sdram->emc_pmacro_tx_pwrd5 << 11 >> 31 << 17) | ((sdram->emc_pmacro_tx_pwrd5 << 12 >> 31 << 16) | ((sdram->emc_pmacro_tx_pwrd5 << 13 >> 31 << 15) | ((sdram->emc_pmacro_tx_pwrd5 << 14 >> 31 << 14) | ((sdram->emc_pmacro_tx_pwrd5 << 15 >> 31 << 13) | ((sdram->emc_pmacro_tx_pwrd5 << 18 >> 31 << 12) | ((sdram->emc_pmacro_tx_pwrd5 << 19 >> 31 << 11) | ((sdram->emc_pmacro_tx_pwrd5 << 21 >> 31 << 10) | ((sdram->emc_pmacro_tx_pwrd5 << 22 >> 31 << 9) | ((sdram->emc_pmacro_tx_pwrd5 << 23 >> 31 << 8) | ((sdram->emc_pmacro_tx_pwrd5 << 24 >> 31 << 7) | ((sdram->emc_pmacro_tx_pwrd5 << 25 >> 31 << 6) | (32 * (sdram->emc_pmacro_tx_pwrd5 << 26 >> 31) | (16 * (sdram->emc_pmacro_tx_pwrd5 << 27 >> 31) | (8 * (sdram->emc_pmacro_tx_pwrd5 << 28 >> 31) | (4 * (sdram->emc_pmacro_tx_pwrd5 << 29 >> 31) | (2 * (sdram->emc_pmacro_tx_pwrd5 << 30 >> 31) | (sdram->emc_pmacro_tx_pwrd5 & 1 | 2 * (pmc->scratch82 >> 1)) & 0xFFFFFFFD) & 0xFFFFFFFB) & 0xFFFFFFF7) & 0xFFFFFFEF) & 0xFFFFFFDF) & 0xFFFFFFBF) & 0xFFFFFF7F) & 0xFFFFFEFF) & 0xFFFFFDFF) & 0xFFFFFBFF) & 0xFFFFF7FF) & 0xFFFFEFFF) & 0xFFFFDFFF) & 0xFFFFBFFF) & 0xFFFF7FFF) & 0xFFFEFFFF) & 0xFFFDFFFF) & 0xFFFBFFFF) & 0xFFF7FFFF) & 0xFFEFFFFF) & 0xFFDFFFFF) & 0xFFBFFFFF) & 0xFF7FFFFF) & 0xFEFFFFFF) & 0xFDFFFFFF; +// pmc->scratch82 = ((u16)(sdram->emc_wr_rcd) << 26) | ((4 * sdram->emc_pmacro_tx_pwrd5 >> 31 << 25) | tmp) & 0x3FFFFFF; +// pmc->scratch83 = ((u8)(sdram->emc_config_sample_delay) << 25) | ((sdram->emc_auto_cal_channel >> 31 << 24) | ((2 * sdram->emc_auto_cal_channel >> 31 << 23) | ((4 * sdram->emc_auto_cal_channel >> 31 << 22) | ((16 * sdram->emc_auto_cal_channel >> 25 << 15) | ((sdram->emc_auto_cal_channel << 11 >> 27 << 10) | ((sdram->emc_auto_cal_channel << 20 >> 28 << 6) | (sdram->emc_auto_cal_channel & 0x3F | (pmc->scratch83 >> 6 << 6)) & 0xFFFFFC3F) & 0xFFFF83FF) & 0xFFC07FFF) & 0xFFBFFFFF) & 0xFF7FFFFF) & 0xFEFFFFFF) & 0x1FFFFFF; +// pmc->scratch84 = (sdram->emc_sel_dpd_ctrl << 13 >> 29 << 29) | ((sdram->emc_sel_dpd_ctrl << 23 >> 31 << 28) | ((sdram->emc_sel_dpd_ctrl << 26 >> 31 << 27) | ((sdram->emc_sel_dpd_ctrl << 27 >> 31 << 26) | ((sdram->emc_sel_dpd_ctrl << 28 >> 31 << 25) | ((sdram->emc_sel_dpd_ctrl << 29 >> 31 << 24) | ((4 * sdram->emc_pmacro_rx_term >> 26 << 18) | ((sdram->emc_pmacro_rx_term << 10 >> 26 << 12) | ((sdram->emc_pmacro_rx_term << 18 >> 26 << 6) | (sdram->emc_pmacro_rx_term & 0x3F | (pmc->scratch84 >> 6 << 6)) & 0xFFFFF03F) & 0xFFFC0FFF) & 0xFF03FFFF) & 0xFEFFFFFF) & 0xFDFFFFFF) & 0xFBFFFFFF) & 0xF7FFFFFF) & 0xEFFFFFFF) & 0x1FFFFFFF; +// pmc->scratch85 = (4 * sdram->emc_obdly >> 30 << 30) | (4 * ((sdram->emc_obdly << 24) | ((4 * sdram->emc_pmacro_dq_tx_drive >> 26 << 18) | ((sdram->emc_pmacro_dq_tx_drive << 10 >> 26 << 12) | ((sdram->emc_pmacro_dq_tx_drive << 18 >> 26 << 6) | (sdram->emc_pmacro_dq_tx_drive & 0x3F | (pmc->scratch85 >> 6 << 6)) & 0xFFFFF03F) & 0xFFFC0FFF) & 0xFF03FFFF) & 0xC0FFFFFF) >> 2); +// pmc->scratch86 = (sdram->emc_pmacro_vttgen_ctrl1 << 10 >> 30 << 30) | (4 * ((sdram->emc_pmacro_vttgen_ctrl1 << 16 >> 26 << 24) | ((4 * sdram->emc_pmacro_ca_tx_drive >> 26 << 18) | ((sdram->emc_pmacro_ca_tx_drive << 10 >> 26 << 12) | ((sdram->emc_pmacro_ca_tx_drive << 18 >> 26 << 6) | (sdram->emc_pmacro_ca_tx_drive & 0x3F | (pmc->scratch86 >> 6 << 6)) & 0xFFFFF03F) & 0xFFFC0FFF) & 0xFF03FFFF) & 0xC0FFFFFF) >> 2); +// pmc->scratch87 = (sdram->emc_pmacro_vttgen_ctrl2 >> 16 << 24) | ((16 * sdram->emc_pmacro_zcrtl >> 30 << 22) | ((sdram->emc_pmacro_zcrtl << 6 >> 30 << 20) | ((sdram->emc_pmacro_zcrtl << 8 >> 30 << 18) | ((sdram->emc_pmacro_zcrtl << 10 >> 30 << 16) | ((sdram->emc_pmacro_zcrtl << 12 >> 30 << 14) | ((sdram->emc_pmacro_zcrtl << 14 >> 30 << 12) | ((sdram->emc_pmacro_zcrtl << 16 >> 30 << 10) | ((sdram->emc_pmacro_zcrtl << 18 >> 30 << 8) | ((sdram->emc_pmacro_zcrtl << 20 >> 30 << 6) | (16 * (sdram->emc_pmacro_zcrtl << 22 >> 30) | (4 * (sdram->emc_pmacro_zcrtl << 24 >> 30) | ((sdram->emc_pmacro_zcrtl << 26 >> 30) | 4 * (pmc->scratch87 >> 2)) & 0xFFFFFFF3) & 0xFFFFFFCF) & 0xFFFFFF3F) & 0xFFFFFCFF) & 0xFFFFF3FF) & 0xFFFFCFFF) & 0xFFFF3FFF) & 0xFFFCFFFF) & 0xFFF3FFFF) & 0xFFCFFFFF) & 0xFF3FFFFF) & 0xFFFFFF; +// pmc->scratch88 = (sdram->mc_emem_arb_timing_rc << 24) | ((sdram->emc_zcal_interval << 14) | ((sdram->emc_zcal_interval << 8 >> 18) | (pmc->scratch88 >> 14 << 14)) & 0xFF003FFF) & 0xFFFFFF; +// pmc->scratch89 = ((u16)(sdram->mc_emem_arb_rsv) << 24) | ((sdram->emc_data_brlshft0 << 8 >> 29 << 21) | ((sdram->emc_data_brlshft0 << 11 >> 29 << 18) | ((sdram->emc_data_brlshft0 << 14 >> 29 << 15) | ((sdram->emc_data_brlshft0 << 17 >> 29 << 12) | ((sdram->emc_data_brlshft0 << 20 >> 29 << 9) | ((sdram->emc_data_brlshft0 << 23 >> 29 << 6) | (8 * (sdram->emc_data_brlshft0 << 26 >> 29) | (sdram->emc_data_brlshft0 & 7 | 8 * (pmc->scratch89 >> 3)) & 0xFFFFFFC7) & 0xFFFFFE3F) & 0xFFFFF1FF) & 0xFFFF8FFF) & 0xFFFC7FFF) & 0xFFE3FFFF) & 0xFF1FFFFF) & 0xFFFFFF; +// pmc->scratch90 = (sdram->emc_data_brlshft1 << 8 >> 29 << 21) | ((sdram->emc_data_brlshft1 << 11 >> 29 << 18) | ((sdram->emc_data_brlshft1 << 14 >> 29 << 15) | ((sdram->emc_data_brlshft1 << 17 >> 29 << 12) | ((sdram->emc_data_brlshft1 << 20 >> 29 << 9) | ((sdram->emc_data_brlshft1 << 23 >> 29 << 6) | (8 * (sdram->emc_data_brlshft1 << 26 >> 29) | (sdram->emc_data_brlshft1 & 7 | 8 * (pmc->scratch90 >> 3)) & 0xFFFFFFC7) & 0xFFFFFE3F) & 0xFFFFF1FF) & 0xFFFF8FFF) & 0xFFFC7FFF) & 0xFFE3FFFF) & 0xFF1FFFFF; +// pmc->scratch91 = (sdram->emc_dqs_brlshft0 << 8 >> 29 << 21) | ((sdram->emc_dqs_brlshft0 << 11 >> 29 << 18) | ((sdram->emc_dqs_brlshft0 << 14 >> 29 << 15) | ((sdram->emc_dqs_brlshft0 << 17 >> 29 << 12) | ((sdram->emc_dqs_brlshft0 << 20 >> 29 << 9) | ((sdram->emc_dqs_brlshft0 << 23 >> 29 << 6) | (8 * (sdram->emc_dqs_brlshft0 << 26 >> 29) | (sdram->emc_dqs_brlshft0 & 7 | 8 * (pmc->scratch91 >> 3)) & 0xFFFFFFC7) & 0xFFFFFE3F) & 0xFFFFF1FF) & 0xFFFF8FFF) & 0xFFFC7FFF) & 0xFFE3FFFF) & 0xFF1FFFFF; +// pmc->scratch92 = (sdram->emc_dqs_brlshft1 << 8 >> 29 << 21) | ((sdram->emc_dqs_brlshft1 << 11 >> 29 << 18) | ((sdram->emc_dqs_brlshft1 << 14 >> 29 << 15) | ((sdram->emc_dqs_brlshft1 << 17 >> 29 << 12) | ((sdram->emc_dqs_brlshft1 << 20 >> 29 << 9) | ((sdram->emc_dqs_brlshft1 << 23 >> 29 << 6) | (8 * (sdram->emc_dqs_brlshft1 << 26 >> 29) | (sdram->emc_dqs_brlshft1 & 7 | 8 * (pmc->scratch92 >> 3)) & 0xFFFFFFC7) & 0xFFFFFE3F) & 0xFFFFF1FF) & 0xFFFF8FFF) & 0xFFFC7FFF) & 0xFFE3FFFF) & 0xFF1FFFFF; +// pmc->scratch93 = (2 * sdram->emc_swizzle_rank0_byte0 >> 29 << 21) | ((32 * sdram->emc_swizzle_rank0_byte0 >> 29 << 18) | ((sdram->emc_swizzle_rank0_byte0 << 9 >> 29 << 15) | ((sdram->emc_swizzle_rank0_byte0 << 13 >> 29 << 12) | ((sdram->emc_swizzle_rank0_byte0 << 17 >> 29 << 9) | ((sdram->emc_swizzle_rank0_byte0 << 21 >> 29 << 6) | (8 * (sdram->emc_swizzle_rank0_byte0 << 25 >> 29) | (sdram->emc_swizzle_rank0_byte0 & 7 | 8 * (pmc->scratch93 >> 3)) & 0xFFFFFFC7) & 0xFFFFFE3F) & 0xFFFFF1FF) & 0xFFFF8FFF) & 0xFFFC7FFF) & 0xFFE3FFFF) & 0xFF1FFFFF; +// pmc->scratch94 = ((u8)(sdram->emc_cfg) << 27 >> 31 << 31) | (2 * ((sdram->emc_ras << 24) | ((2 * sdram->emc_swizzle_rank0_byte1 >> 29 << 21) | ((32 * sdram->emc_swizzle_rank0_byte1 >> 29 << 18) | ((sdram->emc_swizzle_rank0_byte1 << 9 >> 29 << 15) | ((sdram->emc_swizzle_rank0_byte1 << 13 >> 29 << 12) | ((sdram->emc_swizzle_rank0_byte1 << 17 >> 29 << 9) | ((sdram->emc_swizzle_rank0_byte1 << 21 >> 29 << 6) | (8 * (sdram->emc_swizzle_rank0_byte1 << 25 >> 29) | (sdram->emc_swizzle_rank0_byte1 & 7 | 8 * (pmc->scratch94 >> 3)) & 0xFFFFFFC7) & 0xFFFFFE3F) & 0xFFFFF1FF) & 0xFFFF8FFF) & 0xFFFC7FFF) & 0xFFE3FFFF) & 0xFF1FFFFF) & 0x80FFFFFF) >> 1); +// pmc->scratch95 = ((u8)(sdram->emc_cfg) << 26 >> 31 << 31) | (2 * ((sdram->emc_w2p << 24) | ((2 * sdram->emc_swizzle_rank0_byte2 >> 29 << 21) | ((32 * sdram->emc_swizzle_rank0_byte2 >> 29 << 18) | ((sdram->emc_swizzle_rank0_byte2 << 9 >> 29 << 15) | ((sdram->emc_swizzle_rank0_byte2 << 13 >> 29 << 12) | ((sdram->emc_swizzle_rank0_byte2 << 17 >> 29 << 9) | ((sdram->emc_swizzle_rank0_byte2 << 21 >> 29 << 6) | (8 * (sdram->emc_swizzle_rank0_byte2 << 25 >> 29) | (sdram->emc_swizzle_rank0_byte2 & 7 | 8 * (pmc->scratch95 >> 3)) & 0xFFFFFFC7) & 0xFFFFFE3F) & 0xFFFFF1FF) & 0xFFFF8FFF) & 0xFFFC7FFF) & 0xFFE3FFFF) & 0xFF1FFFFF) & 0x80FFFFFF) >> 1); +// pmc->scratch96 = ((u8)(sdram->emc_cfg) << 25 >> 31 << 31) | (2 * ((sdram->emc_qsafe << 24) | ((2 * sdram->emc_swizzle_rank0_byte3 >> 29 << 21) | (((sdram->emc_swizzle_rank0_byte3 << 9 >> 29 << 15) | ((sdram->emc_swizzle_rank0_byte3 << 13 >> 29 << 12) | ((sdram->emc_swizzle_rank0_byte3 << 17 >> 29 << 9) | ((sdram->emc_swizzle_rank0_byte3 << 21 >> 29 << 6) | (8 * (sdram->emc_swizzle_rank0_byte3 << 25 >> 29) | (sdram->emc_swizzle_rank0_byte3 & 7 | 8 * (pmc->scratch96 >> 3)) & 0xFFFFFFC7) & 0xFFFFFE3F) & 0xFFFFF1FF) & 0xFFFF8FFF) & 0xFFFC7FFF) & 0xFFE3FFFF | (32 * sdram->emc_swizzle_rank0_byte3 >> 29 << 18)) & 0xFF1FFFFF) & 0x80FFFFFF) >> 1); +// pmc->scratch97 = ((u8)(sdram->emc_cfg) << 24 >> 31 << 31) | (2 * ((sdram->emc_rdv << 24) | ((2 * sdram->emc_swizzle_rank1_byte0 >> 29 << 21) | (((sdram->emc_swizzle_rank1_byte0 << 9 >> 29 << 15) | ((sdram->emc_swizzle_rank1_byte0 << 13 >> 29 << 12) | ((sdram->emc_swizzle_rank1_byte0 << 17 >> 29 << 9) | ((sdram->emc_swizzle_rank1_byte0 << 21 >> 29 << 6) | (8 * (sdram->emc_swizzle_rank1_byte0 << 25 >> 29) | (sdram->emc_swizzle_rank1_byte0 & 7 | 8 * (pmc->scratch97 >> 3)) & 0xFFFFFFC7) & 0xFFFFFE3F) & 0xFFFFF1FF) & 0xFFFF8FFF) & 0xFFFC7FFF) & 0xFFE3FFFF | (32 * sdram->emc_swizzle_rank1_byte0 >> 29 << 18)) & 0xFF1FFFFF) & 0x80FFFFFF) >> 1); +// pmc->scratch98 = ((u16)(sdram->emc_cfg) << 23 >> 31 << 31) | (2 * (((u16)(sdram->emc_rw2pden) << 24) | ((2 * sdram->emc_swizzle_rank1_byte1 >> 29 << 21) | ((32 * sdram->emc_swizzle_rank1_byte1 >> 29 << 18) | ((sdram->emc_swizzle_rank1_byte1 << 9 >> 29 << 15) | ((sdram->emc_swizzle_rank1_byte1 << 13 >> 29 << 12) | ((sdram->emc_swizzle_rank1_byte1 << 17 >> 29 << 9) | ((sdram->emc_swizzle_rank1_byte1 << 21 >> 29 << 6) | (8 * (sdram->emc_swizzle_rank1_byte1 << 25 >> 29) | (sdram->emc_swizzle_rank1_byte1 & 7 | 8 * (pmc->scratch98 >> 3)) & 0xFFFFFFC7) & 0xFFFFFE3F) & 0xFFFFF1FF) & 0xFFFF8FFF) & 0xFFFC7FFF) & 0xFFE3FFFF) & 0xFF1FFFFF) & 0x80FFFFFF) >> 1); +// pmc->scratch99 = ((u16)(sdram->emc_cfg) << 22 >> 31 << 31) | (2 * ((sdram->emc_tfaw << 24) | ((2 * sdram->emc_swizzle_rank1_byte2 >> 29 << 21) | ((32 * sdram->emc_swizzle_rank1_byte2 >> 29 << 18) | ((sdram->emc_swizzle_rank1_byte2 << 9 >> 29 << 15) | ((sdram->emc_swizzle_rank1_byte2 << 13 >> 29 << 12) | ((sdram->emc_swizzle_rank1_byte2 << 17 >> 29 << 9) | ((sdram->emc_swizzle_rank1_byte2 << 21 >> 29 << 6) | (8 * (sdram->emc_swizzle_rank1_byte2 << 25 >> 29) | (sdram->emc_swizzle_rank1_byte2 & 7 | 8 * (pmc->scratch99 >> 3)) & 0xFFFFFFC7) & 0xFFFFFE3F) & 0xFFFFF1FF) & 0xFFFF8FFF) & 0xFFFC7FFF) & 0xFFE3FFFF) & 0xFF1FFFFF) & 0x80FFFFFF) >> 1); +// pmc->scratch100 = (sdram->emc_cfg << 13 >> 31 << 31) | (2 * ((sdram->emc_tclkstable << 24) | ((2 * sdram->emc_swizzle_rank1_byte3 >> 29 << 21) | ((32 * sdram->emc_swizzle_rank1_byte3 >> 29 << 18) | ((sdram->emc_swizzle_rank1_byte3 << 9 >> 29 << 15) | ((sdram->emc_swizzle_rank1_byte3 << 13 >> 29 << 12) | ((sdram->emc_swizzle_rank1_byte3 << 17 >> 29 << 9) | ((sdram->emc_swizzle_rank1_byte3 << 21 >> 29 << 6) | (8 * (sdram->emc_swizzle_rank1_byte3 << 25 >> 29) | (sdram->emc_swizzle_rank1_byte3 & 7 | 8 * (pmc->scratch100 >> 3)) & 0xFFFFFFC7) & 0xFFFFFE3F) & 0xFFFFF1FF) & 0xFFFF8FFF) & 0xFFFC7FFF) & 0xFFE3FFFF) & 0xFF1FFFFF) & 0x80FFFFFF) >> 1); +// tmp = 2 * (((u8)(sdram->emc_trtm) << 24) | ((16 * sdram->emc_cfg_pipe2 >> 31 << 23) | ((32 * sdram->emc_cfg_pipe2 >> 31 << 22) | ((sdram->emc_cfg_pipe2 << 6 >> 31 << 21) | ((sdram->emc_cfg_pipe2 << 7 >> 31 << 20) | ((sdram->emc_cfg_pipe2 << 8 >> 31 << 19) | ((sdram->emc_cfg_pipe2 << 9 >> 31 << 18) | ((sdram->emc_cfg_pipe2 << 10 >> 31 << 17) | ((sdram->emc_cfg_pipe2 << 11 >> 31 << 16) | ((sdram->emc_cfg_pipe2 << 12 >> 31 << 15) | ((sdram->emc_cfg_pipe2 << 13 >> 31 << 14) | ((sdram->emc_cfg_pipe2 << 14 >> 31 << 13) | ((sdram->emc_cfg_pipe2 << 15 >> 31 << 12) | ((sdram->emc_cfg_pipe2 << 20 >> 31 << 11) | ((sdram->emc_cfg_pipe2 << 21 >> 31 << 10) | ((sdram->emc_cfg_pipe2 << 22 >> 31 << 9) | ((sdram->emc_cfg_pipe2 << 23 >> 31 << 8) | ((sdram->emc_cfg_pipe2 << 24 >> 31 << 7) | ((sdram->emc_cfg_pipe2 << 25 >> 31 << 6) | (32 * (sdram->emc_cfg_pipe2 << 26 >> 31) | (16 * (sdram->emc_cfg_pipe2 << 27 >> 31) | (8 * (sdram->emc_cfg_pipe2 << 28 >> 31) | (4 * (sdram->emc_cfg_pipe2 << 29 >> 31) | (2 * (sdram->emc_cfg_pipe2 << 30 >> 31) | (sdram->emc_cfg_pipe2 & 1 | 2 * (pmc->scratch101 >> 1)) & 0xFFFFFFFD) & 0xFFFFFFFB) & 0xFFFFFFF7) & 0xFFFFFFEF) & 0xFFFFFFDF) & 0xFFFFFFBF) & 0xFFFFFF7F) & 0xFFFFFEFF) & 0xFFFFFDFF) & 0xFFFFFBFF) & 0xFFFFF7FF) & 0xFFFFEFFF) & 0xFFFFDFFF) & 0xFFFFBFFF) & 0xFFFF7FFF) & 0xFFFEFFFF) & 0xFFFDFFFF) & 0xFFFBFFFF) & 0xFFF7FFFF) & 0xFFEFFFFF) & 0xFFDFFFFF) & 0xFFBFFFFF) & 0xFF7FFFFF) & 0x80FFFFFF) >> 1; +// pmc->scratch101 = (sdram->emc_cfg << 10 >> 31 << 31) | tmp; +// tmp = (2 * (pmc->scratch102 >> 1) | sdram->emc_cfg_pipe1 & 1) & 0xFFFFFFFD; +// pmc->scratch102 = (sdram->emc_cfg << 9 >> 31 << 31) | (2 * (((u8)(sdram->emc_twtm) << 24) | ((16 * sdram->emc_cfg_pipe1 >> 31 << 23) | ((32 * sdram->emc_cfg_pipe1 >> 31 << 22) | ((sdram->emc_cfg_pipe1 << 6 >> 31 << 21) | ((sdram->emc_cfg_pipe1 << 7 >> 31 << 20) | ((sdram->emc_cfg_pipe1 << 8 >> 31 << 19) | ((sdram->emc_cfg_pipe1 << 9 >> 31 << 18) | ((sdram->emc_cfg_pipe1 << 10 >> 31 << 17) | ((sdram->emc_cfg_pipe1 << 11 >> 31 << 16) | ((sdram->emc_cfg_pipe1 << 12 >> 31 << 15) | ((sdram->emc_cfg_pipe1 << 13 >> 31 << 14) | ((sdram->emc_cfg_pipe1 << 14 >> 31 << 13) | ((sdram->emc_cfg_pipe1 << 15 >> 31 << 12) | ((sdram->emc_cfg_pipe1 << 20 >> 31 << 11) | ((sdram->emc_cfg_pipe1 << 21 >> 31 << 10) | ((sdram->emc_cfg_pipe1 << 22 >> 31 << 9) | ((sdram->emc_cfg_pipe1 << 23 >> 31 << 8) | ((sdram->emc_cfg_pipe1 << 24 >> 31 << 7) | ((sdram->emc_cfg_pipe1 << 25 >> 31 << 6) | (32 * (sdram->emc_cfg_pipe1 << 26 >> 31) | (16 * (sdram->emc_cfg_pipe1 << 27 >> 31) | (8 * (sdram->emc_cfg_pipe1 << 28 >> 31) | (4 * (sdram->emc_cfg_pipe1 << 29 >> 31) | (2 * (sdram->emc_cfg_pipe1 << 30 >> 31) | tmp) & 0xFFFFFFFB) & 0xFFFFFFF7) & 0xFFFFFFEF) & 0xFFFFFFDF) & 0xFFFFFFBF) & 0xFFFFFF7F) & 0xFFFFFEFF) & 0xFFFFFDFF) & 0xFFFFFBFF) & 0xFFFFF7FF) & 0xFFFFEFFF) & 0xFFFFDFFF) & 0xFFFFBFFF) & 0xFFFF7FFF) & 0xFFFEFFFF) & 0xFFFDFFFF) & 0xFFFBFFFF) & 0xFFF7FFFF) & 0xFFEFFFFF) & 0xFFDFFFFF) & 0xFFBFFFFF) & 0xFF7FFFFF) & 0x80FFFFFF) >> 1); +// tmp = 2 * (((u8)(sdram->emc_tratm) << 24) | ((sdram->emc_pmacro_ddll_pwrd0 >> 31 << 23) | ((2 * sdram->emc_pmacro_ddll_pwrd0 >> 31 << 22) | ((8 * sdram->emc_pmacro_ddll_pwrd0 >> 31 << 21) | ((16 * sdram->emc_pmacro_ddll_pwrd0 >> 31 << 20) | ((32 * sdram->emc_pmacro_ddll_pwrd0 >> 31 << 19) | ((sdram->emc_pmacro_ddll_pwrd0 << 6 >> 31 << 18) | ((sdram->emc_pmacro_ddll_pwrd0 << 8 >> 31 << 17) | ((sdram->emc_pmacro_ddll_pwrd0 << 9 >> 31 << 16) | ((sdram->emc_pmacro_ddll_pwrd0 << 11 >> 31 << 15) | ((sdram->emc_pmacro_ddll_pwrd0 << 12 >> 31 << 14) | ((sdram->emc_pmacro_ddll_pwrd0 << 13 >> 31 << 13) | ((sdram->emc_pmacro_ddll_pwrd0 << 14 >> 31 << 12) | ((sdram->emc_pmacro_ddll_pwrd0 << 16 >> 31 << 11) | ((sdram->emc_pmacro_ddll_pwrd0 << 17 >> 31 << 10) | ((sdram->emc_pmacro_ddll_pwrd0 << 19 >> 31 << 9) | ((sdram->emc_pmacro_ddll_pwrd0 << 20 >> 31 << 8) | ((sdram->emc_pmacro_ddll_pwrd0 << 21 >> 31 << 7) | ((sdram->emc_pmacro_ddll_pwrd0 << 22 >> 31 << 6) | (32 * (sdram->emc_pmacro_ddll_pwrd0 << 24 >> 31) | (16 * (sdram->emc_pmacro_ddll_pwrd0 << 25 >> 31) | (8 * (sdram->emc_pmacro_ddll_pwrd0 << 27 >> 31) | (4 * (sdram->emc_pmacro_ddll_pwrd0 << 28 >> 31) | (2 * (sdram->emc_pmacro_ddll_pwrd0 << 29 >> 31) | ((sdram->emc_pmacro_ddll_pwrd0 << 30 >> 31) | 2 * (pmc->scratch103 >> 1)) & 0xFFFFFFFD) & 0xFFFFFFFB) & 0xFFFFFFF7) & 0xFFFFFFEF) & 0xFFFFFFDF) & 0xFFFFFFBF) & 0xFFFFFF7F) & 0xFFFFFEFF) & 0xFFFFFDFF) & 0xFFFFFBFF) & 0xFFFFF7FF) & 0xFFFFEFFF) & 0xFFFFDFFF) & 0xFFFFBFFF) & 0xFFFF7FFF) & 0xFFFEFFFF) & 0xFFFDFFFF) & 0xFFFBFFFF) & 0xFFF7FFFF) & 0xFFEFFFFF) & 0xFFDFFFFF) & 0xFFBFFFFF) & 0xFF7FFFFF) & 0x80FFFFFF) >> 1; +// pmc->scratch103 = (sdram->emc_cfg << 8 >> 31 << 31) | tmp; +// tmp = 2 * (((u8)(sdram->emc_twatm) << 24) | ((sdram->emc_pmacro_ddll_pwrd1 >> 31 << 23) | ((2 * sdram->emc_pmacro_ddll_pwrd1 >> 31 << 22) | ((8 * sdram->emc_pmacro_ddll_pwrd1 >> 31 << 21) | ((16 * sdram->emc_pmacro_ddll_pwrd1 >> 31 << 20) | ((32 * sdram->emc_pmacro_ddll_pwrd1 >> 31 << 19) | ((sdram->emc_pmacro_ddll_pwrd1 << 6 >> 31 << 18) | ((sdram->emc_pmacro_ddll_pwrd1 << 8 >> 31 << 17) | ((sdram->emc_pmacro_ddll_pwrd1 << 9 >> 31 << 16) | ((sdram->emc_pmacro_ddll_pwrd1 << 11 >> 31 << 15) | ((sdram->emc_pmacro_ddll_pwrd1 << 12 >> 31 << 14) | ((sdram->emc_pmacro_ddll_pwrd1 << 13 >> 31 << 13) | ((sdram->emc_pmacro_ddll_pwrd1 << 14 >> 31 << 12) | ((sdram->emc_pmacro_ddll_pwrd1 << 16 >> 31 << 11) | ((sdram->emc_pmacro_ddll_pwrd1 << 17 >> 31 << 10) | ((sdram->emc_pmacro_ddll_pwrd1 << 19 >> 31 << 9) | ((sdram->emc_pmacro_ddll_pwrd1 << 20 >> 31 << 8) | ((sdram->emc_pmacro_ddll_pwrd1 << 21 >> 31 << 7) | ((sdram->emc_pmacro_ddll_pwrd1 << 22 >> 31 << 6) | (32 * (sdram->emc_pmacro_ddll_pwrd1 << 24 >> 31) | (16 * (sdram->emc_pmacro_ddll_pwrd1 << 25 >> 31) | (8 * (sdram->emc_pmacro_ddll_pwrd1 << 27 >> 31) | (4 * (sdram->emc_pmacro_ddll_pwrd1 << 28 >> 31) | (2 * (sdram->emc_pmacro_ddll_pwrd1 << 29 >> 31) | ((sdram->emc_pmacro_ddll_pwrd1 << 30 >> 31) | 2 * (pmc->scratch104 >> 1)) & 0xFFFFFFFD) & 0xFFFFFFFB) & 0xFFFFFFF7) & 0xFFFFFFEF) & 0xFFFFFFDF) & 0xFFFFFFBF) & 0xFFFFFF7F) & 0xFFFFFEFF) & 0xFFFFFDFF) & 0xFFFFFBFF) & 0xFFFFF7FF) & 0xFFFFEFFF) & 0xFFFFDFFF) & 0xFFFFBFFF) & 0xFFFF7FFF) & 0xFFFEFFFF) & 0xFFFDFFFF) & 0xFFFBFFFF) & 0xFFF7FFFF) & 0xFFEFFFFF) & 0xFFDFFFFF) & 0xFFBFFFFF) & 0xFF7FFFFF) & 0x80FFFFFF) >> 1; +// pmc->scratch104 = (sdram->emc_cfg << 7 >> 31 << 31) | tmp; +// tmp = (sdram->emc_pmacro_ddll_pwrd2 << 22 >> 31 << 6) | (32 * (sdram->emc_pmacro_ddll_pwrd2 << 24 >> 31) | (16 * (sdram->emc_pmacro_ddll_pwrd2 << 25 >> 31) | (8 * (sdram->emc_pmacro_ddll_pwrd2 << 27 >> 31) | (4 * (sdram->emc_pmacro_ddll_pwrd2 << 28 >> 31) | (2 * (sdram->emc_pmacro_ddll_pwrd2 << 29 >> 31) | ((sdram->emc_pmacro_ddll_pwrd2 << 30 >> 31) | 2 * (pmc->scratch105 >> 1)) & 0xFFFFFFFD) & 0xFFFFFFFB) & 0xFFFFFFF7) & 0xFFFFFFEF) & 0xFFFFFFDF) & 0xFFFFFFBF; +// pmc->scratch105 = (sdram->emc_cfg << 6 >> 31 << 31) | (2 * (((u8)(sdram->emc_tr2ref) << 24) | ((sdram->emc_pmacro_ddll_pwrd2 >> 31 << 23) | ((2 * sdram->emc_pmacro_ddll_pwrd2 >> 31 << 22) | ((8 * sdram->emc_pmacro_ddll_pwrd2 >> 31 << 21) | ((16 * sdram->emc_pmacro_ddll_pwrd2 >> 31 << 20) | ((32 * sdram->emc_pmacro_ddll_pwrd2 >> 31 << 19) | ((sdram->emc_pmacro_ddll_pwrd2 << 6 >> 31 << 18) | ((sdram->emc_pmacro_ddll_pwrd2 << 8 >> 31 << 17) | ((sdram->emc_pmacro_ddll_pwrd2 << 9 >> 31 << 16) | ((sdram->emc_pmacro_ddll_pwrd2 << 11 >> 31 << 15) | ((sdram->emc_pmacro_ddll_pwrd2 << 12 >> 31 << 14) | ((sdram->emc_pmacro_ddll_pwrd2 << 13 >> 31 << 13) | ((sdram->emc_pmacro_ddll_pwrd2 << 14 >> 31 << 12) | ((sdram->emc_pmacro_ddll_pwrd2 << 16 >> 31 << 11) | ((sdram->emc_pmacro_ddll_pwrd2 << 17 >> 31 << 10) | ((sdram->emc_pmacro_ddll_pwrd2 << 19 >> 31 << 9) | ((sdram->emc_pmacro_ddll_pwrd2 << 20 >> 31 << 8) | ((sdram->emc_pmacro_ddll_pwrd2 << 21 >> 31 << 7) | tmp & 0xFFFFFF7F) & 0xFFFFFEFF) & 0xFFFFFDFF) & 0xFFFFFBFF) & 0xFFFFF7FF) & 0xFFFFEFFF) & 0xFFFFDFFF) & 0xFFFFBFFF) & 0xFFFF7FFF) & 0xFFFEFFFF) & 0xFFFDFFFF) & 0xFFFBFFFF) & 0xFFF7FFFF) & 0xFFEFFFFF) & 0xFFDFFFFF) & 0xFFBFFFFF) & 0xFF7FFFFF) & 0x80FFFFFF) >> 1); +// pmc->scratch106 = (32 * sdram->emc_cfg >> 31 << 31) | (2 * (((u16)(sdram->emc_pdex2mrr) << 24) | ((8 * sdram->emc_pmacro_ddll_periodic_offset >> 31 << 23) | ((16 * sdram->emc_pmacro_ddll_periodic_offset >> 31 << 22) | ((32 * sdram->emc_pmacro_ddll_periodic_offset >> 31 << 21) | ((sdram->emc_pmacro_ddll_periodic_offset << 6 >> 31 << 20) | ((sdram->emc_pmacro_ddll_periodic_offset << 7 >> 31 << 19) | ((sdram->emc_pmacro_ddll_periodic_offset << 8 >> 31 << 18) | ((sdram->emc_pmacro_ddll_periodic_offset << 9 >> 31 << 17) | ((sdram->emc_pmacro_ddll_periodic_offset << 10 >> 31 << 16) | ((sdram->emc_pmacro_ddll_periodic_offset << 11 >> 31 << 15) | ((sdram->emc_pmacro_ddll_periodic_offset << 15 >> 31 << 14) | ((sdram->emc_pmacro_ddll_periodic_offset << 16 >> 31 << 13) | ((sdram->emc_pmacro_ddll_periodic_offset << 17 >> 31 << 12) | ((sdram->emc_pmacro_ddll_periodic_offset << 18 >> 31 << 11) | ((sdram->emc_pmacro_ddll_periodic_offset << 19 >> 31 << 10) | ((sdram->emc_pmacro_ddll_periodic_offset << 20 >> 31 << 9) | ((sdram->emc_pmacro_ddll_periodic_offset << 21 >> 31 << 8) | ((sdram->emc_pmacro_ddll_periodic_offset << 22 >> 31 << 7) | ((sdram->emc_pmacro_ddll_periodic_offset << 23 >> 31 << 6) | (sdram->emc_pmacro_ddll_periodic_offset & 0x3F | (pmc->scratch106 >> 6 << 6)) & 0xFFFFFFBF) & 0xFFFFFF7F) & 0xFFFFFEFF) & 0xFFFFFDFF) & 0xFFFFFBFF) & 0xFFFFF7FF) & 0xFFFFEFFF) & 0xFFFFDFFF) & 0xFFFFBFFF) & 0xFFFF7FFF) & 0xFFFEFFFF) & 0xFFFDFFFF) & 0xFFFBFFFF) & 0xFFF7FFFF) & 0xFFEFFFFF) & 0xFFDFFFFF) & 0xFFBFFFFF) & 0xFF7FFFFF) & 0x80FFFFFF) >> 1); +// pmc->scratch107 = (8 * sdram->emc_cfg >> 31 << 31) | (2 * ((sdram->emc_clken_override << 15 >> 31 << 30) | ((sdram->emc_clken_override << 23 >> 31 << 29) | ((sdram->emc_clken_override << 24 >> 31 << 28) | ((sdram->emc_clken_override << 25 >> 31 << 27) | ((sdram->emc_clken_override << 28 >> 31 << 26) | ((sdram->emc_clken_override << 29 >> 31 << 25) | ((sdram->emc_clken_override << 30 >> 31 << 24) | ((sdram->mc_emem_arb_da_covers << 8 >> 24 << 16) | ((sdram->mc_emem_arb_da_covers << 16 >> 24 << 8) | (sdram->mc_emem_arb_da_covers & 0xFF | (pmc->scratch107 >> 8 << 8)) & 0xFFFF00FF) & 0xFF00FFFF) & 0xFEFFFFFF) & 0xFDFFFFFF) & 0xFBFFFFFF) & 0xF7FFFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch108 = (sdram->emc_rfc_pb << 23) | ((sdram->emc_xm2_comp_pad_ctrl >> 24 << 15) | ((sdram->emc_xm2_comp_pad_ctrl << 12 >> 24 << 7) | ((sdram->emc_xm2_comp_pad_ctrl << 20 >> 31 << 6) | (32 * (sdram->emc_xm2_comp_pad_ctrl << 22 >> 31) | (4 * (sdram->emc_xm2_comp_pad_ctrl << 25 >> 29) | (sdram->emc_xm2_comp_pad_ctrl & 3 | 4 * (pmc->scratch108 >> 2)) & 0xFFFFFFE3) & 0xFFFFFFDF) & 0xFFFFFFBF) & 0xFFFF807F) & 0xFF807FFF) & 0x7FFFFF; +// pmc->scratch109 = (sdram->emc_cfg_update >> 31 << 31) | (2 * ((2 * sdram->emc_cfg_update >> 31 << 30) | ((4 * sdram->emc_cfg_update >> 31 << 29) | ((8 * sdram->emc_cfg_update >> 31 << 28) | ((sdram->emc_cfg_update << 21 >> 30 << 26) | ((sdram->emc_cfg_update << 23 >> 31 << 25) | ((sdram->emc_cfg_update << 29 >> 30 << 23) | ((sdram->emc_cfg_update << 22) & 0x7FFFFF | ((sdram->emc_auto_cal_config3 << 8 >> 28 << 18) | ((sdram->emc_auto_cal_config3 << 12 >> 28 << 14) | ((sdram->emc_auto_cal_config3 << 17 >> 25 << 7) | ((pmc->scratch109 >> 7 << 7) | sdram->emc_auto_cal_config3 & 0x7F) & 0xFFFFC07F) & 0xFFFC3FFF) & 0xFFC3FFFF) & 0xFFBFFFFF) & 0xFE7FFFFF) & 0xFDFFFFFF) & 0xF3FFFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch110 = (sdram->emc_rfc << 22) | ((sdram->emc_auto_cal_config4 << 8 >> 28 << 18) | ((sdram->emc_auto_cal_config4 << 12 >> 28 << 14) | ((sdram->emc_auto_cal_config4 << 17 >> 25 << 7) | (sdram->emc_auto_cal_config4 & 0x7F | (pmc->scratch110 >> 7 << 7)) & 0xFFFFC07F) & 0xFFFC3FFF) & 0xFFC3FFFF) & 0x3FFFFF; +// pmc->scratch111 = ((u16)(sdram->emc_txsr) << 22) | ((sdram->emc_auto_cal_config5 << 8 >> 28 << 18) | ((sdram->emc_auto_cal_config5 << 12 >> 28 << 14) | ((sdram->emc_auto_cal_config5 << 17 >> 25 << 7) | ((pmc->scratch111 >> 7 << 7) | sdram->emc_auto_cal_config5 & 0x7F) & 0xFFFFC07F) & 0xFFFC3FFF) & 0xFFC3FFFF) & 0x3FFFFF; +// pmc->scratch112 = (16 * sdram->emc_mc2emc_q >> 28 << 28) | ((sdram->emc_mc2emc_q << 21 >> 29 << 25) | ((sdram->emc_mc2emc_q << 22) & 0x1FFFFFF | ((sdram->emc_auto_cal_config6 << 8 >> 28 << 18) | ((sdram->emc_auto_cal_config6 << 12 >> 28 << 14) | ((sdram->emc_auto_cal_config6 << 17 >> 25 << 7) | (sdram->emc_auto_cal_config6 & 0x7F | (pmc->scratch112 >> 7 << 7)) & 0xFFFFC07F) & 0xFFFC3FFF) & 0xFFC3FFFF) & 0xFE3FFFFF) & 0xF1FFFFFF) & 0xFFFFFFF; +// pmc->scratch113 = (sdram->mc_emem_arb_ring1_throttle << 11 >> 27 << 27) | ((sdram->mc_emem_arb_ring1_throttle << 22) | ((sdram->emc_auto_cal_config7 << 8 >> 28 << 18) | ((sdram->emc_auto_cal_config7 << 12 >> 28 << 14) | ((sdram->emc_auto_cal_config7 << 17 >> 25 << 7) | (sdram->emc_auto_cal_config7 & 0x7F | (pmc->scratch113 >> 7 << 7)) & 0xFFFFC07F) & 0xFFFC3FFF) & 0xFFC3FFFF) & 0xF83FFFFF) & 0x7FFFFFF; +// pmc->scratch114 = (sdram->emc_auto_cal_config8 << 8 >> 28 << 18) | ((sdram->emc_auto_cal_config8 << 12 >> 28 << 14) | ((sdram->emc_auto_cal_config8 << 17 >> 25 << 7) | (sdram->emc_auto_cal_config8 & 0x7F | (pmc->scratch114 >> 7 << 7)) & 0xFFFFC07F) & 0xFFFC3FFF) & 0xFFC3FFFF; +// pmc->scratch115 = (4 * sdram->emc_cfg >> 31 << 31) | (2 * (((u16)(sdram->emc_ar2pden) << 22) | ((sdram->emc_fbio_cfg7 << 10 >> 30 << 20) | ((sdram->emc_fbio_cfg7 << 12 >> 31 << 19) | ((sdram->emc_fbio_cfg7 << 13 >> 31 << 18) | ((sdram->emc_fbio_cfg7 << 14 >> 31 << 17) | ((sdram->emc_fbio_cfg7 << 15 >> 31 << 16) | ((sdram->emc_fbio_cfg7 << 16 >> 31 << 15) | ((sdram->emc_fbio_cfg7 << 17 >> 31 << 14) | ((sdram->emc_fbio_cfg7 << 18 >> 31 << 13) | ((sdram->emc_fbio_cfg7 << 19 >> 31 << 12) | ((sdram->emc_fbio_cfg7 << 20 >> 31 << 11) | ((sdram->emc_fbio_cfg7 << 21 >> 31 << 10) | ((sdram->emc_fbio_cfg7 << 22 >> 31 << 9) | ((sdram->emc_fbio_cfg7 << 23 >> 31 << 8) | ((sdram->emc_fbio_cfg7 << 24 >> 31 << 7) | ((sdram->emc_fbio_cfg7 << 25 >> 31 << 6) | (32 * (sdram->emc_fbio_cfg7 << 26 >> 31) | (16 * (sdram->emc_fbio_cfg7 << 27 >> 31) | (8 * (sdram->emc_fbio_cfg7 << 28 >> 31) | (4 * (sdram->emc_fbio_cfg7 << 29 >> 31) | (2 * (sdram->emc_fbio_cfg7 << 30 >> 31) | (sdram->emc_fbio_cfg7 & 1 | 2 * (pmc->scratch115 >> 1)) & 0xFFFFFFFD) & 0xFFFFFFFB) & 0xFFFFFFF7) & 0xFFFFFFEF) & 0xFFFFFFDF) & 0xFFFFFFBF) & 0xFFFFFF7F) & 0xFFFFFEFF) & 0xFFFFFDFF) & 0xFFFFFBFF) & 0xFFFFF7FF) & 0xFFFFEFFF) & 0xFFFFDFFF) & 0xFFFFBFFF) & 0xFFFF7FFF) & 0xFFFEFFFF) & 0xFFFDFFFF) & 0xFFFBFFFF) & 0xFFF7FFFF) & 0xFFCFFFFF) & 0x803FFFFF) >> 1); +// pmc->scratch123 = (2 * sdram->emc_cfg >> 31 << 31) | (2 * ((sdram->emc_rfc_slr << 22) | ((32 * sdram->emc_pmacro_quse_ddll_rank0_0 >> 21 << 11) | (sdram->emc_pmacro_quse_ddll_rank0_0 & 0x7FF | (pmc->scratch123 >> 11 << 11)) & 0xFFC007FF) & 0x803FFFFF) >> 1); +// pmc->scratch124 = (sdram->emc_cfg >> 31 << 31) | (2 * ((4 * sdram->emc_ibdly >> 30 << 29) | ((sdram->emc_ibdly << 22) & 0x1FFFFFFF | ((32 * sdram->emc_pmacro_quse_ddll_rank0_1 >> 21 << 11) | (sdram->emc_pmacro_quse_ddll_rank0_1 & 0x7FF | (pmc->scratch124 >> 11 << 11)) & 0xFFC007FF) & 0xE03FFFFF) & 0x9FFFFFFF) >> 1); +// pmc->scratch125 = (sdram->emc_fbio_cfg5 << 27 >> 31 << 31) | (2 * (((u16)(sdram->mc_emem_arb_timing_rfcpb) << 22) | ((32 * sdram->emc_pmacro_quse_ddll_rank0_2 >> 21 << 11) | (sdram->emc_pmacro_quse_ddll_rank0_2 & 0x7FF | (pmc->scratch125 >> 11 << 11)) & 0xFFC007FF) & 0x803FFFFF) >> 1); +// pmc->scratch126 = (sdram->emc_fbio_cfg5 << 16 >> 29 << 29) | ((sdram->emc_auto_cal_config9 << 25 >> 31 << 28) | ((sdram->emc_auto_cal_config9 << 26 >> 31 << 27) | ((sdram->emc_auto_cal_config9 << 27 >> 31 << 26) | ((sdram->emc_auto_cal_config9 << 28 >> 31 << 25) | ((sdram->emc_auto_cal_config9 << 29 >> 31 << 24) | ((sdram->emc_auto_cal_config9 << 30 >> 31 << 23) | ((sdram->emc_auto_cal_config9 << 22) & 0x7FFFFF | ((32 * sdram->emc_pmacro_quse_ddll_rank0_3 >> 21 << 11) | (sdram->emc_pmacro_quse_ddll_rank0_3 & 0x7FF | (pmc->scratch126 >> 11 << 11)) & 0xFFC007FF) & 0xFFBFFFFF) & 0xFF7FFFFF) & 0xFEFFFFFF) & 0xFDFFFFFF) & 0xFBFFFFFF) & 0xF7FFFFFF) & 0xEFFFFFFF) & 0x1FFFFFFF; +// pmc->scratch127 = ((u8)(sdram->emc_cfg2) << 26 >> 29 << 29) | ((sdram->emc_rdv_mask << 22) | ((32 * sdram->emc_pmacro_quse_ddll_rank0_4 >> 21 << 11) | (sdram->emc_pmacro_quse_ddll_rank0_4 & 0x7FF | (pmc->scratch127 >> 11 << 11)) & 0xFFC007FF) & 0xE03FFFFF) & 0x1FFFFFFF; +// pmc->scratch128 = (sdram->emc_pmacro_cmd_pad_tx_ctrl << 27 >> 29 << 29) | (((u8)(sdram->emc_rdv_early_mask) << 22) | ((32 * sdram->emc_pmacro_quse_ddll_rank0_5 >> 21 << 11) | (sdram->emc_pmacro_quse_ddll_rank0_5 & 0x7FF | (pmc->scratch128 >> 11 << 11)) & 0xFFC007FF) & 0xE03FFFFF) & 0x1FFFFFFF; +// pmc->scratch129 = (sdram->emc_pmacro_cmd_pad_tx_ctrl << 22 >> 29 << 29) | ((sdram->emc_rdv_early << 22) | ((32 * sdram->emc_pmacro_quse_ddll_rank1_0 >> 21 << 11) | (sdram->emc_pmacro_quse_ddll_rank1_0 & 0x7FF | (pmc->scratch129 >> 11 << 11)) & 0xFFC007FF) & 0xE03FFFFF) & 0x1FFFFFFF; +// pmc->scratch130 = (sdram->emc_pmacro_cmd_pad_tx_ctrl << 17 >> 29 << 29) | ((4 * sdram->emc_quse_width >> 31 << 28) | ((8 * sdram->emc_quse_width >> 31 << 27) | ((sdram->emc_quse_width << 22) & 0x7FFFFFF | ((32 * sdram->emc_pmacro_quse_ddll_rank1_1 >> 21 << 11) | (sdram->emc_pmacro_quse_ddll_rank1_1 & 0x7FF | (pmc->scratch130 >> 11 << 11)) & 0xFFC007FF) & 0xF83FFFFF) & 0xF7FFFFFF) & 0xEFFFFFFF) & 0x1FFFFFFF; +// pmc->scratch131 = (sdram->emc_pmacro_cmd_pad_tx_ctrl << 12 >> 29 << 29) | (((u16)(sdram->emc_pmacro_ddll_short_cmd_2) << 22) | ((32 * sdram->emc_pmacro_quse_ddll_rank1_2 >> 21 << 11) | (sdram->emc_pmacro_quse_ddll_rank1_2 & 0x7FF | (pmc->scratch131 >> 11 << 11)) & 0xFFC007FF) & 0xE03FFFFF) & 0x1FFFFFFF; +// pmc->scratch132 = (sdram->emc_pmacro_data_pad_tx_ctrl << 27 >> 29 << 29) | ((sdram->emc_pmacro_cmd_rx_term_mode << 18 >> 31 << 28) | ((sdram->emc_pmacro_cmd_rx_term_mode << 22 >> 30 << 26) | ((sdram->emc_pmacro_cmd_rx_term_mode << 26 >> 30 << 24) | ((sdram->emc_pmacro_cmd_rx_term_mode << 22) & 0xFFFFFF | ((32 * sdram->emc_pmacro_quse_ddll_rank1_3 >> 21 << 11) | (sdram->emc_pmacro_quse_ddll_rank1_3 & 0x7FF | (pmc->scratch132 >> 11 << 11)) & 0xFFC007FF) & 0xFF3FFFFF) & 0xFCFFFFFF) & 0xF3FFFFFF) & 0xEFFFFFFF) & 0x1FFFFFFF; +// pmc->scratch133 = (sdram->emc_pmacro_data_pad_tx_ctrl << 22 >> 29 << 29) | ((sdram->emc_pmacro_data_rx_term_mode << 18 >> 31 << 28) | ((sdram->emc_pmacro_data_rx_term_mode << 22 >> 30 << 26) | ((sdram->emc_pmacro_data_rx_term_mode << 26 >> 30 << 24) | ((sdram->emc_pmacro_data_rx_term_mode << 22) & 0xFFFFFF | ((32 * sdram->emc_pmacro_quse_ddll_rank1_4 >> 21 << 11) | (sdram->emc_pmacro_quse_ddll_rank1_4 & 0x7FF | (pmc->scratch133 >> 11 << 11)) & 0xFFC007FF) & 0xFF3FFFFF) & 0xFCFFFFFF) & 0xF3FFFFFF) & 0xEFFFFFFF) & 0x1FFFFFFF; +// pmc->scratch134 = (sdram->emc_pmacro_data_pad_tx_ctrl << 17 >> 29 << 29) | ((sdram->mc_emem_arb_timing_rp << 22) | ((32 * sdram->emc_pmacro_quse_ddll_rank1_5 >> 21 << 11) | (sdram->emc_pmacro_quse_ddll_rank1_5 & 0x7FF | (pmc->scratch134 >> 11 << 11)) & 0xFFC007FF) & 0xE03FFFFF) & 0x1FFFFFFF; +// pmc->scratch135 = (sdram->emc_pmacro_data_pad_tx_ctrl << 12 >> 29 << 29) | ((sdram->mc_emem_arb_timing_ras << 22) | ((32 * sdram->emc_pmacro_ob_ddll_long_dq_rank0_0 >> 21 << 11) | (sdram->emc_pmacro_ob_ddll_long_dq_rank0_0 & 0x7FF | (pmc->scratch135 >> 11 << 11)) & 0xFFC007FF) & 0xE03FFFFF) & 0x1FFFFFFF; +// pmc->scratch136 = (sdram->emc_fbio_cfg5 << 23 >> 31 << 31) | (2 * ((sdram->emc_cfg << 14 >> 30 << 29) | ((sdram->mc_emem_arb_timing_faw << 22) & 0x1FFFFFFF | ((32 * sdram->emc_pmacro_ob_ddll_long_dq_rank0_1 >> 21 << 11) | (sdram->emc_pmacro_ob_ddll_long_dq_rank0_1 & 0x7FF | (pmc->scratch136 >> 11 << 11)) & 0xFFC007FF) & 0xE03FFFFF) & 0x9FFFFFFF) >> 1); +// pmc->scratch137 = (sdram->emc_fbio_cfg5 << 21 >> 31 << 31) | (2 * ((sdram->emc_fbio_cfg5 << 29) | ((sdram->mc_emem_arb_timing_rap2pre << 22) & 0x1FFFFFFF | ((32 * sdram->emc_pmacro_ob_ddll_long_dq_rank0_2 >> 21 << 11) | (sdram->emc_pmacro_ob_ddll_long_dq_rank0_2 & 0x7FF | (pmc->scratch137 >> 11 << 11)) & 0xFFC007FF) & 0xE03FFFFF) & 0x9FFFFFFF) >> 1); +// pmc->scratch138 = (sdram->emc_fbio_cfg5 << 19 >> 31 << 31) | (2 * ((sdram->emc_fbio_cfg5 << 28 >> 30 << 29) | ((sdram->mc_emem_arb_timing_wap2pre << 22) & 0x1FFFFFFF | ((32 * sdram->emc_pmacro_ob_ddll_long_dq_rank0_3 >> 21 << 11) | (sdram->emc_pmacro_ob_ddll_long_dq_rank0_3 & 0x7FF | (pmc->scratch138 >> 11 << 11)) & 0xFFC007FF) & 0xE03FFFFF) & 0x9FFFFFFF) >> 1); +// pmc->scratch139 = (sdram->emc_fbio_cfg5 << 7 >> 31 << 31) | (2 * ((16 * sdram->emc_cfg2 >> 30 << 29) | (((u8)(sdram->mc_emem_arb_timing_r2w) << 22) & 0x1FFFFFFF | ((32 * sdram->emc_pmacro_ob_ddll_long_dq_rank0_4 >> 21 << 11) | (sdram->emc_pmacro_ob_ddll_long_dq_rank0_4 & 0x7FF | (pmc->scratch139 >> 11 << 11)) & 0xFFC007FF) & 0xE03FFFFF) & 0x9FFFFFFF) >> 1); +// pmc->scratch140 = (16 * sdram->emc_fbio_cfg5 >> 31 << 31) | (2 * ((32 * sdram->emc_fbio_cfg5 >> 31 << 30) | ((sdram->emc_fbio_cfg5 << 6 >> 31 << 29) | (((u8)(sdram->mc_emem_arb_timing_w2r) << 22) & 0x1FFFFFFF | ((32 * sdram->emc_pmacro_ob_ddll_long_dq_rank0_5 >> 21 << 11) | (sdram->emc_pmacro_ob_ddll_long_dq_rank0_5 & 0x7FF | (pmc->scratch140 >> 11 << 11)) & 0xFFC007FF) & 0xE03FFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch141 = (sdram->emc_fbio_cfg5 << 8 >> 28 << 28) | (((u16)(sdram->emc_wdv) << 22) | ((32 * sdram->emc_pmacro_ob_ddll_long_dq_rank1_0 >> 21 << 11) | (sdram->emc_pmacro_ob_ddll_long_dq_rank1_0 & 0x7FF | (pmc->scratch141 >> 11 << 11)) & 0xFFC007FF) & 0xF03FFFFF) & 0xFFFFFFF; +// pmc->scratch142 = ((u8)(sdram->emc_cfg2) << 31) | (2 * ((sdram->emc_fbio_cfg5 >> 31 << 30) | ((2 * sdram->emc_fbio_cfg5 >> 31 << 29) | ((8 * sdram->emc_fbio_cfg5 >> 31 << 28) | ((sdram->emc_quse << 22) & 0xFFFFFFF | ((32 * sdram->emc_pmacro_ob_ddll_long_dq_rank1_1 >> 21 << 11) | (sdram->emc_pmacro_ob_ddll_long_dq_rank1_1 & 0x7FF | (pmc->scratch142 >> 11 << 11)) & 0xFFC007FF) & 0xF03FFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch143 = (((u16)(sdram->emc_cfg2) << 21) >> 31 << 31) | (2 * ((((u16)(sdram->emc_cfg2) << 24) >> 31 << 30) | ((((u16)(sdram->emc_cfg2) << 29) >> 31 << 29) | ((((u16)(sdram->emc_cfg2) << 30) >> 31 << 28) | (((u8)(sdram->emc_pdex2wr) << 22) & 0xFFFFFFF | ((32 * sdram->emc_pmacro_ob_ddll_long_dq_rank1_2 >> 21 << 11) | (sdram->emc_pmacro_ob_ddll_long_dq_rank1_2 & 0x7FF | (pmc->scratch143 >> 11 << 11)) & 0xFFC007FF) & 0xF03FFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch144 = (sdram->emc_cfg2 << 15 >> 31 << 31) | (2 * ((sdram->emc_cfg2 << 16 >> 31 << 30) | ((sdram->emc_cfg2 << 17 >> 31 << 29) | ((sdram->emc_cfg2 << 20 >> 31 << 28) | (((u8)(sdram->emc_pdex2rd) << 22) & 0xFFFFFFF | ((32 * sdram->emc_pmacro_ob_ddll_long_dq_rank1_3 >> 21 << 11) | (sdram->emc_pmacro_ob_ddll_long_dq_rank1_3 & 0x7FF | (pmc->scratch144 >> 11 << 11)) & 0xFFC007FF) & 0xF03FFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch145 = (sdram->emc_cfg2 << 7 >> 31 << 31) | (2 * ((sdram->emc_cfg2 << 8 >> 31 << 30) | ((sdram->emc_cfg2 << 9 >> 31 << 29) | ((sdram->emc_cfg2 << 11 >> 31 << 28) | (((u16)(sdram->emc_pdex2che) << 22) & 0xFFFFFFF | ((32 * sdram->emc_pmacro_ob_ddll_long_dq_rank1_4 >> 21 << 11) | (sdram->emc_pmacro_ob_ddll_long_dq_rank1_4 & 0x7FF | (pmc->scratch145 >> 11 << 11)) & 0xFFC007FF) & 0xF03FFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch146 = (2 * sdram->emc_cfg2 >> 31 << 31) | (2 * ((4 * sdram->emc_cfg2 >> 31 << 30) | (((sdram->emc_cfg2 << 6 >> 31 << 28) | (((u8)(sdram->emc_pchg2pden) << 22) & 0xFFFFFFF | ((32 * sdram->emc_pmacro_ob_ddll_long_dq_rank1_5 >> 21 << 11) | (sdram->emc_pmacro_ob_ddll_long_dq_rank1_5 & 0x7FF | (pmc->scratch146 >> 11 << 11)) & 0xFFC007FF) & 0xF03FFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF | (8 * sdram->emc_cfg2 >> 31 << 29)) & 0xBFFFFFFF) >> 1); +// pmc->scratch147 = (((u8)(sdram->emc_cfg_pipe) << 29) >> 31 << 31) | (2 * ((((u8)(sdram->emc_cfg_pipe) << 30) >> 31 << 30) | ((((u8)(sdram->emc_cfg_pipe) << 31) >> 2) | ((sdram->emc_cfg2 >> 31 << 28) | (((u16)(sdram->emc_act2pden) << 22) & 0xFFFFFFF | ((32 * sdram->emc_pmacro_ob_ddll_long_dqs_rank0_0 >> 21 << 11) | (sdram->emc_pmacro_ob_ddll_long_dqs_rank0_0 & 0x7FF | (pmc->scratch147 >> 11 << 11)) & 0xFFC007FF) & 0xF03FFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch148 = (((u8)(sdram->emc_cfg_pipe) << 25) >> 31 << 31) | (2 * ((((u8)(sdram->emc_cfg_pipe) << 26) >> 31 << 30) | ((((u8)(sdram->emc_cfg_pipe) << 27) >> 31 << 29) | ((((u8)(sdram->emc_cfg_pipe) << 28) >> 31 << 28) | (((u16)(sdram->emc_cke2pden) << 22) & 0xFFFFFFF | ((32 * sdram->emc_pmacro_ob_ddll_long_dqs_rank0_1 >> 21 << 11) | (sdram->emc_pmacro_ob_ddll_long_dqs_rank0_1 & 0x7FF | (pmc->scratch148 >> 11 << 11)) & 0xFFC007FF) & 0xF03FFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch149 = (((u16)(sdram->emc_cfg_pipe) << 21) >> 31 << 31) | (2 * ((((u16)(sdram->emc_cfg_pipe) << 22) >> 31 << 30) | ((((u16)(sdram->emc_cfg_pipe) << 23) >> 31 << 29) | ((((u16)(sdram->emc_cfg_pipe) << 24) >> 31 << 28) | ((sdram->emc_tcke << 22) & 0xFFFFFFF | ((32 * sdram->emc_pmacro_ob_ddll_long_dqs_rank0_2 >> 21 << 11) | (sdram->emc_pmacro_ob_ddll_long_dqs_rank0_2 & 0x7FF | (pmc->scratch149 >> 11 << 11)) & 0xFFC007FF) & 0xF03FFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch150 = (sdram->emc_cfg_pipe << 13 >> 31 << 31) | (2 * ((sdram->emc_cfg_pipe << 14 >> 31 << 30) | (((sdram->emc_cfg_pipe << 20 >> 31 << 28) | ((sdram->emc_trpab << 22) & 0xFFFFFFF | ((32 * sdram->emc_pmacro_ob_ddll_long_dqs_rank0_3 >> 21 << 11) | (sdram->emc_pmacro_ob_ddll_long_dqs_rank0_3 & 0x7FF | (pmc->scratch150 >> 11 << 11)) & 0xFFC007FF) & 0xF03FFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF | (sdram->emc_cfg_pipe << 15 >> 31 << 29)) & 0xBFFFFFFF) >> 1); +// pmc->scratch151 = (sdram->emc_cfg_pipe << 9 >> 31 << 31) | (2 * ((sdram->emc_cfg_pipe << 10 >> 31 << 30) | ((sdram->emc_cfg_pipe << 11 >> 31 << 29) | ((sdram->emc_cfg_pipe << 12 >> 31 << 28) | ((sdram->emc_einput << 22) & 0xFFFFFFF | ((32 * sdram->emc_pmacro_ob_ddll_long_dqs_rank0_4 >> 21 << 11) | (sdram->emc_pmacro_ob_ddll_long_dqs_rank0_4 & 0x7FF | (pmc->scratch151 >> 11 << 11)) & 0xFFC007FF) & 0xF03FFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch152 = (32 * sdram->emc_cfg_pipe >> 31 << 31) | (2 * ((sdram->emc_cfg_pipe << 6 >> 31 << 30) | ((sdram->emc_cfg_pipe << 7 >> 31 << 29) | ((sdram->emc_cfg_pipe << 8 >> 31 << 28) | ((sdram->emc_einput_duration << 22) & 0xFFFFFFF | ((32 * sdram->emc_pmacro_ob_ddll_long_dqs_rank0_5 >> 21 << 11) | (sdram->emc_pmacro_ob_ddll_long_dqs_rank0_5 & 0x7FF | (pmc->scratch152 >> 11 << 11)) & 0xFFC007FF) & 0xF03FFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch153 = (((u16)(sdram->emc_pmacro_tx_sel_clk_src0) << 29) >> 31 << 31) | (2 * ((((u16)(sdram->emc_pmacro_tx_sel_clk_src0) << 30) >> 31 << 30) | ((((u16)(sdram->emc_pmacro_tx_sel_clk_src0) << 31) >> 2) | ((16 * sdram->emc_cfg_pipe >> 31 << 28) | ((sdram->emc_puterm_extra << 22) & 0xFFFFFFF | ((32 * sdram->emc_pmacro_ob_ddll_long_dqs_rank1_0 >> 21 << 11) | (sdram->emc_pmacro_ob_ddll_long_dqs_rank1_0 & 0x7FF | (pmc->scratch153 >> 11 << 11)) & 0xFFC007FF) & 0xF03FFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch154 = (((u16)(sdram->emc_pmacro_tx_sel_clk_src0) << 25) >> 31 << 31) | (2 * ((((u16)(sdram->emc_pmacro_tx_sel_clk_src0) << 26) >> 31 << 30) | (((((u16)(sdram->emc_pmacro_tx_sel_clk_src0) << 28) >> 31 << 28) | ((sdram->emc_tckesr << 22) & 0xFFFFFFF | ((32 * sdram->emc_pmacro_ob_ddll_long_dqs_rank1_1 >> 21 << 11) | (sdram->emc_pmacro_ob_ddll_long_dqs_rank1_1 & 0x7FF | (pmc->scratch154 >> 11 << 11)) & 0xFFC007FF) & 0xF03FFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF | (((u16)(sdram->emc_pmacro_tx_sel_clk_src0) << 27) >> 31 << 29)) & 0xBFFFFFFF) >> 1); +// pmc->scratch155 = (((u16)(sdram->emc_pmacro_tx_sel_clk_src0) << 21) >> 31 << 31) | (2 * ((((u16)(sdram->emc_pmacro_tx_sel_clk_src0) << 22) >> 31 << 30) | ((((u16)(sdram->emc_pmacro_tx_sel_clk_src0) << 23) >> 31 << 29) | ((((u16)(sdram->emc_pmacro_tx_sel_clk_src0) << 24) >> 31 << 28) | ((sdram->emc_tpd << 22) & 0xFFFFFFF | ((32 * sdram->emc_pmacro_ob_ddll_long_dqs_rank1_2 >> 21 << 11) | (sdram->emc_pmacro_ob_ddll_long_dqs_rank1_2 & 0x7FF | (pmc->scratch155 >> 11 << 11)) & 0xFFC007FF) & 0xF03FFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch156 = (sdram->emc_pmacro_tx_sel_clk_src0 << 12 >> 31 << 31) | (2 * ((sdram->emc_pmacro_tx_sel_clk_src0 << 13 >> 31 << 30) | ((sdram->emc_pmacro_tx_sel_clk_src0 << 14 >> 31 << 29) | ((sdram->emc_pmacro_tx_sel_clk_src0 << 15 >> 31 << 28) | ((sdram->emc_wdv_mask << 22) & 0xFFFFFFF | ((32 * sdram->emc_pmacro_ob_ddll_long_dqs_rank1_3 >> 21 << 11) | (sdram->emc_pmacro_ob_ddll_long_dqs_rank1_3 & 0x7FF | (pmc->scratch156 >> 11 << 11)) & 0xFFC007FF) & 0xF03FFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch157 = (sdram->emc_pmacro_tx_sel_clk_src0 << 8 >> 31 << 31) | (2 * ((sdram->emc_pmacro_tx_sel_clk_src0 << 9 >> 31 << 30) | ((sdram->emc_pmacro_tx_sel_clk_src0 << 10 >> 31 << 29) | ((sdram->emc_pmacro_tx_sel_clk_src0 << 11 >> 31 << 28) | (((u16)(sdram->emc_wdv_chk) << 22) & 0xFFFFFFF | ((32 * sdram->emc_pmacro_ob_ddll_long_dqs_rank1_4 >> 21 << 11) | (sdram->emc_pmacro_ob_ddll_long_dqs_rank1_4 & 0x7FF | (pmc->scratch157 >> 11 << 11)) & 0xFFC007FF) & 0xF03FFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch158 = ((u16)(sdram->emc_pmacro_tx_sel_clk_src1) << 31) | (2 * ((32 * sdram->emc_pmacro_tx_sel_clk_src0 >> 31 << 30) | ((sdram->emc_pmacro_tx_sel_clk_src0 << 6 >> 31 << 29) | ((sdram->emc_pmacro_tx_sel_clk_src0 << 7 >> 31 << 28) | (((u8)(sdram->emc_cmd_brlshft0) << 26 >> 29 << 25) | (((u8)(sdram->emc_cmd_brlshft0) << 22) & 0x1FFFFFF | ((32 * sdram->emc_pmacro_ob_ddll_long_dqs_rank1_5 >> 21 << 11) | (sdram->emc_pmacro_ob_ddll_long_dqs_rank1_5 & 0x7FF | (pmc->scratch158 >> 11 << 11)) & 0xFFC007FF) & 0xFE3FFFFF) & 0xF1FFFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch159 = (((u16)(sdram->emc_pmacro_tx_sel_clk_src1) << 27) >> 31 << 31) | (2 * ((((u16)(sdram->emc_pmacro_tx_sel_clk_src1) << 28) >> 31 << 30) | ((((u16)(sdram->emc_pmacro_tx_sel_clk_src1) << 29) >> 31 << 29) | ((((u16)(sdram->emc_pmacro_tx_sel_clk_src1) << 30) >> 31 << 28) | (((u8)(sdram->emc_cmd_brlshft1) << 26 >> 29 << 25) | (((u8)(sdram->emc_cmd_brlshft1) << 22) & 0x1FFFFFF | ((32 * sdram->emc_pmacro_ib_ddll_long_dqs_rank0_0 >> 21 << 11) | (sdram->emc_pmacro_ib_ddll_long_dqs_rank0_0 & 0x7FF | (pmc->scratch159 >> 11 << 11)) & 0xFFC007FF) & 0xFE3FFFFF) & 0xF1FFFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch160 = (((u16)(sdram->emc_pmacro_tx_sel_clk_src1) << 23) >> 31 << 31) | (2 * ((((u16)(sdram->emc_pmacro_tx_sel_clk_src1) << 24) >> 31 << 30) | ((((u16)(sdram->emc_pmacro_tx_sel_clk_src1) << 25) >> 31 << 29) | ((((u16)(sdram->emc_pmacro_tx_sel_clk_src1) << 26) >> 31 << 28) | (((u8)(sdram->emc_cmd_brlshft2) << 26 >> 29 << 25) | (((u8)(sdram->emc_cmd_brlshft2) << 22) & 0x1FFFFFF | ((32 * sdram->emc_pmacro_ib_ddll_long_dqs_rank0_1 >> 21 << 11) | (sdram->emc_pmacro_ib_ddll_long_dqs_rank0_1 & 0x7FF | (pmc->scratch160 >> 11 << 11)) & 0xFFC007FF) & 0xFE3FFFFF) & 0xF1FFFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch161 = (sdram->emc_pmacro_tx_sel_clk_src1 << 14 >> 31 << 31) | (2 * ((sdram->emc_pmacro_tx_sel_clk_src1 << 15 >> 31 << 30) | ((sdram->emc_pmacro_tx_sel_clk_src1 << 21 >> 31 << 29) | ((sdram->emc_pmacro_tx_sel_clk_src1 << 22 >> 31 << 28) | (((u8)(sdram->emc_cmd_brlshft3) << 26 >> 29 << 25) | (((u8)(sdram->emc_cmd_brlshft3) << 22) & 0x1FFFFFF | ((32 * sdram->emc_pmacro_ib_ddll_long_dqs_rank0_2 >> 21 << 11) | (sdram->emc_pmacro_ib_ddll_long_dqs_rank0_2 & 0x7FF | (pmc->scratch161 >> 11 << 11)) & 0xFFC007FF) & 0xFE3FFFFF) & 0xF1FFFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch162 = (sdram->emc_pmacro_tx_sel_clk_src1 << 10 >> 31 << 31) | (2 * ((sdram->emc_pmacro_tx_sel_clk_src1 << 11 >> 31 << 30) | ((sdram->emc_pmacro_tx_sel_clk_src1 << 12 >> 31 << 29) | ((sdram->emc_pmacro_tx_sel_clk_src1 << 13 >> 31 << 28) | (((u16)(sdram->emc_wev) << 22) & 0xFFFFFFF | ((32 * sdram->emc_pmacro_ib_ddll_long_dqs_rank0_3 >> 21 << 11) | (sdram->emc_pmacro_ib_ddll_long_dqs_rank0_3 & 0x7FF | (pmc->scratch162 >> 11 << 11)) & 0xFFC007FF) & 0xF03FFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch163 = (sdram->emc_pmacro_tx_sel_clk_src1 << 6 >> 31 << 31) | (2 * ((sdram->emc_pmacro_tx_sel_clk_src1 << 7 >> 31 << 30) | ((sdram->emc_pmacro_tx_sel_clk_src1 << 8 >> 31 << 29) | ((sdram->emc_pmacro_tx_sel_clk_src1 << 9 >> 31 << 28) | (((u16)(sdram->emc_wsv) << 22) & 0xFFFFFFF | ((32 * sdram->emc_pmacro_ib_ddll_long_dqs_rank1_0 >> 21 << 11) | (sdram->emc_pmacro_ib_ddll_long_dqs_rank1_0 & 0x7FF | (pmc->scratch163 >> 11 << 11)) & 0xFFC007FF) & 0xF03FFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch164 = (((u16)(sdram->emc_pmacro_tx_sel_clk_src3) << 29) >> 31 << 31) | (2 * ((((u16)(sdram->emc_pmacro_tx_sel_clk_src3) << 30) >> 31 << 30) | ((((u16)(sdram->emc_pmacro_tx_sel_clk_src3) << 31) >> 2) | ((32 * sdram->emc_pmacro_tx_sel_clk_src1 >> 31 << 28) | (((u8)(sdram->emc_cfg3) << 25 >> 29 << 25) | (((u8)(sdram->emc_cfg3) << 22) & 0x1FFFFFF | ((32 * sdram->emc_pmacro_ib_ddll_long_dqs_rank1_1 >> 21 << 11) | (sdram->emc_pmacro_ib_ddll_long_dqs_rank1_1 & 0x7FF | (pmc->scratch164 >> 11 << 11)) & 0xFFC007FF) & 0xFE3FFFFF) & 0xF1FFFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch165 = (((u16)(sdram->emc_pmacro_tx_sel_clk_src3) << 25) >> 31 << 31) | (2 * ((((u16)(sdram->emc_pmacro_tx_sel_clk_src3) << 26) >> 31 << 30) | ((((u16)(sdram->emc_pmacro_tx_sel_clk_src3) << 27) >> 31 << 29) | ((((u16)(sdram->emc_pmacro_tx_sel_clk_src3) << 28) >> 31 << 28) | ((sdram->emc_puterm_width << 23) & 0xFFFFFFF | ((sdram->emc_puterm_width >> 31 << 22) | ((32 * sdram->emc_pmacro_ib_ddll_long_dqs_rank1_2 >> 21 << 11) | (sdram->emc_pmacro_ib_ddll_long_dqs_rank1_2 & 0x7FF | (pmc->scratch165 >> 11 << 11)) & 0xFFC007FF) & 0xFFBFFFFF) & 0xF07FFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch166 = (((u16)(sdram->emc_pmacro_tx_sel_clk_src3) << 21) >> 31 << 31) | (2 * ((((u16)(sdram->emc_pmacro_tx_sel_clk_src3) << 22) >> 31 << 30) | ((((u16)(sdram->emc_pmacro_tx_sel_clk_src3) << 23) >> 31 << 29) | ((((u16)(sdram->emc_pmacro_tx_sel_clk_src3) << 24) >> 31 << 28) | ((sdram->mc_emem_arb_timing_rcd << 22) & 0xFFFFFFF | ((32 * sdram->emc_pmacro_ib_ddll_long_dqs_rank1_3 >> 21 << 11) | (sdram->emc_pmacro_ib_ddll_long_dqs_rank1_3 & 0x7FF | (pmc->scratch166 >> 11 << 11)) & 0xFFC007FF) & 0xF03FFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch167 = (sdram->emc_pmacro_tx_sel_clk_src3 << 12 >> 31 << 31) | (2 * ((sdram->emc_pmacro_tx_sel_clk_src3 << 13 >> 31 << 30) | ((sdram->emc_pmacro_tx_sel_clk_src3 << 14 >> 31 << 29) | ((sdram->emc_pmacro_tx_sel_clk_src3 << 15 >> 31 << 28) | (((u16)(sdram->mc_emem_arb_timing_ccdmw) << 22) & 0xFFFFFFF | ((32 * sdram->emc_pmacro_ddll_long_cmd_0 >> 21 << 11) | (sdram->emc_pmacro_ddll_long_cmd_0 & 0x7FF | (pmc->scratch167 >> 11 << 11)) & 0xFFC007FF) & 0xF03FFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch168 = (sdram->emc_pmacro_tx_sel_clk_src3 << 8 >> 31 << 31) | (2 * ((sdram->emc_pmacro_tx_sel_clk_src3 << 9 >> 31 << 30) | ((sdram->emc_pmacro_tx_sel_clk_src3 << 10 >> 31 << 29) | ((sdram->emc_pmacro_tx_sel_clk_src3 << 11 >> 31 << 28) | ((sdram->mc_emem_arb_override << 28 >> 31 << 27) | (((sdram->mc_emem_arb_override << 21 >> 31 << 25) | ((sdram->mc_emem_arb_override << 15 >> 31 << 24) | ((32 * sdram->mc_emem_arb_override >> 31 << 23) | ((16 * sdram->mc_emem_arb_override >> 31 << 22) | ((32 * sdram->emc_pmacro_ddll_long_cmd_1 >> 21 << 11) | (sdram->emc_pmacro_ddll_long_cmd_1 & 0x7FF | (pmc->scratch168 >> 11 << 11)) & 0xFFC007FF) & 0xFFBFFFFF) & 0xFF7FFFFF) & 0xFEFFFFFF) & 0xFDFFFFFF) & 0xFBFFFFFF | (sdram->mc_emem_arb_override << 27 >> 31 << 26)) & 0xF7FFFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch169 = ((u16)(sdram->emc_rext) << 27) | (((u16)(sdram->emc_rrd) << 22) | ((32 * sdram->emc_pmacro_ddll_long_cmd_2 >> 21 << 11) | (sdram->emc_pmacro_ddll_long_cmd_2 & 0x7FF | (pmc->scratch169 >> 11 << 11)) & 0xFFC007FF) & 0xF83FFFFF) & 0x7FFFFFF; +// pmc->scratch170 = ((u16)(sdram->emc_wext) << 27) | ((sdram->emc_tclkstop << 22) | ((32 * sdram->emc_pmacro_ddll_long_cmd_3 >> 21 << 11) | (sdram->emc_pmacro_ddll_long_cmd_3 & 0x7FF | (pmc->scratch170 >> 11 << 11)) & 0xFFC007FF) & 0xF83FFFFF) & 0x7FFFFFF; +// tmp = (32 * sdram->emc_pmacro_perbit_fgcg_ctrl0 >> 31 << 21) | ((sdram->emc_pmacro_perbit_fgcg_ctrl0 << 6 >> 31 << 20) | ((sdram->emc_pmacro_perbit_fgcg_ctrl0 << 7 >> 31 << 19) | ((sdram->emc_pmacro_perbit_fgcg_ctrl0 << 8 >> 31 << 18) | ((sdram->emc_pmacro_perbit_fgcg_ctrl0 << 9 >> 31 << 17) | ((sdram->emc_pmacro_perbit_fgcg_ctrl0 << 10 >> 31 << 16) | ((sdram->emc_pmacro_perbit_fgcg_ctrl0 << 11 >> 31 << 15) | ((sdram->emc_pmacro_perbit_fgcg_ctrl0 << 12 >> 31 << 14) | ((sdram->emc_pmacro_perbit_fgcg_ctrl0 << 13 >> 31 << 13) | ((sdram->emc_pmacro_perbit_fgcg_ctrl0 << 14 >> 31 << 12) | ((sdram->emc_pmacro_perbit_fgcg_ctrl0 << 15 >> 31 << 11) | ((sdram->emc_pmacro_perbit_fgcg_ctrl0 << 21 >> 31 << 10) | ((sdram->emc_pmacro_perbit_fgcg_ctrl0 << 22 >> 31 << 9) | ((sdram->emc_pmacro_perbit_fgcg_ctrl0 << 23 >> 31 << 8) | ((sdram->emc_pmacro_perbit_fgcg_ctrl0 << 24 >> 31 << 7) | ((sdram->emc_pmacro_perbit_fgcg_ctrl0 << 25 >> 31 << 6) | (32 * (sdram->emc_pmacro_perbit_fgcg_ctrl0 << 26 >> 31) | (16 * (sdram->emc_pmacro_perbit_fgcg_ctrl0 << 27 >> 31) | (8 * (sdram->emc_pmacro_perbit_fgcg_ctrl0 << 28 >> 31) | (4 * (sdram->emc_pmacro_perbit_fgcg_ctrl0 << 29 >> 31) | (2 * (sdram->emc_pmacro_perbit_fgcg_ctrl0 << 30 >> 31) | (sdram->emc_pmacro_perbit_fgcg_ctrl0 & 1 | 2 * (pmc->scratch171 >> 1)) & 0xFFFFFFFD) & 0xFFFFFFFB) & 0xFFFFFFF7) & 0xFFFFFFEF) & 0xFFFFFFDF) & 0xFFFFFFBF) & 0xFFFFFF7F) & 0xFFFFFEFF) & 0xFFFFFDFF) & 0xFFFFFBFF) & 0xFFFFF7FF) & 0xFFFFEFFF) & 0xFFFFDFFF) & 0xFFFFBFFF) & 0xFFFF7FFF) & 0xFFFEFFFF) & 0xFFFDFFFF) & 0xFFFBFFFF) & 0xFFF7FFFF) & 0xFFEFFFFF) & 0xFFDFFFFF; +// pmc->scratch171 = (sdram->emc_we_duration << 27) | ((sdram->emc_ref_ctrl2 >> 31 << 26) | ((32 * sdram->emc_ref_ctrl2 >> 29 << 23) | ((sdram->emc_ref_ctrl2 << 22) & 0x7FFFFF | tmp & 0xFFBFFFFF) & 0xFC7FFFFF) & 0xFBFFFFFF) & 0x7FFFFFF; +// tmp = (sdram->emc_pmacro_pad_cfg_ctrl << 22 >> 31 << 28) | ((sdram->emc_pmacro_pad_cfg_ctrl << 27) & 0xFFFFFFF | ((sdram->emc_ws_duration << 22) & 0x7FFFFFF | ((32 * sdram->emc_pmacro_perbit_fgcg_ctrl1 >> 31 << 21) | ((sdram->emc_pmacro_perbit_fgcg_ctrl1 << 6 >> 31 << 20) | ((sdram->emc_pmacro_perbit_fgcg_ctrl1 << 7 >> 31 << 19) | ((sdram->emc_pmacro_perbit_fgcg_ctrl1 << 8 >> 31 << 18) | ((sdram->emc_pmacro_perbit_fgcg_ctrl1 << 9 >> 31 << 17) | ((sdram->emc_pmacro_perbit_fgcg_ctrl1 << 10 >> 31 << 16) | ((sdram->emc_pmacro_perbit_fgcg_ctrl1 << 11 >> 31 << 15) | ((sdram->emc_pmacro_perbit_fgcg_ctrl1 << 12 >> 31 << 14) | ((sdram->emc_pmacro_perbit_fgcg_ctrl1 << 13 >> 31 << 13) | ((sdram->emc_pmacro_perbit_fgcg_ctrl1 << 14 >> 31 << 12) | ((sdram->emc_pmacro_perbit_fgcg_ctrl1 << 15 >> 31 << 11) | ((sdram->emc_pmacro_perbit_fgcg_ctrl1 << 21 >> 31 << 10) | ((sdram->emc_pmacro_perbit_fgcg_ctrl1 << 22 >> 31 << 9) | ((sdram->emc_pmacro_perbit_fgcg_ctrl1 << 23 >> 31 << 8) | ((sdram->emc_pmacro_perbit_fgcg_ctrl1 << 24 >> 31 << 7) | ((sdram->emc_pmacro_perbit_fgcg_ctrl1 << 25 >> 31 << 6) | (32 * (sdram->emc_pmacro_perbit_fgcg_ctrl1 << 26 >> 31) | (16 * (sdram->emc_pmacro_perbit_fgcg_ctrl1 << 27 >> 31) | (8 * (sdram->emc_pmacro_perbit_fgcg_ctrl1 << 28 >> 31) | (4 * (sdram->emc_pmacro_perbit_fgcg_ctrl1 << 29 >> 31) | (2 * (sdram->emc_pmacro_perbit_fgcg_ctrl1 << 30 >> 31) | (sdram->emc_pmacro_perbit_fgcg_ctrl1 & 1 | 2 * (pmc->scratch172 >> 1)) & 0xFFFFFFFD) & 0xFFFFFFFB) & 0xFFFFFFF7) & 0xFFFFFFEF) & 0xFFFFFFDF) & 0xFFFFFFBF) & 0xFFFFFF7F) & 0xFFFFFEFF) & 0xFFFFFDFF) & 0xFFFFFBFF) & 0xFFFFF7FF) & 0xFFFFEFFF) & 0xFFFFDFFF) & 0xFFFFBFFF) & 0xFFFF7FFF) & 0xFFFEFFFF) & 0xFFFDFFFF) & 0xFFFBFFFF) & 0xFFF7FFFF) & 0xFFEFFFFF) & 0xFFDFFFFF) & 0xF83FFFFF) & 0xF7FFFFFF) & 0xEFFFFFFF; +// pmc->scratch172 = (sdram->emc_pmacro_pad_cfg_ctrl << 14 >> 30 << 30) | (4 * ((sdram->emc_pmacro_pad_cfg_ctrl << 18 >> 31 << 29) | tmp & 0xDFFFFFFF) >> 2); +// pmc->scratch173 = ((u8)(sdram->mc_emem_arb_timing_r2r) << 27) | ((sdram->mc_emem_arb_timing_rrd << 22) | ((32 * sdram->emc_pmacro_perbit_fgcg_ctrl2 >> 31 << 21) | ((sdram->emc_pmacro_perbit_fgcg_ctrl2 << 6 >> 31 << 20) | ((sdram->emc_pmacro_perbit_fgcg_ctrl2 << 7 >> 31 << 19) | ((sdram->emc_pmacro_perbit_fgcg_ctrl2 << 8 >> 31 << 18) | ((sdram->emc_pmacro_perbit_fgcg_ctrl2 << 9 >> 31 << 17) | ((sdram->emc_pmacro_perbit_fgcg_ctrl2 << 10 >> 31 << 16) | ((sdram->emc_pmacro_perbit_fgcg_ctrl2 << 11 >> 31 << 15) | ((sdram->emc_pmacro_perbit_fgcg_ctrl2 << 12 >> 31 << 14) | ((sdram->emc_pmacro_perbit_fgcg_ctrl2 << 13 >> 31 << 13) | ((sdram->emc_pmacro_perbit_fgcg_ctrl2 << 14 >> 31 << 12) | ((sdram->emc_pmacro_perbit_fgcg_ctrl2 << 15 >> 31 << 11) | ((sdram->emc_pmacro_perbit_fgcg_ctrl2 << 21 >> 31 << 10) | ((sdram->emc_pmacro_perbit_fgcg_ctrl2 << 22 >> 31 << 9) | ((sdram->emc_pmacro_perbit_fgcg_ctrl2 << 23 >> 31 << 8) | ((sdram->emc_pmacro_perbit_fgcg_ctrl2 << 24 >> 31 << 7) | ((sdram->emc_pmacro_perbit_fgcg_ctrl2 << 25 >> 31 << 6) | (32 * (sdram->emc_pmacro_perbit_fgcg_ctrl2 << 26 >> 31) | (16 * (sdram->emc_pmacro_perbit_fgcg_ctrl2 << 27 >> 31) | (8 * (sdram->emc_pmacro_perbit_fgcg_ctrl2 << 28 >> 31) | (4 * (sdram->emc_pmacro_perbit_fgcg_ctrl2 << 29 >> 31) | (2 * (sdram->emc_pmacro_perbit_fgcg_ctrl2 << 30 >> 31) | (sdram->emc_pmacro_perbit_fgcg_ctrl2 & 1 | 2 * (pmc->scratch173 >> 1)) & 0xFFFFFFFD) & 0xFFFFFFFB) & 0xFFFFFFF7) & 0xFFFFFFEF) & 0xFFFFFFDF) & 0xFFFFFFBF) & 0xFFFFFF7F) & 0xFFFFFEFF) & 0xFFFFFDFF) & 0xFFFFFBFF) & 0xFFFFF7FF) & 0xFFFFEFFF) & 0xFFFFDFFF) & 0xFFFFBFFF) & 0xFFFF7FFF) & 0xFFFEFFFF) & 0xFFFDFFFF) & 0xFFFBFFFF) & 0xFFF7FFFF) & 0xFFEFFFFF) & 0xFFDFFFFF) & 0xF83FFFFF) & 0x7FFFFFF; +// tmp = 32 * (sdram->emc_pmacro_perbit_fgcg_ctrl3 << 26 >> 31) | (16 * (sdram->emc_pmacro_perbit_fgcg_ctrl3 << 27 >> 31) | (8 * (sdram->emc_pmacro_perbit_fgcg_ctrl3 << 28 >> 31) | (4 * (sdram->emc_pmacro_perbit_fgcg_ctrl3 << 29 >> 31) | (2 * (sdram->emc_pmacro_perbit_fgcg_ctrl3 << 30 >> 31) | (sdram->emc_pmacro_perbit_fgcg_ctrl3 & 1 | 2 * (pmc->scratch174 >> 1)) & 0xFFFFFFFD) & 0xFFFFFFFB) & 0xFFFFFFF7) & 0xFFFFFFEF) & 0xFFFFFFDF; +// pmc->scratch174 = ((u16)(sdram->emc_pmacro_tx_sel_clk_src2) << 30 >> 31 << 31) | (2 * (((u16)(sdram->emc_pmacro_tx_sel_clk_src2) << 30) | ((32 * sdram->emc_pmacro_tx_sel_clk_src3 >> 31 << 29) | ((sdram->emc_pmacro_tx_sel_clk_src3 << 6 >> 31 << 28) | ((sdram->emc_pmacro_tx_sel_clk_src3 << 7 >> 31 << 27) | (((u8)(sdram->mc_emem_arb_timing_w2w) << 22) & 0x7FFFFFF | ((32 * sdram->emc_pmacro_perbit_fgcg_ctrl3 >> 31 << 21) | ((sdram->emc_pmacro_perbit_fgcg_ctrl3 << 6 >> 31 << 20) | ((sdram->emc_pmacro_perbit_fgcg_ctrl3 << 7 >> 31 << 19) | ((sdram->emc_pmacro_perbit_fgcg_ctrl3 << 8 >> 31 << 18) | ((sdram->emc_pmacro_perbit_fgcg_ctrl3 << 9 >> 31 << 17) | ((sdram->emc_pmacro_perbit_fgcg_ctrl3 << 10 >> 31 << 16) | ((sdram->emc_pmacro_perbit_fgcg_ctrl3 << 11 >> 31 << 15) | ((sdram->emc_pmacro_perbit_fgcg_ctrl3 << 12 >> 31 << 14) | ((sdram->emc_pmacro_perbit_fgcg_ctrl3 << 13 >> 31 << 13) | ((sdram->emc_pmacro_perbit_fgcg_ctrl3 << 14 >> 31 << 12) | ((sdram->emc_pmacro_perbit_fgcg_ctrl3 << 15 >> 31 << 11) | ((sdram->emc_pmacro_perbit_fgcg_ctrl3 << 21 >> 31 << 10) | ((sdram->emc_pmacro_perbit_fgcg_ctrl3 << 22 >> 31 << 9) | ((sdram->emc_pmacro_perbit_fgcg_ctrl3 << 23 >> 31 << 8) | ((sdram->emc_pmacro_perbit_fgcg_ctrl3 << 24 >> 31 << 7) | ((sdram->emc_pmacro_perbit_fgcg_ctrl3 << 25 >> 31 << 6) | tmp & 0xFFFFFFBF) & 0xFFFFFF7F) & 0xFFFFFEFF) & 0xFFFFFDFF) & 0xFFFFFBFF) & 0xFFFFF7FF) & 0xFFFFEFFF) & 0xFFFFDFFF) & 0xFFFFBFFF) & 0xFFFF7FFF) & 0xFFFEFFFF) & 0xFFFDFFFF) & 0xFFFBFFFF) & 0xFFF7FFFF) & 0xFFEFFFFF) & 0xFFDFFFFF) & 0xF83FFFFF) & 0xF7FFFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// tmp = (sdram->emc_pmacro_tx_sel_clk_src2 << 28 >> 31 << 23) | ((sdram->emc_pmacro_tx_sel_clk_src2 << 29 >> 31 << 22) | ((32 * sdram->emc_pmacro_perbit_fgcg_ctrl4 >> 31 << 21) | ((sdram->emc_pmacro_perbit_fgcg_ctrl4 << 6 >> 31 << 20) | ((sdram->emc_pmacro_perbit_fgcg_ctrl4 << 7 >> 31 << 19) | ((sdram->emc_pmacro_perbit_fgcg_ctrl4 << 8 >> 31 << 18) | ((sdram->emc_pmacro_perbit_fgcg_ctrl4 << 9 >> 31 << 17) | ((sdram->emc_pmacro_perbit_fgcg_ctrl4 << 10 >> 31 << 16) | ((sdram->emc_pmacro_perbit_fgcg_ctrl4 << 11 >> 31 << 15) | ((sdram->emc_pmacro_perbit_fgcg_ctrl4 << 12 >> 31 << 14) | ((sdram->emc_pmacro_perbit_fgcg_ctrl4 << 13 >> 31 << 13) | ((sdram->emc_pmacro_perbit_fgcg_ctrl4 << 14 >> 31 << 12) | ((sdram->emc_pmacro_perbit_fgcg_ctrl4 << 15 >> 31 << 11) | ((sdram->emc_pmacro_perbit_fgcg_ctrl4 << 21 >> 31 << 10) | ((sdram->emc_pmacro_perbit_fgcg_ctrl4 << 22 >> 31 << 9) | ((sdram->emc_pmacro_perbit_fgcg_ctrl4 << 23 >> 31 << 8) | ((sdram->emc_pmacro_perbit_fgcg_ctrl4 << 24 >> 31 << 7) | ((sdram->emc_pmacro_perbit_fgcg_ctrl4 << 25 >> 31 << 6) | (32 * (sdram->emc_pmacro_perbit_fgcg_ctrl4 << 26 >> 31) | (16 * (sdram->emc_pmacro_perbit_fgcg_ctrl4 << 27 >> 31) | (8 * (sdram->emc_pmacro_perbit_fgcg_ctrl4 << 28 >> 31) | (4 * (sdram->emc_pmacro_perbit_fgcg_ctrl4 << 29 >> 31) | (2 * (sdram->emc_pmacro_perbit_fgcg_ctrl4 << 30 >> 31) | (sdram->emc_pmacro_perbit_fgcg_ctrl4 & 1 | 2 * (pmc->scratch175 >> 1)) & 0xFFFFFFFD) & 0xFFFFFFFB) & 0xFFFFFFF7) & 0xFFFFFFEF) & 0xFFFFFFDF) & 0xFFFFFFBF) & 0xFFFFFF7F) & 0xFFFFFEFF) & 0xFFFFFDFF) & 0xFFFFFBFF) & 0xFFFFF7FF) & 0xFFFFEFFF) & 0xFFFFDFFF) & 0xFFFFBFFF) & 0xFFFF7FFF) & 0xFFFEFFFF) & 0xFFFDFFFF) & 0xFFFBFFFF) & 0xFFF7FFFF) & 0xFFEFFFFF) & 0xFFDFFFFF) & 0xFFBFFFFF) & 0xFF7FFFFF; +// pmc->scratch175 = (sdram->emc_pmacro_tx_sel_clk_src2 << 15 >> 31 << 31) | (2 * ((sdram->emc_pmacro_tx_sel_clk_src2 << 21 >> 31 << 30) | ((sdram->emc_pmacro_tx_sel_clk_src2 << 22 >> 31 << 29) | ((sdram->emc_pmacro_tx_sel_clk_src2 << 23 >> 31 << 28) | ((sdram->emc_pmacro_tx_sel_clk_src2 << 24 >> 31 << 27) | ((sdram->emc_pmacro_tx_sel_clk_src2 << 25 >> 31 << 26) | ((sdram->emc_pmacro_tx_sel_clk_src2 << 26 >> 31 << 25) | ((sdram->emc_pmacro_tx_sel_clk_src2 << 27 >> 31 << 24) | tmp & 0xFEFFFFFF) & 0xFDFFFFFF) & 0xFBFFFFFF) & 0xF7FFFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// tmp = (sdram->emc_pmacro_tx_sel_clk_src2 << 12 >> 31 << 24) | ((sdram->emc_pmacro_tx_sel_clk_src2 << 13 >> 31 << 23) | ((sdram->emc_pmacro_tx_sel_clk_src2 << 14 >> 31 << 22) | ((32 * sdram->emc_pmacro_perbit_fgcg_ctrl5 >> 31 << 21) | ((sdram->emc_pmacro_perbit_fgcg_ctrl5 << 6 >> 31 << 20) | ((sdram->emc_pmacro_perbit_fgcg_ctrl5 << 7 >> 31 << 19) | ((sdram->emc_pmacro_perbit_fgcg_ctrl5 << 8 >> 31 << 18) | ((sdram->emc_pmacro_perbit_fgcg_ctrl5 << 9 >> 31 << 17) | ((sdram->emc_pmacro_perbit_fgcg_ctrl5 << 10 >> 31 << 16) | ((sdram->emc_pmacro_perbit_fgcg_ctrl5 << 11 >> 31 << 15) | ((sdram->emc_pmacro_perbit_fgcg_ctrl5 << 12 >> 31 << 14) | ((sdram->emc_pmacro_perbit_fgcg_ctrl5 << 13 >> 31 << 13) | ((sdram->emc_pmacro_perbit_fgcg_ctrl5 << 14 >> 31 << 12) | ((sdram->emc_pmacro_perbit_fgcg_ctrl5 << 15 >> 31 << 11) | ((sdram->emc_pmacro_perbit_fgcg_ctrl5 << 21 >> 31 << 10) | ((sdram->emc_pmacro_perbit_fgcg_ctrl5 << 22 >> 31 << 9) | ((sdram->emc_pmacro_perbit_fgcg_ctrl5 << 23 >> 31 << 8) | ((sdram->emc_pmacro_perbit_fgcg_ctrl5 << 24 >> 31 << 7) | ((sdram->emc_pmacro_perbit_fgcg_ctrl5 << 25 >> 31 << 6) | (32 * (sdram->emc_pmacro_perbit_fgcg_ctrl5 << 26 >> 31) | (16 * (sdram->emc_pmacro_perbit_fgcg_ctrl5 << 27 >> 31) | (8 * (sdram->emc_pmacro_perbit_fgcg_ctrl5 << 28 >> 31) | (4 * (sdram->emc_pmacro_perbit_fgcg_ctrl5 << 29 >> 31) | (2 * (sdram->emc_pmacro_perbit_fgcg_ctrl5 << 30 >> 31) | (sdram->emc_pmacro_perbit_fgcg_ctrl5 & 1 | 2 * (pmc->scratch176 >> 1)) & 0xFFFFFFFD) & 0xFFFFFFFB) & 0xFFFFFFF7) & 0xFFFFFFEF) & 0xFFFFFFDF) & 0xFFFFFFBF) & 0xFFFFFF7F) & 0xFFFFFEFF) & 0xFFFFFDFF) & 0xFFFFFBFF) & 0xFFFFF7FF) & 0xFFFFEFFF) & 0xFFFFDFFF) & 0xFFFFBFFF) & 0xFFFF7FFF) & 0xFFFEFFFF) & 0xFFFDFFFF) & 0xFFFBFFFF) & 0xFFF7FFFF) & 0xFFEFFFFF) & 0xFFDFFFFF) & 0xFFBFFFFF) & 0xFF7FFFFF) & 0xFEFFFFFF; +// pmc->scratch176 = (32 * sdram->emc_pmacro_tx_sel_clk_src2 >> 31 << 31) | (2 * ((sdram->emc_pmacro_tx_sel_clk_src2 << 6 >> 31 << 30) | ((sdram->emc_pmacro_tx_sel_clk_src2 << 7 >> 31 << 29) | ((sdram->emc_pmacro_tx_sel_clk_src2 << 8 >> 31 << 28) | ((sdram->emc_pmacro_tx_sel_clk_src2 << 9 >> 31 << 27) | ((sdram->emc_pmacro_tx_sel_clk_src2 << 10 >> 31 << 26) | ((sdram->emc_pmacro_tx_sel_clk_src2 << 11 >> 31 << 25) | tmp & 0xFDFFFFFF) & 0xFBFFFFFF) & 0xF7FFFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch177 = (sdram->emc_pmacro_tx_sel_clk_src4 << 22 >> 31 << 31) | (2 * ((sdram->emc_pmacro_tx_sel_clk_src4 << 23 >> 31 << 30) | ((sdram->emc_pmacro_tx_sel_clk_src4 << 24 >> 31 << 29) | ((sdram->emc_pmacro_tx_sel_clk_src4 << 25 >> 31 << 28) | ((sdram->emc_pmacro_tx_sel_clk_src4 << 26 >> 31 << 27) | ((sdram->emc_pmacro_tx_sel_clk_src4 << 27 >> 31 << 26) | ((sdram->emc_pmacro_tx_sel_clk_src4 << 28 >> 31 << 25) | ((sdram->emc_pmacro_tx_sel_clk_src4 << 29 >> 31 << 24) | ((sdram->emc_pmacro_tx_sel_clk_src4 << 30 >> 31 << 23) | ((sdram->emc_pmacro_tx_sel_clk_src4 << 22) & 0x7FFFFF | ((sdram->mc_emem_arb_cfg >> 28 << 18) | ((16 * sdram->mc_emem_arb_cfg >> 28 << 14) | ((sdram->mc_emem_arb_cfg << 11 >> 27 << 9) | (sdram->mc_emem_arb_cfg & 0x1FF | (pmc->scratch177 >> 9 << 9)) & 0xFFFFC1FF) & 0xFFFC3FFF) & 0xFFC3FFFF) & 0xFFBFFFFF) & 0xFF7FFFFF) & 0xFEFFFFFF) & 0xFDFFFFFF) & 0xFBFFFFFF) & 0xF7FFFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch178 = (sdram->emc_pmacro_tx_sel_clk_src4 << 7 >> 31 << 31) | (2 * ((sdram->emc_pmacro_tx_sel_clk_src4 << 8 >> 31 << 30) | ((sdram->emc_pmacro_tx_sel_clk_src4 << 9 >> 31 << 29) | ((sdram->emc_pmacro_tx_sel_clk_src4 << 10 >> 31 << 28) | ((sdram->emc_pmacro_tx_sel_clk_src4 << 11 >> 31 << 27) | ((sdram->emc_pmacro_tx_sel_clk_src4 << 12 >> 31 << 26) | ((sdram->emc_pmacro_tx_sel_clk_src4 << 13 >> 31 << 25) | ((sdram->emc_pmacro_tx_sel_clk_src4 << 14 >> 31 << 24) | ((sdram->emc_pmacro_tx_sel_clk_src4 << 15 >> 31 << 23) | ((sdram->emc_pmacro_tx_sel_clk_src4 << 21 >> 31 << 22) | ((sdram->mc_emem_arb_misc1 >> 28 << 18) | ((sdram->mc_emem_arb_misc1 << 6 >> 30 << 16) | ((sdram->mc_emem_arb_misc1 << 8 >> 29 << 13) | (16 * (sdram->mc_emem_arb_misc1 << 19 >> 23) | (8 * (sdram->mc_emem_arb_misc1 << 28 >> 31) | (4 * (sdram->mc_emem_arb_misc1 << 29 >> 31) | (2 * (sdram->mc_emem_arb_misc1 << 30 >> 31) | (sdram->mc_emem_arb_misc1 & 1 | 2 * (pmc->scratch178 >> 1)) & 0xFFFFFFFD) & 0xFFFFFFFB) & 0xFFFFFFF7) & 0xFFFFE00F) & 0xFFFF1FFF) & 0xFFFCFFFF) & 0xFFC3FFFF) & 0xFFBFFFFF) & 0xFF7FFFFF) & 0xFEFFFFFF) & 0xFDFFFFFF) & 0xFBFFFFFF) & 0xF7FFFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch179 = (sdram->emc_odt_write >> 31 << 31) | (2 * ((sdram->emc_odt_write << 20 >> 28 << 27) | ((sdram->emc_odt_write << 26 >> 31 << 26) | ((sdram->emc_odt_write << 27 >> 31 << 25) | ((sdram->emc_odt_write << 21) & 0x1FFFFFF | ((32 * sdram->emc_mrs_wait_cnt2 >> 21 << 10) | (sdram->emc_mrs_wait_cnt2 & 0x3FF | (pmc->scratch179 >> 10 << 10)) & 0xFFE003FF) & 0xFE1FFFFF) & 0xFDFFFFFF) & 0xFBFFFFFF) & 0x87FFFFFF) >> 1); +// pmc->scratch180 = (sdram->emc_pmacro_ib_rxrt << 21) | ((32 * sdram->emc_mrs_wait_cnt >> 21 << 10) | (sdram->emc_mrs_wait_cnt & 0x3FF | (pmc->scratch180 >> 10 << 10)) & 0xFFE003FF) & 0x1FFFFF; +// pmc->scratch181 = ((u16)(sdram->emc_pmacro_ddll_long_cmd_4) << 21) | sdram->emc_auto_cal_interval & 0x1FFFFF; +// pmc->scratch182 = (sdram->mc_emem_arb_outstanding_req >> 31 << 31) | (2 * ((2 * sdram->mc_emem_arb_outstanding_req >> 31 << 30) | ((sdram->mc_emem_arb_outstanding_req << 23 >> 2) | ((sdram->emc_emem_arb_refpb_hp_ctrl << 9 >> 25 << 14) | ((sdram->emc_emem_arb_refpb_hp_ctrl << 17 >> 25 << 7) | (sdram->emc_emem_arb_refpb_hp_ctrl & 0x7F | (pmc->scratch182 >> 7 << 7)) & 0xFFFFC07F) & 0xFFE03FFF) & 0xC01FFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch183 = (4 * sdram->emc_pmacro_cmd_ctrl0 >> 31 << 31) | (2 * ((8 * sdram->emc_pmacro_cmd_ctrl0 >> 31 << 30) | ((sdram->emc_pmacro_cmd_ctrl0 << 7 >> 31 << 29) | ((sdram->emc_pmacro_cmd_ctrl0 << 10 >> 31 << 28) | ((sdram->emc_pmacro_cmd_ctrl0 << 11 >> 31 << 27) | ((sdram->emc_pmacro_cmd_ctrl0 << 15 >> 31 << 26) | ((sdram->emc_pmacro_cmd_ctrl0 << 18 >> 31 << 25) | ((sdram->emc_pmacro_cmd_ctrl0 << 19 >> 31 << 24) | ((sdram->emc_pmacro_cmd_ctrl0 << 23 >> 31 << 23) | ((sdram->emc_pmacro_cmd_ctrl0 << 26 >> 31 << 22) | ((sdram->emc_pmacro_cmd_ctrl0 << 27 >> 31 << 21) | ((sdram->emc_pmacro_cmd_ctrl0 << 20) & 0x1FFFFF | ((4 * sdram->emc_xm2_comp_pad_ctrl2 >> 26 << 14) | ((sdram->emc_xm2_comp_pad_ctrl2 << 10 >> 30 << 12) | ((sdram->emc_xm2_comp_pad_ctrl2 << 14 >> 31 << 11) | ((sdram->emc_xm2_comp_pad_ctrl2 << 15 >> 31 << 10) | ((sdram->emc_xm2_comp_pad_ctrl2 << 16 >> 30 << 8) | ((sdram->emc_xm2_comp_pad_ctrl2 << 18 >> 30 << 6) | (4 * (sdram->emc_xm2_comp_pad_ctrl2 << 26 >> 28) | (sdram->emc_xm2_comp_pad_ctrl2 & 3 | 4 * (pmc->scratch183 >> 2)) & 0xFFFFFFC3) & 0xFFFFFF3F) & 0xFFFFFCFF) & 0xFFFFFBFF) & 0xFFFFF7FF) & 0xFFFFCFFF) & 0xFFF03FFF) & 0xFFEFFFFF) & 0xFFDFFFFF) & 0xFFBFFFFF) & 0xFF7FFFFF) & 0xFEFFFFFF) & 0xFDFFFFFF) & 0xFBFFFFFF) & 0xF7FFFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch184 = (4 * sdram->emc_pmacro_cmd_ctrl1 >> 31 << 31) | (2 * ((8 * sdram->emc_pmacro_cmd_ctrl1 >> 31 << 30) | ((sdram->emc_pmacro_cmd_ctrl1 << 7 >> 31 << 29) | ((sdram->emc_pmacro_cmd_ctrl1 << 10 >> 31 << 28) | ((sdram->emc_pmacro_cmd_ctrl1 << 11 >> 31 << 27) | ((sdram->emc_pmacro_cmd_ctrl1 << 15 >> 31 << 26) | ((sdram->emc_pmacro_cmd_ctrl1 << 18 >> 31 << 25) | ((sdram->emc_pmacro_cmd_ctrl1 << 19 >> 31 << 24) | ((sdram->emc_pmacro_cmd_ctrl1 << 23 >> 31 << 23) | ((sdram->emc_pmacro_cmd_ctrl1 << 26 >> 31 << 22) | ((sdram->emc_pmacro_cmd_ctrl1 << 27 >> 31 << 21) | ((sdram->emc_pmacro_cmd_ctrl1 << 20) & 0x1FFFFF | ((sdram->emc_cfg_dig_dll_1 << 12 >> 28 << 16) | ((sdram->emc_cfg_dig_dll_1 << 16 >> 28 << 12) | ((sdram->emc_cfg_dig_dll_1 << 20 >> 26 << 6) | (2 * (sdram->emc_cfg_dig_dll_1 << 26 >> 27) | (sdram->emc_cfg_dig_dll_1 & 1 | 2 * (pmc->scratch184 >> 1)) & 0xFFFFFFC1) & 0xFFFFF03F) & 0xFFFF0FFF) & 0xFFF0FFFF) & 0xFFEFFFFF) & 0xFFDFFFFF) & 0xFFBFFFFF) & 0xFF7FFFFF) & 0xFEFFFFFF) & 0xFDFFFFFF) & 0xFBFFFFFF) & 0xF7FFFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch185 = (4 * sdram->emc_pmacro_cmd_ctrl2 >> 31 << 31) | (2 * ((8 * sdram->emc_pmacro_cmd_ctrl2 >> 31 << 30) | ((sdram->emc_pmacro_cmd_ctrl2 << 7 >> 31 << 29) | ((sdram->emc_pmacro_cmd_ctrl2 << 10 >> 31 << 28) | ((sdram->emc_pmacro_cmd_ctrl2 << 11 >> 31 << 27) | ((sdram->emc_pmacro_cmd_ctrl2 << 15 >> 31 << 26) | ((sdram->emc_pmacro_cmd_ctrl2 << 18 >> 31 << 25) | ((sdram->emc_pmacro_cmd_ctrl2 << 19 >> 31 << 24) | ((sdram->emc_pmacro_cmd_ctrl2 << 23 >> 31 << 23) | ((sdram->emc_pmacro_cmd_ctrl2 << 26 >> 31 << 22) | ((sdram->emc_pmacro_cmd_ctrl2 << 27 >> 31 << 21) | ((sdram->emc_pmacro_cmd_ctrl2 << 20) & 0x1FFFFF | ((sdram->emc_quse_brlshft0 << 12 >> 27 << 15) | ((sdram->emc_quse_brlshft0 << 17 >> 27 << 10) | (32 * (sdram->emc_quse_brlshft0 << 22 >> 27) | (sdram->emc_quse_brlshft0 & 0x1F | 32 * (pmc->scratch185 >> 5)) & 0xFFFFFC1F) & 0xFFFF83FF) & 0xFFF07FFF) & 0xFFEFFFFF) & 0xFFDFFFFF) & 0xFFBFFFFF) & 0xFF7FFFFF) & 0xFEFFFFFF) & 0xFDFFFFFF) & 0xFBFFFFFF) & 0xF7FFFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch186 = (sdram->emc_pmacro_dsr_vttgen_ctrl0 >> 8 << 24) | ((sdram->emc_pmacro_dsr_vttgen_ctrl0 << 20) | ((sdram->emc_quse_brlshft1 << 12 >> 27 << 15) | ((sdram->emc_quse_brlshft1 << 17 >> 27 << 10) | (32 * (sdram->emc_quse_brlshft1 << 22 >> 27) | (sdram->emc_quse_brlshft1 & 0x1F | 32 * (pmc->scratch186 >> 5)) & 0xFFFFFC1F) & 0xFFFF83FF) & 0xFFF07FFF) & 0xFF0FFFFF) & 0xFFFFFF; +// pmc->scratch187 = (sdram->emc_pmacro_perbit_rfu1_ctrl0 << 10 >> 30 << 30) | (4 * ((sdram->emc_pmacro_perbit_rfu1_ctrl0 << 12 >> 30 << 28) | ((sdram->emc_pmacro_perbit_rfu1_ctrl0 << 14 >> 30 << 26) | ((sdram->emc_pmacro_perbit_rfu1_ctrl0 << 26 >> 30 << 24) | ((sdram->emc_pmacro_perbit_rfu1_ctrl0 << 28 >> 30 << 22) | ((sdram->emc_pmacro_perbit_rfu1_ctrl0 << 20) & 0x3FFFFF | ((sdram->emc_quse_brlshft2 << 12 >> 27 << 15) | ((sdram->emc_quse_brlshft2 << 17 >> 27 << 10) | (32 * (sdram->emc_quse_brlshft2 << 22 >> 27) | (sdram->emc_quse_brlshft2 & 0x1F | 32 * (pmc->scratch187 >> 5)) & 0xFFFFFC1F) & 0xFFFF83FF) & 0xFFF07FFF) & 0xFFCFFFFF) & 0xFF3FFFFF) & 0xFCFFFFFF) & 0xF3FFFFFF) & 0xCFFFFFFF) >> 2); +// pmc->scratch188 = (sdram->emc_pmacro_perbit_rfu1_ctrl1 << 10 >> 30 << 30) | (4 * ((sdram->emc_pmacro_perbit_rfu1_ctrl1 << 12 >> 30 << 28) | ((sdram->emc_pmacro_perbit_rfu1_ctrl1 << 14 >> 30 << 26) | ((sdram->emc_pmacro_perbit_rfu1_ctrl1 << 26 >> 30 << 24) | ((sdram->emc_pmacro_perbit_rfu1_ctrl1 << 28 >> 30 << 22) | ((sdram->emc_pmacro_perbit_rfu1_ctrl1 << 20) & 0x3FFFFF | ((sdram->emc_quse_brlshft3 << 12 >> 27 << 15) | ((sdram->emc_quse_brlshft3 << 17 >> 27 << 10) | (32 * (sdram->emc_quse_brlshft3 << 22 >> 27) | (sdram->emc_quse_brlshft3 & 0x1F | 32 * (pmc->scratch188 >> 5)) & 0xFFFFFC1F) & 0xFFFF83FF) & 0xFFF07FFF) & 0xFFCFFFFF) & 0xFF3FFFFF) & 0xFCFFFFFF) & 0xF3FFFFFF) & 0xCFFFFFFF) >> 2); +// pmc->scratch189 = (sdram->emc_trefbw << 18) | ((sdram->emc_dbg >> 31 << 17) | ((2 * sdram->emc_dbg >> 31 << 16) | ((4 * sdram->emc_dbg >> 31 << 15) | ((8 * sdram->emc_dbg >> 31 << 14) | ((16 * sdram->emc_dbg >> 30 << 12) | ((sdram->emc_dbg << 6 >> 31 << 11) | ((sdram->emc_dbg << 7 >> 31 << 10) | ((sdram->emc_dbg << 18 >> 31 << 9) | ((sdram->emc_dbg << 19 >> 31 << 8) | ((sdram->emc_dbg << 20 >> 31 << 7) | ((sdram->emc_dbg << 21 >> 31 << 6) | (32 * (sdram->emc_dbg << 22 >> 31) | (16 * (sdram->emc_dbg << 27 >> 31) | (8 * (sdram->emc_dbg << 28 >> 31) | (4 * (sdram->emc_dbg << 29 >> 31) | (2 * (sdram->emc_dbg << 30 >> 31) | (sdram->emc_dbg & 1 | 2 * (pmc->scratch189 >> 1)) & 0xFFFFFFFD) & 0xFFFFFFFB) & 0xFFFFFFF7) & 0xFFFFFFEF) & 0xFFFFFFDF) & 0xFFFFFFBF) & 0xFFFFFF7F) & 0xFFFFFEFF) & 0xFFFFFDFF) & 0xFFFFFBFF) & 0xFFFFF7FF) & 0xFFFFCFFF) & 0xFFFFBFFF) & 0xFFFF7FFF) & 0xFFFEFFFF) & 0xFFFDFFFF) & 0x3FFFF; +// pmc->scratch191 = (sdram->emc_qpop << 9 >> 25 << 25) | ((sdram->emc_qpop << 18) | ((sdram->emc_zcal_wait_cnt >> 31 << 17) | ((sdram->emc_zcal_wait_cnt << 10 >> 26 << 11) | (sdram->emc_zcal_wait_cnt & 0x7FF | (pmc->scratch191 >> 11 << 11)) & 0xFFFE07FF) & 0xFFFDFFFF) & 0xFE03FFFF) & 0x1FFFFFF; +// pmc->scratch192 = (sdram->emc_pmacro_tx_sel_clk_src4 << 6 >> 31 << 31) | (2 * ((sdram->emc_pmacro_auto_cal_common << 15 >> 31 << 30) | ((sdram->emc_pmacro_auto_cal_common << 18 >> 26 << 24) | ((sdram->emc_pmacro_auto_cal_common << 18) & 0xFFFFFF | ((sdram->emc_zcal_mrw_cmd >> 30 << 16) | ((sdram->emc_zcal_mrw_cmd << 8 >> 24 << 8) | (sdram->emc_zcal_mrw_cmd & 0xFF | (pmc->scratch192 >> 8 << 8)) & 0xFFFF00FF) & 0xFFFCFFFF) & 0xFF03FFFF) & 0xC0FFFFFF) & 0xBFFFFFFF) >> 1); +// tmp = (sdram->emc_dll_cfg1 << 7 >> 31 << 17) | ((sdram->emc_dll_cfg1 << 10 >> 31 << 16) | ((sdram->emc_dll_cfg1 << 11 >> 31 << 15) | ((sdram->emc_dll_cfg1 << 14 >> 30 << 13) | ((sdram->emc_dll_cfg1 << 18 >> 31 << 12) | ((sdram->emc_dll_cfg1 << 19 >> 31 << 11) | ((pmc->scratch193 >> 11 << 11) | sdram->emc_dll_cfg1 & 0x7FF) & 0xFFFFF7FF) & 0xFFFFEFFF) & 0xFFFF9FFF) & 0xFFFF7FFF) & 0xFFFEFFFF) & 0xFFFDFFFF; +// pmc->scratch193 = (sdram->emc_pmacro_tx_sel_clk_src5 << 31) | (2 * ((32 * sdram->emc_pmacro_tx_sel_clk_src4 >> 31 << 30) | ((sdram->emc_pmacro_perbit_rfu1_ctrl2 << 10 >> 30 << 28) | (((sdram->emc_pmacro_perbit_rfu1_ctrl2 << 14 >> 30 << 24) | ((sdram->emc_pmacro_perbit_rfu1_ctrl2 << 26 >> 30 << 22) | ((sdram->emc_pmacro_perbit_rfu1_ctrl2 << 28 >> 30 << 20) | ((sdram->emc_pmacro_perbit_rfu1_ctrl2 << 18) & 0xFFFFF | tmp & 0xFFF3FFFF) & 0xFFCFFFFF) & 0xFF3FFFFF) & 0xFCFFFFFF) & 0xF3FFFFFF | (sdram->emc_pmacro_perbit_rfu1_ctrl2 << 12 >> 30 << 26)) & 0xCFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch194 = (sdram->emc_pmacro_tx_sel_clk_src5 << 29 >> 31 << 31) | (2 * ((sdram->emc_pmacro_tx_sel_clk_src5 << 30 >> 31 << 30) | ((sdram->emc_pmacro_perbit_rfu1_ctrl3 << 10 >> 30 << 28) | (((sdram->emc_pmacro_perbit_rfu1_ctrl3 << 14 >> 30 << 24) | (((sdram->emc_pmacro_perbit_rfu1_ctrl3 << 28 >> 30 << 20) | ((sdram->emc_pmacro_perbit_rfu1_ctrl3 << 18) & 0xFFFFF | ((sdram->emc_pmacro_cmd_brick_ctrl_fdpd << 14 >> 30 << 16) | ((sdram->emc_pmacro_cmd_brick_ctrl_fdpd << 16 >> 30 << 14) | ((sdram->emc_pmacro_cmd_brick_ctrl_fdpd << 18 >> 30 << 12) | ((sdram->emc_pmacro_cmd_brick_ctrl_fdpd << 20 >> 30 << 10) | ((sdram->emc_pmacro_cmd_brick_ctrl_fdpd << 22 >> 30 << 8) | ((sdram->emc_pmacro_cmd_brick_ctrl_fdpd << 24 >> 30 << 6) | (16 * (sdram->emc_pmacro_cmd_brick_ctrl_fdpd << 26 >> 30) | (4 * (sdram->emc_pmacro_cmd_brick_ctrl_fdpd << 28 >> 30) | (sdram->emc_pmacro_cmd_brick_ctrl_fdpd & 3 | 4 * (pmc->scratch194 >> 2)) & 0xFFFFFFF3) & 0xFFFFFFCF) & 0xFFFFFF3F) & 0xFFFFFCFF) & 0xFFFFF3FF) & 0xFFFFCFFF) & 0xFFFF3FFF) & 0xFFFCFFFF) & 0xFFF3FFFF) & 0xFFCFFFFF) & 0xFF3FFFFF | (sdram->emc_pmacro_perbit_rfu1_ctrl3 << 26 >> 30 << 22)) & 0xFCFFFFFF) & 0xF3FFFFFF | (sdram->emc_pmacro_perbit_rfu1_ctrl3 << 12 >> 30 << 26)) & 0xCFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch195 = (sdram->emc_pmacro_tx_sel_clk_src5 << 27 >> 31 << 31) | (2 * ((sdram->emc_pmacro_tx_sel_clk_src5 << 28 >> 31 << 30) | ((sdram->emc_pmacro_perbit_rfu1_ctrl4 << 10 >> 30 << 28) | (((sdram->emc_pmacro_perbit_rfu1_ctrl4 << 14 >> 30 << 24) | ((sdram->emc_pmacro_perbit_rfu1_ctrl4 << 26 >> 30 << 22) | ((sdram->emc_pmacro_perbit_rfu1_ctrl4 << 28 >> 30 << 20) | ((sdram->emc_pmacro_perbit_rfu1_ctrl4 << 18) & 0xFFFFF | ((sdram->emc_pmacro_data_brick_ctrl_fdpd << 14 >> 30 << 16) | ((sdram->emc_pmacro_data_brick_ctrl_fdpd << 16 >> 30 << 14) | ((sdram->emc_pmacro_data_brick_ctrl_fdpd << 18 >> 30 << 12) | ((sdram->emc_pmacro_data_brick_ctrl_fdpd << 20 >> 30 << 10) | ((sdram->emc_pmacro_data_brick_ctrl_fdpd << 22 >> 30 << 8) | ((sdram->emc_pmacro_data_brick_ctrl_fdpd << 24 >> 30 << 6) | (16 * (sdram->emc_pmacro_data_brick_ctrl_fdpd << 26 >> 30) | (4 * (sdram->emc_pmacro_data_brick_ctrl_fdpd << 28 >> 30) | (sdram->emc_pmacro_data_brick_ctrl_fdpd & 3 | 4 * (pmc->scratch195 >> 2)) & 0xFFFFFFF3) & 0xFFFFFFCF) & 0xFFFFFF3F) & 0xFFFFFCFF) & 0xFFFFF3FF) & 0xFFFFCFFF) & 0xFFFF3FFF) & 0xFFFCFFFF) & 0xFFF3FFFF) & 0xFFCFFFFF) & 0xFF3FFFFF) & 0xFCFFFFFF) & 0xF3FFFFFF | (sdram->emc_pmacro_perbit_rfu1_ctrl4 << 12 >> 30 << 26)) & 0xCFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch196 = (sdram->emc_emem_arb_refpb_bank_ctrl >> 31 << 31) | (2 * ((sdram->emc_emem_arb_refpb_bank_ctrl << 17 >> 25 << 24) | ((sdram->emc_emem_arb_refpb_bank_ctrl << 17) & 0xFFFFFF | ((sdram->emc_dyn_self_ref_control >> 31 << 16) | (sdram->emc_dyn_self_ref_control & 0xFFFF | (pmc->scratch196 >> 16 << 16)) & 0xFFFEFFFF) & 0xFF01FFFF) & 0x80FFFFFF) >> 1); +// pmc->scratch197 = (sdram->emc_pmacro_tx_sel_clk_src5 << 24 >> 31 << 31) | (2 * ((sdram->emc_pmacro_tx_sel_clk_src5 << 25 >> 31 << 30) | ((sdram->emc_pmacro_tx_sel_clk_src5 << 26 >> 31 << 29) | ((sdram->emc_pmacro_perbit_rfu1_ctrl5 << 10 >> 30 << 27) | (((sdram->emc_pmacro_perbit_rfu1_ctrl5 << 14 >> 30 << 23) | ((sdram->emc_pmacro_perbit_rfu1_ctrl5 << 26 >> 30 << 21) | ((sdram->emc_pmacro_perbit_rfu1_ctrl5 << 28 >> 30 << 19) | ((sdram->emc_pmacro_perbit_rfu1_ctrl5 << 17) & 0x7FFFF | ((16 * sdram->emc_pmacro_cmd_pad_rx_ctrl >> 28 << 13) | ((sdram->emc_pmacro_cmd_pad_rx_ctrl << 8 >> 31 << 12) | ((sdram->emc_pmacro_cmd_pad_rx_ctrl << 9 >> 31 << 11) | ((sdram->emc_pmacro_cmd_pad_rx_ctrl << 10 >> 31 << 10) | ((sdram->emc_pmacro_cmd_pad_rx_ctrl << 12 >> 28 << 6) | (32 * (sdram->emc_pmacro_cmd_pad_rx_ctrl << 16 >> 31) | (16 * (sdram->emc_pmacro_cmd_pad_rx_ctrl << 19 >> 31) | (4 * (sdram->emc_pmacro_cmd_pad_rx_ctrl << 26 >> 30) | (sdram->emc_pmacro_cmd_pad_rx_ctrl & 3 | 4 * (pmc->scratch197 >> 2)) & 0xFFFFFFF3) & 0xFFFFFFEF) & 0xFFFFFFDF) & 0xFFFFFC3F) & 0xFFFFFBFF) & 0xFFFFF7FF) & 0xFFFFEFFF) & 0xFFFE1FFF) & 0xFFF9FFFF) & 0xFFE7FFFF) & 0xFF9FFFFF) & 0xFE7FFFFF) & 0xF9FFFFFF | (sdram->emc_pmacro_perbit_rfu1_ctrl5 << 12 >> 30 << 25)) & 0xE7FFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch198 = (sdram->emc_pmacro_cmd_pad_tx_ctrl << 31) | (2 * ((32 * sdram->emc_pmacro_tx_sel_clk_src5 >> 31 << 30) | ((sdram->emc_pmacro_tx_sel_clk_src5 << 6 >> 31 << 29) | ((sdram->emc_pmacro_tx_sel_clk_src5 << 7 >> 31 << 28) | ((sdram->emc_pmacro_tx_sel_clk_src5 << 8 >> 31 << 27) | ((sdram->emc_pmacro_tx_sel_clk_src5 << 9 >> 31 << 26) | ((sdram->emc_pmacro_tx_sel_clk_src5 << 10 >> 31 << 25) | ((sdram->emc_pmacro_tx_sel_clk_src5 << 11 >> 31 << 24) | ((sdram->emc_pmacro_tx_sel_clk_src5 << 12 >> 31 << 23) | ((sdram->emc_pmacro_tx_sel_clk_src5 << 13 >> 31 << 22) | ((sdram->emc_pmacro_tx_sel_clk_src5 << 14 >> 31 << 21) | ((sdram->emc_pmacro_tx_sel_clk_src5 << 15 >> 31 << 20) | ((sdram->emc_pmacro_tx_sel_clk_src5 << 21 >> 31 << 19) | ((sdram->emc_pmacro_tx_sel_clk_src5 << 22 >> 31 << 18) | ((sdram->emc_pmacro_tx_sel_clk_src5 << 23 >> 31 << 17) | ((16 * sdram->emc_pmacro_data_pad_rx_ctrl >> 28 << 13) | ((sdram->emc_pmacro_data_pad_rx_ctrl << 8 >> 31 << 12) | ((sdram->emc_pmacro_data_pad_rx_ctrl << 9 >> 31 << 11) | ((sdram->emc_pmacro_data_pad_rx_ctrl << 10 >> 31 << 10) | ((sdram->emc_pmacro_data_pad_rx_ctrl << 12 >> 28 << 6) | (32 * (sdram->emc_pmacro_data_pad_rx_ctrl << 16 >> 31) | (16 * (sdram->emc_pmacro_data_pad_rx_ctrl << 19 >> 31) | (4 * (sdram->emc_pmacro_data_pad_rx_ctrl << 26 >> 30) | (sdram->emc_pmacro_data_pad_rx_ctrl & 3 | 4 * (pmc->scratch198 >> 2)) & 0xFFFFFFF3) & 0xFFFFFFEF) & 0xFFFFFFDF) & 0xFFFFFC3F) & 0xFFFFFBFF) & 0xFFFFF7FF) & 0xFFFFEFFF) & 0xFFFE1FFF) & 0xFFFDFFFF) & 0xFFFBFFFF) & 0xFFF7FFFF) & 0xFFEFFFFF) & 0xFFDFFFFF) & 0xFFBFFFFF) & 0xFF7FFFFF) & 0xFEFFFFFF) & 0xFDFFFFFF) & 0xFBFFFFFF) & 0xF7FFFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch199 = (8 * sdram->emc_cmd_q >> 27 << 27) | ((sdram->emc_cmd_q << 17 >> 29 << 24) | ((sdram->emc_cmd_q << 21 >> 29 << 21) | ((sdram->emc_cmd_q << 16) & 0x1FFFFF | (((u16)(sdram->emc_refresh) << 16 >> 22 << 6) | (sdram->emc_refresh & 0x3F | (pmc->scratch199 >> 6 << 6)) & 0xFFFF003F) & 0xFFE0FFFF) & 0xFF1FFFFF) & 0xF8FFFFFF) & 0x7FFFFFF; +// pmc->scratch210 = (sdram->emc_auto_cal_vref_sel1 << 16 >> 31 << 31) | (2 * ((sdram->emc_auto_cal_vref_sel1 << 17 >> 25 << 24) | ((sdram->emc_auto_cal_vref_sel1 << 24 >> 31 << 23) | ((sdram->emc_auto_cal_vref_sel1 << 16) & 0x7FFFFF | (sdram->emc_acpd_control & 0xFFFF | (pmc->scratch210 >> 16 << 16)) & 0xFF80FFFF) & 0xFF7FFFFF) & 0x80FFFFFF) >> 1); +// tmp = 8 * (sdram->emc_pmacro_auto_cal_cfg0 << 28 >> 31) | (4 * (sdram->emc_pmacro_auto_cal_cfg0 << 29 >> 31) | (2 * (sdram->emc_pmacro_auto_cal_cfg0 << 30 >> 31) | (sdram->emc_pmacro_auto_cal_cfg0 & 1 | 2 * (pmc->scratch211 >> 1)) & 0xFFFFFFFD) & 0xFFFFFFFB) & 0xFFFFFFF7; +// tmp = (sdram->emc_pmacro_auto_cal_cfg1 << 7 >> 31 << 28) | ((sdram->emc_pmacro_auto_cal_cfg1 << 12 >> 31 << 27) | ((sdram->emc_pmacro_auto_cal_cfg1 << 13 >> 31 << 26) | ((sdram->emc_pmacro_auto_cal_cfg1 << 14 >> 31 << 25) | ((sdram->emc_pmacro_auto_cal_cfg1 << 15 >> 31 << 24) | ((sdram->emc_pmacro_auto_cal_cfg1 << 20 >> 31 << 23) | ((sdram->emc_pmacro_auto_cal_cfg1 << 21 >> 31 << 22) | ((sdram->emc_pmacro_auto_cal_cfg1 << 22 >> 31 << 21) | ((sdram->emc_pmacro_auto_cal_cfg1 << 23 >> 31 << 20) | ((sdram->emc_pmacro_auto_cal_cfg1 << 28 >> 31 << 19) | ((sdram->emc_pmacro_auto_cal_cfg1 << 29 >> 31 << 18) | ((sdram->emc_pmacro_auto_cal_cfg1 << 30 >> 31 << 17) | ((sdram->emc_pmacro_auto_cal_cfg1 << 16) & 0x1FFFF | ((16 * sdram->emc_pmacro_auto_cal_cfg0 >> 31 << 15) | ((32 * sdram->emc_pmacro_auto_cal_cfg0 >> 31 << 14) | ((sdram->emc_pmacro_auto_cal_cfg0 << 6 >> 31 << 13) | ((sdram->emc_pmacro_auto_cal_cfg0 << 7 >> 31 << 12) | ((sdram->emc_pmacro_auto_cal_cfg0 << 12 >> 31 << 11) | ((sdram->emc_pmacro_auto_cal_cfg0 << 13 >> 31 << 10) | ((sdram->emc_pmacro_auto_cal_cfg0 << 14 >> 31 << 9) | ((sdram->emc_pmacro_auto_cal_cfg0 << 15 >> 31 << 8) | ((sdram->emc_pmacro_auto_cal_cfg0 << 20 >> 31 << 7) | ((sdram->emc_pmacro_auto_cal_cfg0 << 21 >> 31 << 6) | (32 * (sdram->emc_pmacro_auto_cal_cfg0 << 22 >> 31) | (16 * (sdram->emc_pmacro_auto_cal_cfg0 << 23 >> 31) | tmp & 0xFFFFFFEF) & 0xFFFFFFDF) & 0xFFFFFFBF) & 0xFFFFFF7F) & 0xFFFFFEFF) & 0xFFFFFDFF) & 0xFFFFFBFF) & 0xFFFFF7FF) & 0xFFFFEFFF) & 0xFFFFDFFF) & 0xFFFFBFFF) & 0xFFFF7FFF) & 0xFFFEFFFF) & 0xFFFDFFFF) & 0xFFFBFFFF) & 0xFFF7FFFF) & 0xFFEFFFFF) & 0xFFDFFFFF) & 0xFFBFFFFF) & 0xFF7FFFFF) & 0xFEFFFFFF) & 0xFDFFFFFF) & 0xFBFFFFFF) & 0xF7FFFFFF) & 0xEFFFFFFF; +// pmc->scratch211 = (16 * sdram->emc_pmacro_auto_cal_cfg1 >> 31 << 31) | (2 * ((32 * sdram->emc_pmacro_auto_cal_cfg1 >> 31 << 30) | ((sdram->emc_pmacro_auto_cal_cfg1 << 6 >> 31 << 29) | tmp & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->scratch212 = (sdram->emc_xm2_comp_pad_ctrl3 << 8 >> 28 << 28) | ((sdram->emc_xm2_comp_pad_ctrl3 << 14 >> 31 << 27) | ((sdram->emc_xm2_comp_pad_ctrl3 << 15 >> 31 << 26) | ((sdram->emc_xm2_comp_pad_ctrl3 << 16 >> 30 << 24) | ((sdram->emc_xm2_comp_pad_ctrl3 << 18 >> 30 << 22) | ((sdram->emc_xm2_comp_pad_ctrl3 << 26 >> 28 << 18) | ((sdram->emc_xm2_comp_pad_ctrl3 << 16) & 0x3FFFF | ((16 * sdram->emc_pmacro_auto_cal_cfg2 >> 31 << 15) | ((32 * sdram->emc_pmacro_auto_cal_cfg2 >> 31 << 14) | ((sdram->emc_pmacro_auto_cal_cfg2 << 6 >> 31 << 13) | ((sdram->emc_pmacro_auto_cal_cfg2 << 7 >> 31 << 12) | ((sdram->emc_pmacro_auto_cal_cfg2 << 12 >> 31 << 11) | ((sdram->emc_pmacro_auto_cal_cfg2 << 13 >> 31 << 10) | ((sdram->emc_pmacro_auto_cal_cfg2 << 14 >> 31 << 9) | ((sdram->emc_pmacro_auto_cal_cfg2 << 15 >> 31 << 8) | ((sdram->emc_pmacro_auto_cal_cfg2 << 20 >> 31 << 7) | ((sdram->emc_pmacro_auto_cal_cfg2 << 21 >> 31 << 6) | (32 * (sdram->emc_pmacro_auto_cal_cfg2 << 22 >> 31) | (16 * (sdram->emc_pmacro_auto_cal_cfg2 << 23 >> 31) | (8 * (sdram->emc_pmacro_auto_cal_cfg2 << 28 >> 31) | (4 * (sdram->emc_pmacro_auto_cal_cfg2 << 29 >> 31) | (2 * (sdram->emc_pmacro_auto_cal_cfg2 << 30 >> 31) | (sdram->emc_pmacro_auto_cal_cfg2 & 1 | 2 * (pmc->scratch212 >> 1)) & 0xFFFFFFFD) & 0xFFFFFFFB) & 0xFFFFFFF7) & 0xFFFFFFEF) & 0xFFFFFFDF) & 0xFFFFFFBF) & 0xFFFFFF7F) & 0xFFFFFEFF) & 0xFFFFFDFF) & 0xFFFFFBFF) & 0xFFFFF7FF) & 0xFFFFEFFF) & 0xFFFFDFFF) & 0xFFFFBFFF) & 0xFFFF7FFF) & 0xFFFCFFFF) & 0xFFC3FFFF) & 0xFF3FFFFF) & 0xFCFFFFFF) & 0xFBFFFFFF) & 0xF7FFFFFF) & 0xFFFFFFF; +// pmc->scratch213 = ((u16)(sdram->emc_prerefresh_req_cnt) << 16) | (u16)(sdram->emc_cfg_dig_dll_period); +// pmc->scratch214 = (sdram->emc_pmacro_data_pi_ctrl << 10 >> 26 << 26) | ((sdram->emc_pmacro_data_pi_ctrl << 19 >> 31 << 25) | ((sdram->emc_pmacro_data_pi_ctrl << 20 >> 28 << 21) | ((sdram->emc_pmacro_data_pi_ctrl << 27 >> 31 << 20) | ((sdram->emc_pmacro_data_pi_ctrl << 16) & 0xFFFFF | ((sdram->emc_pmacro_ddll_bypass >> 31 << 15) | ((2 * sdram->emc_pmacro_ddll_bypass >> 31 << 14) | ((4 * sdram->emc_pmacro_ddll_bypass >> 31 << 13) | ((16 * sdram->emc_pmacro_ddll_bypass >> 31 << 12) | ((32 * sdram->emc_pmacro_ddll_bypass >> 31 << 11) | ((sdram->emc_pmacro_ddll_bypass << 6 >> 31 << 10) | ((sdram->emc_pmacro_ddll_bypass << 7 >> 31 << 9) | ((sdram->emc_pmacro_ddll_bypass << 15 >> 31 << 8) | ((sdram->emc_pmacro_ddll_bypass << 16 >> 31 << 7) | ((sdram->emc_pmacro_ddll_bypass << 17 >> 31 << 6) | (32 * (sdram->emc_pmacro_ddll_bypass << 18 >> 31) | (16 * (sdram->emc_pmacro_ddll_bypass << 20 >> 31) | (8 * (sdram->emc_pmacro_ddll_bypass << 21 >> 31) | (4 * (sdram->emc_pmacro_ddll_bypass << 22 >> 31) | (2 * (sdram->emc_pmacro_ddll_bypass << 23 >> 31) | (sdram->emc_pmacro_ddll_bypass & 1 | 2 * (pmc->scratch214 >> 1)) & 0xFFFFFFFD) & 0xFFFFFFFB) & 0xFFFFFFF7) & 0xFFFFFFEF) & 0xFFFFFFDF) & 0xFFFFFFBF) & 0xFFFFFF7F) & 0xFFFFFEFF) & 0xFFFFFDFF) & 0xFFFFFBFF) & 0xFFFFF7FF) & 0xFFFFEFFF) & 0xFFFFDFFF) & 0xFFFFBFFF) & 0xFFFF7FFF) & 0xFFF0FFFF) & 0xFFEFFFFF) & 0xFE1FFFFF) & 0xFDFFFFFF) & 0x3FFFFFF; +// pmc->scratch215 = (sdram->emc_pmacro_cmd_pi_ctrl << 10 >> 26 << 10) | ((sdram->emc_pmacro_cmd_pi_ctrl << 19 >> 31 << 9) | (32 * (sdram->emc_pmacro_cmd_pi_ctrl << 20 >> 28) | (16 * (sdram->emc_pmacro_cmd_pi_ctrl << 27 >> 31) | (sdram->emc_pmacro_cmd_pi_ctrl & 0xF | 16 * (pmc->scratch215 >> 4)) & 0xFFFFFFEF) & 0xFFFFFE1F) & 0xFFFFFDFF) & 0xFFFF03FF; +// tmp = (sdram->emc_pmacro_data_pad_tx_ctrl << 7 >> 31 << 24) | ((sdram->emc_pmacro_data_pad_tx_ctrl << 8 >> 31 << 23) | ((sdram->emc_pmacro_data_pad_tx_ctrl << 9 >> 31 << 22) | ((sdram->emc_pmacro_data_pad_tx_ctrl << 10 >> 31 << 21) | ((sdram->emc_pmacro_data_pad_tx_ctrl << 15 >> 31 << 20) | ((sdram->emc_pmacro_data_pad_tx_ctrl << 16 >> 31 << 19) | ((sdram->emc_pmacro_data_pad_tx_ctrl << 21 >> 31 << 18) | ((sdram->emc_pmacro_data_pad_tx_ctrl << 25 >> 31 << 17) | ((sdram->emc_pmacro_data_pad_tx_ctrl << 26 >> 31 << 16) | ((sdram->emc_pmacro_data_pad_tx_ctrl << 15) & 0xFFFF | ((2 * sdram->emc_pmacro_cmd_pad_tx_ctrl >> 31 << 14) | ((4 * sdram->emc_pmacro_cmd_pad_tx_ctrl >> 31 << 13) | ((8 * sdram->emc_pmacro_cmd_pad_tx_ctrl >> 31 << 12) | ((16 * sdram->emc_pmacro_cmd_pad_tx_ctrl >> 31 << 11) | ((32 * sdram->emc_pmacro_cmd_pad_tx_ctrl >> 31 << 10) | ((sdram->emc_pmacro_cmd_pad_tx_ctrl << 6 >> 31 << 9) | ((sdram->emc_pmacro_cmd_pad_tx_ctrl << 7 >> 31 << 8) | ((sdram->emc_pmacro_cmd_pad_tx_ctrl << 8 >> 31 << 7) | ((sdram->emc_pmacro_cmd_pad_tx_ctrl << 9 >> 31 << 6) | (32 * (sdram->emc_pmacro_cmd_pad_tx_ctrl << 10 >> 31) | (16 * (sdram->emc_pmacro_cmd_pad_tx_ctrl << 15 >> 31) | (8 * (sdram->emc_pmacro_cmd_pad_tx_ctrl << 16 >> 31) | (4 * (sdram->emc_pmacro_cmd_pad_tx_ctrl << 21 >> 31) | (2 * (sdram->emc_pmacro_cmd_pad_tx_ctrl << 25 >> 31) | ((sdram->emc_pmacro_cmd_pad_tx_ctrl << 26 >> 31) | 2 * (pmc->scratch216 >> 1)) & 0xFFFFFFFD) & 0xFFFFFFFB) & 0xFFFFFFF7) & 0xFFFFFFEF) & 0xFFFFFFDF) & 0xFFFFFFBF) & 0xFFFFFF7F) & 0xFFFFFEFF) & 0xFFFFFDFF) & 0xFFFFFBFF) & 0xFFFFF7FF) & 0xFFFFEFFF) & 0xFFFFDFFF) & 0xFFFFBFFF) & 0xFFFF7FFF) & 0xFFFEFFFF) & 0xFFFDFFFF) & 0xFFFBFFFF) & 0xFFF7FFFF) & 0xFFEFFFFF) & 0xFFDFFFFF) & 0xFFBFFFFF) & 0xFF7FFFFF) & 0xFEFFFFFF; + +// s(emc_pin_gpio, 1:0, scratch9, 31:30); +// s(emc_pin_gpio_enable, 1:0, scratch10, 31:30); +// s(emc_dev_select, 1:0, scratch11, 31:30); +// s(emc_zcal_warm_cold_boot_enables, 1:0, scratch12, 31:30); +// s(emc_cfg_dig_dll_period_warm_boot, 1:0, scratch13, 31:30); +// s32(emc_bct_spare13, scratch45); +// s32(emc_bct_spare12, scratch46); +// s32(emc_bct_spare7, scratch47); +// s32(emc_bct_spare6, scratch48); +// s32(emc_bct_spare5, scratch50); +// s32(emc_bct_spare4, scratch51); +// s32(emc_bct_spare3, scratch56); +// s32(emc_bct_spare2, scratch57); +// s32(emc_bct_spare1, scratch58); +// s32(emc_bct_spare0, scratch59); +// s32(emc_bct_spare9, scratch60); +// s32(emc_bct_spare8, scratch61); +// s32(boot_rom_patch_data, scratch62); +// s32(boot_rom_patch_control, scratch63); +// s(mc_clken_override_allwarm_boot, 0:0, scratch65, 31:31); +// pmc->scratch66 = pmc->scratch66 & 0x1FFFFFFF | ((u8)(sdram->emc_extra_refresh_num) << 29); +// pmc->scratch72 = pmc->scratch72 & 0x8FFFFFFF | ((u16)(sdram->pmc_io_dpd3_req_wait) << 28) & 0x70000000; +// pmc->scratch72 = ((2 * pmc->scratch72) >> 1) | ((u16)(sdram->emc_clken_override_allwarm_boot) << 31); +// pmc->scratch73 = pmc->scratch73 & 0x8FFFFFFF | ((u8)(sdram->memory_type) << 28) & 0x70000000; +// pmc->scratch73 = ((2 * pmc->scratch73) >> 1) | (sdram->emc_mrs_warm_boot_enable << 31); +// pmc->scratch74 = pmc->scratch74 & 0x8FFFFFFF | (sdram->pmc_io_dpd4_req_wait << 28) & 0x70000000; +// pmc->scratch74 = ((2 * pmc->scratch74) >> 1) | (sdram->clear_clock2_mc1 << 31); +// pmc->scratch75 = pmc->scratch75 & 0xEFFFFFFF | (sdram->emc_warm_boot_extramode_reg_write_enable << 28) & 0x10000000; +// pmc->scratch75 = pmc->scratch75 & 0xDFFFFFFF | (sdram->clk_rst_pllm_misc20_override_enable << 29) & 0x20000000; +// pmc->scratch75 = pmc->scratch75 & 0xBFFFFFFF | ((u16)(sdram->emc_dbg_write_mux) << 30) & 0x40000000; +// pmc->scratch75 = ((2 * pmc->scratch75) >> 1) | ((u16)(sdram->ahb_arbitration_xbar_ctrl_meminit_done) << 31); +// pmc->scratch90 = pmc->scratch90 & 0xFFFFFF | (sdram->emc_timing_control_wait << 24); +// pmc->scratch91 = pmc->scratch91 & 0xFFFFFF | (sdram->emc_zcal_warm_boot_wait << 24); +// pmc->scratch92 = pmc->scratch92 & 0xFFFFFF | (sdram->warm_boot_wait << 24); +// pmc->scratch93 = pmc->scratch93 & 0xFFFFFF | ((u16)(sdram->emc_pin_program_wait) << 24); +// pmc->scratch114 = pmc->scratch114 & 0x3FFFFF | ((u16)(sdram->emc_auto_cal_wait) << 22); +// pmc->scratch215 = (u16)pmc->scratch215 | ((u16)(sdram->swizzle_rank_byte_encode) << 16); +// pmc->scratch216 = (2 * sdram->emc_pmacro_data_pad_tx_ctrl >> 31 << 30) | ((4 * sdram->emc_pmacro_data_pad_tx_ctrl >> 31 << 29) | ((8 * sdram->emc_pmacro_data_pad_tx_ctrl >> 31 << 28) | ((16 * sdram->emc_pmacro_data_pad_tx_ctrl >> 31 << 27) | ((32 * sdram->emc_pmacro_data_pad_tx_ctrl >> 31 << 26) | ((sdram->emc_pmacro_data_pad_tx_ctrl << 6 >> 31 << 25) | tmp & 0xFDFFFFFF) & 0xFBFFFFFF) & 0xF7FFFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF; +// s(emc_mrw_lpddr2zcal_warm_boot, 23:16, scratch5, 7:0); +// s(emc_mrw_lpddr2zcal_warm_boot, 7:0, scratch5, 15:8); +// s(emc_warm_boot_mrw_extra, 23:16, scratch5, 23:16); +// s(emc_warm_boot_mrw_extra, 7:0, scratch5, 31:24); +// s(emc_mrw_lpddr2zcal_warm_boot, 31:30, scratch6, 1:0); +// s(emc_warm_boot_mrw_extra, 31:30, scratch6, 3:2); +// s(emc_mrw_lpddr2zcal_warm_boot, 27:26, scratch6, 5:4); +// s(emc_warm_boot_mrw_extra, 27:26, scratch6, 7:6); +// s(EmcMrw6, 27:0, scratch8, 27:0); +// s(EmcMrw6, 31:30, scratch8, 29:28); +// s(EmcMrw8, 27:0, scratch9, 27:0); +// s(EmcMrw8, 31:30, scratch9, 29:28); +// s(EmcMrw9, 27:0, scratch10, 27:0); +// s(EmcMrw9, 31:30, scratch10, 29:28); +// s(EmcMrw10, 27:0, scratch11, 27:0); +// s(EmcMrw10, 31:30, scratch11, 29:28); +// s(EmcMrw12, 27:0, scratch12, 27:0); +// s(EmcMrw12, 31:30, scratch12, 29:28); +// s(EmcMrw13, 27:0, scratch13, 27:0); +// s(EmcMrw13, 31:30, scratch13, 29:28); +// s(EmcMrw14, 27:0, scratch14, 27:0); +// s(EmcMrw14, 31:30, scratch14, 29:28); +// s(EmcMrw1, 7:0, scratch15, 7:0); +// s(EmcMrw1, 23:16, scratch15, 15:8); +// s(EmcMrw1, 27:26, scratch15, 17:16); +// s(EmcMrw1, 31:30, scratch15, 19:18); +// s(emc_warm_boot_mrw_extra, 7:0, scratch16, 7:0); +// s(emc_warm_boot_mrw_extra, 23:16, scratch16, 15:8); +// s(emc_warm_boot_mrw_extra, 27:26, scratch16, 17:16); +// s(emc_warm_boot_mrw_extra, 31:30, scratch16, 19:18); +// s(emc_mrw2, 7:0, scratch17, 7:0); +// s(emc_mrw2, 23:16, scratch17, 15:8); +// s(emc_mrw2, 27:26, scratch17, 17:16); +// s(emc_mrw2, 31:30, scratch17, 19:18); +// pmc->scratch18 = (sdram->emc_mrw3 >> 30 << 18) | ((16 * sdram->emc_mrw3 >> 31 << 17) | ((32 * sdram->emc_mrw3 >> 31 << 16) | ((sdram->emc_mrw3 << 8 >> 24 << 8) | ((u8)sdram->emc_mrw3 | (pmc->scratch18 >> 8 << 8)) & 0xFFFF00FF) & 0xFFFEFFFF) & 0xFFFDFFFF) & 0xFFF3FFFF; +// pmc->scratch19 = (sdram->emc_mrw4 >> 30 << 18) | ((16 * sdram->emc_mrw4 >> 31 << 17) | ((32 * sdram->emc_mrw4 >> 31 << 16) | ((sdram->emc_mrw4 << 8 >> 24 << 8) | ((u8)sdram->emc_mrw4 | (pmc->scratch19 >> 8 << 8)) & 0xFFFF00FF) & 0xFFFEFFFF) & 0xFFFDFFFF) & 0xFFF3FFFF; +// s32(emc_cmd_mapping_byte, secure_scratch8); +// s32(emc_pmacro_brick_mapping0, secure_scratch9); +// s32(emc_pmacro_brick_mapping1, secure_scratch10); +// s32(emc_pmacro_brick_mapping2, secure_scratch11); +// s32(mc_video_protect_gpu_override0, secure_scratch12); +// pmc->secure_scratch13 = ((u16)(sdram->emc_adr_cfg) << 31) | (2 * ((((u16)(sdram->mc_untranslated_region_check) << 22) >> 31 << 30) | ((((u16)(sdram->mc_untranslated_region_check) << 23) >> 31 << 29) | (((u16)(sdram->mc_untranslated_region_check) << 28) & 0x1FFFFFFF | ((2 * sdram->emc_cmd_mapping_cmd0_0 >> 25 << 21) | ((sdram->emc_cmd_mapping_cmd0_0 << 9 >> 25 << 14) | ((sdram->emc_cmd_mapping_cmd0_0 << 17 >> 25 << 7) | (sdram->emc_cmd_mapping_cmd0_0 & 0x7F | (pmc->secure_scratch13 >> 7 << 7)) & 0xFFFFC07F) & 0xFFE03FFF) & 0xF01FFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->secure_scratch14 = (sdram->mc_video_protect_write_access << 30 >> 31 << 31) | (2 * ((sdram->mc_video_protect_write_access << 30) | ((sdram->mc_video_protect_bom_adr_hi << 30 >> 2) | ((2 * sdram->emc_cmd_mapping_cmd0_1 >> 25 << 21) | ((sdram->emc_cmd_mapping_cmd0_1 << 9 >> 25 << 14) | ((sdram->emc_cmd_mapping_cmd0_1 << 17 >> 25 << 7) | (sdram->emc_cmd_mapping_cmd0_1 & 0x7F | (pmc->secure_scratch14 >> 7 << 7)) & 0xFFFFC07F) & 0xFFE03FFF) & 0xF01FFFFF) & 0xCFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->secure_scratch15 = ((u16)(sdram->mc_mts_carveout_adr_hi) << 30) | (4 * ((sdram->mc_sec_carveout_adr_hi << 28) | ((2 * sdram->emc_cmd_mapping_cmd1_0 >> 25 << 21) | ((sdram->emc_cmd_mapping_cmd1_0 << 9 >> 25 << 14) | ((sdram->emc_cmd_mapping_cmd1_0 << 17 >> 25 << 7) | (sdram->emc_cmd_mapping_cmd1_0 & 0x7F | (pmc->secure_scratch15 >> 7 << 7)) & 0xFFFFC07F) & 0xFFE03FFF) & 0xF01FFFFF) & 0xCFFFFFFF) >> 2); +// pmc->secure_scratch16 = (sdram->mc_generalized_carveout3_bom_hi << 30) | (4 * ((sdram->mc_generalized_carveout5_bom_hi << 28) | ((2 * sdram->emc_cmd_mapping_cmd1_1 >> 25 << 21) | ((sdram->emc_cmd_mapping_cmd1_1 << 9 >> 25 << 14) | ((sdram->emc_cmd_mapping_cmd1_1 << 17 >> 25 << 7) | (sdram->emc_cmd_mapping_cmd1_1 & 0x7F | (pmc->secure_scratch16 >> 7 << 7)) & 0xFFFFC07F) & 0xFFE03FFF) & 0xF01FFFFF) & 0xCFFFFFFF) >> 2); +// pmc->secure_scratch17 = ((u16)(sdram->mc_generalized_carveout4_bom_hi) << 30) | (4 * (((u16)(sdram->mc_generalized_carveout2_bom_hi) << 28) | ((2 * sdram->emc_cmd_mapping_cmd2_0 >> 25 << 21) | ((sdram->emc_cmd_mapping_cmd2_0 << 9 >> 25 << 14) | ((sdram->emc_cmd_mapping_cmd2_0 << 17 >> 25 << 7) | (sdram->emc_cmd_mapping_cmd2_0 & 0x7F | (pmc->secure_scratch17 >> 7 << 7)) & 0xFFFFC07F) & 0xFFE03FFF) & 0xF01FFFFF) & 0xCFFFFFFF) >> 2); +// pmc->secure_scratch18 = (sdram->emc_fbio_cfg8 << 16 >> 31 << 31) | (2 * (((u16)(sdram->emc_fbio_spare) << 30 >> 31 << 30) | ((sdram->mc_generalized_carveout1_bom_hi << 30 >> 2) | ((2 * sdram->emc_cmd_mapping_cmd2_1 >> 25 << 21) | ((sdram->emc_cmd_mapping_cmd2_1 << 9 >> 25 << 14) | ((sdram->emc_cmd_mapping_cmd2_1 << 17 >> 25 << 7) | (sdram->emc_cmd_mapping_cmd2_1 & 0x7F | (pmc->secure_scratch18 >> 7 << 7)) & 0xFFFFC07F) & 0xFFE03FFF) & 0xF01FFFFF) & 0xCFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->secure_scratch19 = (sdram->mc_video_protect_vpr_override << 31) | (2 * (((u16)(sdram->mc_mts_carveout_reg_ctrl) << 30) | ((sdram->mc_sec_carveout_protect_write_access << 31 >> 2) | (((u16)(sdram->mc_emem_adr_cfg) << 28) & 0x1FFFFFFF | ((2 * sdram->emc_cmd_mapping_cmd3_0 >> 25 << 21) | ((sdram->emc_cmd_mapping_cmd3_0 << 9 >> 25 << 14) | ((sdram->emc_cmd_mapping_cmd3_0 << 17 >> 25 << 7) | (sdram->emc_cmd_mapping_cmd3_0 & 0x7F | (pmc->secure_scratch19 >> 7 << 7)) & 0xFFFFC07F) & 0xFFE03FFF) & 0xF01FFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->secure_scratch20 = (sdram->mc_generalized_carveout2_cfg0 << 25 >> 28 << 28) | ((2 * sdram->emc_cmd_mapping_cmd3_1 >> 25 << 21) | ((sdram->emc_cmd_mapping_cmd3_1 << 9 >> 25 << 14) | ((sdram->emc_cmd_mapping_cmd3_1 << 17 >> 25 << 7) | (sdram->emc_cmd_mapping_cmd3_1 & 0x7F | (pmc->secure_scratch20 >> 7 << 7)) & 0xFFFFC07F) & 0xFFE03FFF) & 0xF01FFFFF) & 0xFFFFFFF; +// pmc->secure_scratch39 = (sdram->mc_video_protect_vpr_override << 30 >> 31 << 31) | (2 * ((sdram->mc_generalized_carveout2_cfg0 << 21 >> 28 << 27) | ((32 * sdram->mc_generalized_carveout4_cfg0 >> 31 << 26) | ((sdram->mc_generalized_carveout4_cfg0 << 6 >> 31 << 25) | ((sdram->mc_generalized_carveout4_cfg0 << 7 >> 31 << 24) | ((sdram->mc_generalized_carveout4_cfg0 << 8 >> 31 << 23) | ((sdram->mc_generalized_carveout4_cfg0 << 9 >> 31 << 22) | ((sdram->mc_generalized_carveout4_cfg0 << 10 >> 28 << 18) | ((sdram->mc_generalized_carveout4_cfg0 << 14 >> 28 << 14) | ((sdram->mc_generalized_carveout4_cfg0 << 18 >> 29 << 11) | ((sdram->mc_generalized_carveout4_cfg0 << 21 >> 28 << 7) | (8 * (sdram->mc_generalized_carveout4_cfg0 << 25 >> 28) | (4 * (sdram->mc_generalized_carveout4_cfg0 << 29 >> 31) | (2 * (sdram->mc_generalized_carveout4_cfg0 << 30 >> 31) | (sdram->mc_generalized_carveout4_cfg0 & 1 | 2 * (pmc->secure_scratch39 >> 1)) & 0xFFFFFFFD) & 0xFFFFFFFB) & 0xFFFFFF87) & 0xFFFFF87F) & 0xFFFFC7FF) & 0xFFFC3FFF) & 0xFFC3FFFF) & 0xFFBFFFFF) & 0xFF7FFFFF) & 0xFEFFFFFF) & 0xFDFFFFFF) & 0xFBFFFFFF) & 0x87FFFFFF) >> 1); +// pmc->secure_scratch40 = (sdram->mc_video_protect_vpr_override << 29 >> 31 << 31) | (2 * ((sdram->mc_generalized_carveout2_cfg0 << 14 >> 28 << 27) | ((32 * sdram->mc_generalized_carveout5_cfg0 >> 31 << 26) | ((sdram->mc_generalized_carveout5_cfg0 << 6 >> 31 << 25) | ((sdram->mc_generalized_carveout5_cfg0 << 7 >> 31 << 24) | ((sdram->mc_generalized_carveout5_cfg0 << 8 >> 31 << 23) | ((sdram->mc_generalized_carveout5_cfg0 << 9 >> 31 << 22) | ((sdram->mc_generalized_carveout5_cfg0 << 10 >> 28 << 18) | ((sdram->mc_generalized_carveout5_cfg0 << 14 >> 28 << 14) | ((sdram->mc_generalized_carveout5_cfg0 << 18 >> 29 << 11) | ((sdram->mc_generalized_carveout5_cfg0 << 21 >> 28 << 7) | (8 * (sdram->mc_generalized_carveout5_cfg0 << 25 >> 28) | (4 * (sdram->mc_generalized_carveout5_cfg0 << 29 >> 31) | (2 * (sdram->mc_generalized_carveout5_cfg0 << 30 >> 31) | (sdram->mc_generalized_carveout5_cfg0 & 1 | 2 * (pmc->secure_scratch40 >> 1)) & 0xFFFFFFFD) & 0xFFFFFFFB) & 0xFFFFFF87) & 0xFFFFF87F) & 0xFFFFC7FF) & 0xFFFC3FFF) & 0xFFC3FFFF) & 0xFFBFFFFF) & 0xFF7FFFFF) & 0xFEFFFFFF) & 0xFDFFFFFF) & 0xFBFFFFFF) & 0x87FFFFFF) >> 1); +// pmc->secure_scratch41 = (sdram->mc_generalized_carveout2_cfg0 << 18 >> 29 << 29) | ((sdram->mc_generalized_carveout2_cfg0 << 10 >> 28 << 25) | ((16 * sdram->emc_cmd_mapping_cmd0_2 >> 28 << 21) | ((sdram->emc_cmd_mapping_cmd0_2 << 9 >> 25 << 14) | ((sdram->emc_cmd_mapping_cmd0_2 << 17 >> 25 << 7) | (sdram->emc_cmd_mapping_cmd0_2 & 0x7F | (pmc->secure_scratch41 >> 7 << 7)) & 0xFFFFC07F) & 0xFFE03FFF) & 0xFE1FFFFF) & 0xE1FFFFFF) & 0x1FFFFFFF; +// pmc->secure_scratch42 = ((u16)(sdram->mc_generalized_carveout1_cfg0) << 18 >> 29 << 29) | (((u16)(sdram->mc_generalized_carveout1_cfg0) << 25 >> 28 << 25) | ((16 * sdram->emc_cmd_mapping_cmd1_2 >> 28 << 21) | ((sdram->emc_cmd_mapping_cmd1_2 << 9 >> 25 << 14) | ((sdram->emc_cmd_mapping_cmd1_2 << 17 >> 25 << 7) | (sdram->emc_cmd_mapping_cmd1_2 & 0x7F | (pmc->secure_scratch42 >> 7 << 7)) & 0xFFFFC07F) & 0xFFE03FFF) & 0xFE1FFFFF) & 0xE1FFFFFF) & 0x1FFFFFFF; +// pmc->secure_scratch43 = ((u16)(sdram->mc_generalized_carveout3_cfg0) << 18 >> 29 << 29) | (((u16)(sdram->mc_generalized_carveout1_cfg0) << 21 >> 28 << 25) | ((16 * sdram->emc_cmd_mapping_cmd2_2 >> 28 << 21) | ((sdram->emc_cmd_mapping_cmd2_2 << 9 >> 25 << 14) | ((sdram->emc_cmd_mapping_cmd2_2 << 17 >> 25 << 7) | (sdram->emc_cmd_mapping_cmd2_2 & 0x7F | (pmc->secure_scratch43 >> 7 << 7)) & 0xFFFFC07F) & 0xFFE03FFF) & 0xFE1FFFFF) & 0xE1FFFFFF) & 0x1FFFFFFF; +// pmc->secure_scratch44 = (sdram->mc_video_protect_vpr_override << 24 >> 31 << 31) | (2 * ((sdram->mc_video_protect_vpr_override << 25 >> 31 << 30) | ((sdram->mc_video_protect_vpr_override << 28 >> 31 << 29) | ((sdram->mc_generalized_carveout1_cfg0 << 14 >> 28 << 25) | ((16 * sdram->emc_cmd_mapping_cmd3_2 >> 28 << 21) | ((sdram->emc_cmd_mapping_cmd3_2 << 9 >> 25 << 14) | ((sdram->emc_cmd_mapping_cmd3_2 << 17 >> 25 << 7) | (sdram->emc_cmd_mapping_cmd3_2 & 0x7F | (pmc->secure_scratch44 >> 7 << 7)) & 0xFFFFC07F) & 0xFFE03FFF) & 0xFE1FFFFF) & 0xE1FFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// s(mc_emem_adr_cfg_channel_mask, 31:9, secure_scratch45, 22:0); +// s(mc_emem_adr_cfg_dev0, 2:0, secure_scratch45, 25:23); +// s(mc_emem_adr_cfg_dev0, 9:8, secure_scratch45, 27:26); +// s(mc_emem_adr_cfg_dev0, 19:16, secure_scratch45, 31:28); +// pmc->secure_scratch46 = (sdram->mc_video_protect_vpr_override << 23 >> 31 << 31) | (2 * ((sdram->mc_emem_adr_cfg_dev1 << 12 >> 28 << 27) | ((sdram->mc_emem_adr_cfg_dev1 << 22 >> 30 << 25) | ((sdram->mc_emem_adr_cfg_dev1 << 22) & 0x1FFFFFF | ((sdram->mc_emem_adr_cfg_bank_mask0 >> 10) | (pmc->secure_scratch46 >> 22 << 22)) & 0xFE3FFFFF) & 0xF9FFFFFF) & 0x87FFFFFF) >> 1); +// pmc->secure_scratch47 = (sdram->mc_video_protect_vpr_override << 20 >> 31 << 31) | (2 * ((sdram->mc_video_protect_vpr_override << 22 >> 31 << 30) | (((u8)(sdram->mc_generalized_carveout3_cfg0) << 25 >> 28 << 26) | ((sdram->mc_generalized_carveout1_cfg0 << 10 >> 28 << 22) | ((sdram->mc_emem_adr_cfg_bank_mask1 >> 10) | (pmc->secure_scratch47 >> 22 << 22)) & 0xFC3FFFFF) & 0xC3FFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->secure_scratch48 = (sdram->mc_video_protect_vpr_override << 16 >> 31 << 31) | (2 * ((sdram->mc_video_protect_vpr_override << 17 >> 31 << 30) | ((sdram->mc_generalized_carveout3_cfg0 << 14 >> 28 << 26) | ((sdram->mc_generalized_carveout3_cfg0 << 21 >> 28 << 22) | ((sdram->mc_emem_adr_cfg_bank_mask2 >> 10) | (pmc->secure_scratch48 >> 22 << 22)) & 0xFC3FFFFF) & 0xC3FFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->secure_scratch49 = (sdram->mc_video_protect_vpr_override << 14 >> 31 << 31) | (2 * ((sdram->mc_emem_cfg >> 31 << 30) | ((sdram->mc_emem_cfg << 18 >> 2) | (sdram->mc_video_protect_gpu_override1 & 0xFFFF | (pmc->secure_scratch49 >> 16 << 16)) & 0xC000FFFF) & 0xBFFFFFFF) >> 1); +// pmc->secure_scratch50 = (sdram->mc_video_protect_vpr_override << 12 >> 31 << 31) | (2 * ((sdram->mc_video_protect_vpr_override << 13 >> 31 << 30) | ((sdram->mc_generalized_carveout1_bom >> 17 << 15) | ((sdram->mc_generalized_carveout3_bom >> 17) | (pmc->secure_scratch50 >> 15 << 15)) & 0xC0007FFF) & 0xBFFFFFFF) >> 1); +// pmc->secure_scratch51 = (sdram->mc_video_protect_vpr_override << 10 >> 31 << 31) | (2 * ((sdram->mc_video_protect_vpr_override << 11 >> 31 << 30) | ((sdram->mc_generalized_carveout2_bom >> 17 << 15) | ((sdram->mc_generalized_carveout4_bom >> 17) | (pmc->secure_scratch51 >> 15 << 15)) & 0xC0007FFF) & 0xBFFFFFFF) >> 1); +// pmc->secure_scratch52 = (sdram->mc_video_protect_vpr_override << 9 >> 31 << 31) | (2 * ((sdram->mc_generalized_carveout3_cfg0 << 10 >> 28 << 27) | ((sdram->mc_video_protect_bom >> 20 << 15) | ((sdram->mc_generalized_carveout5_bom >> 17) | (pmc->secure_scratch52 >> 15 << 15)) & 0xF8007FFF) & 0x87FFFFFF) >> 1); +// pmc->secure_scratch53 = (sdram->mc_video_protect_vpr_override1 << 27 >> 31 << 31) | (2 * ((sdram->mc_video_protect_vpr_override1 << 30 >> 31 << 30) | ((sdram->mc_video_protect_vpr_override1 << 31 >> 2) | ((sdram->mc_video_protect_vpr_override >> 31 << 28) | ((2 * sdram->mc_video_protect_vpr_override >> 31 << 27) | ((4 * sdram->mc_video_protect_vpr_override >> 31 << 26) | ((32 * sdram->mc_video_protect_vpr_override >> 31 << 25) | ((sdram->mc_video_protect_vpr_override << 8 >> 31 << 24) | ((sdram->mc_sec_carveout_bom >> 20 << 12) | (sdram->mc_video_protect_size_mb & 0xFFF | (pmc->secure_scratch53 >> 12 << 12)) & 0xFF000FFF) & 0xFEFFFFFF) & 0xFDFFFFFF) & 0xFBFFFFFF) & 0xF7FFFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->secure_scratch54 = (sdram->mc_video_protect_vpr_override1 << 19 >> 31 << 31) | (2 * ((sdram->mc_video_protect_vpr_override1 << 20 >> 31 << 30) | ((sdram->mc_video_protect_vpr_override1 << 21 >> 31 << 29) | ((sdram->mc_video_protect_vpr_override1 << 22 >> 31 << 28) | ((sdram->mc_video_protect_vpr_override1 << 23 >> 31 << 27) | ((sdram->mc_video_protect_vpr_override1 << 24 >> 31 << 26) | ((sdram->mc_video_protect_vpr_override1 << 25 >> 31 << 25) | ((sdram->mc_video_protect_vpr_override1 << 26 >> 31 << 24) | ((sdram->mc_mts_carveout_bom >> 20 << 12) | (sdram->mc_sec_carveout_size_mb & 0xFFF | (pmc->secure_scratch54 >> 12 << 12)) & 0xFF000FFF) & 0xFEFFFFFF) & 0xFDFFFFFF) & 0xFBFFFFFF) & 0xF7FFFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->secure_scratch55 = (sdram->mc_generalized_carveout2_cfg0 << 30 >> 31 << 31) | (2 * ((sdram->mc_generalized_carveout2_cfg0 << 30) | ((32 * sdram->mc_video_protect_vpr_override1 >> 31 << 29) | ((sdram->mc_video_protect_vpr_override1 << 6 >> 31 << 28) | ((sdram->mc_video_protect_vpr_override1 << 15 >> 31 << 27) | ((sdram->mc_video_protect_vpr_override1 << 16 >> 31 << 26) | ((sdram->mc_video_protect_vpr_override1 << 17 >> 31 << 25) | ((sdram->mc_video_protect_vpr_override1 << 18 >> 31 << 24) | (((u16)(sdram->mc_generalized_carveout4_size_128kb) << 12) & 0xFFFFFF | (sdram->mc_mts_carveout_size_mb & 0xFFF | (pmc->secure_scratch55 >> 12 << 12)) & 0xFF000FFF) & 0xFEFFFFFF) & 0xFDFFFFFF) & 0xFBFFFFFF) & 0xF7FFFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->secure_scratch56 = ((u16)(sdram->mc_generalized_carveout1_cfg0) << 30 >> 31 << 31) | (2 * (((u16)(sdram->mc_generalized_carveout1_cfg0) << 30) | ((32 * sdram->mc_generalized_carveout2_cfg0 >> 31 << 29) | ((sdram->mc_generalized_carveout2_cfg0 << 6 >> 31 << 28) | ((sdram->mc_generalized_carveout2_cfg0 << 7 >> 31 << 27) | ((sdram->mc_generalized_carveout2_cfg0 << 8 >> 31 << 26) | ((sdram->mc_generalized_carveout2_cfg0 << 9 >> 31 << 25) | ((sdram->mc_generalized_carveout2_cfg0 << 29 >> 31 << 24) | (((u16)(sdram->mc_generalized_carveout2_size_128kb) << 12) & 0xFFFFFF | (sdram->mc_generalized_carveout3_size_128kb & 0xFFF | (pmc->secure_scratch56 >> 12 << 12)) & 0xFF000FFF) & 0xFEFFFFFF) & 0xFDFFFFFF) & 0xFBFFFFFF) & 0xF7FFFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); +// pmc->secure_scratch57 = ((u8)(sdram->mc_generalized_carveout3_cfg0) << 30 >> 31 << 31) | (2 * (((u8)(sdram->mc_generalized_carveout3_cfg0) << 30) | ((32 * sdram->mc_generalized_carveout1_cfg0 >> 31 << 29) | ((sdram->mc_generalized_carveout1_cfg0 << 6 >> 31 << 28) | ((sdram->mc_generalized_carveout1_cfg0 << 7 >> 31 << 27) | ((sdram->mc_generalized_carveout1_cfg0 << 8 >> 31 << 26) | ((sdram->mc_generalized_carveout1_cfg0 << 9 >> 31 << 25) | ((sdram->mc_generalized_carveout1_cfg0 << 29 >> 31 << 24) | ((sdram->mc_generalized_carveout5_size_128kb << 12) & 0xFFFFFF | (sdram->mc_generalized_carveout1_size_128kb & 0xFFF | (pmc->secure_scratch57 >> 12 << 12)) & 0xFF000FFF) & 0xFEFFFFFF) & 0xFDFFFFFF) & 0xFBFFFFFF) & 0xF7FFFFFF) & 0xEFFFFFFF) & 0xDFFFFFFF) & 0xBFFFFFFF) >> 1); + +// s32(mc_generalized_carveout1_access0, secure_scratch59); +// s32(mc_generalized_carveout1_access1, secure_scratch60); +// s32(mc_generalized_carveout1_access2, secure_scratch61); +// s32(mc_generalized_carveout1_access3, secure_scratch62); +// s32(mc_generalized_carveout1_access4, secure_scratch63); +// s32(mc_generalized_carveout2_access0, secure_scratch64); +// s32(mc_generalized_carveout2_access1, secure_scratch65); +// s32(mc_generalized_carveout2_access2, secure_scratch66); +// s32(mc_generalized_carveout2_access3, secure_scratch67); +// s32(mc_generalized_carveout2_access4, secure_scratch68); +// s32(mc_generalized_carveout3_access0, secure_scratch69); +// s32(mc_generalized_carveout3_access1, secure_scratch70); +// s32(mc_generalized_carveout3_access2, secure_scratch71); +// s32(mc_generalized_carveout3_access3, secure_scratch72); +// s32(mc_generalized_carveout3_access4, secure_scratch73); +// s32(mc_generalized_carveout4_access0, secure_scratch74); +// s32(mc_generalized_carveout4_access1, secure_scratch75); +// s32(mc_generalized_carveout4_access2, secure_scratch76); +// s32(mc_generalized_carveout4_access3, secure_scratch77); +// s32(mc_generalized_carveout4_access4, secure_scratch78); +// s32(mc_generalized_carveout5_access0, secure_scratch79); +// s32(mc_generalized_carveout5_access1, secure_scratch80); +// s32(mc_generalized_carveout5_access2, secure_scratch81); +// s32(mc_generalized_carveout5_access3, secure_scratch82); +// s32(mc_generalized_carveout1_force_internal_access0, secure_scratch84); +// s32(mc_generalized_carveout1_force_internal_access1, secure_scratch85); +// s32(mc_generalized_carveout1_force_internal_access2, secure_scratch86); +// s32(mc_generalized_carveout1_force_internal_access3, secure_scratch87); +// s32(mc_generalized_carveout1_force_internal_access4, secure_scratch88); +// s32(mc_generalized_carveout2_force_internal_access0, secure_scratch89); +// s32(mc_generalized_carveout2_force_internal_access1, secure_scratch90); +// s32(mc_generalized_carveout2_force_internal_access2, secure_scratch91); +// s32(mc_generalized_carveout2_force_internal_access3, secure_scratch92); +// s32(mc_generalized_carveout2_force_internal_access4, secure_scratch93); +// s32(mc_generalized_carveout3_force_internal_access0, secure_scratch94); +// s32(mc_generalized_carveout3_force_internal_access1, secure_scratch95); +// s32(mc_generalized_carveout3_force_internal_access2, secure_scratch96); +// s32(mc_generalized_carveout3_force_internal_access3, secure_scratch97); +// s32(mc_generalized_carveout3_force_internal_access4, secure_scratch98); +// s32(mc_generalized_carveout4_force_internal_access0, secure_scratch99); +// s32(mc_generalized_carveout4_force_internal_access1, secure_scratch100); +// s32(mc_generalized_carveout4_force_internal_access2, secure_scratch101); +// s32(mc_generalized_carveout4_force_internal_access3, secure_scratch102); +// s32(mc_generalized_carveout4_force_internal_access4, secure_scratch103); +// s32(mc_generalized_carveout5_force_internal_access0, secure_scratch104); +// s32(mc_generalized_carveout5_force_internal_access1, secure_scratch105); +// s32(mc_generalized_carveout5_force_internal_access2, secure_scratch106); +// s32(mc_generalized_carveout5_force_internal_access3, secure_scratch107); + +// pmc->secure_scratch58 = 32 * (32 * sdram->mc_generalized_carveout3_cfg0 >> 31) | (16 * (sdram->mc_generalized_carveout3_cfg0 << 6 >> 31) | (8 * (sdram->mc_generalized_carveout3_cfg0 << 7 >> 31) | (4 * (sdram->mc_generalized_carveout3_cfg0 << 8 >> 31) | (2 * (sdram->mc_generalized_carveout3_cfg0 << 9 >> 31) | ((sdram->mc_generalized_carveout3_cfg0 << 29 >> 31) | 2 * (pmc->secure_scratch58 >> 1)) & 0xFFFFFFFD) & 0xFFFFFFFB) & 0xFFFFFFF7) & 0xFFFFFFEF) & 0xFFFFFFDF; + +// c32(0, scratch2); +// s(pllm_input_divider, 7:0, scratch2, 7:0); +// s(pllm_feedback_divider, 7:0, scratch2, 15:8); +// s(pllm_post_divider, 4:0, scratch2, 20:16); +// s(pllm_kvco, 0:0, scratch2, 17:17); +// s(pllm_kcp, 1:0, scratch2, 19:18); + +// c32(0, scratch35); +// s(pllm_setup_control, 15:0, scratch35, 15:0); + +// c32(0, scratch3); +// s(pllm_input_divider, 7:0, scratch3, 7:0); +// c(0x3e, scratch3, 15:8); +// c(0, scratch3, 20:16); +// s(pllm_kvco, 0:0, scratch3, 21:21); +// s(pllm_kcp, 1:0, scratch3, 23:22); + +// c32(0, scratch36); +// s(PllMSetupControl, 23:0, scratch36, 23:0); + +// c32(0, scratch4); +// s(pllm_stable_time, 9:0, scratch4, 9:0); // s32(pllm_stable_time, scratch4);, s(pllm_stable_time, 31:0, scratch4, 31:10); +// s(pllm_stable_time, 31:0, scratch4, 31:10); +// } + +#pragma GCC diagnostic pop + +void sdram_lp0_save_params(const void *params) +{ + // u32 chip_id = (APB_MISC(APB_MISC_GP_HIDREV) >> 4) & 0xF; + + // if (chip_id != GP_HIDREV_MAJOR_T210B01) + _sdram_lp0_save_params_t210(params); + // else + // _sdram_lp0_save_params_t210b01(params); +} diff --git a/bdk/mem/sdram_lp0_param_t210.h b/bdk/mem/sdram_lp0_param_t210.h index 1422ed3..09e960e 100644 --- a/bdk/mem/sdram_lp0_param_t210.h +++ b/bdk/mem/sdram_lp0_param_t210.h @@ -20,8 +20,8 @@ * directly converting BCT config files (*.cfg) into C structure. */ -#ifndef __SOC_NVIDIA_TEGRA210_SDRAM_PARAM_H__ -#define __SOC_NVIDIA_TEGRA210_SDRAM_PARAM_H__ +#ifndef __TEGRA210_SDRAM_PARAM_H__ +#define __TEGRA210_SDRAM_PARAM_H__ #include @@ -57,7 +57,7 @@ enum /** * Defines the SDRAM parameter structure */ -struct sdram_params +struct sdram_params_t210 { /* Specifies the type of memory device */ diff --git a/bdk/mem/sdram_lp0_param_t210b01.h b/bdk/mem/sdram_lp0_param_t210b01.h new file mode 100644 index 0000000..f987a1e --- /dev/null +++ b/bdk/mem/sdram_lp0_param_t210b01.h @@ -0,0 +1,990 @@ +/* + * Copyright (c) 2020 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. + */ + +#ifndef __TEGRA210B01_SDRAM_PARAM_H__ +#define __TEGRA210B01_SDRAM_PARAM_H__ + +#include + +struct sdram_params_t210b01 +{ + /* Specifies the type of memory device */ + u32 memory_type; + + /* MC/EMC clock source configuration */ + + /* Specifies the M value for PllM */ + u32 pllm_input_divider; + /* Specifies the N value for PllM */ + u32 pllm_feedback_divider; + /* Specifies the time to wait for PLLM to lock (in microseconds) */ + u32 pllm_stable_time; + /* Specifies misc. control bits */ + u32 pllm_setup_control; + /* Specifies the P value for PLLM */ + u32 pllm_post_divider; + /* Specifies value for Charge Pump Gain Control */ + u32 pllm_kcp; + /* Specifies VCO gain */ + u32 pllm_kvco; + /* Spare BCT param */ + u32 emc_bct_spare0; + /* Spare BCT param */ + u32 emc_bct_spare1; + /* Spare BCT param */ + u32 emc_bct_spare2; + /* Spare BCT param */ + u32 emc_bct_spare3; + /* Spare BCT param */ + u32 emc_bct_spare4; + /* Spare BCT param */ + u32 emc_bct_spare5; + /* Spare BCT param */ + u32 emc_bct_spare6; + /* Spare BCT param */ + u32 emc_bct_spare7; + /* Spare BCT param */ + u32 emc_bct_spare8; + /* Spare BCT param */ + u32 emc_bct_spare9; + /* Spare BCT param */ + u32 emc_bct_spare10; + /* Spare BCT param */ + u32 emc_bct_spare11; + /* Spare BCT param */ + u32 emc_bct_spare12; + /* Spare BCT param */ + u32 emc_bct_spare13; + /* Spare BCT param */ + u32 emc_bct_spare_secure0; + /* Spare BCT param */ + u32 emc_bct_spare_secure1; + /* Spare BCT param */ + u32 emc_bct_spare_secure2; + /* Spare BCT param */ + u32 emc_bct_spare_secure3; + /* Spare BCT param */ + u32 emc_bct_spare_secure4; + /* Spare BCT param */ + u32 emc_bct_spare_secure5; + /* Spare BCT param */ + u32 emc_bct_spare_secure6; + /* Spare BCT param */ + u32 emc_bct_spare_secure7; + /* Spare BCT param */ + u32 emc_bct_spare_secure8; + /* Spare BCT param */ + u32 emc_bct_spare_secure9; + /* Spare BCT param */ + u32 emc_bct_spare_secure10; + /* Spare BCT param */ + u32 emc_bct_spare_secure11; + /* Spare BCT param */ + u32 emc_bct_spare_secure12; + /* Spare BCT param */ + u32 emc_bct_spare_secure13; + /* Spare BCT param */ + u32 emc_bct_spare_secure14; + /* Spare BCT param */ + u32 emc_bct_spare_secure15; + /* Spare BCT param */ + u32 emc_bct_spare_secure16; + /* Spare BCT param */ + u32 emc_bct_spare_secure17; + /* Spare BCT param */ + u32 emc_bct_spare_secure18; + /* Spare BCT param */ + u32 emc_bct_spare_secure19; + /* Spare BCT param */ + u32 emc_bct_spare_secure20; + /* Spare BCT param */ + u32 emc_bct_spare_secure21; + /* Spare BCT param */ + u32 emc_bct_spare_secure22; + /* Spare BCT param */ + u32 emc_bct_spare_secure23; + + /* Defines EMC_2X_CLK_SRC, EMC_2X_CLK_DIVISOR, EMC_INVERT_DCD */ + u32 emc_clock_source; + u32 emc_clock_source_dll; + + /* Defines possible override for PLLLM_MISC2 */ + u32 clk_rst_pllm_misc20_override; + /* enables override for PLLLM_MISC2 */ + u32 clk_rst_pllm_misc20_override_enable; + /* defines CLK_ENB_MC1 in register clk_rst_controller_clk_enb_w_clr */ + u32 clear_clock2_mc1; + + /* Auto-calibration of EMC pads */ + + /* Specifies the value for EMC_AUTO_CAL_INTERVAL */ + u32 emc_auto_cal_interval; + /* + * Specifies the value for EMC_AUTO_CAL_CONFIG + * Note: Trigger bits are set by the SDRAM code. + */ + u32 emc_auto_cal_config; + + /* Specifies the value for EMC_AUTO_CAL_CONFIG2 */ + u32 emc_auto_cal_config2; + + /* Specifies the value for EMC_AUTO_CAL_CONFIG3 */ + u32 emc_auto_cal_config3; + u32 emc_auto_cal_config4; + u32 emc_auto_cal_config5; + u32 emc_auto_cal_config6; + u32 emc_auto_cal_config7; + u32 emc_auto_cal_config8; + u32 emc_auto_cal_config9; + + /* Specifies the value for EMC_AUTO_CAL_VREF_SEL_0 */ + u32 emc_auto_cal_vref_sel0; + u32 emc_auto_cal_vref_sel1; + + /* Specifies the value for EMC_AUTO_CAL_CHANNEL */ + u32 emc_auto_cal_channel; + + /* Specifies the value for EMC_PMACRO_AUTOCAL_CFG_0 */ + u32 emc_pmacro_auto_cal_cfg0; + u32 emc_pmacro_auto_cal_cfg1; + u32 emc_pmacro_auto_cal_cfg2; + + u32 emc_pmacro_rx_term; + u32 emc_pmacro_dq_tx_drive; + u32 emc_pmacro_ca_tx_drive; + u32 emc_pmacro_cmd_tx_drive; + u32 emc_pmacro_auto_cal_common; + u32 emc_pmacro_zcrtl; + + /* + * Specifies the time for the calibration + * to stabilize (in microseconds) + */ + u32 emc_auto_cal_wait; + + u32 emc_xm2_comp_pad_ctrl; + u32 emc_xm2_comp_pad_ctrl2; + u32 emc_xm2_comp_pad_ctrl3; + + /* + * DRAM size information + * Specifies the value for EMC_ADR_CFG + */ + u32 emc_adr_cfg; + + /* + * Specifies the time to wait after asserting pin + * CKE (in microseconds) + */ + u32 emc_pin_program_wait; + /* Specifies the extra delay before/after pin RESET/CKE command */ + u32 emc_pin_extra_wait; + + u32 emc_pin_gpio_enable; + u32 emc_pin_gpio; + + /* + * Specifies the extra delay after the first writing + * of EMC_TIMING_CONTROL + */ + u32 emc_timing_control_wait; + + /* Timing parameters required for the SDRAM */ + + /* Specifies the value for EMC_RC */ + u32 emc_rc; + /* Specifies the value for EMC_RFC */ + u32 emc_rfc; + + u32 emc_rfc_pb; + u32 emc_ref_ctrl2; + + /* Specifies the value for EMC_RFC_SLR */ + u32 emc_rfc_slr; + /* Specifies the value for EMC_RAS */ + u32 emc_ras; + /* Specifies the value for EMC_RP */ + u32 emc_rp; + /* Specifies the value for EMC_R2R */ + u32 emc_r2r; + /* Specifies the value for EMC_W2W */ + u32 emc_w2w; + /* Specifies the value for EMC_R2W */ + u32 emc_r2w; + /* Specifies the value for EMC_W2R */ + u32 emc_w2r; + /* Specifies the value for EMC_R2P */ + u32 emc_r2p; + /* Specifies the value for EMC_W2P */ + u32 emc_w2p; + /* Specifies the value for EMC_RD_RCD */ + + u32 emc_tppd; + u32 emc_trtm; + u32 emc_twtm; + u32 emc_tratm; + u32 emc_twatm; + u32 emc_tr2ref; + u32 emc_ccdmw; + + u32 emc_rd_rcd; + /* Specifies the value for EMC_WR_RCD */ + u32 emc_wr_rcd; + /* Specifies the value for EMC_RRD */ + u32 emc_rrd; + /* Specifies the value for EMC_REXT */ + u32 emc_rext; + /* Specifies the value for EMC_WEXT */ + u32 emc_wext; + /* Specifies the value for EMC_WDV */ + u32 emc_wdv; + + u32 emc_wdv_chk; + u32 emc_wsv; + u32 emc_wev; + + /* Specifies the value for EMC_WDV_MASK */ + u32 emc_wdv_mask; + + u32 emc_ws_duration; + u32 emc_we_duration; + + /* Specifies the value for EMC_QUSE */ + u32 emc_quse; + /* Specifies the value for EMC_QUSE_WIDTH */ + u32 emc_quse_width; + /* Specifies the value for EMC_IBDLY */ + u32 emc_ibdly; + + u32 emc_obdly; + + /* Specifies the value for EMC_EINPUT */ + u32 emc_einput; + /* Specifies the value for EMC_EINPUT_DURATION */ + u32 emc_einput_duration; + /* Specifies the value for EMC_PUTERM_EXTRA */ + u32 emc_puterm_extra; + /* Specifies the value for EMC_PUTERM_WIDTH */ + u32 emc_puterm_width; + + u32 emc_qrst; + u32 emc_qsafe; + u32 emc_rdv; + u32 emc_rdv_mask; + + u32 emc_rdv_early; + u32 emc_rdv_early_mask; + + /* Specifies the value for EMC_QPOP */ + u32 emc_qpop; + + /* Specifies the value for EMC_REFRESH */ + u32 emc_refresh; + /* Specifies the value for EMC_BURST_REFRESH_NUM */ + u32 emc_burst_refresh_num; + /* Specifies the value for EMC_PRE_REFRESH_REQ_CNT */ + u32 emc_prerefresh_req_cnt; + /* Specifies the value for EMC_PDEX2WR */ + u32 emc_pdex2wr; + /* Specifies the value for EMC_PDEX2RD */ + u32 emc_pdex2rd; + /* Specifies the value for EMC_PCHG2PDEN */ + u32 emc_pchg2pden; + /* Specifies the value for EMC_ACT2PDEN */ + u32 emc_act2pden; + /* Specifies the value for EMC_AR2PDEN */ + u32 emc_ar2pden; + /* Specifies the value for EMC_RW2PDEN */ + u32 emc_rw2pden; + + u32 emc_cke2pden; + u32 emc_pdex2che; + u32 emc_pdex2mrr; + + /* Specifies the value for EMC_TXSR */ + u32 emc_txsr; + /* Specifies the value for EMC_TXSRDLL */ + u32 emc_txsr_dll; + /* Specifies the value for EMC_TCKE */ + u32 emc_tcke; + /* Specifies the value for EMC_TCKESR */ + u32 emc_tckesr; + /* Specifies the value for EMC_TPD */ + u32 emc_tpd; + /* Specifies the value for EMC_TFAW */ + u32 emc_tfaw; + /* Specifies the value for EMC_TRPAB */ + u32 emc_trpab; + /* Specifies the value for EMC_TCLKSTABLE */ + u32 emc_tclkstable; + /* Specifies the value for EMC_TCLKSTOP */ + u32 emc_tclkstop; + /* Specifies the value for EMC_TREFBW */ + u32 emc_trefbw; + + /* FBIO configuration values */ + + /* Specifies the value for EMC_FBIO_CFG5 */ + u32 emc_fbio_cfg5; + /* Specifies the value for EMC_FBIO_CFG7 */ + u32 emc_fbio_cfg7; + u32 emc_fbio_cfg8; + + /* Command mapping for CMD brick 0 */ + u32 emc_cmd_mapping_cmd0_0; + u32 emc_cmd_mapping_cmd0_1; + u32 emc_cmd_mapping_cmd0_2; + u32 emc_cmd_mapping_cmd1_0; + u32 emc_cmd_mapping_cmd1_1; + u32 emc_cmd_mapping_cmd1_2; + u32 emc_cmd_mapping_cmd2_0; + u32 emc_cmd_mapping_cmd2_1; + u32 emc_cmd_mapping_cmd2_2; + u32 emc_cmd_mapping_cmd3_0; + u32 emc_cmd_mapping_cmd3_1; + u32 emc_cmd_mapping_cmd3_2; + u32 emc_cmd_mapping_byte; + + /* Specifies the value for EMC_FBIO_SPARE */ + u32 emc_fbio_spare; + + /* Specifies the value for EMC_CFG_RSV */ + u32 emc_cfg_rsv; + + /* MRS command values */ + + /* Specifies the value for EMC_MRS */ + u32 emc_mrs; + /* Specifies the MP0 command to initialize mode registers */ + u32 emc_emrs; + /* Specifies the MP2 command to initialize mode registers */ + u32 emc_emrs2; + /* Specifies the MP3 command to initialize mode registers */ + u32 emc_emrs3; + /* Specifies the programming to LPDDR2 Mode Register 1 at cold boot */ + u32 emc_mrw1; + /* Specifies the programming to LPDDR2 Mode Register 2 at cold boot */ + u32 emc_mrw2; + /* Specifies the programming to LPDDR2 Mode Register 3 at cold boot */ + u32 emc_mrw3; + /* Specifies the programming to LPDDR2 Mode Register 11 at cold boot */ + u32 emc_mrw4; + + /* Specifies the programming to LPDDR4 Mode Register 3 at cold boot */ + u32 emc_mrw6; + /* Specifies the programming to LPDDR4 Mode Register 11 at cold boot */ + u32 emc_mrw8; + /* Specifies the programming to LPDDR4 Mode Register 11 at cold boot */ + u32 emc_mrw9; + /* Specifies the programming to LPDDR4 Mode Register 12 at cold boot */ + u32 emc_mrw10; + /* Specifies the programming to LPDDR4 Mode Register 14 at cold boot */ + u32 emc_mrw12; + /* Specifies the programming to LPDDR4 Mode Register 14 at cold boot */ + u32 emc_mrw13; + /* Specifies the programming to LPDDR4 Mode Register 22 at cold boot */ + u32 emc_mrw14; + + /* + * Specifies the programming to extra LPDDR2 Mode Register + * at cold boot + */ + u32 emc_mrw_extra; + /* + * Specifies the programming to extra LPDDR2 Mode Register + * at warm boot + */ + u32 emc_warm_boot_mrw_extra; + /* + * Specify the enable of extra Mode Register programming at + * warm boot + */ + u32 emc_warm_boot_extramode_reg_write_enable; + /* + * Specify the enable of extra Mode Register programming at + * cold boot + */ + u32 emc_extramode_reg_write_enable; + + /* Specifies the EMC_MRW reset command value */ + u32 emc_mrw_reset_command; + /* Specifies the EMC Reset wait time (in microseconds) */ + u32 emc_mrw_reset_ninit_wait; + /* Specifies the value for EMC_MRS_WAIT_CNT */ + u32 emc_mrs_wait_cnt; + /* Specifies the value for EMC_MRS_WAIT_CNT2 */ + u32 emc_mrs_wait_cnt2; + + /* EMC miscellaneous configurations */ + + /* Specifies the value for EMC_CFG */ + u32 emc_cfg; + /* Specifies the value for EMC_CFG_2 */ + u32 emc_cfg2; + /* Specifies the pipe bypass controls */ + u32 emc_cfg_pipe; + + u32 emc_cfg_pipe_clk; + u32 emc_fdpd_ctrl_cmd_no_ramp; + u32 emc_cfg_update; + + /* Specifies the value for EMC_DBG */ + u32 emc_dbg; + + u32 emc_dbg_write_mux; + + /* Specifies the value for EMC_CMDQ */ + u32 emc_cmd_q; + /* Specifies the value for EMC_MC2EMCQ */ + u32 emc_mc2emc_q; + /* Specifies the value for EMC_DYN_SELF_REF_CONTROL */ + u32 emc_dyn_self_ref_control; + + /* Specifies the value for MEM_INIT_DONE */ + u32 ahb_arbitration_xbar_ctrl_meminit_done; + + /* Specifies the value for EMC_CFG_DIG_DLL */ + u32 emc_cfg_dig_dll; + u32 emc_cfg_dig_dll_1; + + /* Specifies the value for EMC_CFG_DIG_DLL_PERIOD */ + u32 emc_cfg_dig_dll_period; + /* Specifies the value of *DEV_SELECTN of various EMC registers */ + u32 emc_dev_select; + + /* Specifies the value for EMC_SEL_DPD_CTRL */ + u32 emc_sel_dpd_ctrl; + + /* Pads trimmer delays */ + u32 emc_fdpd_ctrl_dq; + u32 emc_fdpd_ctrl_cmd; + u32 emc_pmacro_ib_vref_dq_0; + u32 emc_pmacro_ib_vref_dq_1; + u32 emc_pmacro_ib_vref_dqs_0; + u32 emc_pmacro_ib_vref_dqs_1; + u32 emc_pmacro_ib_rxrt; + u32 emc_cfg_pipe1; + u32 emc_cfg_pipe2; + + /* Specifies the value for EMC_PMACRO_QUSE_DDLL_RANK0_0 */ + u32 emc_pmacro_quse_ddll_rank0_0; + u32 emc_pmacro_quse_ddll_rank0_1; + u32 emc_pmacro_quse_ddll_rank0_2; + u32 emc_pmacro_quse_ddll_rank0_3; + u32 emc_pmacro_quse_ddll_rank0_4; + u32 emc_pmacro_quse_ddll_rank0_5; + u32 emc_pmacro_quse_ddll_rank1_0; + u32 emc_pmacro_quse_ddll_rank1_1; + u32 emc_pmacro_quse_ddll_rank1_2; + u32 emc_pmacro_quse_ddll_rank1_3; + u32 emc_pmacro_quse_ddll_rank1_4; + u32 emc_pmacro_quse_ddll_rank1_5; + + u32 emc_pmacro_ob_ddll_long_dq_rank0_0; + u32 emc_pmacro_ob_ddll_long_dq_rank0_1; + u32 emc_pmacro_ob_ddll_long_dq_rank0_2; + u32 emc_pmacro_ob_ddll_long_dq_rank0_3; + u32 emc_pmacro_ob_ddll_long_dq_rank0_4; + u32 emc_pmacro_ob_ddll_long_dq_rank0_5; + u32 emc_pmacro_ob_ddll_long_dq_rank1_0; + u32 emc_pmacro_ob_ddll_long_dq_rank1_1; + u32 emc_pmacro_ob_ddll_long_dq_rank1_2; + u32 emc_pmacro_ob_ddll_long_dq_rank1_3; + u32 emc_pmacro_ob_ddll_long_dq_rank1_4; + u32 emc_pmacro_ob_ddll_long_dq_rank1_5; + + u32 emc_pmacro_ob_ddll_long_dqs_rank0_0; + u32 emc_pmacro_ob_ddll_long_dqs_rank0_1; + u32 emc_pmacro_ob_ddll_long_dqs_rank0_2; + u32 emc_pmacro_ob_ddll_long_dqs_rank0_3; + u32 emc_pmacro_ob_ddll_long_dqs_rank0_4; + u32 emc_pmacro_ob_ddll_long_dqs_rank0_5; + u32 emc_pmacro_ob_ddll_long_dqs_rank1_0; + u32 emc_pmacro_ob_ddll_long_dqs_rank1_1; + u32 emc_pmacro_ob_ddll_long_dqs_rank1_2; + u32 emc_pmacro_ob_ddll_long_dqs_rank1_3; + u32 emc_pmacro_ob_ddll_long_dqs_rank1_4; + u32 emc_pmacro_ob_ddll_long_dqs_rank1_5; + + u32 emc_pmacro_ib_ddll_long_dqs_rank0_0; + u32 emc_pmacro_ib_ddll_long_dqs_rank0_1; + u32 emc_pmacro_ib_ddll_long_dqs_rank0_2; + u32 emc_pmacro_ib_ddll_long_dqs_rank0_3; + u32 emc_pmacro_ib_ddll_long_dqs_rank1_0; + u32 emc_pmacro_ib_ddll_long_dqs_rank1_1; + u32 emc_pmacro_ib_ddll_long_dqs_rank1_2; + u32 emc_pmacro_ib_ddll_long_dqs_rank1_3; + + u32 emc_pmacro_ddll_long_cmd_0; + u32 emc_pmacro_ddll_long_cmd_1; + u32 emc_pmacro_ddll_long_cmd_2; + u32 emc_pmacro_ddll_long_cmd_3; + u32 emc_pmacro_ddll_long_cmd_4; + u32 emc_pmacro_ddll_short_cmd_0; + u32 emc_pmacro_ddll_short_cmd_1; + u32 emc_pmacro_ddll_short_cmd_2; + + u32 emc_pmacro_ddll_periodic_offset; + + /* + * Specifies the delay after asserting CKE pin during a WarmBoot0 + * sequence (in microseconds) + */ + u32 warm_boot_wait; + + /* Specifies the value for EMC_ODT_WRITE */ + u32 emc_odt_write; + + /* Periodic ZQ calibration */ + + /* + * Specifies the value for EMC_ZCAL_INTERVAL + * Value 0 disables ZQ calibration + */ + u32 emc_zcal_interval; + /* Specifies the value for EMC_ZCAL_WAIT_CNT */ + u32 emc_zcal_wait_cnt; + /* Specifies the value for EMC_ZCAL_MRW_CMD */ + u32 emc_zcal_mrw_cmd; + + /* DRAM initialization sequence flow control */ + + /* Specifies the MRS command value for resetting DLL */ + u32 emc_mrs_reset_dll; + /* Specifies the command for ZQ initialization of device 0 */ + u32 emc_zcal_init_dev0; + /* Specifies the command for ZQ initialization of device 1 */ + u32 emc_zcal_init_dev1; + /* + * Specifies the wait time after programming a ZQ initialization + * command (in microseconds) + */ + u32 emc_zcal_init_wait; + /* + * Specifies the enable for ZQ calibration at cold boot [bit 0] + * and warm boot [bit 1] + */ + u32 emc_zcal_warm_cold_boot_enables; + + /* + * Specifies the MRW command to LPDDR2 for ZQ calibration + * on warmboot + */ + /* Is issued to both devices separately */ + u32 emc_mrw_lpddr2zcal_warm_boot; + /* + * Specifies the ZQ command to DDR3 for ZQ calibration on warmboot + * Is issued to both devices separately + */ + u32 emc_zqcal_ddr3_warm_boot; + + u32 emc_zqcal_lpddr4_warm_boot; + + /* + * Specifies the wait time for ZQ calibration on warmboot + * (in microseconds) + */ + u32 emc_zcal_warm_boot_wait; + /* + * Specifies the enable for DRAM Mode Register programming + * at warm boot + */ + u32 emc_mrs_warm_boot_enable; + /* + * Specifies the wait time after sending an MRS DLL reset command + * in microseconds) + */ + u32 emc_mrs_reset_dll_wait; + /* Specifies the extra MRS command to initialize mode registers */ + u32 emc_mrs_extra; + /* Specifies the extra MRS command at warm boot */ + u32 emc_warm_boot_mrs_extra; + /* Specifies the EMRS command to enable the DDR2 DLL */ + u32 emc_emrs_ddr2_dll_enable; + /* Specifies the MRS command to reset the DDR2 DLL */ + u32 emc_mrs_ddr2_dll_reset; + /* Specifies the EMRS command to set OCD calibration */ + u32 emc_emrs_ddr2_ocd_calib; + /* + * Specifies the wait between initializing DDR and setting OCD + * calibration (in microseconds) + */ + u32 emc_ddr2_wait; + /* Specifies the value for EMC_CLKEN_OVERRIDE */ + u32 emc_clken_override; + /* + * Specifies LOG2 of the extra refresh numbers after booting + * Program 0 to disable + */ + u32 emc_extra_refresh_num; + /* Specifies the master override for all EMC clocks */ + u32 emc_clken_override_allwarm_boot; + /* Specifies the master override for all MC clocks */ + u32 mc_clken_override_allwarm_boot; + /* Specifies digital dll period, choosing between 4 to 64 ms */ + u32 emc_cfg_dig_dll_period_warm_boot; + + /* Pad controls */ + + /* Specifies the value for PMC_VDDP_SEL */ + u32 pmc_vddp_sel; + /* Specifies the wait time after programming PMC_VDDP_SEL */ + u32 pmc_vddp_sel_wait; + /* Specifies the value for PMC_DDR_CFG */ + u32 pmc_ddr_cfg; + /* Specifies the value for PMC_IO_DPD3_REQ */ + u32 pmc_io_dpd3_req; + /* Specifies the wait time after programming PMC_IO_DPD3_REQ */ + u32 pmc_io_dpd3_req_wait; + + u32 pmc_io_dpd4_req_wait; + + /* Specifies the value for PMC_REG_SHORT */ + u32 pmc_reg_short; + /* Specifies the value for PMC_NO_IOPOWER */ + u32 pmc_no_io_power; + + u32 pmc_ddr_ctrl_wait; + u32 pmc_ddr_ctrl; + + /* Specifies the value for EMC_ACPD_CONTROL */ + u32 emc_acpd_control; + + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE0 */ + u32 emc_swizzle_rank0_byte0; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE1 */ + u32 emc_swizzle_rank0_byte1; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE2 */ + u32 emc_swizzle_rank0_byte2; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE3 */ + u32 emc_swizzle_rank0_byte3; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE0 */ + u32 emc_swizzle_rank1_byte0; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE1 */ + u32 emc_swizzle_rank1_byte1; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE2 */ + u32 emc_swizzle_rank1_byte2; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE3 */ + u32 emc_swizzle_rank1_byte3; + + /* Specifies the value for EMC_TXDSRVTTGEN */ + u32 emc_txdsrvttgen; + + /* Specifies the value for EMC_DATA_BRLSHFT_0 */ + u32 emc_data_brlshft0; + u32 emc_data_brlshft1; + + u32 emc_dqs_brlshft0; + u32 emc_dqs_brlshft1; + + u32 emc_cmd_brlshft0; + u32 emc_cmd_brlshft1; + u32 emc_cmd_brlshft2; + u32 emc_cmd_brlshft3; + + u32 emc_quse_brlshft0; + u32 emc_quse_brlshft1; + u32 emc_quse_brlshft2; + u32 emc_quse_brlshft3; + + u32 emc_dll_cfg0; + u32 emc_dll_cfg1; + + u32 emc_pmc_scratch1; + u32 emc_pmc_scratch2; + u32 emc_pmc_scratch3; + + u32 emc_pmacro_pad_cfg_ctrl; + + u32 emc_pmacro_vttgen_ctrl0; + u32 emc_pmacro_vttgen_ctrl1; + u32 emc_pmacro_vttgen_ctrl2; + u32 emc_pmacro_dsr_vttgen_ctrl0; + u32 emc_pmacro_brick_ctrl_rfu1; + u32 emc_pmacro_cmd_brick_ctrl_fdpd; + u32 emc_pmacro_brick_ctrl_rfu2; + u32 emc_pmacro_data_brick_ctrl_fdpd; + u32 emc_pmacro_bg_bias_ctrl0; + u32 emc_pmacro_data_pad_rx_ctrl; + u32 emc_pmacro_cmd_pad_rx_ctrl; + u32 emc_pmacro_data_rx_term_mode; + u32 emc_pmacro_cmd_rx_term_mode; + u32 emc_pmacro_data_pad_tx_ctrl; + u32 emc_pmacro_cmd_pad_tx_ctrl; + u32 emc_cfg3; + + u32 emc_pmacro_tx_pwrd0; + u32 emc_pmacro_tx_pwrd1; + u32 emc_pmacro_tx_pwrd2; + u32 emc_pmacro_tx_pwrd3; + u32 emc_pmacro_tx_pwrd4; + u32 emc_pmacro_tx_pwrd5; + + u32 emc_config_sample_delay; + + u32 emc_pmacro_brick_mapping0; + u32 emc_pmacro_brick_mapping1; + u32 emc_pmacro_brick_mapping2; + + u32 emc_pmacro_tx_sel_clk_src0; + u32 emc_pmacro_tx_sel_clk_src1; + u32 emc_pmacro_tx_sel_clk_src2; + u32 emc_pmacro_tx_sel_clk_src3; + u32 emc_pmacro_tx_sel_clk_src4; + u32 emc_pmacro_tx_sel_clk_src5; + + u32 emc_pmacro_perbit_fgcg_ctrl0; + u32 emc_pmacro_perbit_fgcg_ctrl1; + u32 emc_pmacro_perbit_fgcg_ctrl2; + u32 emc_pmacro_perbit_fgcg_ctrl3; + u32 emc_pmacro_perbit_fgcg_ctrl4; + u32 emc_pmacro_perbit_fgcg_ctrl5; + u32 emc_pmacro_perbit_rfu_ctrl0; + u32 emc_pmacro_perbit_rfu_ctrl1; + u32 emc_pmacro_perbit_rfu_ctrl2; + u32 emc_pmacro_perbit_rfu_ctrl3; + u32 emc_pmacro_perbit_rfu_ctrl4; + u32 emc_pmacro_perbit_rfu_ctrl5; + u32 emc_pmacro_perbit_rfu1_ctrl0; + u32 emc_pmacro_perbit_rfu1_ctrl1; + u32 emc_pmacro_perbit_rfu1_ctrl2; + u32 emc_pmacro_perbit_rfu1_ctrl3; + u32 emc_pmacro_perbit_rfu1_ctrl4; + u32 emc_pmacro_perbit_rfu1_ctrl5; + + u32 emc_pmacro_data_pi_ctrl; + u32 emc_pmacro_cmd_pi_ctrl; + + u32 emc_pmacro_ddll_bypass; + + u32 emc_pmacro_ddll_pwrd0; + u32 emc_pmacro_ddll_pwrd1; + u32 emc_pmacro_ddll_pwrd2; + + u32 emc_pmacro_cmd_ctrl0; + u32 emc_pmacro_cmd_ctrl1; + u32 emc_pmacro_cmd_ctrl2; + + /* DRAM size information */ + + /* Specifies the value for MC_EMEM_ADR_CFG */ + u32 mc_emem_adr_cfg; + /* Specifies the value for MC_EMEM_ADR_CFG_DEV0 */ + u32 mc_emem_adr_cfg_dev0; + /* Specifies the value for MC_EMEM_ADR_CFG_DEV1 */ + u32 mc_emem_adr_cfg_dev1; + + u32 mc_emem_adr_cfg_channel_mask; + + /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG0 */ + u32 mc_emem_adr_cfg_bank_mask0; + /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG1 */ + u32 mc_emem_adr_cfg_bank_mask1; + /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG2 */ + u32 mc_emem_adr_cfg_bank_mask2; + + /* + * Specifies the value for MC_EMEM_CFG which holds the external memory + * size (in KBytes) + */ + u32 mc_emem_cfg; + + /* MC arbitration configuration */ + + /* Specifies the value for MC_EMEM_ARB_CFG */ + u32 mc_emem_arb_cfg; + /* Specifies the value for MC_EMEM_ARB_OUTSTANDING_REQ */ + u32 mc_emem_arb_outstanding_req; + + u32 emc_emem_arb_refpb_hp_ctrl; + u32 emc_emem_arb_refpb_bank_ctrl; + + /* Specifies the value for MC_EMEM_ARB_TIMING_RCD */ + u32 mc_emem_arb_timing_rcd; + /* Specifies the value for MC_EMEM_ARB_TIMING_RP */ + u32 mc_emem_arb_timing_rp; + /* Specifies the value for MC_EMEM_ARB_TIMING_RC */ + u32 mc_emem_arb_timing_rc; + /* Specifies the value for MC_EMEM_ARB_TIMING_RAS */ + u32 mc_emem_arb_timing_ras; + /* Specifies the value for MC_EMEM_ARB_TIMING_FAW */ + u32 mc_emem_arb_timing_faw; + /* Specifies the value for MC_EMEM_ARB_TIMING_RRD */ + u32 mc_emem_arb_timing_rrd; + /* Specifies the value for MC_EMEM_ARB_TIMING_RAP2PRE */ + u32 mc_emem_arb_timing_rap2pre; + /* Specifies the value for MC_EMEM_ARB_TIMING_WAP2PRE */ + u32 mc_emem_arb_timing_wap2pre; + /* Specifies the value for MC_EMEM_ARB_TIMING_R2R */ + u32 mc_emem_arb_timing_r2r; + /* Specifies the value for MC_EMEM_ARB_TIMING_W2W */ + u32 mc_emem_arb_timing_w2w; + /* Specifies the value for MC_EMEM_ARB_TIMING_R2W */ + u32 mc_emem_arb_timing_r2w; + /* Specifies the value for MC_EMEM_ARB_TIMING_W2R */ + u32 mc_emem_arb_timing_w2r; + + u32 mc_emem_arb_timing_rfcpb; + + /* Specifies the value for MC_EMEM_ARB_DA_TURNS */ + u32 mc_emem_arb_da_turns; + /* Specifies the value for MC_EMEM_ARB_DA_COVERS */ + u32 mc_emem_arb_da_covers; + /* Specifies the value for MC_EMEM_ARB_MISC0 */ + u32 mc_emem_arb_misc0; + /* Specifies the value for MC_EMEM_ARB_MISC1 */ + u32 mc_emem_arb_misc1; + u32 mc_emem_arb_misc2; + + /* Specifies the value for MC_EMEM_ARB_RING1_THROTTLE */ + u32 mc_emem_arb_ring1_throttle; + /* Specifies the value for MC_EMEM_ARB_OVERRIDE */ + u32 mc_emem_arb_override; + /* Specifies the value for MC_EMEM_ARB_OVERRIDE_1 */ + u32 mc_emem_arb_override1; + /* Specifies the value for MC_EMEM_ARB_RSV */ + u32 mc_emem_arb_rsv; + + u32 mc_da_cfg0; + u32 mc_emem_arb_timing_ccdmw; + + /* Specifies the value for MC_CLKEN_OVERRIDE */ + u32 mc_clken_override; + + /* Specifies the value for MC_STAT_CONTROL */ + u32 mc_stat_control; + /* Specifies the value for MC_VIDEO_PROTECT_BOM */ + u32 mc_video_protect_bom; + /* Specifies the value for MC_VIDEO_PROTECT_BOM_ADR_HI */ + u32 mc_video_protect_bom_adr_hi; + /* Specifies the value for MC_VIDEO_PROTECT_SIZE_MB */ + u32 mc_video_protect_size_mb; + /* Specifies the value for MC_VIDEO_PROTECT_VPR_OVERRIDE */ + u32 mc_video_protect_vpr_override; + /* Specifies the value for MC_VIDEO_PROTECT_VPR_OVERRIDE1 */ + u32 mc_video_protect_vpr_override1; + /* Specifies the value for MC_VIDEO_PROTECT_GPU_OVERRIDE_0 */ + u32 mc_video_protect_gpu_override0; + /* Specifies the value for MC_VIDEO_PROTECT_GPU_OVERRIDE_1 */ + u32 mc_video_protect_gpu_override1; + /* Specifies the value for MC_SEC_CARVEOUT_BOM */ + u32 mc_sec_carveout_bom; + /* Specifies the value for MC_SEC_CARVEOUT_ADR_HI */ + u32 mc_sec_carveout_adr_hi; + /* Specifies the value for MC_SEC_CARVEOUT_SIZE_MB */ + u32 mc_sec_carveout_size_mb; + /* Specifies the value for MC_VIDEO_PROTECT_REG_CTRL.VIDEO_PROTECT_WRITE_ACCESS */ + u32 mc_video_protect_write_access; + /* Specifies the value for MC_SEC_CARVEOUT_REG_CTRL.SEC_CARVEOUT_WRITE_ACCESS */ + u32 mc_sec_carveout_protect_write_access; + + u32 mc_generalized_carveout1_bom; + u32 mc_generalized_carveout1_bom_hi; + u32 mc_generalized_carveout1_size_128kb; + u32 mc_generalized_carveout1_access0; + u32 mc_generalized_carveout1_access1; + u32 mc_generalized_carveout1_access2; + u32 mc_generalized_carveout1_access3; + u32 mc_generalized_carveout1_access4; + u32 mc_generalized_carveout1_force_internal_access0; + u32 mc_generalized_carveout1_force_internal_access1; + u32 mc_generalized_carveout1_force_internal_access2; + u32 mc_generalized_carveout1_force_internal_access3; + u32 mc_generalized_carveout1_force_internal_access4; + u32 mc_generalized_carveout1_cfg0; + + u32 mc_generalized_carveout2_bom; + u32 mc_generalized_carveout2_bom_hi; + u32 mc_generalized_carveout2_size_128kb; + u32 mc_generalized_carveout2_access0; + u32 mc_generalized_carveout2_access1; + u32 mc_generalized_carveout2_access2; + u32 mc_generalized_carveout2_access3; + u32 mc_generalized_carveout2_access4; + u32 mc_generalized_carveout2_force_internal_access0; + u32 mc_generalized_carveout2_force_internal_access1; + u32 mc_generalized_carveout2_force_internal_access2; + u32 mc_generalized_carveout2_force_internal_access3; + u32 mc_generalized_carveout2_force_internal_access4; + u32 mc_generalized_carveout2_cfg0; + + u32 mc_generalized_carveout3_bom; + u32 mc_generalized_carveout3_bom_hi; + u32 mc_generalized_carveout3_size_128kb; + u32 mc_generalized_carveout3_access0; + u32 mc_generalized_carveout3_access1; + u32 mc_generalized_carveout3_access2; + u32 mc_generalized_carveout3_access3; + u32 mc_generalized_carveout3_access4; + u32 mc_generalized_carveout3_force_internal_access0; + u32 mc_generalized_carveout3_force_internal_access1; + u32 mc_generalized_carveout3_force_internal_access2; + u32 mc_generalized_carveout3_force_internal_access3; + u32 mc_generalized_carveout3_force_internal_access4; + u32 mc_generalized_carveout3_cfg0; + + u32 mc_generalized_carveout4_bom; + u32 mc_generalized_carveout4_bom_hi; + u32 mc_generalized_carveout4_size_128kb; + u32 mc_generalized_carveout4_access0; + u32 mc_generalized_carveout4_access1; + u32 mc_generalized_carveout4_access2; + u32 mc_generalized_carveout4_access3; + u32 mc_generalized_carveout4_access4; + u32 mc_generalized_carveout4_force_internal_access0; + u32 mc_generalized_carveout4_force_internal_access1; + u32 mc_generalized_carveout4_force_internal_access2; + u32 mc_generalized_carveout4_force_internal_access3; + u32 mc_generalized_carveout4_force_internal_access4; + u32 mc_generalized_carveout4_cfg0; + + u32 mc_generalized_carveout5_bom; + u32 mc_generalized_carveout5_bom_hi; + u32 mc_generalized_carveout5_size_128kb; + u32 mc_generalized_carveout5_access0; + u32 mc_generalized_carveout5_access1; + u32 mc_generalized_carveout5_access2; + u32 mc_generalized_carveout5_access3; + u32 mc_generalized_carveout5_access4; + u32 mc_generalized_carveout5_force_internal_access0; + u32 mc_generalized_carveout5_force_internal_access1; + u32 mc_generalized_carveout5_force_internal_access2; + u32 mc_generalized_carveout5_force_internal_access3; + u32 mc_generalized_carveout5_force_internal_access4; + u32 mc_generalized_carveout5_cfg0; + + /* Specifies enable for CA training */ + u32 emc_ca_training_enable; + /* Set if bit 6 select is greater than bit 7 select; uses aremc.spec packet SWIZZLE_BIT6_GT_BIT7 */ + u32 swizzle_rank_byte_encode; + /* Specifies enable and offset for patched boot rom write */ + u32 boot_rom_patch_control; + /* Specifies data for patched boot rom write */ + u32 boot_rom_patch_data; + + /* Specifies the value for MC_MTS_CARVEOUT_BOM */ + u32 mc_mts_carveout_bom; + /* Specifies the value for MC_MTS_CARVEOUT_ADR_HI */ + u32 mc_mts_carveout_adr_hi; + /* Specifies the value for MC_MTS_CARVEOUT_SIZE_MB */ + u32 mc_mts_carveout_size_mb; + /* Specifies the value for MC_MTS_CARVEOUT_REG_CTRL */ + u32 mc_mts_carveout_reg_ctrl; + + u32 mc_untranslated_region_check; + + /* Just a place holder for special usage when there is no BCT for certain registers */ + u32 bct_na; +}; + +#endif diff --git a/bdk/mem/sdram_param_t210.h b/bdk/mem/sdram_param_t210.h index 4c6c60a..ed3341b 100644 --- a/bdk/mem/sdram_param_t210.h +++ b/bdk/mem/sdram_param_t210.h @@ -37,7 +37,7 @@ /** * Defines the SDRAM parameter structure */ -typedef struct _sdram_params +typedef struct _sdram_params_t210_t { /* Specifies the type of memory device */ u32 memory_type; @@ -925,6 +925,6 @@ typedef struct _sdram_params u32 mc_mts_carveout_size_mb; /* Specifies the value for MC_MTS_CARVEOUT_REG_CTRL */ u32 mc_mts_carveout_reg_ctrl; -} sdram_params_t; +} sdram_params_t210_t; #endif diff --git a/bdk/mem/sdram_param_t210b01.h b/bdk/mem/sdram_param_t210b01.h new file mode 100644 index 0000000..8bcbed3 --- /dev/null +++ b/bdk/mem/sdram_param_t210b01.h @@ -0,0 +1,989 @@ +/* + * Copyright (c) 2020 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. + */ + +#ifndef _SDRAM_PARAM_T210B01_H_ +#define _SDRAM_PARAM_T210B01_H_ + +typedef struct _sdram_params_t210b01_t +{ + /* Specifies the type of memory device */ + u32 memory_type; + + /* MC/EMC clock source configuration */ + + /* Specifies the M value for PllM */ + u32 pllm_input_divider; + /* Specifies the N value for PllM */ + u32 pllm_feedback_divider; + /* Specifies the time to wait for PLLM to lock (in microseconds) */ + u32 pllm_stable_time; + /* Specifies misc. control bits */ + u32 pllm_setup_control; + /* Specifies the P value for PLLM */ + u32 pllm_post_divider; + /* Specifies value for Charge Pump Gain Control */ + u32 pllm_kcp; + /* Specifies VCO gain */ + u32 pllm_kvco; + /* Spare BCT param */ + u32 emc_bct_spare0; + /* Spare BCT param */ + u32 emc_bct_spare1; + /* Spare BCT param */ + u32 emc_bct_spare2; + /* Spare BCT param */ + u32 emc_bct_spare3; + /* Spare BCT param */ + u32 emc_bct_spare4; + /* Spare BCT param */ + u32 emc_bct_spare5; + /* Spare BCT param */ + u32 emc_bct_spare6; + /* Spare BCT param */ + u32 emc_bct_spare7; + /* Spare BCT param */ + u32 emc_bct_spare8; + /* Spare BCT param */ + u32 emc_bct_spare9; + /* Spare BCT param */ + u32 emc_bct_spare10; + /* Spare BCT param */ + u32 emc_bct_spare11; + /* Spare BCT param */ + u32 emc_bct_spare12; + /* Spare BCT param */ + u32 emc_bct_spare13; + /* Spare BCT param */ + u32 emc_bct_spare_secure0; + /* Spare BCT param */ + u32 emc_bct_spare_secure1; + /* Spare BCT param */ + u32 emc_bct_spare_secure2; + /* Spare BCT param */ + u32 emc_bct_spare_secure3; + /* Spare BCT param */ + u32 emc_bct_spare_secure4; + /* Spare BCT param */ + u32 emc_bct_spare_secure5; + /* Spare BCT param */ + u32 emc_bct_spare_secure6; + /* Spare BCT param */ + u32 emc_bct_spare_secure7; + /* Spare BCT param */ + u32 emc_bct_spare_secure8; + /* Spare BCT param */ + u32 emc_bct_spare_secure9; + /* Spare BCT param */ + u32 emc_bct_spare_secure10; + /* Spare BCT param */ + u32 emc_bct_spare_secure11; + /* Spare BCT param */ + u32 emc_bct_spare_secure12; + /* Spare BCT param */ + u32 emc_bct_spare_secure13; + /* Spare BCT param */ + u32 emc_bct_spare_secure14; + /* Spare BCT param */ + u32 emc_bct_spare_secure15; + /* Spare BCT param */ + u32 emc_bct_spare_secure16; + /* Spare BCT param */ + u32 emc_bct_spare_secure17; + /* Spare BCT param */ + u32 emc_bct_spare_secure18; + /* Spare BCT param */ + u32 emc_bct_spare_secure19; + /* Spare BCT param */ + u32 emc_bct_spare_secure20; + /* Spare BCT param */ + u32 emc_bct_spare_secure21; + /* Spare BCT param */ + u32 emc_bct_spare_secure22; + /* Spare BCT param */ + u32 emc_bct_spare_secure23; + + /* Defines EMC_2X_CLK_SRC, EMC_2X_CLK_DIVISOR, EMC_INVERT_DCD */ + u32 emc_clock_source; + u32 emc_clock_source_dll; + + /* Defines possible override for PLLLM_MISC2 */ + u32 clk_rst_pllm_misc20_override; + /* enables override for PLLLM_MISC2 */ + u32 clk_rst_pllm_misc20_override_enable; + /* defines CLK_ENB_MC1 in register clk_rst_controller_clk_enb_w_clr */ + u32 clear_clock2_mc1; + + /* Auto-calibration of EMC pads */ + + /* Specifies the value for EMC_AUTO_CAL_INTERVAL */ + u32 emc_auto_cal_interval; + /* + * Specifies the value for EMC_AUTO_CAL_CONFIG + * Note: Trigger bits are set by the SDRAM code. + */ + u32 emc_auto_cal_config; + + /* Specifies the value for EMC_AUTO_CAL_CONFIG2 */ + u32 emc_auto_cal_config2; + + /* Specifies the value for EMC_AUTO_CAL_CONFIG3 */ + u32 emc_auto_cal_config3; + u32 emc_auto_cal_config4; + u32 emc_auto_cal_config5; + u32 emc_auto_cal_config6; + u32 emc_auto_cal_config7; + u32 emc_auto_cal_config8; + u32 emc_auto_cal_config9; + + /* Specifies the value for EMC_AUTO_CAL_VREF_SEL_0 */ + u32 emc_auto_cal_vref_sel0; + u32 emc_auto_cal_vref_sel1; + + /* Specifies the value for EMC_AUTO_CAL_CHANNEL */ + u32 emc_auto_cal_channel; + + /* Specifies the value for EMC_PMACRO_AUTOCAL_CFG_0 */ + u32 emc_pmacro_auto_cal_cfg0; + u32 emc_pmacro_auto_cal_cfg1; + u32 emc_pmacro_auto_cal_cfg2; + + u32 emc_pmacro_rx_term; + u32 emc_pmacro_dq_tx_drive; + u32 emc_pmacro_ca_tx_drive; + u32 emc_pmacro_cmd_tx_drive; + u32 emc_pmacro_auto_cal_common; + u32 emc_pmacro_zcrtl; + + /* + * Specifies the time for the calibration + * to stabilize (in microseconds) + */ + u32 emc_auto_cal_wait; + + u32 emc_xm2_comp_pad_ctrl; + u32 emc_xm2_comp_pad_ctrl2; + u32 emc_xm2_comp_pad_ctrl3; + + /* + * DRAM size information + * Specifies the value for EMC_ADR_CFG + */ + u32 emc_adr_cfg; + + /* + * Specifies the time to wait after asserting pin + * CKE (in microseconds) + */ + u32 emc_pin_program_wait; + /* Specifies the extra delay before/after pin RESET/CKE command */ + u32 emc_pin_extra_wait; + + u32 emc_pin_gpio_enable; + u32 emc_pin_gpio; + + /* + * Specifies the extra delay after the first writing + * of EMC_TIMING_CONTROL + */ + u32 emc_timing_control_wait; + + /* Timing parameters required for the SDRAM */ + + /* Specifies the value for EMC_RC */ + u32 emc_rc; + /* Specifies the value for EMC_RFC */ + u32 emc_rfc; + + u32 emc_rfc_pb; + u32 emc_ref_ctrl2; + + /* Specifies the value for EMC_RFC_SLR */ + u32 emc_rfc_slr; + /* Specifies the value for EMC_RAS */ + u32 emc_ras; + /* Specifies the value for EMC_RP */ + u32 emc_rp; + /* Specifies the value for EMC_R2R */ + u32 emc_r2r; + /* Specifies the value for EMC_W2W */ + u32 emc_w2w; + /* Specifies the value for EMC_R2W */ + u32 emc_r2w; + /* Specifies the value for EMC_W2R */ + u32 emc_w2r; + /* Specifies the value for EMC_R2P */ + u32 emc_r2p; + /* Specifies the value for EMC_W2P */ + u32 emc_w2p; + /* Specifies the value for EMC_RD_RCD */ + + u32 emc_tppd; + u32 emc_trtm; + u32 emc_twtm; + u32 emc_tratm; + u32 emc_twatm; + u32 emc_tr2ref; + u32 emc_ccdmw; + + u32 emc_rd_rcd; + /* Specifies the value for EMC_WR_RCD */ + u32 emc_wr_rcd; + /* Specifies the value for EMC_RRD */ + u32 emc_rrd; + /* Specifies the value for EMC_REXT */ + u32 emc_rext; + /* Specifies the value for EMC_WEXT */ + u32 emc_wext; + /* Specifies the value for EMC_WDV */ + u32 emc_wdv; + + u32 emc_wdv_chk; + u32 emc_wsv; + u32 emc_wev; + + /* Specifies the value for EMC_WDV_MASK */ + u32 emc_wdv_mask; + + u32 emc_ws_duration; + u32 emc_we_duration; + + /* Specifies the value for EMC_QUSE */ + u32 emc_quse; + /* Specifies the value for EMC_QUSE_WIDTH */ + u32 emc_quse_width; + /* Specifies the value for EMC_IBDLY */ + u32 emc_ibdly; + + u32 emc_obdly; + + /* Specifies the value for EMC_EINPUT */ + u32 emc_einput; + /* Specifies the value for EMC_EINPUT_DURATION */ + u32 emc_einput_duration; + /* Specifies the value for EMC_PUTERM_EXTRA */ + u32 emc_puterm_extra; + /* Specifies the value for EMC_PUTERM_WIDTH */ + u32 emc_puterm_width; + + u32 emc_qrst; + u32 emc_qsafe; + u32 emc_rdv; + u32 emc_rdv_mask; + + u32 emc_rdv_early; + u32 emc_rdv_early_mask; + + /* Specifies the value for EMC_QPOP */ + u32 emc_qpop; + + /* Specifies the value for EMC_REFRESH */ + u32 emc_refresh; + /* Specifies the value for EMC_BURST_REFRESH_NUM */ + u32 emc_burst_refresh_num; + /* Specifies the value for EMC_PRE_REFRESH_REQ_CNT */ + u32 emc_prerefresh_req_cnt; + /* Specifies the value for EMC_PDEX2WR */ + u32 emc_pdex2wr; + /* Specifies the value for EMC_PDEX2RD */ + u32 emc_pdex2rd; + /* Specifies the value for EMC_PCHG2PDEN */ + u32 emc_pchg2pden; + /* Specifies the value for EMC_ACT2PDEN */ + u32 emc_act2pden; + /* Specifies the value for EMC_AR2PDEN */ + u32 emc_ar2pden; + /* Specifies the value for EMC_RW2PDEN */ + u32 emc_rw2pden; + + u32 emc_cke2pden; + u32 emc_pdex2che; + u32 emc_pdex2mrr; + + /* Specifies the value for EMC_TXSR */ + u32 emc_txsr; + /* Specifies the value for EMC_TXSRDLL */ + u32 emc_txsr_dll; + /* Specifies the value for EMC_TCKE */ + u32 emc_tcke; + /* Specifies the value for EMC_TCKESR */ + u32 emc_tckesr; + /* Specifies the value for EMC_TPD */ + u32 emc_tpd; + /* Specifies the value for EMC_TFAW */ + u32 emc_tfaw; + /* Specifies the value for EMC_TRPAB */ + u32 emc_trpab; + /* Specifies the value for EMC_TCLKSTABLE */ + u32 emc_tclkstable; + /* Specifies the value for EMC_TCLKSTOP */ + u32 emc_tclkstop; + /* Specifies the value for EMC_TREFBW */ + u32 emc_trefbw; + + /* FBIO configuration values */ + + /* Specifies the value for EMC_FBIO_CFG5 */ + u32 emc_fbio_cfg5; + /* Specifies the value for EMC_FBIO_CFG7 */ + u32 emc_fbio_cfg7; + u32 emc_fbio_cfg8; + + /* Command mapping for CMD brick 0 */ + u32 emc_cmd_mapping_cmd0_0; + u32 emc_cmd_mapping_cmd0_1; + u32 emc_cmd_mapping_cmd0_2; + u32 emc_cmd_mapping_cmd1_0; + u32 emc_cmd_mapping_cmd1_1; + u32 emc_cmd_mapping_cmd1_2; + u32 emc_cmd_mapping_cmd2_0; + u32 emc_cmd_mapping_cmd2_1; + u32 emc_cmd_mapping_cmd2_2; + u32 emc_cmd_mapping_cmd3_0; + u32 emc_cmd_mapping_cmd3_1; + u32 emc_cmd_mapping_cmd3_2; + u32 emc_cmd_mapping_byte; + + /* Specifies the value for EMC_FBIO_SPARE */ + u32 emc_fbio_spare; + + /* Specifies the value for EMC_CFG_RSV */ + u32 emc_cfg_rsv; + + /* MRS command values */ + + /* Specifies the value for EMC_MRS */ + u32 emc_mrs; + /* Specifies the MP0 command to initialize mode registers */ + u32 emc_emrs; + /* Specifies the MP2 command to initialize mode registers */ + u32 emc_emrs2; + /* Specifies the MP3 command to initialize mode registers */ + u32 emc_emrs3; + /* Specifies the programming to LPDDR2 Mode Register 1 at cold boot */ + u32 emc_mrw1; + /* Specifies the programming to LPDDR2 Mode Register 2 at cold boot */ + u32 emc_mrw2; + /* Specifies the programming to LPDDR2 Mode Register 3 at cold boot */ + u32 emc_mrw3; + /* Specifies the programming to LPDDR2 Mode Register 11 at cold boot */ + u32 emc_mrw4; + + /* Specifies the programming to LPDDR4 Mode Register 3 at cold boot */ + u32 emc_mrw6; + /* Specifies the programming to LPDDR4 Mode Register 11 at cold boot */ + u32 emc_mrw8; + /* Specifies the programming to LPDDR4 Mode Register 11 at cold boot */ + u32 emc_mrw9; + /* Specifies the programming to LPDDR4 Mode Register 12 at cold boot */ + u32 emc_mrw10; + /* Specifies the programming to LPDDR4 Mode Register 14 at cold boot */ + u32 emc_mrw12; + /* Specifies the programming to LPDDR4 Mode Register 14 at cold boot */ + u32 emc_mrw13; + /* Specifies the programming to LPDDR4 Mode Register 22 at cold boot */ + u32 emc_mrw14; + + /* + * Specifies the programming to extra LPDDR2 Mode Register + * at cold boot + */ + u32 emc_mrw_extra; + /* + * Specifies the programming to extra LPDDR2 Mode Register + * at warm boot + */ + u32 emc_warm_boot_mrw_extra; + /* + * Specify the enable of extra Mode Register programming at + * warm boot + */ + u32 emc_warm_boot_extramode_reg_write_enable; + /* + * Specify the enable of extra Mode Register programming at + * cold boot + */ + u32 emc_extramode_reg_write_enable; + + /* Specifies the EMC_MRW reset command value */ + u32 emc_mrw_reset_command; + /* Specifies the EMC Reset wait time (in microseconds) */ + u32 emc_mrw_reset_ninit_wait; + /* Specifies the value for EMC_MRS_WAIT_CNT */ + u32 emc_mrs_wait_cnt; + /* Specifies the value for EMC_MRS_WAIT_CNT2 */ + u32 emc_mrs_wait_cnt2; + + /* EMC miscellaneous configurations */ + + /* Specifies the value for EMC_CFG */ + u32 emc_cfg; + /* Specifies the value for EMC_CFG_2 */ + u32 emc_cfg2; + /* Specifies the pipe bypass controls */ + u32 emc_cfg_pipe; + + u32 emc_cfg_pipe_clk; + u32 emc_fdpd_ctrl_cmd_no_ramp; + u32 emc_cfg_update; + + /* Specifies the value for EMC_DBG */ + u32 emc_dbg; + + u32 emc_dbg_write_mux; + + /* Specifies the value for EMC_CMDQ */ + u32 emc_cmd_q; + /* Specifies the value for EMC_MC2EMCQ */ + u32 emc_mc2emc_q; + /* Specifies the value for EMC_DYN_SELF_REF_CONTROL */ + u32 emc_dyn_self_ref_control; + + /* Specifies the value for MEM_INIT_DONE */ + u32 ahb_arbitration_xbar_ctrl_meminit_done; + + /* Specifies the value for EMC_CFG_DIG_DLL */ + u32 emc_cfg_dig_dll; + u32 emc_cfg_dig_dll_1; + + /* Specifies the value for EMC_CFG_DIG_DLL_PERIOD */ + u32 emc_cfg_dig_dll_period; + /* Specifies the value of *DEV_SELECTN of various EMC registers */ + u32 emc_dev_select; + + /* Specifies the value for EMC_SEL_DPD_CTRL */ + u32 emc_sel_dpd_ctrl; + + /* Pads trimmer delays */ + u32 emc_fdpd_ctrl_dq; + u32 emc_fdpd_ctrl_cmd; + u32 emc_pmacro_ib_vref_dq_0; + u32 emc_pmacro_ib_vref_dq_1; + u32 emc_pmacro_ib_vref_dqs_0; + u32 emc_pmacro_ib_vref_dqs_1; + u32 emc_pmacro_ib_rxrt; + u32 emc_cfg_pipe1; + u32 emc_cfg_pipe2; + + /* Specifies the value for EMC_PMACRO_QUSE_DDLL_RANK0_0 */ + u32 emc_pmacro_quse_ddll_rank0_0; + u32 emc_pmacro_quse_ddll_rank0_1; + u32 emc_pmacro_quse_ddll_rank0_2; + u32 emc_pmacro_quse_ddll_rank0_3; + u32 emc_pmacro_quse_ddll_rank0_4; + u32 emc_pmacro_quse_ddll_rank0_5; + u32 emc_pmacro_quse_ddll_rank1_0; + u32 emc_pmacro_quse_ddll_rank1_1; + u32 emc_pmacro_quse_ddll_rank1_2; + u32 emc_pmacro_quse_ddll_rank1_3; + u32 emc_pmacro_quse_ddll_rank1_4; + u32 emc_pmacro_quse_ddll_rank1_5; + + u32 emc_pmacro_ob_ddll_long_dq_rank0_0; + u32 emc_pmacro_ob_ddll_long_dq_rank0_1; + u32 emc_pmacro_ob_ddll_long_dq_rank0_2; + u32 emc_pmacro_ob_ddll_long_dq_rank0_3; + u32 emc_pmacro_ob_ddll_long_dq_rank0_4; + u32 emc_pmacro_ob_ddll_long_dq_rank0_5; + u32 emc_pmacro_ob_ddll_long_dq_rank1_0; + u32 emc_pmacro_ob_ddll_long_dq_rank1_1; + u32 emc_pmacro_ob_ddll_long_dq_rank1_2; + u32 emc_pmacro_ob_ddll_long_dq_rank1_3; + u32 emc_pmacro_ob_ddll_long_dq_rank1_4; + u32 emc_pmacro_ob_ddll_long_dq_rank1_5; + + u32 emc_pmacro_ob_ddll_long_dqs_rank0_0; + u32 emc_pmacro_ob_ddll_long_dqs_rank0_1; + u32 emc_pmacro_ob_ddll_long_dqs_rank0_2; + u32 emc_pmacro_ob_ddll_long_dqs_rank0_3; + u32 emc_pmacro_ob_ddll_long_dqs_rank0_4; + u32 emc_pmacro_ob_ddll_long_dqs_rank0_5; + u32 emc_pmacro_ob_ddll_long_dqs_rank1_0; + u32 emc_pmacro_ob_ddll_long_dqs_rank1_1; + u32 emc_pmacro_ob_ddll_long_dqs_rank1_2; + u32 emc_pmacro_ob_ddll_long_dqs_rank1_3; + u32 emc_pmacro_ob_ddll_long_dqs_rank1_4; + u32 emc_pmacro_ob_ddll_long_dqs_rank1_5; + + u32 emc_pmacro_ib_ddll_long_dqs_rank0_0; + u32 emc_pmacro_ib_ddll_long_dqs_rank0_1; + u32 emc_pmacro_ib_ddll_long_dqs_rank0_2; + u32 emc_pmacro_ib_ddll_long_dqs_rank0_3; + u32 emc_pmacro_ib_ddll_long_dqs_rank1_0; + u32 emc_pmacro_ib_ddll_long_dqs_rank1_1; + u32 emc_pmacro_ib_ddll_long_dqs_rank1_2; + u32 emc_pmacro_ib_ddll_long_dqs_rank1_3; + + u32 emc_pmacro_ddll_long_cmd_0; + u32 emc_pmacro_ddll_long_cmd_1; + u32 emc_pmacro_ddll_long_cmd_2; + u32 emc_pmacro_ddll_long_cmd_3; + u32 emc_pmacro_ddll_long_cmd_4; + u32 emc_pmacro_ddll_short_cmd_0; + u32 emc_pmacro_ddll_short_cmd_1; + u32 emc_pmacro_ddll_short_cmd_2; + + u32 emc_pmacro_ddll_periodic_offset; + + /* + * Specifies the delay after asserting CKE pin during a WarmBoot0 + * sequence (in microseconds) + */ + u32 warm_boot_wait; + + /* Specifies the value for EMC_ODT_WRITE */ + u32 emc_odt_write; + + /* Periodic ZQ calibration */ + + /* + * Specifies the value for EMC_ZCAL_INTERVAL + * Value 0 disables ZQ calibration + */ + u32 emc_zcal_interval; + /* Specifies the value for EMC_ZCAL_WAIT_CNT */ + u32 emc_zcal_wait_cnt; + /* Specifies the value for EMC_ZCAL_MRW_CMD */ + u32 emc_zcal_mrw_cmd; + + /* DRAM initialization sequence flow control */ + + /* Specifies the MRS command value for resetting DLL */ + u32 emc_mrs_reset_dll; + /* Specifies the command for ZQ initialization of device 0 */ + u32 emc_zcal_init_dev0; + /* Specifies the command for ZQ initialization of device 1 */ + u32 emc_zcal_init_dev1; + /* + * Specifies the wait time after programming a ZQ initialization + * command (in microseconds) + */ + u32 emc_zcal_init_wait; + /* + * Specifies the enable for ZQ calibration at cold boot [bit 0] + * and warm boot [bit 1] + */ + u32 emc_zcal_warm_cold_boot_enables; + + /* + * Specifies the MRW command to LPDDR2 for ZQ calibration + * on warmboot + */ + /* Is issued to both devices separately */ + u32 emc_mrw_lpddr2zcal_warm_boot; + /* + * Specifies the ZQ command to DDR3 for ZQ calibration on warmboot + * Is issued to both devices separately + */ + u32 emc_zqcal_ddr3_warm_boot; + + u32 emc_zqcal_lpddr4_warm_boot; + + /* + * Specifies the wait time for ZQ calibration on warmboot + * (in microseconds) + */ + u32 emc_zcal_warm_boot_wait; + /* + * Specifies the enable for DRAM Mode Register programming + * at warm boot + */ + u32 emc_mrs_warm_boot_enable; + /* + * Specifies the wait time after sending an MRS DLL reset command + * in microseconds) + */ + u32 emc_mrs_reset_dll_wait; + /* Specifies the extra MRS command to initialize mode registers */ + u32 emc_mrs_extra; + /* Specifies the extra MRS command at warm boot */ + u32 emc_warm_boot_mrs_extra; + /* Specifies the EMRS command to enable the DDR2 DLL */ + u32 emc_emrs_ddr2_dll_enable; + /* Specifies the MRS command to reset the DDR2 DLL */ + u32 emc_mrs_ddr2_dll_reset; + /* Specifies the EMRS command to set OCD calibration */ + u32 emc_emrs_ddr2_ocd_calib; + /* + * Specifies the wait between initializing DDR and setting OCD + * calibration (in microseconds) + */ + u32 emc_ddr2_wait; + /* Specifies the value for EMC_CLKEN_OVERRIDE */ + u32 emc_clken_override; + /* + * Specifies LOG2 of the extra refresh numbers after booting + * Program 0 to disable + */ + u32 emc_extra_refresh_num; + /* Specifies the master override for all EMC clocks */ + u32 emc_clken_override_allwarm_boot; + /* Specifies the master override for all MC clocks */ + u32 mc_clken_override_allwarm_boot; + /* Specifies digital dll period, choosing between 4 to 64 ms */ + u32 emc_cfg_dig_dll_period_warm_boot; + + /* Pad controls */ + + /* Specifies the value for PMC_VDDP_SEL */ + u32 pmc_vddp_sel; + /* Specifies the wait time after programming PMC_VDDP_SEL */ + u32 pmc_vddp_sel_wait; + /* Specifies the value for PMC_DDR_CFG */ + u32 pmc_ddr_cfg; + /* Specifies the value for PMC_IO_DPD3_REQ */ + u32 pmc_io_dpd3_req; + /* Specifies the wait time after programming PMC_IO_DPD3_REQ */ + u32 pmc_io_dpd3_req_wait; + + u32 pmc_io_dpd4_req_wait; + + /* Specifies the value for PMC_REG_SHORT */ + u32 pmc_reg_short; + /* Specifies the value for PMC_NO_IOPOWER */ + u32 pmc_no_io_power; + + u32 pmc_ddr_ctrl_wait; + u32 pmc_ddr_ctrl; + + /* Specifies the value for EMC_ACPD_CONTROL */ + u32 emc_acpd_control; + + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE0 */ + u32 emc_swizzle_rank0_byte0; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE1 */ + u32 emc_swizzle_rank0_byte1; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE2 */ + u32 emc_swizzle_rank0_byte2; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE3 */ + u32 emc_swizzle_rank0_byte3; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE0 */ + u32 emc_swizzle_rank1_byte0; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE1 */ + u32 emc_swizzle_rank1_byte1; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE2 */ + u32 emc_swizzle_rank1_byte2; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE3 */ + u32 emc_swizzle_rank1_byte3; + + /* Specifies the value for EMC_TXDSRVTTGEN */ + u32 emc_txdsrvttgen; + + /* Specifies the value for EMC_DATA_BRLSHFT_0 */ + u32 emc_data_brlshft0; + u32 emc_data_brlshft1; + + u32 emc_dqs_brlshft0; + u32 emc_dqs_brlshft1; + + u32 emc_cmd_brlshft0; + u32 emc_cmd_brlshft1; + u32 emc_cmd_brlshft2; + u32 emc_cmd_brlshft3; + + u32 emc_quse_brlshft0; + u32 emc_quse_brlshft1; + u32 emc_quse_brlshft2; + u32 emc_quse_brlshft3; + + u32 emc_dll_cfg0; + u32 emc_dll_cfg1; + + u32 emc_pmc_scratch1; + u32 emc_pmc_scratch2; + u32 emc_pmc_scratch3; + + u32 emc_pmacro_pad_cfg_ctrl; + + u32 emc_pmacro_vttgen_ctrl0; + u32 emc_pmacro_vttgen_ctrl1; + u32 emc_pmacro_vttgen_ctrl2; + u32 emc_pmacro_dsr_vttgen_ctrl0; + u32 emc_pmacro_brick_ctrl_rfu1; + u32 emc_pmacro_cmd_brick_ctrl_fdpd; + u32 emc_pmacro_brick_ctrl_rfu2; + u32 emc_pmacro_data_brick_ctrl_fdpd; + u32 emc_pmacro_bg_bias_ctrl0; + u32 emc_pmacro_data_pad_rx_ctrl; + u32 emc_pmacro_cmd_pad_rx_ctrl; + u32 emc_pmacro_data_rx_term_mode; + u32 emc_pmacro_cmd_rx_term_mode; + u32 emc_pmacro_data_pad_tx_ctrl; + u32 emc_pmacro_cmd_pad_tx_ctrl; + u32 emc_cfg3; + + u32 emc_pmacro_tx_pwrd0; + u32 emc_pmacro_tx_pwrd1; + u32 emc_pmacro_tx_pwrd2; + u32 emc_pmacro_tx_pwrd3; + u32 emc_pmacro_tx_pwrd4; + u32 emc_pmacro_tx_pwrd5; + + u32 emc_config_sample_delay; + + u32 emc_pmacro_brick_mapping0; + u32 emc_pmacro_brick_mapping1; + u32 emc_pmacro_brick_mapping2; + + u32 emc_pmacro_tx_sel_clk_src0; + u32 emc_pmacro_tx_sel_clk_src1; + u32 emc_pmacro_tx_sel_clk_src2; + u32 emc_pmacro_tx_sel_clk_src3; + u32 emc_pmacro_tx_sel_clk_src4; + u32 emc_pmacro_tx_sel_clk_src5; + + u32 emc_pmacro_perbit_fgcg_ctrl0; + u32 emc_pmacro_perbit_fgcg_ctrl1; + u32 emc_pmacro_perbit_fgcg_ctrl2; + u32 emc_pmacro_perbit_fgcg_ctrl3; + u32 emc_pmacro_perbit_fgcg_ctrl4; + u32 emc_pmacro_perbit_fgcg_ctrl5; + u32 emc_pmacro_perbit_rfu_ctrl0; + u32 emc_pmacro_perbit_rfu_ctrl1; + u32 emc_pmacro_perbit_rfu_ctrl2; + u32 emc_pmacro_perbit_rfu_ctrl3; + u32 emc_pmacro_perbit_rfu_ctrl4; + u32 emc_pmacro_perbit_rfu_ctrl5; + u32 emc_pmacro_perbit_rfu1_ctrl0; + u32 emc_pmacro_perbit_rfu1_ctrl1; + u32 emc_pmacro_perbit_rfu1_ctrl2; + u32 emc_pmacro_perbit_rfu1_ctrl3; + u32 emc_pmacro_perbit_rfu1_ctrl4; + u32 emc_pmacro_perbit_rfu1_ctrl5; + + u32 emc_pmacro_data_pi_ctrl; + u32 emc_pmacro_cmd_pi_ctrl; + + u32 emc_pmacro_ddll_bypass; + + u32 emc_pmacro_ddll_pwrd0; + u32 emc_pmacro_ddll_pwrd1; + u32 emc_pmacro_ddll_pwrd2; + + u32 emc_pmacro_cmd_ctrl0; + u32 emc_pmacro_cmd_ctrl1; + u32 emc_pmacro_cmd_ctrl2; + + /* DRAM size information */ + + /* Specifies the value for MC_EMEM_ADR_CFG */ + u32 mc_emem_adr_cfg; + /* Specifies the value for MC_EMEM_ADR_CFG_DEV0 */ + u32 mc_emem_adr_cfg_dev0; + /* Specifies the value for MC_EMEM_ADR_CFG_DEV1 */ + u32 mc_emem_adr_cfg_dev1; + + u32 mc_emem_adr_cfg_channel_mask; + + /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG0 */ + u32 mc_emem_adr_cfg_bank_mask0; + /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG1 */ + u32 mc_emem_adr_cfg_bank_mask1; + /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG2 */ + u32 mc_emem_adr_cfg_bank_mask2; + + /* + * Specifies the value for MC_EMEM_CFG which holds the external memory + * size (in KBytes) + */ + u32 mc_emem_cfg; + + /* MC arbitration configuration */ + + /* Specifies the value for MC_EMEM_ARB_CFG */ + u32 mc_emem_arb_cfg; + /* Specifies the value for MC_EMEM_ARB_OUTSTANDING_REQ */ + u32 mc_emem_arb_outstanding_req; + + u32 emc_emem_arb_refpb_hp_ctrl; + u32 emc_emem_arb_refpb_bank_ctrl; + + /* Specifies the value for MC_EMEM_ARB_TIMING_RCD */ + u32 mc_emem_arb_timing_rcd; + /* Specifies the value for MC_EMEM_ARB_TIMING_RP */ + u32 mc_emem_arb_timing_rp; + /* Specifies the value for MC_EMEM_ARB_TIMING_RC */ + u32 mc_emem_arb_timing_rc; + /* Specifies the value for MC_EMEM_ARB_TIMING_RAS */ + u32 mc_emem_arb_timing_ras; + /* Specifies the value for MC_EMEM_ARB_TIMING_FAW */ + u32 mc_emem_arb_timing_faw; + /* Specifies the value for MC_EMEM_ARB_TIMING_RRD */ + u32 mc_emem_arb_timing_rrd; + /* Specifies the value for MC_EMEM_ARB_TIMING_RAP2PRE */ + u32 mc_emem_arb_timing_rap2pre; + /* Specifies the value for MC_EMEM_ARB_TIMING_WAP2PRE */ + u32 mc_emem_arb_timing_wap2pre; + /* Specifies the value for MC_EMEM_ARB_TIMING_R2R */ + u32 mc_emem_arb_timing_r2r; + /* Specifies the value for MC_EMEM_ARB_TIMING_W2W */ + u32 mc_emem_arb_timing_w2w; + /* Specifies the value for MC_EMEM_ARB_TIMING_R2W */ + u32 mc_emem_arb_timing_r2w; + /* Specifies the value for MC_EMEM_ARB_TIMING_W2R */ + u32 mc_emem_arb_timing_w2r; + + u32 mc_emem_arb_timing_rfcpb; + + /* Specifies the value for MC_EMEM_ARB_DA_TURNS */ + u32 mc_emem_arb_da_turns; + /* Specifies the value for MC_EMEM_ARB_DA_COVERS */ + u32 mc_emem_arb_da_covers; + /* Specifies the value for MC_EMEM_ARB_MISC0 */ + u32 mc_emem_arb_misc0; + /* Specifies the value for MC_EMEM_ARB_MISC1 */ + u32 mc_emem_arb_misc1; + u32 mc_emem_arb_misc2; + + /* Specifies the value for MC_EMEM_ARB_RING1_THROTTLE */ + u32 mc_emem_arb_ring1_throttle; + /* Specifies the value for MC_EMEM_ARB_OVERRIDE */ + u32 mc_emem_arb_override; + /* Specifies the value for MC_EMEM_ARB_OVERRIDE_1 */ + u32 mc_emem_arb_override1; + /* Specifies the value for MC_EMEM_ARB_RSV */ + u32 mc_emem_arb_rsv; + + u32 mc_da_cfg0; + u32 mc_emem_arb_timing_ccdmw; + + /* Specifies the value for MC_CLKEN_OVERRIDE */ + u32 mc_clken_override; + + /* Specifies the value for MC_STAT_CONTROL */ + u32 mc_stat_control; + /* Specifies the value for MC_VIDEO_PROTECT_BOM */ + u32 mc_video_protect_bom; + /* Specifies the value for MC_VIDEO_PROTECT_BOM_ADR_HI */ + u32 mc_video_protect_bom_adr_hi; + /* Specifies the value for MC_VIDEO_PROTECT_SIZE_MB */ + u32 mc_video_protect_size_mb; + /* Specifies the value for MC_VIDEO_PROTECT_VPR_OVERRIDE */ + u32 mc_video_protect_vpr_override; + /* Specifies the value for MC_VIDEO_PROTECT_VPR_OVERRIDE1 */ + u32 mc_video_protect_vpr_override1; + /* Specifies the value for MC_VIDEO_PROTECT_GPU_OVERRIDE_0 */ + u32 mc_video_protect_gpu_override0; + /* Specifies the value for MC_VIDEO_PROTECT_GPU_OVERRIDE_1 */ + u32 mc_video_protect_gpu_override1; + /* Specifies the value for MC_SEC_CARVEOUT_BOM */ + u32 mc_sec_carveout_bom; + /* Specifies the value for MC_SEC_CARVEOUT_ADR_HI */ + u32 mc_sec_carveout_adr_hi; + /* Specifies the value for MC_SEC_CARVEOUT_SIZE_MB */ + u32 mc_sec_carveout_size_mb; + /* Specifies the value for MC_VIDEO_PROTECT_REG_CTRL.VIDEO_PROTECT_WRITE_ACCESS */ + u32 mc_video_protect_write_access; + /* Specifies the value for MC_SEC_CARVEOUT_REG_CTRL.SEC_CARVEOUT_WRITE_ACCESS */ + u32 mc_sec_carveout_protect_write_access; + + u32 mc_generalized_carveout1_bom; + u32 mc_generalized_carveout1_bom_hi; + u32 mc_generalized_carveout1_size_128kb; + u32 mc_generalized_carveout1_access0; + u32 mc_generalized_carveout1_access1; + u32 mc_generalized_carveout1_access2; + u32 mc_generalized_carveout1_access3; + u32 mc_generalized_carveout1_access4; + u32 mc_generalized_carveout1_force_internal_access0; + u32 mc_generalized_carveout1_force_internal_access1; + u32 mc_generalized_carveout1_force_internal_access2; + u32 mc_generalized_carveout1_force_internal_access3; + u32 mc_generalized_carveout1_force_internal_access4; + u32 mc_generalized_carveout1_cfg0; + + u32 mc_generalized_carveout2_bom; + u32 mc_generalized_carveout2_bom_hi; + u32 mc_generalized_carveout2_size_128kb; + u32 mc_generalized_carveout2_access0; + u32 mc_generalized_carveout2_access1; + u32 mc_generalized_carveout2_access2; + u32 mc_generalized_carveout2_access3; + u32 mc_generalized_carveout2_access4; + u32 mc_generalized_carveout2_force_internal_access0; + u32 mc_generalized_carveout2_force_internal_access1; + u32 mc_generalized_carveout2_force_internal_access2; + u32 mc_generalized_carveout2_force_internal_access3; + u32 mc_generalized_carveout2_force_internal_access4; + u32 mc_generalized_carveout2_cfg0; + + u32 mc_generalized_carveout3_bom; + u32 mc_generalized_carveout3_bom_hi; + u32 mc_generalized_carveout3_size_128kb; + u32 mc_generalized_carveout3_access0; + u32 mc_generalized_carveout3_access1; + u32 mc_generalized_carveout3_access2; + u32 mc_generalized_carveout3_access3; + u32 mc_generalized_carveout3_access4; + u32 mc_generalized_carveout3_force_internal_access0; + u32 mc_generalized_carveout3_force_internal_access1; + u32 mc_generalized_carveout3_force_internal_access2; + u32 mc_generalized_carveout3_force_internal_access3; + u32 mc_generalized_carveout3_force_internal_access4; + u32 mc_generalized_carveout3_cfg0; + + u32 mc_generalized_carveout4_bom; + u32 mc_generalized_carveout4_bom_hi; + u32 mc_generalized_carveout4_size_128kb; + u32 mc_generalized_carveout4_access0; + u32 mc_generalized_carveout4_access1; + u32 mc_generalized_carveout4_access2; + u32 mc_generalized_carveout4_access3; + u32 mc_generalized_carveout4_access4; + u32 mc_generalized_carveout4_force_internal_access0; + u32 mc_generalized_carveout4_force_internal_access1; + u32 mc_generalized_carveout4_force_internal_access2; + u32 mc_generalized_carveout4_force_internal_access3; + u32 mc_generalized_carveout4_force_internal_access4; + u32 mc_generalized_carveout4_cfg0; + + u32 mc_generalized_carveout5_bom; + u32 mc_generalized_carveout5_bom_hi; + u32 mc_generalized_carveout5_size_128kb; + u32 mc_generalized_carveout5_access0; + u32 mc_generalized_carveout5_access1; + u32 mc_generalized_carveout5_access2; + u32 mc_generalized_carveout5_access3; + u32 mc_generalized_carveout5_access4; + u32 mc_generalized_carveout5_force_internal_access0; + u32 mc_generalized_carveout5_force_internal_access1; + u32 mc_generalized_carveout5_force_internal_access2; + u32 mc_generalized_carveout5_force_internal_access3; + u32 mc_generalized_carveout5_force_internal_access4; + u32 mc_generalized_carveout5_cfg0; + + /* Specifies enable for CA training */ + u32 emc_ca_training_enable; + /* Set if bit 6 select is greater than bit 7 select; uses aremc.spec packet SWIZZLE_BIT6_GT_BIT7 */ + u32 swizzle_rank_byte_encode; + /* Specifies enable and offset for patched boot rom write */ + u32 boot_rom_patch_control; + /* Specifies data for patched boot rom write */ + u32 boot_rom_patch_data; + + /* Specifies the value for MC_MTS_CARVEOUT_BOM */ + u32 mc_mts_carveout_bom; + /* Specifies the value for MC_MTS_CARVEOUT_ADR_HI */ + u32 mc_mts_carveout_adr_hi; + /* Specifies the value for MC_MTS_CARVEOUT_SIZE_MB */ + u32 mc_mts_carveout_size_mb; + /* Specifies the value for MC_MTS_CARVEOUT_REG_CTRL */ + u32 mc_mts_carveout_reg_ctrl; + + /* Specifies the clients that are allowed to access untranslated memory */ + u32 mc_untranslated_region_check; + + /* Just a place holder for special usage when there is no BCT for certain registers */ + u32 bct_na; +} sdram_params_t210b01_t; + +#endif diff --git a/bdk/memory_map.h b/bdk/memory_map.h index 6a83651..f72a0c5 100644 --- a/bdk/memory_map.h +++ b/bdk/memory_map.h @@ -20,9 +20,16 @@ //#define IPL_STACK_TOP 0x4003FF00 /* --- BIT/BCT: 0x40000000 - 0x40003000 --- */ /* --- IPL: 0x40003000 - 0x40028000 --- */ +#define LDR_LOAD_ADDR 0x40007000 + #define IPL_LOAD_ADDR 0x40003000 #define IPL_SZ_MAX 0x20000 // 128KB. -//#define IRAM_LIB_ADDR 0x4002B000 + +/* --- XUSB EP context and TRB ring buffers --- */ +#define XUSB_RING_ADDR 0x40020000 + +#define SECMON_MIN_START 0x4002B000 + #define SDRAM_PARAMS_ADDR 0x40030000 // SDRAM extraction buffer during sdram init. #define CBFS_DRAM_EN_ADDR 0x4003e000 // u32. @@ -45,6 +52,10 @@ #define NX_BIS_CACHE_ADDR RAM_DISK_ADDR #define RAM_DISK_SZ 0x41000000 // 1040MB. +// L4T Kernel Panic Storage (PSTORE). +#define PSTORE_ADDR 0xB0000000 +#define PSTORE_SZ 0x200000 // 2MB. + //#define DRAM_LIB_ADDR 0xE0000000 /* --- Chnldr: 252MB 0xC03C0000 - 0xCFFFFFFF --- */ //! Only used when chainloading. diff --git a/bdk/power/bm92t36.c b/bdk/power/bm92t36.c new file mode 100644 index 0000000..d1496f7 --- /dev/null +++ b/bdk/power/bm92t36.c @@ -0,0 +1,99 @@ +/* + * USB-PD driver for Nintendo Switch's TI BM92T36 + * + * Copyright (c) 2020 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 "bm92t36.h" +#include +#include + +#define ALERT_STATUS_REG 0x2 +#define STATUS1_REG 0x3 +#define STATUS2_REG 0x4 +#define COMMAND_REG 0x5 +#define CONFIG1_REG 0x6 +#define DEV_CAPS_REG 0x7 +#define READ_PDOS_SRC_REG 0x8 +#define CONFIG2_REG 0x17 +#define DP_STATUS_REG 0x18 +#define DP_ALERT_EN_REG 0x19 +#define VENDOR_CONFIG_REG 0x1A +#define AUTO_NGT_FIXED_REG 0x20 +#define AUTO_NGT_BATT_REG 0x23 +#define SYS_CONFIG1_REG 0x26 +#define SYS_CONFIG2_REG 0x27 +#define CURRENT_PDO_REG 0x28 +#define CURRENT_RDO_REG 0x2B +#define ALERT_ENABLE_REG 0x2E +#define SYS_CONFIG3_REG 0x2F +#define SET_RDO_REG 0x30 +#define PDOS_SNK_REG 0x33 +#define PDOS_SRC_PROV_REG 0x3C +#define FW_TYPE_REG 0x4B +#define FW_REVISION_REG 0x4C +#define MAN_ID_REG 0x4D +#define DEV_ID_REG 0x4E +#define REV_ID_REG 0x4F +#define INCOMING_VDM_REG 0x50 +#define OUTGOING_VDM_REG 0x60 + +#define STATUS1_INSERT BIT(7) // Cable inserted. + +typedef struct _pd_object_t { + unsigned int amp:10; + unsigned int volt:10; + unsigned int info:10; + unsigned int type:2; +} __attribute__((packed)) pd_object_t; + +static int _bm92t36_read_reg(u8 *buf, u32 size, u32 reg) +{ + return i2c_recv_buf_big(buf, size, I2C_1, BM92T36_I2C_ADDR, reg); +} + +void bm92t36_get_sink_info(bool *inserted, usb_pd_objects_t *usb_pd) +{ + u8 buf[32]; + pd_object_t pdos[7]; + + if (inserted) + { + _bm92t36_read_reg(buf, 2, STATUS1_REG); + *inserted = buf[0] & STATUS1_INSERT ? true : false; + } + + if (usb_pd) + { + _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); + + for (u32 i = 0; i < usb_pd->pdo_no; i++) + { + usb_pd->pdos[i].amperage = pdos[i].amp * 10; + usb_pd->pdos[i].voltage = (pdos[i].volt * 50) / 1000; + } + + _bm92t36_read_reg(buf, 5, CURRENT_PDO_REG); + memcpy(pdos, &buf[1], 4); + usb_pd->selected_pdo.amperage = pdos[0].amp * 10; + usb_pd->selected_pdo.voltage = (pdos[0].volt * 50) / 1000; + } +} diff --git a/bdk/power/bm92t36.h b/bdk/power/bm92t36.h new file mode 100644 index 0000000..e6740d8 --- /dev/null +++ b/bdk/power/bm92t36.h @@ -0,0 +1,41 @@ +/* + * USB-PD driver for Nintendo Switch's TI BM92T36 + * + * Copyright (c) 2020 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 __BM92T36_H_ +#define __BM92T36_H_ + +#include + +#define BM92T36_I2C_ADDR 0x18 + +typedef struct _usb_pd_object_t +{ + u32 amperage; + u32 voltage; +} usb_pd_object_t; + +typedef struct _usb_pd_objects_t +{ + u32 pdo_no; + usb_pd_object_t pdos[7]; + usb_pd_object_t selected_pdo; +} usb_pd_objects_t; + +void bm92t36_get_sink_info(bool *inserted, usb_pd_objects_t *usb_pd); + +#endif diff --git a/bdk/power/max17050.c b/bdk/power/max17050.c index 2491466..a561724 100644 --- a/bdk/power/max17050.c +++ b/bdk/power/max17050.c @@ -26,17 +26,19 @@ #include #include +#define BASE_SNS_UOHM 5000 + /* Status register bits */ -#define STATUS_POR_BIT (1 << 1) -#define STATUS_BST_BIT (1 << 3) -#define STATUS_VMN_BIT (1 << 8) -#define STATUS_TMN_BIT (1 << 9) -#define STATUS_SMN_BIT (1 << 10) -#define STATUS_BI_BIT (1 << 11) -#define STATUS_VMX_BIT (1 << 12) -#define STATUS_TMX_BIT (1 << 13) -#define STATUS_SMX_BIT (1 << 14) -#define STATUS_BR_BIT (1 << 15) +#define STATUS_POR_BIT BIT(1) +#define STATUS_BST_BIT BIT(3) +#define STATUS_VMN_BIT BIT(8) +#define STATUS_TMN_BIT BIT(9) +#define STATUS_SMN_BIT BIT(10) +#define STATUS_BI_BIT BIT(11) +#define STATUS_VMX_BIT BIT(12) +#define STATUS_TMX_BIT BIT(13) +#define STATUS_SMX_BIT BIT(14) +#define STATUS_BR_BIT BIT(15) #define VFSOC0_LOCK 0x0000 #define VFSOC0_UNLOCK 0x0080 @@ -85,31 +87,31 @@ int max17050_get_property(enum MAX17050_reg reg, int *value) break; case MAX17050_VCELL: // Voltage now. data = max17050_get_reg(MAX17050_VCELL); - *value = data * 625 / 8 / 1000; + *value = (data >> 3) * 625 / 1000; /* Units of LSB = 0.625mV */ battery_voltage = *value; break; case MAX17050_AvgVCELL: // Voltage avg. data = max17050_get_reg(MAX17050_AvgVCELL); - *value = data * 625 / 8 / 1000; + *value = (data >> 3) * 625 / 1000; /* Units of LSB = 0.625mV */ break; case MAX17050_OCVInternal: // Voltage ocv. data = max17050_get_reg(MAX17050_OCVInternal); - *value = data * 625 / 8 / 1000; + *value = (data >> 3) * 625 / 1000; /* Units of LSB = 0.625mV */ break; case MAX17050_RepSOC: // Capacity %. *value = max17050_get_reg(MAX17050_RepSOC); break; case MAX17050_DesignCap: // Charge full design. data = max17050_get_reg(MAX17050_DesignCap); - *value = data * 5 / 10; + *value = data * (BASE_SNS_UOHM / MAX17050_BOARD_SNS_RESISTOR_UOHM) / MAX17050_BOARD_CGAIN; break; case MAX17050_FullCAP: // Charge full. data = max17050_get_reg(MAX17050_FullCAP); - *value = data * 5 / 10; + *value = data * (BASE_SNS_UOHM / MAX17050_BOARD_SNS_RESISTOR_UOHM) / MAX17050_BOARD_CGAIN; break; case MAX17050_RepCap: // Charge now. data = max17050_get_reg(MAX17050_RepCap); - *value = data * 5 / 10; + *value = data * (BASE_SNS_UOHM / MAX17050_BOARD_SNS_RESISTOR_UOHM) / MAX17050_BOARD_CGAIN; break; case MAX17050_TEMP: // Temp. data = max17050_get_reg(MAX17050_TEMP); @@ -119,12 +121,12 @@ int max17050_get_property(enum MAX17050_reg reg, int *value) case MAX17050_Current: // Current now. data = max17050_get_reg(MAX17050_Current); *value = (s16)data; - *value *= 1562500 / MAX17050_DEFAULT_SNS_RESISTOR; + *value *= 1562500 / (MAX17050_BOARD_SNS_RESISTOR_UOHM * MAX17050_BOARD_CGAIN); break; case MAX17050_AvgCurrent: // Current avg. data = max17050_get_reg(MAX17050_AvgCurrent); *value = (s16)data; - *value *= 1562500 / MAX17050_DEFAULT_SNS_RESISTOR; + *value *= 1562500 / (MAX17050_BOARD_SNS_RESISTOR_UOHM * MAX17050_BOARD_CGAIN); break; default: return -1; diff --git a/bdk/power/max17050.h b/bdk/power/max17050.h index 254aca3..a9b3d37 100644 --- a/bdk/power/max17050.h +++ b/bdk/power/max17050.h @@ -1,6 +1,5 @@ /* * Fuel gauge driver for Nintendo Switch's Maxim 17050 - * Note that Maxim 8966 and 8997 are mfd and this is its subdevice. * * Copyright (c) 2011 Samsung Electronics * MyungJoo Ham @@ -26,8 +25,11 @@ #include -#define MAX17050_STATUS_BattAbsent (1 << 3) -#define MAX17050_DEFAULT_SNS_RESISTOR 10000 +/* Board default values */ +#define MAX17050_BOARD_CGAIN 2 /* Actual: 1.99993 */ +#define MAX17050_BOARD_SNS_RESISTOR_UOHM 5000 /* 0.005 Ohm */ + +#define MAX17050_STATUS_BattAbsent BIT(3) /* Consider RepCap which is less then 10 units below FullCAP full */ #define MAX17050_FULL_THRESHOLD 10 diff --git a/bdk/power/max77620.h b/bdk/power/max77620.h index 26ea855..23ee299 100644 --- a/bdk/power/max77620.h +++ b/bdk/power/max77620.h @@ -16,13 +16,7 @@ /* GLOBAL, PMIC, GPIO, FPS, ONOFFC, CID Registers */ #define MAX77620_REG_CNFGGLBL1 0x00 -#define MAX77620_CNFGGLBL1_LBDAC_EN (1 << 7) -#define MAX77620_CNFGGLBL1_MPPLD (1 << 6) -#define MAX77620_CNFGGLBL1_LBHYST ((1 << 5) | (1 << 4)) -#define MAX77620_CNFGGLBL1_LBHYST_100 (0 << 4) -#define MAX77620_CNFGGLBL1_LBHYST_200 (1 << 4) -#define MAX77620_CNFGGLBL1_LBHYST_300 (2 << 4) -#define MAX77620_CNFGGLBL1_LBHYST_400 (3 << 4) +#define MAX77620_CNFGGLBL1_LBRSTEN BIT(0) #define MAX77620_CNFGGLBL1_LBDAC_MASK 0x0E #define MAX77620_CNFGGLBL1_LBDAC_2700 (0 << 1) #define MAX77620_CNFGGLBL1_LBDAC_2800 (1 << 1) @@ -32,14 +26,20 @@ #define MAX77620_CNFGGLBL1_LBDAC_3200 (5 << 1) #define MAX77620_CNFGGLBL1_LBDAC_3300 (6 << 1) #define MAX77620_CNFGGLBL1_LBDAC_3400 (7 << 1) -#define MAX77620_CNFGGLBL1_LBRSTEN (1 << 0) +#define MAX77620_CNFGGLBL1_LBHYST_100 (0 << 4) +#define MAX77620_CNFGGLBL1_LBHYST_200 (1 << 4) +#define MAX77620_CNFGGLBL1_LBHYST_300 (2 << 4) +#define MAX77620_CNFGGLBL1_LBHYST_400 (3 << 4) +#define MAX77620_CNFGGLBL1_LBHYST (BIT(5) | BIT(4)) +#define MAX77620_CNFGGLBL1_MPPLD BIT(6) +#define MAX77620_CNFGGLBL1_LBDAC_EN BIT(7) #define MAX77620_REG_CNFGGLBL2 0x01 #define MAX77620_REG_CNFGGLBL3 0x02 #define MAX77620_WDTC_MASK 0x3 -#define MAX77620_WDTOFFC (1 << 4) -#define MAX77620_WDTSLPC (1 << 3) -#define MAX77620_WDTEN (1 << 2) +#define MAX77620_WDTEN BIT(2) +#define MAX77620_WDTSLPC BIT(3) +#define MAX77620_WDTOFFC BIT(4) #define MAX77620_TWD_MASK 0x3 #define MAX77620_TWD_2s 0x0 #define MAX77620_TWD_16s 0x1 @@ -47,15 +47,15 @@ #define MAX77620_TWD_128s 0x3 #define MAX77620_REG_CNFG1_32K 0x03 -#define MAX77620_CNFG1_32K_OUT0_EN (1 << 2) +#define MAX77620_CNFG1_32K_OUT0_EN BIT(2) #define MAX77620_REG_CNFGBBC 0x04 -#define MAX77620_CNFGBBC_ENABLE (1 << 0) +#define MAX77620_CNFGBBC_ENABLE BIT(0) #define MAX77620_CNFGBBC_CURRENT_MASK 0x06 #define MAX77620_CNFGBBC_CURRENT_SHIFT 1 #define MAX77620_CNFGBBC_VOLTAGE_MASK 0x18 #define MAX77620_CNFGBBC_VOLTAGE_SHIFT 3 -#define MAX77620_CNFGBBC_LOW_CURRENT_DISABLE (1 << 5) +#define MAX77620_CNFGBBC_LOW_CURRENT_DISABLE BIT(5) #define MAX77620_CNFGBBC_RESISTOR_MASK 0xC0 #define MAX77620_CNFGBBC_RESISTOR_SHIFT 6 #define MAX77620_CNFGBBC_RESISTOR_100 (0 << MAX77620_CNFGBBC_RESISTOR_SHIFT) @@ -64,19 +64,19 @@ #define MAX77620_CNFGBBC_RESISTOR_6K (3 << MAX77620_CNFGBBC_RESISTOR_SHIFT) #define MAX77620_REG_IRQTOP 0x05 -#define MAX77620_IRQ_TOP_GLBL_MASK (1 << 7) -#define MAX77620_IRQ_TOP_SD_MASK (1 << 6) -#define MAX77620_IRQ_TOP_LDO_MASK (1 << 5) -#define MAX77620_IRQ_TOP_GPIO_MASK (1 << 4) -#define MAX77620_IRQ_TOP_RTC_MASK (1 << 3) -#define MAX77620_IRQ_TOP_32K_MASK (1 << 2) -#define MAX77620_IRQ_TOP_ONOFF_MASK (1 << 1) +#define MAX77620_IRQ_TOP_ONOFF_MASK BIT(1) +#define MAX77620_IRQ_TOP_32K_MASK BIT(2) +#define MAX77620_IRQ_TOP_RTC_MASK BIT(3) +#define MAX77620_IRQ_TOP_GPIO_MASK BIT(4) +#define MAX77620_IRQ_TOP_LDO_MASK BIT(5) +#define MAX77620_IRQ_TOP_SD_MASK BIT(6) +#define MAX77620_IRQ_TOP_GLBL_MASK BIT(7) #define MAX77620_REG_INTLBT 0x06 #define MAX77620_REG_IRQTOPM 0x0D -#define MAX77620_IRQ_LBM_MASK (1 << 3) -#define MAX77620_IRQ_TJALRM1_MASK (1 << 2) -#define MAX77620_IRQ_TJALRM2_MASK (1 << 1) +#define MAX77620_IRQ_TJALRM2_MASK BIT(1) +#define MAX77620_IRQ_TJALRM1_MASK BIT(2) +#define MAX77620_IRQ_LBM_MASK BIT(3) #define MAX77620_REG_IRQSD 0x07 #define MAX77620_REG_IRQ_LVL2_L0_7 0x08 @@ -86,7 +86,7 @@ #define MAX77620_REG_NVERC 0x0C #define MAX77620_REG_INTENLBT 0x0E -#define MAX77620_GLBLM_MASK (1 << 0) +#define MAX77620_GLBLM_MASK BIT(0) #define MAX77620_REG_IRQMASKSD 0x0F #define MAX77620_REG_IRQ_MSK_L0_7 0x10 @@ -108,11 +108,11 @@ #define MAX77620_LDO_VOLT_MASK 0x3F #define MAX77620_REG_DVSSD0 0x1B #define MAX77620_REG_DVSSD1 0x1C -#define MAX77620_REG_SD0_CFG 0x1D -#define MAX77620_REG_SD1_CFG 0x1E -#define MAX77620_REG_SD2_CFG 0x1F -#define MAX77620_REG_SD3_CFG 0x20 -#define MAX77620_REG_SD4_CFG 0x21 +#define MAX77620_REG_SD0_CFG 0x1D // SD CNFG1. +#define MAX77620_REG_SD1_CFG 0x1E // SD CNFG1. +#define MAX77620_REG_SD2_CFG 0x1F // SD CNFG1. +#define MAX77620_REG_SD3_CFG 0x20 // SD CNFG1. +#define MAX77620_REG_SD4_CFG 0x21 // SD CNFG1. #define MAX77620_REG_SD_CFG2 0x22 #define MAX77620_REG_LDO0_CFG 0x23 #define MAX77620_REG_LDO0_CFG2 0x24 @@ -132,23 +132,23 @@ #define MAX77620_REG_LDO7_CFG2 0x32 #define MAX77620_REG_LDO8_CFG 0x33 #define MAX77620_REG_LDO8_CFG2 0x34 +#define MAX77620_LDO_CFG2_SS_MASK (1 << 0) +#define MAX77620_LDO_CFG2_SS_FAST (1 << 0) +#define MAX77620_LDO_CFG2_SS_SLOW 0 +#define MAX77620_LDO_CFG2_ADE_MASK (1 << 1) +#define MAX77620_LDO_CFG2_ADE_DISABLE (0 << 1) +#define MAX77620_LDO_CFG2_ADE_ENABLE (1 << 1) +#define MAX20024_LDO_CFG2_MPOK_MASK BIT(2) #define MAX77620_LDO_POWER_MODE_MASK 0xC0 #define MAX77620_LDO_POWER_MODE_SHIFT 6 #define MAX77620_POWER_MODE_NORMAL 3 #define MAX77620_POWER_MODE_LPM 2 #define MAX77620_POWER_MODE_GLPM 1 #define MAX77620_POWER_MODE_DISABLE 0 -#define MAX20024_LDO_CFG2_MPOK_MASK (1 << 2) -#define MAX77620_LDO_CFG2_ADE_MASK (1 << 1) -#define MAX77620_LDO_CFG2_ADE_DISABLE (0 << 1) -#define MAX77620_LDO_CFG2_ADE_ENABLE (1 << 1) -#define MAX77620_LDO_CFG2_SS_MASK (1 << 0) -#define MAX77620_LDO_CFG2_SS_FAST (1 << 0) -#define MAX77620_LDO_CFG2_SS_SLOW 0 #define MAX77620_REG_LDO_CFG3 0x35 -#define MAX77620_TRACK4_MASK (1 << 5) #define MAX77620_TRACK4_SHIFT 5 +#define MAX77620_TRACK4_MASK (1 << MAX77620_TRACK4_SHIFT) #define MAX77620_LDO_SLEW_RATE_MASK 0x1 @@ -183,19 +183,19 @@ #define MAX77620_CNFG_GPIO_DBNC_32ms (0x3 << 6) #define MAX77620_REG_ONOFFCNFG1 0x41 -#define MAX77620_ONOFFCNFG1_SFT_RST (1 << 7) -#define MAX77620_ONOFFCNFG1_MRT_MASK 0x38 -#define MAX77620_ONOFFCNFG1_MRT_SHIFT 0x3 -#define MAX77620_ONOFFCNFG1_SLPEN (1 << 2) -#define MAX77620_ONOFFCNFG1_PWR_OFF (1 << 1) #define MAX20024_ONOFFCNFG1_CLRSE 0x18 +#define MAX77620_ONOFFCNFG1_PWR_OFF BIT(1) +#define MAX77620_ONOFFCNFG1_SLPEN BIT(2) +#define MAX77620_ONOFFCNFG1_MRT_SHIFT 0x3 +#define MAX77620_ONOFFCNFG1_MRT_MASK 0x38 +#define MAX77620_ONOFFCNFG1_SFT_RST BIT(7) #define MAX77620_REG_ONOFFCNFG2 0x42 -#define MAX77620_ONOFFCNFG2_SFT_RST_WK (1 << 7) -#define MAX77620_ONOFFCNFG2_WD_RST_WK (1 << 6) -#define MAX77620_ONOFFCNFG2_SLP_LPM_MSK (1 << 5) -#define MAX77620_ONOFFCNFG2_WK_ALARM1 (1 << 2) -#define MAX77620_ONOFFCNFG2_WK_EN0 (1 << 0) +#define MAX77620_ONOFFCNFG2_WK_EN0 BIT(0) +#define MAX77620_ONOFFCNFG2_WK_ALARM1 BIT(2) +#define MAX77620_ONOFFCNFG2_SLP_LPM_MSK BIT(5) +#define MAX77620_ONOFFCNFG2_WD_RST_WK BIT(6) +#define MAX77620_ONOFFCNFG2_SFT_RST_WK BIT(7) /* FPS Registers */ #define MAX77620_REG_FPS_CFG0 0x43 @@ -259,8 +259,8 @@ #define MAX77620_CID_DIDM_SHIFT 4 /* CNCG2SD */ -#define MAX77620_SD_CNF2_ROVS_EN_SD1 (1 << 1) -#define MAX77620_SD_CNF2_ROVS_EN_SD0 (1 << 2) +#define MAX77620_SD_CNF2_ROVS_EN_SD1 BIT(1) +#define MAX77620_SD_CNF2_ROVS_EN_SD0 BIT(2) /* Device Identification Metal */ #define MAX77620_CID5_DIDM(n) (((n) >> 4) & 0xF) @@ -272,29 +272,29 @@ #define MAX77620_SD_SR_SHIFT 6 #define MAX77620_SD_POWER_MODE_MASK 0x30 #define MAX77620_SD_POWER_MODE_SHIFT 4 -#define MAX77620_SD_CFG1_ADE_MASK (1 << 3) +#define MAX77620_SD_CFG1_ADE_MASK BIT(3) #define MAX77620_SD_CFG1_ADE_DISABLE 0 -#define MAX77620_SD_CFG1_ADE_ENABLE (1 << 3) +#define MAX77620_SD_CFG1_ADE_ENABLE BIT(3) #define MAX77620_SD_FPWM_MASK 0x04 #define MAX77620_SD_FPWM_SHIFT 2 #define MAX77620_SD_FSRADE_MASK 0x01 #define MAX77620_SD_FSRADE_SHIFT 0 -#define MAX77620_SD_CFG1_FPWM_SD_MASK (1 << 2) +#define MAX77620_SD_CFG1_FPWM_SD_MASK BIT(2) #define MAX77620_SD_CFG1_FPWM_SD_SKIP 0 -#define MAX77620_SD_CFG1_FPWM_SD_FPWM (1 << 2) -#define MAX20024_SD_CFG1_MPOK_MASK (1 << 1) -#define MAX77620_SD_CFG1_FSRADE_SD_MASK (1 << 0) +#define MAX77620_SD_CFG1_FPWM_SD_FPWM BIT(2) +#define MAX20024_SD_CFG1_MPOK_MASK BIT(1) +#define MAX77620_SD_CFG1_FSRADE_SD_MASK BIT(0) #define MAX77620_SD_CFG1_FSRADE_SD_DISABLE 0 -#define MAX77620_SD_CFG1_FSRADE_SD_ENABLE (1 << 0) +#define MAX77620_SD_CFG1_FSRADE_SD_ENABLE BIT(0) -#define MAX77620_IRQ_LVL2_GPIO_EDGE0 (1 << 0) -#define MAX77620_IRQ_LVL2_GPIO_EDGE1 (1 << 1) -#define MAX77620_IRQ_LVL2_GPIO_EDGE2 (1 << 2) -#define MAX77620_IRQ_LVL2_GPIO_EDGE3 (1 << 3) -#define MAX77620_IRQ_LVL2_GPIO_EDGE4 (1 << 4) -#define MAX77620_IRQ_LVL2_GPIO_EDGE5 (1 << 5) -#define MAX77620_IRQ_LVL2_GPIO_EDGE6 (1 << 6) -#define MAX77620_IRQ_LVL2_GPIO_EDGE7 (1 << 7) +#define MAX77620_IRQ_LVL2_GPIO_EDGE0 BIT(0) +#define MAX77620_IRQ_LVL2_GPIO_EDGE1 BIT(1) +#define MAX77620_IRQ_LVL2_GPIO_EDGE2 BIT(2) +#define MAX77620_IRQ_LVL2_GPIO_EDGE3 BIT(3) +#define MAX77620_IRQ_LVL2_GPIO_EDGE4 BIT(4) +#define MAX77620_IRQ_LVL2_GPIO_EDGE5 BIT(5) +#define MAX77620_IRQ_LVL2_GPIO_EDGE6 BIT(6) +#define MAX77620_IRQ_LVL2_GPIO_EDGE7 BIT(7) /* Interrupts */ enum { diff --git a/bdk/power/max7762x.c b/bdk/power/max7762x.c index 425ce1f..c32cf76 100644 --- a/bdk/power/max7762x.c +++ b/bdk/power/max7762x.c @@ -61,17 +61,19 @@ static const max77620_regulator_t _pmic_regulators[] = { { REGULATOR_LDO, "ldo5", 0x00, 50000, 800000, 1800000, 1800000, MAX77620_REG_LDO5_CFG, MAX77620_REG_LDO5_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO5, 3, 7, 0 }, { REGULATOR_LDO, "ldo6", 0x00, 50000, 800000, 2900000, 2900000, MAX77620_REG_LDO6_CFG, MAX77620_REG_LDO6_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO6, 3, 7, 0 }, { REGULATOR_LDO, "ldo7", 0x00, 50000, 800000, 1050000, 1050000, MAX77620_REG_LDO7_CFG, MAX77620_REG_LDO7_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO7, 1, 4, 3 }, - { REGULATOR_LDO, "ldo8", 0x00, 50000, 800000, 1050000, 1050000, MAX77620_REG_LDO8_CFG, MAX77620_REG_LDO8_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO8, 3, 7, 0 } + { REGULATOR_LDO, "ldo8", 0x00, 50000, 800000, 1050000, 2800000, MAX77620_REG_LDO8_CFG, MAX77620_REG_LDO8_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO8, 3, 7, 0 } }; -static void _max77620_try_set_reg(u8 reg, u8 val) +static void _max77620_set_reg(u8 reg, u8 val) { - u8 tmp; - do + u32 retries = 100; + while (retries) { - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, reg, val); - tmp = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, reg); - } while (val != tmp); + if (i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, reg, val)) + break; + usleep(100); + retries--; + } } int max77620_regulator_get_status(u32 id) @@ -93,7 +95,7 @@ int max77620_regulator_config_fps(u32 id) const max77620_regulator_t *reg = &_pmic_regulators[id]; - _max77620_try_set_reg(reg->fps_addr, + _max77620_set_reg(reg->fps_addr, (reg->fps_src << MAX77620_FPS_SRC_SHIFT) | (reg->pu_period << MAX77620_FPS_PU_PERIOD_SHIFT) | (reg->pd_period)); return 1; @@ -112,7 +114,7 @@ int max77620_regulator_set_voltage(u32 id, u32 mv) u32 mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step; u8 val = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, reg->volt_addr); val = (val & ~reg->volt_mask) | (mult & reg->volt_mask); - _max77620_try_set_reg(reg->volt_addr, val); + _max77620_set_reg(reg->volt_addr, val); usleep(1000); return 1; @@ -131,7 +133,7 @@ int max77620_regulator_enable(u32 id, int enable) val = (val & ~reg->enable_mask) | ((MAX77620_POWER_MODE_NORMAL << reg->enable_shift) & reg->enable_mask); else val &= ~reg->enable_mask; - _max77620_try_set_reg(addr, val); + _max77620_set_reg(addr, val); usleep(1000); return 1; @@ -150,7 +152,7 @@ int max77620_regulator_set_volt_and_flags(u32 id, u32 mv, u8 flags) u32 mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step; u8 val = ((flags << reg->enable_shift) & ~reg->volt_mask) | (mult & reg->volt_mask); - _max77620_try_set_reg(reg->volt_addr, val); + _max77620_set_reg(reg->volt_addr, val); usleep(1000); return 1; @@ -166,12 +168,12 @@ void max77620_config_default() if (_pmic_regulators[i].fps_src != MAX77620_FPS_SRC_NONE) max77620_regulator_enable(i, 1); } - _max77620_try_set_reg(MAX77620_REG_SD_CFG2, 4); + _max77620_set_reg(MAX77620_REG_SD_CFG2, 4); } void max77620_low_battery_monitor_config(bool enable) { - _max77620_try_set_reg(MAX77620_REG_CNFGGLBL1, + _max77620_set_reg(MAX77620_REG_CNFGGLBL1, MAX77620_CNFGGLBL1_LBDAC_EN | (enable ? MAX77620_CNFGGLBL1_MPPLD : 0) | MAX77620_CNFGGLBL1_LBHYST_200 | MAX77620_CNFGGLBL1_LBDAC_2800); } diff --git a/bdk/power/max7762x.h b/bdk/power/max7762x.h index f60c3b2..dd06bf7 100644 --- a/bdk/power/max7762x.h +++ b/bdk/power/max7762x.h @@ -69,7 +69,7 @@ #define MAX77621_CONTROL2_REG 3 /* MAX77621_VOUT */ -#define MAX77621_VOUT_ENABLE (1 << 7) +#define MAX77621_VOUT_ENABLE BIT(7) #define MAX77621_VOUT_MASK 0x7F #define MAX77621_VOUT_0_95V 0x37 #define MAX77621_VOUT_1_09V 0x4F @@ -78,12 +78,12 @@ #define MAX77621_DVS_VOUT_MASK 0x7F /* MAX77621_CONTROL1 */ -#define MAX77621_SNS_ENABLE (1 << 7) -#define MAX77621_FPWM_EN_M (1 << 6) -#define MAX77621_NFSR_ENABLE (1 << 5) -#define MAX77621_AD_ENABLE (1 << 4) -#define MAX77621_BIAS_ENABLE (1 << 3) -#define MAX77621_FREQSHIFT_9PER (1 << 2) +#define MAX77621_FREQSHIFT_9PER BIT(2) +#define MAX77621_BIAS_ENABLE BIT(3) +#define MAX77621_AD_ENABLE BIT(4) +#define MAX77621_NFSR_ENABLE BIT(5) +#define MAX77621_FPWM_EN_M BIT(6) +#define MAX77621_SNS_ENABLE BIT(7) #define MAX77621_RAMP_12mV_PER_US 0x0 #define MAX77621_RAMP_25mV_PER_US 0x1 @@ -92,10 +92,10 @@ #define MAX77621_RAMP_MASK 0x3 /* MAX77621_CONTROL2 */ -#define MAX77621_WDTMR_ENABLE (1 << 6) -#define MAX77621_DISCH_ENBABLE (1 << 5) -#define MAX77621_FT_ENABLE (1 << 4) -#define MAX77621_T_JUNCTION_120 (1 << 7) +#define MAX77621_FT_ENABLE BIT(4) +#define MAX77621_DISCH_ENBABLE BIT(5) +#define MAX77621_WDTMR_ENABLE BIT(6) +#define MAX77621_T_JUNCTION_120 BIT(7) #define MAX77621_CKKADV_TRIP_DISABLE 0xC #define MAX77621_CKKADV_TRIP_75mV_PER_US 0x0 diff --git a/bdk/power/max77812.h b/bdk/power/max77812.h new file mode 100644 index 0000000..f8ac3fb --- /dev/null +++ b/bdk/power/max77812.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2020 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 _MAX77812_H_ +#define _MAX77812_H_ + +#define MAX77812_PHASE31_CPU_I2C_ADDR 0x31 +#define MAX77812_PHASE211_CPU_I2C_ADDR 0x33 + +#define MAX77812_REG_RSET 0x00 +#define MAX77812_REG_INT_SRC 0x01 +#define MAX77812_REG_INT_SRC_M 0x02 +#define MAX77812_REG_TOPSYS_INT 0x03 +#define MAX77812_REG_TOPSYS_INT_M 0x04 +#define MAX77812_REG_TOPSYS_STAT 0x05 +#define MAX77812_REG_EN_CTRL 0x06 +#define MAX77812_EN_CTRL_EN_M4 BIT(6) +#define MAX77812_REG_STUP_DLY2 0x07 +#define MAX77812_REG_STUP_DLY3 0x08 +#define MAX77812_REG_STUP_DLY4 0x09 +#define MAX77812_REG_SHDN_DLY1 0x0A +#define MAX77812_REG_SHDN_DLY2 0x0B +#define MAX77812_REG_SHDN_DLY3 0x0C +#define MAX77812_REG_SHDN_DLY4 0x0D +#define MAX77812_REG_WDTRSTB_DEB 0x0E +#define MAX77812_REG_GPI_FUNC 0x0F +#define MAX77812_REG_GPI_DEB1 0x10 +#define MAX77812_REG_GPI_DEB2 0x11 +#define MAX77812_REG_GPI_PD_CTRL 0x12 +#define MAX77812_REG_PROT_CFG 0x13 +#define MAX77812_REG_VERSION 0x14 +#define MAX77812_REG_I2C_CFG 0x15 +#define MAX77812_REG_BUCK_INT 0x20 +#define MAX77812_REG_BUCK_INT_M 0x21 +#define MAX77812_REG_BUCK_STAT 0x22 +#define MAX77812_REG_M1_VOUT 0x23 +#define MAX77812_REG_M2_VOUT 0x24 +#define MAX77812_REG_M3_VOUT 0x25 +#define MAX77812_REG_M4_VOUT 0x26 +#define MAX77812_M4_VOUT_0_80V 0x6E +#define MAX77812_REG_M1_VOUT_D 0x27 +#define MAX77812_REG_M2_VOUT_D 0x28 +#define MAX77812_REG_M3_VOUT_D 0x29 +#define MAX77812_REG_M4_VOUT_D 0x2A +#define MAX77812_REG_M1_VOUT_S 0x2B +#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_GLB_CFG3 0x35 +#define MAX77812_REG_GLB_CFG4 0x36 +#define MAX77812_REG_GLB_CFG5 0x37 +#define MAX77812_REG_GLB_CFG6 0x38 +#define MAX77812_REG_GLB_CFG7 0x39 +#define MAX77812_REG_GLB_CFG8 0x3A +#define MAX77812_REG_PROT_ACCESS 0xFD +#define MAX77812_REG_MAX 0xFE + +#define MAX77812_REG_EN_CTRL_MASK(n) BIT(n) +#define MAX77812_START_SLEW_RATE_MASK 0x07 +#define MAX77812_SHDN_SLEW_RATE_MASK 0x70 +#define MAX77812_RAMPUP_SLEW_RATE_MASK 0x07 +#define MAX77812_RAMPDOWN_SLEW_RATE_MASK 0x70 +#define MAX77812_SLEW_RATE_SHIFT 4 + +#define MAX77812_OP_ACTIVE_DISCHARGE_MASK BIT(7) +#define MAX77812_PEAK_CURRENT_LMT_MASK 0x70 +#define MAX77812_SWITCH_FREQ_MASK 0x0C +#define MAX77812_FORCED_PWM_MASK BIT(1) +#define MAX77812_SLEW_RATE_CNTRL_MASK BIT(0) +#define MAX77812_START_SHD_DELAY_MASK 0x1F +#define MAX77812_VERSION_MASK 0x07 +#define MAX77812_ES2_VERSION 0x04 +#define MAX77812_QS_VERSION 0x05 + +#define MAX77812_VOUT_MASK 0xFF +#define MAX77812_VOUT_N_VOLTAGE 0xFF +#define MAX77812_VOUT_VMIN 250000 +#define MAX77812_VOUT_VMAX 1525000 +#define MAX77812_VOUT_STEP 5000 + +#endif diff --git a/bdk/power/regulator_5v.h b/bdk/power/regulator_5v.h index e916fbd..6bb837a 100644 --- a/bdk/power/regulator_5v.h +++ b/bdk/power/regulator_5v.h @@ -21,9 +21,9 @@ enum { - REGULATOR_5V_FAN = (1 << 0), - REGULATOR_5V_JC_R = (1 << 1), - REGULATOR_5V_JC_L = (1 << 2), + REGULATOR_5V_FAN = BIT(0), + REGULATOR_5V_JC_R = BIT(1), + REGULATOR_5V_JC_L = BIT(2), REGULATOR_5V_ALL = 0xFF }; diff --git a/bdk/rtc/max77620-rtc.h b/bdk/rtc/max77620-rtc.h index d9e216a..93b24c4 100644 --- a/bdk/rtc/max77620-rtc.h +++ b/bdk/rtc/max77620-rtc.h @@ -27,17 +27,17 @@ #define MAX77620_RTC_CONTROLM_REG 0x02 #define MAX77620_RTC_CONTROL_REG 0x03 -#define MAX77620_RTC_BIN_FORMAT (1 << 0) -#define MAX77620_RTC_24H (1 << 1) +#define MAX77620_RTC_BIN_FORMAT BIT(0) +#define MAX77620_RTC_24H BIT(1) #define MAX77620_RTC_UPDATE0_REG 0x04 -#define MAX77620_RTC_WRITE_UPDATE (1 << 0) -#define MAX77620_RTC_READ_UPDATE (1 << 4) +#define MAX77620_RTC_WRITE_UPDATE BIT(0) +#define MAX77620_RTC_READ_UPDATE BIT(4) #define MAX77620_RTC_SEC_REG 0x07 #define MAX77620_RTC_MIN_REG 0x08 #define MAX77620_RTC_HOUR_REG 0x09 -#define MAX77620_RTC_HOUR_PM_MASK (1 << 6) +#define MAX77620_RTC_HOUR_PM_MASK BIT(6) #define MAX77620_RTC_WEEKDAY_REG 0x0A #define MAX77620_RTC_MONTH_REG 0x0B #define MAX77620_RTC_YEAR_REG 0x0C @@ -57,7 +57,7 @@ #define MAX77620_ALARM2_MONTH_REG 0x19 #define MAX77620_ALARM2_YEAR_REG 0x1A #define MAX77620_ALARM2_DATE_REG 0x1B -#define MAX77620_RTC_ALARM_EN_MASK (1 << 7) +#define MAX77620_RTC_ALARM_EN_MASK BIT(7) typedef struct _rtc_time_t { u8 weekday; diff --git a/bdk/sec/se.c b/bdk/sec/se.c index 7be46c9..2f76985 100644 --- a/bdk/sec/se.c +++ b/bdk/sec/se.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -93,22 +94,21 @@ static int _se_wait() return 1; } -static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size) +se_ll_t *ll_dst, *ll_src; +static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size, bool is_oneshot) { - static se_ll_t *ll_dst = NULL, *ll_src = NULL; - if (!ll_dst) - { - ll_dst = (se_ll_t *)malloc(sizeof(se_ll_t)); - ll_src = (se_ll_t *)malloc(sizeof(se_ll_t)); - } + 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); } @@ -120,13 +120,49 @@ static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); SE(SE_OPERATION_REG_OFFSET) = SE_OPERATION(op); + + if (is_oneshot) + { + int res = _se_wait(); + + bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); + + if (src) + free(ll_src); + if (dst) + free(ll_dst); + + return res; + } + + return 1; +} + +static int _se_execute_finalize() +{ int res = _se_wait(); bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); + if (ll_src) + { + free(ll_src); + ll_src = NULL; + } + if (ll_dst) + { + free(ll_dst); + ll_dst = NULL; + } + return res; } +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); +} + static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size) { if (!src || !dst) @@ -138,7 +174,7 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; memcpy(block, src, src_size); - int res = _se_execute(op, block, 0x10, block, 0x10); + int res = _se_execute_oneshot(op, block, 0x10, block, 0x10); memcpy(dst, block, dst_size); free(block); @@ -147,9 +183,11 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr static void _se_aes_ctr_set(void *ctr) { - u32 *data = (u32 *)ctr; - for (u32 i = 0; i < 4; i++) - SE(SE_CRYPTO_CTR_REG_OFFSET + 4 * i) = data[i]; + u32 data[TEGRA_SE_AES_BLOCK_SIZE / 4]; + memcpy(data, ctr, TEGRA_SE_AES_BLOCK_SIZE); + + for (u32 i = 0; i < (TEGRA_SE_AES_BLOCK_SIZE / 4); i++) + SE(SE_CRYPTO_CTR_REG_OFFSET + (4 * i)) = data[i]; } void se_rsa_acc_ctrl(u32 rs, u32 flags) @@ -159,7 +197,7 @@ void se_rsa_acc_ctrl(u32 rs, u32 flags) ((flags >> SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG_SHIFT) & SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG) | ((flags & SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG) ^ SE_RSA_KEY_TBL_DIS_KEY_ALL_COMMON_FLAG); if (flags & SE_RSA_KEY_TBL_DIS_KEY_LOCK_FLAG) - SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) &= ~(1 << rs); + SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) &= ~BIT(rs); } // se_rsa_key_set() was derived from Atmosphère's set_rsa_keyslot @@ -212,7 +250,7 @@ int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_siz SE(SE_RSA_KEY_SIZE_REG_OFFSET) = (_se_rsa_mod_sizes[ks] >> 6) - 1; SE(SE_RSA_EXP_SIZE_REG_OFFSET) = _se_rsa_exp_sizes[ks] >> 2; - res = _se_execute(OP_START, NULL, 0, stack_buf, src_size); + res = _se_execute_oneshot(OP_START, NULL, 0, stack_buf, src_size); // Copy output hash. u32 *dst32 = (u32 *)dst; @@ -227,7 +265,7 @@ void se_key_acc_ctrl(u32 ks, u32 flags) if (flags & SE_KEY_TBL_DIS_KEY_ACCESS_FLAG) SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 4 * ks) = ~flags; if (flags & SE_KEY_TBL_DIS_KEY_LOCK_FLAG) - SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) &= ~(1 << ks); + SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) &= ~BIT(ks); } u32 se_key_acc_ctrl_get(u32 ks) @@ -237,48 +275,61 @@ u32 se_key_acc_ctrl_get(u32 ks) void se_aes_key_set(u32 ks, const void *key, u32 size) { - u32 *data = (u32 *)key; - for (u32 i = 0; i < size / 4; i++) + u32 data[TEGRA_SE_AES_MAX_KEY_SIZE / 4]; + memcpy(data, key, size); + + for (u32 i = 0; i < (size / 4); i++) { SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i; SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data[i]; } } -void se_aes_iv_set(u32 ks, const void *iv, u32 size) +void se_aes_key_partial_set(u32 ks, u32 index, u32 data) { - u32 *data = (u32 *)iv; - for (u32 i = 0; i < size / 4; i++) + SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | index; + SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data; +} + +void se_aes_iv_set(u32 ks, const void *iv) +{ + u32 data[TEGRA_SE_AES_BLOCK_SIZE / 4]; + memcpy(data, iv, TEGRA_SE_AES_BLOCK_SIZE); + + for (u32 i = 0; i < (TEGRA_SE_AES_BLOCK_SIZE / 4); i++) { - SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | 8 | i; + SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(QUAD_ORG_IV) | i; SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data[i]; } } -void se_aes_key_read(u32 ks, void *key, u32 size) +void se_aes_key_get(u32 ks, void *key, u32 size) { - u32 *data = (u32 *)key; - for (u32 i = 0; i < size / 4; i++) + u32 data[TEGRA_SE_AES_MAX_KEY_SIZE / 4]; + + for (u32 i = 0; i < (size / 4); i++) { SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i; data[i] = SE(SE_KEYTABLE_DATA0_REG_OFFSET); } + + memcpy(key, data, size); } void se_aes_key_clear(u32 ks) { - for (u32 i = 0; i < TEGRA_SE_AES_MAX_KEY_SIZE / 4; i++) + for (u32 i = 0; i < (TEGRA_SE_AES_MAX_KEY_SIZE / 4); i++) { SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i; SE(SE_KEYTABLE_DATA0_REG_OFFSET) = 0; } } -void se_aes_key_iv_clear(u32 ks) +void se_aes_iv_clear(u32 ks) { - for (u32 i = 0; i < TEGRA_SE_AES_MAX_KEY_SIZE / 4; i++) + for (u32 i = 0; i < (TEGRA_SE_AES_BLOCK_SIZE / 4); i++) { - SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | 8 | i; + SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(QUAD_ORG_IV) | i; SE(SE_KEYTABLE_DATA0_REG_OFFSET) = 0; } } @@ -290,7 +341,7 @@ int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input) SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst); - return _se_execute(OP_START, NULL, 0, input, 0x10); + return _se_execute_oneshot(OP_START, NULL, 0, input, 0x10); } int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size) @@ -306,7 +357,25 @@ int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT); } SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1; - return _se_execute(OP_START, dst, dst_size, src, src_size); + return _se_execute_oneshot(OP_START, dst, dst_size, src, src_size); +} + +int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size) +{ + if (enc) + { + SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); + SE(SE_CRYPTO_REG_OFFSET) = 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_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY); + SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVAHB) | + SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM); + } + SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1; + return _se_execute_oneshot(OP_START, dst, dst_size, src, src_size); } int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src) @@ -319,8 +388,7 @@ int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_s SE(SE_SPARE_0_REG_OFFSET) = 1; SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); SE(SE_CRYPTO_REG_OFFSET) = 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_VAL(1) | - SE_CRYPTO_VCTRAM_SEL(VCTRAM_AHB); + SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_LNR_CTR) | SE_CRYPTO_CTR_VAL(1); _se_aes_ctr_set(ctr); u32 src_size_aligned = src_size & 0xFFFFFFF0; @@ -329,7 +397,7 @@ int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_s if (src_size_aligned) { SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1; - if (!_se_execute(OP_START, dst, dst_size, src, src_size_aligned)) + if (!_se_execute_oneshot(OP_START, dst, dst_size, src, src_size_aligned)) return 0; } @@ -359,7 +427,7 @@ int se_initialize_rng() SE_RNG_SRC_CONFIG_ENT_SRC_LOCK(RNG_SRC_RO_ENT_LOCK_ENABLE); SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; - int res =_se_execute(OP_START, output_buf, 0x10, NULL, 0); + int res =_se_execute_oneshot(OP_START, output_buf, 0x10, NULL, 0); free(output_buf); if (res) @@ -378,7 +446,7 @@ int se_generate_random(void *dst, u32 size) if (num_blocks) { SE(SE_BLOCK_COUNT_REG_OFFSET) = num_blocks - 1; - if (!_se_execute(OP_START, dst, aligned_size, NULL, 0)) + if (!_se_execute_oneshot(OP_START, dst, aligned_size, NULL, 0)) return 0; } if (size > aligned_size) @@ -394,35 +462,15 @@ int se_generate_random_key(u32 ks_dst, u32 ks_src) SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_MODE(RNG_MODE_NORMAL) | SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY); SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst); - if (!_se_execute(OP_START, NULL, 0, NULL, 0)) + if (!_se_execute_oneshot(OP_START, NULL, 0, NULL, 0)) return 0; SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst) | 1; - if (!_se_execute(OP_START, NULL, 0, NULL, 0)) + if (!_se_execute_oneshot(OP_START, NULL, 0, NULL, 0)) return 0; return 1; } -int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size) -{ - if (enc) - { - SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); - SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) | - SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_XOR_POS(XOR_TOP) | SE_CRYPTO_INPUT_SEL(INPUT_AHB) | - SE_CRYPTO_IV_SEL(IV_ORIGINAL); - } - else - { - SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY); - SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVAHB) | - SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_AHB) | - SE_CRYPTO_IV_SEL(IV_ORIGINAL); - } - SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1; - return _se_execute(OP_START, dst, dst_size, src, src_size); -} - int se_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, const void *src, u32 sec_size) { u8 tweak[0x10]; @@ -500,13 +548,13 @@ int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size) SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_INPUT_SEL(INPUT_AHB) | SE_CRYPTO_XOR_POS(XOR_TOP) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) | SE_CRYPTO_HASH(HASH_ENABLE) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT); - se_aes_key_iv_clear(ks); + se_aes_iv_clear(ks); u32 num_blocks = (src_size + 0xf) >> 4; if (num_blocks > 1) { SE(SE_BLOCK_COUNT_REG_OFFSET) = num_blocks - 2; - if (!_se_execute(OP_START, NULL, 0, src, src_size)) + if (!_se_execute_oneshot(OP_START, NULL, 0, src, src_size)) goto out; SE(SE_CRYPTO_REG_OFFSET) |= SE_CRYPTO_IV_SEL(IV_UPDATED); } @@ -525,7 +573,7 @@ int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size) last_block[i] ^= key[i]; SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; - res = _se_execute(OP_START, NULL, 0, last_block, 0x10); + res = _se_execute_oneshot(OP_START, NULL, 0, last_block, 0x10); u32 *dst32 = (u32 *)dst; for (u32 i = 0; i < (dst_size >> 2); i++) @@ -537,29 +585,91 @@ out:; return res; } -// se_calc_sha256() was derived from Atmosphère's se_calculate_sha256. -int se_calc_sha256(void *dst, const void *src, u32 src_size) +int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot) { int res; - // Setup config for SHA256, size = BITS(src_size). + u32 hash32[TEGRA_SE_SHA_256_SIZE / 4]; + + //! TODO: src_size must be 512 bit aligned if continuing and not last block for SHA256. + if (src_size > 0xFFFFFF || !hash) // Max 16MB - 1 chunks and aligned x4 hash buffer. + return 0; + + // Setup config for SHA256. SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_SHA256) | SE_CONFIG_ENC_ALG(ALG_SHA) | SE_CONFIG_DST(DST_HASHREG); - SE(SE_SHA_CONFIG_REG_OFFSET) = SHA_INIT_HASH; - SE(SE_SHA_MSG_LENGTH_0_REG_OFFSET) = (u32)(src_size << 3); - SE(SE_SHA_MSG_LENGTH_1_REG_OFFSET) = 0; + SE(SE_SHA_CONFIG_REG_OFFSET) = sha_cfg; + SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; + + // Set total size to current buffer size if empty. + if (!total_size) + total_size = src_size; + + // Set total size: BITS(src_size), up to 2 EB. + SE(SE_SHA_MSG_LENGTH_0_REG_OFFSET) = (u32)(total_size << 3); + SE(SE_SHA_MSG_LENGTH_1_REG_OFFSET) = (u32)(total_size >> 29); SE(SE_SHA_MSG_LENGTH_2_REG_OFFSET) = 0; SE(SE_SHA_MSG_LENGTH_3_REG_OFFSET) = 0; - SE(SE_SHA_MSG_LEFT_0_REG_OFFSET) = (u32)(src_size << 3); - SE(SE_SHA_MSG_LEFT_1_REG_OFFSET) = 0; + + // Set size left to hash. + SE(SE_SHA_MSG_LEFT_0_REG_OFFSET) = (u32)(total_size << 3); + SE(SE_SHA_MSG_LEFT_1_REG_OFFSET) = (u32)(total_size >> 29); SE(SE_SHA_MSG_LEFT_2_REG_OFFSET) = 0; SE(SE_SHA_MSG_LEFT_3_REG_OFFSET) = 0; + // If we hash in chunks, copy over the intermediate. + if (sha_cfg == SHA_CONTINUE && msg_left) + { + // Restore message left to process. + SE(SE_SHA_MSG_LEFT_0_REG_OFFSET) = msg_left[0]; + SE(SE_SHA_MSG_LEFT_1_REG_OFFSET) = msg_left[1]; + + // Restore hash reg. + memcpy(hash32, hash, TEGRA_SE_SHA_256_SIZE); + for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++) + SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)) = byte_swap_32(hash32[i]); + } + // Trigger the operation. - res = _se_execute(OP_START, NULL, 0, src, src_size); + res = _se_execute(OP_START, NULL, 0, src, src_size, is_oneshot); + + if (is_oneshot) + { + // Backup message left. + if (msg_left) + { + msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG_OFFSET); + msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG_OFFSET); + } + + // Copy output hash. + for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++) + hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG_OFFSET + (i << 2))); + memcpy(hash, hash32, TEGRA_SE_SHA_256_SIZE); + } + + return res; +} + +int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size) +{ + return se_calc_sha256(hash, NULL, src, src_size, 0, SHA_INIT_HASH, true); +} + +int se_calc_sha256_finalize(void *hash, u32 *msg_left) +{ + u32 hash32[TEGRA_SE_SHA_256_SIZE / 4]; + int res = _se_execute_finalize(); + + // Backup message left. + if (msg_left) + { + msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG_OFFSET); + msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG_OFFSET); + } // Copy output hash. - u32 *dst32 = (u32 *)dst; - for (u32 i = 0; i < 8; i++) - dst32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG_OFFSET + (i << 2))); + for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++) + hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG_OFFSET + (i << 2))); + memcpy(hash, hash32, TEGRA_SE_SHA_256_SIZE); return res; } @@ -573,7 +683,7 @@ int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *ke if (key_size > 0x40) { - if (!se_calc_sha256(secret, key, key_size)) + if (!se_calc_sha256_oneshot(secret, key, key_size)) goto out; memset(secret + 0x20, 0, 0x20); } @@ -593,10 +703,10 @@ int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *ke } memcpy(ipad + 0x40, src, src_size); - if (!se_calc_sha256(dst, ipad, 0x40 + src_size)) + if (!se_calc_sha256_oneshot(dst, ipad, 0x40 + src_size)) goto out; memcpy(opad + 0x40, dst, 0x20); - if (!se_calc_sha256(dst, opad, 0x60)) + if (!se_calc_sha256_oneshot(dst, opad, 0x60)) goto out; res = 1; @@ -611,8 +721,8 @@ out:; // _mgf1_xor() and rsa_oaep_decode were derived from Atmosphère static void _mgf1_xor(void *masked, u32 masked_size, const void *seed, u32 seed_size) { - u8 cur_hash[0x20]; - u8 hash_buf[0xe4]; + u8 cur_hash[0x20] __attribute__((aligned(4))); + u8 hash_buf[0xe4] __attribute__((aligned(4))); u32 hash_buf_size = seed_size + 4; memcpy(hash_buf, seed, seed_size); @@ -627,7 +737,7 @@ static void _mgf1_xor(void *masked, u32 masked_size, const void *seed, u32 seed_ hash_buf[seed_size + 3 - i] = (round_num >> (8 * i)) & 0xff; round_num++; - se_calc_sha256(cur_hash, hash_buf, hash_buf_size); + se_calc_sha256_oneshot(cur_hash, hash_buf, hash_buf_size); for (unsigned int i = 0; i < cur_size; i++) { *p_out ^= cur_hash[i]; @@ -678,3 +788,59 @@ u32 se_rsa_oaep_decode(void *dst, u32 dst_size, const void *label_digest, u32 la return msg_size; } +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_OFFSET) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_SRK); + SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(0) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM); + SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY) | SE_RNG_CONFIG_MODE(RNG_MODE_FORCE_RESEED); + SE(SE_CRYPTO_LAST_BLOCK) = 0; + _se_execute_oneshot(OP_START, NULL, 0, NULL, 0); + + // Save AES keys. + SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); + + for (u32 i = 0; i < TEGRA_SE_KEYSLOT_COUNT; i++) + { + SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(AES_KEYTABLE) | + (i << SE_KEY_INDEX_SHIFT) | SE_CONTEXT_SAVE_WORD_QUAD(KEYS_0_3); + + SE(SE_CRYPTO_LAST_BLOCK) = 0; + _se_execute_oneshot(OP_CTX_SAVE, aligned_buf, 0x10, NULL, 0); + memcpy(keys + i * keysize, aligned_buf, 0x10); + + if (keysize > 0x10) + { + SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(AES_KEYTABLE) | + (i << SE_KEY_INDEX_SHIFT) | SE_CONTEXT_SAVE_WORD_QUAD(KEYS_4_7); + + SE(SE_CRYPTO_LAST_BLOCK) = 0; + _se_execute_oneshot(OP_CTX_SAVE, aligned_buf, 0x10, NULL, 0); + memcpy(keys + i * keysize + 0x10, aligned_buf, 0x10); + } + } + + // Save SRK to PMC secure scratches. + SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(SRK); + SE(SE_CRYPTO_LAST_BLOCK) = 0; + _se_execute_oneshot(OP_CTX_SAVE, NULL, 0, NULL, 0); + + // End context save. + SE(SE_CONFIG_REG_OFFSET) = 0; + _se_execute_oneshot(OP_CTX_SAVE, NULL, 0, NULL, 0); + + // Get SRK. + u32 srk[4]; + srk[0] = PMC(APBDEV_PMC_SECURE_SCRATCH4); + srk[1] = PMC(APBDEV_PMC_SECURE_SCRATCH5); + srk[2] = PMC(APBDEV_PMC_SECURE_SCRATCH6); + srk[3] = PMC(APBDEV_PMC_SECURE_SCRATCH7); + + // Decrypt context. + se_aes_key_clear(3); + se_aes_key_set(3, srk, 0x10); + se_aes_crypt_cbc(3, 0, keys, TEGRA_SE_KEYSLOT_COUNT * keysize, keys, TEGRA_SE_KEYSLOT_COUNT * keysize); + se_aes_key_clear(3); +} diff --git a/bdk/sec/se.h b/bdk/sec/se.h index f10acb3..400d865 100644 --- a/bdk/sec/se.h +++ b/bdk/sec/se.h @@ -26,9 +26,11 @@ int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_siz void se_key_acc_ctrl(u32 ks, u32 flags); u32 se_key_acc_ctrl_get(u32 ks); void se_aes_key_set(u32 ks, const void *key, u32 size); -void se_aes_iv_set(u32 ks, const void *iv, u32 size); -void se_aes_key_read(u32 ks, void *key, u32 size); +void se_aes_iv_set(u32 ks, const void *iv); +void se_aes_key_partial_set(u32 ks, u32 index, u32 data); +void se_aes_key_get(u32 ks, void *key, u32 size); void se_aes_key_clear(u32 ks); +void se_aes_iv_clear(u32 ks); int se_initialize_rng(); int se_generate_random(void *dst, u32 size); int se_generate_random_key(u32 ks_dst, u32 ks_src); @@ -40,8 +42,11 @@ int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, int se_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, const void *src, u32 sec_size); int se_aes_xts_crypt(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, const void *src, u32 sec_size, u32 num_secs); int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size); -int se_calc_sha256(void *dst, const void *src, u32 src_size); +int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot); +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_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size); u32 se_rsa_oaep_decode(void *dst, u32 dst_size, const void *label_digest, u32 label_digest_size, u8 *buf, u32 buf_size); +void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize); #endif diff --git a/bdk/sec/se_t210.h b/bdk/sec/se_t210.h index 83557f7..6fbf1b0 100644 --- a/bdk/sec/se_t210.h +++ b/bdk/sec/se_t210.h @@ -47,15 +47,15 @@ #define ALG_RSA 4 #define ALG_NOP 0 #define ALG_AES_DEC 1 -#define SE_CONFIG_ENC_ALG(x) (x << SE_CONFIG_ENC_ALG_SHIFT) -#define SE_CONFIG_DEC_ALG(x) (x << SE_CONFIG_DEC_ALG_SHIFT) +#define SE_CONFIG_ENC_ALG(x) ((x) << SE_CONFIG_ENC_ALG_SHIFT) +#define SE_CONFIG_DEC_ALG(x) ((x) << SE_CONFIG_DEC_ALG_SHIFT) #define SE_CONFIG_DST_SHIFT 2 #define DST_MEMORY 0 #define DST_HASHREG 1 #define DST_KEYTAB 2 #define DST_SRK 3 #define DST_RSAREG 4 -#define SE_CONFIG_DST(x) (x << SE_CONFIG_DST_SHIFT) +#define SE_CONFIG_DST(x) ((x) << SE_CONFIG_DST_SHIFT) #define SE_CONFIG_ENC_MODE_SHIFT 24 #define SE_CONFIG_DEC_MODE_SHIFT 16 #define MODE_KEY128 0 @@ -66,57 +66,57 @@ #define MODE_SHA256 5 #define MODE_SHA384 6 #define MODE_SHA512 7 -#define SE_CONFIG_ENC_MODE(x) (x << SE_CONFIG_ENC_MODE_SHIFT) -#define SE_CONFIG_DEC_MODE(x) (x << SE_CONFIG_DEC_MODE_SHIFT) +#define SE_CONFIG_ENC_MODE(x) ((x) << SE_CONFIG_ENC_MODE_SHIFT) +#define SE_CONFIG_DEC_MODE(x) ((x) << SE_CONFIG_DEC_MODE_SHIFT) #define SE_RNG_CONFIG_REG_OFFSET 0x340 #define RNG_MODE_SHIFT 0 #define RNG_MODE_NORMAL 0 #define RNG_MODE_FORCE_INSTANTION 1 #define RNG_MODE_FORCE_RESEED 2 -#define SE_RNG_CONFIG_MODE(x) (x << RNG_MODE_SHIFT) +#define SE_RNG_CONFIG_MODE(x) ((x) << RNG_MODE_SHIFT) #define RNG_SRC_SHIFT 2 #define RNG_SRC_NONE 0 #define RNG_SRC_ENTROPY 1 #define RNG_SRC_LFSR 2 -#define SE_RNG_CONFIG_SRC(x) (x << RNG_SRC_SHIFT) +#define SE_RNG_CONFIG_SRC(x) ((x) << RNG_SRC_SHIFT) #define SE_RNG_SRC_CONFIG_REG_OFFSET 0x344 #define RNG_SRC_RO_ENT_SHIFT 1 #define RNG_SRC_RO_ENT_ENABLE 1 #define RNG_SRC_RO_ENT_DISABLE 0 -#define SE_RNG_SRC_CONFIG_ENT_SRC(x) (x << RNG_SRC_RO_ENT_SHIFT) +#define SE_RNG_SRC_CONFIG_ENT_SRC(x) ((x) << RNG_SRC_RO_ENT_SHIFT) #define RNG_SRC_RO_ENT_LOCK_SHIFT 0 #define RNG_SRC_RO_ENT_LOCK_ENABLE 1 #define RNG_SRC_RO_ENT_LOCK_DISABLE 0 -#define SE_RNG_SRC_CONFIG_ENT_SRC_LOCK(x) (x << RNG_SRC_RO_ENT_LOCK_SHIFT) +#define SE_RNG_SRC_CONFIG_ENT_SRC_LOCK(x) ((x) << RNG_SRC_RO_ENT_LOCK_SHIFT) #define SE_RNG_RESEED_INTERVAL_REG_OFFSET 0x348 #define SE_KEYTABLE_REG_OFFSET 0x31c #define SE_KEYTABLE_SLOT_SHIFT 4 -#define SE_KEYTABLE_SLOT(x) (x << SE_KEYTABLE_SLOT_SHIFT) +#define SE_KEYTABLE_SLOT(x) ((x) << SE_KEYTABLE_SLOT_SHIFT) #define SE_KEYTABLE_QUAD_SHIFT 2 #define QUAD_KEYS_128 0 #define QUAD_KEYS_192 1 #define QUAD_KEYS_256 1 #define QUAD_ORG_IV 2 #define QUAD_UPDTD_IV 3 -#define SE_KEYTABLE_QUAD(x) (x << SE_KEYTABLE_QUAD_SHIFT) +#define SE_KEYTABLE_QUAD(x) ((x) << SE_KEYTABLE_QUAD_SHIFT) #define SE_KEYTABLE_OP_TYPE_SHIFT 9 #define OP_READ 0 #define OP_WRITE 1 -#define SE_KEYTABLE_OP_TYPE(x) (x << SE_KEYTABLE_OP_TYPE_SHIFT) +#define SE_KEYTABLE_OP_TYPE(x) ((x) << SE_KEYTABLE_OP_TYPE_SHIFT) #define SE_KEYTABLE_TABLE_SEL_SHIFT 8 #define TABLE_KEYIV 0 #define TABLE_SCHEDULE 1 -#define SE_KEYTABLE_TABLE_SEL(x) (x << SE_KEYTABLE_TABLE_SEL_SHIFT) +#define SE_KEYTABLE_TABLE_SEL(x) ((x) << SE_KEYTABLE_TABLE_SEL_SHIFT) #define SE_KEYTABLE_PKT_SHIFT 0 -#define SE_KEYTABLE_PKT(x) (x << SE_KEYTABLE_PKT_SHIFT) +#define SE_KEYTABLE_PKT(x) ((x) << SE_KEYTABLE_PKT_SHIFT) #define SE_OP_DONE_SHIFT 4 #define OP_DONE 1 -#define SE_OP_DONE(x, y) ((x) && (y << SE_OP_DONE_SHIFT)) +#define SE_OP_DONE(x, y) ((x) && ((y) << SE_OP_DONE_SHIFT)) #define SE_CRYPTO_LAST_BLOCK 0x080 @@ -124,37 +124,37 @@ #define SE_CRYPTO_HASH_SHIFT 0 #define HASH_DISABLE 0 #define HASH_ENABLE 1 -#define SE_CRYPTO_HASH(x) (x << SE_CRYPTO_HASH_SHIFT) +#define SE_CRYPTO_HASH(x) ((x) << SE_CRYPTO_HASH_SHIFT) #define SE_CRYPTO_XOR_POS_SHIFT 1 #define XOR_BYPASS 0 #define XOR_TOP 2 #define XOR_BOTTOM 3 -#define SE_CRYPTO_XOR_POS(x) (x << SE_CRYPTO_XOR_POS_SHIFT) +#define SE_CRYPTO_XOR_POS(x) ((x) << SE_CRYPTO_XOR_POS_SHIFT) #define SE_CRYPTO_INPUT_SEL_SHIFT 3 #define INPUT_AHB 0 #define INPUT_RANDOM 1 #define INPUT_AESOUT 2 #define INPUT_LNR_CTR 3 -#define SE_CRYPTO_INPUT_SEL(x) (x << SE_CRYPTO_INPUT_SEL_SHIFT) +#define SE_CRYPTO_INPUT_SEL(x) ((x) << SE_CRYPTO_INPUT_SEL_SHIFT) #define SE_CRYPTO_VCTRAM_SEL_SHIFT 5 #define VCTRAM_AHB 0 #define VCTRAM_AESOUT 2 #define VCTRAM_PREVAHB 3 -#define SE_CRYPTO_VCTRAM_SEL(x) (x << SE_CRYPTO_VCTRAM_SEL_SHIFT) +#define SE_CRYPTO_VCTRAM_SEL(x) ((x) << SE_CRYPTO_VCTRAM_SEL_SHIFT) #define SE_CRYPTO_IV_SEL_SHIFT 7 #define IV_ORIGINAL 0 #define IV_UPDATED 1 -#define SE_CRYPTO_IV_SEL(x) (x << SE_CRYPTO_IV_SEL_SHIFT) +#define SE_CRYPTO_IV_SEL(x) ((x) << SE_CRYPTO_IV_SEL_SHIFT) #define SE_CRYPTO_CORE_SEL_SHIFT 8 #define CORE_DECRYPT 0 #define CORE_ENCRYPT 1 -#define SE_CRYPTO_CORE_SEL(x) (x << SE_CRYPTO_CORE_SEL_SHIFT) +#define SE_CRYPTO_CORE_SEL(x) ((x) << SE_CRYPTO_CORE_SEL_SHIFT) #define SE_CRYPTO_CTR_VAL_SHIFT 11 -#define SE_CRYPTO_CTR_VAL(x) (x << SE_CRYPTO_CTR_VAL_SHIFT) +#define SE_CRYPTO_CTR_VAL(x) ((x) << SE_CRYPTO_CTR_VAL_SHIFT) #define SE_CRYPTO_KEY_INDEX_SHIFT 24 -#define SE_CRYPTO_KEY_INDEX(x) (x << SE_CRYPTO_KEY_INDEX_SHIFT) +#define SE_CRYPTO_KEY_INDEX(x) ((x) << SE_CRYPTO_KEY_INDEX_SHIFT) #define SE_CRYPTO_CTR_CNTN_SHIFT 11 -#define SE_CRYPTO_CTR_CNTN(x) (x << SE_CRYPTO_CTR_CNTN_SHIFT) +#define SE_CRYPTO_CTR_CNTN(x) ((x) << SE_CRYPTO_CTR_CNTN_SHIFT) #define SE_CRYPTO_CTR_REG_COUNT 4 #define SE_CRYPTO_CTR_REG_OFFSET 0x308 @@ -166,7 +166,7 @@ #define OP_RESTART 2 #define OP_CTX_SAVE 3 #define OP_RESTART_IN 4 -#define SE_OPERATION(x) (x << SE_OPERATION_SHIFT) +#define SE_OPERATION(x) ((x) << SE_OPERATION_SHIFT) #define SE_CONTEXT_SAVE_CONFIG_REG_OFFSET 0x070 #define SE_CONTEXT_SAVE_WORD_QUAD_SHIFT 0 @@ -174,16 +174,16 @@ #define KEYS_4_7 1 #define ORIG_IV 2 #define UPD_IV 3 -#define SE_CONTEXT_SAVE_WORD_QUAD(x) (x << SE_CONTEXT_SAVE_WORD_QUAD_SHIFT) +#define SE_CONTEXT_SAVE_WORD_QUAD(x) ((x) << SE_CONTEXT_SAVE_WORD_QUAD_SHIFT) #define SE_CONTEXT_SAVE_KEY_INDEX_SHIFT 8 -#define SE_CONTEXT_SAVE_KEY_INDEX(x) (x << SE_CONTEXT_SAVE_KEY_INDEX_SHIFT) +#define SE_CONTEXT_SAVE_KEY_INDEX(x) ((x) << SE_CONTEXT_SAVE_KEY_INDEX_SHIFT) -#define SE_CONTEXT_SAVAE_STICKY_WORD_QUAD_SHIFT 24 +#define SE_CONTEXT_SAVE_STICKY_WORD_QUAD_SHIFT 24 #define STICKY_0_3 0 #define STICKY_4_7 1 #define SE_CONTEXT_SAVE_STICKY_WORD_QUAD(x) \ - (x << SE_CONTEXT_SAVAE_STICKY_WORD_QUAD_SHIFT) + ((x) << SE_CONTEXT_SAVE_STICKY_WORD_QUAD_SHIFT) #define SE_CONTEXT_SAVE_SRC_SHIFT 29 #define STICKY_BITS 0 @@ -193,15 +193,20 @@ #define RSA_KEYTABLE 1 #define AES_KEYTABLE 2 -#define SE_CONTEXT_SAVE_SRC(x) (x << SE_CONTEXT_SAVE_SRC_SHIFT) +#define SE_CONTEXT_SAVE_SRC(x) ((x) << SE_CONTEXT_SAVE_SRC_SHIFT) #define SE_CONTEXT_SAVE_RSA_KEY_INDEX_SHIFT 16 #define SE_CONTEXT_SAVE_RSA_KEY_INDEX(x) \ - (x << SE_CONTEXT_SAVE_RSA_KEY_INDEX_SHIFT) + ((x) << SE_CONTEXT_SAVE_RSA_KEY_INDEX_SHIFT) #define SE_CONTEXT_RSA_WORD_QUAD_SHIFT 12 #define SE_CONTEXT_RSA_WORD_QUAD(x) \ - (x << SE_CONTEXT_RSA_WORD_QUAD_SHIFT) + ((x) << SE_CONTEXT_RSA_WORD_QUAD_SHIFT) + +#define SE_CTX_SAVE_AUTO 0x074 +#define CTX_SAVE_AUTO_ENABLE BIT(0) +#define CTX_SAVE_AUTO_LOCK BIT(8) +#define CTX_SAVE_AUTO_CURR_CNT_MASK (0x3FF << 16) #define SE_INT_ENABLE_REG_OFFSET 0x00c #define SE_INT_STATUS_REG_OFFSET 0x010 @@ -210,9 +215,9 @@ #define INT_UNSET 0 #define INT_SET 1 #define SE_INT_OP_DONE_SHIFT 4 -#define SE_INT_OP_DONE(x) (x << SE_INT_OP_DONE_SHIFT) +#define SE_INT_OP_DONE(x) ((x) << SE_INT_OP_DONE_SHIFT) #define SE_INT_ERROR_SHIFT 16 -#define SE_INT_ERROR(x) (x << SE_INT_ERROR_SHIFT) +#define SE_INT_ERROR(x) ((x) << SE_INT_ERROR_SHIFT) #define SE_STATUS_0 0x800 #define SE_STATUS_0_STATE_WAIT_IN 3 @@ -223,10 +228,10 @@ #define SE_CRYPTO_KEYTABLE_DST_REG_OFFSET 0X330 #define SE_CRYPTO_KEYTABLE_DST_WORD_QUAD_SHIFT 0 #define SE_CRYPTO_KEYTABLE_DST_WORD_QUAD(x) \ - (x << SE_CRYPTO_KEYTABLE_DST_WORD_QUAD_SHIFT) + ((x) << SE_CRYPTO_KEYTABLE_DST_WORD_QUAD_SHIFT) #define SE_KEY_INDEX_SHIFT 8 -#define SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(x) (x << SE_KEY_INDEX_SHIFT) +#define SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(x) ((x) << SE_KEY_INDEX_SHIFT) #define SE_IN_LL_ADDR_REG_OFFSET 0x018 #define SE_OUT_LL_ADDR_REG_OFFSET 0x024 @@ -260,6 +265,10 @@ #define TEGRA_SE_AES_MIN_KEY_SIZE 16 #define TEGRA_SE_AES_MAX_KEY_SIZE 32 #define TEGRA_SE_AES_IV_SIZE 16 +#define TEGRA_SE_SHA_512_SIZE 64 +#define TEGRA_SE_SHA_384_SIZE 48 +#define TEGRA_SE_SHA_256_SIZE 32 +#define TEGRA_SE_SHA_192_SIZE 24 #define TEGRA_SE_RNG_IV_SIZE 16 #define TEGRA_SE_RNG_DT_SIZE 16 #define TEGRA_SE_RNG_KEY_SIZE 16 @@ -277,13 +286,13 @@ #define SE_KEY_TBL_DIS_KEY_LOCK_FLAG 0x80 #define SE_KEY_TABLE_ACCESS_REG_OFFSET 0x284 -#define SE_KEY_TBL_DIS_KEYREAD_FLAG (1 << 0) -#define SE_KEY_TBL_DIS_KEYUPDATE_FLAG (1 << 1) -#define SE_KEY_TBL_DIS_OIVREAD_FLAG (1 << 2) -#define SE_KEY_TBL_DIS_OIVUPDATE_FLAG (1 << 3) -#define SE_KEY_TBL_DIS_UIVREAD_FLAG (1 << 4) -#define SE_KEY_TBL_DIS_UIVUPDATE_FLAG (1 << 5) -#define SE_KEY_TBL_DIS_KEYUSE_FLAG (1 << 6) +#define SE_KEY_TBL_DIS_KEYREAD_FLAG BIT(0) +#define SE_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1) +#define SE_KEY_TBL_DIS_OIVREAD_FLAG BIT(2) +#define SE_KEY_TBL_DIS_OIVUPDATE_FLAG BIT(3) +#define SE_KEY_TBL_DIS_UIVREAD_FLAG BIT(4) +#define SE_KEY_TBL_DIS_UIVUPDATE_FLAG BIT(5) +#define SE_KEY_TBL_DIS_KEYUSE_FLAG BIT(6) #define SE_KEY_TBL_DIS_KEY_ACCESS_FLAG 0x7F #define SE_KEY_READ_DISABLE_SHIFT 0 @@ -340,11 +349,11 @@ #define SE_RSA_KEY_TBL_DIS_KEY_LOCK_FLAG 0x80 #define SE_RSA_KEYTABLE_ACCESS_REG_OFFSET 0x410 -#define SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG (1 << 0) -#define SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG (1 << 1) +#define SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG BIT(0) +#define SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1) #define SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG (SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG | SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG) -#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG (1 << 2) -#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG_SHIFT (1 << 2) +#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG BIT(2) +#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG_SHIFT BIT(2) #define SE_RSA_KEY_TBL_DIS_KEY_ALL_COMMON_FLAG 7 #define SE_RSA_KEY_TBL_DIS_KEY_ALL_FLAG 0x7F @@ -355,37 +364,37 @@ #define RSA_KEY_READ 0 #define RSA_KEY_WRITE 1 #define SE_RSA_KEY_OP_SHIFT 10 -#define SE_RSA_KEY_OP(x) (x << SE_RSA_KEY_OP_SHIFT) +#define SE_RSA_KEY_OP(x) ((x) << SE_RSA_KEY_OP_SHIFT) #define RSA_KEY_INPUT_MODE_REG 0 #define RSA_KEY_INPUT_MODE_DMA 1 #define RSA_KEY_INPUT_MODE_SHIFT 8 -#define RSA_KEY_INPUT_MODE(x) (x << RSA_KEY_INPUT_MODE_SHIFT) +#define RSA_KEY_INPUT_MODE(x) ((x) << RSA_KEY_INPUT_MODE_SHIFT) #define RSA_KEY_SLOT_ONE 0 #define RSA_KEY_SLOT_TW0 1 #define RSA_KEY_NUM_SHIFT 7 -#define RSA_KEY_NUM(x) (x << RSA_KEY_NUM_SHIFT) +#define RSA_KEY_NUM(x) ((x) << RSA_KEY_NUM_SHIFT) #define RSA_KEY_TYPE_EXP 0 #define RSA_KEY_TYPE_MOD 1 #define RSA_KEY_TYPE_SHIFT 6 -#define RSA_KEY_TYPE(x) (x << RSA_KEY_TYPE_SHIFT) +#define RSA_KEY_TYPE(x) ((x) << RSA_KEY_TYPE_SHIFT) #define SE_RSA_KEY_SIZE_REG_OFFSET 0x404 #define SE_RSA_EXP_SIZE_REG_OFFSET 0x408 #define RSA_KEY_SLOT_SHIFT 24 -#define RSA_KEY_SLOT(x) (x << RSA_KEY_SLOT_SHIFT) +#define RSA_KEY_SLOT(x) ((x) << RSA_KEY_SLOT_SHIFT) #define SE_RSA_CONFIG 0x400 #define RSA_KEY_PKT_WORD_ADDR_SHIFT 0 -#define RSA_KEY_PKT_WORD_ADDR(x) (x << RSA_KEY_PKT_WORD_ADDR_SHIFT) +#define RSA_KEY_PKT_WORD_ADDR(x) ((x) << RSA_KEY_PKT_WORD_ADDR_SHIFT) #define RSA_KEY_WORD_ADDR_SHIFT 0 -#define RSA_KEY_WORD_ADDR(x) (x << RSA_KEY_WORD_ADDR_SHIFT) +#define RSA_KEY_WORD_ADDR(x) ((x) << RSA_KEY_WORD_ADDR_SHIFT) #define SE_RSA_KEYTABLE_PKT_SHIFT 0 -#define SE_RSA_KEYTABLE_PKT(x) (x << SE_RSA_KEYTABLE_PKT_SHIFT) +#define SE_RSA_KEYTABLE_PKT(x) ((x) << SE_RSA_KEYTABLE_PKT_SHIFT) #endif /* _CRYPTO_TEGRA_SE_H */ diff --git a/bdk/sec/tsec_t210.h b/bdk/sec/tsec_t210.h index befe269..889d0d4 100644 --- a/bdk/sec/tsec_t210.h +++ b/bdk/sec/tsec_t210.h @@ -20,30 +20,30 @@ #define TSEC_BOOTKEYVER 0x1040 #define TSEC_STATUS 0x1044 #define TSEC_ITFEN 0x1048 -#define TSEC_ITFEN_CTXEN (1 << 0) -#define TSEC_ITFEN_MTHDEN (1 << 1) +#define TSEC_ITFEN_CTXEN BIT(0) +#define TSEC_ITFEN_MTHDEN BIT(1) #define TSEC_IRQMSET 0x1010 -#define TSEC_IRQMSET_WDTMR (1 << 1) -#define TSEC_IRQMSET_HALT (1 << 4) -#define TSEC_IRQMSET_EXTERR (1 << 5) -#define TSEC_IRQMSET_SWGEN0 (1 << 6) -#define TSEC_IRQMSET_SWGEN1 (1 << 7) +#define TSEC_IRQMSET_WDTMR BIT(1) +#define TSEC_IRQMSET_HALT BIT(4) +#define TSEC_IRQMSET_EXTERR BIT(5) +#define TSEC_IRQMSET_SWGEN0 BIT(6) +#define TSEC_IRQMSET_SWGEN1 BIT(7) #define TSEC_IRQMSET_EXT(val) (((val) & 0xFF) << 8) #define TSEC_IRQDEST 0x101C -#define TSEC_IRQDEST_HALT (1 << 4) -#define TSEC_IRQDEST_EXTERR (1 << 5) -#define TSEC_IRQDEST_SWGEN0 (1 << 6) -#define TSEC_IRQDEST_SWGEN1 (1 << 7) +#define TSEC_IRQDEST_HALT BIT(4) +#define TSEC_IRQDEST_EXTERR BIT(5) +#define TSEC_IRQDEST_SWGEN0 BIT(6) +#define TSEC_IRQDEST_SWGEN1 BIT(7) #define TSEC_IRQDEST_EXT(val) (((val) & 0xFF) << 8) #define TSEC_CPUCTL 0x1100 -#define TSEC_CPUCTL_STARTCPU (1 << 1) +#define TSEC_CPUCTL_STARTCPU BIT(1) #define TSEC_BOOTVEC 0x1104 #define TSEC_DMACTL 0x110C #define TSEC_DMATRFBASE 0x1110 #define TSEC_DMATRFMOFFS 0x1114 #define TSEC_DMATRFCMD 0x1118 -#define TSEC_DMATRFCMD_IDLE (1 << 1) -#define TSEC_DMATRFCMD_IMEM (1 << 4) +#define TSEC_DMATRFCMD_IDLE BIT(1) +#define TSEC_DMATRFCMD_IMEM BIT(4) #define TSEC_DMATRFCMD_SIZE_256B (6 << 8) #define TSEC_DMATRFFBOFFS 0x111C diff --git a/bdk/soc/bpmp.c b/bdk/soc/bpmp.c index 1a8a205..2e1819d 100644 --- a/bdk/soc/bpmp.c +++ b/bdk/soc/bpmp.c @@ -25,38 +25,38 @@ #define BPMP_MMU_CACHE_LINE_SIZE 0x20 #define BPMP_CACHE_CONFIG 0x0 -#define CFG_ENABLE_CACHE (1 << 0) -#define CFG_ENABLE_SKEW_ASSOC (1 << 1) -#define CFG_DISABLE_RANDOM_ALLOC (1 << 2) -#define CFG_FORCE_WRITE_THROUGH (1 << 3) -#define CFG_NEVER_ALLOCATE (1 << 6) -#define CFG_ENABLE_INTERRUPT (1 << 7) -#define CFG_MMU_TAG_MODE(x) (x << 8) +#define CFG_ENABLE_CACHE BIT(0) +#define CFG_ENABLE_SKEW_ASSOC BIT(1) +#define CFG_DISABLE_RANDOM_ALLOC BIT(2) +#define CFG_FORCE_WRITE_THROUGH BIT(3) +#define CFG_NEVER_ALLOCATE BIT(6) +#define CFG_ENABLE_INTERRUPT BIT(7) +#define CFG_MMU_TAG_MODE(x) ((x) << 8) #define TAG_MODE_PARALLEL 0 #define TAG_MODE_TAG_FIRST 1 #define TAG_MODE_MMU_FIRST 2 -#define CFG_DISABLE_WRITE_BUFFER (1 << 10) -#define CFG_DISABLE_READ_BUFFER (1 << 11) -#define CFG_ENABLE_HANG_DETECT (1 << 12) -#define CFG_FULL_LINE_DIRTY (1 << 13) -#define CFG_TAG_CHK_ABRT_ON_ERR (1 << 14) -#define CFG_TAG_CHK_CLR_ERR (1 << 15) -#define CFG_DISABLE_SAMELINE (1 << 16) -#define CFG_OBS_BUS_EN (1 << 31) +#define CFG_DISABLE_WRITE_BUFFER BIT(10) +#define CFG_DISABLE_READ_BUFFER BIT(11) +#define CFG_ENABLE_HANG_DETECT BIT(12) +#define CFG_FULL_LINE_DIRTY BIT(13) +#define CFG_TAG_CHK_ABRT_ON_ERR BIT(14) +#define CFG_TAG_CHK_CLR_ERR BIT(15) +#define CFG_DISABLE_SAMELINE BIT(16) +#define CFG_OBS_BUS_EN BIT(31) #define BPMP_CACHE_LOCK 0x4 -#define LOCK_LINE(x) (1 << x) +#define LOCK_LINE(x) BIT((x)) #define BPMP_CACHE_SIZE 0xC #define BPMP_CACHE_LFSR 0x10 #define BPMP_CACHE_TAG_STATUS 0x14 -#define TAG_STATUS_TAG_CHECK_ERROR (1 << 0) +#define TAG_STATUS_TAG_CHECK_ERROR BIT(0) #define TAG_STATUS_CONFLICT_ADDR_MASK 0xFFFFFFE0 #define BPMP_CACHE_CLKEN_OVERRIDE 0x18 -#define CLKEN_OVERRIDE_WR_MCCIF_CLKEN (1 << 0) -#define CLKEN_OVERRIDE_RD_MCCIF_CLKEN (1 << 1) +#define CLKEN_OVERRIDE_WR_MCCIF_CLKEN BIT(0) +#define CLKEN_OVERRIDE_RD_MCCIF_CLKEN BIT(1) #define BPMP_CACHE_MAINT_ADDR 0x20 #define BPMP_CACHE_MAINT_DATA 0x24 @@ -68,8 +68,8 @@ #define BPMP_CACHE_INT_CLEAR 0x44 #define BPMP_CACHE_INT_RAW_EVENT 0x48 #define BPMP_CACHE_INT_STATUS 0x4C -#define INT_MAINT_DONE (1 << 0) -#define INT_MAINT_ERROR (1 << 1) +#define INT_MAINT_DONE BIT(0) +#define INT_MAINT_ERROR BIT(1) #define BPMP_CACHE_RB_CFG 0x80 #define BPMP_CACHE_WB_CFG 0x84 @@ -78,12 +78,12 @@ #define BPMP_CACHE_MMU_SHADOW_COPY_MASK 0xA4 #define BPMP_CACHE_MMU_CFG 0xAC -#define MMU_CFG_BLOCK_MAIN_ENTRY_WR (1 << 0) -#define MMU_CFG_SEQ_EN (1 << 1) -#define MMU_CFG_TLB_EN (1 << 2) -#define MMU_CFG_SEG_CHECK_ALL_ENTRIES (1 << 3) -#define MMU_CFG_ABORT_STORE_LAST (1 << 4) -#define MMU_CFG_CLR_ABORT (1 << 5) +#define MMU_CFG_BLOCK_MAIN_ENTRY_WR BIT(0) +#define MMU_CFG_SEQ_EN BIT(1) +#define MMU_CFG_TLB_EN BIT(2) +#define MMU_CFG_SEG_CHECK_ALL_ENTRIES BIT(3) +#define MMU_CFG_ABORT_STORE_LAST BIT(4) +#define MMU_CFG_CLR_ABORT BIT(5) #define BPMP_CACHE_MMU_CMD 0xB0 #define MMU_CMD_NOP 0 @@ -98,25 +98,25 @@ #define ABORT_STAT_UNIT_TLB 3 #define ABORT_STAT_UNIT_SEG 4 #define ABORT_STAT_UNIT_FALLBACK 5 -#define ABORT_STAT_OVERLAP (1 << 3) +#define ABORT_STAT_OVERLAP BIT(3) #define ABORT_STAT_ENTRY (0x1F << 4) #define ABORT_STAT_TYPE_MASK (3 << 16) #define ABORT_STAT_TYPE_EXE (0 << 16) #define ABORT_STAT_TYPE_RD (1 << 16) #define ABORT_STAT_TYPE_WR (2 << 16) #define ABORT_STAT_SIZE (3 << 18) -#define ABORT_STAT_SEQ (1 << 20) -#define ABORT_STAT_PROT (1 << 21) +#define ABORT_STAT_SEQ BIT(20) +#define ABORT_STAT_PROT BIT(21) #define BPMP_CACHE_MMU_ABORT_ADDR 0xB8 #define BPMP_CACHE_MMU_ACTIVE_ENTRIES 0xBC #define BPMP_MMU_SHADOW_ENTRY_BASE (BPMP_CACHE_BASE + 0x400) #define BPMP_MMU_MAIN_ENTRY_BASE (BPMP_CACHE_BASE + 0x800) -#define MMU_EN_CACHED (1 << 0) -#define MMU_EN_EXEC (1 << 1) -#define MMU_EN_READ (1 << 2) -#define MMU_EN_WRITE (1 << 3) +#define MMU_EN_CACHED BIT(0) +#define MMU_EN_EXEC BIT(1) +#define MMU_EN_READ BIT(2) +#define MMU_EN_WRITE BIT(3) bpmp_mmu_entry_t mmu_entries[] = { @@ -153,7 +153,7 @@ void bpmp_mmu_set_entry(int idx, bpmp_mmu_entry_t *entry, bool apply) 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) |= (1 << idx); + BPMP_CACHE_CTRL(BPMP_CACHE_MMU_SHADOW_COPY_MASK) |= BIT(idx); if (apply) BPMP_CACHE_CTRL(BPMP_CACHE_MMU_CMD) = MMU_CMD_COPY_SHADOW; @@ -172,7 +172,7 @@ void bpmp_mmu_enable() // Init BPMP MMU entries. BPMP_CACHE_CTRL(BPMP_CACHE_MMU_SHADOW_COPY_MASK) = 0; - for (u32 idx = 0; idx < (sizeof(mmu_entries) / sizeof(bpmp_mmu_entry_t)); idx++) + for (u32 idx = 0; idx < ARRAY_SIZE(mmu_entries); idx++) bpmp_mmu_set_entry(idx, &mmu_entries[idx], false); BPMP_CACHE_CTRL(BPMP_CACHE_MMU_CMD) = MMU_CMD_COPY_SHADOW; diff --git a/bdk/soc/ccplex.c b/bdk/soc/ccplex.c index 24a4787..a8d782d 100644 --- a/bdk/soc/ccplex.c +++ b/bdk/soc/ccplex.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 naehrwert + * Copyright (c) 2018-2020 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,18 +16,21 @@ */ #include +#include +#include #include #include -#include #include #include #include #include +#include +#include -void _ccplex_enable_power() +void _ccplex_enable_power_t210() { u8 tmp = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO); // Get current pinmuxing - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO, tmp & ~(1 << 5)); // Disable GPIO5 pinmuxing. + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO, tmp & ~BIT(5)); // Disable GPIO5 pinmuxing. i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO5, MAX77620_CNFG_GPIO_DRV_PUSHPULL | MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH); // Enable cores power. @@ -40,37 +44,12 @@ void _ccplex_enable_power() i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_DVS_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_0_95V); } -int _ccplex_pmc_enable_partition(u32 part, int enable) +void _ccplex_enable_power_t210b01() { - u32 part_mask = 1 << part; - u32 desired_state = enable << part; - - // Check if the partition has the state we want. - if ((PMC(APBDEV_PMC_PWRGATE_STATUS) & part_mask) == desired_state) - return 1; - - u32 i = 5001; - while (PMC(APBDEV_PMC_PWRGATE_TOGGLE) & 0x100) - { - usleep(1); - i--; - if (i < 1) - return 0; - } - - // Toggle power gating. - PMC(APBDEV_PMC_PWRGATE_TOGGLE) = part | 0x100; - - i = 5001; - while (i > 0) - { - if ((PMC(APBDEV_PMC_PWRGATE_STATUS) & part_mask) == desired_state) - break; - usleep(1); - i--; - } - - return 1; + u8 pmic_cpu_addr = !(FUSE(FUSE_RESERVED_ODM28) & 1) ? MAX77812_PHASE31_CPU_I2C_ADDR : MAX77812_PHASE211_CPU_I2C_ADDR; + u8 tmp = i2c_recv_byte(I2C_5, pmic_cpu_addr, MAX77812_REG_EN_CTRL); + i2c_send_byte(I2C_5, pmic_cpu_addr, MAX77812_REG_EN_CTRL, tmp | MAX77812_EN_CTRL_EN_M4); + i2c_send_byte(I2C_5, pmic_cpu_addr, MAX77812_REG_M4_VOUT, MAX77812_M4_VOUT_0_80V); } void ccplex_boot_cpu0(u32 entry) @@ -78,7 +57,10 @@ void ccplex_boot_cpu0(u32 entry) // Set ACTIVE_CLUSER to FAST. FLOW_CTLR(FLOW_CTLR_BPMP_CLUSTER_CONTROL) &= 0xFFFFFFFE; - _ccplex_enable_power(); + if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210) + _ccplex_enable_power_t210(); + else + _ccplex_enable_power_t210b01(); if (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & 0x40000000)) // PLLX_ENABLE. { @@ -94,12 +76,12 @@ void ccplex_boot_cpu0(u32 entry) // Configure MSELECT source and enable clock. CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) & 0x1FFFFF00) | 6; - CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) = (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) & 0xFFFFFFF7) | 8; + CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) = (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) & ~BIT(CLK_V_MSELECT)) | BIT(CLK_V_MSELECT); // Configure initial CPU clock frequency and enable clock. CLOCK(CLK_RST_CONTROLLER_CCLK_BURST_POLICY) = 0x20008888; CLOCK(CLK_RST_CONTROLLER_SUPER_CCLK_DIVIDER) = 0x80000000; - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = 1; + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = BIT(CLK_V_CPUG); clock_enable_coresight(); @@ -107,11 +89,11 @@ void ccplex_boot_cpu0(u32 entry) CLOCK(CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2) &= 0xFFFFF000; // Enable CPU rail. - _ccplex_pmc_enable_partition(0, 1); - // Enable cluster 0 non-CPU. - _ccplex_pmc_enable_partition(15, 1); - // Enable CE0. - _ccplex_pmc_enable_partition(14, 1); + pmc_enable_partition(0, 1); + // Enable cluster 0 non-CPU rail. + pmc_enable_partition(15, 1); + // Enable CE0 rail. + pmc_enable_partition(14, 1); // Request and wait for RAM repair. FLOW_CTLR(FLOW_CTLR_RAM_REPAIR) = 1; @@ -131,7 +113,7 @@ void ccplex_boot_cpu0(u32 entry) // MC(MC_TZ_SECURITY_CTRL) = 1; // Clear MSELECT reset. - CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_V) &= 0xFFFFFFF7; + CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_V) &= ~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 41e69a2..cf0007e 100644 --- a/bdk/soc/clock.c +++ b/bdk/soc/clock.c @@ -16,110 +16,101 @@ */ #include +#include #include #include #include -/* - * CLOCK Peripherals: - * L 0 - 31 - * H 32 - 63 - * U 64 - 95 - * V 96 - 127 - * W 128 - 159 - * X 160 - 191 - * Y 192 - 223 - */ - /* clock_t: reset, enable, source, index, clk_src, clk_div */ static const clock_t _clock_uart[] = { -/* UART A */ { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTA, 6, 0, 2 }, -/* UART B */ { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTB, 7, 0, 2 }, -/* UART C */ { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_UARTC, 23, 0, 2 }, -/* UART D */ { CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_UARTD, 1, 0, 2 }, -/* UART E */ { CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_UARTAPE, 20, 0, 2 } + { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTA, CLK_L_UARTA, 0, 2 }, + { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTB, CLK_L_UARTB, 0, 2 }, + { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_UARTC, CLK_H_UARTC, 0, 2 }, + { CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_UARTD, CLK_U_UARTD, 0, 2 }, + { CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_UARTAPE, CLK_Y_UARTAPE, 0, 2 } }; //I2C default parameters - TLOW: 4, THIGH: 2, DEBOUNCE: 0, FM_DIV: 26. static const clock_t _clock_i2c[] = { -/* I2C1 */ { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_I2C1, 12, 0, 19 }, //20.4MHz -> 100KHz -/* I2C2 */ { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_I2C2, 22, 0, 4 }, //81.6MHz -> 400KHz -/* I2C3 */ { CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_I2C3, 3, 0, 4 }, //81.6MHz -> 400KHz -/* I2C4 */ { CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_I2C4, 7, 0, 19 }, //20.4MHz -> 100KHz -/* I2C5 */ { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_I2C5, 15, 0, 4 }, //81.6MHz -> 400KHz -/* I2C6 */ { CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_I2C6, 6, 0, 19 } //20.4MHz -> 100KHz + { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_I2C1, CLK_L_I2C1, 0, 19 }, //20.4MHz -> 100KHz + { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_I2C2, CLK_H_I2C2, 0, 4 }, //81.6MHz -> 400KHz + { CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_I2C3, CLK_U_I2C3, 0, 4 }, //81.6MHz -> 400KHz + { CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_I2C4, CLK_V_I2C4, 0, 19 }, //20.4MHz -> 100KHz + { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_I2C5, CLK_H_I2C5, 0, 4 }, //81.6MHz -> 400KHz + { 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, 31, 0, 0 + CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_SE, CLK_V_SE, 0, 0 }; static clock_t _clock_tzram = { - CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_NO_SOURCE, 30, 0, 0 + CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_NO_SOURCE, CLK_V_TZRAM, 0, 0 }; static clock_t _clock_host1x = { - CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X, 28, 4, 3 + CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X, CLK_L_HOST1X, 4, 3 }; static clock_t _clock_tsec = { - CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_TSEC, 19, 0, 2 + CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_TSEC, CLK_U_TSEC, 0, 2 }; static clock_t _clock_sor_safe = { - CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_NO_SOURCE, 30, 0, 0 + CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_NO_SOURCE, CLK_Y_SOR_SAFE, 0, 0 }; static clock_t _clock_sor0 = { - CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_NO_SOURCE, 22, 0, 0 + CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_NO_SOURCE, CLK_X_SOR0, 0, 0 }; static clock_t _clock_sor1 = { - CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_SOR1, 23, 0, 2 + CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_SOR1, CLK_X_SOR1, 0, 2 }; static clock_t _clock_kfuse = { - CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, 8, 0, 0 + CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_KFUSE, 0, 0 }; static clock_t _clock_cl_dvfs = { - CLK_RST_CONTROLLER_RST_DEVICES_W, CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_NO_SOURCE, 27, 0, 0 + CLK_RST_CONTROLLER_RST_DEVICES_W, CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_NO_SOURCE, CLK_W_DVFS, 0, 0 }; static clock_t _clock_coresight = { - CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_CSITE, 9, 0, 4 + CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_CSITE, CLK_U_CSITE, 0, 4 }; static clock_t _clock_pwm = { - CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, 17, 6, 4 // Fref: 6.2MHz. + 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. Stock PLLP / 54: 7.55MHz. }; static clock_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, 1, 4, 66 + CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM, CLK_Y_SDMMC_LEGACY_TM, 4, 66 }; void clock_enable(const clock_t *clk) { // Put clock into reset. - CLOCK(clk->reset) = (CLOCK(clk->reset) & ~(1 << clk->index)) | (1 << clk->index); + CLOCK(clk->reset) = (CLOCK(clk->reset) & ~BIT(clk->index)) | BIT(clk->index); // Disable. - CLOCK(clk->enable) &= ~(1 << clk->index); + CLOCK(clk->enable) &= ~BIT(clk->index); // Configure clock source if required. if (clk->source) CLOCK(clk->source) = clk->clk_div | (clk->clk_src << 29); // Enable. - CLOCK(clk->enable) = (CLOCK(clk->enable) & ~(1 << clk->index)) | (1 << clk->index); + CLOCK(clk->enable) = (CLOCK(clk->enable) & ~BIT(clk->index)) | BIT(clk->index); usleep(2); // Take clock off reset. - CLOCK(clk->reset) &= ~(1 << clk->index); + CLOCK(clk->reset) &= ~BIT(clk->index); } void clock_disable(const clock_t *clk) { // Put clock into reset. - CLOCK(clk->reset) = (CLOCK(clk->reset) & ~(1 << clk->index)) | (1 << clk->index); + CLOCK(clk->reset) = (CLOCK(clk->reset) & ~BIT(clk->index)) | BIT(clk->index); // Disable. - CLOCK(clk->enable) &= ~(1 << clk->index); + CLOCK(clk->enable) &= ~BIT(clk->index); } void clock_enable_fuse(bool enable) { + // Enable Fuse registers visibility. CLOCK(CLK_RST_CONTROLLER_MISC_CLK_ENB) = (CLOCK(CLK_RST_CONTROLLER_MISC_CLK_ENB) & 0xEFFFFFFF) | ((enable & 1) << 28); } @@ -133,7 +124,7 @@ void clock_disable_uart(u32 idx) clock_disable(&_clock_uart[idx]); } -#define UART_SRC_CLK_DIV_EN (1 << 24) +#define UART_SRC_CLK_DIV_EN BIT(24) int clock_uart_use_src_div(u32 idx, u32 baud) { @@ -164,6 +155,10 @@ void clock_disable_i2c(u32 idx) void clock_enable_se() { clock_enable(&_clock_se); + + // Lock clock to always enabled if T210B01. + if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01) + CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SE) |= 0x100; } void clock_enable_tzram() @@ -223,12 +218,12 @@ void clock_disable_sor1() void clock_enable_kfuse() { - //clock_enable(&_clock_kfuse); - CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) = (CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) & 0xFFFFFEFF) | 0x100; - CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) &= 0xFFFFFEFF; - CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) = (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) & 0xFFFFFEFF) | 0x100; + u32 kfuse_clk_unmask = ~BIT(CLK_H_KFUSE); + CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) = (CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) & kfuse_clk_unmask) | BIT(CLK_H_KFUSE); + CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) &= kfuse_clk_unmask; + CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) = (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) & kfuse_clk_unmask) | BIT(CLK_H_KFUSE); usleep(10); - CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) &= 0xFFFFFEFF; + CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) &= kfuse_clk_unmask; usleep(20); } @@ -281,7 +276,7 @@ void clock_enable_pllc(u32 divn) CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_2) |= 0xF0 << 8; // PLLC_FLL_LD_MEM. // Disable PLL and IDDQ in case they are on. - CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) &= ~PLLCX_BASE_ENABLE; + CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) &= ~PLLCX_BASE_ENABLE; CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_1) &= ~PLLC_MISC1_IDDQ; usleep(10); @@ -294,7 +289,7 @@ void clock_enable_pllc(u32 divn) ; // Disable PLLC_OUT1, enable reset and set div to 1.5. - CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) = (1 << 8); + CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) = BIT(8); // Enable PLLC_OUT1 and bring it out of reset. CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) |= (PLLC_OUT1_CLKEN | PLLC_OUT1_RSTN_CLR); @@ -304,15 +299,15 @@ 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_BASE) &= ~PLLCX_BASE_ENABLE; - CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) |= PLLCX_BASE_REF_DIS; + CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) &= ~(PLLC_OUT1_CLKEN | PLLC_OUT1_RSTN_CLR); + 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) |= PLLC_MISC_RESET; usleep(10); } -#define PLLC4_ENABLED (1 << 31) +#define PLLC4_ENABLED BIT(31) #define PLLC4_IN_USE (~PLLC4_ENABLED) u32 pllc4_enabled = 0; @@ -362,48 +357,60 @@ static void _clock_disable_pllc4(u32 mask) pllc4_enabled = 0; } -#define L_SWR_SDMMC1_RST (1 << 14) -#define L_SWR_SDMMC2_RST (1 << 9) -#define L_SWR_SDMMC4_RST (1 << 15) -#define U_SWR_SDMMC3_RST (1 << 5) +void clock_enable_pllu() +{ + // Configure PLLU. + CLOCK(CLK_RST_CONTROLLER_PLLU_MISC) |= BIT(29); // Disable reference clock. + u32 pllu_cfg = (CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) & 0xFFE00000) | BIT(24) | (1 << 16) | (0x19 << 8) | 2; + CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) = pllu_cfg; + CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) = pllu_cfg | PLLCX_BASE_ENABLE; // Enable. -#define L_CLK_ENB_SDMMC1 (1 << 14) -#define L_CLK_ENB_SDMMC2 (1 << 9) -#define L_CLK_ENB_SDMMC4 (1 << 15) -#define U_CLK_ENB_SDMMC3 (1 << 5) + // Wait for PLL to stabilize. + u32 timeout = (u32)TMR(TIMERUS_CNTR_1US) + 1300; + while (!(CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) & PLLCX_BASE_LOCK)) // PLL_LOCK. + if ((u32)TMR(TIMERUS_CNTR_1US) > timeout) + break; + usleep(10); -#define L_SET_SDMMC1_RST (1 << 14) -#define L_SET_SDMMC2_RST (1 << 9) -#define L_SET_SDMMC4_RST (1 << 15) -#define U_SET_SDMMC3_RST (1 << 5) + // Enable PLLU USB/HSIC/ICUSB/48M. + CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) |= 0x2E00000; +} -#define L_CLR_SDMMC1_RST (1 << 14) -#define L_CLR_SDMMC2_RST (1 << 9) -#define L_CLR_SDMMC4_RST (1 << 15) -#define U_CLR_SDMMC3_RST (1 << 5) +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. +} -#define L_SET_CLK_ENB_SDMMC1 (1 << 14) -#define L_SET_CLK_ENB_SDMMC2 (1 << 9) -#define L_SET_CLK_ENB_SDMMC4 (1 << 15) -#define U_SET_CLK_ENB_SDMMC3 (1 << 5) +void clock_enable_utmipll() +{ + // Set UTMIPLL dividers and config based on OSC and enable it to 960 MHz. + CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG0) = (CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG0) & 0xFF0000FF) | (25 << 16) | (1 << 8); // 38.4Mhz * (25 / 1) = 960 MHz. + CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG2) = (CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG2) & 0xFF00003F) | (24 << 18); // Set delay count for 38.4Mhz osc crystal. + CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG1) = (CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG1) & 0x7FFA000) | (1 << 15) | 375; -#define L_CLR_CLK_ENB_SDMMC1 (1 << 14) -#define L_CLR_CLK_ENB_SDMMC2 (1 << 9) -#define L_CLR_CLK_ENB_SDMMC4 (1 << 15) -#define U_CLR_CLK_ENB_SDMMC3 (1 << 5) + // Wait for UTMIPLL to stabilize. + u32 retries = 10; // Wait 20us + while (!(CLOCK(CLK_RST_CONTROLLER_UTMIPLL_HW_PWRDN_CFG0) & UTMIPLL_LOCK) && retries) + { + usleep(1); + retries--; + } +} static int _clock_sdmmc_is_reset(u32 id) { switch (id) { case SDMMC_1: - return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_L) & L_SWR_SDMMC1_RST; + return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_L) & BIT(CLK_L_SDMMC1); case SDMMC_2: - return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_L) & L_SWR_SDMMC2_RST; + return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_L) & BIT(CLK_L_SDMMC2); case SDMMC_3: - return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_U) & U_SWR_SDMMC3_RST; + return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_U) & BIT(CLK_U_SDMMC3); case SDMMC_4: - return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_L) & L_SWR_SDMMC4_RST; + return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_L) & BIT(CLK_L_SDMMC4); } return 0; } @@ -413,16 +420,16 @@ static void _clock_sdmmc_set_reset(u32 id) switch (id) { case SDMMC_1: - CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = L_SET_SDMMC1_RST; + CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_SDMMC1); break; case SDMMC_2: - CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = L_SET_SDMMC2_RST; + CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_SDMMC2); break; case SDMMC_3: - CLOCK(CLK_RST_CONTROLLER_RST_DEV_U_SET) = U_SET_SDMMC3_RST; + CLOCK(CLK_RST_CONTROLLER_RST_DEV_U_SET) = BIT(CLK_U_SDMMC3); break; case SDMMC_4: - CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = L_SET_SDMMC4_RST; + CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_SDMMC4); break; } } @@ -432,16 +439,16 @@ static void _clock_sdmmc_clear_reset(u32 id) switch (id) { case SDMMC_1: - CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = L_CLR_SDMMC1_RST; + CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = BIT(CLK_L_SDMMC1); break; case SDMMC_2: - CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = L_CLR_SDMMC2_RST; + CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = BIT(CLK_L_SDMMC2); break; case SDMMC_3: - CLOCK(CLK_RST_CONTROLLER_RST_DEV_U_CLR) = U_CLR_SDMMC3_RST; + CLOCK(CLK_RST_CONTROLLER_RST_DEV_U_CLR) = BIT(CLK_U_SDMMC3); break; case SDMMC_4: - CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = L_CLR_SDMMC4_RST; + CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = BIT(CLK_L_SDMMC4); break; } } @@ -451,13 +458,13 @@ static int _clock_sdmmc_is_enabled(u32 id) switch (id) { case SDMMC_1: - return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & L_CLK_ENB_SDMMC1; + return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & BIT(CLK_L_SDMMC1); case SDMMC_2: - return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & L_CLK_ENB_SDMMC2; + return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & BIT(CLK_L_SDMMC2); case SDMMC_3: - return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_U) & U_CLK_ENB_SDMMC3; + return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_U) & BIT(CLK_U_SDMMC3); case SDMMC_4: - return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & L_CLK_ENB_SDMMC4; + return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & BIT(CLK_L_SDMMC4); } return 0; } @@ -467,16 +474,16 @@ static void _clock_sdmmc_set_enable(u32 id) switch (id) { case SDMMC_1: - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = L_SET_CLK_ENB_SDMMC1; + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_SDMMC1); break; case SDMMC_2: - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = L_SET_CLK_ENB_SDMMC2; + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_SDMMC2); break; case SDMMC_3: - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_U_SET) = U_SET_CLK_ENB_SDMMC3; + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_U_SET) = BIT(CLK_U_SDMMC3); break; case SDMMC_4: - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = L_SET_CLK_ENB_SDMMC4; + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_SDMMC4); break; } } @@ -486,16 +493,16 @@ static void _clock_sdmmc_clear_enable(u32 id) switch (id) { case SDMMC_1: - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = L_CLR_CLK_ENB_SDMMC1; + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = BIT(CLK_L_SDMMC1); break; case SDMMC_2: - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = L_CLR_CLK_ENB_SDMMC2; + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = BIT(CLK_L_SDMMC2); break; case SDMMC_3: - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_U_CLR) = U_CLR_CLK_ENB_SDMMC3; + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_U_CLR) = BIT(CLK_U_SDMMC3); break; case SDMMC_4: - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = L_CLR_CLK_ENB_SDMMC4; + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = BIT(CLK_L_SDMMC4); break; } } @@ -503,7 +510,7 @@ static void _clock_sdmmc_clear_enable(u32 id) static void _clock_sdmmc_config_legacy_tm() { clock_t *clk = &_clock_sdmmc_legacy_tm; - if (!(CLOCK(clk->enable) & (1 << clk->index))) + if (!(CLOCK(clk->enable) & BIT(clk->index))) clock_enable(clk); } @@ -588,7 +595,7 @@ static int _clock_sdmmc_config_clock_host(u32 *pclock, u32 id, u32 val) // Enable PLLC4 if in use by any SDMMC. if (source) - _clock_enable_pllc4(1 << id); + _clock_enable_pllc4(BIT(id)); // Set SDMMC legacy timeout clock. _clock_sdmmc_config_legacy_tm(); @@ -680,7 +687,7 @@ void clock_sdmmc_get_card_clock_div(u32 *pclock, u16 *pdivisor, u32 type) *pclock = 40800; *pdivisor = 1; break; - case SDHCI_TIMING_MMC_DDR52: // Actual IO Freq: 49.92 MHz. + case SDHCI_TIMING_MMC_HS102: // Actual IO Freq: 99.84 MHz. *pclock = 200000; *pdivisor = 2; break; @@ -712,5 +719,5 @@ void clock_sdmmc_disable(u32 id) _clock_sdmmc_set_reset(id); _clock_sdmmc_clear_enable(id); _clock_sdmmc_is_reset(id); - _clock_disable_pllc4(1 << id); + _clock_disable_pllc4(BIT(id)); } diff --git a/bdk/soc/clock.h b/bdk/soc/clock.h index bbcd482..2f6de41 100644 --- a/bdk/soc/clock.h +++ b/bdk/soc/clock.h @@ -48,6 +48,7 @@ #define CLK_RST_CONTROLLER_PLLA_MISC1 0xB8 #define CLK_RST_CONTROLLER_PLLA_MISC 0xBC #define CLK_RST_CONTROLLER_PLLU_BASE 0xC0 +#define CLK_RST_CONTROLLER_PLLU_OUTA 0xC4 #define CLK_RST_CONTROLLER_PLLU_MISC 0xCC #define CLK_RST_CONTROLLER_PLLD_BASE 0xD0 #define CLK_RST_CONTROLLER_PLLD_MISC1 0xD8 @@ -131,6 +132,7 @@ #define CLK_RST_CONTROLLER_UTMIP_PLL_CFG2 0x488 #define CLK_RST_CONTROLLER_PLLE_AUX 0x48C #define CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S0 0x4A0 +#define CLK_RST_CONTROLLER_UTMIP_PLL_CFG3 0x4C0 #define CLK_RST_CONTROLLER_PLLX_MISC_3 0x518 #define CLK_RST_CONTROLLER_UTMIPLL_HW_PWRDN_CFG0 0x52C #define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRE 0x554 @@ -140,6 +142,9 @@ #define CLK_RST_CONTROLLER_PLLC_MISC_2 0x5D0 #define CLK_RST_CONTROLLER_PLLC4_OUT 0x5E4 #define CLK_RST_CONTROLLER_PLLMB_BASE 0x5E8 +#define CLK_RST_CONTROLLER_CLK_SOURCE_XUSB_FS 0x608 +#define CLK_RST_CONTROLLER_CLK_SOURCE_XUSB_CORE_DEV 0x60C +#define CLK_RST_CONTROLLER_CLK_SOURCE_XUSB_SS 0x610 #define CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP 0x620 #define CLK_RST_CONTROLLER_CLK_SOURCE_I2C6 0x65C #define CLK_RST_CONTROLLER_CLK_SOURCE_EMC_DLL 0x664 @@ -153,23 +158,288 @@ #define CLK_NO_SOURCE 0x0 /*! PLL control and status bits */ -#define PLLCX_BASE_ENABLE (1 << 30) -#define PLLCX_BASE_REF_DIS (1 << 29) -#define PLLCX_BASE_LOCK (1 << 27) +#define PLLCX_BASE_LOCK BIT(27) +#define PLLCX_BASE_REF_DIS BIT(29) +#define PLLCX_BASE_ENABLE BIT(30) -#define PLLA_BASE_IDDQ (1 << 25) -#define PLLA_OUT0_CLKEN (1 << 1) -#define PLLA_OUT0_RSTN_CLR (1 << 0) +#define PLLA_OUT0_RSTN_CLR BIT(0) +#define PLLA_OUT0_CLKEN BIT(1) +#define PLLA_BASE_IDDQ BIT(25) -#define PLLC_MISC_RESET (1 << 30) -#define PLLC_MISC1_IDDQ (1 << 27) -#define PLLC_OUT1_CLKEN (1 << 1) -#define PLLC_OUT1_RSTN_CLR (1 << 0) +#define PLLC_OUT1_RSTN_CLR BIT(0) +#define PLLC_OUT1_CLKEN BIT(1) +#define PLLC_MISC1_IDDQ BIT(27) +#define PLLC_MISC_RESET BIT(30) -#define PLLC4_MISC_EN_LCKDET (1 << 30) -#define PLLC4_BASE_IDDQ (1 << 18) -#define PLLC4_OUT3_CLKEN (1 << 1) -#define PLLC4_OUT3_RSTN_CLR (1 << 0) +#define PLLC4_OUT3_RSTN_CLR BIT(0) +#define PLLC4_OUT3_CLKEN BIT(1) +#define PLLC4_BASE_IDDQ BIT(18) +#define PLLC4_MISC_EN_LCKDET BIT(30) + +#define UTMIPLL_LOCK BIT(31) + +/* + * CLOCK Peripherals: + * L 0 - 31 + * H 32 - 63 + * U 64 - 95 + * V 96 - 127 + * W 128 - 159 + * X 160 - 191 + * Y 192 - 223 + */ + +enum CLK_L_DEV +{ + CLK_L_CPU = 0, // Only reset. Deprecated. + CLK_L_BPMP = 1, // Only reset. + CLK_L_SYS = 2, // Only reset. + CLK_L_ISPB = 3, + CLK_L_RTC = 4, + CLK_L_TMR = 5, + CLK_L_UARTA = 6, + CLK_L_UARTB = 7, + CLK_L_GPIO = 8, + CLK_L_SDMMC2 = 9, + CLK_L_SPDIF = 10, + CLK_L_I2S2 = 11, // I2S1 + CLK_L_I2C1 = 12, + CLK_L_NDFLASH = 13, // HIDDEN. + CLK_L_SDMMC1 = 14, + CLK_L_SDMMC4 = 15, + CLK_L_TWC = 16, // HIDDEN. + CLK_L_PWM = 17, + CLK_L_I2S3 = 18, + CLK_L_EPP = 19, // HIDDEN. + CLK_L_VI = 20, + CLK_L_2D = 21, // HIDDEN. + CLK_L_USBD = 22, + CLK_L_ISP = 23, + CLK_L_3D = 24, // HIDDEN. + //CLK_L_ = 25, + CLK_L_DISP2 = 26, + CLK_L_DISP1 = 27, + CLK_L_HOST1X = 28, + CLK_L_VCP = 29, // HIDDEN. + CLK_L_I2S1 = 30, // I2S0 + CLK_L_BPMP_CACHE_CTRL = 31, // CONTROLLER +}; + +enum CLK_H_DEV +{ + CLK_H_MEM = 0, // MC. + CLK_H_AHBDMA = 1, + CLK_H_APBDMA = 2, + //CLK_H_ = 3, + CLK_H_KBC = 4, // HIDDEN. + CLK_H_STAT_MON = 5, + CLK_H_PMC = 6, + CLK_H_FUSE = 7, + CLK_H_KFUSE = 8, + CLK_H_SPI1 = 9, + CLK_H_SNOR = 10, // HIDDEN. + CLK_H_JTAG2TBC = 11, + CLK_H_SPI2 = 12, + CLK_H_XIO = 13, // HIDDEN. + CLK_H_SPI3 = 14, + CLK_H_I2C5 = 15, + CLK_H_DSI = 16, + //CLK_H_ = 17, + CLK_H_HSI = 18, // HIDDEN. + CLK_H_HDMI = 19, // HIDDEN. + CLK_H_CSI = 20, + //CLK_H_ = 21, + CLK_H_I2C2 = 22, + CLK_H_UARTC = 23, + CLK_H_MIPI_CAL = 24, + CLK_H_EMC = 25, + CLK_H_USB2 = 26, + CLK_H_USB3 = 27, // HIDDEN. + CLK_H_MPE = 28, // HIDDEN. + CLK_H_VDE = 29, // HIDDEN. + CLK_H_BSEA = 30, // HIDDEN. + CLK_H_BSEV = 31, +}; + +enum CLK_U_DEV +{ + //CLK_U_ = 0, + CLK_U_UARTD = 1, + CLK_U_UARTE = 2, // HIDDEN. + CLK_U_I2C3 = 3, + CLK_U_SPI4 = 4, + CLK_U_SDMMC3 = 5, + CLK_U_PCIE = 6, + CLK_U_UNUSED = 7, // RESERVED + CLK_U_AFI = 8, + CLK_U_CSITE = 9, + CLK_U_PCIEXCLK = 10, // Only reset. + CLK_U_BPMPUCQ = 11, // HIDDEN. + CLK_U_LA = 12, + CLK_U_TRACECLKIN = 13, // HIDDEN. + CLK_U_SOC_THERM = 14, + CLK_U_DTV = 15, + CLK_U_NAND_SPEED = 16, // HIDDEN. + CLK_U_I2C_SLOW = 17, + CLK_U_DSIB = 18, + CLK_U_TSEC = 19, + CLK_U_IRAMA = 20, + CLK_U_IRAMB = 21, + CLK_U_IRAMC = 22, + CLK_U_IRAMD = 23, // EMUCIF ON RESET + CLK_U_BPMP_CACHE_RAM = 24, + CLK_U_XUSB_HOST = 25, + CLK_U_CLK_M_DOUBLER = 26, + CLK_U_MSENC = 27, // HIDDEN. + CLK_U_SUS_OUT = 28, + CLK_U_DEV2_OUT = 29, + CLK_U_DEV1_OUT = 30, + CLK_U_XUSB_DEV = 31, +}; + +enum CLK_V_DEV +{ + CLK_V_CPUG = 0, + CLK_V_CPULP = 1, // Reserved. + CLK_V_3D2 = 2, // HIDDEN. + CLK_V_MSELECT = 3, + CLK_V_TSENSOR = 4, + CLK_V_I2S4 = 5, + CLK_V_I2S5 = 6, + CLK_V_I2C4 = 7, + CLK_V_SPI5 = 8, // HIDDEN. + CLK_V_SPI6 = 9, // HIDDEN. + CLK_V_AHUB = 10, // AUDIO. + CLK_V_APB2APE = 11, // APBIF. + CLK_V_DAM0 = 12, // HIDDEN. + CLK_V_DAM1 = 13, // HIDDEN. + CLK_V_DAM2 = 14, // HIDDEN. + CLK_V_HDA2CODEC_2X = 15, + CLK_V_ATOMICS = 16, + //CLK_V_ = 17, + //CLK_V_ = 18, + //CLK_V_ = 19, + //CLK_V_ = 20, + //CLK_V_ = 21, + CLK_V_SPDIF_DOUBLER = 22, + CLK_V_ACTMON = 23, + CLK_V_EXTPERIPH1 = 24, + CLK_V_EXTPERIPH2 = 25, + CLK_V_EXTPERIPH3 = 26, + CLK_V_SATA_OOB = 27, + CLK_V_SATA = 28, + CLK_V_HDA = 29, + CLK_V_TZRAM = 30, // HIDDEN. + CLK_V_SE = 31, // HIDDEN. +}; + +enum CLK_W_DEV +{ + CLK_W_HDA2HDMICODEC = 0, + CLK_W_RESERVED0 = 1, //satacoldrstn + CLK_W_PCIERX0 = 2, + CLK_W_PCIERX1 = 3, + CLK_W_PCIERX2 = 4, + CLK_W_PCIERX3 = 5, + CLK_W_PCIERX4 = 6, + CLK_W_PCIERX5 = 7, + CLK_W_CEC = 8, + CLK_W_PCIE2_IOBIST = 9, + CLK_W_EMC_IOBIST = 10, + CLK_W_HDMI_IOBIST = 11, // HIDDEN. + CLK_W_SATA_IOBIST = 12, + CLK_W_MIPI_IOBIST = 13, + CLK_W_XUSB_PADCTL = 14, // Only reset. + CLK_W_XUSB = 15, + CLK_W_CILAB = 16, + CLK_W_CILCD = 17, + CLK_W_CILEF = 18, + CLK_W_DSIA_LP = 19, + CLK_W_DSIB_LP = 20, + CLK_W_ENTROPY = 21, + CLK_W_DDS = 22, // HIDDEN. + //CLK_W_ = 23, + CLK_W_DP2 = 24, // HIDDEN. + CLK_W_AMX0 = 25, // HIDDEN. + CLK_W_ADX0 = 26, // HIDDEN. + CLK_W_DVFS = 27, + CLK_W_XUSB_SS = 28, + CLK_W_EMC_LATENCY = 29, + CLK_W_MC1 = 30, + //CLK_W_ = 31, +}; + +enum CLK_X_DEV +{ + CLK_X_SPARE = 0, + CLK_X_DMIC1 = 1, + CLK_X_DMIC2 = 2, + CLK_X_ETR = 3, + CLK_X_CAM_MCLK = 4, + CLK_X_CAM_MCLK2 = 5, + CLK_X_I2C6 = 6, + CLK_X_MC_CAPA = 7, // MC DAISY CHAIN1 + CLK_X_MC_CBPA = 8, // MC DAISY CHAIN2 + CLK_X_MC_CPU = 9, + CLK_X_MC_BBC = 10, + CLK_X_VIM2_CLK = 11, + //CLK_X_ = 12, + CLK_X_MIPIBIF = 13, //RESERVED + CLK_X_EMC_DLL = 14, + //CLK_X_ = 15, + CLK_X_HDMI_AUDIO = 16, // HIDDEN. + CLK_X_UART_FST_MIPI_CAL = 17, + CLK_X_VIC = 18, + //CLK_X_ = 19, + CLK_X_ADX1 = 20, // HIDDEN. + CLK_X_DPAUX = 21, + CLK_X_SOR0 = 22, + CLK_X_SOR1 = 23, + CLK_X_GPU = 24, + CLK_X_DBGAPB = 25, + CLK_X_HPLL_ADSP = 26, + CLK_X_PLLP_ADSP = 27, + CLK_X_PLLA_ADSP = 28, + CLK_X_PLLG_REF = 29, + //CLK_X_ = 30, + //CLK_X_ = 31, +}; + +enum CLK_Y_DEV +{ + CLK_Y_SPARE1 = 0, + CLK_Y_SDMMC_LEGACY_TM = 1, + CLK_Y_NVDEC = 2, + CLK_Y_NVJPG = 3, + CLK_Y_AXIAP = 4, + CLK_Y_DMIC3 = 5, + CLK_Y_APE = 6, + CLK_Y_ADSP = 7, + CLK_Y_MC_CDPA = 8, // MC DAISY CHAIN4 + CLK_Y_MC_CCPA = 9, // MC DAISY CHAIN3 + CLK_Y_MAUD = 10, + //CLK_Y_ = 11, + CLK_Y_SATA_USB_UPHY = 12, // Only reset. + CLK_Y_PEX_USB_UPHY = 13, // Only reset. + CLK_Y_TSECB = 14, + CLK_Y_DPAUX1 = 15, + CLK_Y_VI_I2C = 16, + CLK_Y_HSIC_TRK = 17, + CLK_Y_USB2_TRK = 18, + CLK_Y_QSPI = 19, + CLK_Y_UARTAPE = 20, + CLK_Y_ADSPINTF = 21, // Only reset. + CLK_Y_ADSPPERIPH = 22, // Only reset. + CLK_Y_ADSPDBG = 23, // Only reset. + CLK_Y_ADSPWDT = 24, // Only reset. + CLK_Y_ADSPSCU = 25, // Only reset. + CLK_Y_ADSPNEON = 26, + CLK_Y_NVENC = 27, + CLK_Y_IQC2 = 28, + CLK_Y_IQC1 = 29, + CLK_Y_SOR_SAFE = 30, + CLK_Y_PLLP_OUT_CPU = 31, +}; /*! Generic clock descriptor. */ typedef struct _clock_t @@ -215,6 +485,9 @@ void clock_enable_pwm(); void clock_disable_pwm(); 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 84c366d..62dba31 100644 --- a/bdk/soc/fuse.c +++ b/bdk/soc/fuse.c @@ -20,9 +20,9 @@ #include #include +#include #include - -#define ARRAYSIZE(x) (sizeof(x) / sizeof(*x)) +#include static const u32 evp_thunk_template[] = { 0xe92d0007, // STMFD SP!, {R0-R2} @@ -62,12 +62,48 @@ u32 fuse_read_odm(u32 idx) u32 fuse_read_odm_keygen_rev() { - if ((fuse_read_odm(4) & 0x800) && fuse_read_odm(0) == 0x8E61ECAE && fuse_read_odm(1) == 0xF2BA3BB2) + bool has_new_keygen; + + // Check if it has new keygen. + if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01) + has_new_keygen = true; + else + has_new_keygen = (fuse_read_odm(4) & 0x800) && fuse_read_odm(0) == 0x8E61ECAE && fuse_read_odm(1) == 0xF2BA3BB2; + + if (has_new_keygen) return (fuse_read_odm(2) & 0x1F); return 0; } +u32 fuse_read_hw_type() +{ + if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01) + { + switch ((fuse_read_odm(4) & 0xF0000) >> 16) + { + case 1: + return FUSE_NX_HW_TYPE_IOWA; + case 2: + return FUSE_NX_HW_TYPE_HOAG; + } + } + + return FUSE_NX_HW_TYPE_ICOSA; +} + +u8 fuse_count_burnt(u32 val) +{ + u8 burnt_fuses = 0; + for (u32 i = 0; i < 32; i++) + { + if ((val >> i) & 1) + burnt_fuses++; + } + + return burnt_fuses; +} + void fuse_wait_idle() { u32 ctrl; @@ -87,7 +123,9 @@ u32 fuse_read(u32 addr) void fuse_read_array(u32 *words) { - for (u32 i = 0; i < 192; i++) + u32 array_size = (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01) ? 256 : 192; + + for (u32 i = 0; i < array_size; i++) words[i] = fuse_read(i); } @@ -133,7 +171,7 @@ static int _patch_hash_one(u32 *word) { return 3; } - for (u32 i = 0; i < ARRAYSIZE(hash_vals); i++) + for (u32 i = 0; i < ARRAY_SIZE(hash_vals); i++) { if (hash_vals[i] == hash) { @@ -222,7 +260,7 @@ int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value)) while (word_count) { total_read += word_count; - if (total_read >= ARRAYSIZE(words)) + if (total_read >= ARRAY_SIZE(words)) { break; } @@ -279,7 +317,7 @@ int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len) while (word_count) { total_read += word_count; - if (total_read >= ARRAYSIZE(words)) + if (total_read >= ARRAY_SIZE(words)) { break; } @@ -328,8 +366,8 @@ int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len) bool fuse_check_patched_rcm() { - // Check if XUSB in use. - if (FUSE(FUSE_RESERVED_SW) & (1<<7)) + // Check if XUSB in use or Tegra X1+. + if (FUSE(FUSE_RESERVED_SW) & (1<<7) || hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01) return true; // Check if RCM is ipatched. diff --git a/bdk/soc/fuse.h b/bdk/soc/fuse.h index e5ca2fb..d7d5c77 100644 --- a/bdk/soc/fuse.h +++ b/bdk/soc/fuse.h @@ -64,6 +64,7 @@ #define FUSE_OPT_X_COORDINATE 0x214 #define FUSE_OPT_Y_COORDINATE 0x218 #define FUSE_GPU_IDDQ_CALIB 0x228 +#define FUSE_RESERVED_ODM28 0x240 #define FUSE_USB_CALIB_EXT 0x350 /*! Fuse commands. */ @@ -75,12 +76,21 @@ /*! Fuse cache registers. */ #define FUSE_RESERVED_ODMX(x) (0x1C8 + 4 * (x)) +enum +{ + FUSE_NX_HW_TYPE_ICOSA, + FUSE_NX_HW_TYPE_IOWA, + FUSE_NX_HW_TYPE_HOAG +}; + void fuse_disable_program(); -u32 fuse_read_odm(u32 idx); -u32 fuse_read_odm_keygen_rev(); +u32 fuse_read_odm(u32 idx); +u32 fuse_read_odm_keygen_rev(); +u32 fuse_read_hw_type(); +u8 fuse_count_burnt(u32 val); void fuse_wait_idle(); -int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value)); -int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len); +int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value)); +int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len); void fuse_read_array(u32 *words); bool fuse_check_patched_rcm(); diff --git a/bdk/soc/gpio.c b/bdk/soc/gpio.c index 281e867..5cd2ccd 100644 --- a/bdk/soc/gpio.c +++ b/bdk/soc/gpio.c @@ -18,23 +18,23 @@ #include #include -#define GPIO_BANK_IDX(port) (port >> 2) +#define GPIO_BANK_IDX(port) ((port) >> 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 + (((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_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 + (((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_IRQ_BANK1 32 #define GPIO_IRQ_BANK2 33 diff --git a/bdk/soc/gpio.h b/bdk/soc/gpio.h index 99aed88..0c92b14 100644 --- a/bdk/soc/gpio.h +++ b/bdk/soc/gpio.h @@ -41,14 +41,14 @@ #define GPIO_ANY_EDGE_CHANGE 1 /*! GPIO pins (0-7 for each port). */ -#define GPIO_PIN_0 (1 << 0) -#define GPIO_PIN_1 (1 << 1) -#define GPIO_PIN_2 (1 << 2) -#define GPIO_PIN_3 (1 << 3) -#define GPIO_PIN_4 (1 << 4) -#define GPIO_PIN_5 (1 << 5) -#define GPIO_PIN_6 (1 << 6) -#define GPIO_PIN_7 (1 << 7) +#define GPIO_PIN_0 BIT(0) +#define GPIO_PIN_1 BIT(1) +#define GPIO_PIN_2 BIT(2) +#define GPIO_PIN_3 BIT(3) +#define GPIO_PIN_4 BIT(4) +#define GPIO_PIN_5 BIT(5) +#define GPIO_PIN_6 BIT(6) +#define GPIO_PIN_7 BIT(7) /*! GPIO ports (A-EE). */ #define GPIO_PORT_A 0 diff --git a/bdk/soc/hw_init.c b/bdk/soc/hw_init.c index 7b7ca04..dd79dc6 100644 --- a/bdk/soc/hw_init.c +++ b/bdk/soc/hw_init.c @@ -56,7 +56,15 @@ extern volatile nyx_storage_t *nyx_str; * PCLK - 68MHz init (-> 136MHz -> OC/4). */ -void _config_oscillators() +u32 hw_get_chip_id() +{ + if (((APB_MISC(APB_MISC_GP_HIDREV) >> 4) & 0xF) >= GP_HIDREV_MAJOR_T210B01) + return GP_HIDREV_MAJOR_T210B01; + else + return GP_HIDREV_MAJOR_T210; +} + +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. @@ -73,35 +81,44 @@ void _config_oscillators() 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 SCLK div to 1. - CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20004444; // Set clk 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. } -void _config_gpios() +static void _config_gpios(bool nx_hoag) { - PINMUX_AUX(PINMUX_AUX_UART2_TX) = 0; - PINMUX_AUX(PINMUX_AUX_UART3_TX) = 0; + // Clamp inputs when tristated. + APB_MISC(APB_MISC_PP_PINMUX_GLOBAL) = 0; + + if (!nx_hoag) + { + 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); + } // Set Joy-Con IsAttached direction. PINMUX_AUX(PINMUX_AUX_GPIO_PE6) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE; PINMUX_AUX(PINMUX_AUX_GPIO_PH6) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE; - // Set pin mode for Joy-Con IsAttached and 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 // 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 and 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); + // 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); @@ -120,27 +137,28 @@ void _config_gpios() // gpio_config(GPIO_PORT_Y, GPIO_PIN_1, GPIO_MODE_GPIO); } -void _config_pmc_scratch() +static void _config_pmc_scratch() { - PMC(APBDEV_PMC_SCRATCH20) &= 0xFFF3FFFF; // Unset Debug console from Customer Option. + 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_SECURE_SCRATCH21) |= PMC_FUSE_PRIVATEKEYDISABLE_TZ_STICKY_BIT; } -void _mbist_workaround() +static void _mbist_workaround() { - CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= (1 << 10); // Enable AHUB clock. - CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= (1 << 6); // Enable APE clock. + // Make sure Audio clocks are enabled before accessing I2S. + CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= BIT(CLK_V_AHUB); + CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= BIT(CLK_Y_APE); // Set mux output to SOR1 clock switch. CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SOR1) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SOR1) | 0x8000) & 0xFFFFBFFF; // Enabled PLLD and set csi to PLLD for test pattern generation. CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) |= 0x40800000; - // Clear per-clock resets. - CLOCK(CLK_RST_CONTROLLER_RST_DEV_Y_CLR) = 0x40; // Clear reset APE. - CLOCK(CLK_RST_CONTROLLER_RST_DEV_X_CLR) = 0x40000; // Clear reset VIC. - CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = 0x18000000; // Clear reset DISP1, HOST1X. + // Clear per-clock resets for APE/VIC/HOST1X/DISP1. + CLOCK(CLK_RST_CONTROLLER_RST_DEV_Y_CLR) = BIT(CLK_Y_APE); + CLOCK(CLK_RST_CONTROLLER_RST_DEV_X_CLR) = BIT(CLK_X_VIC); + CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = BIT(CLK_L_HOST1X) | BIT(CLK_L_DISP1); usleep(2); // I2S channels to master and disable SLCG. @@ -159,20 +177,59 @@ void _mbist_workaround() VIC(0x8C) = 0xFFFFFFFF; usleep(2); - // Set per-clock reset. - CLOCK(CLK_RST_CONTROLLER_RST_DEV_Y_SET) = 0x40; // Set reset APE. - CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = 0x18000000; // Set reset DISP1, HOST1x. - CLOCK(CLK_RST_CONTROLLER_RST_DEV_X_SET) = 0x40000; // Set reset VIC. + // Set per-clock reset for APE/VIC/HOST1X/DISP1. + CLOCK(CLK_RST_CONTROLLER_RST_DEV_Y_SET) = BIT(CLK_Y_APE); + CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_HOST1X) | BIT(CLK_L_DISP1); + CLOCK(CLK_RST_CONTROLLER_RST_DEV_X_SET) = BIT(CLK_X_VIC); // Enable specific clocks and disable all others. - CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) = 0xC0; // Enable clock PMC, FUSE. - CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) = 0x80000130; // Enable clock RTC, TMR, GPIO, BPMP_CACHE. - //CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) = 0x80400130; // Keep USBD ON. - CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_U) = 0x1F00200; // Enable clock CSITE, IRAMA, IRAMB, IRAMC, IRAMD, BPMP_CACHE_RAM. - CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) = 0x80400808; // Enable clock MSELECT, APB2APE, SPDIF_DOUBLER, SE. - CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_W) = 0x402000FC; // Enable clock PCIERX0, PCIERX1, PCIERX2, PCIERX3, PCIERX4, PCIERX5, ENTROPY, MC1. - CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_X) = 0x23000780; // Enable clock MC_CAPA, MC_CAPB, MC_CPU, MC_BBC, DBGAPB, HPLL_ADSP, PLLG_REF. - CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) = 0x300; // Enable clock MC_CDPA, MC_CCPA. + // CLK L Devices. + CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) = + BIT(CLK_H_PMC) | + BIT(CLK_H_FUSE); + // CLK H Devices. + CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) = + BIT(CLK_L_RTC) | + BIT(CLK_L_TMR) | + BIT(CLK_L_GPIO) | + BIT(CLK_L_BPMP_CACHE_CTRL); + // CLK U Devices. + CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_U) = + BIT(CLK_U_CSITE) | + BIT(CLK_U_IRAMA) | + BIT(CLK_U_IRAMB) | + BIT(CLK_U_IRAMC) | + BIT(CLK_U_IRAMD) | + BIT(CLK_U_BPMP_CACHE_RAM); + // CLK V Devices. + CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) = + BIT(CLK_V_MSELECT) | + BIT(CLK_V_APB2APE) | + BIT(CLK_V_SPDIF_DOUBLER) | + BIT(CLK_V_SE); + // CLK W Devices. + CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_W) = + BIT(CLK_W_PCIERX0) | + BIT(CLK_W_PCIERX1) | + BIT(CLK_W_PCIERX2) | + BIT(CLK_W_PCIERX3) | + BIT(CLK_W_PCIERX4) | + BIT(CLK_W_PCIERX5) | + BIT(CLK_W_ENTROPY) | + BIT(CLK_W_MC1); + // CLK X Devices. + CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_X) = + BIT(CLK_X_MC_CAPA) | + BIT(CLK_X_MC_CBPA) | + BIT(CLK_X_MC_CPU) | + BIT(CLK_X_MC_BBC) | + BIT(CLK_X_GPU) | + BIT(CLK_X_DBGAPB) | + BIT(CLK_X_PLLG_REF); + // CLK Y Devices. + CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) = + BIT(CLK_Y_MC_CDPA) | + BIT(CLK_Y_MC_CCPA); // Disable clock gate overrides. CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRA) = 0; @@ -182,20 +239,21 @@ void _mbist_workaround() CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRE) = 0; // 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_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_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. } -void _config_se_brom() +static void _config_se_brom() { // Enable fuse clock. clock_enable_fuse(true); // Skip SBK/SSK if sept was run. - if (!(b_cfg.boot_cfg & BOOT_CFG_SEPT_RUN)) + bool sbk_skip = b_cfg.boot_cfg & BOOT_CFG_SEPT_RUN || FUSE(FUSE_PRIVATE_KEY0) == 0xFFFFFFFF; + if (!sbk_skip) { // Bootrom part we skipped. u32 sbk[4] = { @@ -225,115 +283,145 @@ void _config_se_brom() APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) = (APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) & 0xF0) | (7 << 10); } -void _config_regulators() +static void _config_regulators(bool tegra_t210) { // Disable low battery shutdown monitor. max77620_low_battery_monitor_config(false); // Disable SDMMC1 IO power. - gpio_output_enable(GPIO_PORT_E, GPIO_PIN_4, GPIO_OUTPUT_DISABLE); + gpio_write(GPIO_PORT_E, GPIO_PIN_4, GPIO_LOW); max77620_regulator_enable(REGULATOR_LDO2, 0); sd_power_cycle_time_start = get_tmr_ms(); 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, - (1 << 6) | (3 << MAX77620_ONOFFCNFG1_MRT_SHIFT)); // PWR delay for forced shutdown off. + BIT(6) | (3 << MAX77620_ONOFFCNFG1_MRT_SHIFT)); // PWR delay for forced shutdown off. - // Configure all Flexible Power Sequencers. - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_CFG0, - (7 << MAX77620_FPS_TIME_PERIOD_SHIFT)); - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_CFG1, - (7 << MAX77620_FPS_TIME_PERIOD_SHIFT) | (1 << MAX77620_FPS_EN_SRC_SHIFT)); - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_CFG2, - (7 << MAX77620_FPS_TIME_PERIOD_SHIFT)); - max77620_regulator_config_fps(REGULATOR_LDO4); - max77620_regulator_config_fps(REGULATOR_LDO8); - max77620_regulator_config_fps(REGULATOR_SD0); - max77620_regulator_config_fps(REGULATOR_SD1); - max77620_regulator_config_fps(REGULATOR_SD3); + if (tegra_t210) + { + // Configure all Flexible Power Sequencers for MAX77620. + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_CFG0, (7 << MAX77620_FPS_TIME_PERIOD_SHIFT)); + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_CFG1, (7 << MAX77620_FPS_TIME_PERIOD_SHIFT) | (1 << MAX77620_FPS_EN_SRC_SHIFT)); + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_CFG2, (7 << MAX77620_FPS_TIME_PERIOD_SHIFT)); + max77620_regulator_config_fps(REGULATOR_LDO4); + max77620_regulator_config_fps(REGULATOR_LDO8); + max77620_regulator_config_fps(REGULATOR_SD0); + max77620_regulator_config_fps(REGULATOR_SD1); + max77620_regulator_config_fps(REGULATOR_SD3); - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_GPIO3, - (4 << MAX77620_FPS_TIME_PERIOD_SHIFT) | (2 << MAX77620_FPS_PD_PERIOD_SHIFT)); // 3.x+ + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_GPIO3, + (4 << MAX77620_FPS_TIME_PERIOD_SHIFT) | (2 << MAX77620_FPS_PD_PERIOD_SHIFT)); // 3.x+ - // Set vdd_core voltage to 1.125V. - max77620_regulator_set_voltage(REGULATOR_SD0, 1125000); + // Set vdd_core voltage to 1.125V. + max77620_regulator_set_voltage(REGULATOR_SD0, 1125000); - // Fix CPU/GPU after a L4T warmboot. - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO5, 2); - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO6, 2); + // Fix CPU/GPU after a L4T warmboot. + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO5, 2); + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO6, 2); - i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_REG, MAX77621_VOUT_0_95V); // Disable power. - i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_DVS_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_1_09V); // Enable DVS power. - i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL1_REG, MAX77621_RAMP_50mV_PER_US); - i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL2_REG, - MAX77621_T_JUNCTION_120 | MAX77621_FT_ENABLE | MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS | - MAX77621_CKKADV_TRIP_150mV_PER_US | MAX77621_INDUCTOR_NOMINAL); + i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_REG, MAX77621_VOUT_0_95V); // Disable power. + i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_DVS_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_1_09V); // Enable DVS power. + i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL1_REG, MAX77621_RAMP_50mV_PER_US); + i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL2_REG, + MAX77621_T_JUNCTION_120 | MAX77621_FT_ENABLE | MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS | + MAX77621_CKKADV_TRIP_150mV_PER_US | MAX77621_INDUCTOR_NOMINAL); - i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_VOUT_REG, MAX77621_VOUT_0_95V); // Disable power. - i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_VOUT_DVS_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_1_09V); // Enable DVS power. - i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_CONTROL1_REG, MAX77621_RAMP_50mV_PER_US); - i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_CONTROL2_REG, - MAX77621_T_JUNCTION_120 | MAX77621_FT_ENABLE | MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS | - MAX77621_CKKADV_TRIP_150mV_PER_US | MAX77621_INDUCTOR_NOMINAL); + i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_VOUT_REG, MAX77621_VOUT_0_95V); // Disable power. + i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_VOUT_DVS_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_1_09V); // Enable DVS power. + i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_CONTROL1_REG, MAX77621_RAMP_50mV_PER_US); + i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_CONTROL2_REG, + MAX77621_T_JUNCTION_120 | MAX77621_FT_ENABLE | MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS | + MAX77621_CKKADV_TRIP_150mV_PER_US | MAX77621_INDUCTOR_NOMINAL); + } + else // Tegra X1+ set vdd_core voltage to 1.05V. + max77620_regulator_set_voltage(REGULATOR_SD0, 1050000); } -void config_hw() +void hw_init() { + // Get Chip ID. + 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; - _mbist_workaround(); + // Perform Memory Built-In Self Test WAR if T210. + if (tegra_t210) + _mbist_workaround(); + + // Enable Security Engine clock. clock_enable_se(); - // Enable fuse clock. + // Enable Fuse clock. clock_enable_fuse(true); - // Disable fuse programming. + // Disable Fuse programming. fuse_disable_program(); + // Enable clocks to Memory controllers and disable AHB redirect. mc_enable(); + // Initialize counters, CLKM, BPMP and other clocks based on 38.4MHz oscillator. _config_oscillators(); - APB_MISC(APB_MISC_PP_PINMUX_GLOBAL) = 0; - _config_gpios(); + + // Initialize pin configuration. + _config_gpios(nx_hoag); #ifdef DEBUG_UART_PORT clock_enable_uart(DEBUG_UART_PORT); uart_init(DEBUG_UART_PORT, 115200); #endif + // Enable Dynamic Voltage and Frequency Scaling device clock. clock_enable_cl_dvfs(); + // Enable clocks to I2C1 and I2CPWR. clock_enable_i2c(I2C_1); clock_enable_i2c(I2C_5); + // Enable clock to TZRAM. clock_enable_tzram(); - i2c_init(I2C_1); + // Initialize I2C5, mandatory for PMIC. i2c_init(I2C_5); + //! TODO: Why? Device is NFC MCU on Lite. + if (nx_hoag) + max77620_regulator_set_volt_and_flags(REGULATOR_LDO8, 2800000, MAX77620_POWER_MODE_NORMAL); + + // Initialize I2C1 for various power related devices. + i2c_init(I2C_1); + // Enable charger in case it's disabled. bq24193_enable_charger(); - _config_regulators(); + // Initialize various regulators based on Erista/Mariko platform. + _config_regulators(tegra_t210); _config_pmc_scratch(); // Missing from 4.x+ - CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003333; // Set SCLK to PLLP_OUT (408MHz). + // Set BPMP/SCLK to PLLP_OUT (408MHz). + CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003333; + // Disable TZRAM shutdown control and lock the regs. + if (!tegra_t210) + { + PMC(APBDEV_PMC_TZRAM_PWR_CNTRL) &= 0xFFFFFFFE; + PMC(APBDEV_PMC_TZRAM_NON_SEC_DISABLE) = 3; + PMC(APBDEV_PMC_TZRAM_SEC_DISABLE) = 3; + } + + // Initialize External memory controller and configure DRAM parameters. sdram_init(); bpmp_mmu_enable(); - mc_enable_ahb_redirect(); - - // Clear flags from PMC_SCRATCH0 - PMC(APBDEV_PMC_SCRATCH0) &= ~PMC_SCRATCH0_MODE_PAYLOAD; } -void reconfig_hw_workaround(bool extra_reconfig, u32 magic) +void hw_reinit_workaround(bool extra_reconfig, u32 magic) { // Disable BPMP max clock. bpmp_clk_rate_set(BPMP_CLK_NORMAL); @@ -354,8 +442,8 @@ void reconfig_hw_workaround(bool extra_reconfig, u32 magic) nyx_str->mtc_cfg.init_done = 0; // Re-enable clocks to Audio Processing Engine as a workaround to hanging. - CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= (1 << 10); // Enable AHUB clock. - CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= (1 << 6); // Enable APE clock. + 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 (extra_reconfig) { @@ -377,7 +465,7 @@ void reconfig_hw_workaround(bool extra_reconfig, u32 magic) // Enable clock to USBD and init SDMMC1 to avoid hangs with bad hw inits. if (magic == 0xBAADF00D) { - CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) |= (1 << 22); + 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(); diff --git a/bdk/soc/hw_init.h b/bdk/soc/hw_init.h index d19f271..ff9ae4a 100644 --- a/bdk/soc/hw_init.h +++ b/bdk/soc/hw_init.h @@ -20,7 +20,8 @@ #include -void config_hw(); -void reconfig_hw_workaround(bool extra_reconfig, u32 magic); +void hw_init(); +void hw_reinit_workaround(bool extra_reconfig, u32 magic); +u32 hw_get_chip_id(); #endif diff --git a/bdk/soc/i2c.c b/bdk/soc/i2c.c index d3f31e7..099a182 100644 --- a/bdk/soc/i2c.c +++ b/bdk/soc/i2c.c @@ -20,31 +20,98 @@ #include #include +#define I2C_PACKET_PROT_I2C BIT(4) +#define I2C_HEADER_CONT_XFER BIT(15) +#define I2C_HEADER_REP_START BIT(16) +#define I2C_HEADER_IE_ENABLE BIT(17) +#define I2C_HEADER_READ BIT(19) + +#define I2C_CNFG (0x00 / 4) +#define CMD1_WRITE (0 << 6) +#define CMD1_READ BIT(6) +#define NORMAL_MODE_GO BIT(9) +#define PACKET_MODE_GO BIT(10) +#define NEW_MASTER_FSM BIT(11) +#define DEBOUNCE_CNT_4T (2 << 12) + +#define I2C_CMD_ADDR0 (0x04 / 4) +#define ADDR0_WRITE 0 +#define ADDR0_READ 1 + +#define I2C_CMD_DATA1 (0x0C / 4) +#define I2C_CMD_DATA2 (0x10 / 4) + +#define I2C_STATUS (0x1C / 4) +#define I2C_STATUS_NOACK (0xF << 0) +#define I2C_STATUS_BUSY BIT(8) + +#define I2C_TX_FIFO (0x50 / 4) +#define I2C_RX_FIFO (0x54 / 4) + +#define I2C_FIFO_CONTROL (0x5C / 4) +#define RX_FIFO_FLUSH BIT(0) +#define TX_FIFO_FLUSH BIT(1) + +#define I2C_FIFO_STATUS (0x60 / 4) +#define RX_FIFO_FULL_CNT (0xF << 0) +#define TX_FIFO_EMPTY_CNT (0xF << 4) + +#define I2C_INT_EN (0x64 / 4) +#define I2C_INT_STATUS (0x68 / 4) +#define I2C_INT_SOURCE (0x70 / 4) +#define RX_FIFO_DATA_REQ BIT(0) +#define TX_FIFO_DATA_REQ BIT(1) +#define ARB_LOST BIT(2) +#define NO_ACK BIT(3) +#define RX_FIFO_UNDER BIT(4) +#define TX_FIFO_OVER BIT(5) +#define ALL_PACKETS_COMPLETE BIT(6) +#define PACKET_COMPLETE BIT(7) +#define BUS_CLEAR_DONE BIT(11) + +#define I2C_CLK_DIVISOR (0x6C / 4) + +#define I2C_BUS_CLEAR_CONFIG (0x84 / 4) +#define BC_ENABLE BIT(0) +#define BC_TERMINATE BIT(1) + +#define I2C_BUS_CLEAR_STATUS (0x88 / 4) + +#define I2C_CONFIG_LOAD (0x8C / 4) +#define MSTR_CONFIG_LOAD BIT(0) +#define TIMEOUT_CONFIG_LOAD BIT(2) + static const u32 i2c_addrs[] = { - 0x7000C000, 0x7000C400, 0x7000C500, - 0x7000C700, 0x7000D000, 0x7000D100 + 0x7000C000, // I2C_1. + 0x7000C400, // I2C_2. + 0x7000C500, // I2C_3. + 0x7000C700, // I2C_4. + 0x7000D000, // I2C_5. + 0x7000D100 // I2C_6. }; -static void _i2c_wait(vu32 *base) +static void _i2c_load_cfg_wait(vu32 *base) { - base[I2C_CONFIG_LOAD] = 0x25; + 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] & 1)) + if (!(base[I2C_CONFIG_LOAD] & MSTR_CONFIG_LOAD)) break; } } -static int _i2c_send_pkt(u32 idx, u32 x, u8 *buf, u32 size) +static int _i2c_send_single(u32 i2c_idx, u32 dev_addr, u8 *buf, u32 size) { if (size > 8) return 0; u32 tmp = 0; - vu32 *base = (vu32 *)i2c_addrs[idx]; - base[I2C_CMD_ADDR0] = x << 1; //Set x (send mode). + vu32 *base = (vu32 *)i2c_addrs[i2c_idx]; + + // Set device address and send mode. + base[I2C_CMD_ADDR0] = dev_addr << 1 | ADDR0_WRITE; if (size > 4) { @@ -60,44 +127,55 @@ static int _i2c_send_pkt(u32 idx, u32 x, u8 *buf, u32 size) base[I2C_CMD_DATA1] = tmp; //Set value. } - base[I2C_CNFG] = ((size - 1) << 1) | 0x2800; //Set size and send mode. - _i2c_wait(base); //Kick transaction. + // Set size and send mode. + base[I2C_CNFG] = ((size - 1) << 1) | DEBOUNCE_CNT_4T | NEW_MASTER_FSM | CMD1_WRITE; - base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFFDFF) | 0x200; + // Load configuration. + _i2c_load_cfg_wait(base); - u32 timeout = get_tmr_ms() + 1500; - while (base[I2C_STATUS] & 0x100) + // Initiate transaction on normal mode. + base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | NORMAL_MODE_GO; + + u32 timeout = get_tmr_ms() + 400; // Actual for max 8 bytes at 100KHz is 0.74ms. + while (base[I2C_STATUS] & I2C_STATUS_BUSY) { if (get_tmr_ms() > timeout) return 0; } - if (base[I2C_STATUS] << 28) + if (base[I2C_STATUS] & I2C_STATUS_NOACK) return 0; return 1; } -static int _i2c_recv_pkt(u32 idx, u8 *buf, u32 size, u32 x) +static int _i2c_recv_single(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr) { if (size > 8) return 0; - vu32 *base = (vu32 *)i2c_addrs[idx]; - base[I2C_CMD_ADDR0] = (x << 1) | 1; // Set x (recv mode). - base[I2C_CNFG] = ((size - 1) << 1) | 0x2840; // Set size and recv mode. - _i2c_wait(base); // Kick transaction. + vu32 *base = (vu32 *)i2c_addrs[i2c_idx]; - base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFFDFF) | 0x200; + // Set device address and recv mode. + base[I2C_CMD_ADDR0] = (dev_addr << 1) | ADDR0_READ; - u32 timeout = get_tmr_ms() + 1500; - while (base[I2C_STATUS] & 0x100) + // Set size and recv mode. + base[I2C_CNFG] = ((size - 1) << 1) | DEBOUNCE_CNT_4T | NEW_MASTER_FSM | CMD1_READ; + + // Load configuration. + _i2c_load_cfg_wait(base); + + // Initiate transaction on normal mode. + base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | NORMAL_MODE_GO; + + u32 timeout = get_tmr_ms() + 400; // Actual for max 8 bytes at 100KHz is 0.74ms. + while (base[I2C_STATUS] & I2C_STATUS_BUSY) { if (get_tmr_ms() > timeout) return 0; } - if (base[I2C_STATUS] << 28) + if (base[I2C_STATUS] & I2C_STATUS_NOACK) return 0; u32 tmp = base[I2C_CMD_DATA1]; // Get LS value. @@ -113,60 +191,234 @@ static int _i2c_recv_pkt(u32 idx, u8 *buf, u32 size, u32 x) return 1; } -void i2c_init(u32 idx) +static int _i2c_send_pkt(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr) { - vu32 *base = (vu32 *)i2c_addrs[idx]; + if (size > 32) + return 0; - base[I2C_CLK_DIVISOR_REGISTER] = 0x50001; - base[I2C_BUS_CLEAR_CONFIG] = 0x90003; - _i2c_wait(base); + int res = 0; + + vu32 *base = (vu32 *)i2c_addrs[i2c_idx]; + + // Enable interrupts. + base[I2C_INT_EN] = ALL_PACKETS_COMPLETE | PACKET_COMPLETE | NO_ACK | + 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 recv mode. + base[I2C_CNFG] = DEBOUNCE_CNT_4T | NEW_MASTER_FSM | CMD1_WRITE; + + // Set and flush FIFO. + base[I2C_FIFO_CONTROL] = RX_FIFO_FLUSH | TX_FIFO_FLUSH; + + // Load configuration. + _i2c_load_cfg_wait(base); + + // Initiate transaction on packet mode. + base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | PACKET_MODE_GO; + + u32 hdr[3]; + hdr[0] = I2C_PACKET_PROT_I2C; + hdr[1] = size - 1; + hdr[2] = I2C_HEADER_IE_ENABLE | I2C_HEADER_CONT_XFER | (dev_addr << 1); + + // Send header with request. + base[I2C_TX_FIFO] = hdr[0]; + base[I2C_TX_FIFO] = hdr[1]; + base[I2C_TX_FIFO] = hdr[2]; + + u32 timeout = get_tmr_ms() + 400; + while (size) + { + if (base[I2C_FIFO_STATUS] & TX_FIFO_EMPTY_CNT) + { + u32 tmp = 0; + u32 snd_size = MIN(size, 4); + memcpy(&tmp, buf, snd_size); + base[I2C_TX_FIFO] = tmp; + buf += snd_size; + size -= snd_size; + } + + if (get_tmr_ms() > timeout) + { + res = 1; + break; + } + } + + if (base[I2C_STATUS] & I2C_STATUS_NOACK || base[I2C_INT_STATUS] & NO_ACK) + res = 1; + + // Disable packet mode. + usleep(20); + base[I2C_CNFG] &= 0xFFFFF9FF; + + // Disable interrupts. + base[I2C_INT_EN] = 0; + + return res; +} + +static int _i2c_recv_pkt(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr, u32 reg) +{ + if (size > 32) + return 0; + + int res = 0; + + vu32 *base = (vu32 *)i2c_addrs[i2c_idx]; + + // Enable interrupts. + base[I2C_INT_EN] = ALL_PACKETS_COMPLETE | PACKET_COMPLETE | NO_ACK | + ARB_LOST | TX_FIFO_OVER | RX_FIFO_UNDER | RX_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 recv mode. + base[I2C_CNFG] = DEBOUNCE_CNT_4T | NEW_MASTER_FSM | CMD1_READ; + + // Set and flush FIFO. + base[I2C_FIFO_CONTROL] = RX_FIFO_FLUSH | TX_FIFO_FLUSH; + + // Load configuration. + _i2c_load_cfg_wait(base); + + // Initiate transaction on packet mode. + base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | PACKET_MODE_GO; + + // Send reg request. + u32 hdr[3]; + hdr[0] = I2C_PACKET_PROT_I2C; + hdr[1] = 1 - 1; + hdr[2] = I2C_HEADER_REP_START | (dev_addr << 1); + + // Send header with reg request. + base[I2C_TX_FIFO] = hdr[0]; + base[I2C_TX_FIFO] = hdr[1]; + base[I2C_TX_FIFO] = hdr[2]; + base[I2C_TX_FIFO] = reg; + + u32 timeout = get_tmr_ms() + 400; + while (!(base[I2C_FIFO_STATUS] & TX_FIFO_EMPTY_CNT)) + if (get_tmr_ms() > timeout) + break; + + // Send read request. + hdr[1] = size - 1; + hdr[2] = I2C_HEADER_READ | (dev_addr << 1); + + // Send header with read request. + base[I2C_TX_FIFO] = hdr[0]; + base[I2C_TX_FIFO] = hdr[1]; + base[I2C_TX_FIFO] = hdr[2]; + + timeout = get_tmr_ms() + 400; + while (size) + { + if (base[I2C_FIFO_STATUS] & RX_FIFO_FULL_CNT) + { + u32 rcv_size = MIN(size, 4); + u32 tmp = base[I2C_RX_FIFO]; + memcpy(buf, &tmp, rcv_size); + buf += rcv_size; + size -= rcv_size; + } + + if (get_tmr_ms() > timeout) + { + res = 1; + break; + } + } + + if (base[I2C_STATUS] & I2C_STATUS_NOACK || base[I2C_INT_STATUS] & NO_ACK) + res = 1; + + // Disable packet mode. + usleep(20); + base[I2C_CNFG] &= 0xFFFFF9FF; + + // Disable interrupts. + base[I2C_INT_EN] = 0; + + return res; +} + +void i2c_init(u32 i2c_idx) +{ + vu32 *base = (vu32 *)i2c_addrs[i2c_idx]; + + base[I2C_CLK_DIVISOR] = (5 << 16) | 1; // SF mode Div: 6, HS mode div: 2. + base[I2C_BUS_CLEAR_CONFIG] = (9 << 16) | BC_TERMINATE | BC_ENABLE; + + // Load configuration. + _i2c_load_cfg_wait(base); for (u32 i = 0; i < 10; i++) { usleep(20000); - if (base[INTERRUPT_STATUS_REGISTER] & 0x800) + if (base[I2C_INT_STATUS] & BUS_CLEAR_DONE) break; } (vu32)base[I2C_BUS_CLEAR_STATUS]; - base[INTERRUPT_STATUS_REGISTER] = base[INTERRUPT_STATUS_REGISTER]; + base[I2C_INT_STATUS] = base[I2C_INT_STATUS]; } -int i2c_send_buf_small(u32 idx, u32 x, u32 y, u8 *buf, u32 size) +int i2c_recv_buf(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr) +{ + return _i2c_recv_single(i2c_idx, buf, size, dev_addr); +} + +int i2c_send_buf_big(u32 i2c_idx, u32 dev_addr, u8 *buf, u32 size) +{ + if (size > 32) + return 0; + + return _i2c_send_pkt(i2c_idx, buf, size, dev_addr); +} + +int i2c_recv_buf_big(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr, u32 reg) +{ + return _i2c_recv_pkt(i2c_idx, buf, size, dev_addr, reg); +} + +int i2c_send_buf_small(u32 i2c_idx, u32 dev_addr, u32 reg, u8 *buf, u32 size) { u8 tmp[4]; if (size > 7) return 0; - tmp[0] = y; + tmp[0] = reg; memcpy(tmp + 1, buf, size); - return _i2c_send_pkt(idx, x, tmp, size + 1); + return _i2c_send_single(i2c_idx, dev_addr, tmp, size + 1); } -int i2c_recv_buf(u8 *buf, u32 size, u32 idx, u32 x) +int i2c_recv_buf_small(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr, u32 reg) { - return _i2c_recv_pkt(idx, buf, size, x); -} - -int i2c_recv_buf_small(u8 *buf, u32 size, u32 idx, u32 x, u32 y) -{ - int res = _i2c_send_pkt(idx, x, (u8 *)&y, 1); + int res = _i2c_send_single(i2c_idx, dev_addr, (u8 *)®, 1); if (res) - res = _i2c_recv_pkt(idx, buf, size, x); + res = _i2c_recv_single(i2c_idx, buf, size, dev_addr); return res; } -int i2c_send_byte(u32 idx, u32 x, u32 y, u8 b) +int i2c_send_byte(u32 i2c_idx, u32 dev_addr, u32 reg, u8 val) { - return i2c_send_buf_small(idx, x, y, &b, 1); + return i2c_send_buf_small(i2c_idx, dev_addr, reg, &val, 1); } -u8 i2c_recv_byte(u32 idx, u32 x, u32 y) +u8 i2c_recv_byte(u32 i2c_idx, u32 dev_addr, u32 reg) { u8 tmp = 0; - i2c_recv_buf_small(&tmp, 1, idx, x, y); + i2c_recv_buf_small(&tmp, 1, i2c_idx, dev_addr, reg); return tmp; } diff --git a/bdk/soc/i2c.h b/bdk/soc/i2c.h index a630b15..a04eec1 100644 --- a/bdk/soc/i2c.h +++ b/bdk/soc/i2c.h @@ -27,22 +27,13 @@ #define I2C_5 4 #define I2C_6 5 -#define I2C_CNFG 0x00 -#define I2C_CMD_ADDR0 0x01 -#define I2C_CMD_DATA1 0x03 -#define I2C_CMD_DATA2 0x04 -#define I2C_STATUS 0x07 -#define INTERRUPT_STATUS_REGISTER 0x1A -#define I2C_CLK_DIVISOR_REGISTER 0x1B -#define I2C_BUS_CLEAR_CONFIG 0x21 -#define I2C_BUS_CLEAR_STATUS 0x22 -#define I2C_CONFIG_LOAD 0x23 - -void i2c_init(u32 idx); -int i2c_send_buf_small(u32 idx, u32 x, u32 y, u8 *buf, u32 size); -int i2c_recv_buf(u8 *buf, u32 size, u32 idx, u32 x); -int i2c_recv_buf_small(u8 *buf, u32 size, u32 idx, u32 x, u32 y); -int i2c_send_byte(u32 idx, u32 x, u32 y, u8 b); -u8 i2c_recv_byte(u32 idx, u32 x, u32 y); +void i2c_init(u32 i2c_idx); +int i2c_recv_buf(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr); +int i2c_send_buf_big(u32 i2c_idx, u32 dev_addr, u8 *buf, u32 size); +int i2c_recv_buf_big(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr, u32 reg); +int i2c_send_buf_small(u32 i2c_idx, u32 dev_addr, u32 reg, u8 *buf, u32 size); +int i2c_recv_buf_small(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr, u32 reg); +int i2c_send_byte(u32 i2c_idx, u32 dev_addr, u32 reg, u8 val); +u8 i2c_recv_byte(u32 i2c_idx, u32 dev_addr, u32 reg); #endif diff --git a/bdk/soc/irq.c b/bdk/soc/irq.c index cb34d12..4fb39ca 100644 --- a/bdk/soc/irq.c +++ b/bdk/soc/irq.c @@ -47,10 +47,10 @@ static void _irq_enable_source(u32 irq) u32 bit = irq % 32; // Set as normal IRQ. - ICTLR(ctrl_idx, PRI_ICTLR_COP_IEP_CLASS) &= ~(1 << bit); + ICTLR(ctrl_idx, PRI_ICTLR_COP_IEP_CLASS) &= ~BIT(bit); // Enable IRQ source. - ICTLR(ctrl_idx, PRI_ICTLR_COP_IER_SET) = 1 << bit; + ICTLR(ctrl_idx, PRI_ICTLR_COP_IER_SET) = BIT(bit); } static void _irq_disable_source(u32 irq) @@ -59,7 +59,7 @@ static void _irq_disable_source(u32 irq) u32 bit = irq % 32; // Disable IRQ source. - ICTLR(ctrl_idx, PRI_ICTLR_COP_IER_CLR) = 1 << bit; + ICTLR(ctrl_idx, PRI_ICTLR_COP_IER_CLR) = BIT(bit); } static void _irq_disable_and_ack_all() @@ -79,7 +79,7 @@ static void _irq_ack_source(u32 irq) u32 bit = irq % 32; // Force stop the interrupt as it's serviced here. - ICTLR(ctrl_idx, PRI_ICTLR_FIR_CLR) = 1 << bit; + ICTLR(ctrl_idx, PRI_ICTLR_FIR_CLR) = BIT(bit); } void irq_free(u32 irq) diff --git a/bdk/soc/irq.h b/bdk/soc/irq.h index d33ffbe..dbd5ee2 100644 --- a/bdk/soc/irq.h +++ b/bdk/soc/irq.h @@ -209,8 +209,8 @@ typedef enum _irq_status_t typedef enum _irq_flags_t { IRQ_FLAG_NONE = 0, - IRQ_FLAG_ONE_OFF = (1 << 0), - IRQ_FLAG_REPLACEABLE = (1 << 1) + IRQ_FLAG_ONE_OFF = BIT(0), + IRQ_FLAG_REPLACEABLE = BIT(1) } irq_flags_t; void irq_end(); diff --git a/bdk/soc/kfuse.h b/bdk/soc/kfuse.h index 099dcac..2cd290b 100644 --- a/bdk/soc/kfuse.h +++ b/bdk/soc/kfuse.h @@ -19,16 +19,16 @@ #include -#define KFUSE_STATE_SOFTRESET (1 << 31) -#define KFUSE_STATE_STOP (1 << 25) -#define KFUSE_STATE_RESTART (1 << 24) -#define KFUSE_STATE_CRCPASS (1 << 17) -#define KFUSE_STATE_DONE (1 << 16) -#define KFUSE_STATE_ERRBLOCK_MASK 0x3F00 -#define KFUSE_STATE_ERRBLOCK_SHIFT 8 #define KFUSE_STATE_CURBLOCK_MASK 0x3F +#define KFUSE_STATE_ERRBLOCK_SHIFT 8 +#define KFUSE_STATE_ERRBLOCK_MASK 0x3F00 +#define KFUSE_STATE_DONE BIT(16) +#define KFUSE_STATE_CRCPASS BIT(17) +#define KFUSE_STATE_RESTART BIT(24) +#define KFUSE_STATE_STOP BIT(25) +#define KFUSE_STATE_SOFTRESET BIT(31) -#define KFUSE_KEYADDR_AUTOINC (1<<16) +#define KFUSE_KEYADDR_AUTOINC BIT(16) #define KFUSE_STATE 0x80 #define KFUSE_KEYADDR 0x88 diff --git a/bdk/soc/pinmux.h b/bdk/soc/pinmux.h index 9a3ed5c..48fcab3 100644 --- a/bdk/soc/pinmux.h +++ b/bdk/soc/pinmux.h @@ -71,6 +71,18 @@ #define PINMUX_AUX_GPIO_PH6 0x250 #define PINMUX_AUX_GPIO_PK3 0x260 #define PINMUX_AUX_GPIO_PZ1 0x280 +/* Only in T210B01 */ +#define PINMUX_AUX_SDMMC2_DAT0 0x294 +#define PINMUX_AUX_SDMMC2_DAT1 0x298 +#define PINMUX_AUX_SDMMC2_DAT2 0x29C +#define PINMUX_AUX_SDMMC2_DAT3 0x2A0 +#define PINMUX_AUX_SDMMC2_DAT4 0x2A4 +#define PINMUX_AUX_SDMMC2_DAT5 0x2A8 +#define PINMUX_AUX_SDMMC2_DAT6 0x2AC +#define PINMUX_AUX_SDMMC2_DAT7 0x2B0 +#define PINMUX_AUX_SDMMC2_CLK 0x2B4 +#define PINMUX_AUX_SDMMC2_CMD 0x2BC + /*! 0:UART-A, 1:UART-B, 3:UART-C, 3:UART-D */ #define PINMUX_AUX_UARTX_TX(x) (0xE4 + 0x10 * (x)) #define PINMUX_AUX_UARTX_RX(x) (0xE8 + 0x10 * (x)) @@ -87,17 +99,18 @@ #define PINMUX_PULL_DOWN (1 << 2) #define PINMUX_PULL_UP (2 << 2) -#define PINMUX_TRISTATE (1 << 4) -#define PINMUX_PARKED (1 << 5) -#define PINMUX_INPUT_ENABLE (1 << 6) -#define PINMUX_LOCK (1 << 7) -#define PINMUX_LPDR (1 << 8) -#define PINMUX_HSM (1 << 9) +#define PINMUX_TRISTATE BIT(4) +#define PINMUX_PARKED BIT(5) +#define PINMUX_INPUT_ENABLE BIT(6) +#define PINMUX_LOCK BIT(7) +#define PINMUX_LPDR BIT(8) +#define PINMUX_HSM BIT(9) -#define PINMUX_IO_HV (1 << 10) -#define PINMUX_OPEN_DRAIN (1 << 11) -#define PINMUX_SCHMT (1 << 12) +#define PINMUX_IO_HV BIT(10) +#define PINMUX_OPEN_DRAIN BIT(11) +#define PINMUX_SCHMT BIT(12) +#define PINMUX_DRIVE_MASK (3 << 13) #define PINMUX_DRIVE_1X (0 << 13) #define PINMUX_DRIVE_2X (1 << 13) #define PINMUX_DRIVE_3X (2 << 13) diff --git a/bdk/soc/pmc.c b/bdk/soc/pmc.c new file mode 100644 index 0000000..62caa22 --- /dev/null +++ b/bdk/soc/pmc.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020 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 + +int pmc_enable_partition(u32 part, int enable) +{ + u32 part_mask = BIT(part); + u32 desired_state = enable << part; + + // Check if the partition has the state we want. + if ((PMC(APBDEV_PMC_PWRGATE_STATUS) & part_mask) == desired_state) + return 1; + + u32 i = 5001; + while (PMC(APBDEV_PMC_PWRGATE_TOGGLE) & 0x100) + { + usleep(1); + i--; + if (i < 1) + return 0; + } + + // Toggle power gating. + PMC(APBDEV_PMC_PWRGATE_TOGGLE) = part | 0x100; + + i = 5001; + while (i > 0) + { + if ((PMC(APBDEV_PMC_PWRGATE_STATUS) & part_mask) == desired_state) + break; + usleep(1); + i--; + } + + return 1; +} diff --git a/bdk/soc/pmc.h b/bdk/soc/pmc.h index 7df7922..c27d937 100644 --- a/bdk/soc/pmc.h +++ b/bdk/soc/pmc.h @@ -1,6 +1,7 @@ /* * Copyright (c) 2018 naehrwert * Copyright (c) 2018 st4rk + * Copyright (c) 2018-2020 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,44 +19,54 @@ #ifndef _PMC_H_ #define _PMC_H_ +#include + /*! PMC registers. */ #define APBDEV_PMC_CNTRL 0x0 -#define PMC_CNTRL_MAIN_RST (1 << 4) +#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_GPIO_IO_EN (1 << 21) -#define PMC_NO_IOPOWER_AUDIO_HV (1 << 18) -#define PMC_NO_IOPOWER_SDMMC1_IO_EN (1 << 12) +#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_RECOVERY (1 << 31) -#define PMC_SCRATCH0_MODE_FASTBOOT (1 << 30) -#define PMC_SCRATCH0_MODE_PAYLOAD (1 << 29) -#define PMC_SCRATCH0_MODE_RCM (1 << 1) -#define PMC_SCRATCH0_MODE_WARMBOOT (1 << 0) +#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_GPIO_IO_EN (1 << 21) -#define PMC_PWR_DET_AUDIO_HV (1 << 18) -#define PMC_PWR_DET_SDMMC1_IO_EN (1 << 12) +#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_FLAG BIT(24) #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 (1 << 2) +#define PMC_CLK_OUT_CNTRL_CLK1_FORCE_EN BIT(2) #define APBDEV_PMC_RST_STATUS 0x1B4 #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 @@ -83,5 +94,10 @@ #define APBDEV_PMC_SCRATCH188 0x810 #define APBDEV_PMC_SCRATCH190 0x818 #define APBDEV_PMC_SCRATCH200 0x840 +#define APBDEV_PMC_TZRAM_PWR_CNTRL 0xBE8 +#define APBDEV_PMC_TZRAM_SEC_DISABLE 0xBEC +#define APBDEV_PMC_TZRAM_NON_SEC_DISABLE 0xBF0 + +int pmc_enable_partition(u32 part, int enable); #endif diff --git a/bdk/soc/t210.h b/bdk/soc/t210.h index 78432c1..e48f53a 100644 --- a/bdk/soc/t210.h +++ b/bdk/soc/t210.h @@ -61,6 +61,9 @@ #define EMC_BASE 0x7001B000 #define EMC0_BASE 0x7001E000 #define EMC1_BASE 0x7001F000 +#define XUSB_HOST_BASE 0x70090000 +#define XUSB_PADCTL_BASE 0x7009F000 +#define XUSB_DEV_BASE 0x700D0000 #define MIPI_CAL_BASE 0x700E3000 #define CL_DVFS_BASE 0x70110000 #define I2S_BASE 0x702D1000 @@ -79,7 +82,7 @@ #define VIC(off) _REG(VIC_BASE, off) #define TSEC(off) _REG(TSEC_BASE, off) #define SOR1(off) _REG(SOR1_BASE, off) -#define ICTLR(cidx, off) _REG(ICTLR_BASE + (0x100 * cidx), 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) #define FLOW_CTLR(off) _REG(FLOW_CTLR_BASE, off) @@ -109,6 +112,12 @@ #define EMC(off) _REG(EMC_BASE, off) #define EMC_CH0(off) _REG(EMC0_BASE, off) #define EMC_CH1(off) _REG(EMC1_BASE, off) +#define XUSB_HOST(off) _REG(XUSB_HOST_BASE, off) +#define XUSB_PADCTL(off) _REG(XUSB_PADCTL_BASE, off) +#define XUSB_DEV(off) _REG(XUSB_DEV_BASE, off) +#define XUSB_DEV_XHCI(off) _REG(XUSB_DEV_BASE, off) +#define XUSB_DEV_PCI(off) _REG(XUSB_DEV_BASE + 0x8000, off) +#define XUSB_DEV_DEV(off) _REG(XUSB_DEV_BASE + 0x9000, off) #define MIPI_CAL(off) _REG(MIPI_CAL_BASE, off) #define CL_DVFS(off) _REG(CL_DVFS_BASE, off) #define I2S(off) _REG(I2S_BASE, off) @@ -149,14 +158,33 @@ /*! AHB Gizmo registers. */ #define AHB_ARBITRATION_PRIORITY_CTRL 0x8 -#define ARBITRATION_PRIORITY_CTRL_ENB_FAST_REARBITRATE (1 << 6) +#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 (1 << 2) +#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_USB_IMMEDIATE (1 << 18) +#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 MEM_PREFETCH_ENABLE (1 << 31) -#define MEM_PREFETCH_AHB_MST_USB 6 +#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_AHB_SPARE_REG 0x110 /*! Misc registers. */ #define APB_MISC_PP_STRAPPING_OPT_A 0x08 @@ -170,19 +198,16 @@ #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 -/*! System registers. */ -#define AHB_ARBITRATION_XBAR_CTRL 0xE0 -#define AHB_AHB_SPARE_REG 0x110 - /*! Secure boot registers. */ #define SB_CSR 0x0 -#define SB_CSR_NS_RST_VEC_WR_DIS (1 << 1) -#define SB_CSR_PIROM_DISABLE (1 << 4) +#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 (1 << 0) +#define SB_AA64_RST_AARCH64_MODE_EN BIT(0) #define SB_AA64_RESET_HIGH 0x34 /*! SOR registers. */ @@ -217,20 +242,20 @@ #define TIMERUS_USEC_CFG (0x10 + 0x4) #define TIMER_TMR8_TMR_PTV 0x78 #define TIMER_TMR9_TMR_PTV 0x80 -#define TIMER_EN (1 << 31) -#define TIMER_PER_EN (1 << 30) +#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 (1 << 30) +#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 (1 << 14) -#define TIMER_PMCRESET_EN (1 << 15) +#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 (1 << 0) -#define TIMER_CNT_DISABLE (1 << 1) +#define TIMER_START_CNT BIT(0) +#define TIMER_CNT_DISABLE BIT(1) #define TIMER_WDT4_UNLOCK_PATTERN (0x10C + 0x80) #define TIMER_MAGIC_PTRN 0xC45A @@ -245,29 +270,29 @@ #define I2S4_CTRL 0x3A0 #define I2S5_CG 0x488 #define I2S5_CTRL 0x4A0 -#define I2S_CG_SLCG_ENABLE (1 << 0) -#define I2S_CTRL_MASTER_EN (1 << 10) +#define I2S_CG_SLCG_ENABLE BIT(0) +#define I2S_CTRL_MASTER_EN BIT(10) /*! PWM registers. */ #define PWM_CONTROLLER_PWM_CSR_0 0x00 #define PWM_CONTROLLER_PWM_CSR_1 0x10 -#define PWM_CSR_EN (1 << 31) +#define PWM_CSR_EN BIT(31) /*! Special registers. */ #define EMC_SCRATCH0 0x324 -#define EMC_HEKA_UPD (1 << 30) -#define EMC_SEPT_RUN (1 << 31) +#define EMC_HEKA_UPD BIT(30) +#define EMC_SEPT_RUN BIT(31) /*! Flow controller registers. */ #define FLOW_CTLR_HALT_COP_EVENTS 0x4 -#define HALT_COP_GIC_IRQ (1 << 9) -#define HALT_COP_LIC_IRQ (1 << 11) -#define HALT_COP_SEC (1 << 23) -#define HALT_COP_MSEC (1 << 24) -#define HALT_COP_USEC (1 << 25) -#define HALT_COP_JTAG (1 << 28) -#define HALT_COP_WAIT_EVENT (1 << 30) -#define HALT_COP_STOP_UNTIL_IRQ (1 << 31) +#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 @@ -280,9 +305,4 @@ #define FLOW_CTLR_RAM_REPAIR 0x40 #define FLOW_CTLR_BPMP_CLUSTER_CONTROL 0x98 -/*! USB controller registers. */ -#define USB1_UTMIP_BAT_CHRG_CFG0 0x830 -#define BAT_CHRG_CFG0_OP_SRC_EN (1 << 3) -#define BAT_CHRG_CFG0_PWRDOWN_CHRG (1 << 0) - #endif diff --git a/bdk/storage/mmc.h b/bdk/storage/mmc.h index dddb956..efa9e10 100644 --- a/bdk/storage/mmc.h +++ b/bdk/storage/mmc.h @@ -31,7 +31,7 @@ #define MMC_ALL_SEND_CID 2 /* bcr R2 */ #define MMC_SET_RELATIVE_ADDR 3 /* ac [31:16] RCA R1 */ #define MMC_SET_DSR 4 /* bc [31:16] RCA */ -#define MMC_SLEEP_AWAKE 5 /* ac [31:16] RCA 15:flg R1b */ +#define MMC_SLEEP_AWAKE 5 /* ac [31:16] RCA 15:flg R1b */ #define MMC_SWITCH 6 /* ac [31:0] See below R1b */ #define MMC_SELECT_CARD 7 /* ac [31:16] RCA R1 */ #define MMC_SEND_EXT_CSD 8 /* adtc R1 */ @@ -51,7 +51,7 @@ #define MMC_READ_SINGLE_BLOCK 17 /* adtc [31:0] data addr R1 */ #define MMC_READ_MULTIPLE_BLOCK 18 /* adtc [31:0] data addr R1 */ #define MMC_SEND_TUNING_BLOCK 19 /* adtc R1 */ -#define MMC_SEND_TUNING_BLOCK_HS200 21 /* adtc R1 */ +#define MMC_SEND_TUNING_BLOCK_HS200 21 /* adtc R1 */ /* class 3 */ #define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1 */ @@ -136,8 +136,8 @@ c : clear by read #define R1_WP_ERASE_SKIP (1 << 15) /* sx, c */ #define R1_CARD_ECC_DISABLED (1 << 14) /* sx, a */ #define R1_ERASE_RESET (1 << 13) /* sr, c */ -#define R1_STATUS(x) (x & 0xFFFFE000) -#define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */ +#define R1_STATUS(x) ((x) & 0xFFFFE000) +#define R1_CURRENT_STATE(x) (((x) & 0x00001E00) >> 9) /* sx, b (4 bits) */ #define R1_READY_FOR_DATA (1 << 8) /* sx, a */ #define R1_SWITCH_ERROR (1 << 7) /* sx, c */ #define R1_EXCEPTION_EVENT (1 << 6) /* sr, a */ diff --git a/bdk/storage/sdmmc.c b/bdk/storage/sdmmc.c index fc41458..43f837d 100644 --- a/bdk/storage/sdmmc.c +++ b/bdk/storage/sdmmc.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2019 CTCaer + * Copyright (c) 2018-2020 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, @@ -48,15 +48,18 @@ static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size) static int _sdmmc_storage_check_result(u32 res) { //Error mask: - //R1_OUT_OF_RANGE, R1_ADDRESS_ERROR, R1_BLOCK_LEN_ERROR, - //R1_ERASE_SEQ_ERROR, R1_ERASE_PARAM, R1_WP_VIOLATION, - //R1_LOCK_UNLOCK_FAILED, R1_COM_CRC_ERROR, R1_ILLEGAL_COMMAND, - //R1_CARD_ECC_FAILED, R1_CC_ERROR, R1_ERROR, R1_CID_CSD_OVERWRITE, - //R1_WP_ERASE_SKIP, R1_ERASE_RESET, R1_SWITCH_ERROR - if (!(res & 0xFDF9A080)) - return 1; - //TODO: R1_SWITCH_ERROR we can skip for certain card types. - return 0; + //TODO: R1_SWITCH_ERROR can be skipped for certain card types. + if (res & + (R1_OUT_OF_RANGE | R1_ADDRESS_ERROR | R1_BLOCK_LEN_ERROR | + R1_ERASE_SEQ_ERROR | R1_ERASE_PARAM | R1_WP_VIOLATION | + R1_LOCK_UNLOCK_FAILED | R1_COM_CRC_ERROR | R1_ILLEGAL_COMMAND | + R1_CARD_ECC_FAILED | R1_CC_ERROR | R1_ERROR | + R1_CID_CSD_OVERWRITE | R1_WP_ERASE_SKIP | R1_ERASE_RESET | + R1_SWITCH_ERROR)) + return 0; + + // No errors. + return 1; } static int _sdmmc_storage_execute_cmd_type1_ex(sdmmc_storage_t *storage, u32 *resp, u32 cmd, u32 arg, u32 check_busy, u32 expected_state, u32 mask) @@ -169,14 +172,23 @@ int sdmmc_storage_end(sdmmc_storage_t *storage) sdmmc_end(storage->sdmmc); + storage->initialized = 0; + return 1; } static int _sdmmc_storage_readwrite(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf, u32 is_write) { u8 *bbuf = (u8 *)buf; - bool first_reinit = false; - while (num_sectors) + u32 sct_off = sector; + u32 sct_total = num_sectors; + bool first_reinit = true; + + // Exit if not initialized. + if (!storage->initialized) + return 0; + + while (sct_total) { u32 blkcnt = 0; // Retry 5 times if failed. @@ -184,7 +196,7 @@ static int _sdmmc_storage_readwrite(sdmmc_storage_t *storage, u32 sector, u32 nu do { reinit_try: - if (_sdmmc_storage_readwrite_ex(storage, &blkcnt, sector, MIN(num_sectors, 0xFFFF), bbuf, is_write)) + if (_sdmmc_storage_readwrite_ex(storage, &blkcnt, sct_off, MIN(sct_total, 0xFFFF), bbuf, is_write)) goto out; else retries--; @@ -201,7 +213,7 @@ reinit_try: sd_error_count_increment(SD_ERROR_RW_FAIL); - if (!first_reinit) + if (first_reinit) res = sd_initialize(true); else { @@ -210,19 +222,28 @@ reinit_try: sd_error_count_increment(SD_ERROR_INIT_FAIL); } + // Reset values for a retry. + blkcnt = 0; retries = 3; - first_reinit = true; + first_reinit = false; + // If succesful reinit, restart xfer. if (res) + { + bbuf = (u8 *)buf; + sct_off = sector; + sct_total = num_sectors; + goto reinit_try; + } } + // Failed. return 0; out: -DPRINTF("readwrite: %08X\n", blkcnt); - sector += blkcnt; - num_sectors -= blkcnt; + sct_off += blkcnt; + sct_total -= blkcnt; bbuf += 512 * blkcnt; } @@ -275,9 +296,11 @@ static int _mmc_storage_get_op_cond_inner(sdmmc_storage_t *storage, u32 *pout, u case SDMMC_POWER_1_8: arg = SD_OCR_CCS | SD_OCR_VDD_18; break; + case SDMMC_POWER_3_3: arg = SD_OCR_CCS | SD_OCR_VDD_27_34; break; + default: return 0; } @@ -334,6 +357,7 @@ static void _mmc_storage_parse_cid(sdmmc_storage_t *storage) 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 */ @@ -343,6 +367,7 @@ static void _mmc_storage_parse_cid(sdmmc_storage_t *storage) storage->cid.prv = unstuff_bits(raw_cid, 48, 8); storage->cid.serial = unstuff_bits(raw_cid, 16, 32); break; + default: break; } @@ -387,6 +412,10 @@ static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf) 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.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->sec_cnt = *(u32 *)&buf[EXT_CSD_SEC_CNT]; } @@ -429,6 +458,7 @@ static int _mmc_storage_switch_buswidth(sdmmc_storage_t *storage, u32 bus_width) case SDMMC_BUS_WIDTH_4: arg = SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_4); break; + case SDMMC_BUS_WIDTH_8: arg = SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_8); break; @@ -487,7 +517,7 @@ static int _mmc_storage_enable_HS400(sdmmc_storage_t *storage) if (!_mmc_storage_enable_HS200(storage)) return 0; - sdmmc_set_tap_value(storage->sdmmc); + sdmmc_save_tap_value(storage->sdmmc); if (!_mmc_storage_enable_HS(storage, 0)) return 0; @@ -543,7 +573,7 @@ int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_wid storage->sdmmc = sdmmc; storage->rca = 2; //TODO: 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_AUTO_CAL_DISABLE)) + 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"); @@ -614,7 +644,9 @@ DPRINTF("[MMC] BKOPS enabled\n"); return 0; DPRINTF("[MMC] succesfully switched to HS mode\n"); - sdmmc_card_clock_ctrl(storage->sdmmc, SDMMC_AUTO_CAL_ENABLE); + sdmmc_card_clock_powersave(storage->sdmmc, SDMMC_POWER_SAVE_ENABLE); + + storage->initialized = 1; return 1; } @@ -628,6 +660,7 @@ int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition) return 0; storage->partition = partition; + return 1; } @@ -666,7 +699,7 @@ static int _sd_storage_send_if_cond(sdmmc_storage_t *storage) return (resp & 0xFF) == 0xAA ? 0 : 2; } -static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, int is_version_1, int supports_low_voltage) +static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, int is_version_1, int bus_low_voltage_support) { sdmmc_cmd_t cmdbuf; // Support for Current > 150mA @@ -674,7 +707,7 @@ static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, int // Support for handling block-addressed SDHC cards arg |= (~is_version_1 & 1) ? SD_OCR_CCS : 0; // Support for 1.8V - arg |= (supports_low_voltage & ~is_version_1 & 1) ? SD_OCR_S18R : 0; + arg |= (bus_low_voltage_support & ~is_version_1 & 1) ? SD_OCR_S18R : 0; // This is needed for most cards. Do not set bit7 even if 1.8V is supported. arg |= SD_OCR_VDD_32_33; sdmmc_init_cmd(&cmdbuf, SD_APP_OP_COND, arg, SDMMC_RSP_TYPE_3, 0); @@ -684,22 +717,24 @@ static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, int return sdmmc_get_rsp(storage->sdmmc, cond, 4, SDMMC_RSP_TYPE_3); } -static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, int is_version_1, int supports_low_voltage) +static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, int is_version_1, int bus_low_voltage_support) { u32 timeout = get_tmr_ms() + 1500; while (1) { u32 cond = 0; - if (!_sd_storage_get_op_cond_once(storage, &cond, is_version_1, supports_low_voltage)) + if (!_sd_storage_get_op_cond_once(storage, &cond, is_version_1, bus_low_voltage_support)) break; if (cond & MMC_CARD_BUSY) { +DPRINTF("[SD] cond: %08X, lv: %d\n", cond, bus_low_voltage_support); + if (cond & SD_OCR_CCS) storage->has_sector_access = 1; // Check if card supports 1.8V signaling. - if (cond & SD_ROCR_S18A && supports_low_voltage) + if (cond & SD_ROCR_S18A && bus_low_voltage_support) { //The low voltage regulator configuration is valid for SDMMC1 only. if (storage->sdmmc->id == SDMMC_1 && @@ -712,6 +747,10 @@ static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, int is_version_1, i DPRINTF("-> switched to low voltage\n"); } } + else + { +DPRINTF("[SD] no low voltage support\n"); + } return 1; } @@ -867,12 +906,15 @@ void _sd_storage_set_current_limit(sdmmc_storage_t *storage, u16 current_limit, case SD_SET_CURRENT_LIMIT_800: DPRINTF("[SD] power limit raised to 800mA\n"); break; + case SD_SET_CURRENT_LIMIT_600: DPRINTF("[SD] power limit raised to 600mA\n"); break; + case SD_SET_CURRENT_LIMIT_400: DPRINTF("[SD] power limit raised to 400mA\n"); break; + default: case SD_SET_CURRENT_LIMIT_200: DPRINTF("[SD] power limit defaulted to 200mA\n"); @@ -885,7 +927,7 @@ int _sd_storage_enable_highspeed(sdmmc_storage_t *storage, u32 hs_type, u8 *buf) { if (!_sd_storage_switch(storage, buf, SD_SWITCH_CHECK, 0, hs_type)) return 0; -DPRINTF("[SD] supports switch to (U)HS mode\n"); +DPRINTF("[SD] supports (U)HS mode: %d\n", buf[16] & 0xF); u32 type_out = buf[16] & 0xF; if (type_out != hs_type) @@ -921,6 +963,7 @@ int _sd_storage_enable_uhs_low_volt(sdmmc_storage_t *storage, u32 type, u8 *buf) 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); @@ -959,7 +1002,7 @@ DPRINTF("[SD] bus speed set to SDR50\n"); if (access_mode & SD_MODE_UHS_SDR25) { type = SDHCI_TIMING_UHS_SDR25; - hs_type = UHS_SDR50_BUS_SPEED; + hs_type = UHS_SDR25_BUS_SPEED; DPRINTF("[SD] bus speed set to SDR25\n"); storage->csd.busspeed = 25; break; @@ -972,6 +1015,7 @@ DPRINTF("[SD] bus speed set to SDR25\n"); DPRINTF("[SD] bus speed set to SDR12\n"); storage->csd.busspeed = 12; break; + default: return 0; break; @@ -982,10 +1026,10 @@ DPRINTF("[SD] bus speed set to SDR12\n"); DPRINTF("[SD] card accepted UHS\n"); if (!sdmmc_setup_clock(storage->sdmmc, type)) return 0; -DPRINTF("[SD] setup clock\n"); +DPRINTF("[SD] after setup clock\n"); if (!sdmmc_tuning_execute(storage->sdmmc, type, MMC_SEND_TUNING_BLOCK)) return 0; -DPRINTF("[SD] config tuning\n"); +DPRINTF("[SD] after tuning\n"); return _sdmmc_storage_check_status(storage); } @@ -1030,23 +1074,30 @@ static void _sd_storage_parse_ssr(sdmmc_storage_t *storage) raw_ssr2[0] = *(u32 *)&storage->raw_ssr[16]; 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); + switch(unstuff_bits(raw_ssr1, 440 - 384, 8)) { case 0: storage->ssr.speed_class = 0; break; + case 1: storage->ssr.speed_class = 2; break; + case 2: storage->ssr.speed_class = 4; break; + case 3: storage->ssr.speed_class = 6; break; + case 4: storage->ssr.speed_class = 10; break; + default: storage->ssr.speed_class = unstuff_bits(raw_ssr1, 440 - 384, 8); break; @@ -1126,6 +1177,7 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage) case 0: storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2); break; + case 1: storage->csd.c_size = (1 + unstuff_bits(raw_csd, 48, 22)); storage->csd.capacity = storage->csd.c_size << 10; @@ -1134,7 +1186,7 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage) } } -static bool _sdmmc_storage_supports_low_voltage(u32 bus_width, u32 type) +static bool _sdmmc_storage_get_low_voltage_support(u32 bus_width, u32 type) { switch (type) { @@ -1153,9 +1205,10 @@ static bool _sdmmc_storage_supports_low_voltage(u32 bus_width, u32 type) void sdmmc_storage_init_wait_sd() { + // T210/T210B01 WAR: Wait exactly 239ms for IO and Controller power to discharge. u32 sd_poweroff_time = (u32)get_tmr_ms() - sd_power_cycle_time_start; - if (sd_poweroff_time < 100) - msleep(100 - sd_poweroff_time); + if (sd_poweroff_time < 239) + msleep(239 - sd_poweroff_time); } int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type) @@ -1163,13 +1216,15 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_widt int is_version_1 = 0; u8 *buf = (u8 *)SDMMC_UPPER_BUFFER; +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(); 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_AUTO_CAL_DISABLE)) + if (!sdmmc_init(sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID, SDMMC_POWER_SAVE_DISABLE)) return 0; DPRINTF("[SD] after init\n"); @@ -1184,9 +1239,9 @@ DPRINTF("[SD] went to idle state\n"); return 0; DPRINTF("[SD] after send if cond\n"); - bool supports_low_voltage = _sdmmc_storage_supports_low_voltage(bus_width, type); + bool bus_low_voltage_support = _sdmmc_storage_get_low_voltage_support(bus_width, type); - if (!_sd_storage_get_op_cond(storage, is_version_1, supports_low_voltage)) + if (!_sd_storage_get_op_cond(storage, is_version_1, bus_low_voltage_support)) return 0; DPRINTF("[SD] got op cond\n"); @@ -1264,7 +1319,7 @@ DPRINTF("[SD] SD does not support wide bus width\n"); return 0; DPRINTF("[SD] enabled UHS\n"); - sdmmc_card_clock_ctrl(sdmmc, SDMMC_AUTO_CAL_ENABLE); + sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE); } else if (type != SDHCI_TIMING_SD_DS12 && (storage->scr.sda_vsn & 0xF) != 0) { @@ -1277,6 +1332,7 @@ DPRINTF("[SD] enabled HS\n"); case SDMMC_BUS_WIDTH_4: storage->csd.busspeed = 25; break; + case SDMMC_BUS_WIDTH_1: storage->csd.busspeed = 6; break; @@ -1289,6 +1345,8 @@ DPRINTF("[SD] enabled HS\n"); DPRINTF("[SD] got sd status\n"); } + storage->initialized = 1; + return 1; } @@ -1328,17 +1386,19 @@ 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_DDR52, SDMMC_AUTO_CAL_DISABLE)) + if (!sdmmc_init(sdmmc, SDMMC_2, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS102, SDMMC_POWER_SAVE_DISABLE)) return 0; DPRINTF("[gc] after init\n"); usleep(1000 + (10000 + sdmmc->divisor - 1) / sdmmc->divisor); - if (!sdmmc_tuning_execute(storage->sdmmc, SDHCI_TIMING_MMC_DDR52, MMC_SEND_TUNING_BLOCK_HS200)) + if (!sdmmc_tuning_execute(storage->sdmmc, SDHCI_TIMING_MMC_HS102, MMC_SEND_TUNING_BLOCK_HS200)) return 0; DPRINTF("[gc] after tuning\n"); - sdmmc_card_clock_ctrl(sdmmc, SDMMC_AUTO_CAL_ENABLE); + sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE); + + storage->initialized = 1; return 1; } diff --git a/bdk/storage/sdmmc.h b/bdk/storage/sdmmc.h index 6bfad77..68d70f0 100644 --- a/bdk/storage/sdmmc.h +++ b/bdk/storage/sdmmc.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018 CTCaer + * Copyright (c) 2018-2020 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, @@ -65,16 +65,19 @@ typedef struct _mmc_csd typedef struct _mmc_ext_csd { - u8 rev; u32 sectors; int bkops; /* background support bit */ int bkops_en; /* manual bkops enable bit */ + u8 rev; u8 ext_struct; /* 194 */ u8 card_type; /* 196 */ u8 bkops_status; /* 246 */ - u16 dev_version; + u8 pre_eol_info; + u8 dev_life_est_a; + u8 dev_life_est_b; u8 boot_mult; u8 rpmb_mult; + u16 dev_version; } mmc_ext_csd_t; typedef struct _sd_scr @@ -92,6 +95,7 @@ typedef struct _sd_ssr u8 uhs_grade; u8 video_class; u8 app_class; + u32 protected_size; } sd_ssr_t; /*! SDMMC storage context. */ @@ -112,6 +116,7 @@ typedef struct _sdmmc_storage_t mmc_ext_csd_t ext_csd; sd_scr_t scr; sd_ssr_t ssr; + int initialized; } sdmmc_storage_t; int sdmmc_storage_end(sdmmc_storage_t *storage); diff --git a/bdk/storage/sdmmc_driver.c b/bdk/storage/sdmmc_driver.c index 557fe8d..3eaded0 100644 --- a/bdk/storage/sdmmc_driver.c +++ b/bdk/storage/sdmmc_driver.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2019 CTCaer + * Copyright (c) 2018-2020 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -65,12 +66,15 @@ static int _sdmmc_set_io_power(sdmmc_t *sdmmc, u32 power) case SDMMC_POWER_OFF: sdmmc->regs->pwrcon &= ~SDHCI_POWER_ON; break; + case SDMMC_POWER_1_8: sdmmc->regs->pwrcon = SDHCI_POWER_180; break; + case SDMMC_POWER_3_3: sdmmc->regs->pwrcon = SDHCI_POWER_330; break; + default: return 0; } @@ -103,7 +107,7 @@ void sdmmc_set_bus_width(sdmmc_t *sdmmc, u32 bus_width) sdmmc->regs->hostctl = host_control | SDHCI_CTRL_8BITBUS; } -void sdmmc_set_tap_value(sdmmc_t *sdmmc) +void sdmmc_save_tap_value(sdmmc_t *sdmmc) { sdmmc->venclkctl_tap = sdmmc->regs->venclkctl >> 16; sdmmc->venclkctl_set = 1; @@ -112,7 +116,7 @@ void sdmmc_set_tap_value(sdmmc_t *sdmmc) static int _sdmmc_config_tap_val(sdmmc_t *sdmmc, u32 type) { const u32 dqs_trim_val = 0x28; - const u32 tap_values[] = { 4, 0, 3, 0 }; + const u32 tap_values_t210[] = { 4, 0, 3, 0 }; u32 tap_val = 0; @@ -129,36 +133,49 @@ static int _sdmmc_config_tap_val(sdmmc_t *sdmmc, u32 type) tap_val = sdmmc->venclkctl_tap; } else - { - tap_val = tap_values[sdmmc->id]; - } + tap_val = sdmmc->t210b01 ? 11 : tap_values_t210[sdmmc->id]; + sdmmc->regs->venclkctl = (sdmmc->regs->venclkctl & 0xFF00FFFF) | (tap_val << 16); return 1; } -static int _sdmmc_get_clkcon(sdmmc_t *sdmmc) +static int _sdmmc_commit_changes(sdmmc_t *sdmmc) { return sdmmc->regs->clkcon; } static void _sdmmc_pad_config_fallback(sdmmc_t *sdmmc, u32 power) { - _sdmmc_get_clkcon(sdmmc); + _sdmmc_commit_changes(sdmmc); switch (sdmmc->id) { case SDMMC_1: // 33 Ohm 2X Driver. if (power == SDMMC_POWER_OFF) break; u32 sdmmc1_pad_cfg = APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL) & 0xF8080FFF; - if (power == SDMMC_POWER_1_8) - APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL) = sdmmc1_pad_cfg | (0xB0F << 12); // Up: 11, Dn: 15. For 33 ohm. + if (sdmmc->t210b01) + sdmmc1_pad_cfg |= (0x808 << 12); // Up: 8, Dn: 8. For 33 ohm. + else if (power == SDMMC_POWER_1_8) + sdmmc1_pad_cfg |= (0xB0F << 12); // Up: 11, Dn: 15. For 33 ohm. else if (power == SDMMC_POWER_3_3) - APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL) = sdmmc1_pad_cfg | (0xC0C << 12); // Up: 12, Dn: 12. For 33 ohm. + sdmmc1_pad_cfg |= (0xC0C << 12); // Up: 12, Dn: 12. For 33 ohm. + APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL) = sdmmc1_pad_cfg; + (void)APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL); // Commit write. break; + case SDMMC_2: - case SDMMC_4: // 50 Ohm 2X Driver. PU:16, PD:16. - APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) = (APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) & 0xFFFFC003) | 0x1040; + if (sdmmc->t210b01) + APB_MISC(APB_MISC_GP_EMMC2_PAD_CFGPADCTRL) = (APB_MISC(APB_MISC_GP_EMMC2_PAD_CFGPADCTRL) & 0xF8080FFF) | 0xA0A000; + else + APB_MISC(APB_MISC_GP_EMMC2_PAD_CFGPADCTRL) = (APB_MISC(APB_MISC_GP_EMMC2_PAD_CFGPADCTRL) & 0xFFFFC003) | 0x1040; // PU:16, PD:16. + (void)APB_MISC(APB_MISC_GP_EMMC2_PAD_CFGPADCTRL); + 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); + (void)APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL); // Commit write. break; } } @@ -176,13 +193,13 @@ static void _sdmmc_autocal_execute(sdmmc_t *sdmmc, u32 power) if (!(sdmmc->regs->sdmemcmppadctl & TEGRA_MMC_SDMEMCOMPPADCTRL_PAD_E_INPUT_PWRD)) { sdmmc->regs->sdmemcmppadctl |= TEGRA_MMC_SDMEMCOMPPADCTRL_PAD_E_INPUT_PWRD; - _sdmmc_get_clkcon(sdmmc); + _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_get_clkcon(sdmmc); + _sdmmc_commit_changes(sdmmc); usleep(2); u32 timeout = get_tmr_ms() + 10; @@ -194,24 +211,18 @@ static void _sdmmc_autocal_execute(sdmmc_t *sdmmc, u32 power) break; } } -/* - // Check if PU results are inside limits. - // SDMMC1: CZ pads - 7-bit PU. SDMMC2/4: LV_CZ pads - 5-bit PU. - u8 autocal_pu_status = sdmmc->regs->autocalsts & 0x7F; - switch (sdmmc->id) - { - case SDMMC_1: - if (!autocal_pu_status || autocal_pu_status == 0x7F) - timeout = 0; - break; - case SDMMC_2: - case SDMMC_4: - autocal_pu_status &= 0x1F; - if (!autocal_pu_status || autocal_pu_status == 0x1F) - timeout = 0; - break; - } -*/ + +#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; + if (!autocal_pu_status) + EPRINTF("SDMMC: Comp Pad short to gnd!"); + else if (autocal_pu_status == code_mask) + EPRINTF("SDMMC: Comp Pad open!"); +#endif + // In case auto calibration fails, we load suggested standard values. if (!timeout) { @@ -241,12 +252,13 @@ static int _sdmmc_dll_cal_execute(sdmmc_t *sdmmc) } #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); // Add -4 TX_DLY_CODE_OFFSET if HS533. + sdmmc->regs->vendllcalcfg = sdmmc->regs->vendllcalcfg &= 0xFFFFC07F | (0x7C << 7); #endif sdmmc->regs->vendllcalcfg |= TEGRA_MMC_DLLCAL_CFG_EN_CALIBRATE; - _sdmmc_get_clkcon(sdmmc); + _sdmmc_commit_changes(sdmmc); u32 timeout = get_tmr_ms() + 5; while (sdmmc->regs->vendllcalcfg & TEGRA_MMC_DLLCAL_CFG_EN_CALIBRATE) @@ -277,12 +289,21 @@ out:; static void _sdmmc_reset(sdmmc_t *sdmmc) { sdmmc->regs->swrst |= SDHCI_RESET_CMD | SDHCI_RESET_DATA; - _sdmmc_get_clkcon(sdmmc); + _sdmmc_commit_changes(sdmmc); u32 timeout = get_tmr_ms() + 2000; while ((sdmmc->regs->swrst & (SDHCI_RESET_CMD | SDHCI_RESET_DATA)) && get_tmr_ms() < timeout) ; } +static void _sdmmc_reset_all(sdmmc_t *sdmmc) +{ + sdmmc->regs->swrst |= SDHCI_RESET_ALL; + _sdmmc_commit_changes(sdmmc); + u32 timeout = get_tmr_ms() + 2000;//100ms + while ((sdmmc->regs->swrst & SDHCI_RESET_ALL) && get_tmr_ms() < timeout) + ; +} + int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type) { // Disable the SD clock if it was enabled, and reenable it later. @@ -306,36 +327,41 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type) sdmmc->regs->hostctl &= ~SDHCI_CTRL_HISPD; sdmmc->regs->hostctl2 &= ~SDHCI_CTRL_VDD_180; break; + case SDHCI_TIMING_MMC_HS52: case SDHCI_TIMING_SD_HS25: sdmmc->regs->hostctl |= SDHCI_CTRL_HISPD; sdmmc->regs->hostctl2 &= ~SDHCI_CTRL_VDD_180; 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_SDR104: case SDHCI_TIMING_UHS_SDR82: case SDHCI_TIMING_UHS_DDR50: - case SDHCI_TIMING_MMC_DDR52: + case SDHCI_TIMING_MMC_HS102: 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 |= 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 |= 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 |= SDHCI_CTRL_VDD_180; break; } - _sdmmc_get_clkcon(sdmmc); + _sdmmc_commit_changes(sdmmc); u32 clock; u16 divisor; @@ -373,10 +399,10 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type) static void _sdmmc_card_clock_enable(sdmmc_t *sdmmc) { // Recalibrate conditionally. - if ((sdmmc->id == SDMMC_1) && !sdmmc->auto_cal_enabled) + if (sdmmc->manual_cal && !sdmmc->powersave_enabled) _sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc)); - if (!sdmmc->auto_cal_enabled) + if (!sdmmc->powersave_enabled) { if (!(sdmmc->regs->clkcon & SDHCI_CLOCK_CARD_EN)) sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; @@ -390,18 +416,17 @@ static void _sdmmc_sd_clock_disable(sdmmc_t *sdmmc) sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN; } -void sdmmc_card_clock_ctrl(sdmmc_t *sdmmc, int auto_cal_enable) +void sdmmc_card_clock_powersave(sdmmc_t *sdmmc, int powersave_enable) { // Recalibrate periodically for SDMMC1. - if ((sdmmc->id == SDMMC_1) && !auto_cal_enable && sdmmc->card_clock_enabled) + if (sdmmc->manual_cal && !powersave_enable && sdmmc->card_clock_enabled) _sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc)); - sdmmc->auto_cal_enabled = auto_cal_enable; - if (auto_cal_enable) + sdmmc->powersave_enabled = powersave_enable; + if (powersave_enable) { - if (!(sdmmc->regs->clkcon & SDHCI_CLOCK_CARD_EN)) - return; - sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN; + if (sdmmc->regs->clkcon & SDHCI_CLOCK_CARD_EN) + sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN; return; } @@ -422,6 +447,7 @@ static int _sdmmc_cache_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type) return 0; rsp[0] = sdmmc->regs->rspreg0; break; + case SDMMC_RSP_TYPE_2: if (size < 0x10) return 0; @@ -450,9 +476,9 @@ static int _sdmmc_cache_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type) rsp[i - 1] |= (tempreg >> 24) & 0xFF; } break; + default: return 0; - break; } return 1; @@ -473,6 +499,7 @@ int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type) return 0; rsp[0] = sdmmc->rsp[0]; break; + case SDMMC_RSP_TYPE_2: if (size < 0x10) return 0; @@ -481,9 +508,9 @@ int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type) rsp[2] = sdmmc->rsp[2]; rsp[3] = sdmmc->rsp[3]; break; + default: return 0; - break; } return 1; @@ -491,7 +518,7 @@ int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type) static int _sdmmc_wait_cmd_data_inhibit(sdmmc_t *sdmmc, bool wait_dat) { - _sdmmc_get_clkcon(sdmmc); + _sdmmc_commit_changes(sdmmc); u32 timeout = get_tmr_ms() + 2000; while(sdmmc->regs->prnsts & SDHCI_CMD_INHIBIT) @@ -517,7 +544,7 @@ static int _sdmmc_wait_cmd_data_inhibit(sdmmc_t *sdmmc, bool wait_dat) static int _sdmmc_wait_card_busy(sdmmc_t *sdmmc) { - _sdmmc_get_clkcon(sdmmc); + _sdmmc_commit_changes(sdmmc); u32 timeout = get_tmr_ms() + 2000; while (!(sdmmc->regs->prnsts & SDHCI_DATA_0_LVL_MASK)) @@ -536,16 +563,19 @@ static int _sdmmc_setup_read_small_block(sdmmc_t *sdmmc) { case SDMMC_BUS_WIDTH_1: return 0; - break; + case SDMMC_BUS_WIDTH_4: sdmmc->regs->blksize = 64; break; + case SDMMC_BUS_WIDTH_8: sdmmc->regs->blksize = 128; break; } + sdmmc->regs->blkcnt = 1; sdmmc->regs->trnmod = SDHCI_TRNS_READ; + return 1; } @@ -557,6 +587,7 @@ static int _sdmmc_send_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, bool is_data_presen { case SDMMC_RSP_TYPE_0: break; + case SDMMC_RSP_TYPE_1: case SDMMC_RSP_TYPE_4: case SDMMC_RSP_TYPE_5: @@ -565,15 +596,17 @@ static int _sdmmc_send_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, bool is_data_presen else cmdflags = SDHCI_CMD_RESP_LEN48 | SDHCI_CMD_INDEX | SDHCI_CMD_CRC; break; + case SDMMC_RSP_TYPE_2: cmdflags = SDHCI_CMD_RESP_LEN136 | SDHCI_CMD_CRC; break; + case SDMMC_RSP_TYPE_3: cmdflags = SDHCI_CMD_RESP_LEN48; break; + default: return 0; - break; } if (is_data_present) @@ -596,7 +629,7 @@ static void _sdmmc_send_tuning_cmd(sdmmc_t *sdmmc, u32 cmd) static int _sdmmc_tuning_execute_once(sdmmc_t *sdmmc, u32 cmd) { - if (sdmmc->auto_cal_enabled) + if (sdmmc->powersave_enabled) return 0; if (!_sdmmc_wait_cmd_data_inhibit(sdmmc, true)) return 0; @@ -608,13 +641,13 @@ static int _sdmmc_tuning_execute_once(sdmmc_t *sdmmc, u32 cmd) sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN; _sdmmc_send_tuning_cmd(sdmmc, cmd); - _sdmmc_get_clkcon(sdmmc); + _sdmmc_commit_changes(sdmmc); usleep(1); _sdmmc_reset(sdmmc); sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; - _sdmmc_get_clkcon(sdmmc); + _sdmmc_commit_changes(sdmmc); u32 timeout = get_tmr_us() + 5000; while (get_tmr_us() < timeout) @@ -623,7 +656,7 @@ 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_get_clkcon(sdmmc); + _sdmmc_commit_changes(sdmmc); usleep((1000 * 8 + sdmmc->divisor - 1) / sdmmc->divisor); return 1; } @@ -632,7 +665,7 @@ static int _sdmmc_tuning_execute_once(sdmmc_t *sdmmc, u32 cmd) _sdmmc_reset(sdmmc); sdmmc->regs->norintstsen &= ~SDHCI_INT_DATA_AVAIL; - _sdmmc_get_clkcon(sdmmc); + _sdmmc_commit_changes(sdmmc); usleep((1000 * 8 + sdmmc->divisor - 1) / sdmmc->divisor); return 0; @@ -651,15 +684,18 @@ int sdmmc_tuning_execute(sdmmc_t *sdmmc, u32 type, u32 cmd) max = 128; flag = (2 << 13); // 128 iterations. break; + case SDHCI_TIMING_UHS_SDR50: case SDHCI_TIMING_UHS_DDR50: - case SDHCI_TIMING_MMC_DDR52: + case SDHCI_TIMING_MMC_HS102: max = 256; flag = (4 << 13); // 256 iterations. break; + case SDHCI_TIMING_UHS_SDR12: case SDHCI_TIMING_UHS_SDR25: return 1; + default: return 0; } @@ -688,7 +724,7 @@ static int _sdmmc_enable_internal_clock(sdmmc_t *sdmmc) { //Enable internal clock and wait till it is stable. sdmmc->regs->clkcon |= SDHCI_CLOCK_INT_EN; - _sdmmc_get_clkcon(sdmmc); + _sdmmc_commit_changes(sdmmc); u32 timeout = get_tmr_ms() + 2000; while (!(sdmmc->regs->clkcon & SDHCI_CLOCK_INT_STABLE)) { @@ -724,17 +760,28 @@ static int _sdmmc_autocal_config_offset(sdmmc_t *sdmmc, u32 power) off_pd = 5; off_pu = 5; break; + case SDMMC_1: - case SDMMC_3: if (power == SDMMC_POWER_1_8) { - off_pd = 123; - off_pu = 123; + if (!sdmmc->t210b01) + { + off_pd = 123; + off_pu = 123; + } + else + { + off_pd = 6; + off_pu = 6; + } } else if (power == SDMMC_POWER_3_3) { - off_pd = 125; - off_pu = 0; + if (!sdmmc->t210b01) + { + off_pd = 125; + off_pu = 0; + } } else return 0; @@ -764,7 +811,7 @@ static int _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; @@ -772,6 +819,9 @@ DPRINTF("norintsts %08X; errintsts %08X\n", norintsts, errintsts); // Check for error interrupt. if (norintsts & SDHCI_INT_ERROR) { +#ifdef ERROR_EXTRA_PRINTING + EPRINTFARGS("SDMMC: norintsts %08X, errintsts %08X\n", norintsts, errintsts); +#endif sdmmc->regs->errintsts = errintsts; return SDMMC_MASKINT_ERROR; } @@ -786,7 +836,7 @@ DPRINTF("norintsts %08X; errintsts %08X\n", norintsts, errintsts); static int _sdmmc_wait_response(sdmmc_t *sdmmc) { - _sdmmc_get_clkcon(sdmmc); + _sdmmc_commit_changes(sdmmc); u32 timeout = get_tmr_ms() + 2000; while (true) @@ -837,7 +887,7 @@ int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp) return 0; // Recalibrate periodically for SDMMC1. - if ((sdmmc->id == SDMMC_1) && sdmmc->auto_cal_enabled) + if (sdmmc->manual_cal && sdmmc->powersave_enabled) _sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc)); bool should_disable_sd_clock = false; @@ -845,7 +895,7 @@ int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp) { should_disable_sd_clock = true; sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; - _sdmmc_get_clkcon(sdmmc); + _sdmmc_commit_changes(sdmmc); usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor); } @@ -963,8 +1013,6 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_ is_data_present = true; } - else - is_data_present = false; _sdmmc_enable_interrupts(sdmmc); @@ -983,7 +1031,7 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_ EPRINTF("SDMMC: Transfer timeout!"); #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) { @@ -994,7 +1042,7 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_ if (!result) { #ifdef ERROR_EXTRA_PRINTING - EPRINTFARGS("SDMMC: Unknown response %08X!", sdmmc->rsp[0]); + EPRINTF("SDMMC: Unknown response type!"); #endif } } @@ -1004,7 +1052,7 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_ if (!result) { #ifdef ERROR_EXTRA_PRINTING - EPRINTF("SDMMC: DMA Update failed!"); + EPRINTFARGS("SDMMC: DMA Update failed (%08X)!", result); #endif } } @@ -1047,7 +1095,56 @@ bool sdmmc_get_sd_inserted() return (!gpio_read(GPIO_PORT_Z, GPIO_PIN_1)); } -static int _sdmmc_config_sdmmc1() +static void _sdmmc_config_sdmmc1_schmitt() +{ + PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) |= PINMUX_SCHMT; + PINMUX_AUX(PINMUX_AUX_SDMMC1_CMD) |= PINMUX_SCHMT; + PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT3) |= PINMUX_SCHMT; + PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT2) |= PINMUX_SCHMT; + PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT1) |= PINMUX_SCHMT; + PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT0) |= PINMUX_SCHMT; +} + +static void _sdmmc_config_sdmmc2_schmitt() +{ + PINMUX_AUX(PINMUX_AUX_SDMMC2_CLK) |= PINMUX_SCHMT; + PINMUX_AUX(PINMUX_AUX_SDMMC2_CMD) |= PINMUX_SCHMT; + PINMUX_AUX(PINMUX_AUX_SDMMC2_DAT7) |= PINMUX_SCHMT; + PINMUX_AUX(PINMUX_AUX_SDMMC2_DAT6) |= PINMUX_SCHMT; + PINMUX_AUX(PINMUX_AUX_SDMMC2_DAT5) |= PINMUX_SCHMT; + PINMUX_AUX(PINMUX_AUX_SDMMC2_DAT4) |= PINMUX_SCHMT; + PINMUX_AUX(PINMUX_AUX_SDMMC2_DAT3) |= PINMUX_SCHMT; + PINMUX_AUX(PINMUX_AUX_SDMMC2_DAT2) |= PINMUX_SCHMT; + PINMUX_AUX(PINMUX_AUX_SDMMC2_DAT1) |= PINMUX_SCHMT; + PINMUX_AUX(PINMUX_AUX_SDMMC2_DAT0) |= PINMUX_SCHMT; +} + +static void _sdmmc_config_sdmmc1_pads(bool discharge) +{ + u32 sdmmc1_pin_mask = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5; + + // Set values for Reset state. + u32 function = GPIO_MODE_SPIO; + u32 level = GPIO_LOW; + u32 output = GPIO_OUTPUT_DISABLE; + + // Set values for dicharging. + if (discharge) + { + function = GPIO_MODE_GPIO; + level = GPIO_HIGH; + output = GPIO_OUTPUT_ENABLE; + } + + // Set all pads function. + gpio_config(GPIO_PORT_M, sdmmc1_pin_mask, function); + // Set all pads output level. + gpio_write(GPIO_PORT_M, sdmmc1_pin_mask, level); + // Set all pads output. + gpio_output_enable(GPIO_PORT_M, sdmmc1_pin_mask, output); +} + +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. @@ -1062,74 +1159,101 @@ static int _sdmmc_config_sdmmc1() /* * Pinmux config: - * DRV_TYPE = DRIVE_2X + * DRV_TYPE = DRIVE_2X (for 33 Ohm driver) * E_SCHMT = ENABLE (for 1.8V), DISABLE (for 3.3V) * E_INPUT = ENABLE * TRISTATE = PASSTHROUGH * APB_MISC_GP_SDMMCx_CLK_LPBK_CONTROL = SDMMCx_CLK_PAD_E_LPBK for CLK */ - // Configure SDMMC1 pinmux. - APB_MISC(APB_MISC_GP_SDMMC1_CLK_LPBK_CONTROL) = 1; // Enable deep loopback for SDMMC1 CLK pad. - PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED; - PINMUX_AUX(PINMUX_AUX_SDMMC1_CMD) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_PULL_UP; - PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT3) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_PULL_UP; - PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT2) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_PULL_UP; - PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT1) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_PULL_UP; - PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT0) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_PULL_UP; + // Enable deep loopback for SDMMC1 CLK pad. + APB_MISC(APB_MISC_GP_SDMMC1_CLK_LPBK_CONTROL) = 1; + + // Configure SDMMC1 CLK pinmux, based on state and SoC type. + 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); + + // Configure reset state of SDMMC1 pins pinmux. + PINMUX_AUX(PINMUX_AUX_SDMMC1_CMD) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PULL_UP; + PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT3) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PULL_UP; + PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT2) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PULL_UP; + PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT1) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PULL_UP; + PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT0) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PULL_UP; + + // Force schmitt trigger for T210B01. + if (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. // 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(1000); + usleep(10000); - // Enable SD card power. + // Enable SD card IO power. max77620_regulator_set_voltage(REGULATOR_LDO2, 3300000); max77620_regulator_enable(REGULATOR_LDO2, 1); usleep(1000); // Set pad slew codes to get good quality clock. - APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL) = (APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL) & 0xFFFFFFF) | 0x50000000; - usleep(1000); + if (!t210b01) + { + APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL) = (APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL) & 0xFFFFFFF) | 0x50000000; + (void)APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL); // Commit write. + usleep(1000); + } return 1; } -static void _sdmmc_config_emmc(u32 id) +static void _sdmmc_config_emmc(u32 id, bool t210b01) { switch (id) { case SDMMC_2: - // Unset park for pads. - APB_MISC(APB_MISC_GP_EMMC2_PAD_CFGPADCTRL) &= 0xF8003FFF; + if (!t210b01) + { + // Unset park for pads. + APB_MISC(APB_MISC_GP_EMMC2_PAD_CFGPADCTRL) &= 0xF8003FFF; + (void)APB_MISC(APB_MISC_GP_EMMC2_PAD_CFGPADCTRL); // Commit write. + } + else // Enable schmitt trigger for T210B01. + _sdmmc_config_sdmmc2_schmitt(); break; + case SDMMC_4: // Unset park for pads. APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) &= 0xF8003FFF; // Set default pad cfg. - APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) = (APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) & 0xFFFFC003) | 0x1040; - - // Enabled schmitt trigger. - APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) |= 1; // Enable Schmitt trigger. + if (t210b01) + APB_MISC(APB_MISC_GP_EMMC4_PAD_PUPD_CFGPADCTRL) &= 0xFFBFFFF9; // Unset CMD/CLK/DQS powedown. + // Enable schmitt trigger. + APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) |= 1; + (void)APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL); // Commit write. break; } } -int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int auto_cal_enable) +int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int powersave_enable) { - const u32 trim_values[] = { 2, 8, 3, 8 }; + u32 clock; + u16 divisor; + u8 vref_sel = 7; - if (id > SDMMC_4) + 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; + + if (id > SDMMC_4 || id == SDMMC_3) return 0; memset(sdmmc, 0, sizeof(sdmmc_t)); @@ -1137,45 +1261,57 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int a sdmmc->regs = (t210_sdmmc_t *)_sdmmc_bases[id]; sdmmc->id = id; sdmmc->clock_stopped = 1; + sdmmc->t210b01 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01; // Do specific SDMMC HW configuration. switch (id) { case SDMMC_1: - if (!_sdmmc_config_sdmmc1()) + if (!_sdmmc_config_sdmmc1(sdmmc->t210b01)) return 0; + if (sdmmc->t210b01) + vref_sel = 0; + else + sdmmc->manual_cal = 1; break; + case SDMMC_2: case SDMMC_4: - _sdmmc_config_emmc(id); + _sdmmc_config_emmc(id, sdmmc->t210b01); break; } + // Disable clock if enabled. if (clock_sdmmc_is_not_reset_and_enabled(id)) { _sdmmc_sd_clock_disable(sdmmc); - _sdmmc_get_clkcon(sdmmc); + _sdmmc_commit_changes(sdmmc); } - u32 clock; - u16 divisor; + // Configure and enable selected clock. clock_sdmmc_get_card_clock_div(&clock, &divisor, type); clock_sdmmc_enable(id, clock); + // Make sure all sdmmc registers are reset. + _sdmmc_reset_all(sdmmc); + sdmmc->clock_stopped = 0; - //TODO: make this skip-able. + // 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) | 7; + (sdmmc->regs->sdmemcmppadctl & TEGRA_MMC_SDMEMCOMPPADCTRL_COMP_VREF_SEL_MASK) | vref_sel; + // Configure auto calibration values. if (!_sdmmc_autocal_config_offset(sdmmc, power)) return 0; + // Calibrate pads. _sdmmc_autocal_execute(sdmmc, power); + // Enable internal clock and power. if (_sdmmc_enable_internal_clock(sdmmc)) { sdmmc_set_bus_width(sdmmc, bus_width); @@ -1183,18 +1319,63 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int a if (sdmmc_setup_clock(sdmmc, type)) { - sdmmc_card_clock_ctrl(sdmmc, auto_cal_enable); + sdmmc_card_clock_powersave(sdmmc, powersave_enable); _sdmmc_card_clock_enable(sdmmc); - _sdmmc_get_clkcon(sdmmc); + _sdmmc_commit_changes(sdmmc); return 1; } - - return 0; } + return 0; } +void sdmmc1_disable_power() +{ + // Ensure regulator is into default voltage. + if (PMC(APBDEV_PMC_PWR_DET_VAL) & PMC_PWR_DET_SDMMC1_IO_EN) + { + // Switch to 1.8V and wait for regulator to stabilize. + max77620_regulator_set_voltage(REGULATOR_LDO2, 1800000); + usleep(150); + + // Inform IO pads that we switched to 1.8V. + PMC(APBDEV_PMC_PWR_DET_VAL) &= ~(PMC_PWR_DET_SDMMC1_IO_EN); + (void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write. + } + + // T210B01 WAR: Clear pull down from CLK pad. + PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) &= ~PINMUX_PULL_MASK; + + // T210B01 WAR: Set pads to discharge state. + _sdmmc_config_sdmmc1_pads(true); + + // Disable SD card IO power regulator. + max77620_regulator_enable(REGULATOR_LDO2, 0); + usleep(4000); + + // Disable SD card IO power pin. + gpio_write(GPIO_PORT_E, GPIO_PIN_4, GPIO_LOW); + + // T210/T210B01 WAR: Set start timer for IO and Controller power discharge. + sd_power_cycle_time_start = get_tmr_ms(); + usleep(1000); // To power cycle, min 1ms without power is needed. + + // Disable SDMMC1 controller power. + PMC(APBDEV_PMC_NO_IOPOWER) |= PMC_NO_IOPOWER_SDMMC1_IO_EN; + (void)PMC(APBDEV_PMC_NO_IOPOWER); // Commit write. + + // Inform IO pads that next voltage might be 3.3V. + PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_SDMMC1_IO_EN; + (void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write. + + // T210B01 WAR: Restore pads to reset state. + _sdmmc_config_sdmmc1_pads(false); + + // T210B01 WAR: Restore pull down to CLK pad. + PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) |= PINMUX_PULL_DOWN; +} + void sdmmc_end(sdmmc_t *sdmmc) { if (!sdmmc->clock_stopped) @@ -1205,18 +1386,9 @@ void sdmmc_end(sdmmc_t *sdmmc) // Disable SD card power. if (sdmmc->id == SDMMC_1) - { - gpio_output_enable(GPIO_PORT_E, GPIO_PIN_4, GPIO_OUTPUT_DISABLE); - max77620_regulator_enable(REGULATOR_LDO2, 0); + sdmmc1_disable_power(); - // Inform IO pads that next voltage might be 3.3V. - PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_SDMMC1_IO_EN; - - sd_power_cycle_time_start = get_tmr_ms(); // Some SanDisk U1 cards need 100ms for a power cycle. - usleep(1000); // To power cycle, min 1ms without power is needed. - } - - _sdmmc_get_clkcon(sdmmc); + _sdmmc_commit_changes(sdmmc); clock_sdmmc_disable(sdmmc->id); sdmmc->clock_stopped = 1; } @@ -1236,7 +1408,7 @@ int sdmmc_execute_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *b return 0; // Recalibrate periodically for SDMMC1. - if (sdmmc->id == SDMMC_1 && sdmmc->auto_cal_enabled) + if (sdmmc->manual_cal && sdmmc->powersave_enabled) _sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc)); int should_disable_sd_clock = 0; @@ -1244,7 +1416,7 @@ 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_get_clkcon(sdmmc); + _sdmmc_commit_changes(sdmmc); usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor); } @@ -1265,36 +1437,32 @@ int sdmmc_enable_low_voltage(sdmmc_t *sdmmc) if (!sdmmc_setup_clock(sdmmc, SDHCI_TIMING_UHS_SDR12)) return 0; - _sdmmc_get_clkcon(sdmmc); + _sdmmc_commit_changes(sdmmc); // Switch to 1.8V and wait for regulator to stabilize. Assume max possible wait needed. max77620_regulator_set_voltage(REGULATOR_LDO2, 1800000); - usleep(300); + usleep(150); // Inform IO pads that we switched to 1.8V. PMC(APBDEV_PMC_PWR_DET_VAL) &= ~(PMC_PWR_DET_SDMMC1_IO_EN); + (void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write. // Enable schmitt trigger for better duty cycle and low jitter clock. - PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) |= PINMUX_SCHMT; - PINMUX_AUX(PINMUX_AUX_SDMMC1_CMD) |= PINMUX_SCHMT; - PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT3) |= PINMUX_SCHMT; - PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT2) |= PINMUX_SCHMT; - PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT1) |= PINMUX_SCHMT; - PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT0) |= PINMUX_SCHMT; + _sdmmc_config_sdmmc1_schmitt(); _sdmmc_autocal_config_offset(sdmmc, SDMMC_POWER_1_8); _sdmmc_autocal_execute(sdmmc, SDMMC_POWER_1_8); _sdmmc_set_io_power(sdmmc, SDMMC_POWER_1_8); - _sdmmc_get_clkcon(sdmmc); + _sdmmc_commit_changes(sdmmc); msleep(5); // Wait minimum 5ms before turning on the card clock. // Turn on SDCLK. if (sdmmc->regs->hostctl2 & SDHCI_CTRL_VDD_180) { sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; - _sdmmc_get_clkcon(sdmmc); + _sdmmc_commit_changes(sdmmc); usleep(1000); - if ((sdmmc->regs->prnsts & 0xF00000) == 0xF00000) + if ((sdmmc->regs->prnsts & SDHCI_DATA_LVL_MASK) == SDHCI_DATA_LVL_MASK) return 1; } diff --git a/bdk/storage/sdmmc_driver.h b/bdk/storage/sdmmc_driver.h index 2937d93..fb2b1b3 100644 --- a/bdk/storage/sdmmc_driver.h +++ b/bdk/storage/sdmmc_driver.h @@ -195,13 +195,13 @@ #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_DDR52 14 +#define SDHCI_TIMING_MMC_HS102 14 #define SDHCI_CAN_64BIT 0x10000000 /*! SDMMC Low power features. */ -#define SDMMC_AUTO_CAL_DISABLE 0 -#define SDMMC_AUTO_CAL_ENABLE 1 +#define SDMMC_POWER_SAVE_DISABLE 0 +#define SDMMC_POWER_SAVE_ENABLE 1 /*! Helper for SWITCH command argument. */ #define SDMMC_SWITCH(mode, index, value) (((mode) << 24) | ((index) << 16) | ((value) << 8)) @@ -213,7 +213,8 @@ typedef struct _sdmmc_t u32 id; u32 divisor; u32 clock_stopped; - int auto_cal_enabled; + int powersave_enabled; + int manual_cal; int card_clock_enabled; int venclkctl_set; u32 venclkctl_tap; @@ -221,6 +222,7 @@ typedef struct _sdmmc_t u32 dma_addr_next; u32 rsp[4]; u32 rsp3; + int t210b01; } sdmmc_t; /*! SDMMC command. */ @@ -246,14 +248,14 @@ typedef struct _sdmmc_req_t 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_set_tap_value(sdmmc_t *sdmmc); +void sdmmc_save_tap_value(sdmmc_t *sdmmc); int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type); -void sdmmc_card_clock_ctrl(sdmmc_t *sdmmc, int auto_cal_enable); +void sdmmc_card_clock_powersave(sdmmc_t *sdmmc, int powersave_enable); int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type); int sdmmc_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 auto_cal_enable); +int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int powersave_enable); 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 c5ecf11..2c1b3a5 100644 --- a/bdk/storage/sdmmc_t210.h +++ b/bdk/storage/sdmmc_t210.h @@ -103,6 +103,7 @@ typedef struct _t210_sdmmc_t vu32 iospare; vu32 mcciffifoctl; vu32 timeoutwcoal; + vu32 unk1; } t210_sdmmc_t; #endif diff --git a/bdk/thermal/fan.c b/bdk/thermal/fan.c index 686f9e8..f39b082 100644 --- a/bdk/thermal/fan.c +++ b/bdk/thermal/fan.c @@ -38,7 +38,7 @@ void set_fan_duty(u32 duty) gpio_config(GPIO_PORT_S, GPIO_PIN_7, GPIO_MODE_GPIO); gpio_output_enable(GPIO_PORT_S, GPIO_PIN_7, GPIO_OUTPUT_DISABLE); - PWM(PWM_CONTROLLER_PWM_CSR_1) = PWM_CSR_EN | (1 << 24); // Max PWM to disable fan. + PWM(PWM_CONTROLLER_PWM_CSR_1) = PWM_CSR_EN | (0x100 << 16); // Max PWM to disable fan. PINMUX_AUX(PINMUX_AUX_LCD_GPIO2) = 1; // Set source to PWM1. gpio_config(GPIO_PORT_V, GPIO_PIN_4, GPIO_MODE_SPIO); // Fan power mode. @@ -55,7 +55,7 @@ void set_fan_duty(u32 duty) // If disabled send a 0 duty. if (inv_duty == 236) { - PWM(PWM_CONTROLLER_PWM_CSR_1) = PWM_CSR_EN | (1 << 24); // Bit 24 is absolute 0%. + PWM(PWM_CONTROLLER_PWM_CSR_1) = PWM_CSR_EN | (0x100 << 16); // Bit 24 is absolute 0%. regulator_disable_5v(REGULATOR_5V_FAN); // Disable fan. diff --git a/bdk/usb/usb_descriptor_types.h b/bdk/usb/usb_descriptor_types.h new file mode 100644 index 0000000..9f86e9d --- /dev/null +++ b/bdk/usb/usb_descriptor_types.h @@ -0,0 +1,238 @@ +/* + * USB driver for Tegra X1 + * + * Copyright (c) 2019-2020 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 _USB_DESCRIPTORS_TYPES_H_ +#define _USB_DESCRIPTORS_TYPES_H_ + +#include + +typedef enum { + USB_DESCRIPTOR_DEVICE = 1, + USB_DESCRIPTOR_CONFIGURATION = 2, + USB_DESCRIPTOR_STRING = 3, + USB_DESCRIPTOR_INTERFACE = 4, + USB_DESCRIPTOR_ENDPOINT = 5, + USB_DESCRIPTOR_DEVICE_QUALIFIER = 6, + USB_DESCRIPTOR_OTHER_SPEED_CONFIGURATION = 7, + USB_DESCRIPTOR_INTERFACE_POWER = 8, + USB_DESCRIPTOR_INTERFACE_OTG = 9, + USB_DESCRIPTOR_DEVICE_BINARY_OBJECT = 15, + USB_DESCRIPTOR_DEVICE_BINARY_OBJECT_CAP = 16, + USB_DESCRIPTOR_HID = 33, + USB_DESCRIPTOR_HID_REPORT = 34 +} usb_desc_type_t; + +typedef enum { + USB_DESCRIPTOR_MS_COMPAT_ID = 4, + USB_DESCRIPTOR_MS_EXTENDED_PROPERTIES = 5 +} usb_vendor_desc_type_t; + +typedef enum { + USB_ATTR_REMOTE_WAKE_UP = 0x20, + USB_ATTR_SELF_POWERED = 0x40, + USB_ATTR_BUS_POWERED_RSVD = 0x80 +} usb_cfg_attr_type_t; + +typedef enum +{ + USB_EP_TYPE_CTRL = 0, + USB_EP_TYPE_ISO = 1, + USB_EP_TYPE_BULK = 2, + USB_EP_TYPE_INTR = 3 +} usb_cfg_ep_type_t; + +/* Device descriptor structure */ +typedef struct _usb_dev_descr_t +{ + u8 bLength; // Size of this descriptor in bytes. + u8 bDescriptorType; // Device Descriptor Type. (USB_DESCRIPTOR_DEVICE) + u16 bcdUSB; // USB Spec. Release number (2.1). + u8 bDeviceClass; // Class is specified in the interface descriptor. + u8 bDeviceSubClass; // SubClass is specified in the interface descriptor. + u8 bDeviceProtocol; // Protocol is specified in the interface descriptor. + u8 bMaxPacketSize; // Maximum packet size for EP0. + u16 idVendor; // Vendor ID assigned by USB forum. + u16 idProduct; // Product ID assigned by Organization. + u16 bcdDevice; // Device Release number in BCD. + u8 iManufacturer; // Index of String descriptor describing Manufacturer. + u8 iProduct; // Index of String descriptor describing Product. + u8 iSerialNumber; // Index of String descriptor describing Serial number. + u8 bNumConfigs; // Number of possible configuration. +} __attribute__((packed)) usb_dev_descr_t; + +/* Device Qualifier descriptor structure */ +typedef struct _usb_dev_qual_descr_t +{ + u8 bLength; // Size of this descriptor in bytes. + u8 bDescriptorType; // Device Descriptor Type. (USB_DESCRIPTOR_DEVICE_QUALIFIER) + u16 bcdUSB; // USB Spec. Release number (2.1). + u8 bDeviceClass; // Class is specified in the interface descriptor. + u8 bDeviceSubClass; // SubClass is specified in the interface descriptor. + u8 bDeviceProtocol; // Protocol is specified in the interface descriptor. + u8 bMaxPacketSize; // Maximum packet size for EP0. + u8 bNumOtherConfigs; // Number of possible other-speed configurations. + u8 bReserved; // Reserved for future use, must be zero +} __attribute__((packed)) usb_dev_qual_descr_t; + +/* Configuration descriptor structure */ +typedef struct _usb_cfg_descr_t +{ + u8 bLength; // Length of this descriptor. + u8 bDescriptorType; // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION). + u16 wTotalLength; // Total length of all descriptors for this configuration. + u8 bNumInterfaces; // Number of interfaces in this configuration. + u8 bConfigurationValue; // Value of this configuration (1 based). + u8 iConfiguration; // Index of String Descriptor describing the configuration. + u8 bmAttributes; // Configuration characteristics. + u8 bMaxPower; // Maximum power consumed by this configuration. +} __attribute__((packed)) usb_cfg_descr_t; + +/* Interface descriptor structure */ +typedef struct _usb_inter_descr_t +{ + u8 bLength; // Length of this descriptor. + u8 bDescriptorType; // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE). + u8 bInterfaceNumber; // Number of this interface (0 based). + u8 bAlternateSetting; // Value of this alternate interface setting. + u8 bNumEndpoints; // Number of endpoints in this interface. + u8 bInterfaceClass; // Class code (assigned by the USB-IF). + u8 bInterfaceSubClass; // Subclass code (assigned by the USB-IF). + u8 bInterfaceProtocol; // Protocol code (assigned by the USB-IF). + u8 iInterface; // Index of String Descriptor describing the interface. +} __attribute__((packed)) usb_inter_descr_t; + +/* HID descriptor structure */ +typedef struct _usb_hid_descr_t +{ + u8 bLength; // Length of this descriptor. + u8 bDescriptorType; // INTERFACE descriptor type (USB_DESCRIPTOR_HID). + u16 bcdHID; // HID class specification release + u8 bCountryCode; // Country code. + u8 bNumDescriptors; // Number of descriptors. + u8 bClassDescriptorType; // Type of class descriptor (USB_DESCRIPTOR_HID_REPORT). + u16 bDescriptorLength; // Report descriptor length. +} __attribute__((packed)) usb_hid_descr_t; + +/* Endpoint descriptor structure */ +typedef struct _usb_ep_descr_t +{ + u8 bLength; // Length of this descriptor. + u8 bDescriptorType; // ENDPOINT descriptor type (USB_DESCRIPTOR_ENDPOINT). + u8 bEndpointAddress; // Endpoint address. bit7 indicates direction (0=OUT, 1=IN). + u8 bmAttributes; // Endpoint transfer type. + u16 wMaxPacketSize; // Maximum packet size. + u8 bInterval; // Polling interval in frames. For Interrupt and Isochronous data transfer only. +} __attribute__((packed)) usb_ep_descr_t; + +typedef struct _usb_cfg_simple_descr_t +{ + usb_cfg_descr_t config; + usb_inter_descr_t interface; + usb_ep_descr_t endpoint[2]; +} __attribute__((packed)) usb_cfg_simple_descr_t; + +typedef struct _usb_cfg_hid_descr_t +{ + usb_cfg_descr_t config; + usb_inter_descr_t interface; + usb_hid_descr_t hid; + usb_ep_descr_t endpoint[2]; +} __attribute__((packed)) usb_cfg_hid_descr_t; + +typedef struct _usb_dev_bot_t +{ + u8 bLength; // Size of this descriptor in bytes. + u8 bDescriptorType; // Device Descriptor Type. (USB_DESCRIPTOR_DEVICE_BINARY_OBJECT) + u16 wTotalLength; // Size of this descriptor in bytes. + u8 bNumDeviceCaps; // Number of device capabilities in this descriptor. + + /* Device Capability USB 2.0 Extension Descriptor */ + /* Needed for a USB2.10 device. */ + u8 bLengthCap0; // Size of this capability descriptor in bytes. + u8 bDescriptorTypeCap0; // Device Capability Descriptor Type. (USB_DESCRIPTOR_DEVICE_BINARY_OBJECT_CAP) + u8 bDevCapabilityTypeCap0; // USB2: 2. + u32 bmAttributesCap0; // bit1: Link Power Management (LPM). + + u8 bLengthCap1; // Size of this capability descriptor in bytes. + u8 bDescriptorTypeCap1; // Device Capability Descriptor Type. (USB_DESCRIPTOR_DEVICE_BINARY_OBJECT_CAP) + u8 bDevCapabilityTypeCap1; // USB3: 3. + u8 bmAttributesCap1; // bit1: Latency Tolerance Messaging (LTM). + u16 wSpeedsSupported; // Supported bus speeds. 1: Low Speed, 2: Full Speed, 4: High Speed, 8: Super Speed. + u8 bFunctionalitySupport; // Lowest speed at which all the functionality is available. 1: Full speed and above. + u8 bU1DevExitLat; // USB3.0 U1 exit latency. + u16 wU2DevExitLat; // USB3.0 U2 exit latency. + +} __attribute__((packed)) usb_dev_bot_t; + +/* Microsoft OS String descriptor structure */ +typedef struct _usb_ms_os_descr_t +{ + u8 bLength; // 0x12 + u8 bDescriptorType; // 3 + u16 wSignature[7]; // "MSFT100" UTF16 LE + u8 bVendorCode; // + u8 bPadding; +} __attribute__((packed)) usb_ms_os_descr_t; + +/* Microsoft Compatible ID Feature descriptor structure */ +typedef struct _usb_ms_cid_descr_t +{ + u32 dLength; + u16 wVersion; + u16 wCompatibilityId; + u8 bSections; + u8 bReserved0[7]; + u8 bInterfaceNumber; + u8 bReserved1; + u8 bCompatibleId[8]; + u8 bSubCompatibleId[8]; + u8 bReserved2[6]; +} __attribute__((packed)) usb_ms_cid_descr_t; + +/* Microsoft Extended Properties Feature descriptor structure */ +typedef struct _usb_ms_ext_prop_descr_t +{ + u32 dLength; + u16 wVersion; + u16 wExtendedProperty; + u16 wSections; + u32 dPropertySize; + u32 dPropertyType; + u16 wPropertyNameLength; + u16 wPropertyName[22]; // UTF16 LE + u32 dPropertyDataLength; + u16 wPropertyData[2]; // UTF16 LE +} __attribute__((packed)) usb_ms_ext_prop_descr_t; + +typedef struct _usb_desc_t +{ + usb_dev_descr_t *dev; + usb_dev_qual_descr_t *dev_qual; + usb_cfg_simple_descr_t *cfg; + usb_cfg_simple_descr_t *cfg_other; + usb_dev_bot_t *dev_bot; + u8 *vendor; + u8 *product; + u8 *serial; + u8 *lang_id; + usb_ms_os_descr_t *ms_os; + usb_ms_cid_descr_t *ms_cid; + usb_ms_ext_prop_descr_t *mx_ext; +} usb_desc_t; + +#endif diff --git a/bdk/usb/usb_descriptors.h b/bdk/usb/usb_descriptors.c similarity index 65% rename from bdk/usb/usb_descriptors.h rename to bdk/usb/usb_descriptors.c index 74556f8..389a70d 100644 --- a/bdk/usb/usb_descriptors.h +++ b/bdk/usb/usb_descriptors.c @@ -1,7 +1,7 @@ /* * USB driver for Tegra X1 * - * Copyright (c) 2019 CTCaer + * Copyright (c) 2019-2020 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,224 +16,10 @@ * along with this program. If not, see . */ -#ifndef _USB_DESCRIPTORS_H_ -#define _USB_DESCRIPTORS_H_ - +#include #include -typedef enum { - USB_DESCRIPTOR_DEVICE = 1, - USB_DESCRIPTOR_CONFIGURATION = 2, - USB_DESCRIPTOR_STRING = 3, - USB_DESCRIPTOR_INTERFACE = 4, - USB_DESCRIPTOR_ENDPOINT = 5, - USB_DESCRIPTOR_DEVICE_QUALIFIER = 6, - USB_DESCRIPTOR_OTHER_SPEED_CONFIGURATION = 7, - USB_DESCRIPTOR_INTERFACE_POWER = 8, - USB_DESCRIPTOR_INTERFACE_OTG = 9, - USB_DESCRIPTOR_DEVICE_BINARY_OBJECT = 15, - USB_DESCRIPTOR_DEVICE_BINARY_OBJECT_CAP = 16, - USB_DESCRIPTOR_HID = 33, - USB_DESCRIPTOR_HID_REPORT = 34 -} usb_desc_type_t; - -typedef enum { - USB_DESCRIPTOR_MS_COMPAT_ID = 4, - USB_DESCRIPTOR_MS_EXTENDED_PROPERTIES = 5 -} usb_vendor_desc_type_t; - -typedef enum { - USB_ATTR_REMOTE_WAKE_UP = 0x20, - USB_ATTR_SELF_POWERED = 0x40, - USB_ATTR_BUS_POWERED_RSVD = 0x80 -} usb_cfg_attr_type_t; - -typedef enum -{ - USB_EP_TYPE_CTRL = 0, - USB_EP_TYPE_ISO = 1, - USB_EP_TYPE_BULK = 2, - USB_EP_TYPE_INTR = 3 -} usb_cfg_ep_type_t; - -/* Device descriptor structure */ -typedef struct _usb_dev_descr_t -{ - u8 bLength; // Size of this descriptor in bytes. - u8 bDescriptorType; // Device Descriptor Type. (USB_DESCRIPTOR_DEVICE) - u16 bcdUSB; // USB Spec. Release number (2.1). - u8 bDeviceClass; // Class is specified in the interface descriptor. - u8 bDeviceSubClass; // SubClass is specified in the interface descriptor. - u8 bDeviceProtocol; // Protocol is specified in the interface descriptor. - u8 bMaxPacketSize; // Maximum packet size for EP0. - u16 idVendor; // Vendor ID assigned by USB forum. - u16 idProduct; // Product ID assigned by Organization. - u16 bcdDevice; // Device Release number in BCD. - u8 iManufacturer; // Index of String descriptor describing Manufacturer. - u8 iProduct; // Index of String descriptor describing Product. - u8 iSerialNumber; // Index of String descriptor describing Serial number. - u8 bNumConfigs; // Number of possible configuration. -} __attribute__((packed)) usb_dev_descr_t; - -/* Device Qualigier descriptor structure */ -typedef struct _usb_dev_qual_descr_t -{ - u8 bLength; // Size of this descriptor in bytes. - u8 bDescriptorType; // Device Descriptor Type. (USB_DESCRIPTOR_DEVICE_QUALIFIER) - u16 bcdUSB; // USB Spec. Release number (2.1). - u8 bDeviceClass; // Class is specified in the interface descriptor. - u8 bDeviceSubClass; // SubClass is specified in the interface descriptor. - u8 bDeviceProtocol; // Protocol is specified in the interface descriptor. - u8 bMaxPacketSize; // Maximum packet size for EP0. - u8 bNumOtherConfigs; // Number of possible other-speed configurations. - u8 bReserved; // Reserved for future use, must be zero -} __attribute__((packed)) usb_dev_qual_descr_t; - -/* Configuration descriptor structure */ -typedef struct _usb_cfg_descr_t -{ - u8 bLength; // Length of this descriptor. - u8 bDescriptorType; // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION). - u16 wTotalLength; // Total length of all descriptors for this configuration. - u8 bNumInterfaces; // Number of interfaces in this configuration. - u8 bConfigurationValue; // Value of this configuration (1 based). - u8 iConfiguration; // Index of String Descriptor describing the configuration. - u8 bmAttributes; // Configuration characteristics. - u8 bMaxPower; // Maximum power consumed by this configuration. -} __attribute__((packed)) usb_cfg_descr_t; - -/* Interface descriptor structure */ -typedef struct _usb_inter_descr_t -{ - u8 bLength; // Length of this descriptor. - u8 bDescriptorType; // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE). - u8 bInterfaceNumber; // Number of this interface (0 based). - u8 bAlternateSetting; // Value of this alternate interface setting. - u8 bNumEndpoints; // Number of endpoints in this interface. - u8 bInterfaceClass; // Class code (assigned by the USB-IF). - u8 bInterfaceSubClass; // Subclass code (assigned by the USB-IF). - u8 bInterfaceProtocol; // Protocol code (assigned by the USB-IF). - u8 iInterface; // Index of String Descriptor describing the interface. -} __attribute__((packed)) usb_inter_descr_t; - -/* HID descriptor structure */ -typedef struct _usb_hid_descr_t -{ - u8 bLength; // Length of this descriptor. - u8 bDescriptorType; // INTERFACE descriptor type (USB_DESCRIPTOR_HID). - u16 bcdHID; // HID class specification release - u8 bCountryCode; // Country code. - u8 bNumDescriptors; // Number of descriptors. - u8 bClassDescriptorType; // Type of class descriptor (USB_DESCRIPTOR_HID_REPORT). - u16 bDescriptorLength; // Report descriptor length. -} __attribute__((packed)) usb_hid_descr_t; - -/* Endpoint descriptor structure */ -typedef struct _usb_ep_descr_t -{ - u8 bLength; // Length of this descriptor. - u8 bDescriptorType; // ENDPOINT descriptor type (USB_DESCRIPTOR_ENDPOINT). - u8 bEndpointAddress; // Endpoint address. bit7 indicates direction (0=OUT, 1=IN). - u8 bmAttributes; // Endpoint transfer type. - u16 wMaxPacketSize; // Maximum packet size. - u8 bInterval; // Polling interval in frames. For Interrupt and Isochronous data transfer only. -} __attribute__((packed)) usb_ep_descr_t; - -typedef struct _usb_cfg_simple_descr_t -{ - usb_cfg_descr_t config; - usb_inter_descr_t interface; - usb_ep_descr_t endpoint[2]; -} __attribute__((packed)) usb_cfg_simple_descr_t; - -typedef struct _usb_cfg_hid_descr_t -{ - usb_cfg_descr_t config; - usb_inter_descr_t interface; - usb_hid_descr_t hid; - usb_ep_descr_t endpoint[2]; -} __attribute__((packed)) usb_cfg_hid_descr_t; - -typedef struct _usb_dev_bot_t -{ - u8 bLength; // Size of this descriptor in bytes. - u8 bDescriptorType; // Device Descriptor Type. (USB_DESCRIPTOR_DEVICE_BINARY_OBJECT) - u16 wTotalLength; // Size of this descriptor in bytes. - u8 bNumDeviceCaps; // Number of device capabilities in this descriptor. - - /* Device Capability USB 2.0 Extension Descriptor */ - /* Needed for a USB2.10 device. */ - u8 bLengthCap0; // Size of this capability descriptor in bytes. - u8 bDescriptorTypeCap0; // Device Capability Descriptor Type. (USB_DESCRIPTOR_DEVICE_BINARY_OBJECT_CAP) - u8 bDevCapabilityTypeCap0; // USB2: 2. - u32 bmAttributesCap0; // bit1: Link Power Management (LPM). - - u8 bLengthCap1; // Size of this capability descriptor in bytes. - u8 bDescriptorTypeCap1; // Device Capability Descriptor Type. (USB_DESCRIPTOR_DEVICE_BINARY_OBJECT_CAP) - u8 bDevCapabilityTypeCap1; // USB3: 3. - u8 bmAttributesCap1; // bit1: Latency Tolerance Messaging (LTM). - u16 wSpeedsSupported; // Supported bus speeds. 1: Low Speed, 2: Full Speed, 4: High Speed, 8: Super Speed. - u8 bFunctionalitySupport; // Lowest speed at which all the functionality is available. 1: Full speed and above. - u8 bU1DevExitLat; // USB3.0 U1 exit latency. - u16 wU2DevExitLat; // USB3.0 U2 exit latency. - -} __attribute__((packed)) usb_dev_bot_t; - -/* Microsoft OS String descriptor structure */ -typedef struct _usb_ms_os_descr_t -{ - u8 bLength; // 0x12 - u8 bDescriptorType; // 3 - u16 wSignature[7]; // "MSFT100" UTF16 LE - u8 bVendorCode; // - u8 bPadding; -} __attribute__((packed)) usb_ms_os_descr_t; - -/* Microsoft Compatible ID Feature descriptor structure */ -typedef struct _usb_ms_cid_descr_t -{ - u32 dLength; - u16 wVersion; - u16 wCompatibilityId; - u8 bSections; - u8 bReserved0[7]; - u8 bInterfaceNumber; - u8 bReserved1; - u8 bCompatibleId[8]; - u8 bSubCompatibleId[8]; - u8 bReserved2[6]; -} __attribute__((packed)) usb_ms_cid_descr_t; - -/* Microsoft Extended Properties Feature descriptor structure */ -typedef struct _usb_ms_ext_prop_descr_t -{ - u32 dLength; - u16 wVersion; - u16 wExtendedProperty; - u16 wSections; - u32 dPropertySize; - u32 dPropertyType; - u16 wPropertyNameLength; - u16 wPropertyName[22]; // UTF16 LE - u32 dPropertyDataLength; - u16 wPropertyData[2]; // UTF16 LE -} __attribute__((packed)) usb_ms_ext_prop_descr_t; - -typedef struct _usb_desc_t -{ - usb_dev_descr_t *dev; - usb_dev_qual_descr_t *dev_qual; - usb_cfg_simple_descr_t *cfg; - usb_cfg_simple_descr_t *cfg_other; - usb_dev_bot_t *dev_bot; - u8 *vendor; - u8 *product; - usb_ms_os_descr_t *ms_os; - usb_ms_cid_descr_t *ms_cid; - usb_ms_ext_prop_descr_t *mx_ext; -} usb_desc_t; - -usb_dev_descr_t usb_device_descriptor_ums = +static usb_dev_descr_t usb_device_descriptor_ums = { .bLength = 18, .bDescriptorType = USB_DESCRIPTOR_DEVICE, @@ -251,7 +37,7 @@ usb_dev_descr_t usb_device_descriptor_ums = .bNumConfigs = 1 }; -usb_dev_qual_descr_t usb_device_qualifier_descriptor = +static usb_dev_qual_descr_t usb_device_qualifier_descriptor = { .bLength = 10, .bDescriptorType = USB_DESCRIPTOR_DEVICE_QUALIFIER, @@ -264,7 +50,7 @@ usb_dev_qual_descr_t usb_device_qualifier_descriptor = .bReserved = 0x00 }; -usb_cfg_simple_descr_t usb_configuration_descriptor_ums = +static usb_cfg_simple_descr_t usb_configuration_descriptor_ums = { /* Configuration descriptor structure */ .config.bLength = 9, @@ -304,7 +90,7 @@ usb_cfg_simple_descr_t usb_configuration_descriptor_ums = .endpoint[1].bInterval = 0x00 }; -usb_cfg_simple_descr_t usb_other_speed_config_descriptor_ums = +static usb_cfg_simple_descr_t usb_other_speed_config_descriptor_ums = { /* Other Speed Configuration descriptor structure */ .config.bLength = 9, @@ -344,7 +130,7 @@ usb_cfg_simple_descr_t usb_other_speed_config_descriptor_ums = .endpoint[1].bInterval = 0 }; -usb_dev_bot_t usb_device_binary_object_descriptor = +static usb_dev_bot_t usb_device_binary_object_descriptor = { .bLength = 5, .bDescriptorType = USB_DESCRIPTOR_DEVICE_BINARY_OBJECT, @@ -369,20 +155,33 @@ usb_dev_bot_t usb_device_binary_object_descriptor = .wU2DevExitLat = 0 }; -u8 usb_vendor_string_descriptor_ums[32] = +static u8 usb_lang_id_string_descriptor[4] = +{ + 4, 3, + 0x09, 0x04 +}; + +static u8 usb_serial_string_descriptor[26] = +{ + 26, 0x03, + 'C', 0x00, '7', 0x00, 'C', 0x00, '0', 0x00, + '9', 0x00, '2', 0x00, '4', 0x00, '2', 0x00, 'F', 0x00, '7', 0x00, '0', 0x00, '3', 0x00 +}; + +static u8 usb_vendor_string_descriptor_ums[32] = { 26, 0x03, 'N', 0, 'y', 0, 'x', 0, ' ', 0, 'U', 0, 'S', 0, 'B', 0, ' ', 0, 'D', 0, 'i', 0, 's', 0, 'k', 0 }; -u8 usb_product_string_descriptor_ums[22] = +static u8 usb_product_string_descriptor_ums[22] = { 8, 0x03, 'U', 0, 'M', 0, 'S', 0 }; -usb_ms_os_descr_t usb_ms_os_descriptor = +static usb_ms_os_descr_t usb_ms_os_descriptor = { .bLength = 0x28, .bDescriptorType = 0x03, @@ -396,7 +195,7 @@ usb_ms_os_descr_t usb_ms_os_descriptor = .bVendorCode = 0x99, }; -usb_ms_cid_descr_t usb_ms_cid_descriptor = +static usb_ms_cid_descr_t usb_ms_cid_descriptor = { .dLength = 0x28, .wVersion = 0x100, @@ -413,7 +212,7 @@ usb_ms_cid_descr_t usb_ms_cid_descriptor = .bCompatibleId[5] = 'B', }; -usb_ms_ext_prop_descr_t usb_ms_ext_prop_descriptor_ums = +static usb_ms_ext_prop_descr_t usb_ms_ext_prop_descriptor_ums = { .dLength = 0x48, .wVersion = 0x100, @@ -452,7 +251,7 @@ usb_ms_ext_prop_descr_t usb_ms_ext_prop_descriptor_ums = .wPropertyData[1] = 0x10, }; -usb_ms_ext_prop_descr_t usb_ms_ext_prop_descriptor_hid = +static usb_ms_ext_prop_descr_t usb_ms_ext_prop_descriptor_hid = { .dLength = 7, .wVersion = 0x100, @@ -460,7 +259,7 @@ usb_ms_ext_prop_descr_t usb_ms_ext_prop_descriptor_hid = .wSections = 0, }; -usb_dev_descr_t usb_device_descriptor_hid_jc = +static usb_dev_descr_t usb_device_descriptor_hid_jc = { .bLength = 18, .bDescriptorType = USB_DESCRIPTOR_DEVICE, @@ -478,7 +277,7 @@ usb_dev_descr_t usb_device_descriptor_hid_jc = .bNumConfigs = 1 }; -usb_dev_descr_t usb_device_descriptor_hid_touch = +static usb_dev_descr_t usb_device_descriptor_hid_touch = { .bLength = 18, .bDescriptorType = USB_DESCRIPTOR_DEVICE, @@ -496,75 +295,6 @@ usb_dev_descr_t usb_device_descriptor_hid_touch = .bNumConfigs = 1 }; -usb_cfg_hid_descr_t usb_configuration_descriptor_hid_jc = -{ - /* Configuration descriptor structure */ - .config.bLength = 9, - .config.bDescriptorType = USB_DESCRIPTOR_CONFIGURATION, - .config.wTotalLength = sizeof(usb_cfg_hid_descr_t), - .config.bNumInterfaces = 0x01, - .config.bConfigurationValue = 0x01, - .config.iConfiguration = 0x00, - .config.bmAttributes = USB_ATTR_SELF_POWERED | USB_ATTR_BUS_POWERED_RSVD, - .config.bMaxPower = 32 / 2, - - /* Interface descriptor structure */ - .interface.bLength = 9, - .interface.bDescriptorType = USB_DESCRIPTOR_INTERFACE, - .interface.bInterfaceNumber = 0, - .interface.bAlternateSetting = 0, - .interface.bNumEndpoints = 2, - .interface.bInterfaceClass = 0x03, // Human Interface Device Class. - .interface.bInterfaceSubClass = 0x00, // SCSI Transparent Command Set. - .interface.bInterfaceProtocol = 0x00, // Bulk-Only Transport. - .interface.iInterface = 0x00, - - .hid.bLength = 9, - .hid.bDescriptorType = USB_DESCRIPTOR_HID, - .hid.bcdHID = 0x110, - .hid.bCountryCode = 0, - .hid.bNumDescriptors = 1, - .hid.bClassDescriptorType = USB_DESCRIPTOR_HID_REPORT, - .hid.bDescriptorLength = 0x43, - - /* Endpoint descriptor structure EP1 IN */ - .endpoint[0].bLength = 7, - .endpoint[0].bDescriptorType = USB_DESCRIPTOR_ENDPOINT, - .endpoint[0].bEndpointAddress = 0x81, // USB_EP_ADDR_BULK_IN. - .endpoint[0].bmAttributes = USB_EP_TYPE_INTR, - .endpoint[0].wMaxPacketSize = 0x200, - .endpoint[0].bInterval = 4, // 4ms on FS, 8ms on HS. - - /* Endpoint descriptor structure EP1 OUT */ - .endpoint[1].bLength = 7, - .endpoint[1].bDescriptorType = USB_DESCRIPTOR_ENDPOINT, - .endpoint[1].bEndpointAddress = 0x01, // USB_EP_ADDR_BULK_OUT. - .endpoint[1].bmAttributes = USB_EP_TYPE_INTR, - .endpoint[1].wMaxPacketSize = 0x200, - .endpoint[1].bInterval = 4 // 4ms on FS, 8ms on HS. -}; - -u8 usb_vendor_string_descriptor_hid[22] = -{ - 16, 0x03, - 'N', 0, 'y', 0, 'x', 0, ' ', 0, - 'U', 0, 'S', 0, 'B', 0 -}; - -u8 usb_product_string_descriptor_hid_jc[24] = -{ - 24, 0x03, - 'N', 0, 'y', 0, 'x', 0, ' ', 0, - 'J', 0, 'o', 0, 'y', 0, '-', 0, 'C', 0, 'o', 0, 'n', 0 -}; - -u8 usb_product_string_descriptor_hid_touch[26] = -{ - 26, 0x03, - 'N', 0, 'y', 0, 'x', 0, ' ', 0, - 'T', 0, 'o', 0, 'u', 0, 'c', 0, 'h', 0, 'p', 0, 'a', 0, 'd', 0 -}; - u8 hid_report_descriptor_jc[] = { 0x05, 0x01, // USAGE_PAGE (Generic Desktop), @@ -602,6 +332,8 @@ u8 hid_report_descriptor_jc[] = 0xc0 // END_COLLECTION(), }; +u32 hid_report_descriptor_jc_size = sizeof(hid_report_descriptor_jc); + u8 hid_report_descriptor_touch[] = { 0x05, 0x0d, // USAGE_PAGE (Digitizers) @@ -658,8 +390,78 @@ u8 hid_report_descriptor_touch[] = 0xc0, // END_COLLECTION 0xc0, // END_COLLECTION }; +u32 hid_report_descriptor_touch_size = sizeof(hid_report_descriptor_touch); -usb_cfg_hid_descr_t usb_configuration_descriptor_hid_touch = +static usb_cfg_hid_descr_t usb_configuration_descriptor_hid_jc = +{ + /* Configuration descriptor structure */ + .config.bLength = 9, + .config.bDescriptorType = USB_DESCRIPTOR_CONFIGURATION, + .config.wTotalLength = sizeof(usb_cfg_hid_descr_t), + .config.bNumInterfaces = 0x01, + .config.bConfigurationValue = 0x01, + .config.iConfiguration = 0x00, + .config.bmAttributes = USB_ATTR_SELF_POWERED | USB_ATTR_BUS_POWERED_RSVD, + .config.bMaxPower = 32 / 2, + + /* Interface descriptor structure */ + .interface.bLength = 9, + .interface.bDescriptorType = USB_DESCRIPTOR_INTERFACE, + .interface.bInterfaceNumber = 0, + .interface.bAlternateSetting = 0, + .interface.bNumEndpoints = 2, + .interface.bInterfaceClass = 0x03, // Human Interface Device Class. + .interface.bInterfaceSubClass = 0x00, // SCSI Transparent Command Set. + .interface.bInterfaceProtocol = 0x00, // Bulk-Only Transport. + .interface.iInterface = 0x00, + + .hid.bLength = 9, + .hid.bDescriptorType = USB_DESCRIPTOR_HID, + .hid.bcdHID = 0x110, + .hid.bCountryCode = 0, + .hid.bNumDescriptors = 1, + .hid.bClassDescriptorType = USB_DESCRIPTOR_HID_REPORT, + .hid.bDescriptorLength = sizeof(hid_report_descriptor_jc), + + /* Endpoint descriptor structure EP1 IN */ + .endpoint[0].bLength = 7, + .endpoint[0].bDescriptorType = USB_DESCRIPTOR_ENDPOINT, + .endpoint[0].bEndpointAddress = 0x81, // USB_EP_ADDR_BULK_IN. + .endpoint[0].bmAttributes = USB_EP_TYPE_INTR, + .endpoint[0].wMaxPacketSize = 0x200, + .endpoint[0].bInterval = 4, // 8ms on HS. + + /* Endpoint descriptor structure EP1 OUT */ + .endpoint[1].bLength = 7, + .endpoint[1].bDescriptorType = USB_DESCRIPTOR_ENDPOINT, + .endpoint[1].bEndpointAddress = 0x01, // USB_EP_ADDR_BULK_OUT. + .endpoint[1].bmAttributes = USB_EP_TYPE_INTR, + .endpoint[1].wMaxPacketSize = 0x200, + .endpoint[1].bInterval = 4 // 8ms on HS. +}; + +static u8 usb_vendor_string_descriptor_hid[22] = +{ + 16, 0x03, + 'N', 0, 'y', 0, 'x', 0, ' ', 0, + 'U', 0, 'S', 0, 'B', 0 +}; + +static u8 usb_product_string_descriptor_hid_jc[24] = +{ + 24, 0x03, + 'N', 0, 'y', 0, 'x', 0, ' ', 0, + 'J', 0, 'o', 0, 'y', 0, '-', 0, 'C', 0, 'o', 0, 'n', 0 +}; + +static u8 usb_product_string_descriptor_hid_touch[26] = +{ + 26, 0x03, + 'N', 0, 'y', 0, 'x', 0, ' ', 0, + 'T', 0, 'o', 0, 'u', 0, 'c', 0, 'h', 0, 'p', 0, 'a', 0, 'd', 0 +}; + +static usb_cfg_hid_descr_t usb_configuration_descriptor_hid_touch = { /* Configuration descriptor structure */ .config.bLength = 9, @@ -696,7 +498,7 @@ usb_cfg_hid_descr_t usb_configuration_descriptor_hid_touch = .endpoint[0].bEndpointAddress = 0x81, // USB_EP_ADDR_BULK_IN. .endpoint[0].bmAttributes = USB_EP_TYPE_INTR, .endpoint[0].wMaxPacketSize = 0x200, - .endpoint[0].bInterval = 4, // 4ms on FS, 8ms on HS. + .endpoint[0].bInterval = 3, // 4ms on HS. /* Endpoint descriptor structure EP1 OUT */ .endpoint[1].bLength = 7, @@ -704,7 +506,7 @@ usb_cfg_hid_descr_t usb_configuration_descriptor_hid_touch = .endpoint[1].bEndpointAddress = 0x01, // USB_EP_ADDR_BULK_OUT. .endpoint[1].bmAttributes = USB_EP_TYPE_INTR, .endpoint[1].wMaxPacketSize = 0x200, - .endpoint[1].bInterval = 4 // 4ms on FS, 8ms on HS. + .endpoint[1].bInterval = 3 // 4ms on HS. }; usb_desc_t usb_gadget_ums_descriptors = @@ -716,6 +518,8 @@ usb_desc_t usb_gadget_ums_descriptors = .dev_bot = &usb_device_binary_object_descriptor, .vendor = usb_vendor_string_descriptor_ums, .product = usb_product_string_descriptor_ums, + .serial = usb_serial_string_descriptor, + .lang_id = usb_lang_id_string_descriptor, .ms_os = &usb_ms_os_descriptor, .ms_cid = &usb_ms_cid_descriptor, .mx_ext = &usb_ms_ext_prop_descriptor_ums @@ -730,6 +534,8 @@ usb_desc_t usb_gadget_hid_jc_descriptors = .dev_bot = &usb_device_binary_object_descriptor, .vendor = usb_vendor_string_descriptor_hid, .product = usb_product_string_descriptor_hid_jc, + .serial = usb_serial_string_descriptor, + .lang_id = usb_lang_id_string_descriptor, .ms_os = &usb_ms_os_descriptor, .ms_cid = &usb_ms_cid_descriptor, .mx_ext = &usb_ms_ext_prop_descriptor_hid @@ -744,9 +550,9 @@ usb_desc_t usb_gadget_hid_touch_descriptors = .dev_bot = &usb_device_binary_object_descriptor, .vendor = usb_vendor_string_descriptor_hid, .product = usb_product_string_descriptor_hid_touch, + .serial = usb_serial_string_descriptor, + .lang_id = usb_lang_id_string_descriptor, .ms_os = &usb_ms_os_descriptor, .ms_cid = &usb_ms_cid_descriptor, .mx_ext = &usb_ms_ext_prop_descriptor_hid }; - -#endif diff --git a/bdk/usb/usb_gadget_hid.c b/bdk/usb/usb_gadget_hid.c index e26dd9a..3437b40 100644 --- a/bdk/usb/usb_gadget_hid.c +++ b/bdk/usb/usb_gadget_hid.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include @@ -67,6 +69,7 @@ typedef struct _jc_cal_t } jc_cal_t; static jc_cal_t jc_cal_ctx; +static usb_ops_t usb_ops; static bool _jc_calibration(jc_gamepad_rpt_t *jc_pad) { @@ -306,16 +309,16 @@ static bool _fts_touch_read(touchpad_report_t *rpt) static u8 _hid_transfer_start(usb_ctxt_t *usbs, u32 len) { - u8 status = usb_device_write_ep1_in((u8 *)USB_EP_BULK_IN_BUF_ADDR, len, NULL, true); - - if (status == 26) + u8 status = usb_ops.usb_device_ep1_in_write((u8 *)USB_EP_BULK_IN_BUF_ADDR, len, NULL, USB_XFER_SYNCED); + if (status == USB_ERROR_XFER_ERROR) { - usbs->set_text(usbs->label, "#C7EA46 Status:# Error EP IN"); - usbd_flush_endpoint(3); + usbs->set_text(usbs->label, "#FFDD00 Error:# EP IN transfer!"); + if (usb_ops.usbd_flush_endpoint) + usb_ops.usbd_flush_endpoint(USB_EP_BULK_IN); } // Linux mitigation: If timed out, clear status. - if (status == 3) + if (status == USB_ERROR_TIMEOUT) return 0; return status; @@ -350,6 +353,12 @@ int usb_device_gadget_hid(usb_ctxt_t *usbs) u32 gadget_type; u32 polling_time; + // Get USB Controller ops. + if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210) + usb_device_get_ops(&usb_ops); + else + xusb_device_get_ops(&usb_ops); + if (usbs->type == USB_HID_GAMEPAD) { polling_time = 8000; @@ -363,21 +372,21 @@ int usb_device_gadget_hid(usb_ctxt_t *usbs) usbs->set_text(usbs->label, "#C7EA46 Status:# Started USB"); - if (usb_device_init()) + if (usb_ops.usb_device_init()) { - usbd_end(false, true); + usb_ops.usbd_end(false, true); return 1; } usbs->set_text(usbs->label, "#C7EA46 Status:# Waiting for connection"); // Initialize Control Endpoint. - if (usb_device_ep0_initialize(gadget_type)) + if (usb_ops.usb_device_enumerate(gadget_type)) goto error; usbs->set_text(usbs->label, "#C7EA46 Status:# Waiting for HID report request"); - if (usb_device_get_hid_report()) + if (usb_ops.usb_device_class_send_hid_report()) goto error; usbs->set_text(usbs->label, "#C7EA46 Status:# Started HID emulation"); @@ -400,11 +409,11 @@ int usb_device_gadget_hid(usb_ctxt_t *usbs) } // Check for suspended USB in case the cable was pulled. - if (usb_device_get_suspended()) + if (usb_ops.usb_device_get_suspended()) break; // Disconnected. // Handle control endpoint. - usbd_handle_ep0_pending_control_transfer(); + usb_ops.usbd_handle_ep0_ctrl_setup(); // Wait max gadget timing. timer = get_tmr_us() - timer; @@ -422,11 +431,11 @@ int usb_device_gadget_hid(usb_ctxt_t *usbs) goto exit; error: - usbs->set_text(usbs->label, "#C7EA46 Status:# Timed out or canceled"); + usbs->set_text(usbs->label, "#FFDD00 Error:# Timed out or canceled"); res = 1; exit: - usbd_end(true, false); + usb_ops.usbd_end(true, false); return res; } diff --git a/bdk/usb/usb_gadget_ums.c b/bdk/usb/usb_gadget_ums.c index 01ab237..97deeb5 100644 --- a/bdk/usb/usb_gadget_ums.c +++ b/bdk/usb/usb_gadget_ums.c @@ -23,6 +23,8 @@ #include #include +#include +#include #include #include #include @@ -198,7 +200,6 @@ typedef struct _usbd_gadget_ums_t { u32 lun_idx; // lun index logical_unit_t lun; - u32 bulk_out_maxpacket; // 512 enum ums_state state; // For exception handling. enum data_direction data_dir; @@ -215,12 +216,15 @@ typedef struct _usbd_gadget_ums_t { int can_stall; u32 timeouts; + bool xusb; void (*system_maintenance)(bool); void *label; void (*set_text)(void *, const char *); } usbd_gadget_ums_t; +static usb_ops_t usb_ops; + static inline void put_array_le_to_be16(u16 val, void *p) { u8 *_p = p; @@ -271,7 +275,7 @@ static void raise_exception(usbd_gadget_ums_t *ums, enum ums_state new_state) static void ums_handle_ep0_ctrl(usbd_gadget_ums_t *ums) { - if (usbd_handle_ep0_pending_control_transfer()) + if (usb_ops.usbd_handle_ep0_ctrl_setup()) raise_exception(ums, UMS_STATE_PROTOCOL_RESET); } @@ -284,46 +288,56 @@ static int ums_wedge_bulk_in_endpoint(usbd_gadget_ums_t *ums) static int ums_set_stall(u32 ep) { - usbd_set_ep_stall(ep, 1); + usb_ops.usbd_set_ep_stall(ep, USB_EP_CFG_STALL); return 0; } static int ums_clear_stall(u32 ep) { - usbd_set_ep_stall(ep, 0); + usb_ops.usbd_set_ep_stall(ep, USB_EP_CFG_CLEAR); return 0; } +static void ums_flush_endpoint(u32 ep) +{ + if (usb_ops.usbd_flush_endpoint) + usb_ops.usbd_flush_endpoint(ep); +} + static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32 ep, bool sync) { if (ep == bulk_ctxt->bulk_in) { - bulk_ctxt->bulk_in_status = usb_device_write_ep1_in( + bulk_ctxt->bulk_in_status = usb_ops.usb_device_ep1_in_write( bulk_ctxt->bulk_in_buf, bulk_ctxt->bulk_in_length, &bulk_ctxt->bulk_in_length_actual, sync); - if (bulk_ctxt->bulk_in_status == 26) + if (bulk_ctxt->bulk_in_status == USB_ERROR_XFER_ERROR) { - ums->set_text(ums->label, "#C7EA46 Status:# Error EP IN"); - usbd_flush_endpoint(bulk_ctxt->bulk_in); + ums->set_text(ums->label, "#FFDD00 Error:# EP IN transfer!"); + ums_flush_endpoint(bulk_ctxt->bulk_in); } + else if (bulk_ctxt->bulk_in_status == USB2_ERROR_XFER_NOT_ALIGNED) + ums->set_text(ums->label, "#FFDD00 Error:# EP IN Buffer not aligned!"); if (sync) bulk_ctxt->bulk_in_buf_state = BUF_STATE_EMPTY; } else { - bulk_ctxt->bulk_out_status = usb_device_read_ep1_out( + bulk_ctxt->bulk_out_status = usb_ops.usb_device_ep1_out_read( bulk_ctxt->bulk_out_buf, bulk_ctxt->bulk_out_length, &bulk_ctxt->bulk_out_length_actual, sync); - if (bulk_ctxt->bulk_out_status == 26) + if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR) { - ums->set_text(ums->label, "#C7EA46 Status:# Error EP OUT"); - usbd_flush_endpoint(bulk_ctxt->bulk_out); + ums->set_text(ums->label, "#FFDD00 Error:# EP OUT transfer!"); + ums_flush_endpoint(bulk_ctxt->bulk_out); } + else if (bulk_ctxt->bulk_out_status == USB2_ERROR_XFER_NOT_ALIGNED) + ums->set_text(ums->label, "#FFDD00 Error:# EP OUT Buffer not aligned!"); if (sync) bulk_ctxt->bulk_out_buf_state = BUF_STATE_FULL; @@ -332,14 +346,14 @@ static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, static void _ums_transfer_out_big_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { - bulk_ctxt->bulk_out_status = usb_device_read_ep1_out_big_reads( + bulk_ctxt->bulk_out_status = usb_ops.usb_device_ep1_out_read_big( bulk_ctxt->bulk_out_buf, bulk_ctxt->bulk_out_length, &bulk_ctxt->bulk_out_length_actual); - if (bulk_ctxt->bulk_out_status == 26) + if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR) { - ums->set_text(ums->label, "#C7EA46 Status:# Error EP OUT"); - usbd_flush_endpoint(bulk_ctxt->bulk_out); + ums->set_text(ums->label, "#FFDD00 Error:# EP OUT transfer!"); + ums_flush_endpoint(bulk_ctxt->bulk_out); } bulk_ctxt->bulk_out_buf_state = BUF_STATE_FULL; @@ -349,24 +363,26 @@ static void _ums_transfer_finish(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, { if (ep == bulk_ctxt->bulk_in) { - bulk_ctxt->bulk_in_status = usb_device_ep1_in_writing_finish(&bulk_ctxt->bulk_in_length_actual); + bulk_ctxt->bulk_in_status = usb_ops.usb_device_ep1_in_writing_finish( + &bulk_ctxt->bulk_in_length_actual); - if (bulk_ctxt->bulk_in_status == 26) + if (bulk_ctxt->bulk_in_status == USB_ERROR_XFER_ERROR) { - ums->set_text(ums->label, "#C7EA46 Status:# Error EP IN"); - usbd_flush_endpoint(bulk_ctxt->bulk_in); + ums->set_text(ums->label, "#FFDD00 Error:# EP IN transfer!"); + ums_flush_endpoint(bulk_ctxt->bulk_in); } bulk_ctxt->bulk_in_buf_state = BUF_STATE_EMPTY; } else { - bulk_ctxt->bulk_out_status = usb_device_ep1_out_reading_finish(&bulk_ctxt->bulk_out_length_actual); + bulk_ctxt->bulk_out_status = usb_ops.usb_device_ep1_out_reading_finish( + &bulk_ctxt->bulk_out_length_actual, 1000000); - if (bulk_ctxt->bulk_out_status == 26) + if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR) { - ums->set_text(ums->label, "#C7EA46 Status:# Error EP OUT"); - usbd_flush_endpoint(bulk_ctxt->bulk_out); + ums->set_text(ums->label, "#FFDD00 Error:# EP OUT transfer!"); + ums_flush_endpoint(bulk_ctxt->bulk_out); } bulk_ctxt->bulk_out_buf_state = BUF_STATE_FULL; @@ -485,7 +501,7 @@ static int _scsi_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) // If an error occurred, report it and its position. if (!amount) { - ums->set_text(ums->label, "#C7EA46 Status:# Error SDMMC Read"); + ums->set_text(ums->label, "#FFDD00 Error:# SDMMC Read!"); ums->lun.sense_data = SS_UNRECOVERED_READ_ERROR; ums->lun.sense_data_info = lba_offset; ums->lun.info_valid = 1; @@ -497,7 +513,7 @@ static int _scsi_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) break; // Start the USB transfer. - _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, false); + _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_START); first_read = false; // Increment our buffer to read new data. @@ -568,7 +584,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) if (usb_lba_offset >= ums->lun.num_sectors) //////////Check if it works with concurrency { - ums->set_text(ums->label, "#C7EA46 Status:# Write Error - Past last sector"); + ums->set_text(ums->label, "#FFDD00 Error:# Write - Past last sector!"); amount_left_to_req = 0; ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; ums->lun.sense_data_info = usb_lba_offset; @@ -596,7 +612,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) ums->lun.sense_data = SS_COMMUNICATION_FAILURE; ums->lun.sense_data_info = lba_offset; ums->lun.info_valid = 1; - sprintf(txt_buf, "#C7EA46 Status:# Write Error - Comm failure %d", bulk_ctxt->bulk_out_status); + sprintf(txt_buf, "#FFDD00 Error:# Write - Comm failure %d!", bulk_ctxt->bulk_out_status); ums->set_text(ums->label, txt_buf); break; } @@ -634,7 +650,7 @@ DPRINTF("file write %X @ %X\n", amount, lba_offset); /* If an error occurred, report it and its position */ if (!amount) { - ums->set_text(ums->label, "#C7EA46 Status:# Error SDMMC Write"); + ums->set_text(ums->label, "#FFDD00 Error:# SDMMC Write!"); ums->lun.sense_data = SS_WRITE_ERROR; ums->lun.sense_data_info = lba_offset; ums->lun.info_valid = 1; @@ -645,7 +661,7 @@ DPRINTF("file write %X @ %X\n", amount, lba_offset); // Did the host decide to stop early? if (bulk_ctxt->bulk_out_length_actual < bulk_ctxt->bulk_out_length) { - ums->set_text(ums->label, "#C7EA46 Status:# Empty Write"); + ums->set_text(ums->label, "#FFDD00 Error:# Empty Write!"); ums->short_packet_received = 1; break; } @@ -699,7 +715,7 @@ DPRINTF("File read %X @ %X\n", amount, lba_offset); if (!amount) { - ums->set_text(ums->label, "#C7EA46 Status:# Error file verify"); + ums->set_text(ums->label, "#FFDD00 Error:# File verify!"); ums->lun.sense_data = SS_UNRECOVERED_READ_ERROR; ums->lun.sense_data_info = lba_offset; ums->lun.info_valid = 1; @@ -943,7 +959,7 @@ static int _scsi_mode_sense(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) buf += 4; } else // SC_MODE_SENSE_10. - { + { buf[3] = (ums->lun.ro ? 0x80 : 0x00); // WP, DPOFUA. buf += 8; } @@ -1158,7 +1174,7 @@ DPRINTF("SCSI command: %X; Dc=%d, D%c=%X; Hc=%d, H%c=%X\n", ums->cmnd[1] &= 0x1F; // Mask away the LUN. for (u32 i = 1; i < cmnd_size; ++i) { - if (ums->cmnd[i] && !(mask & (1 << i))) + if (ums->cmnd[i] && !(mask & BIT(i))) { ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; @@ -1382,7 +1398,7 @@ static int pad_with_zeros(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) u32 nsend = MIN(ums->usb_amount_left, USB_EP_BUFFER_MAX_SIZE); memset(bulk_ctxt->bulk_in_buf + current_len_to_keep, 0, nsend - current_len_to_keep); bulk_ctxt->bulk_in_length = nsend; - _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, true); + _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED); ums->usb_amount_left -= nsend; current_len_to_keep = 0; } @@ -1400,7 +1416,7 @@ static int throw_away_data(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) u32 amount = MIN(ums->usb_amount_left, USB_EP_BUFFER_MAX_SIZE); bulk_ctxt->bulk_out_length = amount; - _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, true); + _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED); ums->usb_amount_left -= amount; return 0; @@ -1412,7 +1428,7 @@ static int throw_away_data(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) // A short packet or an error ends everything. if (bulk_ctxt->bulk_out_length_actual != bulk_ctxt->bulk_out_length || - bulk_ctxt->bulk_out_status != 0) + bulk_ctxt->bulk_out_status != USB_RES_OK) { raise_exception(ums, UMS_STATE_ABORT_BULK_OUT); return -4; // Interrupted system call @@ -1436,7 +1452,7 @@ static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { ums_set_stall(bulk_ctxt->bulk_out); rc = ums_set_stall(bulk_ctxt->bulk_in); - ums->set_text(ums->label, "#C7EA46 Status:# Direction unknown. Stalled both EP"); + ums->set_text(ums->label, "#FFDD00 Error:# Direction unknown. Stalled both EP!"); } // Else do nothing. break; @@ -1447,7 +1463,7 @@ static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) // If there's no residue, simply send the last buffer. if (!ums->residue) { - _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, true); + _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED); /* For Bulk-only, if we're allowed to stall then send the * short packet and halt the bulk-in endpoint. If we can't @@ -1455,9 +1471,9 @@ static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) } else if (ums->can_stall) { - _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, true); + _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED); rc = ums_set_stall(bulk_ctxt->bulk_in); - ums->set_text(ums->label, "#C7EA46 Status:# Residue. Stalled EP IN"); + ums->set_text(ums->label, "#FFDD00 Error:# Residue. Stalled EP IN!"); } else rc = pad_with_zeros(ums, bulk_ctxt); @@ -1523,26 +1539,28 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) DPRINTF("USB: EP timeout\n"); // In case we disconnected, exit UMS. // Raise timeout if removable and didn't got a unit ready command inside 4s. - if (bulk_ctxt->bulk_out_status == 28 || - (bulk_ctxt->bulk_out_status == 3 && ums->lun.removable && !ums->lun.prevent_medium_removal)) + if (bulk_ctxt->bulk_out_status == USB2_ERROR_XFER_EP_DISABLED || + (bulk_ctxt->bulk_out_status == USB_ERROR_TIMEOUT && ums->lun.removable && !ums->lun.prevent_medium_removal)) { - if (bulk_ctxt->bulk_out_status == 3) + if (bulk_ctxt->bulk_out_status == USB_ERROR_TIMEOUT) { - if (usb_device_get_port_status() == 0x885) + if (usb_ops.usb_device_get_port_in_sleep()) { ums->set_text(ums->label, "#C7EA46 Status:# EP in sleep"); - ums->timeouts += 10; + ums->timeouts += 14; } - else + else if (!ums->xusb) // Timeout only on USB2. + { + ums->timeouts += 4; DPRINTF("USB: EP removable\n"); + } } else { gfx_printf("USB: EP disabled\n"); msleep(500); + ums->timeouts += 4; } - - ums->timeouts += 4; } if (ums->lun.unmounted) @@ -1592,7 +1610,7 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { ums_set_stall(bulk_ctxt->bulk_out); ums_set_stall(bulk_ctxt->bulk_in); - ums->set_text(ums->label, "#C7EA46 Status:# CBW unknown - Stalled both EP"); + ums->set_text(ums->label, "#FFDD00 Error:# CBW unknown - Stalled both EP!"); } return -22; // Invalid argument. @@ -1634,7 +1652,7 @@ static int get_next_command(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) bulk_ctxt->bulk_out_length = USB_BULK_CB_WRAP_LEN; /* Queue a request to read a Bulk-only CBW */ - _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, true); + _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED); /* We will drain the buffer in software, which means we * can reuse it for the next filling. No need to advance @@ -1659,7 +1677,7 @@ static void send_status(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) if (ums->phase_error) { - ums->set_text(ums->label, "#C7EA46 Status:# Phase-error"); + ums->set_text(ums->label, "#FFDD00 Error:# Phase-error!"); status = USB_STATUS_PHASE_ERROR; sd = SS_INVALID_COMMAND; } @@ -1680,7 +1698,7 @@ static void send_status(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) csw->Status = status; bulk_ctxt->bulk_in_length = USB_BULK_CS_WRAP_LEN; - _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, true); + _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED); } static void handle_exception(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) @@ -1688,8 +1706,8 @@ static void handle_exception(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) enum ums_state old_state; /* Clear out the controller's fifos */ - usbd_flush_endpoint(bulk_ctxt->bulk_in); - usbd_flush_endpoint(bulk_ctxt->bulk_out); + ums_flush_endpoint(bulk_ctxt->bulk_in); + ums_flush_endpoint(bulk_ctxt->bulk_out); /* Reset the I/O buffer states and pointers, the SCSI * state, and the exception. Then invoke the handler. */ @@ -1764,26 +1782,32 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs) int res = 0; sdmmc_t sdmmc; sdmmc_storage_t storage; + usbd_gadget_ums_t ums = {0}; + + // Get USB Controller ops. + if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210) + usb_device_get_ops(&usb_ops); + else + { + ums.xusb = true; + xusb_device_get_ops(&usb_ops); + } usbs->set_text(usbs->label, "#C7EA46 Status:# Started USB"); - if (usb_device_init()) + if (usb_ops.usb_device_init()) { - usbd_end(false, true); + usb_ops.usbd_end(false, true); return 1; } - usbd_gadget_ums_t ums; - memset(&ums, 0, sizeof(usbd_gadget_ums_t)); - - ums.bulk_out_maxpacket = usbd_get_max_pkt_length(USB_EP_BULK_IN); ums.state = UMS_STATE_NORMAL; ums.can_stall = 0; - ums.bulk_ctxt.bulk_in = 3; + ums.bulk_ctxt.bulk_in = USB_EP_BULK_IN; ums.bulk_ctxt.bulk_in_buf = (u8 *)USB_EP_BULK_IN_BUF_ADDR; - ums.bulk_ctxt.bulk_out = 2; + ums.bulk_ctxt.bulk_out = USB_EP_BULK_OUT; ums.bulk_ctxt.bulk_out_buf = (u8 *)USB_EP_BULK_OUT_BUF_ADDR; // Set LUN parameters. @@ -1820,12 +1844,12 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs) ums.set_text(ums.label, "#C7EA46 Status:# Waiting for connection"); // Initialize Control Endpoint. - if (usb_device_ep0_initialize(USB_GADGET_UMS)) + if (usb_ops.usb_device_enumerate(USB_GADGET_UMS)) goto error; ums.set_text(ums.label, "#C7EA46 Status:# Waiting for LUN"); - if (usb_device_get_max_lun(0)) // One device for now. + if (usb_ops.usb_device_class_send_max_lun(0)) // One device for now. goto error; ums.set_text(ums.label, "#C7EA46 Status:# Started UMS"); @@ -1878,14 +1902,14 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs) goto exit; error: - ums.set_text(ums.label, "#C7EA46 Status:# Timed out or canceled"); + ums.set_text(ums.label, "#FFDD00 Error:# Timed out or canceled!"); res = 1; exit: if (ums.lun.type == MMC_EMMC) sdmmc_storage_end(ums.lun.storage); - usbd_end(true, false); + usb_ops.usbd_end(true, false); return res; } diff --git a/bdk/usb/usb_t210.h b/bdk/usb/usb_t210.h index d670317..4d67c69 100644 --- a/bdk/usb/usb_t210.h +++ b/bdk/usb/usb_t210.h @@ -1,7 +1,7 @@ /* - * USB driver for Tegra X1 + * Enhanced & eXtensible USB device (EDCI & XDCI) driver for Tegra X1 * - * Copyright (c) 2019 CTCaer + * Copyright (c) 2019-2020 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -21,14 +21,16 @@ #include +/* EHCI USB */ + /* General USB registers */ #define USB1_IF_USB_SUSP_CTRL 0x400 -#define SUSP_CTRL_USB_WAKE_ON_CNNT_EN_DEV (1 << 3) -#define SUSP_CTRL_USB_WAKE_ON_DISCON_EN_DEV (1 << 4) -#define SUSP_CTRL_USB_PHY_CLK_VALID (1 << 7) -#define SUSP_CTRL_UTMIP_RESET (1 << 11) -#define SUSP_CTRL_UTMIP_PHY_ENB (1 << 12) -#define SUSP_CTRL_UTMIP_UTMIP_SUSPL1_SET (1 << 25) +#define SUSP_CTRL_USB_WAKE_ON_CNNT_EN_DEV BIT(3) +#define SUSP_CTRL_USB_WAKE_ON_DISCON_EN_DEV BIT(4) +#define SUSP_CTRL_USB_PHY_CLK_VALID BIT(7) +#define SUSP_CTRL_UTMIP_RESET BIT(11) +#define SUSP_CTRL_UTMIP_PHY_ENB BIT(12) +#define SUSP_CTRL_UTMIP_UTMIP_SUSPL1_SET BIT(25) #define USB1_IF_USB_PHY_VBUS_SENSORS 0x404 #define USB1_UTMIP_XCVR_CFG0 0x808 #define USB1_UTMIP_BIAS_CFG0 0x80C @@ -37,6 +39,9 @@ #define USB1_UTMIP_TX_CFG0 0x820 #define USB1_UTMIP_MISC_CFG1 0x828 #define USB1_UTMIP_DEBOUNCE_CFG0 0x82C +#define USB1_UTMIP_BAT_CHRG_CFG0 0x830 +#define BAT_CHRG_CFG0_PWRDOWN_CHRG BIT(0) +#define BAT_CHRG_CFG0_OP_SRC_EN BIT(3) #define USB1_UTMIP_SPARE_CFG0 0x834 #define USB1_UTMIP_XCVR_CFG1 0x838 #define USB1_UTMIP_BIAS_CFG1 0x83C @@ -46,38 +51,38 @@ /* USB Queue Head Descriptor */ #define USB2_QH_USB2D_QH_EP_BASE (USB_BASE + 0x1000) -#define USB_QHD_EP_CAP_IOS_ENABLE (1 << 15) +#define USB_QHD_EP_CAP_IOS_ENABLE BIT(15) #define USB_QHD_EP_CAP_MAX_PKT_LEN_MASK 0x7FF -#define USB_QHD_EP_CAP_ZERO_LEN_TERM_DIS (1 << 29) +#define USB_QHD_EP_CAP_ZERO_LEN_TERM_DIS BIT(29) #define USB_QHD_EP_CAP_MULTI_NON_ISO (0 << 30) #define USB_QHD_EP_CAP_MULTI_1 (1 << 30) #define USB_QHD_EP_CAP_MULTI_2 (2 << 30) #define USB_QHD_EP_CAP_MULTI_3 (3 << 30) -#define USB_QHD_TOKEN_XFER_ERROR (1 << 3) -#define USB_QHD_TOKEN_BUFFER_ERROR (1 << 5) -#define USB_QHD_TOKEN_HALTED (1 << 6) -#define USB_QHD_TOKEN_ACTIVE (1 << 7) +#define USB_QHD_TOKEN_XFER_ERROR BIT(3) +#define USB_QHD_TOKEN_BUFFER_ERROR BIT(5) +#define USB_QHD_TOKEN_HALTED BIT(6) +#define USB_QHD_TOKEN_ACTIVE BIT(7) #define USB_QHD_TOKEN_MULT_OVERR_MASK (2 << 10) -#define USB_QHD_TOKEN_IRQ_ON_COMPLETE (1 << 15) +#define USB_QHD_TOKEN_IRQ_ON_COMPLETE BIT(15) #define USB_QHD_TOKEN_TOTAL_BYTES_SHIFT 16 /* USB_OTG/USB_1 controllers register bits */ -#define USB2D_PORTSC1_SUSP (1 << 7) +#define USB2D_PORTSC1_SUSP BIT(7) -#define USB2D_USBCMD_RUN (1 << 0) -#define USB2D_USBCMD_RESET (1 << 1) +#define USB2D_USBCMD_RUN BIT(0) +#define USB2D_USBCMD_RESET BIT(1) #define USB2D_USBCMD_ITC_MASK (0xFF << 16) -#define USB2D_USBSTS_UI (1 << 0) -#define USB2D_USBSTS_UEI (1 << 1) -#define USB2D_USBSTS_PCI (1 << 2) -#define USB2D_USBSTS_FRI (1 << 3) -#define USB2D_USBSTS_SEI (1 << 4) -#define USB2D_USBSTS_AAI (1 << 5) -#define USB2D_USBSTS_URI (1 << 6) -#define USB2D_USBSTS_SRI (1 << 7) -#define USB2D_USBSTS_SLI (1 << 8) +#define USB2D_USBSTS_UI BIT(0) +#define USB2D_USBSTS_UEI BIT(1) +#define USB2D_USBSTS_PCI BIT(2) +#define USB2D_USBSTS_FRI BIT(3) +#define USB2D_USBSTS_SEI BIT(4) +#define USB2D_USBSTS_AAI BIT(5) +#define USB2D_USBSTS_URI BIT(6) +#define USB2D_USBSTS_SRI BIT(7) +#define USB2D_USBSTS_SLI BIT(8) #define USB2D_USBMODE_CM_MASK (3 << 0) #define USB2D_USBMODE_CM_IDLE 0 @@ -85,33 +90,33 @@ #define USB2D_USBMODE_CM_DEVICE 2 #define USB2D_USBMODE_CM_HOST 3 -#define USB2D_ENDPT_STATUS_RX_OFFSET (1 << 0) -#define USB2D_ENDPT_STATUS_TX_OFFSET (1 << 16) +#define USB2D_ENDPT_STATUS_RX_OFFSET BIT(0) +#define USB2D_ENDPT_STATUS_TX_OFFSET BIT(16) -#define USB2D_ENDPTCTRL_RX_EP_STALL (1 << 0) +#define USB2D_ENDPTCTRL_RX_EP_STALL BIT(0) #define USB2D_ENDPTCTRL_RX_EP_TYPE_CTRL (0 << 2) #define USB2D_ENDPTCTRL_RX_EP_TYPE_ISO (1 << 2) #define USB2D_ENDPTCTRL_RX_EP_TYPE_BULK (2 << 2) #define USB2D_ENDPTCTRL_RX_EP_TYPE_INTR (3 << 2) #define USB2D_ENDPTCTRL_RX_EP_TYPE_MASK (3 << 2) -#define USB2D_ENDPTCTRL_RX_EP_INHIBIT (1 << 5) -#define USB2D_ENDPTCTRL_RX_EP_RESET (1 << 6) -#define USB2D_ENDPTCTRL_RX_EP_ENABLE (1 << 7) -#define USB2D_ENDPTCTRL_TX_EP_STALL (1 << 16) +#define USB2D_ENDPTCTRL_RX_EP_INHIBIT BIT(5) +#define USB2D_ENDPTCTRL_RX_EP_RESET BIT(6) +#define USB2D_ENDPTCTRL_RX_EP_ENABLE BIT(7) +#define USB2D_ENDPTCTRL_TX_EP_STALL BIT(16) #define USB2D_ENDPTCTRL_TX_EP_TYPE_CTRL (0 << 18) #define USB2D_ENDPTCTRL_TX_EP_TYPE_ISO (1 << 18) #define USB2D_ENDPTCTRL_TX_EP_TYPE_BULK (2 << 18) #define USB2D_ENDPTCTRL_TX_EP_TYPE_INTR (3 << 18) #define USB2D_ENDPTCTRL_TX_EP_TYPE_MASK (3 << 18) -#define USB2D_ENDPTCTRL_TX_EP_INHIBIT (1 << 21) -#define USB2D_ENDPTCTRL_TX_EP_RESET (1 << 22) -#define USB2D_ENDPTCTRL_TX_EP_ENABLE (1 << 23) +#define USB2D_ENDPTCTRL_TX_EP_INHIBIT BIT(21) +#define USB2D_ENDPTCTRL_TX_EP_RESET BIT(22) +#define USB2D_ENDPTCTRL_TX_EP_ENABLE BIT(23) -#define USB2D_HOSTPC1_DEVLC_ASUS (1 << 17) -#define USB2D_HOSTPC1_DEVLC_PHCD (1 << 22) +#define USB2D_HOSTPC1_DEVLC_ASUS BIT(17) +#define USB2D_HOSTPC1_DEVLC_PHCD BIT(22) #define USB2D_HOSTPC1_DEVLC_PSPD_MASK (3 << 25) -#define USB2D_OTGSC_USB_ID_PULLUP (1 << 5) +#define USB2D_OTGSC_USB_ID_PULLUP BIT(5) #define USB2D_OTGSC_USB_IRQ_STS_MASK (0x7F << 16) /* USB_OTG/USB_1 controllers registers */ @@ -169,4 +174,119 @@ typedef struct _t210_usb2d_t vu32 endptctrl[16]; } t210_usb2d_t; + +/* XHCI USB */ + +/* XUSB DEV XHCI registers */ +#define XUSB_DEV_XHCI_DB 0x4 +#define XUSB_DEV_XHCI_ERSTSZ 0x8 +#define XUSB_DEV_XHCI_ERST0BALO 0x10 +#define XUSB_DEV_XHCI_ERST0BAHI 0x14 +#define XUSB_DEV_XHCI_ERST1BALO 0x18 +#define XUSB_DEV_XHCI_ERST1BAHI 0x1C +#define XUSB_DEV_XHCI_ERDPLO 0x20 +#define XHCI_ERDPLO_EHB BIT(3) +#define XUSB_DEV_XHCI_ERDPHI 0x24 +#define XUSB_DEV_XHCI_EREPLO 0x28 +#define XCHI_ECS BIT(0) +#define XUSB_DEV_XHCI_EREPHI 0x2C +#define XUSB_DEV_XHCI_CTRL 0x30 +#define XHCI_CTRL_RUN BIT(0) +#define XHCI_CTRL_LSE BIT(1) +#define XHCI_CTRL_IE BIT(4) +#define XHCI_CTRL_ENABLE BIT(31) +#define XUSB_DEV_XHCI_ST 0x34 +#define XHCI_ST_RC BIT(0) +#define XHCI_ST_IP BIT(4) +#define XUSB_DEV_XHCI_PORTSC 0x3C +#define XHCI_PORTSC_PR BIT(4) +#define XHCI_PORTSC_PLS_MASK (0xF << 5) +#define XHCI_PORTSC_PLS_U0 (0 << 5) +#define XHCI_PORTSC_PLS_U1 (1 << 5) +#define XHCI_PORTSC_PLS_U2 (2 << 5) +#define XHCI_PORTSC_PLS_U3 (3 << 5) +#define XHCI_PORTSC_PLS_DISABLED (4 << 5) +#define XHCI_PORTSC_PLS_RXDETECT (5 << 5) +#define XHCI_PORTSC_PLS_INACTIVE (6 << 5) +#define XHCI_PORTSC_PLS_POLLING (7 << 5) +#define XHCI_PORTSC_PLS_RECOVERY (8 << 5) +#define XHCI_PORTSC_PLS_HOTRESET (9 << 5) +#define XHCI_PORTSC_PLS_COMPLIANCE (10 << 5) +#define XHCI_PORTSC_PLS_LOOPBACK (11 << 5) +#define XHCI_PORTSC_PLS_RESUME (15 << 5) +#define XHCI_PORTSC_PS (0xF << 10) +#define XHCI_PORTSC_LWS BIT(16) +#define XHCI_PORTSC_CSC BIT(17) +#define XHCI_PORTSC_WRC BIT(19) +#define XHCI_PORTSC_PRC BIT(21) +#define XHCI_PORTSC_PLC BIT(22) +#define XHCI_PORTSC_CEC BIT(23) +#define XHCI_PORTSC_WPR BIT(30) +#define XUSB_DEV_XHCI_ECPLO 0x40 +#define XUSB_DEV_XHCI_ECPHI 0x44 +#define XUSB_DEV_XHCI_EP_HALT 0x50 +#define XHCI_EP_HALT_DCI BIT(0) +#define XUSB_DEV_XHCI_EP_PAUSE 0x54 +#define XUSB_DEV_XHCI_EP_RELOAD 0x58 +#define XUSB_DEV_XHCI_EP_STCHG 0x5C +#define XUSB_DEV_XHCI_PORTHALT 0x6C +#define XHCI_PORTHALT_HALT_LTSSM BIT(0) +#define XHCI_PORTHALT_STCHG_REQ BIT(20) +#define XUSB_DEV_XHCI_CFG_DEV_FE 0x85C +#define XHCI_CFG_DEV_FE_PORTREGSEL_MASK (3 << 0) +#define XHCI_CFG_DEV_FE_PORTREGSEL_SS (1 << 0) +#define XHCI_CFG_DEV_FE_PORTREGSEL_HSFS (2 << 0) + +/* XUSB DEV PCI registers */ +#define XUSB_CFG_1 0x4 +#define CFG_1_IO_SPACE BIT(0) +#define CFG_1_MEMORY_SPACE BIT(1) +#define CFG_1_BUS_MASTER BIT(2) +#define XUSB_CFG_4 0x10 +#define CFG_4_ADDRESS_TYPE_32_BIT (0 << 1) +#define CFG_4_ADDRESS_TYPE_64_BIT (2 << 1) + +/* XUSB DEV Device registers */ +#define XUSB_DEV_CONFIGURATION 0x180 +#define DEV_CONFIGURATION_EN_FPCI BIT(0) +#define XUSB_DEV_INTR_MASK 0x188 +#define DEV_INTR_MASK_IP_INT_MASK BIT(16) + +/* XUSB Pad Control registers */ +#define XUSB_PADCTL_USB2_PAD_MUX 0x4 +#define PADCTL_USB2_PAD_MUX_USB2_OTG_PAD_PORT0_USB2 (0 << 0) +#define PADCTL_USB2_PAD_MUX_USB2_OTG_PAD_PORT0_XUSB (1 << 0) +#define PADCTL_USB2_PAD_MUX_USB2_OTG_PAD_PORT0_MASK (3 << 0) +#define PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_USB2 (0 << 18) +#define PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_XUSB (1 << 18) +#define PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_MASK (3 << 18) +#define XUSB_PADCTL_USB2_PORT_CAP 0x8 +#define PADCTL_USB2_PORT_CAP_PORT_0_CAP_DIS (0 << 0) +#define PADCTL_USB2_PORT_CAP_PORT_0_CAP_HOST (1 << 0) +#define PADCTL_USB2_PORT_CAP_PORT_0_CAP_DEV (2 << 0) +#define PADCTL_USB2_PORT_CAP_PORT_0_CAP_OTG (3 << 0) +#define PADCTL_USB2_PORT_CAP_PORT_0_CAP_MASK (3 << 0) +#define XUSB_PADCTL_SS_PORT_MAP 0x14 +#define PADCTL_SS_PORT_MAP_PORT0_MASK (0xF << 0) +#define XUSB_PADCTL_ELPG_PROGRAM_0 0x20 +#define XUSB_PADCTL_ELPG_PROGRAM_1 0x24 +#define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD0_CTL0 0x80 +#define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD0_CTL1 0x84 +#define XUSB_PADCTL_USB2_OTG_PAD0_CTL_0 0x88 +#define XUSB_PADCTL_USB2_OTG_PAD0_CTL_1 0x8C +#define XUSB_PADCTL_USB2_BIAS_PAD_CTL_0 0x284 +#define XUSB_PADCTL_USB2_BIAS_PAD_CTL_1 0x288 +#define XUSB_PADCTL_USB2_VBUS_ID 0xC60 +#define PADCTL_USB2_VBUS_ID_VBUS_OVR_EN (1 << 12) +#define PADCTL_USB2_VBUS_ID_VBUS_OVR_MASK (3 << 12) +#define PADCTL_USB2_VBUS_ID_VBUS_ON BIT(14) +#define PADCTL_USB2_VBUS_ID_SRC_ID_OVR_EN (1 << 16) +#define PADCTL_USB2_VBUS_ID_SRC_MASK (3 << 16) +#define PADCTL_USB2_VBUS_ID_OVR_GND (0 << 18) +#define PADCTL_USB2_VBUS_ID_OVR_C (1 << 18) +#define PADCTL_USB2_VBUS_ID_OVR_B (2 << 18) +#define PADCTL_USB2_VBUS_ID_OVR_A (4 << 18) +#define PADCTL_USB2_VBUS_ID_OVR_FLOAT (8 << 18) +#define PADCTL_USB2_VBUS_ID_OVR_MASK (0xF << 18) + #endif diff --git a/bdk/usb/usbd.c b/bdk/usb/usbd.c index 712629a..8cf37c3 100644 --- a/bdk/usb/usbd.c +++ b/bdk/usb/usbd.c @@ -1,7 +1,7 @@ /* - * USB Device driver for Tegra X1 + * Enhanced USB Device (EDCI) driver for Tegra X1 * - * Copyright (c) 2019 CTCaer + * Copyright (c) 2019-2020 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,7 +20,7 @@ #include #include -#include +#include #include #include @@ -42,20 +42,6 @@ typedef enum USB_HW_EP1 = 1 } usb_hw_ep_t; -typedef enum -{ - USB_EP_ADDR_CTRL_OUT = 0x00, - USB_EP_ADDR_CTRL_IN = 0x80, - USB_EP_ADDR_BULK_OUT = 0x01, - USB_EP_ADDR_BULK_IN = 0x81, -} usb_ep_addr_t; - -typedef enum -{ - USB_EP_CFG_RESET = 0, - USB_EP_CFG_STALL = 1 -} usb_ep_cfg_t; - typedef enum { USB_EP_STATUS_IDLE = 0, @@ -67,72 +53,12 @@ typedef enum } usb_ep_status_t; typedef enum { - USB_SETUP_RECIPIENT_DEVICE = 0, - USB_SETUP_RECIPIENT_INTERFACE = 1, - USB_SETUP_RECIPIENT_ENDPOINT = 2, - USB_SETUP_RECIPIENT_OTHER = 3, - - USB_SETUP_TYPE_STANDARD = 0x00, - USB_SETUP_TYPE_CLASS = 0x20, - USB_SETUP_TYPE_VENDOR = 0x40, - USB_SETUP_TYPE_RESERVED = 0x60, - - USB_SETUP_HOST_TO_DEVICE = 0x00, - USB_SETUP_DEVICE_TO_HOST = 0x80, -} usb_setup_req_type_t; - -typedef enum { - USB_REQUEST_GET_STATUS = 0, - USB_REQUEST_CLEAR_FEATURE = 1, - USB_REQUEST_SET_FEATURE = 3, - USB_REQUEST_SET_ADDRESS = 5, - USB_REQUEST_GET_DESCRIPTOR = 6, - USB_REQUEST_SET_DESCRIPTOR = 7, - USB_REQUEST_GET_CONFIGURATION = 8, - USB_REQUEST_SET_CONFIGURATION = 9, - USB_REQUEST_GET_INTERFACE = 10, - USB_REQUEST_SET_INTERFACE = 11, - USB_REQUEST_SYNCH_FRAME = 12, - - USB_REQUEST_GET_MS_DESCRIPTOR = 0x99, - - USB_REQUEST_BULK_GET_MAX_LUN = 0xFE, - USB_REQUEST_BULK_RESET = 0xFF -} usb_standard_req_t; - -typedef enum { - USB_FEATURE_ENDPOINT_HALT = 0, - USB_FEATURE_DEVICE_REMOTE_WAKEUP = 1, - USB_FEATURE_TEST_MODE = 2, -} usb_get_status_req_t; - -typedef enum { - USB_STATUS_EP_OK = 0, - USB_STATUS_EP_HALTED = 1, - - USB_STATUS_DEV_SELF_POWERED = 1, - USB_STATUS_DEV_REMOTE_WAKE = 2, -} usb_set_clear_feature_req_t; - -typedef enum { - USB_XFER_DIR_OUT = 0, - USB_XFER_DIR_IN = 1, -} usb_xfer_dir_t; - -typedef enum { - USB_SPEED_LOW = 0, - USB_SPEED_FULL = 1, - USB_SPEED_HIGH = 2, - USB_SPEED_SUPER = 3, + USB_LOW_SPEED = 0, + USB_FULL_SPEED = 1, + USB_HIGH_SPEED = 2, + USB_SUPER_SPEED = 3, } usb_speed_t; -typedef enum { - USB_XFER_TYPE_CONTROL = 0, - USB_XFER_TYPE_ISOCHRONOUS = 1, - USB_XFER_TYPE_BULK = 2, - USB_XFER_TYPE_INTERRUPT = 3, -} usb_xfer_type_t; - typedef struct _dTD_t { vu32 next_dTD; @@ -161,45 +87,32 @@ typedef struct _usbd_t int ep_bytes_requested[4]; } usbd_t; -typedef struct _usb_ctrl_setup_t -{ - u8 bmRequestType; - u8 bRequest; - u16 wValue; - u16 wIndex; - u16 wLength; -} usb_ctrl_setup_t; - typedef struct _usbd_controller_t { u32 port_speed; t210_usb2d_t *regs; usb_ctrl_setup_t control_setup; usb_desc_t *desc; - usb_gadget_type type; - u8 configuration_set; - u8 usb_phy_ready; - u8 configuration; - u8 interface; + usb_gadget_type gadget; + u8 config_num; + u8 interface_num; u8 max_lun; - u8 max_lun_set; - u8 bulk_reset_req; - u8 hid_report_sent; - bool charger_detect; + bool usb_phy_ready; + bool configuration_set; + bool max_lun_set; + bool bulk_reset_req; + bool hid_report_sent; + u32 charger_detect; } usbd_controller_t; -u8 usb_serial_string_descriptor[26] = -{ - 26, 0x03, - 'C', 0x00, '7', 0x00, 'C', 0x00, '0', 0x00, - '9', 0x00, '2', 0x00, '4', 0x00, '2', 0x00, 'F', 0x00, '7', 0x00, '0', 0x00, '3', 0x00 -}; +extern u8 hid_report_descriptor_jc[]; +extern u8 hid_report_descriptor_touch[]; +extern u32 hid_report_descriptor_jc_size; +extern u32 hid_report_descriptor_touch_size; -u8 usb_lang_id_string_descriptor[] = -{ - 4, 3, - 0x09, 0x04 -}; +extern usb_desc_t usb_gadget_hid_jc_descriptors; +extern usb_desc_t usb_gadget_hid_touch_descriptors; +extern usb_desc_t usb_gadget_ums_descriptors; usbd_t *usbdaemon; @@ -212,7 +125,7 @@ u8 *usb_ep0_ctrl_buf = (u8 *)USB_EP_CONTROL_BUF_ADDR; static int _usbd_reset_usb_otg_phy_device_mode() { - usbd_otg->usb_phy_ready = 0; + usbd_otg->usb_phy_ready = false; // Clear UTMIP reset. USB(USB1_IF_USB_SUSP_CTRL) &= ~SUSP_CTRL_UTMIP_RESET; @@ -223,10 +136,10 @@ static int _usbd_reset_usb_otg_phy_device_mode() { retries--; if (!retries) - return 1; + return USB_ERROR_INIT; usleep(1); } - usbd_otg->usb_phy_ready = 1; + usbd_otg->usb_phy_ready = true; // Clear all device addresses, enabled setup requests and transmit events. usbd_otg->regs->periodiclistbase = 0; @@ -248,7 +161,7 @@ static int _usbd_reset_usb_otg_phy_device_mode() { retries--; if (!retries) - return 2; + return USB_ERROR_INIT; usleep(1); } @@ -258,7 +171,7 @@ static int _usbd_reset_usb_otg_phy_device_mode() { retries--; if (!retries) - return 3; + return USB_ERROR_INIT; usleep(1); } @@ -271,7 +184,7 @@ static int _usbd_reset_usb_otg_phy_device_mode() { retries--; if (!retries) - return 4; + return USB_ERROR_INIT; usleep(1); } @@ -296,7 +209,7 @@ static int _usbd_reset_usb_otg_phy_device_mode() // Set all interrupts to immediate. usbd_otg->regs->usbcmd &= ~USB2D_USBCMD_ITC_MASK; - return 0; + return USB_RES_OK; } static void _usb_charger_detect() @@ -312,7 +225,7 @@ static void _usb_charger_detect() gpio_config(GPIO_PORT_V, GPIO_PIN_3, GPIO_MODE_GPIO); // Configure charger pin. - PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN0) &= + PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN1) &= ~(PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_TRISTATE | PINMUX_PULL_MASK); gpio_config(GPIO_PORT_CC, GPIO_PIN_5, GPIO_MODE_GPIO); gpio_output_enable(GPIO_PORT_CC, GPIO_PIN_5, GPIO_OUTPUT_ENABLE); @@ -329,45 +242,29 @@ static void _usb_charger_detect() } } -int usb_device_init() +static void _usb_init_phy() { - if (usb_init_done) - return 0; - - // Configure PLLU. - CLOCK(CLK_RST_CONTROLLER_PLLU_MISC) = CLOCK(CLK_RST_CONTROLLER_PLLU_MISC) | 0x20000000; // Disable reference clock. - u32 pllu_cfg = (((((CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) >> 8 << 8) | 2) & 0xFFFF00FF) | ((0x19 << 8) & 0xFFFF)) & 0xFFE0FFFF) | (1<< 16) | 0x1000000; - CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) = pllu_cfg; - CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) = pllu_cfg | 0x40000000; // Enable. - - // Wait for PLL to stabilize. - u32 timeout = (u32)TMR(TIMERUS_CNTR_1US) + 1300; - while (!(CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) & (1 << 27))) // PLL_LOCK. - if ((u32)TMR(TIMERUS_CNTR_1US) > timeout) - break; - usleep(10); - - // Enable PLLU USB/HSIC/ICUSB/48M. - CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) = CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) | 0x2600000 | 0x800000; + // Configure and enable PLLU. + clock_enable_pllu(); // Enable USBD clock. - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = (1 << 22); + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_USBD); usleep(2); - CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = (1 << 22); + CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_USBD); usleep(2); - CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = (1 << 22); + CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = BIT(CLK_L_USBD); usleep(2); // Clear XUSB_PADCTL reset - CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_CLR) = (1 << 14); + CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_CLR) = BIT(CLK_W_XUSB_PADCTL); // Enable USB PHY and reset for programming. u32 usb_susp_ctrl = USB(USB1_IF_USB_SUSP_CTRL); USB(USB1_IF_USB_SUSP_CTRL) = usb_susp_ctrl | SUSP_CTRL_UTMIP_RESET; USB(USB1_IF_USB_SUSP_CTRL) = usb_susp_ctrl | SUSP_CTRL_UTMIP_PHY_ENB | SUSP_CTRL_UTMIP_RESET; - // Disable UTMIPLL IDDQ. - CLOCK(CLK_RST_CONTROLLER_UTMIPLL_HW_PWRDN_CFG0) &= 0xFFFFFFFD; + // Enable IDDQ control by software and disable UTMIPLL IDDQ. + CLOCK(CLK_RST_CONTROLLER_UTMIPLL_HW_PWRDN_CFG0) = (CLOCK(CLK_RST_CONTROLLER_UTMIPLL_HW_PWRDN_CFG0) & 0xFFFFFFFC) | 1; usleep(10); // Disable crystal clock. @@ -378,18 +275,8 @@ int usb_device_init() USB(USB1_IF_USB_PHY_VBUS_SENSORS) |= 0x1000; USB(USB1_IF_USB_PHY_VBUS_SENSORS) |= 0x800; - // Set UTMIPLL dividers and enable it. - CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG0) = (CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG0) & 0xFF0000FF) | 0x190000 | 0x100; - CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG2) = (CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG2) & 0xFF00003F) | 0x600000; // Set delay count for 38.4Mhz osc crystal. - CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG1) = ((CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG1) & 0x7FFF000) | 0x8000 | 0x177) & 0xFFFFAFFF; - - // Wait for UTMIPLL to stabilize. - u32 retries = 10; // Wait 20us - while (!(CLOCK(CLK_RST_CONTROLLER_UTMIPLL_HW_PWRDN_CFG0) & 0x80000000) && retries) - { - usleep(1); - retries--; - } + // Set UTMIPLL dividers and config based on OSC and enable it to 960 MHz. + clock_enable_utmipll(); // Configure UTMIP Transceiver Cells. u32 fuse_usb_calib = FUSE(FUSE_USB_CALIB); @@ -418,8 +305,9 @@ int usb_device_init() // Enable crystal clock. CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG2) |= 0x40000000; - // Enable USB2 tracking. - CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= 0x40000; + + // Enable USB2 tracking clock. + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_Y_SET) = BIT(CLK_Y_USB2_TRK); CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_USB2_HSIC_TRK) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_USB2_HSIC_TRK) & 0xFFFFFF00) | 6; // Set trank divisor to 4. USB(USB1_UTMIP_BIAS_CFG1) = (USB(USB1_UTMIP_BIAS_CFG1) & 0xFFC03F07) | 0x78000 | 0x50; // Set delays. @@ -441,8 +329,8 @@ int usb_device_init() // TRK cycle done. Force PDTRK input into power down. USB(USB1_UTMIP_BIAS_CFG1) = (USB(USB1_UTMIP_BIAS_CFG1) & 0xFF7FFFFF) | 1; - // Disable USB2_TRK clock and configure UTMIP misc. - CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) &= 0xFFFBFFFF; + // Disable USB2 tracking clock and configure UTMIP misc. + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_Y_CLR) = BIT(CLK_Y_USB2_TRK); CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG2) = (CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG2) & 0xFEFFFFEA) | 0x2000000 | 0x28 | 2; usleep(1); @@ -450,7 +338,7 @@ int usb_device_init() usleep(1); // Clear power downs on UTMIP ID and VBUS wake up, PD, PD2, PDZI, PDCHRP, PDDR. - PMC(APBDEV_PMC_USB_AO) &= 0xFFFFFFF3; // UTMIP ID and VBUS wake up. + PMC(APBDEV_PMC_USB_AO) &= 0xFFFFFFF3; // UTMIP ID and VBUS wake up. usleep(1); USB(USB1_UTMIP_XCVR_CFG0) &= 0xFFFFBFFF; // UTMIP_FORCE_PD_POWERDOWN. usleep(1); @@ -462,13 +350,22 @@ int usb_device_init() usleep(1); USB(USB1_UTMIP_XCVR_CFG1) &= 0xFFFFFFEF; // UTMIP_FORCE_PDDR_POWERDOWN. usleep(1); +} + +int usb_device_init() +{ + if (usb_init_done) + return USB_RES_OK; + + // Initialize USB2 controller PHY. + _usb_init_phy(); // AHB USB performance cfg. - AHB_GIZMO(AHB_GIZMO_AHB_MEM) |= AHB_MEM_ENB_FAST_REARBITRATE; - AHB_GIZMO(AHB_GIZMO_USB) |= AHB_GIZMO_USB_IMMEDIATE; - AHB_GIZMO(AHB_ARBITRATION_PRIORITY_CTRL) |= ARBITRATION_PRIORITY_CTRL_ENB_FAST_REARBITRATE; + AHB_GIZMO(AHB_GIZMO_AHB_MEM) |= AHB_MEM_DONT_SPLIT_AHB_WR | AHB_MEM_ENB_FAST_REARBITRATE; + AHB_GIZMO(AHB_GIZMO_USB) |= AHB_GIZMO_IMMEDIATE; + AHB_GIZMO(AHB_ARBITRATION_PRIORITY_CTRL) = PRIORITY_CTRL_WEIGHT(7) | PRIORITY_SELECT_USB; AHB_GIZMO(AHB_AHB_MEM_PREFETCH_CFG1) = - MEM_PREFETCH_ENABLE | (MEM_PREFETCH_AHB_MST_USB << 26) | (12 << 21) | 0x1000; // addr boundary 64KB + MEM_PREFETCH_ENABLE | MEM_PREFETCH_USB_MST_ID | MEM_PREFETCH_ADDR_BNDRY(12) | 0x1000; // Addr boundary 64KB, Inactivity 4096 cycles. // Set software and hardware context storage and clear it. usbdaemon = (usbd_t *)USBD_ADDR; // Depends on USB_TD_BUFFER_PAGE_SIZE aligned address. @@ -477,18 +374,18 @@ int usb_device_init() memset(usbdaemon, 0, sizeof(usbd_t)); usbd_otg->regs = (t210_usb2d_t *)USB_OTG_BASE; - usbd_otg->usb_phy_ready = 0; + usbd_otg->usb_phy_ready = false; // Initialize USB PHY on the USB_OTG Controller (#1) in Device mode. - int result = _usbd_reset_usb_otg_phy_device_mode(); - usbd_otg->configuration_set = 0; + int res = _usbd_reset_usb_otg_phy_device_mode(); + usbd_otg->configuration_set = false; _usb_charger_detect(); - if (!result) + if (!res) usb_init_done = true; - return result; + return res; } static void _usb_device_power_down() @@ -499,10 +396,10 @@ static void _usb_device_power_down() // A reset or clear of the PHCD suspend bit must happen. // Power down OTG and Bias circuits. - USB(USB1_UTMIP_BIAS_CFG0) |= (1 << 11) | (1 << 10); // UTMIP_OTGPD, UTMIP_BIASPD. + USB(USB1_UTMIP_BIAS_CFG0) |= BIT(11) | BIT(10); // UTMIP_OTGPD, UTMIP_BIASPD. // Power down ID detectors. - USB(USB1_UTMIP_BIAS_CFG0) |= (1 << 23) | (1 << 22); //UTMIP_IDPD_SEL, UTMIP_IDPD_VAL. + USB(USB1_UTMIP_BIAS_CFG0) |= BIT(23) | BIT(22); // UTMIP_IDPD_SEL, UTMIP_IDPD_VAL. if (usbd_otg->charger_detect) { @@ -512,46 +409,44 @@ static void _usb_device_power_down() // Power down the UTMIP transceivers. // UTMIP_FORCE_PDZI_POWERDOWN, UTMIP_FORCE_PD2_POWERDOWN, UTMIP_FORCE_PD_POWERDOWN. - USB(USB1_UTMIP_XCVR_CFG0) |= (1 << 18) | (1 << 16) |(1 << 14); + USB(USB1_UTMIP_XCVR_CFG0) |= BIT(18) | BIT(16) |BIT(14); // UTMIP_FORCE_PDDR_POWERDOWN, UTMIP_FORCE_PDCHRP_POWERDOWN, UTMIP_FORCE_PDDISC_POWERDOWN. - USB(USB1_UTMIP_XCVR_CFG1) |= (1 << 4) | (1 << 2) | (1 << 0); + USB(USB1_UTMIP_XCVR_CFG1) |= BIT(4) | BIT(2) | BIT(0); // Keep UTMIP in reset. USB(USB1_IF_USB_SUSP_CTRL) |= SUSP_CTRL_UTMIP_RESET; // Power down PD trunk. - USB(USB1_UTMIP_BIAS_CFG1) |= (1 << 0); //UTMIP_FORCE_PDTRK_POWERDOWN. + USB(USB1_UTMIP_BIAS_CFG1) |= BIT(0); //UTMIP_FORCE_PDTRK_POWERDOWN. // Force UTMIP_PLL power down. - CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG1) |= (1 << 14); // UTMIP_FORCE_PLL_ENABLE_POWERDOWN. - CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG1) |= (1 << 12); // UTMIP_FORCE_PLL_ACTIVE_POWERDOWN. - CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG2) |= (1 << 4) | (1 << 0); // UTMIP_FORCE_PD_SAMP_A/C_POWERDOWN. - CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG1) |= (1 << 16); // UTMIP_FORCE_PLLU_POWERDOWN. + CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG1) |= BIT(14); // UTMIP_FORCE_PLL_ENABLE_POWERDOWN. + CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG1) |= BIT(12); // UTMIP_FORCE_PLL_ACTIVE_POWERDOWN. + CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG2) |= BIT(4) | BIT(0); // UTMIP_FORCE_PD_SAMP_A/C_POWERDOWN. + CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG1) |= BIT(16); // UTMIP_FORCE_PLLU_POWERDOWN. // Disable crystal clock. USB(USB1_UTMIP_MISC_CFG1) &= 0xBFFFFFFF; - // Enable UTMIPLL IDDQ. - CLOCK(CLK_RST_CONTROLLER_UTMIPLL_HW_PWRDN_CFG0) |= 2; + // Force enable UTMIPLL IDDQ. + CLOCK(CLK_RST_CONTROLLER_UTMIPLL_HW_PWRDN_CFG0) |= 3; // Set XUSB_PADCTL reset - CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = (1 << 14); + CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB_PADCTL); // Disable USBD clock. - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = (1 << 22); + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = BIT(CLK_L_USBD); - // Completely 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. + // Disable PLLU. + clock_disable_pllu(); usb_init_done = false; } -static void _usbd_stall_reset_ep1(usb_xfer_dir_t direction, usb_ep_cfg_t stall) +static void _usbd_stall_reset_ep1(usb_dir_t direction, usb_ep_cfg_t stall) { stall &= 1; - if (direction == USB_XFER_DIR_IN) + if (direction == USB_DIR_IN) { usbd_otg->regs->endptctrl[1] = (usbd_otg->regs->endptctrl[1] & ~USB2D_ENDPTCTRL_TX_EP_STALL) | ((u32)stall << 16); if (!stall) @@ -565,42 +460,17 @@ static void _usbd_stall_reset_ep1(usb_xfer_dir_t direction, usb_ep_cfg_t stall) } } -void usbd_end(bool reset_ep, bool only_controller) -{ - if (reset_ep) - { - usbd_flush_endpoint(USB_EP_ALL); - _usbd_stall_reset_ep1(0, USB_EP_CFG_RESET); // EP1 Bulk IN. - _usbd_stall_reset_ep1(1, USB_EP_CFG_RESET); // EP1 Bulk OUT. - //TODO: what about EP0 simultaneous in/out reset. - - usbd_otg->configuration = 0; - usbd_otg->interface = 0; - usbd_otg->configuration_set = 0; - usbd_otg->max_lun_set = 0; - } - - // Stop device controller. - usbd_otg->regs->usbcmd &= ~USB2D_USBCMD_RUN; - - // Enable PHY auto low power suspend. - usbd_otg->regs->hostpc1_devlc |= USB2D_HOSTPC1_DEVLC_ASUS; - - if (!only_controller) - _usb_device_power_down(); -} - void usb_device_stall_ep1_bulk_out() { - _usbd_stall_reset_ep1(USB_XFER_DIR_OUT, USB_EP_CFG_STALL); + _usbd_stall_reset_ep1(USB_DIR_OUT, USB_EP_CFG_STALL); } void usb_device_stall_ep1_bulk_in() { - _usbd_stall_reset_ep1(USB_XFER_DIR_IN, USB_EP_CFG_STALL); + _usbd_stall_reset_ep1(USB_DIR_IN, USB_EP_CFG_STALL); } -int usbd_get_max_pkt_length(int endpoint) +static int _usbd_get_max_pkt_length(int endpoint) { switch (endpoint) { @@ -609,7 +479,7 @@ int usbd_get_max_pkt_length(int endpoint) return 64; case USB_EP_BULK_OUT: case USB_EP_BULK_IN: - if (usbd_otg->port_speed == 2) + if (usbd_otg->port_speed == USB_HIGH_SPEED) return 512; else return 64; @@ -621,7 +491,7 @@ int usbd_get_max_pkt_length(int endpoint) static void _usbd_initialize_ep_ctrl(u32 endpoint) { usb_hw_ep_t actual_ep = (endpoint & 2) >> 1; - usb_xfer_dir_t direction = endpoint & 1; + usb_dir_t direction = endpoint & 1; memset((void *)&usbdaemon->qhs[endpoint], 0, sizeof(dQH_t)); @@ -630,14 +500,14 @@ static void _usbd_initialize_ep_ctrl(u32 endpoint) usbdaemon->qhs[endpoint].next_dTD_ptr = 1; // TERMINATE_SET - u32 max_packet_len = usbd_get_max_pkt_length(endpoint) & USB_QHD_EP_CAP_MAX_PKT_LEN_MASK; + u32 max_packet_len = _usbd_get_max_pkt_length(endpoint) & USB_QHD_EP_CAP_MAX_PKT_LEN_MASK; usbdaemon->qhs[endpoint].ep_capabilities |= max_packet_len << 16; - if (direction == USB_XFER_DIR_IN) + if (direction == USB_DIR_IN) { u32 endpoint_type = usbd_otg->regs->endptctrl[actual_ep] & ~USB2D_ENDPTCTRL_TX_EP_TYPE_MASK; if (actual_ep) - endpoint_type |= usbd_otg->type ? USB2D_ENDPTCTRL_TX_EP_TYPE_INTR : USB2D_ENDPTCTRL_TX_EP_TYPE_BULK; + endpoint_type |= usbd_otg->gadget ? USB2D_ENDPTCTRL_TX_EP_TYPE_INTR : USB2D_ENDPTCTRL_TX_EP_TYPE_BULK; else endpoint_type |= USB2D_ENDPTCTRL_TX_EP_TYPE_CTRL; @@ -655,7 +525,7 @@ static void _usbd_initialize_ep_ctrl(u32 endpoint) u32 endpoint_type = usbd_otg->regs->endptctrl[actual_ep] & ~USB2D_ENDPTCTRL_RX_EP_TYPE_MASK; if (actual_ep) { - endpoint_type |= usbd_otg->type ? USB2D_ENDPTCTRL_RX_EP_TYPE_INTR : USB2D_ENDPTCTRL_RX_EP_TYPE_BULK; + endpoint_type |= usbd_otg->gadget ? USB2D_ENDPTCTRL_RX_EP_TYPE_INTR : USB2D_ENDPTCTRL_RX_EP_TYPE_BULK; } else endpoint_type |= USB2D_ENDPTCTRL_RX_EP_TYPE_CTRL; @@ -691,11 +561,11 @@ static int _usbd_initialize_ep0() { retries--; if (!retries) - return 3; + return USB_ERROR_TIMEOUT; usleep(1); } - return 0; + return USB_RES_OK; } // static void _disable_usb_wdt4() @@ -713,13 +583,13 @@ int usbd_flush_endpoint(u32 endpoint) { usb_hw_ep_t actual_ep = (endpoint & 2) >> 1; - usb_xfer_dir_t direction = endpoint & 1; + usb_dir_t direction = endpoint & 1; u32 reg_mask = endpoint; // Flash all endpoints or 1. if (endpoint != USB_EP_ALL) { - if (direction == USB_XFER_DIR_IN) + if (direction == USB_DIR_IN) reg_mask = USB2D_ENDPT_STATUS_TX_OFFSET << actual_ep; else reg_mask = USB2D_ENDPT_STATUS_RX_OFFSET << actual_ep; @@ -731,7 +601,7 @@ int usbd_flush_endpoint(u32 endpoint) { retries--; if (!retries) - return 3; + return USB_ERROR_TIMEOUT; usleep(1); } @@ -741,7 +611,7 @@ int usbd_flush_endpoint(u32 endpoint) { retries--; if (!retries) - return 3; + return USB_ERROR_TIMEOUT; usleep(1); } @@ -751,18 +621,42 @@ int usbd_flush_endpoint(u32 endpoint) { retries--; if (!retries) - return 3; + return USB_ERROR_TIMEOUT; usleep(1); } - return 0; + return USB_RES_OK; +} + +void usbd_end(bool reset_ep, bool only_controller) +{ + if (reset_ep) + { + usbd_flush_endpoint(USB_EP_ALL); + _usbd_stall_reset_ep1(USB_DIR_OUT, USB_EP_CFG_RESET); // EP1 Bulk OUT. + _usbd_stall_reset_ep1(USB_DIR_IN, USB_EP_CFG_RESET); // EP1 Bulk IN. + + usbd_otg->config_num = 0; + usbd_otg->interface_num = 0; + usbd_otg->configuration_set = false; + usbd_otg->max_lun_set = false; + } + + // Stop device controller. + usbd_otg->regs->usbcmd &= ~USB2D_USBCMD_RUN; + + // Enable PHY auto low power suspend. + usbd_otg->regs->hostpc1_devlc |= USB2D_HOSTPC1_DEVLC_ASUS; + + if (!only_controller) + _usb_device_power_down(); } static void _usbd_mark_ep_complete(u32 endpoint) { u32 complete_bit; usb_hw_ep_t actual_ep = (endpoint & 2) >> 1; - usb_xfer_dir_t direction = endpoint & 1; + usb_dir_t direction = endpoint & 1; usbd_flush_endpoint(endpoint); memset((void *)&usbdaemon->dtds[endpoint * 4], 0, sizeof(dTD_t) * 4); @@ -770,7 +664,7 @@ static void _usbd_mark_ep_complete(u32 endpoint) usbdaemon->ep_configured[endpoint] = 0; usbdaemon->ep_bytes_requested[endpoint] = 0; - if (direction == USB_XFER_DIR_IN) + if (direction == USB_DIR_IN) complete_bit = USB2D_ENDPT_STATUS_TX_OFFSET << actual_ep; else complete_bit = USB2D_ENDPT_STATUS_RX_OFFSET << actual_ep; @@ -784,9 +678,9 @@ static usb_ep_status_t _usbd_get_ep_status(usb_ep_t endpoint) u32 reg_val; u32 reg_mask; u32 actual_ep = (endpoint & 2) >> 1; - usb_xfer_dir_t direction = endpoint & 1; + usb_dir_t direction = endpoint & 1; - if (direction == USB_XFER_DIR_IN) + if (direction == USB_DIR_IN) reg_mask = USB2D_ENDPT_STATUS_TX_OFFSET << actual_ep; else reg_mask = USB2D_ENDPT_STATUS_RX_OFFSET << actual_ep; @@ -797,7 +691,7 @@ static usb_ep_status_t _usbd_get_ep_status(usb_ep_t endpoint) reg_val = usbd_otg->regs->endptctrl[0]; // Check stalled status. - if (direction == USB_XFER_DIR_IN) + if (direction == USB_DIR_IN) status = reg_val & USB2D_ENDPTCTRL_TX_EP_STALL; else status = reg_val & USB2D_ENDPTCTRL_RX_EP_STALL; @@ -806,7 +700,7 @@ static usb_ep_status_t _usbd_get_ep_status(usb_ep_t endpoint) return USB_EP_STATUS_STALLED; // Check enabled status. - if (direction == USB_XFER_DIR_IN) + if (direction == USB_DIR_IN) status = reg_val & USB2D_ENDPTCTRL_TX_EP_ENABLE; else status = reg_val & USB2D_ENDPTCTRL_RX_EP_ENABLE; @@ -837,7 +731,7 @@ static int _usbd_ep_operation(usb_ep_t endpoint, u8 *buf, u32 len, bool sync) u32 prime_bit; usb_hw_ep_t actual_ep = (endpoint & 2) >> 1; - usb_xfer_dir_t direction = endpoint & 1; + usb_dir_t direction = endpoint & 1; u32 length_left = len; u32 dtd_ep_idx = endpoint * 4; @@ -846,7 +740,7 @@ static int _usbd_ep_operation(usb_ep_t endpoint, u8 *buf, u32 len, bool sync) if (endpoint == USB_EP_CTRL_OUT) usbdaemon->qhs[endpoint].ep_capabilities = USB_QHD_EP_CAP_IOS_ENABLE; - u32 max_packet_len = usbd_get_max_pkt_length(endpoint) & USB_QHD_EP_CAP_MAX_PKT_LEN_MASK; + u32 max_packet_len = _usbd_get_max_pkt_length(endpoint) & USB_QHD_EP_CAP_MAX_PKT_LEN_MASK; usbdaemon->qhs[endpoint].ep_capabilities |= (max_packet_len << 16) | USB_QHD_EP_CAP_ZERO_LEN_TERM_DIS; usbdaemon->qhs[endpoint].next_dTD_ptr = 0; // Clear terminate bit. //usbdaemon->qhs[endpoint].ep_capabilities |= USB_QHD_TOKEN_IRQ_ON_COMPLETE; @@ -890,7 +784,7 @@ static int _usbd_ep_operation(usb_ep_t endpoint, u8 *buf, u32 len, bool sync) AHB_GIZMO(AHB_AHB_MEM_PREFETCH_CFG1) &= ~MEM_PREFETCH_ENABLE; AHB_GIZMO(AHB_AHB_MEM_PREFETCH_CFG1) |= MEM_PREFETCH_ENABLE; - if (direction == USB_XFER_DIR_IN) + if (direction == USB_DIR_IN) { prime_bit = USB2D_ENDPT_STATUS_TX_OFFSET << actual_ep; bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); @@ -901,7 +795,7 @@ static int _usbd_ep_operation(usb_ep_t endpoint, u8 *buf, u32 len, bool sync) // Prime endpoint. usbd_otg->regs->endptprime |= prime_bit; // USB2_CONTROLLER_USB2D_ENDPTPRIME. - int res = 0; + int res = USB_RES_OK; usb_ep_status_t ep_status; if (sync) { @@ -915,25 +809,25 @@ static int _usbd_ep_operation(usb_ep_t endpoint, u8 *buf, u32 len, bool sync) if (ep_status != USB_EP_STATUS_ACTIVE) { if (ep_status == USB_EP_STATUS_DISABLED) - res = 28; + res = USB2_ERROR_XFER_EP_DISABLED; goto out; } retries--; usleep(1); } - res = 3; + res = USB_ERROR_TIMEOUT; } else if (ep_status == USB_EP_STATUS_DISABLED) - res = 28; + res = USB2_ERROR_XFER_EP_DISABLED; out: if (res) _usbd_mark_ep_complete(endpoint); else if (_usbd_get_ep_status(endpoint) != USB_EP_STATUS_IDLE) - res = 26; - } + res = USB_ERROR_XFER_ERROR; - if (direction == USB_XFER_DIR_OUT) - bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); + if (direction == USB_DIR_OUT) + bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); + } return res; } @@ -951,40 +845,42 @@ static void _usbd_set_ep0_stall() USB2D_ENDPTCTRL_RX_EP_ENABLE | USB2D_ENDPTCTRL_RX_EP_STALL; } -void usbd_set_ep_stall(u32 endpoint, int ep_stall) +int usbd_set_ep_stall(u32 endpoint, int ep_stall) { usb_hw_ep_t actual_ep = (endpoint & 2) >> 1; - usb_xfer_dir_t direction = endpoint & 1; + usb_dir_t direction = endpoint & 1; if (ep_stall) { - if (direction == USB_XFER_DIR_IN) + if (direction == USB_DIR_IN) usbd_otg->regs->endptctrl[actual_ep] |= USB2D_ENDPTCTRL_TX_EP_STALL; // Stall EP Bulk IN. else usbd_otg->regs->endptctrl[actual_ep] |= USB2D_ENDPTCTRL_RX_EP_STALL; // Stall EP Bulk OUT. } else { - if (direction == USB_XFER_DIR_IN) + if (direction == USB_DIR_IN) usbd_otg->regs->endptctrl[actual_ep] &= ~USB2D_ENDPTCTRL_TX_EP_STALL; // Clear stall EP Bulk IN. else usbd_otg->regs->endptctrl[actual_ep] &= ~USB2D_ENDPTCTRL_RX_EP_STALL; // Clear stall EP Bulk OUT. } + + return USB_RES_OK; } -static void _usbd_handle_get_class_request(bool *transmit_data, u8 *descriptor, int *size, int *ep_stall) +static void _usbd_handle_get_class_request(bool *transmit_data, u8 *descriptor, int *size, bool *ep_stall) { u8 _bRequest = usbd_otg->control_setup.bRequest; u16 _wIndex = usbd_otg->control_setup.wIndex; u16 _wValue = usbd_otg->control_setup.wValue; u16 _wLength = usbd_otg->control_setup.wLength; - bool valid_interface = _wIndex == usbd_otg->interface; - bool valid_len = _bRequest == USB_REQUEST_BULK_GET_MAX_LUN ? 1 : 0; + bool valid_interface = _wIndex == usbd_otg->interface_num; + bool valid_len = (_bRequest == USB_REQUEST_BULK_GET_MAX_LUN) ? 1 : 0; if (!valid_interface || _wValue != 0 || _wLength != valid_len) { - *ep_stall = 1; + *ep_stall = true; return; } @@ -992,20 +888,21 @@ static void _usbd_handle_get_class_request(bool *transmit_data, u8 *descriptor, { case USB_REQUEST_BULK_RESET: _usbd_ep_ack(USB_EP_CTRL_IN); - usbd_otg->bulk_reset_req = 1; + usbd_otg->bulk_reset_req = true; break; // DELAYED_STATUS; case USB_REQUEST_BULK_GET_MAX_LUN: - *transmit_data = 1; + *transmit_data = true; + *size = 1; descriptor[0] = usbd_otg->max_lun; // Set 0 LUN for 1 drive supported. - usbd_otg->max_lun_set = 1; + usbd_otg->max_lun_set = true; break; default: - *ep_stall = 1; + *ep_stall = true; break; } } -static void _usbd_handle_get_descriptor(bool *transmit_data, void **descriptor, int *size, int *ep_stall) +static void _usbd_handle_get_descriptor(bool *transmit_data, void **descriptor, int *size, bool *ep_stall) { u8 descriptor_type = usbd_otg->control_setup.wValue >> 8; u8 descriptor_subtype = usbd_otg->control_setup.wValue & 0xFF; @@ -1023,13 +920,13 @@ static void _usbd_handle_get_descriptor(bool *transmit_data, void **descriptor, */ *descriptor = usbd_otg->desc->dev; *size = usbd_otg->desc->dev->bLength; - *transmit_data = 1; + *transmit_data = true; return; } case USB_DESCRIPTOR_CONFIGURATION: - if (usbd_otg->type == USB_GADGET_UMS) + if (usbd_otg->gadget == USB_GADGET_UMS) { - if (usbd_otg->port_speed == 2) // High speed. 512 bytes. + if (usbd_otg->port_speed == USB_HIGH_SPEED) // High speed. 512 bytes. { usbd_otg->desc->cfg->endpoint[0].wMaxPacketSize = 0x200; usbd_otg->desc->cfg->endpoint[1].wMaxPacketSize = 0x200; @@ -1043,20 +940,24 @@ static void _usbd_handle_get_descriptor(bool *transmit_data, void **descriptor, else { usb_cfg_hid_descr_t *tmp = (usb_cfg_hid_descr_t *)usbd_otg->desc->cfg; - if (usbd_otg->port_speed == 2) // High speed. 512 bytes. + if (usbd_otg->port_speed == USB_HIGH_SPEED) // High speed. 512 bytes. { tmp->endpoint[0].wMaxPacketSize = 0x200; tmp->endpoint[1].wMaxPacketSize = 0x200; + tmp->endpoint[0].bInterval = usbd_otg->gadget == USB_GADGET_HID_GAMEPAD ? 4 : 3; // 8ms : 4ms. + tmp->endpoint[1].bInterval = usbd_otg->gadget == USB_GADGET_HID_GAMEPAD ? 4 : 3; // 8ms : 4ms. } else // Full speed. 64 bytes. { tmp->endpoint[0].wMaxPacketSize = 0x40; tmp->endpoint[1].wMaxPacketSize = 0x40; + tmp->endpoint[0].bInterval = usbd_otg->gadget == USB_GADGET_HID_GAMEPAD ? 8 : 4; // 8ms : 4ms. + tmp->endpoint[1].bInterval = usbd_otg->gadget == USB_GADGET_HID_GAMEPAD ? 8 : 4; // 8ms : 4ms. } } *descriptor = usbd_otg->desc->cfg; *size = usbd_otg->desc->cfg->config.wTotalLength; - *transmit_data = 1; + *transmit_data = true; return; case USB_DESCRIPTOR_STRING: switch (descriptor_subtype) @@ -1070,31 +971,32 @@ static void _usbd_handle_get_descriptor(bool *transmit_data, void **descriptor, *size = usbd_otg->desc->product[0]; break; case 3: - *descriptor = usb_serial_string_descriptor; - *size = usb_serial_string_descriptor[0]; + *descriptor = usbd_otg->desc->serial; + *size = usbd_otg->desc->serial[0]; break; case 0xEE: *descriptor = usbd_otg->desc->ms_os; *size = usbd_otg->desc->ms_os->bLength; break; default: - *descriptor = usb_lang_id_string_descriptor; + *descriptor = usbd_otg->desc->lang_id; *size = 4; break; } - *transmit_data = 1; + *transmit_data = true; return; case USB_DESCRIPTOR_DEVICE_QUALIFIER: if (!usbd_otg->desc->dev_qual) goto exit; + usbd_otg->desc->dev_qual->bNumOtherConfigs = 1; *descriptor = usbd_otg->desc->dev_qual; *size = usbd_otg->desc->dev_qual->bLength; - *transmit_data = 1; + *transmit_data = true; return; case USB_DESCRIPTOR_OTHER_SPEED_CONFIGURATION: if (!usbd_otg->desc->cfg_other) goto exit; - if (usbd_otg->port_speed == 2) + if (usbd_otg->port_speed == USB_HIGH_SPEED) { usbd_otg->desc->cfg_other->endpoint[0].wMaxPacketSize = 0x40; usbd_otg->desc->cfg_other->endpoint[1].wMaxPacketSize = 0x40; @@ -1108,62 +1010,61 @@ static void _usbd_handle_get_descriptor(bool *transmit_data, void **descriptor, usbd_otg->desc->cfg_other->config.bMaxPower = 500 / 2; *descriptor = usbd_otg->desc->cfg_other; *size = usbd_otg->desc->cfg_other->config.wTotalLength; - *transmit_data = 1; + *transmit_data = true; return; case USB_DESCRIPTOR_DEVICE_BINARY_OBJECT: *descriptor = usbd_otg->desc->dev_bot; *size = usbd_otg->desc->dev_bot->wTotalLength; - *transmit_data = 1; + *transmit_data = true; return; default: - *transmit_data = 0; - *ep_stall = 1; + *transmit_data = false; + *ep_stall = true; return; } exit: - *transmit_data = 0; - *ep_stall = 1; + *transmit_data = false; + *ep_stall = true; return; } -static int _usbd_handle_set_request(int *ep_stall) +static int _usbd_handle_set_request(bool *ep_stall) { - int ret = 0; + int res = USB_RES_OK; u8 bRequest = usbd_otg->control_setup.bRequest; if (bRequest == USB_REQUEST_SET_ADDRESS) { - ret = _usbd_ep_ack(USB_EP_CTRL_IN); + res = _usbd_ep_ack(USB_EP_CTRL_IN); // Set USB address for device mode. - if (!ret) + if (!res) usbd_otg->regs->periodiclistbase = (usbd_otg->regs->periodiclistbase & 0x1FFFFFF) | ((usbd_otg->control_setup.wValue & 0xFF) << 25); } else if (bRequest == USB_REQUEST_SET_CONFIGURATION) { - ret = _usbd_ep_ack(USB_EP_CTRL_IN); - if (!ret) + res = _usbd_ep_ack(USB_EP_CTRL_IN); + if (!res) { - usbd_otg->configuration = usbd_otg->control_setup.wValue; + usbd_otg->config_num = usbd_otg->control_setup.wValue; _usbd_initialize_ep_ctrl(USB_EP_BULK_OUT); _usbd_initialize_ep_ctrl(USB_EP_BULK_IN); - usbd_otg->configuration_set = 1; + usbd_otg->configuration_set = true; } } else - *ep_stall = 1; + *ep_stall = true; - return ret; + return res; } static int _usbd_handle_ep0_control_transfer() { - int direction; + int res = USB_RES_OK; + bool ep_stall = false; + bool transmit_data = false; - int ret = 0; - bool transmit_data = 0; u8 *descriptor = (u8 *)USB_DESCRIPTOR_ADDR; int size = 0; - int ep_stall = 0; u8 _bmRequestType = usbd_otg->control_setup.bmRequestType; u8 _bRequest = usbd_otg->control_setup.bRequest; @@ -1175,23 +1076,24 @@ static int _usbd_handle_ep0_control_transfer() switch (_bmRequestType) { - case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_DEVICE | USB_SETUP_TYPE_STANDARD): - ret = _usbd_handle_set_request(&ep_stall); + case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_DEVICE): + res = _usbd_handle_set_request(&ep_stall); break; - case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_STANDARD): - ret = _usbd_ep_ack(USB_EP_CTRL_IN); - if (!ret) - usbd_otg->interface = _wValue; + case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_INTERFACE): + res = _usbd_ep_ack(USB_EP_CTRL_IN); + if (!res) + usbd_otg->interface_num = _wValue; break; - case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_ENDPOINT | USB_SETUP_TYPE_STANDARD): + case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT): switch (_bRequest) { case USB_REQUEST_CLEAR_FEATURE: case USB_REQUEST_SET_FEATURE: if ((_wValue & 0xFF) == USB_FEATURE_ENDPOINT_HALT) { + int direction; switch (_wIndex) // endpoint { case USB_EP_ADDR_CTRL_OUT: @@ -1216,94 +1118,101 @@ static int _usbd_handle_ep0_control_transfer() else _usbd_stall_reset_ep1(direction, USB_EP_CFG_STALL); - ret = _usbd_ep_ack(USB_EP_CTRL_IN); + res = _usbd_ep_ack(USB_EP_CTRL_IN); } else _usbd_stall_reset_ep1(3, USB_EP_CFG_STALL); break; default: - ep_stall = 1; + ep_stall = true; break; } break; - case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS): + + case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE): + memset(descriptor, 0, _wLength); _usbd_handle_get_class_request(&transmit_data, descriptor, &size, &ep_stall); break; - case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_DEVICE | USB_SETUP_TYPE_STANDARD): + + case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_DEVICE): switch (_bRequest) { case USB_REQUEST_GET_STATUS: descriptor[0] = USB_STATUS_DEV_SELF_POWERED; descriptor[1] = 0; // No support for remove wake up. - transmit_data = 1; + transmit_data = true; size = 2; break; case USB_REQUEST_GET_DESCRIPTOR: _usbd_handle_get_descriptor(&transmit_data, (void **)&descriptor, &size, &ep_stall); break; case USB_REQUEST_GET_CONFIGURATION: - descriptor = (u8 *)&usbd_otg->configuration; + descriptor = (u8 *)&usbd_otg->config_num; size = _wLength; - transmit_data = 1; + transmit_data = true; break; default: - ep_stall = 1; + ep_stall = true; break; } break; - case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_STANDARD): + case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_INTERFACE): if (_bRequest == USB_REQUEST_GET_INTERFACE) { - descriptor = (void *)&usbd_otg->interface; + memset(descriptor, 0, _wLength); + descriptor[0] = usbd_otg->interface_num; + size = _wLength; } else if (_bRequest == USB_REQUEST_GET_STATUS) { memset(descriptor, 0, _wLength); + size = _wLength; } - else if (_bRequest == USB_REQUEST_GET_DESCRIPTOR && (_wValue >> 8) == USB_DESCRIPTOR_HID_REPORT && usbd_otg->type > USB_GADGET_UMS) + else if (_bRequest == USB_REQUEST_GET_DESCRIPTOR && (_wValue >> 8) == USB_DESCRIPTOR_HID_REPORT && usbd_otg->gadget > USB_GADGET_UMS) { - if (usbd_otg->type == USB_GADGET_HID_GAMEPAD) + if (usbd_otg->gadget == USB_GADGET_HID_GAMEPAD) { descriptor = (u8 *)&hid_report_descriptor_jc; - _wLength = sizeof(hid_report_descriptor_jc); + size = hid_report_descriptor_jc_size; } else // USB_GADGET_HID_TOUCHPAD { descriptor = (u8 *)&hid_report_descriptor_touch; - _wLength = sizeof(hid_report_descriptor_touch); + size = hid_report_descriptor_touch_size; } - usbd_otg->hid_report_sent = 1; + usbd_otg->hid_report_sent = true; } else { - ep_stall = 1; + ep_stall = true; break; } - size = _wLength; - transmit_data = 1; + if (_wLength < size) + size = _wLength; + transmit_data = true; break; - case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_ENDPOINT | USB_SETUP_TYPE_STANDARD): + case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT): if (_bRequest == USB_REQUEST_GET_STATUS) { int ep_req; switch (_wIndex) { - case 0: - ep_req = 0; + case USB_EP_ADDR_CTRL_OUT: + ep_req = USB_EP_CTRL_OUT; break; - case 1: - ep_req = 2; + case USB_EP_ADDR_BULK_OUT: + ep_req = USB_EP_BULK_OUT; break; - case 0x80: - ep_req = 1; + case USB_EP_ADDR_CTRL_IN: + ep_req = USB_EP_CTRL_IN; break; - case 0x81: - ep_req = 3; + case USB_EP_ADDR_BULK_IN: + ep_req = USB_EP_BULK_IN; break; default: _usbd_stall_reset_ep1(3, USB_EP_CFG_STALL); @@ -1318,20 +1227,19 @@ static int _usbd_handle_ep0_control_transfer() else descriptor[0] = USB_STATUS_EP_OK; - transmit_data = 1; + transmit_data = true; } else _usbd_stall_reset_ep1(3, USB_EP_CFG_STALL); break; - case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS): + case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE): memset(descriptor, 0, _wLength); - _usbd_handle_get_class_request(&transmit_data, descriptor, &size, &ep_stall); - size = _wLength; break; - case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR): - case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_DEVICE | USB_SETUP_TYPE_VENDOR): + + case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_VENDOR | USB_SETUP_RECIPIENT_INTERFACE): + case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_VENDOR | USB_SETUP_RECIPIENT_DEVICE): if (_bRequest == USB_REQUEST_GET_MS_DESCRIPTOR) { switch (_wIndex) @@ -1339,24 +1247,24 @@ static int _usbd_handle_ep0_control_transfer() case USB_DESCRIPTOR_MS_COMPAT_ID: descriptor = (u8 *)usbd_otg->desc->ms_cid; size = usbd_otg->desc->ms_cid->dLength; - transmit_data = 1; + transmit_data = true; break; case USB_DESCRIPTOR_MS_EXTENDED_PROPERTIES: descriptor = (u8 *)usbd_otg->desc->mx_ext; size = usbd_otg->desc->mx_ext->dLength; - transmit_data = 1; + transmit_data = true; break; default: - ep_stall = 1; + ep_stall = true; break; } } else - ep_stall = 1; + ep_stall = true; break; default: - ep_stall = 1; + ep_stall = true; break; } @@ -1367,16 +1275,16 @@ static int _usbd_handle_ep0_control_transfer() if (_wLength < size) size = _wLength; - ret = _usbd_ep_operation(USB_EP_CTRL_IN, usb_ep0_ctrl_buf, size, true); - if (!ret) - ret = _usbd_ep_ack(USB_EP_CTRL_OUT); + res = _usbd_ep_operation(USB_EP_CTRL_IN, usb_ep0_ctrl_buf, size, true); + if (!res) + res = _usbd_ep_ack(USB_EP_CTRL_OUT); } out: if (ep_stall) _usbd_set_ep0_stall(); - return ret; + return res; } static int _usbd_ep0_initialize() @@ -1394,8 +1302,8 @@ static int _usbd_ep0_initialize() if (enter) { - usbd_otg->configuration_set = 0; - usbd_otg->max_lun_set = 0; + usbd_otg->configuration_set = false; + usbd_otg->max_lun_set = false; // Timeout if cable or communication isn't started in 1.5 minutes. u32 timer = get_tmr_ms() + 90000; @@ -1432,19 +1340,19 @@ static int _usbd_ep0_initialize() break; } if (usbd_otg->configuration_set) - return 0; + return USB_RES_OK; if (timer < get_tmr_ms() || btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN)) - return 2; + return USB_ERROR_USER_ABORT; } } - return 3; + return USB_ERROR_TIMEOUT; } -int usb_device_ep0_initialize(usb_gadget_type type) +int usb_device_enumerate(usb_gadget_type gadget) { - switch (type) + switch (gadget) { case USB_GADGET_UMS: usbd_otg->desc = &usb_gadget_ums_descriptors; @@ -1457,15 +1365,12 @@ int usb_device_ep0_initialize(usb_gadget_type type) break; } - usbd_otg->type = type; + usbd_otg->gadget = gadget; - int result = _usbd_ep0_initialize(); - if (result) - result = 8; - return result; + return _usbd_ep0_initialize(); } -int usbd_handle_ep0_pending_control_transfer() +int usbd_handle_ep0_ctrl_setup() { // Acknowledge setup request for EP0 and copy its configuration. u32 ep0_setup_req = usbd_otg->regs->endptsetupstat; @@ -1477,49 +1382,51 @@ int usbd_handle_ep0_pending_control_transfer() memset(usb_ep0_ctrl_buf, 0, USB_TD_BUFFER_PAGE_SIZE); } + // Only return error if bulk reset was requested. if (usbd_otg->bulk_reset_req) { - usbd_otg->bulk_reset_req = 0; - return 1; + usbd_otg->bulk_reset_req = false; + return USB_RES_BULK_RESET; } - return 0; + return USB_RES_OK; } -static usb_ep_status_t _usbd_get_ep1_status(usb_xfer_dir_t dir) +static usb_ep_status_t _usbd_get_ep1_status(usb_dir_t dir) { usb_ep_t ep; - if (dir == USB_XFER_DIR_OUT) + if (dir == USB_DIR_OUT) ep = USB_EP_BULK_OUT; else ep = USB_EP_BULK_IN; return _usbd_get_ep_status(ep); } -int usb_device_read_ep1_out(u8 *buf, u32 len, u32 *bytes_read, bool sync) +int usb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, bool sync) { + if ((u32)buf % USB_EP_BUFFER_ALIGN) + return USB2_ERROR_XFER_NOT_ALIGNED; + if (len > USB_EP_BUFFER_MAX_SIZE) len = USB_EP_BUFFER_MAX_SIZE; - int result = _usbd_ep_operation(USB_EP_BULK_OUT, buf, len, sync); + int res = _usbd_ep_operation(USB_EP_BULK_OUT, buf, len, sync); if (sync && bytes_read) - { - if (result) - *bytes_read = 0; - else - *bytes_read = len; - } + *bytes_read = res ? 0 : len; - return result; + return res; } -int usb_device_read_ep1_out_big_reads(u8 *buf, u32 len, u32 *bytes_read) +int usb_device_ep1_out_read_big(u8 *buf, u32 len, u32 *bytes_read) { + if ((u32)buf % USB_EP_BUFFER_ALIGN) + return USB2_ERROR_XFER_NOT_ALIGNED; + if (len > USB_EP_BULK_OUT_MAX_XFER) len = USB_EP_BULK_OUT_MAX_XFER; - int result; + int res; u32 bytes = 0; *bytes_read = 0; u8 *buf_curr = buf; @@ -1528,75 +1435,73 @@ int usb_device_read_ep1_out_big_reads(u8 *buf, u32 len, u32 *bytes_read) { u32 len_ep = MIN(len, USB_EP_BUFFER_MAX_SIZE); - result = usb_device_read_ep1_out(buf_curr, len_ep, &bytes, true); - if (!result) - { - len -= len_ep; - buf_curr += len_ep; - *bytes_read = *bytes_read + bytes; - } - else - break; + res = usb_device_ep1_out_read(buf_curr, len_ep, &bytes, USB_XFER_SYNCED); + if (res) + return res; + + len -= len_ep; + buf_curr += len_ep; + *bytes_read = *bytes_read + bytes; } - return result; + return USB_RES_OK; } static int _usbd_get_ep1_out_bytes_read() { - if (_usbd_get_ep_status(2) != USB_EP_STATUS_IDLE) + if (_usbd_get_ep_status(USB_EP_BULK_OUT) != USB_EP_STATUS_IDLE) return 0; else - return (usbdaemon->ep_bytes_requested[2] - (usbdaemon->qhs[2].token >> 16)); + return (usbdaemon->ep_bytes_requested[USB_EP_BULK_OUT] - (usbdaemon->qhs[USB_EP_BULK_OUT].token >> 16)); } -int usb_device_ep1_out_reading_finish(u32 *pending_bytes) +int usb_device_ep1_out_reading_finish(u32 *pending_bytes, int tries) { usb_ep_status_t ep_status; do { - ep_status = _usbd_get_ep1_status(USB_XFER_DIR_OUT); + ep_status = _usbd_get_ep1_status(USB_DIR_OUT); if ((ep_status == USB_EP_STATUS_IDLE) || (ep_status == USB_EP_STATUS_DISABLED)) break; - usbd_handle_ep0_pending_control_transfer(); + usbd_handle_ep0_ctrl_setup(); } while ((ep_status == USB_EP_STATUS_ACTIVE) || (ep_status == USB_EP_STATUS_STALLED)); *pending_bytes = _usbd_get_ep1_out_bytes_read(); + bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); + if (ep_status == USB_EP_STATUS_IDLE) - return 0; + return USB_RES_OK; else if (ep_status == USB_EP_STATUS_DISABLED) - return 28; + return USB2_ERROR_XFER_EP_DISABLED; else - return 26; + return USB_ERROR_XFER_ERROR; } -int usb_device_write_ep1_in(u8 *buf, u32 len, u32 *bytes_written, bool sync) +int usb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, bool sync) { + if ((u32)buf % USB_EP_BUFFER_ALIGN) + return USB2_ERROR_XFER_NOT_ALIGNED; + if (len > USB_EP_BUFFER_MAX_SIZE) len = USB_EP_BUFFER_MAX_SIZE; - int result = _usbd_ep_operation(USB_EP_BULK_IN, buf, len, sync); + int res = _usbd_ep_operation(USB_EP_BULK_IN, buf, len, sync); if (sync && bytes_written) - { - if (result) - *bytes_written = 0; - else - *bytes_written = len; - } + *bytes_written = res ? 0 : len; - return result; + return res; } static int _usbd_get_ep1_in_bytes_written() { - if (_usbd_get_ep_status(3) != USB_EP_STATUS_IDLE) + if (_usbd_get_ep_status(USB_EP_BULK_IN) != USB_EP_STATUS_IDLE) return 0; else - return (usbdaemon->ep_bytes_requested[3] - (usbdaemon->qhs[3].token >> 16)); + return (usbdaemon->ep_bytes_requested[USB_EP_BULK_IN] - (usbdaemon->qhs[USB_EP_BULK_IN].token >> 16)); } int usb_device_ep1_in_writing_finish(u32 *pending_bytes) @@ -1604,37 +1509,38 @@ int usb_device_ep1_in_writing_finish(u32 *pending_bytes) usb_ep_status_t ep_status; do { - ep_status = _usbd_get_ep1_status(USB_XFER_DIR_IN); + ep_status = _usbd_get_ep1_status(USB_DIR_IN); if ((ep_status == USB_EP_STATUS_IDLE) || (ep_status == USB_EP_STATUS_DISABLED)) break; - usbd_handle_ep0_pending_control_transfer(); + usbd_handle_ep0_ctrl_setup(); } while ((ep_status == USB_EP_STATUS_ACTIVE) || (ep_status == USB_EP_STATUS_STALLED)); *pending_bytes = _usbd_get_ep1_in_bytes_written(); if (ep_status == USB_EP_STATUS_IDLE) - return 0; + return USB_RES_OK; else if (ep_status == USB_EP_STATUS_DISABLED) - return 28; + return USB2_ERROR_XFER_EP_DISABLED; usb_device_stall_ep1_bulk_out(); - return 26; + return USB_ERROR_XFER_ERROR; } bool usb_device_get_suspended() { - u32 suspended = usbd_otg->regs->portsc1 & USB2D_PORTSC1_SUSP; - return (suspended ? true : false); + bool suspended = (usbd_otg->regs->portsc1 & USB2D_PORTSC1_SUSP) == USB2D_PORTSC1_SUSP; + return suspended; } -u32 usb_device_get_port_status() +bool usb_device_get_port_in_sleep() { - return (usbd_otg->regs->portsc1); + // Windows heuristic: Forces port into suspend, sleep and J-State. + return (usbd_otg->regs->portsc1) == 0x885; } -bool usb_device_get_max_lun(u8 max_lun) +int usb_device_class_send_max_lun(u8 max_lun) { // Timeout if get MAX_LUN request doesn't happen in 10s. u32 timer = get_tmr_ms() + 10000; @@ -1643,25 +1549,47 @@ bool usb_device_get_max_lun(u8 max_lun) while (!usbd_otg->max_lun_set) { - usbd_handle_ep0_pending_control_transfer(); + usbd_handle_ep0_ctrl_setup(); if (timer < get_tmr_ms() || btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN)) - return true; + return USB_ERROR_USER_ABORT; } - return false; + return USB_RES_OK; } -bool usb_device_get_hid_report() +int usb_device_class_send_hid_report() { // Timeout if get GET_HID_REPORT request doesn't happen in 10s. u32 timer = get_tmr_ms() + 10000; + // Wait for request and transfer start. while (!usbd_otg->hid_report_sent) { - usbd_handle_ep0_pending_control_transfer(); + usbd_handle_ep0_ctrl_setup(); if (timer < get_tmr_ms() || btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN)) - return true; + return USB_ERROR_USER_ABORT; } - return false; + return USB_RES_OK; } + +void usb_device_get_ops(usb_ops_t *ops) +{ + ops->usbd_flush_endpoint = usbd_flush_endpoint; + ops->usbd_set_ep_stall = usbd_set_ep_stall; + ops->usbd_handle_ep0_ctrl_setup = usbd_handle_ep0_ctrl_setup; + ops->usbd_end = usbd_end; + ops->usb_device_init = usb_device_init; + ops->usb_device_enumerate = usb_device_enumerate; + ops->usb_device_class_send_max_lun = usb_device_class_send_max_lun; + ops->usb_device_class_send_hid_report = usb_device_class_send_hid_report; + ops->usb_device_get_suspended = usb_device_get_suspended; + ops->usb_device_get_port_in_sleep = usb_device_get_port_in_sleep; + + ops->usb_device_ep1_out_read = usb_device_ep1_out_read; + ops->usb_device_ep1_out_read_big = usb_device_ep1_out_read_big; + ops->usb_device_ep1_out_reading_finish = usb_device_ep1_out_reading_finish; + ops->usb_device_ep1_in_write = usb_device_ep1_in_write; + ops->usb_device_ep1_in_writing_finish = usb_device_ep1_in_writing_finish; +} + diff --git a/bdk/usb/usbd.h b/bdk/usb/usbd.h index 82a73e2..6ba2a5a 100644 --- a/bdk/usb/usbd.h +++ b/bdk/usb/usbd.h @@ -1,5 +1,5 @@ /* - * USB Device driver for Tegra X1 + * Enhanced & eXtensible USB Device (EDCI & XDCI) driver for Tegra X1 * * Copyright (c) 2019 CTCaer * @@ -28,6 +28,155 @@ #define USB_EP_BUFFER_2_TD (USB_TD_BUFFER_MAX_SIZE * 2) #define USB_EP_BUFFER_4_TD (USB_TD_BUFFER_MAX_SIZE * 4) #define USB_EP_BUFFER_MAX_SIZE (USB_EP_BUFFER_4_TD) +#define USB_EP_BUFFER_ALIGN (USB_TD_BUFFER_PAGE_SIZE) + +#define USB_XFER_START false +#define USB_XFER_SYNCED true + +typedef enum _usb_hid_type +{ + USB_HID_GAMEPAD, + USB_HID_TOUCHPAD +} usb_hid_type; + +typedef enum _usb_gadget_type +{ + USB_GADGET_UMS = 0, + USB_GADGET_HID_GAMEPAD = 1, + USB_GADGET_HID_TOUCHPAD = 2, +} usb_gadget_type; + +typedef enum { + USB_DIR_OUT = 0, + USB_DIR_IN = 1, +} usb_dir_t; + +typedef enum +{ + XUSB_EP_CTRL_IN = 0, // EP0. + XUSB_EP_CTRL_OUT = 1, // EP0. + + USB_EP_CTRL_OUT = 0, // EP0. + USB_EP_CTRL_IN = 1, // EP0. + + USB_EP_BULK_OUT = 2, // EP1. + USB_EP_BULK_IN = 3, // EP1. + USB_EP_ALL = 0xFFFFFFFF +} usb_ep_t; + +typedef enum +{ + USB_EP_ADDR_CTRL_OUT = 0x00, + USB_EP_ADDR_CTRL_IN = 0x80, + USB_EP_ADDR_BULK_OUT = 0x01, + USB_EP_ADDR_BULK_IN = 0x81, +} usb_ep_addr_t; + +typedef enum +{ + USB_EP_CFG_CLEAR = 0, + USB_EP_CFG_RESET = 0, + USB_EP_CFG_STALL = 1 +} usb_ep_cfg_t; + +typedef enum { + USB_STATUS_EP_OK = 0, + USB_STATUS_EP_HALTED = 1, + + USB_STATUS_DEV_SELF_POWERED = 1, + USB_STATUS_DEV_REMOTE_WAKE = 2, +} usb_set_clear_feature_req_t; + +typedef enum { + USB_SETUP_RECIPIENT_DEVICE = 0, + USB_SETUP_RECIPIENT_INTERFACE = 1, + USB_SETUP_RECIPIENT_ENDPOINT = 2, + USB_SETUP_RECIPIENT_OTHER = 3, + + USB_SETUP_TYPE_STANDARD = 0x00, + USB_SETUP_TYPE_CLASS = 0x20, + USB_SETUP_TYPE_VENDOR = 0x40, + USB_SETUP_TYPE_RESERVED = 0x60, + + USB_SETUP_HOST_TO_DEVICE = 0x00, + USB_SETUP_DEVICE_TO_HOST = 0x80, +} usb_setup_req_type_t; + +typedef enum { + USB_REQUEST_GET_STATUS = 0, + USB_REQUEST_CLEAR_FEATURE = 1, + USB_REQUEST_SET_FEATURE = 3, + USB_REQUEST_SET_ADDRESS = 5, + USB_REQUEST_GET_DESCRIPTOR = 6, + USB_REQUEST_SET_DESCRIPTOR = 7, + USB_REQUEST_GET_CONFIGURATION = 8, + USB_REQUEST_SET_CONFIGURATION = 9, + USB_REQUEST_GET_INTERFACE = 10, + USB_REQUEST_SET_INTERFACE = 11, + USB_REQUEST_SYNCH_FRAME = 12, + USB_REQUEST_SET_SEL = 13, + + USB_REQUEST_GET_MS_DESCRIPTOR = 0x99, + + USB_REQUEST_BULK_GET_MAX_LUN = 0xFE, + USB_REQUEST_BULK_RESET = 0xFF +} usb_standard_req_t; + +typedef enum { + USB_FEATURE_ENDPOINT_HALT = 0, + USB_FEATURE_DEVICE_REMOTE_WAKEUP = 1, + USB_FEATURE_TEST_MODE = 2, +} usb_get_status_req_t; + +typedef enum _usb_error_t +{ + USB_RES_OK = 0, + USB_RES_BULK_RESET = 1, + + USB_ERROR_USER_ABORT = 2, + USB_ERROR_TIMEOUT = 3, + USB_ERROR_INIT = 4, + USB_ERROR_XFER_ERROR = 5, + + USB2_ERROR_XFER_EP_DISABLED = 28, + USB2_ERROR_XFER_NOT_ALIGNED = 29, + + XUSB_ERROR_INVALID_EP = USB_ERROR_XFER_ERROR, // From 2. + XUSB_ERROR_XFER_BULK_IN_RESIDUE = 7, + XUSB_ERROR_INVALID_CYCLE = USB2_ERROR_XFER_EP_DISABLED, // From 8. + XUSB_ERROR_SEQ_NUM = 51, + XUSB_ERROR_XFER_DIR = 52, + XUSB_ERROR_PORT_CFG = 54 +} usb_error_t; + +typedef struct _usb_ctrl_setup_t +{ + u8 bmRequestType; + u8 bRequest; + u16 wValue; + u16 wIndex; + u16 wLength; +} usb_ctrl_setup_t; + +typedef struct _usb_ops_t +{ + int (*usbd_flush_endpoint)(u32); + int (*usbd_set_ep_stall)(u32, int); + int (*usbd_handle_ep0_ctrl_setup)(); + void (*usbd_end)(bool, bool); + int (*usb_device_init)(); + int (*usb_device_enumerate)(usb_gadget_type gadget); + int (*usb_device_class_send_max_lun)(u8); + int (*usb_device_class_send_hid_report)(); + + int (*usb_device_ep1_out_read)(u8 *, u32, u32 *, bool); + int (*usb_device_ep1_out_read_big)(u8 *, u32, u32 *); + int (*usb_device_ep1_out_reading_finish)(u32 *, int); + int (*usb_device_ep1_in_write)(u8 *, u32, u32 *, bool); + int (*usb_device_ep1_in_writing_finish)(u32 *); + bool (*usb_device_get_suspended)(); + bool (*usb_device_get_port_in_sleep)(); +} usb_ops_t; typedef struct _usb_ctxt_t { @@ -41,46 +190,10 @@ typedef struct _usb_ctxt_t void (*set_text)(void *, const char *); } usb_ctxt_t; -typedef enum _usb_hid_type -{ - USB_HID_GAMEPAD, - USB_HID_TOUCHPAD -} usb_hid_type; - -typedef enum _usb_gadget_type -{ - USB_GADGET_UMS, - USB_GADGET_HID_GAMEPAD, - USB_GADGET_HID_TOUCHPAD -} usb_gadget_type; - -typedef enum -{ - USB_EP_CTRL_OUT = 0, // EP0. - USB_EP_CTRL_IN = 1, // EP0. - USB_EP_BULK_OUT = 2, // EP1. - USB_EP_BULK_IN = 3, // EP1. - USB_EP_ALL = 0xFFFFFFFF -} usb_ep_t; - -int usbd_flush_endpoint(u32 ep); -void usbd_set_ep_stall(u32 endpoint, int ep_stall); -int usbd_get_max_pkt_length(int endpoint); -int usbd_handle_ep0_pending_control_transfer(); -void usbd_end(bool reset_ep, bool only_controller); -int usb_device_init(); -int usb_device_ep0_initialize(usb_gadget_type type); -int usb_device_read_ep1_out(u8 *buf, u32 len, u32 *bytes_read, bool sync); -int usb_device_read_ep1_out_big_reads(u8 *buf, u32 len, u32 *bytes_read); -int usb_device_ep1_out_reading_finish(u32 *pending_bytes); -int usb_device_write_ep1_in(u8 *buf, u32 len, u32 *bytes_written, bool sync); -int usb_device_ep1_in_writing_finish(u32 *pending_bytes); -bool usb_device_get_suspended(); +void usb_device_get_ops(usb_ops_t *ops); +void xusb_device_get_ops(usb_ops_t *ops); int usb_device_gadget_ums(usb_ctxt_t *usbs); int usb_device_gadget_hid(usb_ctxt_t *usbs); -bool usb_device_get_max_lun(u8 max_lun); -bool usb_device_get_hid_report(); -u32 usb_device_get_port_status(); #endif \ No newline at end of file diff --git a/bdk/usb/xusbd.c b/bdk/usb/xusbd.c new file mode 100644 index 0000000..e33ca44 --- /dev/null +++ b/bdk/usb/xusbd.c @@ -0,0 +1,2022 @@ +/* + * eXtensible USB Device driver (XDCI) for Tegra X1 + * + * Copyright (c) 2020 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define XUSB_TRB_SLOTS 16 //! TODO: Consider upping it. +#define XUSB_LINK_TRB_IDX (XUSB_TRB_SLOTS - 1) +#define XUSB_LAST_TRB_IDX (XUSB_TRB_SLOTS - 1) + +#define EP_DONT_RING 0 +#define EP_RING_DOORBELL 1 + +typedef enum { + XUSB_FULL_SPEED = 1, + XUSB_HIGH_SPEED = 3, + XUSB_SUPER_SPEED = 4 +} xusb_speed_t; + +typedef enum { + EP_DISABLED = 0, + EP_RUNNING = 1, + EP_HALTED = 2, + EP_STOPPED = 3, + EP_ERROR = 4 +} xusb_ep_status_t; + +typedef enum { + EP_TYPE_ISOC_OUT = 1, + EP_TYPE_BULK_OUT = 2, + EP_TYPE_INTR_OUT = 3, + EP_TYPE_CNTRL = 4, + EP_TYPE_ISOC_IN = 5, + EP_TYPE_BULK_IN = 6, + EP_TYPE_INTR_IN = 7 +} xusb_ep_type_t; + +typedef enum { + XUSB_DEFAULT = 0, + XUSB_ADDRESSED_STS_WAIT = 1, + XUSB_ADDRESSED = 2, + XUSB_CONFIGURED_STS_WAIT = 3, + XUSB_CONFIGURED = 4, + + XUSB_LUN_CONFIGURED_STS_WAIT = 5, + XUSB_LUN_CONFIGURED = 6, + XUSB_HID_CONFIGURED_STS_WAIT = 7, + XUSB_HID_CONFIGURED = 8, + + // XUSB_CONNECTED = , + // XUSB_DISCONNECTED = , + // XUSB_RESET = , + // XUSB_SUSPENDED = , +} xusb_dev_state_t; + +typedef enum { + XUSB_TRB_NONE = 0, + XUSB_TRB_NORMAL = 1, + XUSB_TRB_DATA = 3, + XUSB_TRB_STATUS = 4, + XUSB_TRB_LINK = 6, + XUSB_TRB_TRANSFER = 32, + XUSB_TRB_PORT_CHANGE = 34, + XUSB_TRB_SETUP = 63, +} xusb_trb_type_t; + +typedef enum { + XUSB_COMP_INVALID = 0, + XUSB_COMP_SUCCESS = 1, + XUSB_COMP_DATA_BUFFER_ERROR = 2, + XUSB_COMP_BABBLE_DETECTED_ERROR = 3, + XUSB_COMP_USB_TRANSACTION_ERROR = 4, + XUSB_COMP_TRB_ERROR = 5, + XUSB_COMP_STALL_ERROR = 6, + XUSB_COMP_RESOURCE_ERROR = 7, + XUSB_COMP_BANDWIDTH_ERROR = 8, + XUSB_COMP_NO_SLOTS_AVAILABLE_ERROR = 9, + XUSB_COMP_INVALID_STREAM_TYPE_ERROR = 10, + XUSB_COMP_SLOT_NOT_ENABLED_ERROR = 11, + XUSB_COMP_EP_DISABLED_ERROR = 12, + XUSB_COMP_SHORT_PKT = 13, + XUSB_COMP_RING_UNDERRUN = 14, + XUSB_COMP_RING_OVERRUN = 15, + XUSB_COMP_VF_EVENT_RING_FULL_ERROR = 16, + XUSB_COMP_PARAMETER_ERROR = 17, + XUSB_COMP_BANDWIDTH_OVERRUN_ERROR = 18, + XUSB_COMP_CONTEXT_STATE_ERROR = 19, + XUSB_COMP_NO_PING_RESPONSE_ERROR = 20, + XUSB_COMP_EVENT_RING_FULL_ERROR = 21, + XUSB_COMP_INCOMPATIBLE_DEVICE_ERROR = 22, + XUSB_COMP_MISSED_SERVICE_ERROR = 23, + XUSB_COMP_COMMAND_RING_STOPPED = 24, + XUSB_COMP_COMMAND_ABORTED = 25, + XUSB_COMP_STOPPED = 26, + XUSB_COMP_STOPPED_LENGTH_INVALID = 27, + XUSB_COMP_STOPPED_SHORT_PACKET = 28, + XUSB_COMP_EXIT_LATENCY_LARGE_ERROR = 29, + XUSB_COMP_ISOCH_BUFFER_OVERRUN = 31, + XUSB_COMP_EVENT_LOST_ERROR = 32, + XUSB_COMP_UNDEFINED_ERROR = 33, + XUSB_COMP_INVALID_STREAM_ID_ERROR = 34, + XUSB_COMP_SECONDARY_BANDWIDTH_ERROR = 35, + XUSB_COMP_SPLIT_TRANSACTION_ERROR = 36, + + XUSB_COMP_CODE_STREAM_NUMP_ERROR = 219, + XUSB_COMP_PRIME_PIPE_RECEIVED = 220, + XUSB_COMP_HOST_REJECTED = 221, + XUSB_COMP_CTRL_DIR_ERROR = 222, + XUSB_COMP_CTRL_SEQ_NUM_ERROR = 223 +} xusb_comp_code_t; + +typedef struct _event_trb_t +{ + u32 rsvd0; + u32 rsvd1; + + u32 rsvd2:24; + u32 comp_code:8; + + u32 cycle:1; + u32 rsvd3:9; + u32 trb_type:6; + u32 ep_id:5; + u32 rsvd4:11; +} event_trb_t; + +typedef struct _transfer_event_trb_t { + u32 trb_pointer_lo; + u32 trb_pointer_hi; + + u32 trb_tx_len:24; + u32 comp_code:8; + + u32 cycle:1; + u32 rsvddw3_0:1; + u32 event_data:1; + u32 rsvddw3_1:7; + u32 trb_type:6; + u32 ep_id:5; + u32 rsvddw3_2:11; +} transfer_event_trb_t; + +typedef struct _setup_event_trb_t +{ + usb_ctrl_setup_t ctrl_setup_data; + + u32 ctrl_seq_num:16; + u32 rsvddw2_0:8; + u32 comp_code:8; + + u32 cycle:1; + u32 rsvddw3_0:9; + u32 trb_type:6; + u32 ep_id:5; + u32 rsvddw3_1:11; +} setup_event_trb_t; + +typedef struct _status_trb_t +{ + u32 rsvd0; + u32 rsvd1; + + u32 rsvd2:22; + u32 interrupt_target:10; + + u32 cycle:1; + u32 ent:1; + u32 rsvd3_0:2; + u32 chain:1; + u32 ioc:1; + u32 rsvd3_1:4; + u32 trb_type:6; + u32 dir:1; + u32 rsvd3_2:15; +} status_trb_t; + +typedef struct _normal_trb_t +{ + u32 databufptr_lo; + u32 databufptr_hi; + + u32 trb_tx_len:17; + u32 td_size:5; + u32 interrupt_target:10; + + u32 cycle:1; + u32 ent:1; + u32 isp:1; + u32 no_snoop:1; + u32 chain:1; + u32 ioc:1; + u32 idt:1; + u32 rsvd0_0:2; + u32 bei:1; + u32 trb_type:6; + u32 rsvd0_1:16; +} normal_trb_t; + +typedef struct _data_trb_t +{ + u32 databufptr_lo; + u32 databufptr_hi; + + u32 trb_tx_len:17; + u32 td_size:5; + u32 interrupt_target:10; + + u32 cycle:1; + u32 ent:1; + u32 isp:1; + u32 no_snoop:1; + u32 chain:1; + u32 ioc:1; + u32 rsvd0_0:4; + u32 trb_type:6; + u32 dir:1; + u32 rsvd0_1:15; +} data_trb_t; + +typedef struct _link_trb_t +{ + u32 rsvd0_0:4; + u32 ring_seg_ptrlo:28; + + u32 ring_seg_ptrhi; + + u32 rsvd1_0:22; + u32 interrupt_target:10; + + u32 cycle:1; + u32 toggle_cycle:1; + u32 rsvd3_0:2; + u32 chain:1; + u32 ioc:1; + u32 rsvd3_1:4; + u32 trb_type:6; + u32 rsvd3_2:16; +} link_trb_t; + +typedef struct _xusb_ep_ctx_t +{ + // Common context. + u32 ep_state:3; + u32 rsvddW0_0:5; + u32 mult:2; + u32 max_pstreams:5; + u32 lsa:1; + u32 interval:8; + u32 rsvddW0_1:8; + + u32 rsvddw1_0:1; + u32 cerr:2; + u32 ep_type:3; + u32 rsvddw1_1:1; + u32 hid:1; + u32 max_burst_size:8; + u32 max_packet_size:16; + + u32 dcs:1; + u32 rsvddw2_0:3; + u32 trd_dequeueptr_lo:28; + + u32 trd_dequeueptr_hi; + + u32 avg_trb_len:16; + u32 max_esit_payload:16; + + // Nvidia context. + u32 event_data_txlen_acc; + + u32 cprog:8; + u32 sbyte:7; + u32 tp:2; + u32 rec:1; + u32 cec:2; + u32 ced:1; + u32 hsp1:1; + u32 rty1:1; + u32 std:1; + u32 status:8; + + u32 data_offset; + + u32 scratch_pad0; + + u32 scratch_pad1; + + u32 cping:8; + u32 sping:8; + u32 toggle_cycle:2; + u32 no_snoop:1; + u32 ro:1; + u32 tlm:1; + u32 dlm:1; + u32 hsp2:1; + u32 rty2:1; + u32 stop_rec_req:8; + + u32 device_addr:8; + u32 hub_addr:8; + u32 root_port_num:8; + u32 slot_id:8; + + u32 routing_string:20; + u32 speed:4; + u32 lpu:1; + u32 mtt:1; + u32 hub:1; + u32 dci:5; + + u32 tthub_slot_id:8; + u32 ttport_num:8; + u32 ssf:4; + u32 sps:2; + u32 interrupt_target:10; + + u32 frz:1; + u32 end:1; + u32 elm:1; + u32 mrx:1; + u32 ep_linklo:28; + + u32 ep_linkhi; +} xusb_ep_ctx_t; + +typedef struct _xusbd_controller_t +{ + data_trb_t *cntrl_epenqueue_ptr; + data_trb_t *cntrl_epdequeue_ptr; + u32 cntrl_producer_cycle; + data_trb_t *bulkout_epenqueue_ptr; + data_trb_t *bulkout_epdequeue_ptr; + u32 bulkout_producer_cycle; + data_trb_t *bulkin_epenqueue_ptr; + data_trb_t *bulkin_epdequeue_ptr; + u32 bulkin_producer_cycle; + event_trb_t *event_enqueue_ptr; + event_trb_t *event_dequeue_ptr; + u32 event_ccs; + u32 device_state; + u32 bytes_remaining[2]; + u32 tx_count[2]; + u32 ctrl_seq_num; + u32 config_num; + u32 interface_num; + u32 wait_for_event_trb; + u32 port_speed; + + usb_desc_t *desc; + usb_gadget_type gadget; + + u8 max_lun; + bool max_lun_set; + bool bulk_reset_req; +} xusbd_controller_t; + +extern u32 hid_report_descriptor_jc_size; +extern u32 hid_report_descriptor_touch_size; +extern u8 hid_report_descriptor_jc[]; +extern u8 hid_report_descriptor_touch[]; +extern usb_desc_t usb_gadget_hid_jc_descriptors; +extern usb_desc_t usb_gadget_hid_touch_descriptors; +extern usb_desc_t usb_gadget_ums_descriptors; + +// All rings and EP context must be aligned to 0x10. +typedef struct _xusbd_event_queues_t +{ + event_trb_t xusb_event_ring_seg0[XUSB_TRB_SLOTS]; + event_trb_t xusb_event_ring_seg1[XUSB_TRB_SLOTS]; + data_trb_t xusb_cntrl_event_queue[XUSB_TRB_SLOTS]; + data_trb_t xusb_bulkin_event_queue[XUSB_TRB_SLOTS]; + data_trb_t xusb_bulkout_event_queue[XUSB_TRB_SLOTS]; + volatile xusb_ep_ctx_t xusb_ep_ctxt[4]; +} xusbd_event_queues_t; + +// Set event queues context to a 0x10 aligned address. +xusbd_event_queues_t *xusb_evtq = (xusbd_event_queues_t *)XUSB_RING_ADDR; + +xusbd_controller_t *usbd_xotg; +xusbd_controller_t usbd_xotg_controller_ctxt; + +static int _xusb_xhci_mask_wait(u32 reg, u32 mask, u32 val, u32 retries) +{ + do + { + if ((XUSB_DEV_XHCI(reg) & mask) == val) + return USB_RES_OK; + usleep(1); + --retries; + } + while (retries); + + return USB_ERROR_TIMEOUT; +} + +// Event rings aligned to 0x10 +static void _xusbd_ep_init_event_ring() +{ + memset(xusb_evtq->xusb_event_ring_seg0, 0, sizeof(xusb_evtq->xusb_event_ring_seg0)); + memset(xusb_evtq->xusb_event_ring_seg1, 0, sizeof(xusb_evtq->xusb_event_ring_seg1)); + + //! TODO USB3: enable pcie regulators. + + // Set Event Ring Segment 0 Base Address. + XUSB_DEV_XHCI(XUSB_DEV_XHCI_ERST0BALO) = (u32)xusb_evtq->xusb_event_ring_seg0; + XUSB_DEV_XHCI(XUSB_DEV_XHCI_ERST0BAHI) = 0; + + // Set Event Ring Segment 1 Base Address. + XUSB_DEV_XHCI(XUSB_DEV_XHCI_ERST1BALO) = (u32)xusb_evtq->xusb_event_ring_seg1; + XUSB_DEV_XHCI(XUSB_DEV_XHCI_ERST1BAHI) = 0; + + // Set Event Ring Segment sizes. + XUSB_DEV_XHCI(XUSB_DEV_XHCI_ERSTSZ) = (XUSB_TRB_SLOTS << 16) | XUSB_TRB_SLOTS; + + // Set Enqueue and Dequeue pointers. + usbd_xotg->event_enqueue_ptr = xusb_evtq->xusb_event_ring_seg0; + usbd_xotg->event_dequeue_ptr = xusb_evtq->xusb_event_ring_seg0; + usbd_xotg->event_ccs = 1; + + // Event Ring Enqueue Pointer. + u32 evt_ring_addr = (u32)xusb_evtq->xusb_event_ring_seg0 & 0xFFFFFFF0; + XUSB_DEV_XHCI(XUSB_DEV_XHCI_EREPLO) = (XUSB_DEV_XHCI(XUSB_DEV_XHCI_EREPLO) & 0xE) | evt_ring_addr | XCHI_ECS; + XUSB_DEV_XHCI(XUSB_DEV_XHCI_EREPHI) = 0; + + // Set Event Ring Dequeue Pointer. + XUSB_DEV_XHCI(XUSB_DEV_XHCI_ERDPLO) = (XUSB_DEV_XHCI(XUSB_DEV_XHCI_ERDPLO) & 0xF) | evt_ring_addr; + XUSB_DEV_XHCI(XUSB_DEV_XHCI_ERDPHI) = 0; +} + +static void _xusb_ep_set_type_and_metrics(u32 ep_idx, volatile xusb_ep_ctx_t *ep_ctxt) +{ + usb_ep_descr_t *ep_desc = NULL; + usb_ep_descr_t *endpoints = usbd_xotg->desc->cfg->endpoint; + + switch (ep_idx) + { + case XUSB_EP_CTRL_IN: + // Set EP type. + ep_ctxt->ep_type = EP_TYPE_CNTRL; + + // Set max packet size based on port speed. + ep_ctxt->avg_trb_len = 8; + ep_ctxt->max_packet_size = 64; //! TODO USB3: max_packet_size = 512. + break; + + case USB_EP_BULK_OUT: + // Set default EP type. + ep_ctxt->ep_type = EP_TYPE_BULK_OUT; + + // Check configuration descriptor. + if (usbd_xotg->desc->cfg->interface.bInterfaceClass == 0x3) // HID Class. + endpoints = (usb_ep_descr_t *)((void *)endpoints + sizeof(usb_hid_descr_t)); + + for (u32 i = 0; i < usbd_xotg->desc->cfg->interface.bNumEndpoints; i++) + if (endpoints[i].bEndpointAddress == USB_EP_ADDR_BULK_OUT) + { + ep_desc = &endpoints[i]; + break; + } + + // Set actual EP type. + if (ep_desc) + { + switch (ep_desc->bmAttributes) + { + case USB_EP_TYPE_ISO: + ep_ctxt->ep_type = EP_TYPE_ISOC_OUT; + break; + case USB_EP_TYPE_BULK: + ep_ctxt->ep_type = EP_TYPE_BULK_OUT; + break; + case USB_EP_TYPE_INTR: + ep_ctxt->ep_type = EP_TYPE_INTR_OUT; + break; + } + } + + // Set average TRB length. + //TODO: Use ep type instead (we don't expect to calculate avg per gadget)? + switch (usbd_xotg->gadget) + { + case USB_GADGET_UMS: + ep_ctxt->avg_trb_len = 3072; + break; + case USB_GADGET_HID_GAMEPAD: + case USB_GADGET_HID_TOUCHPAD: + ep_ctxt->avg_trb_len = 1024; + break; + default: + switch (usbd_xotg->port_speed) + { + case XUSB_SUPER_SPEED: + ep_ctxt->avg_trb_len = 1024; + break; + case XUSB_HIGH_SPEED: + case XUSB_FULL_SPEED: + ep_ctxt->avg_trb_len = 512; + break; + } + break; + } + + // Set max burst rate. + ep_ctxt->max_burst_size = (ep_desc->wMaxPacketSize >> 11) & 3; + + // Set max packet size based on port speed. + if (usbd_xotg->port_speed == XUSB_SUPER_SPEED) + { + ep_ctxt->max_packet_size = 1024; + + //! TODO USB3: + // If ISO or INTR EP, set Max Esit Payload size. + // ep_ctxt->max_burst_size = bMaxBurst; + //if (ep_ctxt->ep_type == EP_TYPE_INTR_OUT || ep_ctxt->ep_type == EP_TYPE_ISOC_OUT) + // ep_ctxt->max_esit_payload = ep_ctxt->max_packet_size * (ep_ctxt->max_burst_size + 1); + } + else if (usbd_xotg->port_speed == XUSB_HIGH_SPEED) + { + ep_ctxt->max_packet_size = 512; + + // If ISO or INTR EP, set Max Esit Payload size. + if (ep_ctxt->ep_type == EP_TYPE_INTR_OUT || ep_ctxt->ep_type == EP_TYPE_ISOC_OUT) + ep_ctxt->max_esit_payload = ep_ctxt->max_packet_size * (ep_ctxt->max_burst_size + 1); + } + else + { + ep_ctxt->max_packet_size = 64; + + // If ISO or INTR EP, set Max Esit Payload size. + if (ep_ctxt->ep_type == EP_TYPE_INTR_OUT || ep_ctxt->ep_type == EP_TYPE_ISOC_OUT) + ep_ctxt->max_esit_payload = ep_ctxt->max_packet_size; + } + break; + + case USB_EP_BULK_IN: + // Set default EP type. + ep_ctxt->ep_type = EP_TYPE_BULK_IN; + + // Check configuration descriptor. + if (usbd_xotg->desc->cfg->interface.bInterfaceClass == 0x3) // HID Class. + endpoints = (usb_ep_descr_t *)((void *)endpoints + sizeof(usb_hid_descr_t)); + + for (u32 i = 0; i < usbd_xotg->desc->cfg->interface.bNumEndpoints; i++) + if (endpoints[i].bEndpointAddress == USB_EP_ADDR_BULK_IN) + { + ep_desc = &endpoints[i]; + break; + } + + // Set actual EP type. + if (ep_desc) + { + switch (ep_desc->bmAttributes) + { + case USB_EP_TYPE_ISO: + ep_ctxt->ep_type = EP_TYPE_ISOC_IN; + break; + case USB_EP_TYPE_BULK: + ep_ctxt->ep_type = EP_TYPE_BULK_IN; + break; + case USB_EP_TYPE_INTR: + ep_ctxt->ep_type = EP_TYPE_INTR_IN; + break; + } + } + + // Set average TRB length. + //TODO: Use ep type instead (we don't expect to calculate avg per gadget)? + switch (usbd_xotg->gadget) + { + case USB_GADGET_UMS: + ep_ctxt->avg_trb_len = 3072; + break; + case USB_GADGET_HID_GAMEPAD: + case USB_GADGET_HID_TOUCHPAD: + ep_ctxt->avg_trb_len = 16; // Normal interrupt avg is 1024KB. + break; + default: + switch (usbd_xotg->port_speed) + { + case XUSB_SUPER_SPEED: + ep_ctxt->avg_trb_len = 1024; + break; + case XUSB_HIGH_SPEED: + case XUSB_FULL_SPEED: + ep_ctxt->avg_trb_len = 512; + break; + } + break; + } + + // Set max burst rate. + ep_ctxt->max_burst_size = (ep_desc->wMaxPacketSize >> 11) & 3; + + // Set max packet size based on port speed. + if (usbd_xotg->port_speed == XUSB_SUPER_SPEED) + { + ep_ctxt->max_packet_size = 1024; + + //! TODO USB3: + // If ISO or INTR EP, set Max Esit Payload size. + // ep_ctxt->max_burst_size = bMaxBurst; + //if (ep_ctxt->ep_type == EP_TYPE_INTR_IN || ep_ctxt->ep_type == EP_TYPE_ISOC_IN) + // ep_ctxt->max_esit_payload = ep_ctxt->max_packet_size * (ep_ctxt->max_burst_size + 1); + } + else if (usbd_xotg->port_speed == XUSB_HIGH_SPEED) + { + ep_ctxt->max_packet_size = 512; + + // If ISO or INTR EP, set Max Esit Payload size. + if (ep_ctxt->ep_type == EP_TYPE_INTR_IN || ep_ctxt->ep_type == EP_TYPE_ISOC_IN) + ep_ctxt->max_esit_payload = ep_ctxt->max_packet_size * (ep_ctxt->max_burst_size + 1); + } + else + { + ep_ctxt->max_packet_size = 64; + + // If ISO or INTR EP, set Max Esit Payload size. + if (ep_ctxt->ep_type == EP_TYPE_INTR_IN || ep_ctxt->ep_type == EP_TYPE_ISOC_IN) + ep_ctxt->max_esit_payload = ep_ctxt->max_packet_size; + } + break; + } +} + +static int _xusb_ep_init_context(u32 ep_idx) +{ + link_trb_t *link_trb; + + if (ep_idx > USB_EP_BULK_IN) + return USB_ERROR_INIT; + + if (ep_idx == XUSB_EP_CTRL_OUT) + ep_idx = XUSB_EP_CTRL_IN; + + volatile xusb_ep_ctx_t *ep_ctxt = &xusb_evtq->xusb_ep_ctxt[ep_idx]; + memset((void *)ep_ctxt, 0, sizeof(xusb_ep_ctx_t)); + + ep_ctxt->ep_state = EP_RUNNING; + ep_ctxt->dcs = 1; + ep_ctxt->cec = 3; + ep_ctxt->cerr = 3; + ep_ctxt->max_burst_size = 0; + + switch (ep_idx) + { + case XUSB_EP_CTRL_IN: + usbd_xotg->cntrl_producer_cycle = 1; + usbd_xotg->cntrl_epenqueue_ptr = xusb_evtq->xusb_cntrl_event_queue; + usbd_xotg->cntrl_epdequeue_ptr = xusb_evtq->xusb_cntrl_event_queue; + + _xusb_ep_set_type_and_metrics(ep_idx, ep_ctxt); + + ep_ctxt->trd_dequeueptr_lo = (u32)xusb_evtq->xusb_cntrl_event_queue >> 4; + ep_ctxt->trd_dequeueptr_hi = 0; + + link_trb = (link_trb_t *)&xusb_evtq->xusb_cntrl_event_queue[XUSB_LINK_TRB_IDX]; + link_trb->toggle_cycle = 1; + link_trb->ring_seg_ptrlo = (u32)xusb_evtq->xusb_cntrl_event_queue >> 4; + link_trb->ring_seg_ptrhi = 0; + link_trb->trb_type = XUSB_TRB_LINK; + break; + + case USB_EP_BULK_OUT: + usbd_xotg->bulkout_producer_cycle = 1; + usbd_xotg->bulkout_epenqueue_ptr = xusb_evtq->xusb_bulkout_event_queue; + usbd_xotg->bulkout_epdequeue_ptr = xusb_evtq->xusb_bulkout_event_queue; + + _xusb_ep_set_type_and_metrics(ep_idx, ep_ctxt); + + ep_ctxt->trd_dequeueptr_lo = (u32)xusb_evtq->xusb_bulkout_event_queue >> 4; + ep_ctxt->trd_dequeueptr_hi = 0; + + link_trb = (link_trb_t *)&xusb_evtq->xusb_bulkout_event_queue[XUSB_LINK_TRB_IDX]; + link_trb->toggle_cycle = 1; + link_trb->ring_seg_ptrlo = (u32)xusb_evtq->xusb_bulkout_event_queue >> 4; + link_trb->ring_seg_ptrhi = 0; + link_trb->trb_type = XUSB_TRB_LINK; + break; + + case USB_EP_BULK_IN: + usbd_xotg->bulkin_producer_cycle = 1; + usbd_xotg->bulkin_epenqueue_ptr = xusb_evtq->xusb_bulkin_event_queue; + usbd_xotg->bulkin_epdequeue_ptr = xusb_evtq->xusb_bulkin_event_queue; + + _xusb_ep_set_type_and_metrics(ep_idx, ep_ctxt); + + ep_ctxt->trd_dequeueptr_lo = (u32)xusb_evtq->xusb_bulkin_event_queue >> 4; + ep_ctxt->trd_dequeueptr_hi = 0; + + link_trb = (link_trb_t *)&xusb_evtq->xusb_bulkin_event_queue[XUSB_LINK_TRB_IDX]; + link_trb->toggle_cycle = 1; + link_trb->ring_seg_ptrlo = (u32)xusb_evtq->xusb_bulkin_event_queue >> 4; + link_trb->ring_seg_ptrhi = 0; + link_trb->trb_type = XUSB_TRB_LINK; + break; + } + + return USB_RES_OK; +} + +static int _xusbd_ep_initialize(u32 ep_idx) +{ + switch (ep_idx) + { + case XUSB_EP_CTRL_IN: + case XUSB_EP_CTRL_OUT: + return _xusb_ep_init_context(XUSB_EP_CTRL_IN); + case USB_EP_BULK_OUT: + case USB_EP_BULK_IN: + _xusb_ep_init_context(ep_idx); + XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_RELOAD) = BIT(ep_idx); + int res = _xusb_xhci_mask_wait(XUSB_DEV_XHCI_EP_RELOAD, BIT(ep_idx), 0, 1000); + if (!res) + { + XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_PAUSE) &= ~BIT(ep_idx); + XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_HALT) &= ~BIT(ep_idx); + } + return res; + default: + return USB_ERROR_INIT; + } +} + +static void _xusb_init_phy() +{ + // Configure and enable PLLU. + clock_enable_pllu(); + + // Enable IDDQ control by software and disable UTMIPLL IDDQ. + CLOCK(CLK_RST_CONTROLLER_UTMIPLL_HW_PWRDN_CFG0) = (CLOCK(CLK_RST_CONTROLLER_UTMIPLL_HW_PWRDN_CFG0) & 0xFFFFFFFC) | 1; + + // Set UTMIPLL dividers and config based on OSC and enable it to 960 MHz. + clock_enable_utmipll(); + + // Set UTMIP misc config. + CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG2) = (CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG2) & 0xFEFFFFE8) | 0x2000008 | 0x20 | 2; + usleep(2); + + // Set OTG PAD0 calibration. + u32 fuse_usb_calib = FUSE(FUSE_USB_CALIB); + // Set HS_CURR_LEVEL. + XUSB_PADCTL(XUSB_PADCTL_USB2_OTG_PAD0_CTL_0) = (XUSB_PADCTL(XUSB_PADCTL_USB2_OTG_PAD0_CTL_0) & 0xFFFFFFC0) | (fuse_usb_calib & 0x3F); + // Set TERM_RANGE_ADJ and RPD_CTRL. + XUSB_PADCTL(XUSB_PADCTL_USB2_OTG_PAD0_CTL_1) = (XUSB_PADCTL(XUSB_PADCTL_USB2_OTG_PAD0_CTL_1) & 0x83FFFF87) | ((fuse_usb_calib & 0x780) >> 4) | ((u32)(FUSE(FUSE_USB_CALIB_EXT) << 27) >> 1); + + // Set VREG_LEV to 1. + XUSB_PADCTL(XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD0_CTL1) = (XUSB_PADCTL(XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD0_CTL1) & 0xFFFFFE3F) | 0x80; + + // Disable power down on usb2 ports pads. + XUSB_PADCTL(XUSB_PADCTL_USB2_OTG_PAD0_CTL_0) &= 0xDBFFFFFF; // Clear pad power down. + XUSB_PADCTL(XUSB_PADCTL_USB2_OTG_PAD0_CTL_1) &= 0xFFFFFFFB; // Clear pad dr power down. + XUSB_PADCTL(XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD0_CTL0) &= 0xFFFFFFFE; // Clear charging power down. + XUSB_PADCTL(XUSB_PADCTL_USB2_BIAS_PAD_CTL_0) &= 0xFFFFF7FF; // Clear bias power down. + (void)XUSB_PADCTL(XUSB_PADCTL_USB2_OTG_PAD0_CTL_1); // Commit write. + + // Enable USB2 tracking clock. + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_Y_SET) = BIT(CLK_Y_USB2_TRK); + CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_USB2_HSIC_TRK) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_USB2_HSIC_TRK) & 0xFFFFFF00) | 6; // Set trank divisor to 4. + + // Set tracking parameters and trigger it. + XUSB_PADCTL(XUSB_PADCTL_USB2_BIAS_PAD_CTL_1) = 0x451E000; + XUSB_PADCTL(XUSB_PADCTL_USB2_BIAS_PAD_CTL_1) = 0x51E000; + usleep(100); + + // TRK cycle done. Force PDTRK input into power down. + XUSB_PADCTL(XUSB_PADCTL_USB2_BIAS_PAD_CTL_1) = 0x451E000; + usleep(3); + + // Re-trigger it. + XUSB_PADCTL(XUSB_PADCTL_USB2_BIAS_PAD_CTL_1) = 0x51E000; + usleep(100); + + // TRK cycle done. Force PDTRK input into power down. + XUSB_PADCTL(XUSB_PADCTL_USB2_BIAS_PAD_CTL_1) |= 0x4000000; + + // Disable USB2 tracking clock. + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_Y_CLR) = BIT(CLK_Y_USB2_TRK); + + // Wait for XUSB PHY to stabilize. + usleep(30); +} + +static void _xusbd_init_device_clocks() +{ + // Disable reset to PLLU_OUT1 + CLOCK(CLK_RST_CONTROLLER_PLLU_OUTA) |= 1; + usleep(2); + + // Enable XUSB device clock. + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_U_SET) = BIT(CLK_U_XUSB_DEV); + + // Set XUSB device core clock source to PLLP for a 102MHz result. + CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_XUSB_CORE_DEV) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_XUSB_CORE_DEV) & 0x1FFFFF00) | (1 << 29) | 6; + usleep(2); + + // Set XUSB Full-Speed logic clock source to FO 48MHz. + CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_XUSB_FS) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_XUSB_FS) & 0x1FFFFFFF) | (2 << 29); + + // Enable XUSB Super-Speed logic clock. + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_SET) = BIT(CLK_W_XUSB_SS); + + // Set XUSB Super-Speed logic clock source to HSIC 480MHz for 120MHz result and source FS logic clock from Super-Speed. + CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_XUSB_SS) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_XUSB_SS) & 0x1FFFFF00) | (3 << 29) | 6; + + // Clear reset to XUSB device and Super-Speed logic. + CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_CLR) = BIT(CLK_W_XUSB_SS); + CLOCK(CLK_RST_CONTROLLER_RST_DEV_U_CLR) = BIT(CLK_U_XUSB_DEV); + usleep(2); +} + +int xusb_device_init() +{ + ///////////////////////////////////////////////// + CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_USBD); + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = BIT(CLK_L_USBD); + ///////////////////////////////////////////////// + + + // Enable XUSB clock and clear Reset to XUSB Pad Control. + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_SET) = BIT(CLK_W_XUSB); + CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB); + usleep(2); + CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_CLR) = BIT(CLK_W_XUSB); + CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_CLR) = BIT(CLK_W_XUSB_PADCTL); + usleep(2); + + // USB2 Pads to XUSB. + XUSB_PADCTL(XUSB_PADCTL_USB2_PAD_MUX) = + (XUSB_PADCTL(XUSB_PADCTL_USB2_PAD_MUX) & ~(PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_MASK | PADCTL_USB2_PAD_MUX_USB2_OTG_PAD_PORT0_MASK)) | + PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_XUSB | PADCTL_USB2_PAD_MUX_USB2_OTG_PAD_PORT0_XUSB; + + // Initialize XUSB controller PHY. + _xusb_init_phy(); + + // Set USB2.0 Port 0 to device mode. + XUSB_PADCTL(XUSB_PADCTL_USB2_PORT_CAP) = (XUSB_PADCTL(XUSB_PADCTL_USB2_PORT_CAP) & ~PADCTL_USB2_PORT_CAP_PORT_0_CAP_MASK) | PADCTL_USB2_PORT_CAP_PORT_0_CAP_DEV; + + //! TODO USB3 + // // Set USB3.0 Port 0 cap to device. + // XUSB_PADCTL(XUSB_PADCTL_SS_PORT_CAP) = (XUSB_PADCTL(XUSB_PADCTL_SS_PORT_CAP) & ~PADCTL_SS_PORT_CAP_0_PORT1_CAP_MASK) | PADCTL_SS_PORT_CAP_0_PORT1_CAP_DEVICE_ONLY; + + // Set Super Speed Port 0 to USB2 Port 0. + XUSB_PADCTL(XUSB_PADCTL_SS_PORT_MAP) &= ~PADCTL_SS_PORT_MAP_PORT0_MASK; // 0: USB2_PORT0 + + // Power Up ID Wake up and Vbus Wake Up for UTMIP + PMC(APBDEV_PMC_USB_AO) &= 0xFFFFFFF3; + usleep(1); + + // Initialize device clocks. + _xusbd_init_device_clocks(); + + // Enable AHB redirect for access to IRAM for Event/EP ring buffers. + mc_enable_ahb_redirect(); // can be skipped if IRAM is not used///////////////// + + // Enable XUSB device IPFS. + XUSB_DEV_DEV(XUSB_DEV_CONFIGURATION) |= DEV_CONFIGURATION_EN_FPCI; + + // Configure PCI and BAR0 address space. + XUSB_DEV_PCI(XUSB_CFG_1) |= CFG_1_BUS_MASTER | CFG_1_MEMORY_SPACE | CFG_1_IO_SPACE; + usleep(1); + XUSB_DEV_PCI(XUSB_CFG_4) = XUSB_DEV_BASE | CFG_4_ADDRESS_TYPE_32_BIT; + + // Mask SATA interrupt to MCORE. + XUSB_DEV_DEV(XUSB_DEV_INTR_MASK) |= DEV_INTR_MASK_IP_INT_MASK; + + // AHB USB performance cfg. + //TODO: Doesn't help.. +/* + AHB_GIZMO(AHB_GIZMO_AHB_MEM) |= AHB_MEM_DONT_SPLIT_AHB_WR | AHB_MEM_ENB_FAST_REARBITRATE; + AHB_GIZMO(AHB_GIZMO_USB3) |= AHB_GIZMO_IMMEDIATE; + AHB_GIZMO(AHB_ARBITRATION_PRIORITY_CTRL) = PRIORITY_CTRL_WEIGHT(7) | PRIORITY_SELECT_USB3; + AHB_GIZMO(AHB_AHB_MEM_PREFETCH_CFG1) = + MEM_PREFETCH_ENABLE | MEM_PREFETCH_USB3_MST_ID | MEM_PREFETCH_ADDR_BNDRY(12) | 0x1000; // Addr boundary 64KB, Inactivity 4096 cycles. +*/ + + // Initialize context. + usbd_xotg = &usbd_xotg_controller_ctxt; + memset(usbd_xotg, 0, sizeof(xusbd_controller_t)); + + // Initialize event and EP rings. + _xusbd_ep_init_event_ring(); + memset(xusb_evtq->xusb_cntrl_event_queue, 0, sizeof(xusb_evtq->xusb_cntrl_event_queue)); + memset(xusb_evtq->xusb_bulkin_event_queue, 0, sizeof(xusb_evtq->xusb_bulkin_event_queue)); + memset(xusb_evtq->xusb_bulkout_event_queue, 0, sizeof(xusb_evtq->xusb_bulkout_event_queue)); + + // Initialize Control EP. + int res = _xusbd_ep_initialize(XUSB_EP_CTRL_IN); + if (res) + return USB_ERROR_INIT; + + // Enable events and interrupts. + XUSB_DEV_XHCI(XUSB_DEV_XHCI_CTRL) |= XHCI_CTRL_IE | XHCI_CTRL_LSE; + XUSB_DEV_XHCI(XUSB_DEV_XHCI_ECPLO) = (u32)xusb_evtq->xusb_ep_ctxt & 0xFFFFFFF0; + XUSB_DEV_XHCI(XUSB_DEV_XHCI_ECPHI) = 0; + + //! TODO USB3: + // XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTHALT) |= DEV_XHCI_PORTHALT_STCHG_INTR_EN; + + return USB_RES_OK; +} + +static int _xusb_queue_trb(int ep_idx, void *trb, bool ring_doorbell) +{ + int res = USB_RES_OK; + data_trb_t *next_trb; + link_trb_t *link_trb; + + // Copy TRB and advance Enqueue list. + switch (ep_idx) + { + case XUSB_EP_CTRL_IN: + memcpy(usbd_xotg->cntrl_epenqueue_ptr, trb, sizeof(data_trb_t)); + + // Advance queue and if Link TRB set index to 0 and toggle cycle bit. + next_trb = &usbd_xotg->cntrl_epenqueue_ptr[1]; + if (next_trb->trb_type == XUSB_TRB_LINK) + { + link_trb = (link_trb_t *)next_trb; + link_trb->cycle = usbd_xotg->cntrl_producer_cycle & 1; + link_trb->toggle_cycle = 1; + next_trb = (data_trb_t *)(link_trb->ring_seg_ptrlo << 4); + usbd_xotg->cntrl_producer_cycle ^= 1; + } + usbd_xotg->cntrl_epenqueue_ptr = next_trb; + break; + + case USB_EP_BULK_OUT: + memcpy(usbd_xotg->bulkout_epenqueue_ptr, trb, sizeof(data_trb_t)); + + // Advance queue and if Link TRB set index to 0 and toggle cycle bit. + next_trb = &usbd_xotg->bulkout_epenqueue_ptr[1]; + if (next_trb->trb_type == XUSB_TRB_LINK) + { + link_trb = (link_trb_t *)next_trb; + link_trb->cycle = usbd_xotg->bulkout_producer_cycle & 1; + link_trb->toggle_cycle = 1; + next_trb = (data_trb_t *)(link_trb->ring_seg_ptrlo << 4); + usbd_xotg->bulkout_producer_cycle ^= 1; + } + usbd_xotg->bulkout_epenqueue_ptr = next_trb; + break; + + case USB_EP_BULK_IN: + memcpy(usbd_xotg->bulkin_epenqueue_ptr, trb, sizeof(data_trb_t)); + + // Advance queue and if Link TRB set index to 0 and toggle cycle bit. + next_trb = &usbd_xotg->bulkin_epenqueue_ptr[1]; + if (next_trb->trb_type == XUSB_TRB_LINK) + { + link_trb = (link_trb_t *)next_trb; + link_trb->cycle = usbd_xotg->bulkin_producer_cycle & 1; + link_trb->toggle_cycle = 1; + next_trb = (data_trb_t *)(link_trb->ring_seg_ptrlo << 4); + usbd_xotg->bulkin_producer_cycle ^= 1; + } + usbd_xotg->bulkin_epenqueue_ptr = next_trb; + break; + + case XUSB_EP_CTRL_OUT: + default: + res = XUSB_ERROR_INVALID_EP; + break; + } + + // Ring doorbell. + if (ring_doorbell) + { + bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); + u32 target_id = (ep_idx << 8) & 0xFFFF; + if (ep_idx == XUSB_EP_CTRL_IN) + target_id |= usbd_xotg->ctrl_seq_num << 16; + XUSB_DEV_XHCI(XUSB_DEV_XHCI_DB) = target_id; + } + + return res; +} + +static void _xusb_create_status_trb(status_trb_t *trb, usb_dir_t direction) +{ + trb->cycle = usbd_xotg->cntrl_producer_cycle & 1; + trb->ioc = 1; // Enable interrupt on completion. + trb->trb_type = XUSB_TRB_STATUS; + trb->dir = direction; +} + +static void _xusb_create_normal_trb(normal_trb_t *trb, u8 *buf, u32 len, usb_dir_t direction) +{ + u8 producer_cycle; + + trb->databufptr_lo = (u32)buf; + trb->databufptr_hi = 0; + + trb->trb_tx_len = len; + + // Single TRB transfer. + trb->td_size = 0; + trb->chain = 0; + + if (direction == USB_DIR_IN) + producer_cycle = usbd_xotg->bulkin_producer_cycle & 1; + else + producer_cycle = usbd_xotg->bulkout_producer_cycle & 1; + + trb->cycle = producer_cycle; + trb->isp = 1; // Enable interrupt on short packet. + trb->ioc = 1; // Enable interrupt on completion. + trb->trb_type = XUSB_TRB_NORMAL; +} + +static void _xusb_create_data_trb(data_trb_t *trb, u8 *buf, u32 len, usb_dir_t direction) +{ + trb->databufptr_lo = (u32)buf; + trb->databufptr_hi = 0; + + trb->trb_tx_len = len; + + // Single TRB transfer. + trb->td_size = 0; + trb->chain = 0; + + trb->cycle = usbd_xotg->cntrl_producer_cycle & 1; + trb->isp = 1; // Enable interrupt on short packet. + trb->ioc = 1; // Enable interrupt on completion. + trb->trb_type = XUSB_TRB_DATA; + trb->dir = direction; +} + +static int _xusb_issue_status_trb(usb_dir_t direction) +{ + int res = USB_RES_OK; + status_trb_t trb = {0}; + + if (usbd_xotg->cntrl_epenqueue_ptr == usbd_xotg->cntrl_epdequeue_ptr || direction == USB_DIR_OUT) + { + _xusb_create_status_trb(&trb, direction); + res = _xusb_queue_trb(XUSB_EP_CTRL_IN, &trb, EP_RING_DOORBELL); + usbd_xotg->wait_for_event_trb = XUSB_TRB_STATUS; + } + + return res; +} + +static int _xusb_issue_normal_trb(u8 *buf, u32 len, usb_dir_t direction) +{ + normal_trb_t trb = {0}; + + _xusb_create_normal_trb(&trb, buf, len, direction); + int ep_idx = USB_EP_BULK_IN; + if (direction == USB_DIR_OUT) + ep_idx = USB_EP_BULK_OUT; + int res = _xusb_queue_trb(ep_idx, &trb, EP_RING_DOORBELL); + if (!res) + usbd_xotg->wait_for_event_trb = XUSB_TRB_NORMAL; + + return res; +} + +static int _xusb_issue_data_trb(u8 *buf, u32 len, usb_dir_t direction) +{ + data_trb_t trb = {0}; + + int res = USB_RES_OK; + if (usbd_xotg->cntrl_epenqueue_ptr == usbd_xotg->cntrl_epdequeue_ptr) + { + _xusb_create_data_trb(&trb, buf, len, direction); + res = _xusb_queue_trb(XUSB_EP_CTRL_IN, &trb, EP_RING_DOORBELL); + if (!res) + usbd_xotg->wait_for_event_trb = XUSB_TRB_DATA; + } + return res; +} + +int xusb_set_ep_stall(u32 endpoint, int ep_stall) +{ + int ep_idx = BIT(endpoint); + if (ep_stall) + XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_HALT) |= ep_idx; + else + XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_HALT) &= ~ep_idx; + + // Wait for EP status to change. + int res = _xusb_xhci_mask_wait(XUSB_DEV_XHCI_EP_STCHG, ep_idx, ep_idx, 1000); + if (res) + return res; + + // Clear status change. + XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_STCHG) = ep_idx; + + return USB_RES_OK; +} + +static int _xusb_handle_transfer_event(transfer_event_trb_t *trb) +{ + // Advance dequeue list. + data_trb_t *next_trb; + switch (trb->ep_id) + { + case XUSB_EP_CTRL_IN: + next_trb = &usbd_xotg->cntrl_epdequeue_ptr[1]; + if (next_trb->trb_type == XUSB_TRB_LINK) + next_trb = (data_trb_t *)(next_trb->databufptr_lo & 0xFFFFFFF0); + usbd_xotg->cntrl_epdequeue_ptr = next_trb; + break; + case USB_EP_BULK_OUT: + next_trb = &usbd_xotg->bulkout_epdequeue_ptr[1]; + if (next_trb->trb_type == XUSB_TRB_LINK) + next_trb = (data_trb_t *)(next_trb->databufptr_lo & 0xFFFFFFF0); + usbd_xotg->bulkout_epdequeue_ptr = next_trb; + break; + case USB_EP_BULK_IN: + next_trb = &usbd_xotg->bulkin_epdequeue_ptr[1]; + if (next_trb->trb_type == XUSB_TRB_LINK) + next_trb = (data_trb_t *)(next_trb->databufptr_lo & 0xFFFFFFF0); + usbd_xotg->bulkin_epdequeue_ptr = next_trb; + break; + default: + // Should never happen. + break; + } + + // Handle completion code. + switch (trb->comp_code) + { + case XUSB_COMP_SUCCESS: + case XUSB_COMP_SHORT_PKT: + switch (trb->ep_id) + { + case XUSB_EP_CTRL_IN: + if (usbd_xotg->wait_for_event_trb == XUSB_TRB_DATA) + return _xusb_issue_status_trb(USB_DIR_OUT); + else if (usbd_xotg->wait_for_event_trb == XUSB_TRB_STATUS) + { + if (usbd_xotg->device_state == XUSB_ADDRESSED_STS_WAIT) + usbd_xotg->device_state = XUSB_ADDRESSED; + else if (usbd_xotg->device_state == XUSB_CONFIGURED_STS_WAIT) + usbd_xotg->device_state = XUSB_CONFIGURED; + else if (usbd_xotg->device_state == XUSB_LUN_CONFIGURED_STS_WAIT) + usbd_xotg->device_state = XUSB_LUN_CONFIGURED; + else if (usbd_xotg->device_state == XUSB_HID_CONFIGURED_STS_WAIT) + usbd_xotg->device_state = XUSB_HID_CONFIGURED; + } + break; + + case USB_EP_BULK_IN: + usbd_xotg->bytes_remaining[USB_DIR_IN] -= trb->trb_tx_len; + if (usbd_xotg->tx_count[USB_DIR_IN])/////////// + usbd_xotg->tx_count[USB_DIR_IN]--; + + // If bytes remaining for a Bulk IN transfer, return error. + if (trb->trb_tx_len) + return XUSB_ERROR_XFER_BULK_IN_RESIDUE; + break; + + case USB_EP_BULK_OUT: + // If short packet and Bulk OUT, it's not an error because we prime EP for 4KB. + usbd_xotg->bytes_remaining[USB_DIR_OUT] -= trb->trb_tx_len; + if (usbd_xotg->tx_count[USB_DIR_OUT])/////////// + usbd_xotg->tx_count[USB_DIR_OUT]--; + break; + } + return USB_RES_OK; +/* + case XUSB_COMP_USB_TRANSACTION_ERROR: + case XUSB_COMP_TRB_ERROR: + case XUSB_COMP_RING_UNDERRUN: + case XUSB_COMP_RING_OVERRUN: + case XUSB_COMP_CTRL_DIR_ERROR: // Redefined. + xusb_set_ep_stall(trb->ep_id, USB_EP_CFG_STALL); + return USB_RES_OK; +*/ + case XUSB_COMP_CTRL_DIR_ERROR: + return XUSB_ERROR_XFER_DIR; + + case XUSB_COMP_CTRL_SEQ_NUM_ERROR: + return XUSB_ERROR_SEQ_NUM; //! TODO: Can mean a new setup packet was received. + + default: // Every other completion code. + return USB_ERROR_XFER_ERROR; + } +} + +/* + * Other XUSB impl: + * CBT: PR, PRC, WPR, WRC, CSC, REQ, PLC, CEC. + * LNX: REQ, PRC PR, PRC & !PR, WRC, CSC, PLC, CEC. + * BRO: CSC, PR | PRC, WPR | WRC, REQ, PLC, CEC. + */ + +static int _xusb_handle_port_change() +{ + u32 res = USB_RES_OK; + u32 status = XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC); + u32 halt = XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTHALT); + + // Connect status change (CSC). + if (status & XHCI_PORTSC_CSC) + { + //! TODO: Check CCS. + // CCS check seems to be + // XHCI_PORTSC_CCS 1: device_state = XUSB_CONNECTED + // XHCI_PORTSC_CCS 0: device_state = XUSB_DISCONNECTED + // Always do XHCI_PORTSC_CSC bit clear. + + // Set port speed. + usbd_xotg->port_speed = (status & XHCI_PORTSC_PS) >> 10; + + // In case host does not support Super Speed, revert the control EP packet size. + if (usbd_xotg->port_speed != XUSB_SUPER_SPEED) + { + volatile xusb_ep_ctx_t *ep_ctxt = &xusb_evtq->xusb_ep_ctxt[XUSB_EP_CTRL_IN]; + ep_ctxt->avg_trb_len = 8; + ep_ctxt->max_packet_size = 64; + } + + // Clear CSC bit. + status |= XHCI_PORTSC_CSC; + XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) = status; + } + + // Port reset (PR), Port reset change (PRC). + if (status & XHCI_PORTSC_PR || status & XHCI_PORTSC_PRC) + { + //! TODO: + // XHCI_PORTSC_PR: device_state = XUSB_RESET + + //_disable_usb_wdt4(); + + //res = _xusb_xhci_mask_wait(XUSB_DEV_XHCI_PORTSC, XHCI_PORTSC_PRC, XHCI_PORTSC_PRC, 50000); // unpatched0 + // if (res) return res; + _xusb_xhci_mask_wait(XUSB_DEV_XHCI_PORTSC, XHCI_PORTSC_PRC, XHCI_PORTSC_PRC, 50000); // patched0 + + // Clear PRC bit. + status = XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) | XHCI_PORTSC_PRC; + XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) |= XHCI_PORTSC_PRC; + } + + // Warm Port Reset (WPR), Warm Port Reset Change (WRC). + if (status & XHCI_PORTSC_WPR || status & XHCI_PORTSC_WRC) + { + XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTHALT) &= ~XHCI_PORTHALT_HALT_LTSSM; + (void)XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC); + res = _xusb_xhci_mask_wait(XUSB_DEV_XHCI_PORTSC, XHCI_PORTSC_WRC, XHCI_PORTSC_WRC, 1000); + + // Clear WRC bit. + status = XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) | XHCI_PORTSC_WRC; + XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) |= XHCI_PORTSC_WRC; + + //! TODO: WPR: device_state = XUSB_RESET + } + + // Handle Config Request (STCHG_REQ). + if (halt & XHCI_PORTHALT_STCHG_REQ) + { + // Clear Link Training Status. + status = XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTHALT) & ~XHCI_PORTHALT_HALT_LTSSM; + XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTHALT) &= ~XHCI_PORTHALT_HALT_LTSSM; + } + + // Port link state change (PLC). + if (status & XHCI_PORTSC_PLC) + { + //! WAR: Sometimes port speed changes without a CSC event. Set again. + usbd_xotg->port_speed = (status & XHCI_PORTSC_PS) >> 10; + + // check PLS + // if U3 + // device_state = XUSB_SUSPENDED + // else if U0 and XUSB_SUSPENDED + // val = XUSB_DEV_XHCI_EP_PAUSE + // XUSB_DEV_XHCI_EP_PAUSE = 0 + // XUSB_DEV_XHCI_EP_STCHG = val; + + // Clear PLC bit. + status = XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) | XHCI_PORTSC_PLC; + XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) |= XHCI_PORTSC_PLC; + } + + // Port configuration link error (CEC). + if (status & XHCI_PORTSC_CEC) + { + XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) |= XHCI_PORTSC_CEC; + res = XUSB_ERROR_PORT_CFG; + } + + return res; +} + +static int _xusb_handle_get_ep_status(usb_ctrl_setup_t *ctrl_setup) +{ + static u8 xusb_ep_status_descriptor[2] = {0}; + + // Get EP context pointer. + volatile xusb_ep_ctx_t *ep_ctxt = (volatile xusb_ep_ctx_t *)(XUSB_DEV_XHCI(XUSB_DEV_XHCI_ECPLO) & 0xFFFFFFF0); + ep_ctxt = &ep_ctxt[ctrl_setup->wIndex]; + + xusb_ep_status_descriptor[0] = (ep_ctxt->ep_state == EP_HALTED) ? USB_STATUS_EP_HALTED : USB_STATUS_EP_OK; + return _xusb_issue_data_trb(xusb_ep_status_descriptor, 2, USB_DIR_IN); +} + +static int _xusb_handle_get_class_request(usb_ctrl_setup_t *ctrl_setup) +{ + u8 _bRequest = ctrl_setup->bRequest; + u16 _wIndex = ctrl_setup->wIndex; + u16 _wValue = ctrl_setup->wValue; + u16 _wLength = ctrl_setup->wLength; + + bool valid_interface = _wIndex == usbd_xotg->interface_num; + bool valid_len = (_bRequest == USB_REQUEST_BULK_GET_MAX_LUN) ? 1 : 0; + + if (!valid_interface || _wValue != 0 || _wLength != valid_len) + goto stall; + + switch (_bRequest) + { + case USB_REQUEST_BULK_RESET: + usbd_xotg->bulk_reset_req = true; + return _xusb_issue_status_trb(USB_DIR_IN); // DELAYED_STATUS; + case USB_REQUEST_BULK_GET_MAX_LUN: + if (!usbd_xotg->max_lun_set) + goto stall; + usbd_xotg->device_state = XUSB_LUN_CONFIGURED_STS_WAIT; + return _xusb_issue_data_trb(&usbd_xotg->max_lun, 1, USB_DIR_IN); + } + +stall: + xusb_set_ep_stall(XUSB_EP_CTRL_IN, USB_EP_CFG_STALL); + return USB_RES_OK; +} + +static int _xusb_handle_get_descriptor(usb_ctrl_setup_t *ctrl_setup) +{ + u32 size; + void *descriptor; + + u32 wLength = ctrl_setup->wLength; + + u8 descriptor_type = ctrl_setup->wValue >> 8; + u8 descriptor_subtype = ctrl_setup->wValue & 0xFF; + + switch (descriptor_type) + { + case USB_DESCRIPTOR_DEVICE: + //! TODO USB3: Provide a super speed descriptor. +/* + u32 soc_rev = APB_MISC(APB_MISC_GP_HIDREV); + usb_device_descriptor.idProduct = (soc_rev >> 8) & 0xFF; // chip_id. + usb_device_descriptor.idProduct |= ((soc_rev << 4) | (FUSE(FUSE_SKU_INFO) & 0xF)) << 8; // HIDFAM. + usb_device_descriptor.bcdDevice = (soc_rev >> 16) & 0xF; // MINORREV. + usb_device_descriptor.bcdDevice |= ((soc_rev >> 4) & 0xF) << 8; // MAJORREV. +*/ + descriptor = usbd_xotg->desc->dev; + size = usbd_xotg->desc->dev->bLength; + break; + case USB_DESCRIPTOR_CONFIGURATION: + //! TODO USB3: Provide a super speed descriptor. + if (usbd_xotg->gadget == USB_GADGET_UMS) + { + if (usbd_xotg->port_speed == XUSB_HIGH_SPEED) // High speed. 512 bytes. + { + usbd_xotg->desc->cfg->endpoint[0].wMaxPacketSize = 0x200; // No burst. + usbd_xotg->desc->cfg->endpoint[1].wMaxPacketSize = 0x200; // No burst. + } + else // Full speed. 64 bytes. + { + usbd_xotg->desc->cfg->endpoint[0].wMaxPacketSize = 0x40; + usbd_xotg->desc->cfg->endpoint[1].wMaxPacketSize = 0x40; + } + } + else + { + usb_cfg_hid_descr_t *tmp = (usb_cfg_hid_descr_t *)usbd_xotg->desc->cfg; + if (usbd_xotg->port_speed == XUSB_HIGH_SPEED) // High speed. 512 bytes. + { + tmp->endpoint[0].wMaxPacketSize = 0x200; + tmp->endpoint[1].wMaxPacketSize = 0x200; + tmp->endpoint[0].bInterval = usbd_xotg->gadget == USB_GADGET_HID_GAMEPAD ? 4 : 3; // 8ms : 4ms. + tmp->endpoint[1].bInterval = usbd_xotg->gadget == USB_GADGET_HID_GAMEPAD ? 4 : 3; // 8ms : 4ms. + } + else // Full speed. 64 bytes. + { + tmp->endpoint[0].wMaxPacketSize = 0x40; + tmp->endpoint[1].wMaxPacketSize = 0x40; + tmp->endpoint[0].bInterval = usbd_xotg->gadget == USB_GADGET_HID_GAMEPAD ? 8 : 4; // 8ms : 4ms. + tmp->endpoint[1].bInterval = usbd_xotg->gadget == USB_GADGET_HID_GAMEPAD ? 8 : 4; // 8ms : 4ms. + } + } + descriptor = usbd_xotg->desc->cfg; + size = usbd_xotg->desc->cfg->config.wTotalLength; + break; + case USB_DESCRIPTOR_STRING: + switch (descriptor_subtype) + { + case 1: + descriptor = usbd_xotg->desc->vendor; + size = usbd_xotg->desc->vendor[0]; + break; + case 2: + descriptor = usbd_xotg->desc->product; + size = usbd_xotg->desc->product[0]; + break; + case 3: + descriptor = usbd_xotg->desc->serial; + size = usbd_xotg->desc->serial[0]; + break; + case 0xEE: + descriptor = usbd_xotg->desc->ms_os; + size = usbd_xotg->desc->ms_os->bLength; + break; + default: + descriptor = usbd_xotg->desc->lang_id; + size = 4; + break; + } + break; + case USB_DESCRIPTOR_DEVICE_QUALIFIER: + if (!usbd_xotg->desc->dev_qual) + { + xusb_set_ep_stall(XUSB_EP_CTRL_IN, USB_EP_CFG_STALL); + return USB_RES_OK; + } + usbd_xotg->desc->dev_qual->bNumOtherConfigs = 0; + descriptor = usbd_xotg->desc->dev_qual; + size = usbd_xotg->desc->dev_qual->bLength; + break; + case USB_DESCRIPTOR_OTHER_SPEED_CONFIGURATION: + if (!usbd_xotg->desc->cfg_other) + { + xusb_set_ep_stall(XUSB_EP_CTRL_IN, USB_EP_CFG_STALL); + return USB_RES_OK; + } + if (usbd_xotg->port_speed == XUSB_HIGH_SPEED) + { + usbd_xotg->desc->cfg_other->endpoint[0].wMaxPacketSize = 0x40; + usbd_xotg->desc->cfg_other->endpoint[1].wMaxPacketSize = 0x40; + } + else + { + usbd_xotg->desc->cfg_other->endpoint[0].wMaxPacketSize = 0x200; + usbd_xotg->desc->cfg_other->endpoint[1].wMaxPacketSize = 0x200; + } + descriptor = usbd_xotg->desc->cfg_other; + size = usbd_xotg->desc->cfg_other->config.wTotalLength; + break; + case USB_DESCRIPTOR_DEVICE_BINARY_OBJECT: + descriptor = usbd_xotg->desc->dev_bot; + size = usbd_xotg->desc->dev_bot->wTotalLength; + break; + default: + xusb_set_ep_stall(XUSB_EP_CTRL_IN, USB_EP_CFG_STALL); + return USB_RES_OK; + } + + if (wLength < size) + size = wLength; + + return _xusb_issue_data_trb(descriptor, size, USB_DIR_IN); +} + +static void _xusb_handle_set_request_dev_address(usb_ctrl_setup_t *ctrl_setup) +{ + u32 addr = ctrl_setup->wValue & 0xFF; + + XUSB_DEV_XHCI(XUSB_DEV_XHCI_CTRL) = (XUSB_DEV_XHCI(XUSB_DEV_XHCI_CTRL) & 0x80FFFFFF) | (addr << 24); + xusb_evtq->xusb_ep_ctxt[XUSB_EP_CTRL_IN].device_addr = addr; + + _xusb_issue_status_trb(USB_DIR_IN); + + usbd_xotg->device_state = XUSB_ADDRESSED_STS_WAIT; +} + +static void _xusb_handle_set_request_configuration(usb_ctrl_setup_t *ctrl_setup) +{ + u32 config_num = ctrl_setup->wValue; + if (!config_num) //TODO! we can change device_state here. + return; + + // Initialize BULK EPs. + _xusbd_ep_initialize(USB_EP_BULK_OUT); + _xusbd_ep_initialize(USB_EP_BULK_IN); + + // Device mode start. + XUSB_DEV_XHCI(XUSB_DEV_XHCI_CTRL) |= XHCI_CTRL_RUN; + XUSB_DEV_XHCI(XUSB_DEV_XHCI_ST) |= XHCI_ST_RC; + + _xusb_issue_status_trb(USB_DIR_IN); + + usbd_xotg->config_num = config_num; + usbd_xotg->device_state = XUSB_CONFIGURED_STS_WAIT; +} + +static int _xusbd_handle_ep0_control_transfer(usb_ctrl_setup_t *ctrl_setup) +{ + u32 size; + u8 *desc; + bool ep_stall = false; + bool transmit_data = false; + + u8 _bmRequestType = ctrl_setup->bmRequestType; + u8 _bRequest = ctrl_setup->bRequest; + u16 _wValue = ctrl_setup->wValue; + u16 _wIndex = ctrl_setup->wIndex; + u16 _wLength = ctrl_setup->wLength; + + static u8 xusb_dev_status_descriptor[2] = {USB_STATUS_DEV_SELF_POWERED, 0}; + static u8 xusb_interface_descriptor[4] = {0}; + static u8 xusb_configuration_descriptor[2] = {0}; + static u8 xusb_status_descriptor[2] = {0}; + + //gfx_printf("ctrl: %02X %02X %04X %04X %04X\n", _bmRequestType, _bRequest, _wValue, _wIndex, _wLength); + + XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_HALT) &= ~XHCI_EP_HALT_DCI; + u32 res = _xusb_xhci_mask_wait(XUSB_DEV_XHCI_EP_HALT, XHCI_EP_HALT_DCI, 0, 1000); + if (res) + return res; + + switch (_bmRequestType) + { + case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_DEVICE): + if (_bRequest == USB_REQUEST_SET_ADDRESS) + _xusb_handle_set_request_dev_address(ctrl_setup); + else if (_bRequest == USB_REQUEST_SET_CONFIGURATION) + _xusb_handle_set_request_configuration(ctrl_setup); + return USB_RES_OK; // What about others. + + case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_INTERFACE): + usbd_xotg->interface_num = _wValue; + return _xusb_issue_status_trb(USB_DIR_IN); + + case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT): + if ((_wValue & 0xFF) == USB_FEATURE_ENDPOINT_HALT) + { + if (_bRequest == USB_REQUEST_CLEAR_FEATURE) + { + xusb_set_ep_stall(_wIndex, USB_EP_CFG_CLEAR); + return _xusb_issue_status_trb(USB_DIR_IN); + } + else if (_bRequest == USB_REQUEST_SET_FEATURE) + { + xusb_set_ep_stall(_wIndex, USB_EP_CFG_STALL); + return _xusb_issue_status_trb(USB_DIR_IN); + } + } + ep_stall = true; + break; + + case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE): + return _xusb_handle_get_class_request(ctrl_setup); + + case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_DEVICE): + switch (_bRequest) + { + case USB_REQUEST_GET_STATUS: + desc = xusb_dev_status_descriptor; + size = sizeof(xusb_dev_status_descriptor); + transmit_data = true; + break; + case USB_REQUEST_GET_DESCRIPTOR: + return _xusb_handle_get_descriptor(ctrl_setup); + case USB_REQUEST_GET_CONFIGURATION: + xusb_configuration_descriptor[0] = usbd_xotg->config_num; + desc = xusb_configuration_descriptor; + size = sizeof(xusb_configuration_descriptor); + transmit_data = true; + break; + default: + ep_stall = true; + break; + } + break; + + case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_INTERFACE): + if (_bRequest == USB_REQUEST_GET_INTERFACE) + { + desc = xusb_interface_descriptor; + size = sizeof(xusb_interface_descriptor); + xusb_interface_descriptor[0] = usbd_xotg->interface_num; + transmit_data = true; + } + else if (_bRequest == USB_REQUEST_GET_STATUS) + { + desc = xusb_status_descriptor; + size = sizeof(xusb_status_descriptor); + transmit_data = true; + } + else if (_bRequest == USB_REQUEST_GET_DESCRIPTOR && (_wValue >> 8) == USB_DESCRIPTOR_HID_REPORT && usbd_xotg->gadget > USB_GADGET_UMS) + { + if (usbd_xotg->gadget == USB_GADGET_HID_GAMEPAD) + { + desc = (u8 *)&hid_report_descriptor_jc; + size = hid_report_descriptor_jc_size; + } + else // USB_GADGET_HID_TOUCHPAD + { + desc = (u8 *)&hid_report_descriptor_touch; + size = hid_report_descriptor_touch_size; + } + transmit_data = true; + usbd_xotg->device_state = XUSB_HID_CONFIGURED_STS_WAIT; + } + else + ep_stall = true; + break; + + case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT): + if (_bRequest == USB_REQUEST_GET_STATUS) + return _xusb_handle_get_ep_status(ctrl_setup); + + ep_stall = true; + break; + + case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE): + return _xusb_handle_get_class_request(ctrl_setup); + + case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_VENDOR | USB_SETUP_RECIPIENT_INTERFACE): + case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_VENDOR | USB_SETUP_RECIPIENT_DEVICE): + if (_bRequest == USB_REQUEST_GET_MS_DESCRIPTOR) + { + switch (_wIndex) + { + case USB_DESCRIPTOR_MS_COMPAT_ID: + desc = (u8 *)usbd_xotg->desc->ms_cid; + size = usbd_xotg->desc->ms_cid->dLength; + transmit_data = true; + break; + case USB_DESCRIPTOR_MS_EXTENDED_PROPERTIES: + desc = (u8 *)usbd_xotg->desc->mx_ext; + size = usbd_xotg->desc->mx_ext->dLength; + transmit_data = true; + break; + default: + ep_stall = true; + break; + } + } + else + ep_stall = true; + break; + + default: + ep_stall = true; + break; + } + + if (transmit_data) + { + memcpy((u8 *)USB_EP_CONTROL_BUF_ADDR, desc, size); + if (_wLength < size) + size = _wLength; + return _xusb_issue_data_trb((u8 *)USB_EP_CONTROL_BUF_ADDR, size, USB_DIR_IN); + } + + if (ep_stall) + xusb_set_ep_stall(XUSB_EP_CTRL_IN, USB_EP_CFG_STALL); + + return USB_RES_OK; +} + +static int _xusb_ep_operation(u32 tries) +{ + usb_ctrl_setup_t setup_event; + volatile event_trb_t *event_trb; + setup_event_trb_t *setup_event_trb; + + // Wait for an interrupt event. + int res = _xusb_xhci_mask_wait(XUSB_DEV_XHCI_ST, XHCI_ST_IP, XHCI_ST_IP, tries); + if (res) + return res; + + // Clear interrupt status. + XUSB_DEV_XHCI(XUSB_DEV_XHCI_ST) |= XHCI_ST_IP; + + usbd_xotg->event_enqueue_ptr = (event_trb_t *)(XUSB_DEV_XHCI(XUSB_DEV_XHCI_EREPLO) & 0xFFFFFFF0); + event_trb = usbd_xotg->event_dequeue_ptr; + + // Check if cycle matches. + if ((event_trb->cycle & 1) != usbd_xotg->event_ccs) + return XUSB_ERROR_INVALID_CYCLE; + + while ((event_trb->cycle & 1) == usbd_xotg->event_ccs) + { + switch (event_trb->trb_type) + { + case XUSB_TRB_TRANSFER: + res = _xusb_handle_transfer_event((transfer_event_trb_t *)event_trb); + break; + case XUSB_TRB_PORT_CHANGE: + res = _xusb_handle_port_change(); + break; + case XUSB_TRB_SETUP: + setup_event_trb = (setup_event_trb_t *)event_trb; + memcpy(&setup_event, &setup_event_trb->ctrl_setup_data, sizeof(usb_ctrl_setup_t)); + usbd_xotg->ctrl_seq_num = setup_event_trb->ctrl_seq_num; + res = _xusbd_handle_ep0_control_transfer(&setup_event); + break; + default: + // TRB not supported. + break; + } + + // Check if last event TRB and reset to first one. + if (usbd_xotg->event_dequeue_ptr == &xusb_evtq->xusb_event_ring_seg1[XUSB_LAST_TRB_IDX]) + { + usbd_xotg->event_dequeue_ptr = xusb_evtq->xusb_event_ring_seg0; + usbd_xotg->event_ccs ^= 1; + } + else // Advance dequeue to next event. + usbd_xotg->event_dequeue_ptr = &usbd_xotg->event_dequeue_ptr[1]; + + // Set next event. + event_trb = usbd_xotg->event_dequeue_ptr; + + // If events exceed the interrupt time, handle them next interrupt. + if (usbd_xotg->event_dequeue_ptr == usbd_xotg->event_enqueue_ptr) + break; + } + + // Clear Event Handler bit if enabled and set Dequeue pointer. + u32 erdp = XUSB_DEV_XHCI(XUSB_DEV_XHCI_ERDPLO) & 0xF; + if (erdp & XHCI_ERDPLO_EHB) + erdp |= XHCI_ERDPLO_EHB; + XUSB_DEV_XHCI(XUSB_DEV_XHCI_ERDPLO) = ((u32)usbd_xotg->event_dequeue_ptr & 0xFFFFFFF0) | erdp; + + return res; +} + +int xusb_device_enumerate(usb_gadget_type gadget) +{ + switch (gadget) + { + case USB_GADGET_UMS: + usbd_xotg->desc = &usb_gadget_ums_descriptors; + break; + case USB_GADGET_HID_GAMEPAD: + usbd_xotg->desc = &usb_gadget_hid_jc_descriptors; + break; + case USB_GADGET_HID_TOUCHPAD: + usbd_xotg->desc = &usb_gadget_hid_touch_descriptors; + break; + } + + usbd_xotg->gadget = gadget; + + // Disable Wake events. + XUSB_PADCTL(XUSB_PADCTL_ELPG_PROGRAM_0) = 0; + XUSB_PADCTL(XUSB_PADCTL_ELPG_PROGRAM_1) = 0; + + // Enable overrides for VBUS and ID. + XUSB_PADCTL(XUSB_PADCTL_USB2_VBUS_ID) = (XUSB_PADCTL(XUSB_PADCTL_USB2_VBUS_ID) & ~(PADCTL_USB2_VBUS_ID_VBUS_OVR_MASK | PADCTL_USB2_VBUS_ID_SRC_MASK)) | + PADCTL_USB2_VBUS_ID_VBUS_OVR_EN | PADCTL_USB2_VBUS_ID_SRC_ID_OVR_EN; + + // Clear halt for LTSSM. + XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTHALT) &= ~XHCI_PORTHALT_HALT_LTSSM; + + // Enable device mode. + XUSB_DEV_XHCI(XUSB_DEV_XHCI_CTRL) |= XHCI_CTRL_ENABLE; + + // Override access to High/Full Speed. + XUSB_DEV_XHCI(XUSB_DEV_XHCI_CFG_DEV_FE) = (XUSB_DEV_XHCI(XUSB_DEV_XHCI_CFG_DEV_FE) & ~XHCI_CFG_DEV_FE_PORTREGSEL_MASK) | XHCI_CFG_DEV_FE_PORTREGSEL_HSFS; + + XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) = + (XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) & ~XHCI_PORTSC_PLS_MASK) | XHCI_PORTSC_LWS | XHCI_PORTSC_PLS_RXDETECT; + XUSB_DEV_XHCI(XUSB_DEV_XHCI_CFG_DEV_FE) &= ~XHCI_CFG_DEV_FE_PORTREGSEL_MASK; + + // Enable VBUS and set ID to Float. + XUSB_PADCTL(XUSB_PADCTL_USB2_VBUS_ID) = (XUSB_PADCTL(XUSB_PADCTL_USB2_VBUS_ID) & ~PADCTL_USB2_VBUS_ID_OVR_MASK) | + PADCTL_USB2_VBUS_ID_OVR_FLOAT | PADCTL_USB2_VBUS_ID_VBUS_ON; + + usbd_xotg->wait_for_event_trb = XUSB_TRB_SETUP; + usbd_xotg->device_state = XUSB_DEFAULT; + + // Timeout if cable or communication isn't started in 1.5 minutes. + u32 timer = get_tmr_ms() + 90000; + while (true) + { + int res = _xusb_ep_operation(1000000); // 2s timeout. + if (res && res != USB_ERROR_TIMEOUT) + return res; + + if (usbd_xotg->device_state == XUSB_CONFIGURED) + break; + + if (timer < get_tmr_ms() || btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN)) + return USB_ERROR_USER_ABORT; + } + + return USB_RES_OK; +} + +void xusb_end(bool reset_ep, bool only_controller) +{ + CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB_SS); + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_CLR) = BIT(CLK_W_XUSB_SS); + CLOCK(CLK_RST_CONTROLLER_RST_DEV_U_SET) = BIT(CLK_U_XUSB_DEV); + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_U_CLR) = BIT(CLK_U_XUSB_DEV); + CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB_PADCTL); + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_CLR) = BIT(CLK_W_XUSB); + CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB); + mc_disable_ahb_redirect();/////////////////// +} + +int xusb_handle_ep0_ctrl_setup() +{ + /* + * EP0 Control handling is done by normal ep operation in XUSB. + * Here we handle the bulk reset only. + */ + if (usbd_xotg->bulk_reset_req) + { + usbd_xotg->bulk_reset_req = false; + return USB_RES_BULK_RESET; + } + + return USB_RES_OK; +} + +int xusb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, bool sync) +{ + if (len > USB_EP_BUFFER_MAX_SIZE) + len = USB_EP_BUFFER_MAX_SIZE; + + int res = USB_RES_OK; + usbd_xotg->tx_count[USB_DIR_OUT] = 0; + usbd_xotg->bytes_remaining[USB_DIR_OUT] = len; + _xusb_issue_normal_trb(buf, len, USB_DIR_OUT); + usbd_xotg->tx_count[USB_DIR_OUT]++; + + if (sync) + { + while (!res && usbd_xotg->tx_count[USB_DIR_OUT]) + res = _xusb_ep_operation(1000000); // 2s timeout. + + if (bytes_read) + *bytes_read = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_OUT]; + + bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); + } + + return res; +} + +int xusb_device_ep1_out_read_big(u8 *buf, u32 len, u32 *bytes_read) +{ + if (len > USB_EP_BULK_OUT_MAX_XFER) + len = USB_EP_BULK_OUT_MAX_XFER; + + u32 bytes = 0; + *bytes_read = 0; + u8 *buf_curr = buf; + + while (len) + { + u32 len_ep = MIN(len, USB_EP_BUFFER_MAX_SIZE); + + int res = xusb_device_ep1_out_read(buf_curr, len_ep, &bytes, USB_XFER_SYNCED); + if (res) + return res; + + len -= len_ep; + buf_curr += len_ep; + *bytes_read = *bytes_read + bytes; + } + + return USB_RES_OK; +} + +int xusb_device_ep1_out_reading_finish(u32 *pending_bytes, int tries) +{ + int res = USB_RES_OK; + while (!res && usbd_xotg->tx_count[USB_DIR_OUT]) + res = _xusb_ep_operation(tries); + + if (pending_bytes) + *pending_bytes = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_OUT]; + + bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); + + return res; +} + +int xusb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, bool sync) +{ + if (len > USB_EP_BUFFER_MAX_SIZE) + len = USB_EP_BUFFER_MAX_SIZE; + + bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); + + int res = USB_RES_OK; + usbd_xotg->tx_count[USB_DIR_IN] = 0; + usbd_xotg->bytes_remaining[USB_DIR_IN] = len; + _xusb_issue_normal_trb(buf, len, USB_DIR_IN); + usbd_xotg->tx_count[USB_DIR_IN]++; + + if (sync) + { + while (!res && usbd_xotg->tx_count[USB_DIR_IN]) + res = _xusb_ep_operation(1000000); // 2s timeout. + + if (bytes_written) + *bytes_written = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_IN]; + } + else + { + if ((usbd_xotg->port_speed == XUSB_FULL_SPEED && len == 64) || + (usbd_xotg->port_speed == XUSB_HIGH_SPEED && len == 512) || + (usbd_xotg->port_speed == XUSB_SUPER_SPEED && len == 1024)) + { + _xusb_issue_normal_trb(buf, 0, USB_DIR_IN); + usbd_xotg->tx_count[USB_DIR_IN]++; + } + } + + return res; +} + +int xusb_device_ep1_in_writing_finish(u32 *pending_bytes) +{ + int res = USB_RES_OK; + while (!res && usbd_xotg->tx_count[USB_DIR_IN]) + res = _xusb_ep_operation(1000000); // 2s timeout. + + if (pending_bytes) + *pending_bytes = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_IN]; + + return res; +} + +bool xusb_device_get_port_in_sleep() +{ + // Ejection heuristic. + u32 link_mode = XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) & XHCI_PORTSC_PLS_MASK; + return (link_mode == XHCI_PORTSC_PLS_U3); +} + +bool xusb_device_class_send_max_lun(u8 max_lun) +{ + // Timeout if get MAX_LUN request doesn't happen in 10s. + u32 timer = get_tmr_ms() + 10000; + + usbd_xotg->max_lun = max_lun; + usbd_xotg->max_lun_set = true; + + // Wait for request and transfer start. + while (usbd_xotg->device_state != XUSB_LUN_CONFIGURED) + { + _xusb_ep_operation(500000); + if (timer < get_tmr_ms() || btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN)) + return true; + } + + usbd_xotg->device_state = XUSB_CONFIGURED; + + return false; +} + +bool xusb_device_class_send_hid_report() +{ + // Timeout if get GET_HID_REPORT request doesn't happen in 10s. + u32 timer = get_tmr_ms() + 10000; + + // Wait for request and transfer start. + while (usbd_xotg->device_state != XUSB_HID_CONFIGURED) + { + _xusb_ep_operation(500000); + if (timer < get_tmr_ms() || btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN)) + return true; + } + + usbd_xotg->device_state = XUSB_CONFIGURED; + + return false; +} + +void xusb_device_get_ops(usb_ops_t *ops) +{ + ops->usbd_flush_endpoint = NULL; + ops->usbd_set_ep_stall = xusb_set_ep_stall; + ops->usbd_handle_ep0_ctrl_setup = xusb_handle_ep0_ctrl_setup; + ops->usbd_end = xusb_end;////////////////// + ops->usb_device_init = xusb_device_init; + ops->usb_device_enumerate = xusb_device_enumerate; + ops->usb_device_class_send_max_lun = xusb_device_class_send_max_lun; + ops->usb_device_class_send_hid_report = xusb_device_class_send_hid_report; + ops->usb_device_get_suspended = xusb_device_get_port_in_sleep; + ops->usb_device_get_port_in_sleep = xusb_device_get_port_in_sleep; + + ops->usb_device_ep1_out_read = xusb_device_ep1_out_read; + ops->usb_device_ep1_out_read_big = xusb_device_ep1_out_read_big; + ops->usb_device_ep1_out_reading_finish = xusb_device_ep1_out_reading_finish; + ops->usb_device_ep1_in_write = xusb_device_ep1_in_write; + ops->usb_device_ep1_in_writing_finish = xusb_device_ep1_in_writing_finish; +} diff --git a/bdk/utils/btn.h b/bdk/utils/btn.h index f284748..ac191fa 100644 --- a/bdk/utils/btn.h +++ b/bdk/utils/btn.h @@ -20,10 +20,10 @@ #include -#define BTN_POWER (1 << 0) -#define BTN_VOL_DOWN (1 << 1) -#define BTN_VOL_UP (1 << 2) -#define BTN_SINGLE (1 << 7) +#define BTN_POWER BIT(0) +#define BTN_VOL_DOWN BIT(1) +#define BTN_VOL_UP BIT(2) +#define BTN_SINGLE BIT(7) u8 btn_read(); u8 btn_read_vol(); diff --git a/bdk/utils/types.h b/bdk/utils/types.h index 9d85ca0..0300425 100644 --- a/bdk/utils/types.h +++ b/bdk/utils/types.h @@ -23,10 +23,12 @@ #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) #define ALIGN_DOWN(x, a) (((x) - ((a) - 1)) & ~((a) - 1)) +#define BIT(n) (1U << (n)) #define MAX(a, b) ((a) > (b) ? (a) : (b)) #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define DIV_ROUND_UP(a, b) ((a + b - 1) / b) +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) #define LOG2(n) (32 - __builtin_clz(n) - 1) #define OFFSET_OF(t, m) ((u32)&((t *)NULL)->m) @@ -60,17 +62,25 @@ typedef volatile unsigned char vu8; typedef volatile unsigned short vu16; typedef volatile unsigned int vu32; +#ifdef __aarch64__ +typedef u64 uptr; +#else /* __arm__ or __thumb__ */ +typedef u32 uptr; +#endif + static const u32 colors[6] = {COLOR_RED, COLOR_ORANGE, COLOR_YELLOW, COLOR_GREEN, COLOR_BLUE, COLOR_VIOLET}; typedef int bool; #define true 1 #define false 0 -#define BOOT_CFG_AUTOBOOT_EN (1 << 0) -#define BOOT_CFG_FROM_LAUNCH (1 << 1) -#define BOOT_CFG_SEPT_RUN (1 << 7) +#define BOOT_CFG_AUTOBOOT_EN BIT(0) +#define BOOT_CFG_FROM_LAUNCH BIT(1) +#define BOOT_CFG_FROM_ID BIT(2) +#define BOOT_CFG_TO_EMUMMC BIT(3) +#define BOOT_CFG_SEPT_RUN BIT(7) -#define EXTRA_CFG_DUMP_EMUMMC (1 << 0) +#define EXTRA_CFG_DUMP_EMUMMC BIT(0) typedef struct __attribute__((__packed__)) _boot_cfg_t { @@ -82,8 +92,10 @@ typedef struct __attribute__((__packed__)) _boot_cfg_t { struct { - char id[8]; + char id[8]; // 7 char ASCII null teminated. + char emummc_path[0x78]; // emuMMC/XXX, ASCII null teminated. }; + u8 ums; // nyx_ums_type. u8 xt_str[0x80]; }; } boot_cfg_t; diff --git a/bdk/utils/util.c b/bdk/utils/util.c index dd10781..e5cd868 100644 --- a/bdk/utils/util.c +++ b/bdk/utils/util.c @@ -135,7 +135,7 @@ void panic(u32 val) void reboot_normal() { sd_end(); - reconfig_hw_workaround(false, 0); + hw_reinit_workaround(false, 0); panic(0x21); // Bypass fuse programming in package1. } @@ -143,7 +143,7 @@ void reboot_normal() void reboot_rcm() { sd_end(); - reconfig_hw_workaround(false, 0); + hw_reinit_workaround(false, 0); PMC(APBDEV_PMC_SCRATCH0) = PMC_SCRATCH0_MODE_RCM; PMC(APBDEV_PMC_CNTRL) |= PMC_CNTRL_MAIN_RST; @@ -152,10 +152,27 @@ void reboot_rcm() bpmp_halt(); } +void reboot_full() +{ + sd_end(); + hw_reinit_workaround(false, 0); + + // Enable soft reset wake event. + u8 reg = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2); + reg |= MAX77620_ONOFFCNFG2_SFT_RST_WK; + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2, reg); + + // Do a soft reset. + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_SFT_RST); + + while (true) + bpmp_halt(); +} + void power_off() { sd_end(); - reconfig_hw_workaround(false, 0); + hw_reinit_workaround(false, 0); // Stop the alarm, in case we injected and powered off too fast. max77620_rtc_stop_alarm(); diff --git a/bdk/utils/util.h b/bdk/utils/util.h index 948e02c..20df76f 100644 --- a/bdk/utils/util.h +++ b/bdk/utils/util.h @@ -23,21 +23,23 @@ typedef enum { - NYX_CFG_BIS = (1 << 5), - NYX_CFG_UMS = (1 << 6), - NYX_CFG_DUMP = (1 << 7), + NYX_CFG_BIS = BIT(5), + NYX_CFG_UMS = BIT(6), + NYX_CFG_DUMP = BIT(7), } nyx_cfg_t; typedef enum { - ERR_LIBSYS_LP0 = (1 << 0), - ERR_SYSOLD_NYX = (1 << 1), - ERR_SYSOLD_MTC = (1 << 2), - ERR_EXCEPT_ENB = (1 << 31), + ERR_LIBSYS_LP0 = BIT(0), + ERR_SYSOLD_NYX = BIT(1), + ERR_LIBSYS_MTC = BIT(2), + ERR_SD_BOOT_EN = BIT(3), + ERR_L4T_KERNEL = BIT(24), + ERR_EXCEPTION = BIT(31), } hekate_errors_t; -#define byte_swap_32(num) (((num >> 24) & 0xff) | ((num << 8) & 0xff0000) | \ - ((num >> 8 )& 0xff00) | ((num << 24) & 0xff000000)) +#define byte_swap_32(num) ((((num) >> 24) & 0xff) | (((num) << 8) & 0xff0000) | \ + (((num) >> 8 )& 0xff00) | (((num) << 24) & 0xff000000)) typedef struct _cfg_op_t { @@ -71,6 +73,7 @@ void msleep(u32 ms); void panic(u32 val); void reboot_normal(); void reboot_rcm(); +void reboot_full(); void power_off(); void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops); u32 crc32_calc(u32 crc, const u8 *buf, u32 len); diff --git a/source/config.c b/source/config.c index 7168e5b..254095e 100644 --- a/source/config.c +++ b/source/config.c @@ -23,6 +23,7 @@ #include "gfx/tui.h" #include #include +#include #include #include #include @@ -42,12 +43,14 @@ void set_default_configuration() h_cfg.autohosoff = 0; h_cfg.autonogc = 1; h_cfg.updater2p = 0; - h_cfg.brand = NULL; - h_cfg.tagline = NULL; + h_cfg.bootprotect = 0; h_cfg.errors = 0; + h_cfg.eks = NULL; h_cfg.sept_run = EMC(EMC_SCRATCH0) & EMC_SEPT_RUN; + h_cfg.aes_slots_new = false; h_cfg.rcm_patched = fuse_check_patched_rcm(); h_cfg.emummc_force_disable = false; + h_cfg.t210b01 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01; sd_power_cycle_time_start = 0; } diff --git a/source/config.h b/source/config.h index 7833f4f..894cdf9 100644 --- a/source/config.h +++ b/source/config.h @@ -17,6 +17,7 @@ #ifndef _CONFIG_H_ #define _CONFIG_H_ +#include "hos/hos.h" #include typedef struct _hekate_config @@ -29,14 +30,16 @@ typedef struct _hekate_config u32 autohosoff; u32 autonogc; u32 updater2p; - char *brand; - char *tagline; + u32 bootprotect; // Global temporary config. + bool t210b01; bool se_keygen_done; bool sept_run; + bool aes_slots_new; bool emummc_force_disable; bool rcm_patched; u32 errors; + hos_eks_mbr_t *eks; } hekate_config; void set_default_configuration(); diff --git a/source/hos/fss.c b/source/hos/fss.c index 6ae5d8d..09896f9 100644 --- a/source/hos/fss.c +++ b/source/hos/fss.c @@ -19,6 +19,7 @@ #include #include "fss.h" +#include "hos.h" #include "../config.h" #include #include @@ -35,6 +36,7 @@ extern bool is_ipl_updated(void *buf, char *path, bool force); // FSS0 Magic and Meta header offset. #define FSS0_MAGIC 0x30535346 #define FSS0_META_OFFSET 0x4 +#define FSS0_VERSION_0_17_0 0x110000 // FSS0 Content Types. #define CNT_TYPE_FSP 0 @@ -48,9 +50,10 @@ extern bool is_ipl_updated(void *buf, char *path, bool force); #define CNT_TYPE_EMC 8 #define CNT_TYPE_KLD 9 // Kernel Loader. #define CNT_TYPE_KRN 10 // Kernel. +#define CNT_TYPE_EXF 11 // Exosphere Mariko fatal payload. // FSS0 Content Flags. -#define CNT_FLAG0_EXPERIMENTAL (1 << 0) +#define CNT_FLAG0_EXPERIMENTAL BIT(0) // FSS0 Meta Header. typedef struct _fss_meta_t @@ -85,8 +88,12 @@ int parse_fss(launch_ctxt_t *ctxt, const char *path, fss0_sept_t *sept_ctxt) bool stock = false; int sept_used = 0; + // Skip if stock and Exosphere and warmboot are not needed. if (!sept_ctxt) { + bool pkg1_old = ctxt->pkg1_id->kb <= KB_FIRMWARE_VERSION_620; + bool emummc_disabled = !emu_cfg.enabled || h_cfg.emummc_force_disable; + LIST_FOREACH_ENTRY(ini_kv_t, kv, &ctxt->cfg->kvs, link) { if (!strcmp("stock", kv->key)) @@ -94,7 +101,11 @@ int parse_fss(launch_ctxt_t *ctxt, const char *path, fss0_sept_t *sept_ctxt) stock = true; } - if (stock && ctxt->pkg1_id->kb <= KB_FIRMWARE_VERSION_620 && (!emu_cfg.enabled || h_cfg.emummc_force_disable)) +#ifdef HOS_MARIKO_STOCK_SECMON + if (stock && emummc_disabled && (pkg1_old || h_cfg.t210b01)) +#else + if (stock && emummc_disabled && pkg1_old) +#endif return 1; } @@ -113,12 +124,25 @@ int parse_fss(launch_ctxt_t *ctxt, const char *path, fss0_sept_t *sept_ctxt) // Check if valid FSS0 and parse it. if (fss_meta->magic == FSS0_MAGIC) { + bool mariko_not_supported = false; + if (h_cfg.t210b01 && (fss_meta->version < FSS0_VERSION_0_17_0)) + { + gfx_con.mute = false; + mariko_not_supported = true; + } + gfx_printf("Found FSS0, Atmosphere %d.%d.%d-%08x\n" "Max HOS supported: %d.%d.%d\n" "Unpacking and loading components.. ", fss_meta->version >> 24, (fss_meta->version >> 16) & 0xFF, (fss_meta->version >> 8) & 0xFF, fss_meta->git_rev, fss_meta->hos_ver >> 24, (fss_meta->hos_ver >> 16) & 0xFF, (fss_meta->hos_ver >> 8) & 0xFF); + if (mariko_not_supported) + { + EPRINTF("Mariko not supported on < 0.17.0!"); + goto fail; + } + if (!sept_ctxt) { ctxt->atmosphere = true; @@ -137,7 +161,7 @@ int parse_fss(launch_ctxt_t *ctxt, const char *path, fss0_sept_t *sept_ctxt) continue; // If content is experimental and experimental flag is not enabled, skip it. - if ((curr_fss_cnt[i].flags0 & CNT_FLAG0_EXPERIMENTAL) && !ctxt->fss0_enable_experimental) + if ((curr_fss_cnt[i].flags0 & CNT_FLAG0_EXPERIMENTAL) && !ctxt->fss0_experimental) continue; // Parse content. @@ -154,14 +178,31 @@ int parse_fss(launch_ctxt_t *ctxt, const char *path, fss0_sept_t *sept_ctxt) list_append(&ctxt->kip1_list, &mkip1->link); DPRINTF("Loaded %s.kip1 from FSS0 (size %08X)\n", curr_fss_cnt[i].name, curr_fss_cnt[i].size); break; + + case CNT_TYPE_KRN: + if (stock) + continue; + ctxt->kernel_size = curr_fss_cnt[i].size; + ctxt->kernel = content; + break; + case CNT_TYPE_EXO: ctxt->secmon_size = curr_fss_cnt[i].size; ctxt->secmon = content; break; + + case CNT_TYPE_EXF: + ctxt->exofatal_size = curr_fss_cnt[i].size; + ctxt->exofatal = content; + break; + case CNT_TYPE_WBT: + if (h_cfg.t210b01) + continue; ctxt->warmboot_size = curr_fss_cnt[i].size; ctxt->warmboot = content; break; + default: continue; } @@ -201,6 +242,7 @@ out: return (!sept_ctxt ? 1 : sept_used); } +fail: f_close(&fp); free(fss); diff --git a/source/hos/hos.h b/source/hos/hos.h index 4ad8747..b5900c6 100644 --- a/source/hos/hos.h +++ b/source/hos/hos.h @@ -42,6 +42,9 @@ #define HOS_PKG11_MAGIC 0x31314B50 #define HOS_EKS_MAGIC 0x30534B45 +// Use official Mariko secmon when in stock. +//#define HOS_MARIKO_STOCK_SECMON + typedef struct _exo_ctxt_t { bool fs_is_510; @@ -66,17 +69,17 @@ typedef struct _hos_eks_bis_keys_t typedef struct _hos_eks_mbr_t { u32 magic; - u8 enabled[6]; + u8 enabled[5]; u8 enabled_bis; - u8 rsvd; - u32 sbk_low; + u8 rsvd[2]; + u32 lot0; u8 dkg[0x10]; u8 dkk[0x10]; - hos_eks_keys_t keys[6]; + hos_eks_keys_t keys[5]; hos_eks_bis_keys_t bis_keys[3]; } hos_eks_mbr_t; -static_assert(sizeof(hos_eks_mbr_t) == 336, "HOS EKS size is wrong!"); +static_assert(sizeof(hos_eks_mbr_t) == 304, "HOS EKS size is wrong!"); typedef struct _launch_ctxt_t { @@ -90,6 +93,8 @@ typedef struct _launch_ctxt_t u32 warmboot_size; void *secmon; u32 secmon_size; + void *exofatal; + u32 exofatal_size; void *pkg2; u32 pkg2_size; @@ -97,6 +102,7 @@ typedef struct _launch_ctxt_t void *kernel; u32 kernel_size; + link_t kip1_list; char* kip1_patches; @@ -105,7 +111,7 @@ typedef struct _launch_ctxt_t bool debugmode; bool stock; bool atmosphere; - bool fss0_enable_experimental; + bool fss0_experimental; bool emummc_forced; exo_ctxt_t exo_ctx; diff --git a/source/hos/pkg1.c b/source/hos/pkg1.c index 8f81334..23b25bd 100644 --- a/source/hos/pkg1.c +++ b/source/hos/pkg1.c @@ -45,7 +45,7 @@ static const pkg1_id_t _pkg1_ids[] = { const pkg1_id_t *pkg1_identify(u8 *pkg1) { for (u32 i = 0; _pkg1_ids[i].id; i++) - if (!memcmp(pkg1 + 0x10, _pkg1_ids[i].id, 12)) + if (!memcmp(pkg1 + 0x10, _pkg1_ids[i].id, 8)) return &_pkg1_ids[i]; return NULL; } diff --git a/source/hos/pkg1.h b/source/hos/pkg1.h index da1df35..81bef20 100644 --- a/source/hos/pkg1.h +++ b/source/hos/pkg1.h @@ -23,6 +23,19 @@ #define PKG1_OFFSET 0x100000 #define KEYBLOB_OFFSET 0x180000 +typedef struct _bl_hdr_t210b01_t +{ + u8 aes_mac[0x10]; + u8 rsa_sig[0x100]; + u8 salt[0x20]; + u8 sha256[0x20]; + u32 version; + u32 size; + u32 load_addr; + u32 entrypoint; + u8 rsvd[0x10]; +} bl_hdr_t210b01_t; + typedef struct _pkg1_id_t { const char *id; diff --git a/source/hos/sept.c b/source/hos/sept.c index fe9222f..5e6ef73 100644 --- a/source/hos/sept.c +++ b/source/hos/sept.c @@ -105,7 +105,6 @@ int reboot_to_sept(const u8 *tsec_fw, const u32 tsec_size, const u32 kb) } } - if (!fss0_sept_used) { // Copy sept-primary. @@ -173,7 +172,7 @@ int reboot_to_sept(const u8 *tsec_fw, const u32 tsec_size, const u32 kb) PMC(APBDEV_PMC_SCRATCH33) = SEPT_PRI_ADDR; PMC(APBDEV_PMC_SCRATCH40) = 0x6000F208; - reconfig_hw_workaround(false, 0); + hw_reinit_workaround(false, 0); (*sept)(); diff --git a/source/keys/key_sources.inl b/source/keys/key_sources.inl index 5cb7f08..0ba95f9 100644 --- a/source/keys/key_sources.inl +++ b/source/keys/key_sources.inl @@ -14,13 +14,12 @@ * along with this program. If not, see . */ -static u8 zeros[0x10] = {0}; - -static u8 null_hash[0x20] = { +// Sha256 hash of the null string. +static const u8 null_hash[0x20] __attribute__((aligned(4))) = { 0xE3, 0xB0, 0xC4, 0x42, 0x98, 0xFC, 0x1C, 0x14, 0x9A, 0xFB, 0xF4, 0xC8, 0x99, 0x6F, 0xB9, 0x24, 0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C, 0xA4, 0x95, 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55}; -static const u8 keyblob_key_source[][0x10] = { +static const u8 keyblob_key_source[][0x10] __attribute__((aligned(4))) = { {0xDF, 0x20, 0x6F, 0x59, 0x44, 0x54, 0xEF, 0xDC, 0x70, 0x74, 0x48, 0x3B, 0x0D, 0xED, 0x9F, 0xD3}, //1.0.0 {0x0C, 0x25, 0x61, 0x5D, 0x68, 0x4C, 0xEB, 0x42, 0x1C, 0x23, 0x79, 0xEA, 0x82, 0x25, 0x12, 0xAC}, //3.0.0 {0x33, 0x76, 0x85, 0xEE, 0x88, 0x4A, 0xAE, 0x0A, 0xC2, 0x8A, 0xFD, 0x7D, 0x63, 0xC0, 0x43, 0x3B}, //3.0.1 @@ -29,7 +28,7 @@ static const u8 keyblob_key_source[][0x10] = { {0xD8, 0xCC, 0xE1, 0x26, 0x6A, 0x35, 0x3F, 0xCC, 0x20, 0xF3, 0x2D, 0x3B, 0x51, 0x7D, 0xE9, 0xC0} //6.0.0 }; -static const u8 master_kek_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_600][0x10] = { +static const u8 master_kek_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_620 + 1][0x10] __attribute__((aligned(4))) = { {0x37, 0x4B, 0x77, 0x29, 0x59, 0xB4, 0x04, 0x30, 0x81, 0xF6, 0xE5, 0x8C, 0x6D, 0x36, 0x17, 0x9A}, //6.2.0 {0x9A, 0x3E, 0xA9, 0xAB, 0xFD, 0x56, 0x46, 0x1C, 0x9B, 0xF6, 0x48, 0x7F, 0x5C, 0xFA, 0x09, 0x5C}, //7.0.0 {0xDE, 0xDC, 0xE3, 0x39, 0x30, 0x88, 0x16, 0xF8, 0xAE, 0x97, 0xAD, 0xEC, 0x64, 0x2D, 0x41, 0x41}, //8.1.0 @@ -37,7 +36,7 @@ static const u8 master_kek_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION {0x30, 0x3F, 0x02, 0x7E, 0xD8, 0x38, 0xEC, 0xD7, 0x93, 0x25, 0x34, 0xB5, 0x30, 0xEB, 0xCA, 0x7A}, //9.1.0 }; -static const u8 master_key_vectors[KB_FIRMWARE_VERSION_MAX+1][0x10] = { +static const u8 master_key_vectors[KB_FIRMWARE_VERSION_MAX + 1][0x10] __attribute__((aligned(4))) = { {0x0C, 0xF0, 0x59, 0xAC, 0x85, 0xF6, 0x26, 0x65, 0xE1, 0xE9, 0x19, 0x55, 0xE6, 0xF2, 0x67, 0x3D}, /* Zeroes encrypted with Master Key 00. */ {0x29, 0x4C, 0x04, 0xC8, 0xEB, 0x10, 0xED, 0x9D, 0x51, 0x64, 0x97, 0xFB, 0xF3, 0x4D, 0x50, 0xDD}, /* Master key 00 encrypted with Master key 01. */ {0xDE, 0xCF, 0xEB, 0xEB, 0x10, 0xAE, 0x74, 0xD8, 0xAD, 0x7C, 0xF4, 0x9E, 0x62, 0xE0, 0xE8, 0x72}, /* Master key 01 encrypted with Master key 02. */ @@ -53,32 +52,38 @@ static const u8 master_key_vectors[KB_FIRMWARE_VERSION_MAX+1][0x10] = { //======================================Keys======================================// // from Package1 -> Secure_Monitor -static const u8 aes_kek_generation_source[0x10] = { +static const u8 aes_kek_generation_source[0x10] __attribute__((aligned(4))) = { 0x4D, 0x87, 0x09, 0x86, 0xC4, 0x5D, 0x20, 0x72, 0x2F, 0xBA, 0x10, 0x53, 0xDA, 0x92, 0xE8, 0xA9}; -static const u8 aes_kek_seed_01[0x10] = { +static const u8 aes_kek_seed_01[0x10] __attribute__((aligned(4))) = { 0xA2, 0xAB, 0xBF, 0x9C, 0x92, 0x2F, 0xBB, 0xE3, 0x78, 0x79, 0x9B, 0xC0, 0xCC, 0xEA, 0xA5, 0x74}; -static const u8 aes_kek_seed_03[0x10] = { +static const u8 aes_kek_seed_03[0x10] __attribute__((aligned(4))) = { 0xE5, 0x4D, 0x9A, 0x02, 0xF0, 0x4F, 0x5F, 0xA8, 0xAD, 0x76, 0x0A, 0xF6, 0x32, 0x95, 0x59, 0xBB}; -static const u8 package2_key_source[0x10] = { +static const u8 package2_key_source[0x10] __attribute__((aligned(4))) = { 0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7}; -static const u8 titlekek_source[0x10] = { +static const u8 titlekek_source[0x10] __attribute__((aligned(4))) = { 0x1E, 0xDC, 0x7B, 0x3B, 0x60, 0xE6, 0xB4, 0xD8, 0x78, 0xB8, 0x17, 0x15, 0x98, 0x5E, 0x62, 0x9B}; -static const u8 retail_specific_aes_key_source[0x10] = { +static const u8 retail_specific_aes_key_source[0x10] __attribute__((aligned(4))) = { 0xE2, 0xD6, 0xB8, 0x7A, 0x11, 0x9C, 0xB8, 0x80, 0xE8, 0x22, 0x88, 0x8A, 0x46, 0xFB, 0xA1, 0x95}; -// from Package1ldr (or Secure_Monitor on 6.2.0) -static const u8 keyblob_mac_key_source[0x10] = { +// from Package1ldr (or Secure_Monitor on 6.2.0+) +static const u8 keyblob_mac_key_source[0x10] __attribute__((aligned(4))) = { 0x59, 0xC7, 0xFB, 0x6F, 0xBE, 0x9B, 0xBE, 0x87, 0x65, 0x6B, 0x15, 0xC0, 0x53, 0x73, 0x36, 0xA5}; -static const u8 master_key_source[0x10] = { +static const u8 master_key_source[0x10] __attribute__((aligned(4))) = { 0xD8, 0xA2, 0x41, 0x0A, 0xC6, 0xC5, 0x90, 0x01, 0xC6, 0x1D, 0x6A, 0x26, 0x7C, 0x51, 0x3F, 0x3C}; -static const u8 per_console_key_source[0x10] = { +static const u8 per_console_key_source[0x10] __attribute__((aligned(4))) = { 0x4F, 0x02, 0x5F, 0x0E, 0xB6, 0x6D, 0x11, 0x0E, 0xDC, 0x32, 0x7D, 0x41, 0x86, 0xC2, 0xF4, 0x78}; -static const u8 device_master_key_source_kek_source[0x10] = { +static const u8 device_master_key_source_kek_source[0x10] __attribute__((aligned(4))) = { 0x0C, 0x91, 0x09, 0xDB, 0x93, 0x93, 0x07, 0x81, 0x07, 0x3C, 0xC4, 0x16, 0x22, 0x7C, 0x6C, 0x28}; -static const u8 mariko_master_kek_source[0x10] = { - 0x0E, 0x44, 0x0C, 0xED, 0xB4, 0x36, 0xC0, 0x3F, 0xAA, 0x1D, 0xAE, 0xBF, 0x62, 0xB1, 0x09, 0x82}; +static const u8 mariko_master_kek_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_600 + 1][0x10] __attribute__((aligned(4))) = { + {0x77, 0x60, 0x5A, 0xD2, 0xEE, 0x6E, 0xF8, 0x3C, 0x3F, 0x72, 0xE2, 0x59, 0x9D, 0xAC, 0x5E, 0x56}, // 6.0.0. + {0x1E, 0x80, 0xB8, 0x17, 0x3E, 0xC0, 0x60, 0xAA, 0x11, 0xBE, 0x1A, 0x4A, 0xA6, 0x6F, 0xE4, 0xAE}, // 6.2.0. + {0x94, 0x08, 0x67, 0xBD, 0x0A, 0x00, 0x38, 0x84, 0x11, 0xD3, 0x1A, 0xDB, 0xDD, 0x8D, 0xF1, 0x8A}, // 7.0.0. + {0x5C, 0x24, 0xE3, 0xB8, 0xB4, 0xF7, 0x00, 0xC2, 0x3C, 0xFD, 0x0A, 0xCE, 0x13, 0xC3, 0xDC, 0x23}, // 8.1.0. + {0x86, 0x69, 0xF0, 0x09, 0x87, 0xC8, 0x05, 0xAE, 0xB5, 0x7B, 0x48, 0x74, 0xDE, 0x62, 0xA6, 0x13}, // 9.0.0. + {0x0E, 0x44, 0x0C, 0xED, 0xB4, 0x36, 0xC0, 0x3F, 0xAA, 0x1D, 0xAE, 0xBF, 0x62, 0xB1, 0x09, 0x82}, // 9.1.0. +}; -static const u8 device_master_key_source_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_400 + 1][0x10] = { +static const u8 device_master_key_source_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_400 + 1][0x10] __attribute__((aligned(4))) = { {0x8B, 0x4E, 0x1C, 0x22, 0x42, 0x07, 0xC8, 0x73, 0x56, 0x94, 0x08, 0x8B, 0xCC, 0x47, 0x0F, 0x5D}, /* 4.0.0 Device Master Key Source Source. */ {0x6C, 0xEF, 0xC6, 0x27, 0x8B, 0xEC, 0x8A, 0x91, 0x99, 0xAB, 0x24, 0xAC, 0x4F, 0x1C, 0x8F, 0x1C}, /* 5.0.0 Device Master Key Source Source. */ {0x70, 0x08, 0x1B, 0x97, 0x44, 0x64, 0xF8, 0x91, 0x54, 0x9D, 0xC6, 0x84, 0x8F, 0x1A, 0xB2, 0xE4}, /* 6.0.0 Device Master Key Source Source. */ @@ -90,18 +95,18 @@ static const u8 device_master_key_source_sources[KB_FIRMWARE_VERSION_MAX - KB_FI }; // from ES -static const u8 eticket_rsa_kek_source[0x10] = { +static const u8 eticket_rsa_kek_source[0x10] __attribute__((aligned(4))) = { 0XDB, 0XA4, 0X51, 0X12, 0X4C, 0XA0, 0XA9, 0X83, 0X68, 0X14, 0XF5, 0XED, 0X95, 0XE3, 0X12, 0X5B}; -static const u8 eticket_rsa_kekek_source[0x10] = { +static const u8 eticket_rsa_kekek_source[0x10] __attribute__((aligned(4))) = { 0X46, 0X6E, 0X57, 0XB7, 0X4A, 0X44, 0X7F, 0X02, 0XF3, 0X21, 0XCD, 0XE5, 0X8F, 0X2F, 0X55, 0X35}; // from SSL -static const u8 ssl_rsa_kek_source_x[0x10] = { +static const u8 ssl_rsa_kek_source_x[0x10] __attribute__((aligned(4))) = { 0X7F, 0X5B, 0XB0, 0X84, 0X7B, 0X25, 0XAA, 0X67, 0XFA, 0XC8, 0X4B, 0XE2, 0X3D, 0X7B, 0X69, 0X03}; -static const u8 ssl_rsa_kek_source_y[0x10] = { +static const u8 ssl_rsa_kek_source_y[0x10] __attribute__((aligned(4))) = { 0X9A, 0X38, 0X3B, 0XF4, 0X31, 0XD0, 0XBD, 0X81, 0X32, 0X53, 0X4B, 0XA9, 0X64, 0X39, 0X7D, 0XE3}; -static const u8 device_master_kek_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_400 + 1][0x10] = { +static const u8 device_master_kek_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_400 + 1][0x10] __attribute__((aligned(4))) = { {0x88, 0x62, 0x34, 0x6E, 0xFA, 0xF7, 0xD8, 0x3F, 0xE1, 0x30, 0x39, 0x50, 0xF0, 0xB7, 0x5D, 0x5D}, /* 4.0.0 Device Master Kek Source. */ {0x06, 0x1E, 0x7B, 0xE9, 0x6D, 0x47, 0x8C, 0x77, 0xC5, 0xC8, 0xE7, 0x94, 0x9A, 0xA8, 0x5F, 0x2E}, /* 5.0.0 Device Master Kek Source. */ {0x99, 0xFA, 0x98, 0xBD, 0x15, 0x1C, 0x72, 0xFD, 0x7D, 0x9A, 0xD5, 0x41, 0x00, 0xFD, 0xB2, 0xEF}, /* 6.0.0 Device Master Kek Source. */ @@ -113,52 +118,46 @@ static const u8 device_master_kek_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_ }; // from SPL -static const u8 aes_key_generation_source[0x10] = { +static const u8 aes_key_generation_source[0x10] __attribute__((aligned(4))) = { 0x89, 0x61, 0x5E, 0xE0, 0x5C, 0x31, 0xB6, 0x80, 0x5F, 0xE5, 0x8F, 0x3D, 0xA2, 0x4F, 0x7A, 0xA8}; // from FS -static const u8 bis_kek_source[0x10] = { +static const u8 bis_kek_source[0x10] __attribute__((aligned(4))) = { 0x34, 0xC1, 0xA0, 0xC4, 0x82, 0x58, 0xF8, 0xB4, 0xFA, 0x9E, 0x5E, 0x6A, 0xDA, 0xFC, 0x7E, 0x4F}; -static const u8 bis_key_source[3][0x20] = { - { - 0xF8, 0x3F, 0x38, 0x6E, 0x2C, 0xD2, 0xCA, 0x32, 0xA8, 0x9A, 0xB9, 0xAA, 0x29, 0xBF, 0xC7, 0x48, - 0x7D, 0x92, 0xB0, 0x3A, 0xA8, 0xBF, 0xDE, 0xE1, 0xA7, 0x4C, 0x3B, 0x6E, 0x35, 0xCB, 0x71, 0x06}, - { - 0x41, 0x00, 0x30, 0x49, 0xDD, 0xCC, 0xC0, 0x65, 0x64, 0x7A, 0x7E, 0xB4, 0x1E, 0xED, 0x9C, 0x5F, - 0x44, 0x42, 0x4E, 0xDA, 0xB4, 0x9D, 0xFC, 0xD9, 0x87, 0x77, 0x24, 0x9A, 0xDC, 0x9F, 0x7C, 0xA4}, - { - 0x52, 0xC2, 0xE9, 0xEB, 0x09, 0xE3, 0xEE, 0x29, 0x32, 0xA1, 0x0C, 0x1F, 0xB6, 0xA0, 0x92, 0x6C, - 0x4D, 0x12, 0xE1, 0x4B, 0x2A, 0x47, 0x4C, 0x1C, 0x09, 0xCB, 0x03, 0x59, 0xF0, 0x15, 0xF4, 0xE4} +static const u8 bis_key_source[3][0x20] __attribute__((aligned(4))) = { + {0xF8, 0x3F, 0x38, 0x6E, 0x2C, 0xD2, 0xCA, 0x32, 0xA8, 0x9A, 0xB9, 0xAA, 0x29, 0xBF, 0xC7, 0x48, + 0x7D, 0x92, 0xB0, 0x3A, 0xA8, 0xBF, 0xDE, 0xE1, 0xA7, 0x4C, 0x3B, 0x6E, 0x35, 0xCB, 0x71, 0x06}, + {0x41, 0x00, 0x30, 0x49, 0xDD, 0xCC, 0xC0, 0x65, 0x64, 0x7A, 0x7E, 0xB4, 0x1E, 0xED, 0x9C, 0x5F, + 0x44, 0x42, 0x4E, 0xDA, 0xB4, 0x9D, 0xFC, 0xD9, 0x87, 0x77, 0x24, 0x9A, 0xDC, 0x9F, 0x7C, 0xA4}, + {0x52, 0xC2, 0xE9, 0xEB, 0x09, 0xE3, 0xEE, 0x29, 0x32, 0xA1, 0x0C, 0x1F, 0xB6, 0xA0, 0x92, 0x6C, + 0x4D, 0x12, 0xE1, 0x4B, 0x2A, 0x47, 0x4C, 0x1C, 0x09, 0xCB, 0x03, 0x59, 0xF0, 0x15, 0xF4, 0xE4} }; -static const u8 header_kek_source[0x10] = { +static const u8 header_kek_source[0x10] __attribute__((aligned(4))) = { 0x1F, 0x12, 0x91, 0x3A, 0x4A, 0xCB, 0xF0, 0x0D, 0x4C, 0xDE, 0x3A, 0xF6, 0xD5, 0x23, 0x88, 0x2A}; -static const u8 header_key_source[0x20] = { +static const u8 header_key_source[0x20] __attribute__((aligned(4))) = { 0x5A, 0x3E, 0xD8, 0x4F, 0xDE, 0xC0, 0xD8, 0x26, 0x31, 0xF7, 0xE2, 0x5D, 0x19, 0x7B, 0xF5, 0xD0, 0x1C, 0x9B, 0x7B, 0xFA, 0xF6, 0x28, 0x18, 0x3D, 0x71, 0xF6, 0x4D, 0x73, 0xF1, 0x50, 0xB9, 0xD2}; -static const u8 key_area_key_sources[3][0x10] = { - { - 0x7F, 0x59, 0x97, 0x1E, 0x62, 0x9F, 0x36, 0xA1, 0x30, 0x98, 0x06, 0x6F, 0x21, 0x44, 0xC3, 0x0D}, // application - { - 0x32, 0x7D, 0x36, 0x08, 0x5A, 0xD1, 0x75, 0x8D, 0xAB, 0x4E, 0x6F, 0xBA, 0xA5, 0x55, 0xD8, 0x82}, // ocean - { - 0x87, 0x45, 0xF1, 0xBB, 0xA6, 0xBE, 0x79, 0x64, 0x7D, 0x04, 0x8B, 0xA6, 0x7B, 0x5F, 0xDA, 0x4A}, // system +static const u8 key_area_key_sources[3][0x10] __attribute__((aligned(4))) = { + {0x7F, 0x59, 0x97, 0x1E, 0x62, 0x9F, 0x36, 0xA1, 0x30, 0x98, 0x06, 0x6F, 0x21, 0x44, 0xC3, 0x0D}, // application + {0x32, 0x7D, 0x36, 0x08, 0x5A, 0xD1, 0x75, 0x8D, 0xAB, 0x4E, 0x6F, 0xBA, 0xA5, 0x55, 0xD8, 0x82}, // ocean + {0x87, 0x45, 0xF1, 0xBB, 0xA6, 0xBE, 0x79, 0x64, 0x7D, 0x04, 0x8B, 0xA6, 0x7B, 0x5F, 0xDA, 0x4A}, // system }; -static const u8 save_mac_kek_source[0x10] = { +static const u8 save_mac_kek_source[0x10] __attribute__((aligned(4))) = { 0XD8, 0X9C, 0X23, 0X6E, 0XC9, 0X12, 0X4E, 0X43, 0XC8, 0X2B, 0X03, 0X87, 0X43, 0XF9, 0XCF, 0X1B}; -static const u8 save_mac_key_source[0x10] = { +static const u8 save_mac_key_source[0x10] __attribute__((aligned(4))) = { 0XE4, 0XCD, 0X3D, 0X4A, 0XD5, 0X0F, 0X74, 0X28, 0X45, 0XA4, 0X87, 0XE5, 0XA0, 0X63, 0XEA, 0X1F}; -static const u8 save_mac_sd_card_kek_source[0x10] = { +static const u8 save_mac_sd_card_kek_source[0x10] __attribute__((aligned(4))) = { 0X04, 0X89, 0XEF, 0X5D, 0X32, 0X6E, 0X1A, 0X59, 0XC4, 0XB7, 0XAB, 0X8C, 0X36, 0X7A, 0XAB, 0X17}; -static const u8 save_mac_sd_card_key_source[0x10] = { +static const u8 save_mac_sd_card_key_source[0x10] __attribute__((aligned(4))) = { 0X6F, 0X64, 0X59, 0X47, 0XC5, 0X61, 0X46, 0XF9, 0XFF, 0XA0, 0X45, 0XD5, 0X95, 0X33, 0X29, 0X18}; -static const u8 sd_card_custom_storage_key_source[0x20] = { +static const u8 sd_card_custom_storage_key_source[0x20] __attribute__((aligned(4))) = { 0X37, 0X0C, 0X34, 0X5E, 0X12, 0XE4, 0XCE, 0XFE, 0X21, 0XB5, 0X8E, 0X64, 0XDB, 0X52, 0XAF, 0X35, 0X4F, 0X2C, 0XA5, 0XA3, 0XFC, 0X99, 0X9A, 0X47, 0XC0, 0X3E, 0XE0, 0X04, 0X48, 0X5B, 0X2F, 0XD0}; -static const u8 sd_card_kek_source[0x10] = { +static const u8 sd_card_kek_source[0x10] __attribute__((aligned(4))) = { 0X88, 0X35, 0X8D, 0X9C, 0X62, 0X9B, 0XA1, 0XA0, 0X01, 0X47, 0XDB, 0XE0, 0X62, 0X1B, 0X54, 0X32}; -static const u8 sd_card_nca_key_source[0x20] = { +static const u8 sd_card_nca_key_source[0x20] __attribute__((aligned(4))) = { 0X58, 0X41, 0XA2, 0X84, 0X93, 0X5B, 0X56, 0X27, 0X8B, 0X8E, 0X1F, 0XC5, 0X18, 0XE9, 0X9F, 0X2B, 0X67, 0XC7, 0X93, 0XF0, 0XF2, 0X4F, 0XDE, 0XD0, 0X75, 0X49, 0X5D, 0XCA, 0X00, 0X6D, 0X99, 0XC2}; -static const u8 sd_card_save_key_source[0x20] = { +static const u8 sd_card_save_key_source[0x20] __attribute__((aligned(4))) = { 0X24, 0X49, 0XB7, 0X22, 0X72, 0X67, 0X03, 0XA8, 0X19, 0X65, 0XE6, 0XE3, 0XEA, 0X58, 0X2F, 0XDD, 0X9A, 0X95, 0X15, 0X17, 0XB1, 0X6E, 0X8F, 0X7F, 0X1F, 0X68, 0X26, 0X31, 0X52, 0XEA, 0X29, 0X6A}; diff --git a/source/keys/keys.c b/source/keys/keys.c index a33a260..3e4a10a 100644 --- a/source/keys/keys.c +++ b/source/keys/keys.c @@ -20,7 +20,6 @@ #include #include #include "../gfx/tui.h" -#include "../hos/hos.h" #include "../hos/pkg1.h" #include "../hos/pkg2.h" #include "../hos/sept.h" @@ -71,11 +70,11 @@ static ALWAYS_INLINE u32 _read_be_u32(const void *buffer, u32 offset) { } // key functions -static int _key_exists(const void *data) { return memcmp(data, zeros, 0x10) != 0; }; +static int _key_exists(const void *data) { return memcmp(data, "\x00\x00\x00\x00\x00\x00\x00\x00", 8) != 0; }; static void _save_key(const char *name, const void *data, u32 len, char *outbuf); static void _save_key_family(const char *name, const void *data, u32 start_key, u32 num_keys, u32 len, char *outbuf); static void _generate_kek(u32 ks, const void *key_source, void *master_key, const void *kek_seed, const void *key_seed); -static void _get_device_key(u32 ks, void *out_device_key, u32 revision, const void *device_key, const void *master_key); +static void _get_device_key(u32 ks, void *out_device_key, u32 revision, const void *device_key, const void *new_device_key, const void *master_key); // titlekey functions static bool _test_key_pair(const void *E, const void *D, const void *N); @@ -94,6 +93,302 @@ static ALWAYS_INLINE u32 _get_tsec_fw_size(tsec_key_data_t *key_data) { return key_data->blob0_size + sizeof(tsec_key_data_t) + key_data->blob1_size + key_data->blob2_size + key_data->blob3_size + key_data->blob4_size; } +static u8 *_read_pkg1(sdmmc_t *sdmmc, const pkg1_id_t **pkg1_id) { + if (emummc_storage_init_mmc(&emmc_storage, sdmmc)) { + EPRINTF("Unable to init MMC."); + return NULL; + } + TPRINTFARGS("%kMMC init... ", colors[(color_idx++) % 6]); + + // Read package1. + u8 *pkg1 = (u8 *)malloc(PKG1_MAX_SIZE); + if (!emummc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0)) { + EPRINTF("Unable to set partition."); + return NULL; + } + if (!emummc_storage_read(&emmc_storage, PKG1_OFFSET / NX_EMMC_BLOCKSIZE, PKG1_MAX_SIZE / NX_EMMC_BLOCKSIZE, pkg1)) { + EPRINTF("Unable to read pkg1."); + return NULL; + } + + u32 pk1_offset = h_cfg.t210b01 ? sizeof(bl_hdr_t210b01_t) : 0; // Skip T210B01 OEM header. + *pkg1_id = pkg1_identify(pkg1 + pk1_offset); + if (!*pkg1_id) { + EPRINTF("Unknown pkg1 version.\n Make sure you have the latest Lockpick_RCM.\n If a new firmware version just came out,\n Lockpick_RCM must be updated.\n Check Github for new release."); + gfx_hexdump(0, pkg1, 0x20); + return NULL; + } + + return pkg1; +} + +#define RELOC_META_OFF 0x7C + +static bool _handle_sept(void *tsec_fw, u32 tsec_size, u32 kb, void *out_key) { + sd_mount(); + if (!f_stat("sd:/sept/payload.bak", NULL)) { + if (f_unlink("sd:/sept/payload.bin")) + gfx_printf("%kNote: no payload.bin already in /sept\n", colors[(color_idx++) % 6]); + f_rename("sd:/sept/payload.bak", "sd:/sept/payload.bin"); + } + + if (!h_cfg.sept_run) { + // bundle lp0 fw for sept instead of loading it from SD as hekate does + sdram_lp0_save_params(sdram_get_params_patched()); + + FIL fp; + if (f_stat("sd:/sept", NULL)) { + EPRINTF("On firmware 7.x+ but Sept missing.\nSkipping new key derivation..."); + return true; + } + // backup post-reboot payload + if (!f_stat("sd:/sept/payload.bin", NULL)) { + if (f_rename("sd:/sept/payload.bin", "sd:/sept/payload.bak")) { + EPRINTF("Unable to backup payload.bin."); + return false; + } + } + // write self to payload.bin to run again when sept finishes + volatile reloc_meta_t *relocator = (reloc_meta_t *)(IPL_LOAD_ADDR + RELOC_META_OFF); + u32 payload_size = relocator->end - IPL_LOAD_ADDR; + if (f_open(&fp, "sd:/sept/payload.bin", FA_CREATE_NEW | FA_WRITE)) { + EPRINTF("Unable to open /sept/payload.bin to write."); + return false; + } + gfx_printf("%kWrite self to /sept/payload.bin...", colors[(color_idx++) % 6]); + if (f_write(&fp, (u8 *)IPL_LOAD_ADDR, payload_size, NULL)) { + EPRINTF("Unable to write self to /sept/payload.bin."); + f_close(&fp); + return false; + } + gfx_printf(" done"); + f_close(&fp); + gfx_printf("%k\nRebooting to sept...\n\n", colors[(color_idx++) % 6]); + sdmmc_storage_end(&emmc_storage); + if (!reboot_to_sept((u8 *)tsec_fw, tsec_size, kb)) { + return false; + } + } else { + se_aes_key_get(se_key_acc_ctrl_get(12) == 0x6A ? 13 : 12, out_key, AES_128_KEY_SIZE); + } + + return true; +} + +static bool _derive_tsec_keys(tsec_ctxt_t *tsec_ctxt, u32 kb, key_derivation_ctx_t *keys) { + tsec_ctxt->fw = _find_tsec_fw(tsec_ctxt->pkg1); + if (!tsec_ctxt->fw) { + EPRINTF("Unable to locate TSEC firmware."); + return false; + } + + minerva_periodic_training(); + + tsec_ctxt->size = _get_tsec_fw_size((tsec_key_data_t *)(tsec_ctxt->fw + TSEC_KEY_DATA_OFFSET)); + if (tsec_ctxt->size > PKG1_MAX_SIZE) { + EPRINTF("Unexpected TSEC firmware size."); + return false; + } + + if (kb >= KB_FIRMWARE_VERSION_700) { + if (!_handle_sept(tsec_ctxt->fw, tsec_ctxt->size, kb, keys->master_key[KB_FIRMWARE_VERSION_MAX])) { + return false; + } + } else if (kb == KB_FIRMWARE_VERSION_620) { + u8 *tsec_paged = (u8 *)page_alloc(3); + memcpy(tsec_paged, tsec_ctxt->fw, tsec_ctxt->size); + tsec_ctxt->fw = tsec_paged; + } + + int res = 0; + u32 retries = 0; + + mc_disable_ahb_redirect(); + + while (tsec_query(keys->tsec_keys, kb, tsec_ctxt) < 0) { + memset(keys->tsec_keys, 0, sizeof(keys->tsec_keys)); + retries++; + if (retries > 15) { + res = -1; + break; + } + } + + mc_enable_ahb_redirect(); + + if (res < 0) { + EPRINTFARGS("ERROR %x dumping TSEC.\n", res); + return false; + } + + TPRINTFARGS("%kTSEC key(s)... ", colors[(color_idx++) % 6]); + return true; +} + +static void _derive_master_key_mariko(u32 kb, key_derivation_ctx_t *keys) { + // Relies on the SBK being properly set in slot 14 + se_aes_crypt_block_ecb(14, 0, keys->device_key_4x, device_master_key_source_kek_source); + // Relies on the Mariko KEK being properly set in slot 12 + se_aes_unwrap_key(8, 12, &mariko_master_kek_sources[kb - KB_FIRMWARE_VERSION_600]); + se_aes_crypt_block_ecb(8, 0, keys->master_key[kb], master_key_source); +} + +static void _derive_master_keys_post_620(u32 pkg1_kb, key_derivation_ctx_t *keys) { + // on firmware 6.2.0 only, the tsec_root_key is available + if (pkg1_kb == KB_FIRMWARE_VERSION_620 && _key_exists(keys->tsec_keys + AES_128_KEY_SIZE)) { + se_aes_key_set(8, keys->tsec_keys + AES_128_KEY_SIZE, AES_128_KEY_SIZE); // mkek6 = unwrap(mkeks6, tsecroot) + se_aes_crypt_block_ecb(8, 0, keys->master_kek[6], master_kek_sources[0]); + se_aes_key_set(8, keys->master_kek[6], AES_128_KEY_SIZE); // mkey = unwrap(mkek, mks) + se_aes_crypt_block_ecb(8, 0, keys->master_key[6], master_key_source); + } + + if (pkg1_kb >= KB_FIRMWARE_VERSION_620) { + // derive all lower master keys in case keyblobs are bad + // handle sept version differences + for (u32 kb = pkg1_kb == KB_FIRMWARE_VERSION_620 ? KB_FIRMWARE_VERSION_620 : KB_FIRMWARE_VERSION_MAX; kb >= KB_FIRMWARE_VERSION_620; kb--) { + for (u32 i = kb; i > 0; i--) { + se_aes_key_set(8, keys->master_key[i], AES_128_KEY_SIZE); + se_aes_crypt_block_ecb(8, 0, keys->master_key[i - 1], master_key_vectors[i]); + } + se_aes_key_set(8, keys->master_key[0], AES_128_KEY_SIZE); + se_aes_crypt_block_ecb(8, 0, keys->temp_key, master_key_vectors[0]); + if (!_key_exists(keys->temp_key)) { + break; + } + memcpy(keys->master_key[kb - 1], keys->master_key[kb], AES_128_KEY_SIZE); + memset(keys->master_key[kb], 0, AES_128_KEY_SIZE); + } + if (_key_exists(keys->temp_key)) { + EPRINTFARGS("Unable to derive master key. kb = %d.\n Check sept files on SD and retry.", pkg1_kb); + memset(keys->master_key, 0, sizeof(keys->master_key)); + } + } +} + +static void _derive_master_keys_from_keyblobs(key_derivation_ctx_t *keys) { + u8 *keyblob_block = (u8 *)calloc(KB_FIRMWARE_VERSION_600 + 1, NX_EMMC_BLOCKSIZE); + encrypted_keyblob_t *current_keyblob = (encrypted_keyblob_t *)keyblob_block; + u32 keyblob_mac[AES_128_KEY_SIZE / 4] = {0}; + + keys->sbk[0] = FUSE(FUSE_PRIVATE_KEY0); + keys->sbk[1] = FUSE(FUSE_PRIVATE_KEY1); + keys->sbk[2] = FUSE(FUSE_PRIVATE_KEY2); + keys->sbk[3] = FUSE(FUSE_PRIVATE_KEY3); + + if (keys->sbk[0] == 0xFFFFFFFF) { + u8 *aes_keys = (u8 *)calloc(0x1000, 1); + se_get_aes_keys(aes_keys + 0x800, aes_keys, AES_128_KEY_SIZE); + memcpy(keys->sbk, aes_keys + 14 * AES_128_KEY_SIZE, AES_128_KEY_SIZE); + free(aes_keys); + } + + se_aes_key_set(8, keys->tsec_keys, sizeof(keys->tsec_keys) / 2); + + if (!emummc_storage_read(&emmc_storage, KEYBLOB_OFFSET / NX_EMMC_BLOCKSIZE, KB_FIRMWARE_VERSION_600 + 1, keyblob_block)) { + EPRINTF("Unable to read keyblobs."); + } + + for (u32 i = 0; i <= KB_FIRMWARE_VERSION_600; i++, current_keyblob++) { + minerva_periodic_training(); + se_aes_crypt_block_ecb(8, 0, keys->keyblob_key[i], keyblob_key_source[i]); // temp = unwrap(kbks, tsec) + se_aes_crypt_block_ecb(14, 0, keys->keyblob_key[i], keys->keyblob_key[i]); // kbk = unwrap(temp, sbk) + se_aes_key_set(7, keys->keyblob_key[i], sizeof(keys->keyblob_key[i])); + se_aes_crypt_block_ecb(7, 0, keys->keyblob_mac_key[i], keyblob_mac_key_source); // kbm = unwrap(kbms, kbk) + if (i == 0) { + se_aes_crypt_block_ecb(7, 0, keys->device_key, per_console_key_source); // devkey = unwrap(pcks, kbk0) + se_aes_crypt_block_ecb(7, 0, keys->device_key_4x, device_master_key_source_kek_source); + } + + // verify keyblob is not corrupt + se_aes_key_set(10, keys->keyblob_mac_key[i], sizeof(keys->keyblob_mac_key[i])); + se_aes_cmac(10, keyblob_mac, sizeof(keyblob_mac), current_keyblob->iv, sizeof(current_keyblob->iv) + sizeof(keyblob_t)); + if (memcmp(current_keyblob, keyblob_mac, sizeof(keyblob_mac)) != 0) { + EPRINTFARGS("Keyblob %x corrupt.", i); + continue; + } + + // decrypt keyblobs + se_aes_key_set(6, keys->keyblob_key[i], sizeof(keys->keyblob_key[i])); + se_aes_crypt_ctr(6, &keys->keyblob[i], sizeof(keyblob_t), ¤t_keyblob->key_data, sizeof(keyblob_t), current_keyblob->iv); + + memcpy(keys->package1_key[i], keys->keyblob[i].package1_key, sizeof(keys->package1_key[i])); + memcpy(keys->master_kek[i], keys->keyblob[i].master_kek, sizeof(keys->master_kek[i])); + se_aes_key_set(7, keys->master_kek[i], sizeof(keys->master_kek[i])); + if (!_key_exists(keys->master_key[i])) { + se_aes_crypt_block_ecb(7, 0, keys->master_key[i], master_key_source); + } + } + free(keyblob_block); +} + +static void _derive_bis_keys(key_derivation_ctx_t *keys) { + /* key = unwrap(source, wrapped_key): + key_set(ks, wrapped_key), block_ecb(ks, 0, key, source) -> final key in key + */ + minerva_periodic_training(); + u32 key_generation = fuse_read_odm_keygen_rev(); + if (key_generation) + key_generation--; + + if (!(_key_exists(keys->device_key) || (key_generation && _key_exists(keys->master_key[0]) && _key_exists(keys->device_key_4x)))) { + return; + } + _get_device_key(8, keys->temp_key, key_generation, keys->device_key, keys->device_key_4x, keys->master_key[0]); + se_aes_key_set(8, keys->temp_key, AES_128_KEY_SIZE); + se_aes_unwrap_key(8, 8, retail_specific_aes_key_source); // kek = unwrap(rsaks, devkey) + se_aes_crypt_block_ecb(8, 0, keys->bis_key[0] + 0x00, bis_key_source[0] + 0x00); // bkey = unwrap(bkeys, kek) + se_aes_crypt_block_ecb(8, 0, keys->bis_key[0] + 0x10, bis_key_source[0] + 0x10); + // kek = generate_kek(bkeks, devkey, aeskek, aeskey) + _generate_kek(8, bis_kek_source, keys->temp_key, aes_kek_generation_source, aes_key_generation_source); + se_aes_crypt_block_ecb(8, 0, keys->bis_key[1] + 0x00, bis_key_source[1] + 0x00); // bkey = unwrap(bkeys, kek) + se_aes_crypt_block_ecb(8, 0, keys->bis_key[1] + 0x10, bis_key_source[1] + 0x10); + se_aes_crypt_block_ecb(8, 0, keys->bis_key[2] + 0x00, bis_key_source[2] + 0x00); + se_aes_crypt_block_ecb(8, 0, keys->bis_key[2] + 0x10, bis_key_source[2] + 0x10); + memcpy(keys->bis_key[3], keys->bis_key[2], 0x20); +} + +static void _derive_misc_keys(key_derivation_ctx_t *keys, u32 *derivable_key_count) { + if (_key_exists(keys->master_key[0])) { + _generate_kek(8, header_kek_source, keys->master_key[0], aes_kek_generation_source, aes_key_generation_source); + se_aes_crypt_block_ecb(8, 0, keys->header_key + 0x00, header_key_source + 0x00); + se_aes_crypt_block_ecb(8, 0, keys->header_key + 0x10, header_key_source + 0x10); + } + + if (_key_exists(keys->device_key) || (_key_exists(keys->master_key[0]) && _key_exists(keys->device_key_4x))) { + _get_device_key(8, keys->temp_key, 0, keys->device_key, keys->device_key_4x, keys->master_key[0]); + _generate_kek(8, save_mac_kek_source, keys->temp_key, aes_kek_generation_source, NULL); + se_aes_crypt_block_ecb(8, 0, keys->save_mac_key, save_mac_key_source); + } + + if (_key_exists(keys->master_key[*derivable_key_count])) { + *derivable_key_count = KB_FIRMWARE_VERSION_MAX + 1; + } + for (u32 i = 0; i < *derivable_key_count; i++) { + if (!_key_exists(keys->master_key[i])) + continue; + for (u32 j = 0; j < 3; j++) { + _generate_kek(8, key_area_key_sources[j], keys->master_key[i], aes_kek_generation_source, NULL); + se_aes_crypt_block_ecb(8, 0, keys->key_area_key[j][i], aes_key_generation_source); + } + se_aes_key_set(8, keys->master_key[i], AES_128_KEY_SIZE); + se_aes_crypt_block_ecb(8, 0, keys->package2_key[i], package2_key_source); + se_aes_crypt_block_ecb(8, 0, keys->titlekek[i], titlekek_source); + } + + // derive eticket_rsa_kek and ssl_rsa_kek + if (_key_exists(keys->master_key[0])) { + for (u32 i = 0; i < AES_128_KEY_SIZE; i++) + keys->temp_key[i] = aes_kek_generation_source[i] ^ aes_kek_seed_03[i]; + _generate_kek(8, eticket_rsa_kekek_source, keys->master_key[0], keys->temp_key, NULL); + se_aes_crypt_block_ecb(8, 0, keys->eticket_rsa_kek, eticket_rsa_kek_source); + + for (u32 i = 0; i < AES_128_KEY_SIZE; i++) + keys->temp_key[i] = aes_kek_generation_source[i] ^ aes_kek_seed_01[i]; + _generate_kek(8, ssl_rsa_kek_source_x, keys->master_key[0], keys->temp_key, NULL); + se_aes_crypt_block_ecb(8, 0, keys->ssl_rsa_kek, ssl_rsa_kek_source_y); + } +} + static bool _get_titlekeys_from_save(u32 buf_size, const u8 *save_mac_key, titlekey_buffer_t *titlekey_buffer, rsa_keypair_t *rsa_keypair) { FIL fp; u64 br = buf_size; @@ -130,8 +425,8 @@ static bool _get_titlekeys_from_save(u32 buf_size, const u8 *save_mac_key, title return false; } - char ticket_bin_path[0x40] = "/ticket.bin"; - char ticket_list_bin_path[0x40] = "/ticket_list.bin"; + const char ticket_bin_path[32] = "/ticket.bin"; + const char ticket_list_bin_path[32] = "/ticket_list.bin"; save_data_file_ctx_t ticket_file; if (!save_open_file(save_ctx, &ticket_file, ticket_list_bin_path, OPEN_MODE_READ)) { @@ -171,7 +466,7 @@ static bool _get_titlekeys_from_save(u32 buf_size, const u8 *save_mac_key, title offset = 0; terminator_reached = false; - u32 pct = 0, last_pct = 0; + u32 pct = 0, last_pct = 0, i = 0; while (offset < ticket_file.size && !terminator_reached) { if (!save_data_file_read(&ticket_file, &br, offset, titlekey_buffer->read_buffer, buf_size) || titlekey_buffer->read_buffer[0] == 0 || br != buf_size) break; @@ -184,10 +479,14 @@ static bool _get_titlekeys_from_save(u32 buf_size, const u8 *save_mac_key, title last_pct = pct; tui_pbar(save_x, save_y, pct, COLOR_GREEN, 0xFF155500); } - if (curr_ticket->signature_type != ticket_sig_type_rsa2048_sha256) { + if (i == file_tkey_count || curr_ticket->signature_type == 0) { terminator_reached = true; break; } + if (curr_ticket->signature_type != ticket_sig_type_rsa2048_sha256) { + i++; + continue; + } if (is_personalized) { se_rsa_exp_mod(0, curr_ticket->titlekey_block, sizeof(curr_ticket->titlekey_block), curr_ticket->titlekey_block, sizeof(curr_ticket->titlekey_block)); if (se_rsa_oaep_decode( @@ -201,6 +500,7 @@ static bool _get_titlekeys_from_save(u32 buf_size, const u8 *save_mac_key, title memcpy(titlekey_buffer->rights_ids[_titlekey_count], curr_ticket->rights_id, sizeof(titlekey_buffer->rights_ids[0])); memcpy(titlekey_buffer->titlekeys[_titlekey_count], curr_ticket->titlekey_block, sizeof(titlekey_buffer->titlekeys[0])); _titlekey_count++; + i++; } } tui_pbar(save_x, save_y, 100, COLOR_GREEN, 0xFF155500); @@ -221,36 +521,365 @@ static bool _get_titlekeys_from_save(u32 buf_size, const u8 *save_mac_key, title return true; } -#define RELOC_META_OFF 0x7C +static bool _derive_sd_seed(key_derivation_ctx_t *keys) { + FIL fp; + u32 read_bytes = 0; + char *private_path = malloc(200); + strcpy(private_path, "sd:/"); + + if (emu_cfg.nintendo_path && (emu_cfg.enabled || !h_cfg.emummc_force_disable)) { + strcat(private_path, emu_cfg.nintendo_path); + } else { + strcat(private_path, "Nintendo"); + } + strcat(private_path, "/Contents/private"); + FRESULT fr = f_open(&fp, private_path, FA_READ | FA_OPEN_EXISTING); + free(private_path); + if (fr) { + EPRINTF("Unable to open SD seed vector. Skipping."); + return false; + } + // get sd seed verification vector + if (f_read(&fp, keys->temp_key, AES_128_KEY_SIZE, &read_bytes) || read_bytes != AES_128_KEY_SIZE) { + EPRINTF("Unable to read SD seed vector. Skipping."); + f_close(&fp); + return false; + } + f_close(&fp); + + // this file is small enough that parsing the savedata properly is slower + if (f_open(&fp, "bis:/save/8000000000000043", FA_READ | FA_OPEN_EXISTING)) { + EPRINTF("Unable to open ns_appman save.\nSkipping SD seed."); + return false; + } + + u8 read_buf[0x20] __attribute__((aligned(4))) = {0}; + for (u32 i = 0x8000; i < f_size(&fp); i += 0x4000) { + if (f_lseek(&fp, i) || f_read(&fp, read_buf, 0x20, &read_bytes) || read_bytes != 0x20) + break; + if (!memcmp(keys->temp_key, read_buf, sizeof(keys->temp_key))) { + memcpy(keys->sd_seed, read_buf + 0x10, sizeof(keys->sd_seed)); + break; + } + } + f_close(&fp); + + TPRINTFARGS("%kSD Seed... ", colors[(color_idx++) % 6]); + + return true; +} + +static bool _derive_titlekeys(key_derivation_ctx_t *keys, titlekey_buffer_t *titlekey_buffer) { + if (!_key_exists(keys->eticket_rsa_kek)) { + return false; + } + + gfx_printf("%kTitlekeys... \n", colors[(color_idx++) % 6]); + + u32 buf_size = 0x4000; + rsa_keypair_t rsa_keypair = {0}; + + if (!emummc_storage_read(&emmc_storage, NX_EMMC_CALIBRATION_OFFSET / NX_EMMC_BLOCKSIZE, NX_EMMC_CALIBRATION_SIZE / NX_EMMC_BLOCKSIZE, titlekey_buffer->read_buffer)) { + EPRINTF("Unable to read PRODINFO."); + return false; + } + + se_aes_xts_crypt(1, 0, 0, 0, titlekey_buffer->read_buffer, titlekey_buffer->read_buffer, XTS_CLUSTER_SIZE, NX_EMMC_CALIBRATION_SIZE / XTS_CLUSTER_SIZE); + + nx_emmc_cal0_t *cal0 = (nx_emmc_cal0_t *)titlekey_buffer->read_buffer; + if (cal0->magic != MAGIC_CAL0) { + EPRINTF("Invalid CAL0 magic. Check BIS key 0."); + return false; + } + + // settings sysmodule manually zeroes this out below cal version 9 + u32 keypair_generation = cal0->version <= 8 ? 0 : cal0->ext_ecc_rsa2048_eticket_key_ver; + + if (keypair_generation) { + keypair_generation--; + for (u32 i = 0; i < AES_128_KEY_SIZE; i++) + keys->temp_key[i] = aes_kek_generation_source[i] ^ aes_kek_seed_03[i]; + u32 temp_device_key[AES_128_KEY_SIZE / 4] = {0}; + _get_device_key(7, temp_device_key, keypair_generation, keys->device_key, keys->device_key_4x, keys->master_key[0]); + _generate_kek(7, eticket_rsa_kekek_source, temp_device_key, keys->temp_key, NULL); + se_aes_crypt_block_ecb(7, 0, keys->eticket_rsa_kek_personalized, eticket_rsa_kek_source); + memcpy(keys->temp_key, keys->eticket_rsa_kek_personalized, sizeof(keys->temp_key)); + } else { + memcpy(keys->temp_key, keys->eticket_rsa_kek, sizeof(keys->temp_key)); + } + + se_aes_key_set(6, keys->temp_key, sizeof(keys->temp_key)); + se_aes_crypt_ctr(6, &rsa_keypair, sizeof(rsa_keypair), cal0->ext_ecc_rsa2048_eticket_key, sizeof(cal0->ext_ecc_rsa2048_eticket_key), cal0->ext_ecc_rsa2048_eticket_key_iv); + + // Check public exponent is 65537 big endian + if (_read_be_u32(rsa_keypair.public_exponent, 0) != 65537) { + EPRINTF("Invalid public exponent."); + return false; + } + + if (!_test_key_pair(rsa_keypair.public_exponent, rsa_keypair.private_exponent, rsa_keypair.modulus)) { + EPRINTF("Invalid keypair. Check eticket_rsa_kek."); + return false; + } + + se_rsa_key_set(0, rsa_keypair.modulus, sizeof(rsa_keypair.modulus), rsa_keypair.private_exponent, sizeof(rsa_keypair.private_exponent)); + + _get_titlekeys_from_save(buf_size, keys->save_mac_key, titlekey_buffer, NULL); + _get_titlekeys_from_save(buf_size, keys->save_mac_key, titlekey_buffer, &rsa_keypair); + + gfx_printf("\n%k Found %d titlekeys.\n", colors[(color_idx++) % 6], _titlekey_count); + + return true; +} + +static bool _derive_emmc_keys(key_derivation_ctx_t *keys, titlekey_buffer_t *titlekey_buffer) { + // Set BIS keys. + // PRODINFO/PRODINFOF + se_aes_key_set(0, keys->bis_key[0] + 0x00, AES_128_KEY_SIZE); + se_aes_key_set(1, keys->bis_key[0] + 0x10, AES_128_KEY_SIZE); + // SAFE + se_aes_key_set(2, keys->bis_key[1] + 0x00, AES_128_KEY_SIZE); + se_aes_key_set(3, keys->bis_key[1] + 0x10, AES_128_KEY_SIZE); + // SYSTEM/USER + se_aes_key_set(4, keys->bis_key[2] + 0x00, AES_128_KEY_SIZE); + se_aes_key_set(5, keys->bis_key[2] + 0x10, AES_128_KEY_SIZE); + + if (!emummc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP)) { + EPRINTF("Unable to set partition."); + return false; + } + // Parse eMMC GPT. + LIST_INIT(gpt); + nx_emmc_gpt_parse(&gpt, &emmc_storage); + + emmc_part_t *system_part = nx_emmc_part_find(&gpt, "SYSTEM"); + if (!system_part) { + EPRINTF("Unable to locate System partition."); + nx_emmc_gpt_free(&gpt); + return false; + } + + nx_emmc_bis_init(system_part); + + if (f_mount(&emmc_fs, "bis:", 1)) { + EPRINTF("Unable to mount system partition."); + nx_emmc_gpt_free(&gpt); + return false; + } + + if (!_derive_sd_seed(keys)) { + EPRINTF("Unable to get SD seed."); + } + + bool res = _derive_titlekeys(keys, titlekey_buffer); + if (!res) { + EPRINTF("Unable to derive titlekeys."); + } + f_mount(NULL, "bis:", 1); + nx_emmc_gpt_free(&gpt); + + return res; +} + +// The security engine supports partial key override for locked keyslots +// This allows for a manageable brute force on a PC +// Then we can recover the Mariko KEK, BEK, unique SBK and SSK +static void _save_mariko_partial_keys(char *text_buffer) { + u32 pos = 0; + u32 zeros[4] = {0}; + u8 *data = malloc(4 * AES_128_KEY_SIZE); + for (u32 ks = 12; ks < 16; ks++) { + // First, encrypt zeros with complete key + se_aes_crypt_block_ecb(ks, 1, &data[3 * AES_128_KEY_SIZE], zeros); + pos += sprintf(&text_buffer[pos], "%d\n", ks); + + // We only need to overwrite 3 of the dwords of the key + for (u32 i = 0; i < 3; i++) { + // Overwrite ith dword of key with zeros + se_aes_key_partial_set(ks, i, 0); + // Encrypt zeros with more of the key zeroed out + se_aes_crypt_block_ecb(ks, 1, &data[(2 - i) * AES_128_KEY_SIZE], zeros); + } + for (u32 i = 0; i < 4; i++) { + for (u32 j = 0; j < AES_128_KEY_SIZE; j++) + pos += sprintf(&text_buffer[pos], "%02x", data[i * AES_128_KEY_SIZE + j]); + pos += sprintf(&text_buffer[pos], "\n"); + } + } + free(data); + sd_save_to_file(text_buffer, strlen(text_buffer), "sd:/switch/partialaes.keys"); +} + +static void _save_keys_to_sd(key_derivation_ctx_t *keys, titlekey_buffer_t *titlekey_buffer, const pkg1_id_t *pkg1_id, u32 start_whole_operation_time, u32 derivable_key_count) { + char *text_buffer = NULL; + if (!sd_mount()) { + EPRINTF("Unable to mount SD."); + return; + } + + u32 text_buffer_size = MAX(_titlekey_count * sizeof(titlekey_text_buffer_t) + 1, 0x4000); + text_buffer = (char *)calloc(1, text_buffer_size); + + SAVE_KEY(aes_kek_generation_source); + SAVE_KEY(aes_key_generation_source); + SAVE_KEY(bis_kek_source); + SAVE_KEY_FAMILY_VAR(bis_key, keys->bis_key, 0); + SAVE_KEY_FAMILY(bis_key_source, 0); + SAVE_KEY_VAR(device_key, keys->device_key); + SAVE_KEY_VAR(device_key_4x, keys->device_key_4x); + SAVE_KEY_VAR(eticket_rsa_kek, keys->eticket_rsa_kek); + SAVE_KEY_VAR(eticket_rsa_kek_personalized, keys->eticket_rsa_kek_personalized); + SAVE_KEY(eticket_rsa_kek_source); + SAVE_KEY(eticket_rsa_kekek_source); + SAVE_KEY(header_kek_source); + SAVE_KEY_VAR(header_key, keys->header_key); + SAVE_KEY(header_key_source); + SAVE_KEY_FAMILY_VAR(key_area_key_application, keys->key_area_key[0], 0); + SAVE_KEY_VAR(key_area_key_application_source, key_area_key_sources[0]); + SAVE_KEY_FAMILY_VAR(key_area_key_ocean, keys->key_area_key[1], 0); + SAVE_KEY_VAR(key_area_key_ocean_source, key_area_key_sources[1]); + SAVE_KEY_FAMILY_VAR(key_area_key_system, keys->key_area_key[2], 0); + SAVE_KEY_VAR(key_area_key_system_source, key_area_key_sources[2]); + SAVE_KEY_FAMILY_VAR(keyblob, keys->keyblob, 0); + SAVE_KEY_FAMILY_VAR(keyblob_key, keys->keyblob_key, 0); + SAVE_KEY_FAMILY(keyblob_key_source, 0); + SAVE_KEY_FAMILY_VAR(keyblob_mac_key, keys->keyblob_mac_key, 0); + SAVE_KEY(keyblob_mac_key_source); + SAVE_KEY_FAMILY_VAR(master_kek, keys->master_kek, 0); + SAVE_KEY_FAMILY_VAR(master_kek_source, master_kek_sources, KB_FIRMWARE_VERSION_620); + SAVE_KEY_FAMILY_VAR(master_key, keys->master_key, 0); + SAVE_KEY(master_key_source); + SAVE_KEY_FAMILY_VAR(package1_key, keys->package1_key, 0); + SAVE_KEY_FAMILY_VAR(package2_key, keys->package2_key, 0); + SAVE_KEY(package2_key_source); + SAVE_KEY(per_console_key_source); + SAVE_KEY(retail_specific_aes_key_source); + for (u32 i = 0; i < AES_128_KEY_SIZE; i++) + keys->temp_key[i] = aes_kek_generation_source[i] ^ aes_kek_seed_03[i]; + SAVE_KEY_VAR(rsa_oaep_kek_generation_source, keys->temp_key); + for (u32 i = 0; i < AES_128_KEY_SIZE; i++) + keys->temp_key[i] = aes_kek_generation_source[i] ^ aes_kek_seed_01[i]; + SAVE_KEY_VAR(rsa_private_kek_generation_source, keys->temp_key); + SAVE_KEY(save_mac_kek_source); + SAVE_KEY_VAR(save_mac_key, keys->save_mac_key); + SAVE_KEY(save_mac_key_source); + SAVE_KEY(save_mac_sd_card_kek_source); + SAVE_KEY(save_mac_sd_card_key_source); + SAVE_KEY(sd_card_custom_storage_key_source); + SAVE_KEY(sd_card_kek_source); + SAVE_KEY(sd_card_nca_key_source); + SAVE_KEY(sd_card_save_key_source); + SAVE_KEY_VAR(sd_seed, keys->sd_seed); + SAVE_KEY_VAR(secure_boot_key, keys->sbk); + SAVE_KEY_VAR(ssl_rsa_kek, keys->ssl_rsa_kek); + SAVE_KEY(ssl_rsa_kek_source_x); + SAVE_KEY(ssl_rsa_kek_source_y); + SAVE_KEY_FAMILY_VAR(titlekek, keys->titlekek, 0); + SAVE_KEY(titlekek_source); + _save_key("tsec_key", keys->tsec_keys, AES_128_KEY_SIZE, text_buffer); + if (pkg1_id->kb == KB_FIRMWARE_VERSION_620) + _save_key("tsec_root_key", keys->tsec_keys + AES_128_KEY_SIZE, AES_128_KEY_SIZE, text_buffer); + + end_time = get_tmr_us(); + gfx_printf("\n%k Found %d keys.\n\n", colors[(color_idx++) % 6], _key_count); + gfx_printf("%kLockpick totally done in %d us\n\n", colors[(color_idx++) % 6], end_time - start_whole_operation_time); + gfx_printf("%kFound through master_key_%02x.\n\n", colors[(color_idx++) % 6], derivable_key_count - 1); + + f_mkdir("sd:/switch"); + char keyfile_path[30] = "sd:/switch/prod.keys"; + if (fuse_read_odm(4) & 3) + sprintf(&keyfile_path[11], "dev.keys"); + + FILINFO fno; + if (!sd_save_to_file(text_buffer, strlen(text_buffer), keyfile_path) && !f_stat(keyfile_path, &fno)) { + gfx_printf("%kWrote %d bytes to %s\n", colors[(color_idx++) % 6], (u32)fno.fsize, keyfile_path); + } else + EPRINTF("Unable to save keys to SD."); + + if (_titlekey_count == 0) { + free(text_buffer); + return; + } + memset(text_buffer, 0, text_buffer_size); + + titlekey_text_buffer_t *titlekey_text = (titlekey_text_buffer_t *)text_buffer; + + for (u32 i = 0; i < _titlekey_count; i++) { + for (u32 j = 0; j < AES_128_KEY_SIZE; j++) + sprintf(&titlekey_text[i].rights_id[j * 2], "%02x", titlekey_buffer->rights_ids[i][j]); + sprintf(titlekey_text[i].equals, " = "); + for (u32 j = 0; j < AES_128_KEY_SIZE; j++) + sprintf(&titlekey_text[i].titlekey[j * 2], "%02x", titlekey_buffer->titlekeys[i][j]); + sprintf(titlekey_text[i].newline, "\n"); + } + sprintf(&keyfile_path[11], "title.keys"); + if (!sd_save_to_file(text_buffer, strlen(text_buffer), keyfile_path) && !f_stat(keyfile_path, &fno)) { + gfx_printf("%kWrote %d bytes to %s\n", colors[(color_idx++) % 6], (u32)fno.fsize, keyfile_path); + } else + EPRINTF("Unable to save titlekeys to SD."); + + if (h_cfg.t210b01) { + memset(text_buffer, 0, text_buffer_size); + _save_mariko_partial_keys(text_buffer); + } + + free(text_buffer); +} + +static void _derive_keys() { + u32 start_whole_operation_time = get_tmr_us(); + sdmmc_t sdmmc; + + const pkg1_id_t *pkg1_id; + u8 *pkg1 = _read_pkg1(&sdmmc, &pkg1_id); + if (!pkg1) { + return; + } + + u32 derivable_key_count = pkg1_id->kb >= KB_FIRMWARE_VERSION_620 ? pkg1_id->kb + 1 : 6; + bool res = true; + key_derivation_ctx_t __attribute__((aligned(4))) keys = {0}; + + if (!h_cfg.t210b01) { + tsec_ctxt_t tsec_ctxt; + tsec_ctxt.pkg1 = pkg1; + res =_derive_tsec_keys(&tsec_ctxt, pkg1_id->kb, &keys); + } + free(pkg1); + if (res == false) { + return; + } + + // Master key derivation + if (h_cfg.t210b01) { + _derive_master_key_mariko(pkg1_id->kb, &keys); + _derive_master_keys_post_620(pkg1_id->kb, &keys); + } else { + _derive_master_keys_post_620(pkg1_id->kb, &keys); + _derive_master_keys_from_keyblobs(&keys); + } + + TPRINTFARGS("%kMaster keys... ", colors[(color_idx++) % 6]); + + _derive_bis_keys(&keys); + + TPRINTFARGS("%kBIS keys... ", colors[(color_idx++) % 6]); + + _derive_misc_keys(&keys, &derivable_key_count); + + titlekey_buffer_t *titlekey_buffer = (titlekey_buffer_t *)TITLEKEY_BUF_ADR; + + // BIS key for SYSTEM partition + if (_key_exists(keys.bis_key[2])) { + _derive_emmc_keys(&keys, titlekey_buffer); + } else { + EPRINTF("Missing needed BIS keys.\nSkipping SD seed and titlekeys."); + } + + _save_keys_to_sd(&keys, titlekey_buffer, pkg1_id, start_whole_operation_time, derivable_key_count); +} void dump_keys() { - u8 temp_key[0x10], - bis_key[4][0x20] = {0}, - device_key[0x10] = {0}, - device_key_4x[0x10] = {0}, - sd_seed[0x10] = {0}, - // FS-related keys - header_key[0x20] = {0}, - save_mac_key[0x10] = {0}, - // other sysmodule keys - eticket_rsa_kek[0x10] = {0}, - eticket_rsa_kek_personalized[0x10] = {0}, - ssl_rsa_kek[0x10] = {0}, - // keyblob-derived families - keyblob_key[KB_FIRMWARE_VERSION_600+1][0x10] = {0}, - keyblob_mac_key[KB_FIRMWARE_VERSION_600+1][0x10] = {0}, - package1_key[KB_FIRMWARE_VERSION_600+1][0x10] = {0}, - // master key-derived families - key_area_key[3][KB_FIRMWARE_VERSION_MAX+1][0x10] = {0}, - master_kek[KB_FIRMWARE_VERSION_MAX+1][0x10] = {0}, - master_key[KB_FIRMWARE_VERSION_MAX+1][0x10] = {0}, - package2_key[KB_FIRMWARE_VERSION_MAX+1][0x10] = {0}, - titlekek[KB_FIRMWARE_VERSION_MAX+1][0x10] = {0}; - - keyblob_t keyblob[KB_FIRMWARE_VERSION_600+1] = {0}; - - sd_mount(); - display_backlight_brightness(h_cfg.backlight, 1000); gfx_clear_grey(0x1B); gfx_con_setpos(0, 0); @@ -263,557 +892,9 @@ void dump_keys() { color_idx = 0; start_time = get_tmr_us(); - u32 begin_time = get_tmr_us(); - u32 retries = 0; - tsec_ctxt_t tsec_ctxt; - sdmmc_t sdmmc; + _derive_keys(); - if (emummc_storage_init_mmc(&emmc_storage, &sdmmc)) { - EPRINTF("Unable to init MMC."); - goto out_wait; - } - TPRINTFARGS("%kMMC init... ", colors[(color_idx++) % 6]); - - // Read package1. - u8 *pkg1 = (u8 *)malloc(PKG1_MAX_SIZE); - if (!emummc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0)) { - EPRINTF("Unable to set partition."); - goto out_wait; - } - if (!emummc_storage_read(&emmc_storage, PKG1_OFFSET / NX_EMMC_BLOCKSIZE, PKG1_MAX_SIZE / NX_EMMC_BLOCKSIZE, pkg1)) { - EPRINTF("Unable to read pkg1."); - goto out_wait; - } - const pkg1_id_t *pkg1_id = pkg1_identify(pkg1); - if (!pkg1_id) { - EPRINTF("Unknown pkg1 version.\n Make sure you have the latest Lockpick_RCM.\n If a new firmware version just came out,\n Lockpick_RCM must be updated.\n Check Github for new release."); - goto out_wait; - } - - tsec_ctxt.fw = _find_tsec_fw(pkg1); - if (!tsec_ctxt.fw) { - EPRINTF("Unable to locate TSEC firmware."); - goto out_wait; - } - - minerva_periodic_training(); - - tsec_ctxt.pkg1 = pkg1; - tsec_ctxt.size = _get_tsec_fw_size((tsec_key_data_t *)(tsec_ctxt.fw + TSEC_KEY_DATA_OFFSET)); - if (tsec_ctxt.size > PKG1_MAX_SIZE) { - EPRINTF("Unexpected TSEC firmware size."); - goto out_wait; - } - - u32 derivable_key_count = pkg1_id->kb >= KB_FIRMWARE_VERSION_620 ? pkg1_id->kb + 1 : 6; - - if (pkg1_id->kb >= KB_FIRMWARE_VERSION_700) { - sd_mount(); - if (!f_stat("sd:/sept/payload.bak", NULL)) { - if (f_unlink("sd:/sept/payload.bin")) - gfx_printf("%kNote: no payload.bin already in /sept\n", colors[(color_idx++) % 6]); - f_rename("sd:/sept/payload.bak", "sd:/sept/payload.bin"); - } - - if (!h_cfg.sept_run) { - // bundle lp0 fw for sept instead of loading it from SD as hekate does - sdram_lp0_save_params(sdram_get_params_patched()); - - FIL fp; - if (f_stat("sd:/sept", NULL)) { - EPRINTF("On firmware 7.x+ but Sept missing.\nSkipping new key derivation..."); - goto get_tsec; - } - // backup post-reboot payload - if (!f_stat("sd:/sept/payload.bin", NULL)) { - if (f_rename("sd:/sept/payload.bin", "sd:/sept/payload.bak")) { - EPRINTF("Unable to backup payload.bin."); - goto out_wait; - } - } - // write self to payload.bin to run again when sept finishes - volatile reloc_meta_t *relocator = (reloc_meta_t *)(IPL_LOAD_ADDR + RELOC_META_OFF); - u32 payload_size = relocator->end - IPL_LOAD_ADDR; - if (f_open(&fp, "sd:/sept/payload.bin", FA_CREATE_NEW | FA_WRITE)) { - EPRINTF("Unable to open /sept/payload.bin to write."); - goto out_wait; - } - gfx_printf("%kWrite self to /sept/payload.bin...", colors[(color_idx++) % 6]); - if (f_write(&fp, (u8 *)IPL_LOAD_ADDR, payload_size, NULL)) { - EPRINTF("Unable to write self to /sept/payload.bin."); - f_close(&fp); - goto out_wait; - } - gfx_printf(" done"); - f_close(&fp); - gfx_printf("%k\nFirmware 7.x or higher detected.\n\n", colors[(color_idx++) % 6]); - gfx_printf("%kRenamed /sept/payload.bin", colors[(color_idx++) % 6]); - gfx_printf("\n to /sept/payload.bak\n\n"); - gfx_printf("%kCopied self to /sept/payload.bin\n", colors[(color_idx++) % 6]); - sdmmc_storage_end(&emmc_storage); - if (!reboot_to_sept((u8 *)tsec_ctxt.fw, tsec_ctxt.size, pkg1_id->kb)) - goto out_wait; - } else { - se_aes_key_read(se_key_acc_ctrl_get(12) == 0x6A ? 13 : 12, master_key[KB_FIRMWARE_VERSION_MAX], 0x10); - } - } - -get_tsec: ; - u8 tsec_keys[0x10 * 2] = {0}; - - if (pkg1_id->kb == KB_FIRMWARE_VERSION_620) { - u8 *tsec_paged = (u8 *)page_alloc(3); - memcpy(tsec_paged, (void *)tsec_ctxt.fw, tsec_ctxt.size); - tsec_ctxt.fw = tsec_paged; - } - - int res = 0; - - mc_disable_ahb_redirect(); - - while (tsec_query(tsec_keys, pkg1_id->kb, &tsec_ctxt) < 0) { - memset(tsec_keys, 0x00, 0x20); - retries++; - if (retries > 15) { - res = -1; - break; - } - } - free(pkg1); - - mc_enable_ahb_redirect(); - - if (res < 0) { - EPRINTFARGS("ERROR %x dumping TSEC.\n", res); - goto out_wait; - } - - TPRINTFARGS("%kTSEC key(s)... ", colors[(color_idx++) % 6]); - - // Master key derivation - - // on firmware 6.2.0 only, tsec_query delivers the tsec_root_key - if (pkg1_id->kb == KB_FIRMWARE_VERSION_620 && _key_exists(tsec_keys + 0x10)) { - se_aes_key_set(8, tsec_keys + 0x10, 0x10); // mkek6 = unwrap(mkeks6, tsecroot) - se_aes_crypt_block_ecb(8, 0, master_kek[6], master_kek_sources[0]); - se_aes_key_set(8, master_kek[6], 0x10); // mkey = unwrap(mkek, mks) - se_aes_crypt_block_ecb(8, 0, master_key[6], master_key_source); - } - - if (pkg1_id->kb >= KB_FIRMWARE_VERSION_620) { - // derive all lower master keys in case keyblobs are bad - if (_key_exists(master_key[pkg1_id->kb])) { - for (u32 i = pkg1_id->kb; i > 0; i--) { - se_aes_key_set(8, master_key[i], 0x10); - se_aes_crypt_block_ecb(8, 0, master_key[i-1], master_key_vectors[i]); - } - se_aes_key_set(8, master_key[0], 0x10); - se_aes_crypt_block_ecb(8, 0, temp_key, master_key_vectors[0]); - if (_key_exists(temp_key)) { - EPRINTFARGS("Unable to derive master key. kb = %d.\n Put current sept files on SD and retry.", pkg1_id->kb); - memset(master_key, 0, sizeof(master_key)); - } - } else if (_key_exists(master_key[KB_FIRMWARE_VERSION_MAX])) { - // handle sept version differences - for (u32 kb = KB_FIRMWARE_VERSION_MAX; kb >= KB_FIRMWARE_VERSION_620; kb--) { - for (u32 i = kb; i > 0; i--) { - se_aes_key_set(8, master_key[i], 0x10); - se_aes_crypt_block_ecb(8, 0, master_key[i-1], master_key_vectors[i]); - } - se_aes_key_set(8, master_key[0], 0x10); - se_aes_crypt_block_ecb(8, 0, temp_key, master_key_vectors[0]); - if (!_key_exists(temp_key)) { - break; - } - memcpy(master_key[kb-1], master_key[kb], 0x10); - memset(master_key[kb], 0, 0x10); - } - if (_key_exists(temp_key)) { - EPRINTF("Unable to derive master keys via sept."); - memset(master_key, 0, sizeof(master_key)); - } - } - } - - u8 *keyblob_block = (u8 *)calloc(KB_FIRMWARE_VERSION_600 + 1, NX_EMMC_BLOCKSIZE); - encrypted_keyblob_t *current_keyblob = (encrypted_keyblob_t *)keyblob_block; - u8 keyblob_mac[0x10] = {0}; - u32 sbk[4] = {FUSE(FUSE_PRIVATE_KEY0), FUSE(FUSE_PRIVATE_KEY1), - FUSE(FUSE_PRIVATE_KEY2), FUSE(FUSE_PRIVATE_KEY3)}; - se_aes_key_set(8, tsec_keys, sizeof(tsec_keys) / 2); - se_aes_key_set(9, sbk, sizeof(sbk)); - - if (!emummc_storage_read(&emmc_storage, KEYBLOB_OFFSET / NX_EMMC_BLOCKSIZE, KB_FIRMWARE_VERSION_600 + 1, keyblob_block)) { - EPRINTF("Unable to read keyblob."); - } - - for (u32 i = 0; i <= KB_FIRMWARE_VERSION_600; i++, current_keyblob++) { - minerva_periodic_training(); - se_aes_crypt_block_ecb(8, 0, keyblob_key[i], keyblob_key_source[i]); // temp = unwrap(kbks, tsec) - se_aes_crypt_block_ecb(9, 0, keyblob_key[i], keyblob_key[i]); // kbk = unwrap(temp, sbk) - se_aes_key_set(7, keyblob_key[i], sizeof(keyblob_key[i])); - se_aes_crypt_block_ecb(7, 0, keyblob_mac_key[i], keyblob_mac_key_source); // kbm = unwrap(kbms, kbk) - if (i == 0) { - se_aes_crypt_block_ecb(7, 0, device_key, per_console_key_source); // devkey = unwrap(pcks, kbk0) - se_aes_crypt_block_ecb(7, 0, device_key_4x, device_master_key_source_kek_source); - } - - // verify keyblob is not corrupt - se_aes_key_set(10, keyblob_mac_key[i], sizeof(keyblob_mac_key[i])); - se_aes_cmac(10, keyblob_mac, sizeof(keyblob_mac), current_keyblob->iv, sizeof(current_keyblob->iv) + sizeof(keyblob_t)); - if (memcmp(current_keyblob, keyblob_mac, sizeof(keyblob_mac)) != 0) { - EPRINTFARGS("Keyblob %x corrupt.", i); - continue; - } - - // decrypt keyblobs - se_aes_key_set(6, keyblob_key[i], sizeof(keyblob_key[i])); - se_aes_crypt_ctr(6, &keyblob[i], sizeof(keyblob_t), ¤t_keyblob->key_data, sizeof(keyblob_t), current_keyblob->iv); - - memcpy(package1_key[i], keyblob[i].package1_key, sizeof(package1_key[i])); - memcpy(master_kek[i], keyblob[i].master_kek, sizeof(master_kek[i])); - se_aes_key_set(7, master_kek[i], sizeof(master_kek[i])); - se_aes_crypt_block_ecb(7, 0, master_key[i], master_key_source); - } - free(keyblob_block); - - TPRINTFARGS("%kMaster keys... ", colors[(color_idx++) % 6]); - - /* key = unwrap(source, wrapped_key): - key_set(ks, wrapped_key), block_ecb(ks, 0, key, source) -> final key in key - */ - minerva_periodic_training(); - u32 key_generation = fuse_read_odm_keygen_rev(); - if (key_generation) - key_generation--; - - if (_key_exists(device_key)) { - if (key_generation) { - _get_device_key(8, temp_key, key_generation, device_key_4x, master_key[0]); - } else - memcpy(temp_key, device_key, 0x10); - se_aes_key_set(8, temp_key, 0x10); - se_aes_unwrap_key(8, 8, retail_specific_aes_key_source); // kek = unwrap(rsaks, devkey) - se_aes_crypt_block_ecb(8, 0, bis_key[0] + 0x00, bis_key_source[0] + 0x00); // bkey = unwrap(bkeys, kek) - se_aes_crypt_block_ecb(8, 0, bis_key[0] + 0x10, bis_key_source[0] + 0x10); - // kek = generate_kek(bkeks, devkey, aeskek, aeskey) - _generate_kek(8, bis_kek_source, temp_key, aes_kek_generation_source, aes_key_generation_source); - se_aes_crypt_block_ecb(8, 0, bis_key[1] + 0x00, bis_key_source[1] + 0x00); // bkey = unwrap(bkeys, kek) - se_aes_crypt_block_ecb(8, 0, bis_key[1] + 0x10, bis_key_source[1] + 0x10); - se_aes_crypt_block_ecb(8, 0, bis_key[2] + 0x00, bis_key_source[2] + 0x00); - se_aes_crypt_block_ecb(8, 0, bis_key[2] + 0x10, bis_key_source[2] + 0x10); - memcpy(bis_key[3], bis_key[2], 0x20); - } - - TPRINTFARGS("%kFS keys... ", colors[(color_idx++) % 6]); - - if (_key_exists(master_key[0])) { - _generate_kek(8, header_kek_source, master_key[0], aes_kek_generation_source, aes_key_generation_source); - se_aes_crypt_block_ecb(8, 0, header_key + 0x00, header_key_source + 0x00); - se_aes_crypt_block_ecb(8, 0, header_key + 0x10, header_key_source + 0x10); - } - - if (_key_exists(device_key)) { - _generate_kek(8, save_mac_kek_source, device_key, aes_kek_generation_source, NULL); - se_aes_crypt_block_ecb(8, 0, save_mac_key, save_mac_key_source); - } - - if (_key_exists(master_key[derivable_key_count])) { - derivable_key_count = KB_FIRMWARE_VERSION_MAX + 1; - } - for (u32 i = 0; i < derivable_key_count; i++) { - if (!_key_exists(master_key[i])) - continue; - for (u32 j = 0; j < 3; j++) { - _generate_kek(8, key_area_key_sources[j], master_key[i], aes_kek_generation_source, NULL); - se_aes_crypt_block_ecb(8, 0, key_area_key[j][i], aes_key_generation_source); - } - se_aes_key_set(8, master_key[i], 0x10); - se_aes_crypt_block_ecb(8, 0, package2_key[i], package2_key_source); - se_aes_crypt_block_ecb(8, 0, titlekek[i], titlekek_source); - } - - if (!_key_exists(header_key) || !_key_exists(bis_key[2])) - { - EPRINTF("Missing FS keys. Skipping ES/SSL keys."); - goto key_output; - } - - FILINFO fno; - FIL fp; - u32 read_bytes = 0; - - // derive eticket_rsa_kek and ssl_rsa_kek - if (_key_exists(master_key[0])) { - for (u32 i = 0; i < 0x10; i++) - temp_key[i] = aes_kek_generation_source[i] ^ aes_kek_seed_03[i]; - _generate_kek(7, eticket_rsa_kekek_source, master_key[0], temp_key, NULL); - se_aes_crypt_block_ecb(7, 0, eticket_rsa_kek, eticket_rsa_kek_source); - - for (u32 i = 0; i < 0x10; i++) - temp_key[i] = aes_kek_generation_source[i] ^ aes_kek_seed_01[i]; - _generate_kek(7, ssl_rsa_kek_source_x, master_key[0], temp_key, NULL); - se_aes_crypt_block_ecb(7, 0, ssl_rsa_kek, ssl_rsa_kek_source_y); - } - - // Set BIS keys. - // PRODINFO/PRODINFOF - se_aes_key_set(0, bis_key[0] + 0x00, 0x10); - se_aes_key_set(1, bis_key[0] + 0x10, 0x10); - // SAFE - se_aes_key_set(2, bis_key[1] + 0x00, 0x10); - se_aes_key_set(3, bis_key[1] + 0x10, 0x10); - // SYSTEM/USER - se_aes_key_set(4, bis_key[2] + 0x00, 0x10); - se_aes_key_set(5, bis_key[2] + 0x10, 0x10); - - // Set header key for NCA decryption. - se_aes_key_set(8, header_key + 0x00, 0x10); - se_aes_key_set(9, header_key + 0x10, 0x10); - - if (!emummc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP)) { - EPRINTF("Unable to set partition."); - goto out_wait; - } - // Parse eMMC GPT. - LIST_INIT(gpt); - nx_emmc_gpt_parse(&gpt, &emmc_storage); - - emmc_part_t *system_part = nx_emmc_part_find(&gpt, "SYSTEM"); - if (!system_part) { - EPRINTF("Unable to locate System partition."); - goto key_output; - } - - nx_emmc_bis_init(system_part); - - if (f_mount(&emmc_fs, "bis:", 1)) { - EPRINTF("Unable to mount system partition."); - goto key_output; - } - - char private_path[200] = "sd:/"; - if (emu_cfg.nintendo_path && (emu_cfg.enabled || !h_cfg.emummc_force_disable)) { - strcat(private_path, emu_cfg.nintendo_path); - } else { - strcat(private_path, "Nintendo"); - } - strcat(private_path, "/Contents/private"); - if (f_open(&fp, private_path, FA_READ | FA_OPEN_EXISTING)) { - EPRINTF("Unable to open SD seed vector. Skipping."); - goto get_titlekeys; - } - // get sd seed verification vector - if (f_read(&fp, temp_key, 0x10, &read_bytes) || read_bytes != 0x10) { - EPRINTF("Unable to read SD seed vector. Skipping."); - f_close(&fp); - goto get_titlekeys; - } - f_close(&fp); - - // this file is so small that parsing the savedata properly would take longer - if (f_open(&fp, "bis:/save/8000000000000043", FA_READ | FA_OPEN_EXISTING)) { - EPRINTF("Unable to open ns_appman save.\nSkipping SD seed."); - goto get_titlekeys; - } - - u8 read_buf[0x20] = {0}; - for (u32 i = 0x8000; i < f_size(&fp); i += 0x4000) { - if (f_lseek(&fp, i) || f_read(&fp, read_buf, 0x20, &read_bytes) || read_bytes != 0x20) - break; - if (!memcmp(temp_key, read_buf, sizeof(temp_key))) { - memcpy(sd_seed, read_buf + 0x10, sizeof(sd_seed)); - break; - } - } - f_close(&fp); - - TPRINTFARGS("%kSD Seed... ", colors[(color_idx++) % 6]); - -get_titlekeys: - if (!_key_exists(eticket_rsa_kek)) - goto dismount; - - gfx_printf("%kTitlekeys... \n", colors[(color_idx++) % 6]); - - u32 buf_size = 0x4000; - rsa_keypair_t rsa_keypair = {0}; - - titlekey_buffer_t *titlekey_buffer = (titlekey_buffer_t *)TITLEKEY_BUF_ADR; - - if (!emummc_storage_read(&emmc_storage, NX_EMMC_CALIBRATION_OFFSET / NX_EMMC_BLOCKSIZE, NX_EMMC_CALIBRATION_SIZE / NX_EMMC_BLOCKSIZE, titlekey_buffer->read_buffer)) { - EPRINTF("Unable to read PRODINFO."); - goto dismount; - } - - se_aes_xts_crypt(1, 0, 0, 0, titlekey_buffer->read_buffer, titlekey_buffer->read_buffer, XTS_CLUSTER_SIZE, NX_EMMC_CALIBRATION_SIZE / XTS_CLUSTER_SIZE); - - nx_emmc_cal0_t *cal0 = (nx_emmc_cal0_t *)titlekey_buffer->read_buffer; - if (cal0->magic != 0x304C4143) { - EPRINTF("Invalid CAL0 magic. Check BIS key 0."); - goto dismount; - } - - // settings sysmodule manually zeroes this out below cal version 9 - u32 keypair_generation = cal0->version <= 8 ? 0 : cal0->ext_ecc_rsa2048_eticket_key_ver; - - if (keypair_generation) { - keypair_generation--; - for (u32 i = 0; i < 0x10; i++) - temp_key[i] = aes_kek_generation_source[i] ^ aes_kek_seed_03[i]; - u8 temp_device_key[0x10] = {0}; - _get_device_key(7, temp_device_key, keypair_generation, device_key_4x, master_key[0]); - _generate_kek(7, eticket_rsa_kekek_source, temp_device_key, temp_key, NULL); - se_aes_crypt_block_ecb(7, 0, eticket_rsa_kek_personalized, eticket_rsa_kek_source); - memcpy(temp_key, eticket_rsa_kek_personalized, sizeof(temp_key)); - } else { - memcpy(temp_key, eticket_rsa_kek, sizeof(temp_key)); - } - - se_aes_key_set(6, temp_key, sizeof(temp_key)); - se_aes_crypt_ctr(6, &rsa_keypair, sizeof(rsa_keypair), cal0->ext_ecc_rsa2048_eticket_key, sizeof(cal0->ext_ecc_rsa2048_eticket_key), cal0->ext_ecc_rsa2048_eticket_key_iv); - - // Check public exponent is 65537 big endian - if (_read_be_u32(rsa_keypair.public_exponent, 0) != 65537) { - EPRINTF("Invalid public exponent."); - goto dismount; - } - - if (!_test_key_pair(rsa_keypair.public_exponent, rsa_keypair.private_exponent, rsa_keypair.modulus)) { - EPRINTF("Invalid keypair. Check eticket_rsa_kek."); - goto dismount; - } - - se_rsa_key_set(0, rsa_keypair.modulus, sizeof(rsa_keypair.modulus), rsa_keypair.private_exponent, sizeof(rsa_keypair.private_exponent)); - - _get_titlekeys_from_save(buf_size, save_mac_key, titlekey_buffer, NULL); - _get_titlekeys_from_save(buf_size, save_mac_key, titlekey_buffer, &rsa_keypair); - - gfx_printf("\n%k Found %d titlekeys.\n", colors[(color_idx++) % 6], _titlekey_count); - -dismount: ; - - f_mount(NULL, "bis:", 1); - nx_emmc_gpt_free(&gpt); - -key_output: ; - char *text_buffer = NULL; - if (!sd_mount()) { - EPRINTF("Unable to mount SD."); - goto free_buffers; - } - - typedef struct { - char rights_id[0x20]; - char equals[3]; - char titlekey[0x20]; - char newline[1]; - } titlekey_text_buffer_t; - - u32 text_buffer_size = MAX(_titlekey_count * sizeof(titlekey_text_buffer_t) + 1, 0x4000); - text_buffer = (char *)calloc(1, text_buffer_size); - - SAVE_KEY(aes_kek_generation_source); - SAVE_KEY(aes_key_generation_source); - SAVE_KEY(bis_kek_source); - SAVE_KEY_FAMILY(bis_key, 0); - SAVE_KEY_FAMILY(bis_key_source, 0); - SAVE_KEY(device_key); - SAVE_KEY(device_key_4x); - SAVE_KEY(eticket_rsa_kek); - SAVE_KEY(eticket_rsa_kek_personalized); - SAVE_KEY(eticket_rsa_kek_source); - SAVE_KEY(eticket_rsa_kekek_source); - SAVE_KEY(header_kek_source); - SAVE_KEY(header_key); - SAVE_KEY(header_key_source); - SAVE_KEY_FAMILY_VAR(key_area_key_application, key_area_key[0], 0); - SAVE_KEY_VAR(key_area_key_application_source, key_area_key_sources[0]); - SAVE_KEY_FAMILY_VAR(key_area_key_ocean, key_area_key[1], 0); - SAVE_KEY_VAR(key_area_key_ocean_source, key_area_key_sources[1]); - SAVE_KEY_FAMILY_VAR(key_area_key_system, key_area_key[2], 0); - SAVE_KEY_VAR(key_area_key_system_source, key_area_key_sources[2]); - SAVE_KEY_FAMILY(keyblob, 0); - SAVE_KEY_FAMILY(keyblob_key, 0); - SAVE_KEY_FAMILY(keyblob_key_source, 0); - SAVE_KEY_FAMILY(keyblob_mac_key, 0); - SAVE_KEY(keyblob_mac_key_source); - SAVE_KEY_FAMILY(master_kek, 0); - SAVE_KEY_FAMILY_VAR(master_kek_source, master_kek_sources, KB_FIRMWARE_VERSION_620); - SAVE_KEY_FAMILY(master_key, 0); - SAVE_KEY(master_key_source); - SAVE_KEY_FAMILY(package1_key, 0); - SAVE_KEY_FAMILY(package2_key, 0); - SAVE_KEY(package2_key_source); - SAVE_KEY(per_console_key_source); - SAVE_KEY(retail_specific_aes_key_source); - for (u32 i = 0; i < 0x10; i++) - temp_key[i] = aes_kek_generation_source[i] ^ aes_kek_seed_03[i]; - SAVE_KEY_VAR(rsa_oaep_kek_generation_source, temp_key); - for (u32 i = 0; i < 0x10; i++) - temp_key[i] = aes_kek_generation_source[i] ^ aes_kek_seed_01[i]; - SAVE_KEY_VAR(rsa_private_kek_generation_source, temp_key); - SAVE_KEY(save_mac_kek_source); - SAVE_KEY(save_mac_key); - SAVE_KEY(save_mac_key_source); - SAVE_KEY(save_mac_sd_card_kek_source); - SAVE_KEY(save_mac_sd_card_key_source); - SAVE_KEY(sd_card_custom_storage_key_source); - SAVE_KEY(sd_card_kek_source); - SAVE_KEY(sd_card_nca_key_source); - SAVE_KEY(sd_card_save_key_source); - SAVE_KEY(sd_seed); - SAVE_KEY_VAR(secure_boot_key, sbk); - SAVE_KEY(ssl_rsa_kek); - SAVE_KEY(ssl_rsa_kek_source_x); - SAVE_KEY(ssl_rsa_kek_source_y); - SAVE_KEY_FAMILY(titlekek, 0); - SAVE_KEY(titlekek_source); - _save_key("tsec_key", tsec_keys, 0x10, text_buffer); - if (pkg1_id->kb == KB_FIRMWARE_VERSION_620) - _save_key("tsec_root_key", tsec_keys + 0x10, 0x10, text_buffer); - - end_time = get_tmr_us(); - gfx_printf("\n%k Found %d keys.\n\n", colors[(color_idx++) % 6], _key_count); - gfx_printf("%kLockpick totally done in %d us\n\n", colors[(color_idx++) % 6], end_time - begin_time); - gfx_printf("%kFound through master_key_%02x.\n\n", colors[(color_idx++) % 6], derivable_key_count - 1); - - f_mkdir("sd:/switch"); - char keyfile_path[30] = "sd:/switch/"; - if (!(fuse_read_odm(4) & 3)) - sprintf(&keyfile_path[11], "prod.keys"); - else - sprintf(&keyfile_path[11], "dev.keys"); - if (!sd_save_to_file(text_buffer, strlen(text_buffer), keyfile_path) && !f_stat(keyfile_path, &fno)) { - gfx_printf("%kWrote %d bytes to %s\n", colors[(color_idx++) % 6], (u32)fno.fsize, keyfile_path); - } else - EPRINTF("Unable to save keys to SD."); - - if (_titlekey_count == 0) - goto free_buffers; - memset(text_buffer, 0, text_buffer_size); - - titlekey_text_buffer_t *titlekey_text = (titlekey_text_buffer_t *)text_buffer; - - for (u32 i = 0; i < _titlekey_count; i++) { - for (u32 j = 0; j < 0x10; j++) - sprintf(&titlekey_text[i].rights_id[j * 2], "%02x", titlekey_buffer->rights_ids[i][j]); - sprintf(titlekey_text[i].equals, " = "); - for (u32 j = 0; j < 0x10; j++) - sprintf(&titlekey_text[i].titlekey[j * 2], "%02x", titlekey_buffer->titlekeys[i][j]); - sprintf(titlekey_text[i].newline, "\n"); - } - sprintf(&keyfile_path[11], "title.keys"); - if (!sd_save_to_file(text_buffer, strlen(text_buffer), keyfile_path) && !f_stat(keyfile_path, &fno)) { - gfx_printf("%kWrote %d bytes to %s\n", colors[(color_idx++) % 6], (u32)fno.fsize, keyfile_path); - } else - EPRINTF("Unable to save titlekeys to SD."); - -free_buffers: - free(text_buffer); - -out_wait: emummc_load_cfg(); // Ignore whether emummc is enabled. h_cfg.emummc_force_disable = emu_cfg.sector == 0 && !emu_cfg.path; @@ -836,48 +917,57 @@ static void _save_key(const char *name, const void *data, u32 len, char *outbuf) } static void _save_key_family(const char *name, const void *data, u32 start_key, u32 num_keys, u32 len, char *outbuf) { - char temp_name[0x40] = {0}; + char *temp_name = calloc(1, 0x40); for (u32 i = 0; i < num_keys; i++) { sprintf(temp_name, "%s_%02x", name, i + start_key); _save_key(temp_name, data + i * len, len, outbuf); } + free(temp_name); } static void _generate_kek(u32 ks, const void *key_source, void *master_key, const void *kek_seed, const void *key_seed) { if (!_key_exists(key_source) || !_key_exists(master_key) || !_key_exists(kek_seed)) return; - se_aes_key_set(ks, master_key, 0x10); + se_aes_key_set(ks, master_key, AES_128_KEY_SIZE); se_aes_unwrap_key(ks, ks, kek_seed); se_aes_unwrap_key(ks, ks, key_source); if (key_seed && _key_exists(key_seed)) se_aes_unwrap_key(ks, ks, key_seed); } -static void _get_device_key(u32 ks, void *out_device_key, u32 revision, const void *device_key, const void *master_key) { - if (revision < KB_FIRMWARE_VERSION_400) - memcpy(out_device_key, device_key, 0x10); +static void _get_device_key(u32 ks, void *out_device_key, u32 revision, const void *device_key, const void *new_device_key, const void *master_key) { + if (revision == KB_FIRMWARE_VERSION_100_200 && !h_cfg.t210b01) { + memcpy(out_device_key, device_key, AES_128_KEY_SIZE); + return; + } - revision -= KB_FIRMWARE_VERSION_400; - u8 temp_key[0x10] = {0}; - se_aes_key_set(ks, device_key, 0x10); - se_aes_crypt_ecb(ks, 0, temp_key, 0x10, device_master_key_source_sources[revision], 0x10); - se_aes_key_set(ks, master_key, 0x10); + if (revision >= KB_FIRMWARE_VERSION_400) { + revision -= KB_FIRMWARE_VERSION_400; + } else { + revision = 0; + } + u32 temp_key[AES_128_KEY_SIZE / 4] = {0}; + se_aes_key_set(ks, new_device_key, AES_128_KEY_SIZE); + se_aes_crypt_ecb(ks, 0, temp_key, AES_128_KEY_SIZE, device_master_key_source_sources[revision], AES_128_KEY_SIZE); + se_aes_key_set(ks, master_key, AES_128_KEY_SIZE); se_aes_unwrap_key(ks, ks, device_master_kek_sources[revision]); - se_aes_crypt_ecb(ks, 0, out_device_key, 0x10, temp_key, 0x10); + se_aes_crypt_ecb(ks, 0, out_device_key, AES_128_KEY_SIZE, temp_key, AES_128_KEY_SIZE); } static bool _test_key_pair(const void *public_exponent, const void *private_exponent, const void *modulus) { - u8 plaintext[0x100] = {0}, ciphertext[0x100] = {0}, work[0x100] = {0}; + u8 plaintext[RSA_2048_KEY_SIZE] __attribute__((aligned(4))) = {0}, + ciphertext[RSA_2048_KEY_SIZE] __attribute__((aligned(4))) = {0}, + work[RSA_2048_KEY_SIZE] __attribute__((aligned(4))) = {0}; // 0xCAFEBABE plaintext[0xfc] = 0xca; plaintext[0xfd] = 0xfe; plaintext[0xfe] = 0xba; plaintext[0xff] = 0xbe; - se_rsa_key_set(0, modulus, 0x100, private_exponent, 0x100); - se_rsa_exp_mod(0, ciphertext, 0x100, plaintext, 0x100); + se_rsa_key_set(0, modulus, RSA_2048_KEY_SIZE, private_exponent, RSA_2048_KEY_SIZE); + se_rsa_exp_mod(0, ciphertext, RSA_2048_KEY_SIZE, plaintext, RSA_2048_KEY_SIZE); - se_rsa_key_set(0, modulus, 0x100, public_exponent, 4); - se_rsa_exp_mod(0, work, 0x100, ciphertext, 0x100); + se_rsa_key_set(0, modulus, RSA_2048_KEY_SIZE, public_exponent, 4); + se_rsa_exp_mod(0, work, RSA_2048_KEY_SIZE, ciphertext, RSA_2048_KEY_SIZE); - return !memcmp(plaintext, work, 0x100); + return !memcmp(plaintext, work, RSA_2048_KEY_SIZE); } diff --git a/source/keys/keys.h b/source/keys/keys.h index ae6ead4..b3018a5 100644 --- a/source/keys/keys.h +++ b/source/keys/keys.h @@ -19,13 +19,18 @@ #include +#include "../hos/hos.h" + +#define AES_128_KEY_SIZE 16 +#define RSA_2048_KEY_SIZE 256 + // only tickets of type Rsa2048Sha256 are expected typedef struct { u32 signature_type; // always 0x10004 - u8 signature[0x100]; + u8 signature[RSA_2048_KEY_SIZE]; u8 sig_padding[0x3C]; char issuer[0x40]; - u8 titlekey_block[0x100]; + u8 titlekey_block[RSA_2048_KEY_SIZE]; u8 format_version; u8 titlekey_type; u16 ticket_version; @@ -59,8 +64,8 @@ typedef struct { } titlekey_buffer_t; typedef struct { - u8 private_exponent[0x100]; - u8 modulus[0x100]; + u8 private_exponent[RSA_2048_KEY_SIZE]; + u8 modulus[RSA_2048_KEY_SIZE]; u8 public_exponent[4]; u8 reserved[0x14]; u64 device_id; @@ -68,9 +73,9 @@ typedef struct { } rsa_keypair_t; typedef struct { - u8 master_kek[0x10]; + u8 master_kek[AES_128_KEY_SIZE]; u8 data[0x70]; - u8 package1_key[0x10]; + u8 package1_key[AES_128_KEY_SIZE]; } keyblob_t; typedef struct { @@ -80,6 +85,41 @@ typedef struct { u8 unused[0x150]; } encrypted_keyblob_t; +typedef struct { + u8 temp_key[AES_128_KEY_SIZE], + bis_key[4][AES_128_KEY_SIZE * 2], + device_key[AES_128_KEY_SIZE], + device_key_4x[AES_128_KEY_SIZE], + sd_seed[AES_128_KEY_SIZE], + // FS-related keys + header_key[AES_128_KEY_SIZE * 2], + save_mac_key[AES_128_KEY_SIZE], + // other sysmodule keys + eticket_rsa_kek[AES_128_KEY_SIZE], + eticket_rsa_kek_personalized[AES_128_KEY_SIZE], + ssl_rsa_kek[AES_128_KEY_SIZE], + // keyblob-derived families + keyblob_key[KB_FIRMWARE_VERSION_600 + 1][AES_128_KEY_SIZE], + keyblob_mac_key[KB_FIRMWARE_VERSION_600 + 1][AES_128_KEY_SIZE], + package1_key[KB_FIRMWARE_VERSION_600 + 1][AES_128_KEY_SIZE], + // master key-derived families + key_area_key[3][KB_FIRMWARE_VERSION_MAX + 1][AES_128_KEY_SIZE], + master_kek[KB_FIRMWARE_VERSION_MAX + 1][AES_128_KEY_SIZE], + master_key[KB_FIRMWARE_VERSION_MAX + 1][AES_128_KEY_SIZE], + package2_key[KB_FIRMWARE_VERSION_MAX + 1][AES_128_KEY_SIZE], + titlekek[KB_FIRMWARE_VERSION_MAX + 1][AES_128_KEY_SIZE], + tsec_keys[AES_128_KEY_SIZE * 2]; + u32 sbk[4]; + keyblob_t keyblob[KB_FIRMWARE_VERSION_600 + 1]; +} key_derivation_ctx_t; + +typedef struct { + char rights_id[0x20]; + char equals[3]; + char titlekey[0x20]; + char newline[1]; +} titlekey_text_buffer_t; + #define TPRINTF(text) \ end_time = get_tmr_us(); \ gfx_printf(text" done in %d us\n", end_time - start_time); \ diff --git a/source/main.c b/source/main.c index f88a91c..5a7d03a 100644 --- a/source/main.c +++ b/source/main.c @@ -31,7 +31,7 @@ #include #include #include -#include "soc/hw_init.h" +#include #include "storage/emummc.h" #include "storage/nx_emmc.h" #include @@ -126,12 +126,12 @@ int launch_payload(char *path) { reloc_patcher(PATCHED_RELOC_ENTRY, EXT_PAYLOAD_ADDR, ALIGN(size, 0x10)); - reconfig_hw_workaround(false, byte_swap_32(*(u32 *)(buf + size - sizeof(u32)))); + hw_reinit_workaround(false, byte_swap_32(*(u32 *)(buf + size - sizeof(u32)))); } else { reloc_patcher(PATCHED_RELOC_ENTRY, EXT_PAYLOAD_ADDR, 0x7000); - reconfig_hw_workaround(true, 0); + hw_reinit_workaround(true, 0); } // Some cards (Sandisk U1), do not like a fast power cycle. Wait min 100ms. @@ -297,27 +297,30 @@ void _get_key_generations(char *sysnand_label, char *emunand_label) sdmmc_t sdmmc; sdmmc_storage_t storage; sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400); - u8 *bct = (u8 *)malloc(NX_EMMC_BLOCKSIZE); + u8 *pkg1 = (u8 *)malloc(PKG1_MAX_SIZE); sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0); - sdmmc_storage_read(&storage, 0x2200 / NX_EMMC_BLOCKSIZE, 1, bct); + sdmmc_storage_read(&storage, PKG1_OFFSET / NX_EMMC_BLOCKSIZE, PKG1_MAX_SIZE / NX_EMMC_BLOCKSIZE, pkg1); sdmmc_storage_end(&storage); - sprintf(sysnand_label + 36, "% 3d", bct[0x130] - 1); + u32 pk1_offset = h_cfg.t210b01 ? sizeof(bl_hdr_t210b01_t) : 0; // Skip T210B01 OEM header. + const pkg1_id_t *pkg1_id = pkg1_identify(pkg1 + pk1_offset); + sprintf(sysnand_label + 36, "% 3d", pkg1_id->kb); ment_top[0].caption = sysnand_label; if (h_cfg.emummc_force_disable) { - free(bct); + free(pkg1); return; } emummc_storage_init_mmc(&storage, &sdmmc); - memset(bct, 0, NX_EMMC_BLOCKSIZE); + memset(pkg1, 0, PKG1_MAX_SIZE); emummc_storage_set_mmc_partition(&storage, EMMC_BOOT0); - emummc_storage_read(&storage, 0x2200 / NX_EMMC_BLOCKSIZE, 1, bct); + emummc_storage_read(&storage, PKG1_OFFSET / NX_EMMC_BLOCKSIZE, PKG1_MAX_SIZE / NX_EMMC_BLOCKSIZE, pkg1); emummc_storage_end(&storage); - sprintf(emunand_label + 36, "% 3d", bct[0x130] - 1); - free(bct); + pkg1_id = pkg1_identify(pkg1 + pk1_offset); + sprintf(emunand_label + 36, "% 3d", pkg1_id->kb); + free(pkg1); ment_top[1].caption = emunand_label; } @@ -326,7 +329,7 @@ extern void pivot_stack(u32 stack_top); void ipl_main() { // Do initial HW configuration. This is compatible with consecutive reruns without a reset. - config_hw(); + hw_init(); // Pivot the stack so we have enough space. pivot_stack(IPL_STACK_TOP); @@ -342,9 +345,12 @@ void ipl_main() // Set bootloader's default configuration. set_default_configuration(); - sd_mount(); + // Mount SD Card. + h_cfg.errors |= !sd_mount() ? ERR_SD_BOOT_EN : 0; - minerva_init(); + // Train DRAM and switch to max frequency. + if (minerva_init()) //!TODO: Add Tegra210B01 support to minerva. + h_cfg.errors |= ERR_LIBSYS_MTC; minerva_change_freq(FREQ_1600); display_init(); @@ -381,6 +387,19 @@ void ipl_main() ment_top[1].handler = NULL; } + // Grey out reboot to RCM option if on Mariko or patched console. + if (h_cfg.t210b01 || h_cfg.rcm_patched) + { + ment_top[6].type = MENT_CAPTION; + ment_top[6].color = 0xFF555555; + ment_top[6].handler = NULL; + } + + if (h_cfg.rcm_patched) + { + ment_top[5].handler = reboot_full; + } + // Update key generations listed in menu. _get_key_generations((char *)ment_top[0].caption, (char *)ment_top[1].caption); diff --git a/source/storage/emummc.c b/source/storage/emummc.c index 5253edc..baa4560 100644 --- a/source/storage/emummc.c +++ b/source/storage/emummc.c @@ -136,7 +136,7 @@ int emummc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc) FILINFO fno; emu_cfg.active_part = 0; - // Always init eMMC even when in emuMMC. eMMC is needed from theh emuMMC driver anyway. + // Always init eMMC even when in emuMMC. eMMC is needed from the emuMMC driver anyway. if (!sdmmc_storage_init_mmc(storage, sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400)) return 2; @@ -276,7 +276,7 @@ int emummc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition) emu_cfg.active_part = partition; if (!emu_cfg.enabled || h_cfg.emummc_force_disable) - return sdmmc_storage_set_mmc_partition(storage, partition); + sdmmc_storage_set_mmc_partition(storage, partition); else if (emu_cfg.sector) return 1; else diff --git a/source/storage/nx_emmc_bis.c b/source/storage/nx_emmc_bis.c index 243a3ee..a2d19c2 100644 --- a/source/storage/nx_emmc_bis.c +++ b/source/storage/nx_emmc_bis.c @@ -95,7 +95,7 @@ static int _nx_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, u32 enc, u8 *tweak, for (u32 i = 0; i < (tweak_exp << 5); i++) _gf256_mul_x_le(tweak); - u8 orig_tweak[0x10]; + u8 orig_tweak[0x10] __attribute__((aligned(4))); memcpy(orig_tweak, tweak, 0x10); // We are assuming a 0x10-aligned sector size in this implementation. @@ -131,7 +131,7 @@ static int nx_emmc_bis_write_block(u32 sector, u32 count, void *buff, bool force if (!system_part) return 3; // Not ready. - u8 tweak[0x10]; + u8 tweak[0x10] __attribute__((aligned(4))); u32 cluster = sector / SECTORS_PER_CLUSTER; u32 aligned_sector = cluster * SECTORS_PER_CLUSTER; u32 sector_index_in_cluster = sector % SECTORS_PER_CLUSTER; @@ -186,8 +186,8 @@ static int nx_emmc_bis_read_block(u32 sector, u32 count, void *buff) static u32 prev_cluster = -1; static u32 prev_sector = 0; - static u8 tweak[0x10]; - u8 cache_tweak[0x10]; + static u8 tweak[0x10] __attribute__((aligned(4))); + u8 cache_tweak[0x10] __attribute__((aligned(4))); u32 tweak_exp = 0; bool regen_tweak = true; diff --git a/source/storage/nx_emmc_bis.h b/source/storage/nx_emmc_bis.h index 3a6aeca..4eb5d82 100644 --- a/source/storage/nx_emmc_bis.h +++ b/source/storage/nx_emmc_bis.h @@ -225,6 +225,7 @@ typedef struct _nx_emmc_cal0_t u8 console_6axis_sensor_mount_type; } __attribute__((packed)) nx_emmc_cal0_t; +#define MAGIC_CAL0 0x304C4143 #define NX_EMMC_CALIBRATION_OFFSET 0x4400 #define NX_EMMC_CALIBRATION_SIZE 0x8000 #define XTS_CLUSTER_SIZE 0x4000