1
0
Fork 0
mirror of https://github.com/s1204IT/Lockpick_RCM.git synced 2024-11-26 03:32:13 +00:00

Update to hekate bdk 5.6.0

This commit is contained in:
shchmue 2021-08-28 14:10:33 -06:00
parent a89e9b4d7f
commit f2f3c5daf0
43 changed files with 1530 additions and 1533 deletions

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer * Copyright (c) 2018-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -22,6 +22,7 @@
#include <power/max7762x.h> #include <power/max7762x.h>
#include <mem/heap.h> #include <mem/heap.h>
#include <soc/clock.h> #include <soc/clock.h>
#include <soc/fuse.h>
#include <soc/gpio.h> #include <soc/gpio.h>
#include <soc/hw_init.h> #include <soc/hw_init.h>
#include <soc/i2c.h> #include <soc/i2c.h>
@ -35,6 +36,7 @@
extern volatile nyx_storage_t *nyx_str; extern volatile nyx_storage_t *nyx_str;
static u32 _display_id = 0; static u32 _display_id = 0;
static bool nx_aula = false;
static void _display_panel_and_hw_end(bool no_panel_deinit); static void _display_panel_and_hw_end(bool no_panel_deinit);
@ -91,7 +93,7 @@ int display_dsi_read(u8 cmd, u32 len, void *data, bool video_enabled)
// Wait for vblank before starting the transfer. // Wait for vblank before starting the transfer.
DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = DC_CMD_INT_FRAME_END_INT; // Clear interrupt. 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) while (!(DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) & DC_CMD_INT_FRAME_END_INT))
; ;
} }
@ -134,19 +136,22 @@ int display_dsi_read(u8 cmd, u32 len, void *data, bool video_enabled)
case DCS_2_BYTE_SHORT_RD_RES: case DCS_2_BYTE_SHORT_RD_RES:
memcpy(data, &fifo[2], 2); memcpy(data, &fifo[2], 2);
break; break;
case ACK_ERROR_RES: case ACK_ERROR_RES:
default: default:
res = 1; res = 1;
break; break;
} }
} }
else
res = 1;
// Disable host cmd packets during video and restore host control. // Disable host cmd packets during video and restore host control.
if (video_enabled) if (video_enabled)
{ {
// Wait for vblank before reseting sync points. // Wait for vblank before reseting sync points.
DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = DC_CMD_INT_FRAME_END_INT; // Clear interrupt. 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) while (!(DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) & DC_CMD_INT_FRAME_END_INT))
; ;
// Reset all states of syncpt block. // Reset all states of syncpt block.
@ -181,7 +186,7 @@ void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled)
host_control = DSI(_DSIREG(DSI_HOST_CONTROL)); host_control = DSI(_DSIREG(DSI_HOST_CONTROL));
// Enable host transfer trigger. // Enable host transfer trigger.
DSI(_DSIREG(DSI_HOST_CONTROL)) |= DSI_HOST_CONTROL_TX_TRIG_HOST; DSI(_DSIREG(DSI_HOST_CONTROL)) = host_control | DSI_HOST_CONTROL_TX_TRIG_HOST;
switch (len) switch (len)
{ {
@ -216,8 +221,71 @@ void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled)
DSI(_DSIREG(DSI_HOST_CONTROL)) = host_control; DSI(_DSIREG(DSI_HOST_CONTROL)) = host_control;
} }
void display_dsi_vblank_write(u8 cmd, u32 len, void *data)
{
u8 *fifo8;
u32 *fifo32;
// 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))
;
switch (len)
{
case 0:
DSI(_DSIREG(DSI_WR_DATA)) = (cmd << 8) | MIPI_DSI_DCS_SHORT_WRITE;
break;
case 1:
DSI(_DSIREG(DSI_WR_DATA)) = ((cmd | (*(u8 *)data << 8)) << 8) | MIPI_DSI_DCS_SHORT_WRITE_PARAM;
break;
default:
fifo32 = calloc(DSI_STATUS_RX_FIFO_SIZE * 8, 4);
fifo8 = (u8 *)fifo32;
fifo32[0] = (len << 8) | MIPI_DSI_DCS_LONG_WRITE;
fifo8[4] = cmd;
memcpy(&fifo8[5], data, len);
len += 4 + 1; // Increase length by CMD/length word and DCS CMD.
for (u32 i = 0; i < (ALIGN(len, 4) / 4); i++)
DSI(_DSIREG(DSI_WR_DATA)) = fifo32[i];
free(fifo32);
break;
}
// Wait for vblank before reseting sync points.
DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = DC_CMD_INT_FRAME_END_INT; // Clear interrupt.
while (!(DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) & DC_CMD_INT_FRAME_END_INT))
;
// Reset all states of syncpt block.
DSI(_DSIREG(DSI_INCR_SYNCPT_CNTRL)) = DSI_INCR_SYNCPT_SOFT_RESET;
usleep(300); // Stabilization delay.
// Clear syncpt block reset.
DSI(_DSIREG(DSI_INCR_SYNCPT_CNTRL)) = 0;
usleep(300); // Stabilization delay.
// Restore video mode and host control.
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 0;
// Disable and clear vblank interrupt.
DISPLAY_A(_DIREG(DC_CMD_INT_ENABLE)) = 0;
DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = DC_CMD_INT_FRAME_END_INT;
}
void display_init() void display_init()
{ {
// Get Hardware type, as it's used in various DI functions.
nx_aula = fuse_read_hw_type() == FUSE_NX_HW_TYPE_AULA;
// Check if display is already initialized. // Check if display is already initialized.
if (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & BIT(CLK_L_DISP1)) if (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & BIT(CLK_L_DISP1))
_display_panel_and_hw_end(true); _display_panel_and_hw_end(true);
@ -270,22 +338,31 @@ void display_init()
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) &= ~PINMUX_TRISTATE; // PULL_DOWN | 1 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_BL_EN) &= ~PINMUX_TRISTATE; // PULL_DOWN
// Set LCD +-5V pins mode and direction if (nx_aula)
gpio_config(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_MODE_GPIO); {
gpio_output_enable(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_OUTPUT_ENABLE); // Configure LCD RST pin.
gpio_config(GPIO_PORT_V, GPIO_PIN_2, GPIO_MODE_GPIO);
gpio_output_enable(GPIO_PORT_V, GPIO_PIN_2, GPIO_OUTPUT_ENABLE);
}
else
{
// Set LCD +-5V pins mode and direction
gpio_config(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_MODE_GPIO);
gpio_output_enable(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_OUTPUT_ENABLE);
// Enable LCD power. // Enable LCD power.
gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_HIGH); // LCD +5V enable. gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_HIGH); // LCD +5V enable.
usleep(10000); usleep(10000);
gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_HIGH); // LCD -5V enable. gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_HIGH); // LCD -5V enable.
usleep(10000); usleep(10000);
// Configure Backlight PWM/EN and LCD RST pins (BL PWM, BL EN, LCD 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_config(GPIO_PORT_V, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, GPIO_MODE_GPIO);
gpio_output_enable(GPIO_PORT_V, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, GPIO_OUTPUT_ENABLE); gpio_output_enable(GPIO_PORT_V, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, GPIO_OUTPUT_ENABLE);
// Enable Backlight power. // Enable Backlight power.
gpio_write(GPIO_PORT_V, GPIO_PIN_1, GPIO_HIGH); gpio_write(GPIO_PORT_V, GPIO_PIN_1, GPIO_HIGH);
}
// Power up supply regulator for display interface. // Power up supply regulator for display interface.
MIPI_CAL(_DSIREG(MIPI_CAL_MIPI_BIAS_PAD_CFG2)) = 0; MIPI_CAL(_DSIREG(MIPI_CAL_MIPI_BIAS_PAD_CFG2)) = 0;
@ -336,35 +413,18 @@ void display_init()
usleep(60000); usleep(60000);
// Setup DSI device takeover timeout. // Setup DSI device takeover timeout.
DSI(_DSIREG(DSI_BTA_TIMING)) = 0x50204; DSI(_DSIREG(DSI_BTA_TIMING)) = nx_aula ? 0x40103 : 0x50204;
#if 0
// Get Display ID. // Get Display ID.
_display_id = 0xCCCCCC; // Set initial value. 4th byte cleared. _display_id = 0xCCCCCC;
display_dsi_read(MIPI_DCS_GET_DISPLAY_ID, 3, &_display_id, DSI_VIDEO_DISABLED);
#else
// Drain RX FIFO.
_display_dsi_read_rx_fifo(NULL);
// 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 x u32.
for (u32 i = 0; i < 3; i++) for (u32 i = 0; i < 3; i++)
_display_id = DSI(_DSIREG(DSI_RD_DATA)) & 0xFFFFFF; // Skip ack and msg type info and get the payload (display id). {
#endif if (!display_dsi_read(MIPI_DCS_GET_DISPLAY_ID, 3, &_display_id, DSI_VIDEO_DISABLED))
break;
usleep(10000);
}
// Save raw Display ID to Nyx storage. // Save raw Display ID to Nyx storage.
nyx_str->info.disp_id = _display_id; nyx_str->info.disp_id = _display_id;
@ -374,9 +434,23 @@ void display_init()
if ((_display_id & 0xFF) == PANEL_JDI_XXX062M) if ((_display_id & 0xFF) == PANEL_JDI_XXX062M)
_display_id = PANEL_JDI_XXX062M; _display_id = PANEL_JDI_XXX062M;
// For Aula ensure that we have a compatible panel id.
if (nx_aula && _display_id == 0xCCCC)
_display_id = PANEL_SAM_70_UNK;
// Initialize display panel. // Initialize display panel.
switch (_display_id) switch (_display_id)
{ {
case PANEL_SAM_70_UNK:
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 180000);
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE_PARAM, 0xA0, 0); // Write 0 to 0xA0.
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE_PARAM, MIPI_DCS_SET_CONTROL_DISPLAY | (DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL << 8), 0); // Enable brightness control.
DSI(_DSIREG(DSI_WR_DATA)) = 0x339; // MIPI_DSI_DCS_LONG_WRITE: 3 bytes.
DSI(_DSIREG(DSI_WR_DATA)) = 0x000051; // MIPI_DCS_SET_BRIGHTNESS 0000: 0%. FF07: 100%.
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
usleep(5000);
break;
case PANEL_JDI_XXX062M: case PANEL_JDI_XXX062M:
exec_cfg((u32 *)DSI_BASE, _display_init_config_jdi, 43); 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); _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 180000);
@ -415,7 +489,7 @@ void display_init()
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_SET_DISPLAY_ON, 20000); _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_SET_DISPLAY_ON, 20000);
// Configure PLLD for DISP1. // Configure PLLD for DISP1.
plld_div = (1 << 20) | (24 << 11) | 1; // DIVM: 1, DIVN: 24, DIVP: 1. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 234 MHz (offset). plld_div = (1 << 20) | (24 << 11) | 1; // DIVM: 1, DIVN: 24, DIVP: 1. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 234 MHz (offset, it's ddr btw, so normally div2).
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div; CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div;
if (tegra_t210) if (tegra_t210)
@ -465,6 +539,9 @@ void display_init()
void display_backlight_pwm_init() void display_backlight_pwm_init()
{ {
if (_display_id == PANEL_SAM_70_UNK)
return;
clock_enable_pwm(); clock_enable_pwm();
PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN; // Enable PWM and set it to 25KHz PFM. 29.5KHz is stock. PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN; // Enable PWM and set it to 25KHz PFM. 29.5KHz is stock.
@ -478,20 +555,23 @@ void display_backlight(bool enable)
gpio_write(GPIO_PORT_V, GPIO_PIN_0, enable ? GPIO_HIGH : GPIO_LOW); // Backlight PWM GPIO. gpio_write(GPIO_PORT_V, GPIO_PIN_0, enable ? GPIO_HIGH : GPIO_LOW); // Backlight PWM GPIO.
} }
void display_backlight_brightness(u32 brightness, u32 step_delay) void display_dsi_backlight_brightness(u32 brightness)
{
u16 bl_ctrl = byte_swap_16((u16)(brightness * 8));
display_dsi_vblank_write(MIPI_DCS_SET_BRIGHTNESS, 2, &bl_ctrl);
}
void display_pwm_backlight_brightness(u32 brightness, u32 step_delay)
{ {
u32 old_value = (PWM(PWM_CONTROLLER_PWM_CSR_0) >> 16) & 0xFF; u32 old_value = (PWM(PWM_CONTROLLER_PWM_CSR_0) >> 16) & 0xFF;
if (brightness == old_value) if (brightness == old_value)
return; return;
if (brightness > 255)
brightness = 255;
if (old_value < brightness) if (old_value < brightness)
{ {
for (u32 i = old_value; i < brightness + 1; i++) for (u32 i = old_value; i < brightness + 1; i++)
{ {
PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN | (i << 16); // Enable PWM and set it to 25KHz PFM. PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN | (i << 16);
usleep(step_delay); usleep(step_delay);
} }
} }
@ -499,7 +579,7 @@ void display_backlight_brightness(u32 brightness, u32 step_delay)
{ {
for (u32 i = old_value; i > brightness; i--) for (u32 i = old_value; i > brightness; i--)
{ {
PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN | (i << 16); // Enable PWM and set it to 25KHz PFM. PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN | (i << 16);
usleep(step_delay); usleep(step_delay);
} }
} }
@ -507,6 +587,17 @@ void display_backlight_brightness(u32 brightness, u32 step_delay)
PWM(PWM_CONTROLLER_PWM_CSR_0) = 0; PWM(PWM_CONTROLLER_PWM_CSR_0) = 0;
} }
void display_backlight_brightness(u32 brightness, u32 step_delay)
{
if (brightness > 255)
brightness = 255;
if (_display_id != PANEL_SAM_70_UNK)
display_pwm_backlight_brightness(brightness, step_delay);
else
display_dsi_backlight_brightness(brightness);
}
u32 display_get_backlight_brightness() u32 display_get_backlight_brightness()
{ {
return ((PWM(PWM_CONTROLLER_PWM_CSR_0) >> 16) & 0xFF); return ((PWM(PWM_CONTROLLER_PWM_CSR_0) >> 16) & 0xFF);
@ -532,7 +623,9 @@ static void _display_panel_and_hw_end(bool no_panel_deinit)
// De-initialize video controller. // De-initialize video controller.
exec_cfg((u32 *)DISPLAY_A_BASE, _display_video_disp_controller_disable_config, 17); exec_cfg((u32 *)DISPLAY_A_BASE, _display_video_disp_controller_disable_config, 17);
exec_cfg((u32 *)DSI_BASE, _display_dsi_timing_deinit_config, 16); exec_cfg((u32 *)DSI_BASE, _display_dsi_timing_deinit_config, 16);
usleep(10000);
if (_display_id != PANEL_SAM_70_UNK)
usleep(10000);
// De-initialize display panel. // De-initialize display panel.
switch (_display_id) switch (_display_id)
@ -584,16 +677,23 @@ static void _display_panel_and_hw_end(bool no_panel_deinit)
} }
// Blank - powerdown. // Blank - powerdown.
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_ENTER_SLEEP_MODE, 50000); _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_ENTER_SLEEP_MODE,
(_display_id == PANEL_SAM_70_UNK) ? 120000 : 50000);
skip_panel_deinit: skip_panel_deinit:
// Disable LCD power pins. // Disable LCD power pins.
gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_LOW); // LCD Reset disable. 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); // LCD -5V disable. if (!nx_aula) // HOS uses panel id.
usleep(10000); {
gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_LOW); // LCD +5V disable. usleep(10000);
usleep(10000); gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_LOW); // LCD -5V disable.
usleep(10000);
gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_LOW); // LCD +5V disable.
usleep(10000);
}
else
usleep(30000); // Aula Panel.
// Disable Display Interface specific clocks. // Disable Display Interface specific clocks.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = BIT(CLK_H_MIPI_CAL) | BIT(CLK_H_DSI); CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = BIT(CLK_H_MIPI_CAL) | BIT(CLK_H_DSI);
@ -606,9 +706,12 @@ skip_panel_deinit:
DSI(_DSIREG(DSI_POWER_CONTROL)) = 0; DSI(_DSIREG(DSI_POWER_CONTROL)) = 0;
// Switch LCD PWM backlight pin to special function mode and enable PWM0 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. if (!nx_aula)
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & ~PINMUX_TRISTATE) | PINMUX_TRISTATE; {
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & ~PINMUX_FUNC_MASK) | 1; // Set PWM0 mode. gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight PWM.
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & ~PINMUX_TRISTATE) | PINMUX_TRISTATE;
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & ~PINMUX_FUNC_MASK) | 1; // Set PWM0 mode.
}
} }
void display_end() { _display_panel_and_hw_end(false); }; void display_end() { _display_panel_and_hw_end(false); };
@ -620,11 +723,18 @@ u16 display_get_decoded_panel_id()
void display_set_decoded_panel_id(u32 id) void display_set_decoded_panel_id(u32 id)
{ {
// Get Hardware type, as it's used in various DI functions.
nx_aula = fuse_read_hw_type() == FUSE_NX_HW_TYPE_AULA;
// Decode Display ID. // Decode Display ID.
_display_id = ((id >> 8) & 0xFF00) | (id & 0xFF); _display_id = ((id >> 8) & 0xFF00) | (id & 0xFF);
if ((_display_id & 0xFF) == PANEL_JDI_XXX062M) if ((_display_id & 0xFF) == PANEL_JDI_XXX062M)
_display_id = PANEL_JDI_XXX062M; _display_id = PANEL_JDI_XXX062M;
// For Aula ensure that we have a compatible panel id.
if (nx_aula && _display_id == 0xCCCC)
_display_id = PANEL_SAM_70_UNK;
} }
void display_color_screen(u32 color) void display_color_screen(u32 color)
@ -637,9 +747,12 @@ void display_color_screen(u32 color)
DISPLAY_A(_DIREG(DC_WIN_CD_WIN_OPTIONS)) = 0; DISPLAY_A(_DIREG(DC_WIN_CD_WIN_OPTIONS)) = 0;
DISPLAY_A(_DIREG(DC_DISP_BLEND_BACKGROUND_COLOR)) = color; DISPLAY_A(_DIREG(DC_DISP_BLEND_BACKGROUND_COLOR)) = color;
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = (DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) & 0xFFFFFFFE) | GENERAL_ACT_REQ; DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = (DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) & 0xFFFFFFFE) | GENERAL_ACT_REQ;
usleep(35000); usleep(35000); // No need to wait on Aula.
display_backlight(true); if (_display_id != PANEL_SAM_70_UNK)
display_backlight(true);
else
display_backlight_brightness(255, 0);
} }
u32 *display_init_framebuffer_pitch() u32 *display_init_framebuffer_pitch()
@ -649,7 +762,7 @@ u32 *display_init_framebuffer_pitch()
// This configures the framebuffer @ IPL_FB_ADDRESS with a resolution of 1280x720 (line stride 720). // This configures the framebuffer @ IPL_FB_ADDRESS with a resolution of 1280x720 (line stride 720).
exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer_pitch, 32); exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer_pitch, 32);
usleep(35000); usleep(35000); // No need to wait on Aula.
return (u32 *)IPL_FB_ADDRESS; return (u32 *)IPL_FB_ADDRESS;
} }
@ -658,8 +771,7 @@ u32 *display_init_framebuffer_pitch_inv()
{ {
// This configures the framebuffer @ NYX_FB_ADDRESS with a resolution of 1280x720 (line stride 720). // This configures the framebuffer @ NYX_FB_ADDRESS with a resolution of 1280x720 (line stride 720).
exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer_pitch_inv, 34); exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer_pitch_inv, 34);
usleep(35000); // No need to wait on Aula.
usleep(35000);
return (u32 *)NYX_FB_ADDRESS; return (u32 *)NYX_FB_ADDRESS;
} }
@ -668,8 +780,7 @@ u32 *display_init_framebuffer_block()
{ {
// This configures the framebuffer @ NYX_FB_ADDRESS with a resolution of 1280x720 (line stride 720). // This configures the framebuffer @ NYX_FB_ADDRESS with a resolution of 1280x720 (line stride 720).
exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer_block, 34); exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer_block, 34);
usleep(35000); // No need to wait on Aula.
usleep(35000);
return (u32 *)NYX_FB_ADDRESS; return (u32 *)NYX_FB_ADDRESS;
} }

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer * Copyright (c) 2018-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -547,17 +547,17 @@
#define MIPI_DCS_GET_DISPLAY_ID1 0xDA // GET_DISPLAY_ID Byte0, Module Manufacturer ID. #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_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_DISPLAY_ID3 0xDC // GET_DISPLAY_ID Byte2, Module/Driver ID.
#define MIPI_DCS_GET_NUM_ERRORS 0x05 #define MIPI_DCS_GET_NUM_ERRORS 0x05 // 1 byte.
#define MIPI_DCS_GET_RED_CHANNEL 0x06 #define MIPI_DCS_GET_RED_CHANNEL 0x06
#define MIPI_DCS_GET_GREEN_CHANNEL 0x07 #define MIPI_DCS_GET_GREEN_CHANNEL 0x07
#define MIPI_DCS_GET_BLUE_CHANNEL 0x08 #define MIPI_DCS_GET_BLUE_CHANNEL 0x08
#define MIPI_DCS_GET_DISPLAY_STATUS 0x09 #define MIPI_DCS_GET_DISPLAY_STATUS 0x09 // 4 bytes.
#define MIPI_DCS_GET_POWER_MODE 0x0A #define MIPI_DCS_GET_POWER_MODE 0x0A // 1 byte. 2: DISON, 3: NORON, 4: SLPOUT, 7: BSTON.
#define MIPI_DCS_GET_ADDRESS_MODE 0x0B #define MIPI_DCS_GET_ADDRESS_MODE 0x0B // Display Access Control. 1 byte. 0: GS, 1: SS, 3: BGR.
#define MIPI_DCS_GET_PIXEL_FORMAT 0x0C #define MIPI_DCS_GET_PIXEL_FORMAT 0x0C // 1 byte. 4-6: DPI.
#define MIPI_DCS_GET_DISPLAY_MODE 0x0D #define MIPI_DCS_GET_DISPLAY_MODE 0x0D // 1 byte. 0-2: GCS, 3: ALLPOFF, 4: ALLPON, 5: INVON.
#define MIPI_DCS_GET_SIGNAL_MODE 0x0E #define MIPI_DCS_GET_SIGNAL_MODE 0x0E // 1 byte. 0: EODSI, 2: DEON, 3: PCLKON, 4: VSON, 5: HSON, 7: TEON.
#define MIPI_DCS_GET_DIAGNOSTIC_RESULT 0x0F #define MIPI_DCS_GET_DIAGNOSTIC_RESULT 0x0F // 1 byte. 6: FUNDT, 7: REGLD.
#define MIPI_DCS_ENTER_SLEEP_MODE 0x10 #define MIPI_DCS_ENTER_SLEEP_MODE 0x10
#define MIPI_DCS_EXIT_SLEEP_MODE 0x11 #define MIPI_DCS_EXIT_SLEEP_MODE 0x11
#define MIPI_DCS_ENTER_PARTIAL_MODE 0x12 #define MIPI_DCS_ENTER_PARTIAL_MODE 0x12
@ -567,7 +567,7 @@
#define MIPI_DCS_ALL_PIXELS_OFF 0x22 #define MIPI_DCS_ALL_PIXELS_OFF 0x22
#define MIPI_DCS_ALL_PIXELS_ON 0x23 #define MIPI_DCS_ALL_PIXELS_ON 0x23
#define MIPI_DCS_SET_CONTRAST 0x25 // VCON in 40mV steps. 7-bit integer. #define MIPI_DCS_SET_CONTRAST 0x25 // VCON in 40mV steps. 7-bit integer.
#define MIPI_DCS_SET_GAMMA_CURVE 0x26 #define MIPI_DCS_SET_GAMMA_CURVE 0x26 // 1 byte. 0-7: GC.
#define MIPI_DCS_SET_DISPLAY_OFF 0x28 #define MIPI_DCS_SET_DISPLAY_OFF 0x28
#define MIPI_DCS_SET_DISPLAY_ON 0x29 #define MIPI_DCS_SET_DISPLAY_ON 0x29
#define MIPI_DCS_SET_COLUMN_ADDRESS 0x2A #define MIPI_DCS_SET_COLUMN_ADDRESS 0x2A
@ -580,11 +580,11 @@
#define MIPI_DCS_SET_SCROLL_AREA 0x33 #define MIPI_DCS_SET_SCROLL_AREA 0x33
#define MIPI_DCS_SET_TEAR_OFF 0x34 #define MIPI_DCS_SET_TEAR_OFF 0x34
#define MIPI_DCS_SET_TEAR_ON 0x35 #define MIPI_DCS_SET_TEAR_ON 0x35
#define MIPI_DCS_SET_ADDRESS_MODE 0x36 #define MIPI_DCS_SET_ADDRESS_MODE 0x36 // Display Access Control. 1 byte. 0: GS, 1: SS, 3: BGR.
#define MIPI_DCS_SET_SCROLL_START 0x37 #define MIPI_DCS_SET_SCROLL_START 0x37
#define MIPI_DCS_EXIT_IDLE_MODE 0x38 #define MIPI_DCS_EXIT_IDLE_MODE 0x38
#define MIPI_DCS_ENTER_IDLE_MODE 0x39 #define MIPI_DCS_ENTER_IDLE_MODE 0x39
#define MIPI_DCS_SET_PIXEL_FORMAT 0x3A #define MIPI_DCS_SET_PIXEL_FORMAT 0x3A // 1 byte. 4-6: DPI.
#define MIPI_DCS_WRITE_MEMORY_CONTINUE 0x3C #define MIPI_DCS_WRITE_MEMORY_CONTINUE 0x3C
#define MIPI_DCS_READ_MEMORY_CONTINUE 0x3E #define MIPI_DCS_READ_MEMORY_CONTINUE 0x3E
#define MIPI_DCS_GET_3D_CONTROL 0x3F #define MIPI_DCS_GET_3D_CONTROL 0x3F
@ -593,26 +593,34 @@
#define MIPI_DCS_GET_SCANLINE 0x45 #define MIPI_DCS_GET_SCANLINE 0x45
#define MIPI_DCS_SET_TEAR_SCANLINE_WIDTH 0x46 #define MIPI_DCS_SET_TEAR_SCANLINE_WIDTH 0x46
#define MIPI_DCS_GET_SCANLINE_WIDTH 0x47 #define MIPI_DCS_GET_SCANLINE_WIDTH 0x47
#define MIPI_DCS_SET_BRIGHTNESS 0x51 // DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL. #define MIPI_DCS_SET_BRIGHTNESS 0x51 // DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL. 1 byte. 0-7: DBV.
#define MIPI_DCS_GET_BRIGHTNESS 0x52 #define MIPI_DCS_GET_BRIGHTNESS 0x52 // 1 byte. 0-7: DBV.
#define MIPI_DCS_SET_CONTROL_DISPLAY 0x53 #define MIPI_DCS_SET_CONTROL_DISPLAY 0x53 // 1 byte. 2: BL, 3: DD, 5: BCTRL.
#define MIPI_DCS_GET_CONTROL_DISPLAY 0x54 #define MIPI_DCS_GET_CONTROL_DISPLAY 0x54 // 1 byte. 2: BL, 3: DD, 5: BCTRL.
#define MIPI_DCS_SET_CABC_VALUE 0x55 #define MIPI_DCS_SET_CABC_VALUE 0x55 // 1 byte. 0-32: C, 4-7: C.
#define MIPI_DCS_GET_CABC_VALUE 0x56 #define MIPI_DCS_GET_CABC_VALUE 0x56 // 1 byte. 0-32: C, 4-7: C.
#define MIPI_DCS_SET_CABC_MIN_BRI 0x5E #define MIPI_DCS_SET_CABC_MIN_BRI 0x5E // 1 byte. 0-7: CMB.
#define MIPI_DCS_GET_CABC_MIN_BRI 0x5F #define MIPI_DCS_GET_CABC_MIN_BRI 0x5F // 1 byte. 0-7: CMB.
#define MIPI_DCS_GET_AUTO_BRI_DIAG_RES 0x68 // 1 byte. 6-7: D.
#define MIPI_DCS_READ_DDB_START 0xA1 #define MIPI_DCS_READ_DDB_START 0xA1
#define MIPI_DCS_READ_DDB_CONTINUE 0xA8 #define MIPI_DCS_READ_DDB_CONTINUE 0xA8 // 0x100 size.
/*! MIPI DCS Panel Private CMDs. */ /*! MIPI DCS Panel Private CMDs. */
#define MIPI_DCS_PRIV_UNK_A0 0xA0 #define MIPI_DCS_PRIV_UNK_A0 0xA0
#define MIPI_DCS_PRIV_SET_POWER_CONTROL 0xB1 #define MIPI_DCS_PRIV_SET_POWER_CONTROL 0xB1
#define MIPI_DCS_PRIV_SET_EXTC 0xB9 #define MIPI_DCS_PRIV_SET_EXTC 0xB9 // Enable extended commands.
#define MIPI_DCS_PRIV_UNK_BD 0xBD #define MIPI_DCS_PRIV_UNK_BD 0xBD
#define MIPI_DCS_PRIV_UNK_D5 0xD5 #define MIPI_DCS_PRIV_UNK_D5 0xD5
#define MIPI_DCS_PRIV_UNK_D6 0xD6 #define MIPI_DCS_PRIV_UNK_D6 0xD6
#define MIPI_DCS_PRIV_UNK_D8 0xD8 #define MIPI_DCS_PRIV_UNK_D8 0xD8
#define MIPI_DCS_PRIV_UNK_D9 0xD9 #define MIPI_DCS_PRIV_UNK_D9 0xD9
#define MIPI_DCS_PRIV_READ_EXTC_CMD_SPI 0xFE // Read EXTC Command In SPI. 1 byte. 0-6: EXT_SPI_CNT, 7:EXT_SP.
#define MIPI_DCS_PRIV_SET_EXTC_CMD_REG 0xFF // EXTC Command Set enable register. 5 bytes. Pass: FF 98 06 04, PAGE.
/*! MIPI DCS Panel Private CMDs PAGE 1. */
#define MIPI_DCS_PRIV_GET_DISPLAY_ID4 0x00
#define MIPI_DCS_PRIV_GET_DISPLAY_ID5 0x01
#define MIPI_DCS_PRIV_GET_DISPLAY_ID6 0x02
/*! MIPI DCS CMD Defines. */ /*! MIPI DCS CMD Defines. */
#define DCS_POWER_MODE_DISPLAY_ON BIT(2) #define DCS_POWER_MODE_DISPLAY_ON BIT(2)
@ -655,11 +663,15 @@
* [20] 98 [0F]: InnoLux P062CCA-??? [UNCONFIRMED MODEL REV] * [20] 98 [0F]: InnoLux P062CCA-??? [UNCONFIRMED MODEL REV]
* [30] 94 [0F]: AUO A062TAN01 (59.06A33.001) * [30] 94 [0F]: AUO A062TAN01 (59.06A33.001)
* [30] 95 [0F]: AUO A062TAN02 (59.06A33.002) * [30] 95 [0F]: AUO A062TAN02 (59.06A33.002)
* [30] XX [0F]: AUO A062TAN03 (59.06A33.003) [UNCONFIRMED ID]
* *
* 5.5" panels for Hoag skus: * 5.5" panels for Hoag skus:
* [20] 94 [10]: InnoLux 2J055IA-27A (Rev B1) * [20] 94 [10]: InnoLux 2J055IA-27A (Rev B1)
* [30] XX [10]: AUO A055TAN01 (59.05A30.001) [UNCONFIRMED ID] * [30] 93 [10]: AUO A055TAN01 (59.05A30.001)
* [40] XX [10]: Vendor 40 [UNCONFIRMED ID] * [40] XX [10]: Vendor 40 [UNCONFIRMED ID]
*
* 7.0" OLED panels for Aula skus:
* [50] XX [20]: Samsung AMS700XXXX [UNCONFIRMED ID and MODEL]
*/ */
/* Display ID Decoding: /* Display ID Decoding:
@ -672,13 +684,13 @@
* 10h: Japan Display Inc. * 10h: Japan Display Inc.
* 20h: InnoLux Corporation * 20h: InnoLux Corporation
* 30h: AU Optronics * 30h: AU Optronics
* 40h: Unknown1 * 40h: Unknown0
* 50h: Unknown2 (OLED? Samsung? LG?) * 50h: Samsung
* *
* Boards, Panel Size: * Boards, Panel Size:
* 0Fh: Icosa/Iowa, 6.2" * 0Fh: Icosa/Iowa, 6.2"
* 10h: Hoag, 5.5" * 10h: Hoag, 5.5"
* 20h: Unknown, x.x" * 20h: Aula, 7.0"
*/ */
enum enum
@ -690,7 +702,8 @@ enum
PANEL_AUO_A062TAN01 = 0x0F30, PANEL_AUO_A062TAN01 = 0x0F30,
PANEL_INL_2J055IA_27A = 0x1020, PANEL_INL_2J055IA_27A = 0x1020,
PANEL_AUO_A055TAN01 = 0x1030, PANEL_AUO_A055TAN01 = 0x1030,
PANEL_V40_55_UNK = 0x1040 PANEL_V40_55_UNK = 0x1040,
PANEL_SAM_70_UNK = 0x2050
}; };
void display_init(); void display_init();

View file

@ -200,10 +200,10 @@ static const cfg_op_t _display_dsi_init_config_part6[14] = {
//DSI panel config. //DSI panel config.
static const cfg_op_t _display_init_config_jdi[43] = { static const cfg_op_t _display_init_config_jdi[43] = {
{DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes. {DSI_WR_DATA, 0x0439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
{DSI_WR_DATA, 0x9483FFB9}, // MIPI_DCS_PRIV_SET_EXTC. (Pass: FF 83 94). {DSI_WR_DATA, 0x9483FFB9}, // MIPI_DCS_PRIV_SET_EXTC. (Pass: FF 83 94).
{DSI_TRIGGER, DSI_TRIGGER_HOST}, {DSI_TRIGGER, DSI_TRIGGER_HOST},
{DSI_WR_DATA, 0x00BD15}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 0 to 0xBD. {DSI_WR_DATA, 0xBD15}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 0 to 0xBD.
{DSI_TRIGGER, DSI_TRIGGER_HOST}, {DSI_TRIGGER, DSI_TRIGGER_HOST},
{DSI_WR_DATA, 0x1939}, // MIPI_DSI_DCS_LONG_WRITE: 25 bytes. {DSI_WR_DATA, 0x1939}, // MIPI_DSI_DCS_LONG_WRITE: 25 bytes.
{DSI_WR_DATA, 0xAAAAAAD8}, // Register: 0xD8. {DSI_WR_DATA, 0xAAAAAAD8}, // Register: 0xD8.

View file

@ -23,79 +23,117 @@
#include <soc/pinmux.h> #include <soc/pinmux.h>
#include <utils/util.h> #include <utils/util.h>
#define HOS_GAIN BH1730_GAIN_64X #define BH1730_DEFAULT_GAIN BH1730_GAIN_64X
#define HOS_ITIME 38 #define BH1730_DEFAULT_ICYCLE 38
void set_als_cfg(als_table_t *als_val, u8 gain, u8 itime) #define BH1730_INTERNAL_CLOCK_NS 2800
#define BH1730_ADC_CALC_DELAY_US 2000 /* BH1730_INTERNAL_CLOCK_MS * 714 */
#define BH1730_ITIME_CYCLE_TO_US 2700 /* BH1730_INTERNAL_CLOCK_MS * 964 */
#define BH1730_DEFAULT_ITIME_MS 100
#define BH1730_LUX_MULTIPLIER 3600
#define BH1730_LUX_MULTIPLIER_AULA 1410
#define BH1730_LUX_MAX 100000
typedef struct _opt_win_cal_t
{ {
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_GAIN_REG), gain); u32 rc;
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_TIMING_REG), (256 - itime)); u32 cv;
u32 ci;
} opt_win_cal_t;
als_val->gain = gain; // Nintendo Switch Icosa/Iowa Optical Window calibration.
als_val->itime = itime; const opt_win_cal_t opt_win_cal_default[] = {
{ 500, 5002, 7502 },
{ 754, 2250, 2000 },
{ 1029, 1999, 1667 },
{ 1373, 884, 583 },
{ 1879, 309, 165 }
};
// Nintendo Switch Aula Optical Window calibration.
const opt_win_cal_t opt_win_cal_aula[] = {
{ 231, 9697, 30300 },
{ 993, 3333, 2778 },
{ 1478, 1621, 1053 },
{ 7500, 81, 10 }
};
const u32 als_gain_idx_tbl[4] = { 1, 2, 64, 128 };
void set_als_cfg(als_ctxt_t *als_ctxt, u8 gain, u8 cycle)
{
if (gain > BH1730_GAIN_128X)
gain = BH1730_GAIN_128X;
if (!cycle)
cycle = 1;
else if (cycle > 255)
cycle = 255;
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_GAIN_REG), gain);
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_TIMING_REG), (256 - cycle));
als_ctxt->gain = gain;
als_ctxt->cycle = cycle;
} }
void get_als_lux(als_table_t *als_val) void get_als_lux(als_ctxt_t *als_ctxt)
{ {
u32 data[2]; u32 data[2];
float pre_gain_lux; u32 visible_light;
float visible_light; u32 ir_light;
float ir_light; u64 lux = 0;
float light_ratio; u32 itime_us = BH1730_ITIME_CYCLE_TO_US * als_ctxt->cycle;
u8 adc_ready = 0; // Get visible and ir light raw data. Mode is continuous so waiting for new values doesn't matter.
u8 retries = 100;
const float als_gain_idx_tbl[4] = { 1.0, 2.0, 64.0, 128.0 };
const float als_norm_res = 100.0;
const float als_multiplier = 3.6;
const float als_tint = 2.7;
// Wait for ADC to prepare new data.
while (!(adc_ready & BH1730_CTL_ADC_VALID) && retries)
{
retries--;
adc_ready = i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_CONTROL_REG));
}
// Get visible and ir light raw data.
data[0] = i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA0LOW_REG)) + data[0] = i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA0LOW_REG)) +
(i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA0HIGH_REG)) << 8); (i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA0HIGH_REG)) << 8);
data[1] = i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA1LOW_REG)) + data[1] = i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA1LOW_REG)) +
(i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA1HIGH_REG)) << 8); (i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA1HIGH_REG)) << 8);
als_val->over_limit = data[0] > 65534 || data[1] > 65534; visible_light = data[0];
als_val->vi_light = data[0]; ir_light = data[1];
als_val->ir_light = data[1];
if (!data[0] || !retries) als_ctxt->over_limit = visible_light > 65534 || ir_light > 65534;
als_ctxt->vi_light = visible_light;
als_ctxt->ir_light = ir_light;
if (!visible_light)
{ {
als_val->lux = 0.0; als_ctxt->lux = 0;
return; return;
} }
visible_light = (float)data[0]; // Set calibration parameters.
ir_light = (float)data[1]; u32 lux_multiplier = BH1730_LUX_MULTIPLIER;
light_ratio = (float)data[1] / (float)data[0]; u32 opt_win_cal_count = ARRAY_SIZE(opt_win_cal_default);
const opt_win_cal_t *opt_win_cal = opt_win_cal_default;
// The following are specific to the light filter Switch uses. // Apply optical window calibration coefficients.
if (light_ratio < 0.5) for (u32 i = 0; i < opt_win_cal_count; i++)
pre_gain_lux = visible_light * 5.002 - ir_light * 7.502; {
else if (light_ratio < 0.754) if (1000 * ir_light / visible_light < opt_win_cal[i].rc)
pre_gain_lux = visible_light * 2.250 - ir_light * 2.000; {
else if (light_ratio < 1.029) lux = ((u64)opt_win_cal[i].cv * data[0]) - (opt_win_cal[i].ci * data[1]);
pre_gain_lux = visible_light * 1.999 - ir_light * 1.667; break;
else if (light_ratio < 1.373) }
pre_gain_lux = visible_light * 0.884 - ir_light * 0.583; }
else if (light_ratio < 1.879)
pre_gain_lux = visible_light * 0.309 - ir_light * 0.165;
else pre_gain_lux = 0.0;
als_val->lux = (pre_gain_lux / als_gain_idx_tbl[als_val->gain]) * (als_norm_res / ((float)als_val->itime * als_tint)) * als_multiplier; lux *= BH1730_DEFAULT_ITIME_MS * lux_multiplier;
lux /= als_gain_idx_tbl[als_ctxt->gain] * itime_us;
lux /= 1000;
if (lux > BH1730_LUX_MAX)
lux = BH1730_LUX_MAX;
als_ctxt->lux = lux;
} }
u8 als_init(als_table_t *als_val) u8 als_power_on(als_ctxt_t *als_ctxt)
{ {
// Enable power to ALS IC. // Enable power to ALS IC.
max7762x_regulator_set_voltage(REGULATOR_LDO6, 2900000); max7762x_regulator_set_voltage(REGULATOR_LDO6, 2900000);
@ -109,12 +147,10 @@ u8 als_init(als_table_t *als_val)
// Initialize ALS. // Initialize ALS.
u8 id = i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(0x12)); 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); i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_SPEC(BH1730_SPECCMD_RESET), 0);
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_GAIN_REG), HOS_GAIN);
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_TIMING_REG), (256 - HOS_ITIME));
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_CONTROL_REG), BH1730_CTL_POWER_ON | BH1730_CTL_ADC_EN);
als_val->gain = HOS_GAIN; set_als_cfg(als_ctxt, BH1730_DEFAULT_GAIN, BH1730_DEFAULT_ICYCLE);
als_val->itime = HOS_ITIME;
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_CONTROL_REG), BH1730_CTL_POWER_ON | BH1730_CTL_ADC_EN);
return id; return id;
} }

View file

@ -48,18 +48,18 @@
#define BH1730_ADDR(reg) (BH1730_CMD_MAGIC | BH1730_CMD_SETADDR | (reg)) #define BH1730_ADDR(reg) (BH1730_CMD_MAGIC | BH1730_CMD_SETADDR | (reg))
#define BH1730_SPEC(cmd) (BH1730_CMD_MAGIC | BH1730_CMD_SPECCMD | (cmd)) #define BH1730_SPEC(cmd) (BH1730_CMD_MAGIC | BH1730_CMD_SPECCMD | (cmd))
typedef struct _als_table_t typedef struct _als_ctxt_t
{ {
float lux; u32 lux;
bool over_limit; bool over_limit;
u32 vi_light; u32 vi_light;
u32 ir_light; u32 ir_light;
u8 gain; u8 gain;
u8 itime; u8 cycle;
} als_table_t; } als_ctxt_t;
void set_als_cfg(als_table_t *als_val, u8 gain, u8 itime); void set_als_cfg(als_ctxt_t *als_ctxt, u8 gain, u8 cycle);
void get_als_lux(als_table_t *als_val); void get_als_lux(als_ctxt_t *als_ctxt);
u8 als_init(als_table_t *als_val); u8 als_power_on(als_ctxt_t *als_ctxt);
#endif /* __ALS_H_ */ #endif /* __ALS_H_ */

View file

@ -39,7 +39,7 @@ static touch_panel_info_t _panels[] =
{ 1, 0, 1, 1, "GiS GGM6 B2X" }, { 1, 0, 1, 1, "GiS GGM6 B2X" },
{ 2, 0, 0, 0, "NISSHA NBF-K9A" }, { 2, 0, 0, 0, "NISSHA NBF-K9A" },
{ 3, 1, 0, 0, "GiS 5.5\"" }, { 3, 1, 0, 0, "GiS 5.5\"" },
{ 4, 0, 0, 1, "Unknown" }, { 4, 0, 0, 1, "Unknown_001" },
{ -1, 1, 0, 1, "GiS VA 6.2\"" } { -1, 1, 0, 1, "GiS VA 6.2\"" }
}; };

View file

@ -53,6 +53,7 @@
#define STMFTS_RW_FRAMEBUFFER_REG 0xD0 #define STMFTS_RW_FRAMEBUFFER_REG 0xD0
#define STMFTS_SAVE_CX_TUNING 0xFC #define STMFTS_SAVE_CX_TUNING 0xFC
#define STMFTS_DETECTION_CONFIG 0xB0
#define STMFTS_REQU_COMP_DATA 0xB8 #define STMFTS_REQU_COMP_DATA 0xB8
#define STMFTS_VENDOR 0xCF #define STMFTS_VENDOR 0xCF
#define STMFTS_FLASH_UNLOCK 0xF7 #define STMFTS_FLASH_UNLOCK 0xF7

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer * Copyright (c) 2018-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -15,6 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <memory_map.h>
#include <mem/mc.h> #include <mem/mc.h>
#include <soc/t210.h> #include <soc/t210.h>
#include <soc/clock.h> #include <soc/clock.h>
@ -124,13 +125,13 @@ void mc_config_carveout()
MC(MC_SECURITY_CARVEOUT5_CFG0) = 0x8F; MC(MC_SECURITY_CARVEOUT5_CFG0) = 0x8F;
} }
void mc_enable_ahb_redirect() void mc_enable_ahb_redirect(bool full_aperture)
{ {
// Enable ARC_CLK_OVR_ON. // Enable ARC_CLK_OVR_ON.
CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) = (CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) & 0xFFF7FFFF) | 0x80000; CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) = (CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) & 0xFFF7FFFF) | 0x80000;
//MC(MC_IRAM_REG_CTRL) &= 0xFFFFFFFE; //MC(MC_IRAM_REG_CTRL) &= 0xFFFFFFFE;
MC(MC_IRAM_BOM) = 0x40000000; MC(MC_IRAM_BOM) = 0x40000000;
MC(MC_IRAM_TOM) = 0x4003F000; MC(MC_IRAM_TOM) = full_aperture ? DRAM_START : 0x4003F000;
} }
void mc_disable_ahb_redirect() void mc_disable_ahb_redirect()

View file

@ -23,7 +23,7 @@
void mc_config_tsec_carveout(u32 bom, u32 size1mb, bool lock); void mc_config_tsec_carveout(u32 bom, u32 size1mb, bool lock);
void mc_config_carveout(); void mc_config_carveout();
void mc_config_carveout_finalize(); void mc_config_carveout_finalize();
void mc_enable_ahb_redirect(); void mc_enable_ahb_redirect(bool full_aperture);
void mc_disable_ahb_redirect(); void mc_disable_ahb_redirect();
void mc_enable(); void mc_enable();

View file

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018 balika011 * Copyright (c) 2018 balika011
* Copyright (c) 2019-2020 CTCaer * Copyright (c) 2019-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -36,22 +36,46 @@
#define CONFIG_SDRAM_KEEP_ALIVE #define CONFIG_SDRAM_KEEP_ALIVE
//#define CONFIG_SDRAM_COMPRESS_CFG
typedef struct _sdram_vendor_patch_t typedef struct _sdram_vendor_patch_t
{ {
u32 val; u32 val;
u32 addr:10; u32 offset:16;
u32 dramid:22; u32 dramcf:16;
} sdram_vendor_patch_t; } sdram_vendor_patch_t;
#ifdef CONFIG_SDRAM_COMPRESS_CFG static const u8 dram_encoding_t210b01[] = {
#include <libs/compr/lz.h> LPDDR4X_UNUSED,
#include "sdram_config_lz.inl" LPDDR4X_UNUSED,
#else LPDDR4X_UNUSED,
#include "sdram_config.inl" LPDDR4X_4GB_HYNIX_1Y_A,
#endif LPDDR4X_UNUSED,
LPDDR4X_4GB_HYNIX_1Y_A,
LPDDR4X_4GB_HYNIX_1Y_A,
LPDDR4X_4GB_SAMSUNG_X1X2,
LPDDR4X_NO_PATCH,
LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ,
LPDDR4X_NO_PATCH,
LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046,
LPDDR4X_NO_PATCH,
LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ,
LPDDR4X_NO_PATCH,
LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046,
LPDDR4X_4GB_SAMSUNG_Y,
LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL,
LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL,
LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL,
LPDDR4X_4GB_SAMSUNG_1Y_Y,
LPDDR4X_8GB_SAMSUNG_1Y_Y,
LPDDR4X_UNUSED, // Removed.
LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL,
LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL,
LPDDR4X_4GB_MICRON_1Y_A,
LPDDR4X_4GB_MICRON_1Y_A,
LPDDR4X_4GB_MICRON_1Y_A,
LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL,
};
#include "sdram_config.inl"
#include "sdram_config_t210b01.inl" #include "sdram_config_t210b01.inl"
static bool _sdram_wait_emc_status(u32 reg_offset, u32 bit_mask, bool updated_state, s32 emc_channel) static bool _sdram_wait_emc_status(u32 reg_offset, u32 bit_mask, bool updated_state, s32 emc_channel)
@ -1350,57 +1374,21 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params)
SYSREG(AHB_ARBITRATION_XBAR_CTRL) = (SYSREG(AHB_ARBITRATION_XBAR_CTRL) & 0xFFFEFFFF) | (params->ahb_arbitration_xbar_ctrl_meminit_done << 16); 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
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() static void *_sdram_get_params_t210()
{ {
// Check if id is proper. // Check if id is proper.
u32 dramid = fuse_read_dramid(false); u32 dramid = fuse_read_dramid(false);
#ifdef CONFIG_SDRAM_COMPRESS_CFG // Copy base parameters.
u32 *params = (u32 *)SDRAM_PARAMS_ADDR;
memcpy(params, &_dram_cfg_0_samsung_4gb, sizeof(sdram_params_t210_t));
u8 *buf = (u8 *)SDRAM_PARAMS_ADDR; // Patch parameters if needed.
LZ_Uncompress(_dram_cfg_lz, buf, sizeof(_dram_cfg_lz)); for (u32 i = 0; i < ARRAY_SIZE(sdram_cfg_vendor_patches_t210); i++)
return (void *)&buf[sizeof(sdram_params_t210_t) * dramid]; if (sdram_cfg_vendor_patches_t210[i].dramcf & DRAM_ID(dramid))
params[sdram_cfg_vendor_patches_t210[i].offset] = sdram_cfg_vendor_patches_t210[i].val;
#else return (void *)params;
u32 *buf = (u32 *)SDRAM_PARAMS_ADDR;
memcpy(buf, &_dram_cfg_0_samsung_4gb, sizeof(sdram_params_t210_t));
switch (dramid)
{
case LPDDR4_ICOSA_4GB_SAMSUNG_K4F6E304HB_MGCH:
case LPDDR4_ICOSA_4GB_MICRON_MT53B512M32D2NP_062_WT:
break;
case LPDDR4_ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE:
case LPDDR4_ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH:
#ifdef CONFIG_SDRAM_COPPER_SUPPORT
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_t210(dramid, (u32 *)buf);
break;
}
return (void *)buf;
#endif
} }
void *sdram_get_params_t210b01() void *sdram_get_params_t210b01()
@ -1408,38 +1396,20 @@ void *sdram_get_params_t210b01()
// Check if id is proper. // Check if id is proper.
u32 dramid = fuse_read_dramid(false); u32 dramid = fuse_read_dramid(false);
u32 *buf = (u32 *)SDRAM_PARAMS_ADDR; // Copy base parameters.
memcpy(buf, &_dram_cfg_08_10_12_14_samsung_hynix_4gb, sizeof(sdram_params_t210b01_t)); u32 *params = (u32 *)SDRAM_PARAMS_ADDR;
memcpy(params, &_dram_cfg_08_10_12_14_samsung_hynix_4gb, sizeof(sdram_params_t210b01_t));
switch (dramid) // Patch parameters if needed.
{ u8 dram_code = dram_encoding_t210b01[dramid];
case LPDDR4X_IOWA_4GB_SAMSUNG_K4U6E3S4AM_MGCJ: if (!dram_code)
case LPDDR4X_IOWA_4GB_HYNIX_H9HCNNNBKMMLHR_NME: return (void *)params;
case LPDDR4X_HOAG_4GB_SAMSUNG_K4U6E3S4AM_MGCJ:
case LPDDR4X_HOAG_4GB_HYNIX_H9HCNNNBKMMLHR_NME:
break;
case LPDDR4X_IOWA_4GB_SAMSUNG_X1X2: for (u32 i = 0; i < ARRAY_SIZE(sdram_cfg_vendor_patches_t210b01); i++)
case LPDDR4X_IOWA_8GB_SAMSUNG_K4UBE3D4AM_MGCJ: if (sdram_cfg_vendor_patches_t210b01[i].dramcf == dram_code)
case LPDDR4X_IOWA_4GB_MICRON_MT53E512M32D2NP_046_WT: params[sdram_cfg_vendor_patches_t210b01[i].offset] = sdram_cfg_vendor_patches_t210b01[i].val;
case LPDDR4X_HOAG_8GB_SAMSUNG_K4UBE3D4AM_MGCJ:
case LPDDR4X_HOAG_4GB_MICRON_MT53E512M32D2NP_046_WT: return (void *)params;
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_AULA_4GB_SAMSUNG_1Y_A:
case LPDDR4X_AULA_8GB_SAMSUNG_1Y_X:
case LPDDR4X_AULA_4GB_SAMSUNG_1Y_X:
case LPDDR4X_IOWA_4GB_MICRON_1Y_A:
case LPDDR4X_HOAG_4GB_MICRON_1Y_A:
case LPDDR4X_AULA_4GB_MICRON_1Y_A:
_sdram_patch_model_params_t210b01(dramid, (u32 *)buf);
break;
}
return (void *)buf;
} }
/* /*
@ -1485,7 +1455,7 @@ static void _sdram_init_t210()
const sdram_params_t210_t *params = (const sdram_params_t210_t *)_sdram_get_params_t210(); const sdram_params_t210_t *params = (const sdram_params_t210_t *)_sdram_get_params_t210();
// Set DRAM voltage. // Set DRAM voltage.
max7762x_regulator_set_voltage(REGULATOR_SD1, 1100000); max7762x_regulator_set_voltage(REGULATOR_SD1, 1100000); // HOS uses 1.125V
// VDDP Select. // VDDP Select.
PMC(APBDEV_PMC_VDDP_SEL) = params->pmc_vddp_sel; PMC(APBDEV_PMC_VDDP_SEL) = params->pmc_vddp_sel;

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2020 CTCaer * Copyright (c) 2020-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -23,20 +23,26 @@
/* /*
* Tegra X1/X1+ EMC/DRAM Bandwidth Chart: * Tegra X1/X1+ EMC/DRAM Bandwidth Chart:
* *
* 40.8 MHz: 0.61 GiB/s * Note: BWbits T210 = Hz x ddr x bus width x channels = Hz x 2 x 32 x 2.
* 68.0 MHz: 1.01 GiB/s * BWbits T210B01 = Hz x ddr x bus width x channels = Hz x 2 x 64 x 2.
* 102.0 MHz: 1.52 GiB/s * Both assume that both sub-partitions are used and thus reaching max
* 204.0 MHz: 3.04 GiB/s <-- Tegra X1/X1+ Init/SC7 Frequency * bandwidth per channel. (T210: 2x16-bit, T210B01: 2x32-bit).
* 408.0 MHz: 6.08 GiB/s * Retail Mariko use one sub-partition, in order to meet Erista perf.
* 665.6 MHz: 9.92 GiB/s *
* 800.0 MHz: 11.92 GiB/s <-- Tegra X1/X1+ Nvidia OS Boot Frequency * T210 T210B01
* 1065.6 MHz: 15.89 GiB/s * 40.8 MHz: 0.61 1.22 GiB/s
* 1331.2 MHz: 19.84 GiB/s * 68.0 MHz: 1.01 2.02 GiB/s
* 1600.0 MHz: 23.84 GiB/s <-- Tegra X1 Official Max Frequency * 102.0 MHz: 1.52 3.04 GiB/s
* 1862.4 MHz: 27.75 GiB/s <-- Tegra X1+ Official Max Frequency * 204.0 MHz: 3.04 6.08 GiB/s <-- Tegra X1/X1+ Init/SC7 Frequency
* 2131.2 MHz: 31.76 GiB/s * 408.0 MHz: 6.08 12.16 GiB/s
* 665.6 MHz: 9.92 19.84 GiB/s
* 800.0 MHz: 11.92 23.84 GiB/s <-- Tegra X1/X1+ Nvidia OS Boot Frequency
* 1065.6 MHz: 15.89 31.78 GiB/s
* 1331.2 MHz: 19.84 39.68 GiB/s
* 1600.0 MHz: 23.84 47.68 GiB/s <-- Tegra X1/X1+ HOS Max Frequency
* 1862.4 MHz: 27.75 55.50 GiB/s <-- Tegra X1 Official Max Frequency
* 2131.2 MHz: 31.76 63.52 GiB/s <-- Tegra X1+ Official Max Frequency
* *
* Note: BWbits = Hz x bus width x channels = Hz x 64 x 2.
*/ */
enum sdram_ids_erista enum sdram_ids_erista
@ -45,45 +51,73 @@ enum sdram_ids_erista
LPDDR4_ICOSA_4GB_SAMSUNG_K4F6E304HB_MGCH = 0, LPDDR4_ICOSA_4GB_SAMSUNG_K4F6E304HB_MGCH = 0,
LPDDR4_ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 1, LPDDR4_ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 1,
LPDDR4_ICOSA_4GB_MICRON_MT53B512M32D2NP_062_WT = 2, LPDDR4_ICOSA_4GB_MICRON_MT53B512M32D2NP_062_WT = 2,
LPDDR4_COPPER_4GB_SAMSUNG_K4F6E304HB_MGCH = 3, // Changed to AULA Hynix 4GB 1Y-A. LPDDR4_COPPER_4GB_SAMSUNG_K4F6E304HB_MGCH = 3, // Changed to Iowa Hynix 4GB 1Y-A.
LPDDR4_ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH = 4, LPDDR4_ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH = 4,
LPDDR4_COPPER_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 5, LPDDR4_COPPER_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 5, // Changed to Hoag Hynix 4GB 1Y-A.
LPDDR4_COPPER_4GB_MICRON_MT53B512M32D2NP_062_WT = 6, LPDDR4_COPPER_4GB_MICRON_MT53B512M32D2NP_062_WT = 6, // Changed to Aula Hynix 4GB 1Y-A.
}; };
enum sdram_ids_mariko enum sdram_ids_mariko
{ {
// LPDDR4X 4266Mbps.
LPDDR4X_IOWA_4GB_HYNIX_1Y_A = 3, // Replaced from Copper.
LPDDR4X_HOAG_4GB_HYNIX_1Y_A = 5, // Replaced from Copper.
LPDDR4X_AULA_4GB_HYNIX_1Y_A = 6, // Replaced from Copper.
// LPDDR4X 3733Mbps. // LPDDR4X 3733Mbps.
LPDDR4X_IOWA_4GB_SAMSUNG_X1X2 = 7, LPDDR4X_IOWA_4GB_SAMSUNG_X1X2 = 7,
LPDDR4X_IOWA_4GB_SAMSUNG_K4U6E3S4AM_MGCJ = 8, LPDDR4X_IOWA_4GB_SAMSUNG_K4U6E3S4AM_MGCJ = 8, // Die-M.
LPDDR4X_IOWA_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 9, LPDDR4X_IOWA_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 9, // Die-M.
LPDDR4X_IOWA_4GB_HYNIX_H9HCNNNBKMMLHR_NME = 10, LPDDR4X_IOWA_4GB_HYNIX_H9HCNNNBKMMLHR_NME = 10, // Die-M.
LPDDR4X_IOWA_4GB_MICRON_MT53E512M32D2NP_046_WT = 11, // 4266Mbps. LPDDR4X_IOWA_4GB_MICRON_MT53E512M32D2NP_046_WT = 11, // 4266Mbps. WT:E. Die-E.
LPDDR4X_HOAG_4GB_SAMSUNG_K4U6E3S4AM_MGCJ = 12, LPDDR4X_HOAG_4GB_SAMSUNG_K4U6E3S4AM_MGCJ = 12, // Die-M.
LPDDR4X_HOAG_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 13, LPDDR4X_HOAG_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 13, // Die-M.
LPDDR4X_HOAG_4GB_HYNIX_H9HCNNNBKMMLHR_NME = 14, LPDDR4X_HOAG_4GB_HYNIX_H9HCNNNBKMMLHR_NME = 14, // Die-M.
LPDDR4X_HOAG_4GB_MICRON_MT53E512M32D2NP_046_WT = 15, // 4266Mbps. LPDDR4X_HOAG_4GB_MICRON_MT53E512M32D2NP_046_WT = 15, // 4266Mbps. WT:E. Die-E.
// LPDDR4X 4266Mbps? // LPDDR4X 4266Mbps.
LPDDR4X_IOWA_4GB_SAMSUNG_Y = 16, LPDDR4X_IOWA_4GB_SAMSUNG_Y = 16,
LPDDR4X_IOWA_4GB_SAMSUNG_1Y_X = 17, LPDDR4X_IOWA_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 17, // Die-A.
LPDDR4X_IOWA_8GB_SAMSUNG_1Y_X = 18, LPDDR4X_IOWA_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 18, // Die-A.
LPDDR4X_HOAG_4GB_SAMSUNG_1Y_X = 19, LPDDR4X_HOAG_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 19, // Die-A.
LPDDR4X_IOWA_4GB_SAMSUNG_1Y_Y = 20, LPDDR4X_IOWA_4GB_SAMSUNG_1Y_Y = 20,
LPDDR4X_IOWA_8GB_SAMSUNG_1Y_Y = 21, LPDDR4X_IOWA_8GB_SAMSUNG_1Y_Y = 21,
LPDDR4X_AULA_4GB_SAMSUNG_1Y_A = 22, // LPDDR4X_AULA_4GB_SAMSUNG_1Y_A = 22, // Unused.
LPDDR4X_AULA_8GB_SAMSUNG_1Y_X = 23, LPDDR4X_HOAG_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 23, // Die-A.
LPDDR4X_AULA_4GB_SAMSUNG_1Y_X = 24, LPDDR4X_AULA_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 24, // Die-A.
LPDDR4X_IOWA_4GB_MICRON_1Y_A = 25, LPDDR4X_IOWA_4GB_MICRON_1Y_A = 25,
LPDDR4X_HOAG_4GB_MICRON_1Y_A = 26, LPDDR4X_HOAG_4GB_MICRON_1Y_A = 26,
LPDDR4X_AULA_4GB_MICRON_1Y_A = 27 LPDDR4X_AULA_4GB_MICRON_1Y_A = 27,
LPDDR4X_AULA_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 28, // Die-A.
};
enum sdram_codes_mariko
{
LPDDR4X_NO_PATCH = 0,
LPDDR4X_UNUSED = 0,
// LPDDR4X_4GB_SAMSUNG_K4U6E3S4AM_MGCJ DRAM IDs: 08, 12.
// LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLHR_NME DRAM IDs: 10, 14.
LPDDR4X_4GB_SAMSUNG_X1X2 = 1, // DRAM IDs: 07.
LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 2, // DRAM IDs: 09, 13.
LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046 = 3, // DRAM IDs: 11, 15.
LPDDR4X_4GB_SAMSUNG_Y = 4, // DRAM IDs: 16.
LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 5, // DRAM IDs: 17, 19, 24.
LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 6, // DRAM IDs: 18, 23, 28.
LPDDR4X_4GB_SAMSUNG_1Y_Y = 7, // DRAM IDs: 20.
LPDDR4X_8GB_SAMSUNG_1Y_Y = 8, // DRAM IDs: 21.
//LPDDR4X_4GB_SAMSUNG_1Y_A = 9, // DRAM IDs: 22. Unused.
LPDDR4X_4GB_MICRON_1Y_A = 10, // DRAM IDs: 25, 26, 27.
LPDDR4X_4GB_HYNIX_1Y_A = 11, // DRAM IDs: 03, 05, 06.
}; };
void sdram_init(); void sdram_init();

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2020 CTCaer * Copyright (c) 2020-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -646,46 +646,51 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = {
static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210[] = { static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210[] = {
// Hynix timing config. // Hynix timing config.
{ 0x0000000D, 67, DRAM_ID(1) | DRAM_ID(5) }, // emc_r2w. { 0x0000000D, 0x10C / 4, DRAM_ID(1) }, // emc_r2w.
{ 0x00000001, 91, DRAM_ID(1) | DRAM_ID(5) }, // emc_puterm_extra. { 0x00000001, 0x16C / 4, DRAM_ID(1) }, // emc_puterm_extra.
{ 0x80000000, 92, DRAM_ID(1) | DRAM_ID(5) }, // emc_puterm_width. { 0x80000000, 0x170 / 4, DRAM_ID(1) }, // emc_puterm_width.
{ 0x00000210, 317, DRAM_ID(1) | DRAM_ID(5) }, // emc_pmacro_data_rx_term_mode. { 0x00000210, 0x4F4 / 4, DRAM_ID(1) }, // emc_pmacro_data_rx_term_mode.
{ 0x00000005, 368, DRAM_ID(1) | DRAM_ID(5) }, // mc_emem_arb_timing_r2w. { 0x00000005, 0x5C0 / 4, DRAM_ID(1) }, // mc_emem_arb_timing_r2w.
// Samsung 6GB density config. // Samsung 6GB density config.
{ 0x000C0302, 347, DRAM_ID(4) }, // mc_emem_adr_cfg_dev0. 768MB Rank 0 density. { 0x000C0302, 0x56C / 4, DRAM_ID(4) }, // mc_emem_adr_cfg_dev0. 768MB Rank 0 density.
{ 0x000C0302, 348, DRAM_ID(4) }, // mc_emem_adr_cfg_dev1. 768MB Rank 1 density. { 0x000C0302, 0x570 / 4, DRAM_ID(4) }, // mc_emem_adr_cfg_dev1. 768MB Rank 1 density.
{ 0x00001800, 353, DRAM_ID(4) }, // mc_emem_cfg. 6GB total density. { 0x00001800, 0x584 / 4, DRAM_ID(4) }, // mc_emem_cfg. 6GB total density.
#ifdef CONFIG_SDRAM_COPPER_SUPPORT #ifdef CONFIG_SDRAM_COPPER_SUPPORT
// Copper prototype Samsung/Hynix/Micron timing configs. // Copper prototype Samsung/Hynix/Micron timing configs.
{ 0x0000003A, 59, DRAM_ID(6) }, // emc_rfc. Auto refresh. { 0x0000003A, 0xEC / 4, DRAM_ID(6) }, // emc_rfc. Auto refresh.
{ 0x0000001D, 60, DRAM_ID(6) }, // emc_rfc_pb. Bank Auto refresh. { 0x0000001D, 0xF0 / 4, DRAM_ID(6) }, // emc_rfc_pb. Bank Auto refresh.
{ 0x00000012, 108, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_rw2pden. { 0x0000000D, 0x10C / 4, DRAM_ID(5) }, // emc_r2w.
{ 0x0000003B, 112, DRAM_ID(6) }, // emc_txsr. { 0x00000001, 0x16C / 4, DRAM_ID(5) }, // emc_puterm_extra.
{ 0x0000003B, 113, DRAM_ID(6) }, // emc_txsr_dll. { 0x80000000, 0x170 / 4, DRAM_ID(5) }, // emc_puterm_width.
{ 0x00000003, 119, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_tclkstable. { 0x00000012, 0x1B0 / 4, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_rw2pden.
{ 0x00120015, 205, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank0_4. { 0x0000003B, 0x1C0 / 4, DRAM_ID(6) }, // emc_txsr.
{ 0x00160012, 206, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank0_5. { 0x0000003B, 0x1C4 / 4, DRAM_ID(6) }, // emc_txsr_dll.
{ 0x00120015, 211, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank1_4. { 0x00000003, 0x1DC / 4, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_tclkstable.
{ 0x00160012, 212, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank1_5. { 0x00120015, 0x334 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank0_4.
{ 0x002F0032, 213, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_0. { 0x00160012, 0x338 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank0_5.
{ 0x00310032, 214, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_1. { 0x00120015, 0x34C / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank1_4.
{ 0x00360034, 215, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_2. { 0x00160012, 0x350 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank1_5.
{ 0x0033002F, 216, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_3. { 0x002F0032, 0x354 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_0.
{ 0x00000006, 217, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_4. { 0x00310032, 0x358 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_1.
{ 0x002F0032, 219, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_0. { 0x00360034, 0x35C / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_2.
{ 0x00310032, 220, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_1. { 0x0033002F, 0x360 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_3.
{ 0x00360034, 221, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_2. { 0x00000006, 0x364 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_4.
{ 0x0033002F, 222, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_3. { 0x002F0032, 0x36C / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_0.
{ 0x00000006, 223, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_4. { 0x00310032, 0x370 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_1.
{ 0x00150015, 233, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_0. { 0x00360034, 0x374 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_2.
{ 0x00120012, 235, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_2. { 0x0033002F, 0x378 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_3.
{ 0x00160016, 236, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_3. { 0x00000006, 0x37C / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_4.
{ 0x00000015, 237, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_4. { 0x00150015, 0x3A4 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_0.
{ 0x00000012, 295, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_cmd_brlshft2. { 0x00120012, 0x3AC / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_2.
{ 0x00000012, 296, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_cmd_brlshft3. { 0x00160016, 0x3B0 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_3.
{ 0x00000007, 370, DRAM_ID(6) }, // mc_emem_arb_timing_rfcpb. Bank refresh. { 0x00000015, 0x3B4 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_4.
{ 0x72A30504, 373, DRAM_ID(6) }, // mc_emem_arb_misc0. { 0x00000012, 0x49C / 4, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_cmd_brlshft2.
{ 0x00000012, 0x4A0 / 4, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_cmd_brlshft3.
{ 0x00000210, 0x4F4 / 4, DRAM_ID(5) }, // emc_pmacro_data_rx_term_mode.
{ 0x00000005, 0x5C0 / 4, DRAM_ID(5) }, // mc_emem_arb_timing_r2w.
{ 0x00000007, 0x5C8 / 4, DRAM_ID(6) }, // mc_emem_arb_timing_rfcpb. Bank refresh.
{ 0x72A30504, 0x5D4 / 4, DRAM_ID(6) }, // mc_emem_arb_misc0.
#endif #endif
}; };

View file

@ -1,124 +0,0 @@
/*
* Copyright (c) 2018 naehrwert
*
* 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 <http://www.gnu.org/licenses/>.
*/
static const u8 _dram_cfg_lz[1262] = {
0x17, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00,
0x00, 0x2C, 0x17, 0x04, 0x09, 0x00, 0x17, 0x04, 0x04, 0x17, 0x08, 0x08,
0x17, 0x10, 0x10, 0x00, 0x00, 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00,
0x00, 0x04, 0xB4, 0x01, 0x70, 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00,
0x70, 0x17, 0x10, 0x24, 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40,
0x00, 0x00, 0x00, 0x17, 0x04, 0x04, 0x17, 0x09, 0x18, 0xFF, 0xFF, 0x1F,
0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x77,
0x00, 0x17, 0x04, 0x04, 0x17, 0x08, 0x08, 0x17, 0x08, 0x08, 0xA6, 0xA6,
0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, 0x04, 0x04,
0x04, 0x04, 0x17, 0x04, 0x04, 0x17, 0x04, 0x3C, 0x1F, 0x1F, 0x1F, 0x1F,
0x17, 0x04, 0x04, 0x17, 0x06, 0x06, 0x00, 0x00, 0x04, 0x08, 0x17, 0x06,
0x46, 0xA1, 0x01, 0x00, 0x00, 0x32, 0x17, 0x0B, 0x64, 0x01, 0x17, 0x04,
0x7C, 0x17, 0x07, 0x0C, 0x03, 0x17, 0x04, 0x04, 0x00, 0x00, 0x00, 0x1E,
0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x13,
0x17, 0x0B, 0x2C, 0x09, 0x00, 0x00, 0x00, 0x17, 0x05, 0x5D, 0x17, 0x07,
0x10, 0x0B, 0x17, 0x07, 0x28, 0x08, 0x17, 0x07, 0x0C, 0x17, 0x04, 0x1C,
0x20, 0x00, 0x00, 0x00, 0x06, 0x17, 0x04, 0x04, 0x17, 0x07, 0x08, 0x17,
0x04, 0x50, 0x17, 0x04, 0x2C, 0x17, 0x04, 0x1C, 0x17, 0x04, 0x10, 0x17,
0x08, 0x6C, 0x17, 0x04, 0x10, 0x17, 0x04, 0x38, 0x17, 0x04, 0x40, 0x05,
0x17, 0x07, 0x1C, 0x17, 0x08, 0x58, 0x17, 0x04, 0x24, 0x17, 0x04, 0x18,
0x17, 0x08, 0x64, 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14,
0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x17, 0x09, 0x0C, 0x17, 0x05, 0x82,
0x58, 0x17, 0x07, 0x61, 0xC1, 0x17, 0x07, 0x50, 0x17, 0x04, 0x04, 0x17,
0x08, 0x81, 0x48, 0x17, 0x04, 0x04, 0x17, 0x04, 0x28, 0x17, 0x04, 0x60,
0x17, 0x08, 0x54, 0x27, 0x17, 0x04, 0x04, 0x17, 0x07, 0x14, 0x17, 0x04,
0x04, 0x04, 0x17, 0x07, 0x81, 0x58, 0x17, 0x0C, 0x0C, 0x1C, 0x03, 0x00,
0x00, 0x0D, 0xA0, 0x60, 0x91, 0xBF, 0x3B, 0x17, 0x04, 0x5A, 0xF3, 0x0C,
0x04, 0x05, 0x1B, 0x06, 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05,
0x08, 0x1D, 0x09, 0x0A, 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03,
0x02, 0x1B, 0x1C, 0x23, 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02,
0x0A, 0x0B, 0x1D, 0x0D, 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08,
0x24, 0x06, 0x07, 0x9A, 0x12, 0x17, 0x05, 0x83, 0x41, 0x00, 0xFF, 0x17,
0x10, 0x83, 0x6C, 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00,
0x00, 0x0D, 0x08, 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00,
0x00, 0x0B, 0x08, 0x72, 0x72, 0x0E, 0x0C, 0x17, 0x04, 0x20, 0x08, 0x08,
0x0D, 0x0C, 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x17, 0x06,
0x2C, 0x11, 0x08, 0x17, 0x10, 0x84, 0x67, 0x15, 0x00, 0xCC, 0x00, 0x0A,
0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, 0xFF,
0x0F, 0xFF, 0x0F, 0x17, 0x08, 0x83, 0x4C, 0x01, 0x03, 0x00, 0x70, 0x00,
0x0C, 0x00, 0x01, 0x17, 0x04, 0x0C, 0x08, 0x44, 0x00, 0x10, 0x04, 0x04,
0x00, 0x06, 0x13, 0x07, 0x00, 0x80, 0x17, 0x04, 0x10, 0xA0, 0x00, 0x2C,
0x00, 0x01, 0x37, 0x00, 0x00, 0x00, 0x80, 0x17, 0x06, 0x48, 0x08, 0x00,
0x04, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28,
0x28, 0x28, 0x17, 0x04, 0x04, 0x11, 0x11, 0x11, 0x11, 0x17, 0x04, 0x04,
0xBE, 0x00, 0x00, 0x17, 0x05, 0x58, 0x17, 0x08, 0x5C, 0x17, 0x22, 0x85,
0x6A, 0x17, 0x1A, 0x1A, 0x14, 0x00, 0x12, 0x00, 0x10, 0x17, 0x05, 0x83,
0x0A, 0x17, 0x16, 0x18, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00,
0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x17, 0x05, 0x83, 0x0C, 0x17,
0x04, 0x20, 0x17, 0x18, 0x18, 0x28, 0x00, 0x28, 0x17, 0x04, 0x04, 0x17,
0x08, 0x08, 0x17, 0x10, 0x10, 0x00, 0x14, 0x17, 0x05, 0x5A, 0x17, 0x04,
0x5C, 0x17, 0x04, 0x5E, 0x17, 0x04, 0x0E, 0x17, 0x0E, 0x78, 0x17, 0x09,
0x82, 0x50, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51,
0x17, 0x08, 0x18, 0x80, 0x01, 0x00, 0x00, 0x40, 0x17, 0x04, 0x20, 0x03,
0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, 0x11, 0x17, 0x08, 0x82, 0x58,
0x17, 0x0C, 0x38, 0x17, 0x1B, 0x81, 0x6C, 0x17, 0x08, 0x85, 0x60, 0x17,
0x08, 0x86, 0x50, 0x17, 0x08, 0x86, 0x60, 0x17, 0x06, 0x83, 0x21, 0x22,
0x04, 0xFF, 0xFF, 0xAF, 0x4F, 0x17, 0x0C, 0x86, 0x74, 0x17, 0x08, 0x2C,
0x8B, 0xFF, 0x07, 0x17, 0x06, 0x81, 0x04, 0x32, 0x54, 0x76, 0x10, 0x47,
0x32, 0x65, 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75,
0x64, 0x32, 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45,
0x32, 0x67, 0x17, 0x04, 0x24, 0x49, 0x92, 0x24, 0x17, 0x04, 0x04, 0x17,
0x11, 0x7C, 0x1B, 0x17, 0x04, 0x04, 0x17, 0x13, 0x81, 0x14, 0x2F, 0x41,
0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x17, 0x04, 0x7C, 0xFF, 0xFF, 0xFF,
0x7F, 0x0B, 0xD7, 0x06, 0x40, 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03,
0x00, 0x00, 0x5C, 0x01, 0x00, 0x10, 0x10, 0x10, 0x17, 0x06, 0x86, 0x59,
0x17, 0x0F, 0x89, 0x14, 0x37, 0x17, 0x07, 0x82, 0x72, 0x10, 0x17, 0x06,
0x83, 0x0D, 0x00, 0x11, 0x01, 0x17, 0x05, 0x85, 0x39, 0x17, 0x04, 0x0E,
0x0A, 0x17, 0x07, 0x89, 0x29, 0x17, 0x04, 0x1B, 0x17, 0x08, 0x86, 0x77,
0x17, 0x09, 0x12, 0x20, 0x00, 0x00, 0x00, 0x81, 0x10, 0x09, 0x28, 0x93,
0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, 0x17, 0x18, 0x82, 0x2C, 0xFF,
0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0x17, 0x04, 0x04, 0xDC, 0xDC,
0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x17, 0x04, 0x04, 0x17, 0x04, 0x04,
0x17, 0x05, 0x82, 0x24, 0x03, 0x07, 0x17, 0x04, 0x04, 0x00, 0x00, 0x24,
0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, 0x00, 0x28, 0x72, 0x39, 0x00, 0x10,
0x9C, 0x4B, 0x17, 0x04, 0x64, 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00,
0x80, 0x20, 0x10, 0x0A, 0x00, 0x28, 0x10, 0x17, 0x06, 0x85, 0x60, 0x17,
0x10, 0x82, 0x74, 0x17, 0x08, 0x08, 0x17, 0x08, 0x88, 0x00, 0x17, 0x04,
0x10, 0x04, 0x17, 0x0B, 0x87, 0x6C, 0x01, 0x00, 0x02, 0x02, 0x01, 0x02,
0x03, 0x00, 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x17, 0x08, 0x8B, 0x18,
0x1F, 0x17, 0x09, 0x81, 0x73, 0x00, 0xFF, 0x00, 0xFF, 0x17, 0x05, 0x86,
0x48, 0x17, 0x04, 0x0C, 0x17, 0x07, 0x86, 0x34, 0x00, 0x00, 0xF0, 0x17,
0x09, 0x87, 0x54, 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x17, 0x0C, 0x81,
0x52, 0x17, 0x0A, 0x1C, 0x17, 0x10, 0x81, 0x6C, 0x17, 0x0A, 0x82, 0x21,
0x17, 0x07, 0x82, 0x4D, 0x17, 0x0A, 0x8A, 0x1B, 0x17, 0x11, 0x2C, 0x76,
0x0C, 0x17, 0x0A, 0x8A, 0x67, 0x17, 0x0F, 0x84, 0x28, 0x17, 0x06, 0x34,
0x17, 0x17, 0x3A, 0x7E, 0x16, 0x40, 0x17, 0x0C, 0x8B, 0x1F, 0x17, 0x2A,
0x38, 0x1E, 0x17, 0x0A, 0x38, 0x17, 0x13, 0x81, 0x28, 0x00, 0xC0, 0x17,
0x17, 0x55, 0x46, 0x24, 0x17, 0x0A, 0x81, 0x28, 0x17, 0x14, 0x38, 0x17,
0x18, 0x81, 0x60, 0x46, 0x2C, 0x17, 0x06, 0x38, 0xEC, 0x17, 0x0D, 0x16,
0x17, 0x0E, 0x82, 0x3C, 0x17, 0x82, 0x0C, 0x8E, 0x68, 0x17, 0x04, 0x24,
0x17, 0x5C, 0x8E, 0x68, 0x17, 0x07, 0x82, 0x5F, 0x80, 0x17, 0x87, 0x01,
0x8E, 0x68, 0x02, 0x17, 0x81, 0x4A, 0x8E, 0x68, 0x17, 0x0C, 0x87, 0x78,
0x17, 0x85, 0x28, 0x8E, 0x68, 0x17, 0x8E, 0x68, 0x9D, 0x50, 0x17, 0x81,
0x24, 0x8E, 0x68, 0x17, 0x04, 0x2C, 0x17, 0x28, 0x8E, 0x68, 0x17, 0x04,
0x30, 0x17, 0x85, 0x3C, 0x8E, 0x68, 0x12, 0x17, 0x07, 0x85, 0x70, 0x17,
0x88, 0x74, 0x8E, 0x68, 0x17, 0x87, 0x3E, 0x9D, 0x50, 0x0C, 0x17, 0x04,
0x04, 0x17, 0x12, 0x8E, 0x68, 0x18, 0x17, 0x87, 0x12, 0xBB, 0x20, 0x17,
0x83, 0x04, 0x9D, 0x50, 0x15, 0x17, 0x05, 0x8D, 0x76, 0x17, 0x0F, 0x8B,
0x49, 0x17, 0x0B, 0x18, 0x32, 0x00, 0x2F, 0x00, 0x32, 0x00, 0x31, 0x00,
0x34, 0x00, 0x36, 0x00, 0x2F, 0x00, 0x33, 0x17, 0x09, 0x84, 0x0C, 0x17,
0x18, 0x18, 0x17, 0x20, 0x8E, 0x68, 0x15, 0x17, 0x07, 0x5A, 0x17, 0x06,
0x5E, 0x16, 0x00, 0x15, 0x17, 0x82, 0x40, 0x9D, 0x50, 0x17, 0x86, 0x5F,
0xBB, 0x20, 0x3A, 0x00, 0x00, 0x00, 0x1D, 0x17, 0x81, 0x4F, 0xAC, 0x38,
0x3B, 0x17, 0x04, 0x04, 0x17, 0x86, 0x30, 0x8E, 0x68, 0x17, 0x81, 0x53,
0xAC, 0x38, 0x07, 0x17, 0x0D, 0x8E, 0x68, 0xA3, 0x72, 0x17, 0x83, 0x10,
0x8E, 0x68
};

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 CTCaer * Copyright (c) 2020-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -16,8 +16,6 @@
#define DRAM_CFG_T210B01_SIZE 2104 #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 = { static const sdram_params_t210b01_t _dram_cfg_08_10_12_14_samsung_hynix_4gb = {
/* Specifies the type of memory device */ /* Specifies the type of memory device */
.memory_type = MEMORY_TYPE_LPDDR4, .memory_type = MEMORY_TYPE_LPDDR4,
@ -109,7 +107,7 @@ static const sdram_params_t210b01_t _dram_cfg_08_10_12_14_samsung_hynix_4gb = {
.emc_pmacro_ca_tx_drive = 0x3F3F3F3F, .emc_pmacro_ca_tx_drive = 0x3F3F3F3F,
.emc_pmacro_cmd_tx_drive = 0x00001220, .emc_pmacro_cmd_tx_drive = 0x00001220,
.emc_pmacro_auto_cal_common = 0x00000804, .emc_pmacro_auto_cal_common = 0x00000804,
.emc_pmacro_zcrtl = 0x505050, .emc_pmacro_zcrtl = 0x00505050,
/* Specifies the time for the calibration to stabilize (in microseconds) */ /* Specifies the time for the calibration to stabilize (in microseconds) */
.emc_auto_cal_wait = 0x000001A1, .emc_auto_cal_wait = 0x000001A1,
@ -708,295 +706,314 @@ static const sdram_params_t210b01_t _dram_cfg_08_10_12_14_samsung_hynix_4gb = {
static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = { static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = {
// Samsung LPDDR4X 4GB X1X2 for prototype Iowa. // Samsung LPDDR4X 4GB X1X2 for prototype Iowa.
{ 0x000E0022, 0x3AC / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dq_rank0_4. { 0x000E0022, 0x3AC / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dq_rank0_4.
{ 0x001B0010, 0x3B0 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dq_rank0_5. { 0x001B0010, 0x3B0 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dq_rank0_5.
{ 0x000E0022, 0x3C4 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dq_rank1_4. { 0x000E0022, 0x3C4 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dq_rank1_4.
{ 0x001B0010, 0x3C8 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dq_rank1_5. { 0x001B0010, 0x3C8 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dq_rank1_5.
{ 0x00490043, 0x3CC / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank0_0. { 0x00490043, 0x3CC / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank0_0.
{ 0x00420045, 0x3D0 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank0_1. { 0x00420045, 0x3D0 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank0_1.
{ 0x00490047, 0x3D4 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank0_2. { 0x00490047, 0x3D4 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank0_2.
{ 0x00460047, 0x3D8 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank0_3. { 0x00460047, 0x3D8 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank0_3.
{ 0x00000016, 0x3DC / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank0_4. { 0x00000016, 0x3DC / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank0_4.
{ 0x00100000, 0x3E0 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank0_5. { 0x00100000, 0x3E0 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank0_5.
{ 0x00490043, 0x3E4 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank1_0. { 0x00490043, 0x3E4 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank1_0.
{ 0x00420045, 0x3E8 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank1_1. { 0x00420045, 0x3E8 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank1_1.
{ 0x00490047, 0x3EC / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank1_2. { 0x00490047, 0x3EC / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank1_2.
{ 0x00460047, 0x3F0 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank1_3. { 0x00460047, 0x3F0 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank1_3.
{ 0x00000016, 0x3F4 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank1_4. { 0x00000016, 0x3F4 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank1_4.
{ 0x00100000, 0x3F8 / 4, DRAM_ID2(7) }, // emc_pmacro_ob_ddll_long_dqs_rank1_5. { 0x00100000, 0x3F8 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank1_5.
{ 0x00220022, 0x41C / 4, DRAM_ID2(7) }, // emc_pmacro_ddll_long_cmd_0. { 0x00220022, 0x41C / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ddll_long_cmd_0.
{ 0x000E000E, 0x420 / 4, DRAM_ID2(7) }, // emc_pmacro_ddll_long_cmd_1. { 0x000E000E, 0x420 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ddll_long_cmd_1.
{ 0x00100010, 0x424 / 4, DRAM_ID2(7) }, // emc_pmacro_ddll_long_cmd_2. { 0x00100010, 0x424 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ddll_long_cmd_2.
{ 0x001B001B, 0x428 / 4, DRAM_ID2(7) }, // emc_pmacro_ddll_long_cmd_3. { 0x001B001B, 0x428 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ddll_long_cmd_3.
{ 0x00000022, 0x42C / 4, DRAM_ID2(7) }, // emc_pmacro_ddll_long_cmd_4. { 0x00000022, 0x42C / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ddll_long_cmd_4.
// Samsung LPDDR4X 8GB K4UBE3D4AM-MGCJ for SDEV Iowa and Hoag. // Samsung LPDDR4X 8GB K4UBE3D4AM-MGCJ Die-M for SDEV Iowa and Hoag.
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_auto_cal_config2. { 0x05500000, 0x0D4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_auto_cal_config2.
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_auto_cal_vref_sel0. { 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_auto_cal_vref_sel0.
{ 0x00000001, 0x134 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_adr_cfg. 2 Ranks. { 0x00000001, 0x134 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_adr_cfg. 2 Ranks.
{ 0x00000006, 0x1CC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_quse. { 0x00000006, 0x1CC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_quse.
{ 0x00000005, 0x1D0 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_quse_width. { 0x00000005, 0x1D0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_quse_width.
{ 0x00000003, 0x1DC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_einput. { 0x00000003, 0x1DC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_einput.
{ 0x0000000C, 0x1E0 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_einput_duration. { 0x0000000C, 0x1E0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_einput_duration.
{ 0x08010004, 0x2B8 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw1. { 0x08010004, 0x2B8 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw1.
{ 0x08020000, 0x2BC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw2. { 0x08020000, 0x2BC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw2.
{ 0x080D0000, 0x2C0 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw3. { 0x080D0000, 0x2C0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw3.
{ 0x08033131, 0x2C8 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw6. { 0x08033131, 0x2C8 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw6.
{ 0x080B0000, 0x2CC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw8. { 0x080B0000, 0x2CC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw8.
{ 0x0C0E5D5D, 0x2D0 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw9. { 0x0C0E5D5D, 0x2D0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw9.
{ 0x080C5D5D, 0x2D4 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw10. { 0x080C5D5D, 0x2D4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw10.
{ 0x0C0D0808, 0x2D8 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw12. { 0x0C0D0808, 0x2D8 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw12.
{ 0x0C0D0000, 0x2DC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw13. { 0x0C0D0000, 0x2DC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw13.
{ 0x08161414, 0x2E0 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw14. { 0x08161414, 0x2E0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw14.
{ 0x08010004, 0x2E4 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_mrw_extra. { 0x08010004, 0x2E4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw_extra.
{ 0x00000000, 0x340 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_dev_select. Both devices. { 0x00000000, 0x340 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_dev_select. Both devices.
{ 0x35353535, 0x350 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_ib_vref_dq_0. { 0x35353535, 0x350 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_vref_dq_0.
{ 0x35353535, 0x354 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_ib_vref_dq_1. { 0x35353535, 0x354 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_vref_dq_1.
{ 0x00100010, 0x3FC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_ib_ddll_long_dqs_rank0_0. { 0x00100010, 0x3FC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // 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, 0x400 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // 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, 0x404 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // 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, 0x408 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // 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, 0x40C / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // 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, 0x410 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // 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, 0x414 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // 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. { 0x00100010, 0x418 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank1_3.
{ 0x0051004F, 0x450 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_zcal_mrw_cmd. { 0x0051004F, 0x450 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_zcal_mrw_cmd.
{ 0x40000001, 0x45C / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_zcal_init_dev1. { 0x40000001, 0x45C / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_zcal_init_dev1.
{ 0x00000000, 0x594 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_tx_pwrd4. { 0x00000000, 0x594 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_tx_pwrd4.
{ 0x00001000, 0x598 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_tx_pwrd5. { 0x00001000, 0x598 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_tx_pwrd5.
{ 0x00000001, 0x630 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_adr_cfg. 2 Ranks. { 0x00000001, 0x630 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // mc_emem_adr_cfg. 2 Ranks.
{ 0x00002000, 0x64C / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_cfg. 8GB total density. { 0x00002000, 0x64C / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // mc_emem_cfg. 8GB total density.
{ 0x00000002, 0x680 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_arb_timing_r2r. { 0x00000002, 0x680 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // mc_emem_arb_timing_r2r.
{ 0x02020001, 0x694 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_arb_da_turns. { 0x02020001, 0x694 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // mc_emem_arb_da_turns.
{ 0x2A800000, 0x6DC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_video_protect_gpu_override0. { 0x2A800000, 0x6DC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_video_protect_gpu_override1. { 0x00000002, 0x6E0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // mc_video_protect_gpu_override1.
// Micron LPDDR4X 4GB MT53D1024M32D1NP-053-WT for Iowa and Hoag. // Micron LPDDR4X 4GB MT53D1024M32D1NP-053-WT Die-E for retail Iowa and Hoag.
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(11) | DRAM_ID2(15) }, // emc_auto_cal_config2. { 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046 }, // emc_auto_cal_config2.
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(11) | DRAM_ID2(15) }, // emc_auto_cal_vref_sel0. { 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046 }, // emc_auto_cal_vref_sel0.
{ 0x88161414, 0x2E0 / 4, DRAM_ID2(11) | DRAM_ID2(15) }, // emc_mrw14. { 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046 }, // emc_mrw14.
{ 0x80000713, 0x32C / 4, DRAM_ID2(11) | DRAM_ID2(15) }, // emc_dyn_self_ref_control. { 0x80000713, 0x32C / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046 }, // emc_dyn_self_ref_control.
{ 0x2A800000, 0x6DC / 4, DRAM_ID2(11) | DRAM_ID2(15) }, // mc_video_protect_gpu_override0. { 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046 }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, DRAM_ID2(11) | DRAM_ID2(15) }, // mc_video_protect_gpu_override1. { 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046 }, // mc_video_protect_gpu_override1.
// Samsung LPDDR4X 4GB Die-Y for Iowa. // Samsung LPDDR4X 4GB (Y01) Die-? for Iowa.
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(16) }, // emc_auto_cal_config2. { 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_auto_cal_config2.
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(16) }, // emc_auto_cal_vref_sel0. { 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_auto_cal_vref_sel0.
{ 0x88161414, 0x2E0 / 4, DRAM_ID2(16) }, // emc_mrw14. { 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_mrw14.
{ 0x80000713, 0x32C / 4, DRAM_ID2(16) }, // emc_dyn_self_ref_control. { 0x80000713, 0x32C / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_dyn_self_ref_control.
{ 0x32323232, 0x350 / 4, DRAM_ID2(16) }, // emc_pmacro_ib_vref_dq_0. { 0x32323232, 0x350 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_vref_dq_0.
{ 0x32323232, 0x354 / 4, DRAM_ID2(16) }, // emc_pmacro_ib_vref_dq_1. { 0x32323232, 0x354 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_vref_dq_1.
{ 0x000F0018, 0x3AC / 4, DRAM_ID2(16) }, // emc_pmacro_ob_ddll_long_dq_rank0_4. { 0x000F0018, 0x3AC / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dq_rank0_4.
{ 0x000F0018, 0x3C4 / 4, DRAM_ID2(16) }, // emc_pmacro_ob_ddll_long_dq_rank1_4. { 0x000F0018, 0x3C4 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dq_rank1_4.
{ 0x00440048, 0x3CC / 4, DRAM_ID2(16) }, // emc_pmacro_ob_ddll_long_dqs_rank0_0. { 0x00440048, 0x3CC / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_0.
{ 0x00440045, 0x3D0 / 4, DRAM_ID2(16) }, // emc_pmacro_ob_ddll_long_dqs_rank0_1. { 0x00440045, 0x3D0 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_1.
{ 0x00470047, 0x3D4 / 4, DRAM_ID2(16) }, // emc_pmacro_ob_ddll_long_dqs_rank0_2. { 0x00470047, 0x3D4 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_2.
{ 0x0005000D, 0x3DC / 4, DRAM_ID2(16) }, // emc_pmacro_ob_ddll_long_dqs_rank0_4. { 0x0005000D, 0x3DC / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_4.
{ 0x00440048, 0x3E4 / 4, DRAM_ID2(16) }, // emc_pmacro_ob_ddll_long_dqs_rank1_0. { 0x00440048, 0x3E4 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_0.
{ 0x00440045, 0x3E8 / 4, DRAM_ID2(16) }, // emc_pmacro_ob_ddll_long_dqs_rank1_1. { 0x00440045, 0x3E8 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_1.
{ 0x00470047, 0x3EC / 4, DRAM_ID2(16) }, // emc_pmacro_ob_ddll_long_dqs_rank1_2. { 0x00470047, 0x3EC / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_2.
{ 0x0005000D, 0x3F4 / 4, DRAM_ID2(16) }, // emc_pmacro_ob_ddll_long_dqs_rank1_4. { 0x0005000D, 0x3F4 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_4.
{ 0x00780078, 0x3FC / 4, DRAM_ID2(16) }, // emc_pmacro_ib_ddll_long_dqs_rank0_0. { 0x00780078, 0x3FC / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank0_0.
{ 0x00780078, 0x400 / 4, DRAM_ID2(16) }, // emc_pmacro_ib_ddll_long_dqs_rank0_1. { 0x00780078, 0x400 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank0_1.
{ 0x00780078, 0x404 / 4, DRAM_ID2(16) }, // emc_pmacro_ib_ddll_long_dqs_rank0_2. { 0x00780078, 0x404 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank0_2.
{ 0x00780078, 0x408 / 4, DRAM_ID2(16) }, // emc_pmacro_ib_ddll_long_dqs_rank0_3. { 0x00780078, 0x408 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank0_3.
{ 0x00780078, 0x40C / 4, DRAM_ID2(16) }, // emc_pmacro_ib_ddll_long_dqs_rank1_0. { 0x00780078, 0x40C / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank1_0.
{ 0x00780078, 0x410 / 4, DRAM_ID2(16) }, // emc_pmacro_ib_ddll_long_dqs_rank1_1. { 0x00780078, 0x410 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank1_1.
{ 0x00780078, 0x414 / 4, DRAM_ID2(16) }, // emc_pmacro_ib_ddll_long_dqs_rank1_2. { 0x00780078, 0x414 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank1_2.
{ 0x00780078, 0x418 / 4, DRAM_ID2(16) }, // emc_pmacro_ib_ddll_long_dqs_rank1_3. { 0x00780078, 0x418 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank1_3.
{ 0x00180018, 0x41C / 4, DRAM_ID2(16) }, // emc_pmacro_ddll_long_cmd_0. { 0x00180018, 0x41C / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ddll_long_cmd_0.
{ 0x000F000F, 0x420 / 4, DRAM_ID2(16) }, // emc_pmacro_ddll_long_cmd_1. { 0x000F000F, 0x420 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ddll_long_cmd_1.
{ 0x00000018, 0x42C / 4, DRAM_ID2(16) }, // emc_pmacro_ddll_long_cmd_4. { 0x00000018, 0x42C / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ddll_long_cmd_4.
{ 0x2A800000, 0x6DC / 4, DRAM_ID2(16) }, // mc_video_protect_gpu_override0. { 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_SAMSUNG_Y }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, DRAM_ID2(16) }, // mc_video_protect_gpu_override1. { 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // mc_video_protect_gpu_override1.
// Samsung LPDDR4X 4GB 10nm-class (1y) Die-X for Iowa, Hoag and Aula. // Samsung LPDDR4X 4GB K4U6E3S4AA-MGCL 10nm-class (1y-X03) Die-A for retail Iowa, Hoag and Aula.
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_auto_cal_config2. { 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_auto_cal_config2.
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_auto_cal_vref_sel0. { 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_auto_cal_vref_sel0.
{ 0x00000006, 0x1CC / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_quse. { 0x00000006, 0x1CC / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_quse.
{ 0x00000005, 0x1D0 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_quse_width. { 0x00000005, 0x1D0 / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_quse_width.
{ 0x00000003, 0x1DC / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_einput. { 0x00000003, 0x1DC / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_einput.
{ 0x0000000C, 0x1E0 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_einput_duration. { 0x0000000C, 0x1E0 / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_einput_duration.
{ 0x88161414, 0x2E0 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_mrw14. { 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_mrw14.
{ 0x80000713, 0x32C / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_dyn_self_ref_control. { 0x80000713, 0x32C / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_dyn_self_ref_control.
{ 0x2A800000, 0x6DC / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // mc_video_protect_gpu_override0. { 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // mc_video_protect_gpu_override1. { 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // mc_video_protect_gpu_override1.
// Samsung LPDDR4X 8GB 10nm-class (1y) Die-X for SDEV Iowa and Aula. // Samsung LPDDR4X 8GB K4UBE3D4AA-MGCL 10nm-class (1y-X03) Die-A for SDEV Iowa, Hoag and Aula.
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_auto_cal_config2. { 0x05500000, 0x0D4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_auto_cal_config2.
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_auto_cal_vref_sel0. { 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_auto_cal_vref_sel0.
{ 0x00000001, 0x134 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_adr_cfg. 2 Ranks. { 0x00000001, 0x134 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_adr_cfg. 2 Ranks.
{ 0x00000006, 0x1CC / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_quse. { 0x00000006, 0x1CC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_quse.
{ 0x00000005, 0x1D0 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_quse_width. { 0x00000005, 0x1D0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_quse_width.
{ 0x00000003, 0x1DC / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_einput. { 0x00000003, 0x1DC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_einput.
{ 0x0000000C, 0x1E0 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_einput_duration. { 0x0000000C, 0x1E0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_einput_duration.
{ 0x00000008, 0x24C / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_tfaw. { 0x00000008, 0x24C / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_tfaw.
{ 0x08010004, 0x2B8 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw1. { 0x08010004, 0x2B8 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw1.
{ 0x08020000, 0x2BC / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw2. { 0x08020000, 0x2BC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw2.
{ 0x080D0000, 0x2C0 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw3. { 0x080D0000, 0x2C0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw3.
{ 0x08033131, 0x2C8 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw6. { 0x08033131, 0x2C8 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw6.
{ 0x080B0000, 0x2CC / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw8. { 0x080B0000, 0x2CC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw8.
{ 0x0C0E5D5D, 0x2D0 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw9. { 0x0C0E5D5D, 0x2D0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw9.
{ 0x080C5D5D, 0x2D4 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw10. { 0x080C5D5D, 0x2D4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw10.
{ 0x0C0D0808, 0x2D8 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw12. { 0x0C0D0808, 0x2D8 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw12.
{ 0x0C0D0000, 0x2DC / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw13. { 0x0C0D0000, 0x2DC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw13.
{ 0x08161414, 0x2E0 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw14. { 0x08161414, 0x2E0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw14.
{ 0x08010004, 0x2E4 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_mrw_extra. { 0x08010004, 0x2E4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw_extra.
{ 0x00000000, 0x340 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_dev_select. Both devices. { 0x00000000, 0x340 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_dev_select. Both devices.
{ 0x0051004F, 0x450 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_zcal_mrw_cmd. { 0x0051004F, 0x450 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_zcal_mrw_cmd.
{ 0x40000001, 0x45C / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_zcal_init_dev1. { 0x40000001, 0x45C / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_zcal_init_dev1.
{ 0x00000000, 0x594 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_pmacro_tx_pwrd4. { 0x00000000, 0x594 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_pmacro_tx_pwrd4.
{ 0x00001000, 0x598 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_pmacro_tx_pwrd5. { 0x00001000, 0x598 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_pmacro_tx_pwrd5.
{ 0x00000001, 0x630 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_adr_cfg. 2 Ranks. { 0x00000001, 0x630 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_emem_adr_cfg. 2 Ranks.
{ 0x00002000, 0x64C / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_cfg. 8GB total density. { 0x00002000, 0x64C / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_emem_cfg. 8GB total density.
{ 0x00000001, 0x670 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_arb_timing_faw. { 0x00000001, 0x670 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_emem_arb_timing_faw.
{ 0x00000002, 0x680 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_arb_timing_r2r. { 0x00000002, 0x680 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_emem_arb_timing_r2r.
{ 0x02020001, 0x694 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_arb_da_turns. { 0x02020001, 0x694 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_emem_arb_da_turns.
{ 0x2A800000, 0x6DC / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_video_protect_gpu_override0. { 0x2A800000, 0x6DC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_video_protect_gpu_override1. { 0x00000002, 0x6E0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_video_protect_gpu_override1.
// Samsung LPDDR4X 4GB 10nm-class (1y) Die-Y for Iowa. // Samsung LPDDR4X 4GB 10nm-class (1y-Y01) Die-? for Iowa.
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(20) }, // emc_auto_cal_config2. { 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_auto_cal_config2.
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(20) }, // emc_auto_cal_vref_sel0. { 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_auto_cal_vref_sel0.
{ 0x00000008, 0x24C / 4, DRAM_ID2(20) }, // emc_tfaw. { 0x00000008, 0x24C / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_tfaw.
{ 0x88161414, 0x2E0 / 4, DRAM_ID2(20) }, // emc_mrw14. { 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_mrw14.
{ 0x80000713, 0x32C / 4, DRAM_ID2(20) }, // emc_dyn_self_ref_control. { 0x80000713, 0x32C / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_dyn_self_ref_control.
{ 0x000F0018, 0x3AC / 4, DRAM_ID2(20) }, // emc_pmacro_ob_ddll_long_dq_rank0_4. { 0x000F0018, 0x3AC / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dq_rank0_4.
{ 0x000F0018, 0x3C4 / 4, DRAM_ID2(20) }, // emc_pmacro_ob_ddll_long_dq_rank1_4. { 0x000F0018, 0x3C4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dq_rank1_4.
{ 0x00440048, 0x3CC / 4, DRAM_ID2(20) }, // emc_pmacro_ob_ddll_long_dqs_rank0_0. { 0x00440048, 0x3CC / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_0.
{ 0x00440045, 0x3D0 / 4, DRAM_ID2(20) }, // emc_pmacro_ob_ddll_long_dqs_rank0_1. { 0x00440045, 0x3D0 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_1.
{ 0x00470047, 0x3D4 / 4, DRAM_ID2(20) }, // emc_pmacro_ob_ddll_long_dqs_rank0_2. { 0x00470047, 0x3D4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_2.
{ 0x0005000D, 0x3DC / 4, DRAM_ID2(20) }, // emc_pmacro_ob_ddll_long_dqs_rank0_4. { 0x0005000D, 0x3DC / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_4.
{ 0x00440048, 0x3E4 / 4, DRAM_ID2(20) }, // emc_pmacro_ob_ddll_long_dqs_rank1_0. { 0x00440048, 0x3E4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_0.
{ 0x00440045, 0x3E8 / 4, DRAM_ID2(20) }, // emc_pmacro_ob_ddll_long_dqs_rank1_1. { 0x00440045, 0x3E8 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_1.
{ 0x00470047, 0x3EC / 4, DRAM_ID2(20) }, // emc_pmacro_ob_ddll_long_dqs_rank1_2. { 0x00470047, 0x3EC / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_2.
{ 0x0005000D, 0x3F4 / 4, DRAM_ID2(20) }, // emc_pmacro_ob_ddll_long_dqs_rank1_4. { 0x0005000D, 0x3F4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_4.
{ 0x00180018, 0x41C / 4, DRAM_ID2(20) }, // emc_pmacro_ddll_long_cmd_0. { 0x00180018, 0x41C / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ddll_long_cmd_0.
{ 0x000F000F, 0x420 / 4, DRAM_ID2(20) }, // emc_pmacro_ddll_long_cmd_1. { 0x000F000F, 0x420 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ddll_long_cmd_1.
{ 0x00000018, 0x42C / 4, DRAM_ID2(20) }, // emc_pmacro_ddll_long_cmd_4. { 0x00000018, 0x42C / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ddll_long_cmd_4.
{ 0x00000001, 0x670 / 4, DRAM_ID2(20) }, // mc_emem_arb_timing_faw. { 0x00000001, 0x670 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // mc_emem_arb_timing_faw.
{ 0x2A800000, 0x6DC / 4, DRAM_ID2(20) }, // mc_video_protect_gpu_override0. { 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, DRAM_ID2(20) }, // mc_video_protect_gpu_override1. { 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // mc_video_protect_gpu_override1.
// Samsung LPDDR4X 8GB 10nm-class (1y) Die-Y for SDEV Iowa. // Samsung LPDDR4X 8GB 10nm-class (1y-Y01) Die-? for SDEV Iowa.
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(21) }, // emc_auto_cal_config2. { 0x05500000, 0x0D4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_auto_cal_config2.
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(21) }, // emc_auto_cal_vref_sel0. { 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_auto_cal_vref_sel0.
{ 0x00000001, 0x134 / 4, DRAM_ID2(21) }, // emc_adr_cfg. 2 Ranks. { 0x00000001, 0x134 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_adr_cfg. 2 Ranks.
{ 0x00000008, 0x24C / 4, DRAM_ID2(21) }, // emc_tfaw. { 0x00000008, 0x24C / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_tfaw.
{ 0x08010004, 0x2B8 / 4, DRAM_ID2(21) }, // emc_mrw1. { 0x08010004, 0x2B8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw1.
{ 0x08020000, 0x2BC / 4, DRAM_ID2(21) }, // emc_mrw2. { 0x08020000, 0x2BC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw2.
{ 0x080D0000, 0x2C0 / 4, DRAM_ID2(21) }, // emc_mrw3. { 0x080D0000, 0x2C0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw3.
{ 0x08033131, 0x2C8 / 4, DRAM_ID2(21) }, // emc_mrw6. { 0x08033131, 0x2C8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw6.
{ 0x080B0000, 0x2CC / 4, DRAM_ID2(21) }, // emc_mrw8. { 0x080B0000, 0x2CC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw8.
{ 0x0C0E5D5D, 0x2D0 / 4, DRAM_ID2(21) }, // emc_mrw9. { 0x0C0E5D5D, 0x2D0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw9.
{ 0x080C5D5D, 0x2D4 / 4, DRAM_ID2(21) }, // emc_mrw10. { 0x080C5D5D, 0x2D4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw10.
{ 0x0C0D0808, 0x2D8 / 4, DRAM_ID2(21) }, // emc_mrw12. { 0x0C0D0808, 0x2D8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw12.
{ 0x0C0D0000, 0x2DC / 4, DRAM_ID2(21) }, // emc_mrw13. { 0x0C0D0000, 0x2DC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw13.
{ 0x08161414, 0x2E0 / 4, DRAM_ID2(21) }, // emc_mrw14. { 0x08161414, 0x2E0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw14.
{ 0x08010004, 0x2E4 / 4, DRAM_ID2(21) }, // emc_mrw_extra. { 0x08010004, 0x2E4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw_extra.
{ 0x00000000, 0x340 / 4, DRAM_ID2(21) }, // emc_dev_select. Both devices. { 0x00000000, 0x340 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_dev_select. Both devices.
{ 0x32323232, 0x350 / 4, DRAM_ID2(21) }, // emc_pmacro_ib_vref_dq_0. { 0x32323232, 0x350 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ib_vref_dq_0.
{ 0x32323232, 0x354 / 4, DRAM_ID2(21) }, // emc_pmacro_ib_vref_dq_1. { 0x32323232, 0x354 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ib_vref_dq_1.
{ 0x000F0018, 0x3AC / 4, DRAM_ID2(21) }, // emc_pmacro_ob_ddll_long_dq_rank0_4. { 0x000F0018, 0x3AC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dq_rank0_4.
{ 0x000F0018, 0x3C4 / 4, DRAM_ID2(21) }, // emc_pmacro_ob_ddll_long_dq_rank1_4. { 0x000F0018, 0x3C4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dq_rank1_4.
{ 0x00440048, 0x3CC / 4, DRAM_ID2(21) }, // emc_pmacro_ob_ddll_long_dqs_rank0_0. { 0x00440048, 0x3CC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_0.
{ 0x00440045, 0x3D0 / 4, DRAM_ID2(21) }, // emc_pmacro_ob_ddll_long_dqs_rank0_1. { 0x00440045, 0x3D0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_1.
{ 0x00470047, 0x3D4 / 4, DRAM_ID2(21) }, // emc_pmacro_ob_ddll_long_dqs_rank0_2. { 0x00470047, 0x3D4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_2.
{ 0x0005000D, 0x3DC / 4, DRAM_ID2(21) }, // emc_pmacro_ob_ddll_long_dqs_rank0_4. { 0x0005000D, 0x3DC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_4.
{ 0x00440048, 0x3E4 / 4, DRAM_ID2(21) }, // emc_pmacro_ob_ddll_long_dqs_rank1_0. { 0x00440048, 0x3E4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_0.
{ 0x00440045, 0x3E8 / 4, DRAM_ID2(21) }, // emc_pmacro_ob_ddll_long_dqs_rank1_1. { 0x00440045, 0x3E8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_1.
{ 0x00470047, 0x3EC / 4, DRAM_ID2(21) }, // emc_pmacro_ob_ddll_long_dqs_rank1_2. { 0x00470047, 0x3EC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_2.
{ 0x0005000D, 0x3F4 / 4, DRAM_ID2(21) }, // emc_pmacro_ob_ddll_long_dqs_rank1_4. { 0x0005000D, 0x3F4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_4.
{ 0x00180018, 0x41C / 4, DRAM_ID2(21) }, // emc_pmacro_ddll_long_cmd_0. { 0x00180018, 0x41C / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ddll_long_cmd_0.
{ 0x000F000F, 0x420 / 4, DRAM_ID2(21) }, // emc_pmacro_ddll_long_cmd_1. { 0x000F000F, 0x420 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ddll_long_cmd_1.
{ 0x00000018, 0x42C / 4, DRAM_ID2(21) }, // emc_pmacro_ddll_long_cmd_4. { 0x00000018, 0x42C / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ddll_long_cmd_4.
{ 0x0051004F, 0x450 / 4, DRAM_ID2(21) }, // emc_zcal_mrw_cmd. { 0x0051004F, 0x450 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_zcal_mrw_cmd.
{ 0x40000001, 0x45C / 4, DRAM_ID2(21) }, // emc_zcal_init_dev1. { 0x40000001, 0x45C / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_zcal_init_dev1.
{ 0x00000000, 0x594 / 4, DRAM_ID2(21) }, // emc_pmacro_tx_pwrd4. { 0x00000000, 0x594 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_tx_pwrd4.
{ 0x00001000, 0x598 / 4, DRAM_ID2(21) }, // emc_pmacro_tx_pwrd5. { 0x00001000, 0x598 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_tx_pwrd5.
{ 0x00000001, 0x630 / 4, DRAM_ID2(21) }, // mc_emem_adr_cfg. 2 Ranks. { 0x00000001, 0x630 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_emem_adr_cfg. 2 Ranks.
{ 0x00002000, 0x64C / 4, DRAM_ID2(21) }, // mc_emem_cfg. 8GB total density. { 0x00002000, 0x64C / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_emem_cfg. 8GB total density.
{ 0x00000001, 0x670 / 4, DRAM_ID2(21) }, // mc_emem_arb_timing_faw. { 0x00000001, 0x670 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_emem_arb_timing_faw.
{ 0x00000002, 0x680 / 4, DRAM_ID2(21) }, // mc_emem_arb_timing_r2r. { 0x00000002, 0x680 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_emem_arb_timing_r2r.
{ 0x02020001, 0x694 / 4, DRAM_ID2(21) }, // mc_emem_arb_da_turns. { 0x02020001, 0x694 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_emem_arb_da_turns.
{ 0x2A800000, 0x6DC / 4, DRAM_ID2(21) }, // mc_video_protect_gpu_override0. { 0x2A800000, 0x6DC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, DRAM_ID2(21) }, // mc_video_protect_gpu_override1. { 0x00000002, 0x6E0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_video_protect_gpu_override1.
// Samsung LPDDR4X 4GB 10nm-class (1y) Die-A for Unknown Aula. /*
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(22) }, // emc_auto_cal_config2. // Samsung LPDDR4X 4GB 10nm-class (1y-A01) Die-? for prototype (?) Aula. Unused.
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(22) }, // emc_auto_cal_vref_sel0. { 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_auto_cal_config2.
{ 0x00000008, 0x24C / 4, DRAM_ID2(22) }, // emc_tfaw. { 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_auto_cal_vref_sel0.
{ 0x1C041B06, 0x26C / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd0_0. { 0x00000008, 0x24C / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_tfaw.
{ 0x02050307, 0x270 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd0_1. { 0x1C041B06, 0x26C / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_cmd_mapping_cmd0_0.
{ 0x03252500, 0x274 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd0_2. { 0x02050307, 0x270 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_cmd_mapping_cmd0_1.
{ 0x081D1E00, 0x278 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd1_0. { 0x03252500, 0x274 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_cmd_mapping_cmd0_2.
{ 0x090C0A0D, 0x27C / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd1_1. { 0x081D1E00, 0x278 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_cmd_mapping_cmd1_0.
{ 0x0526260B, 0x280 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd1_2. { 0x090C0A0D, 0x27C / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_cmd_mapping_cmd1_1.
{ 0x05030402, 0x284 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd2_0. { 0x0526260B, 0x280 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_cmd_mapping_cmd1_2.
{ 0x1B1C0600, 0x288 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd2_1. { 0x05030402, 0x284 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_cmd_mapping_cmd2_0.
{ 0x07252507, 0x28C / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd2_2. { 0x1B1C0600, 0x288 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_cmd_mapping_cmd2_1.
{ 0x0C1D0B0A, 0x290 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd3_0. { 0x07252507, 0x28C / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_cmd_mapping_cmd2_2.
{ 0x0800090D, 0x294 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd3_1. { 0x0C1D0B0A, 0x290 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_cmd_mapping_cmd3_0.
{ 0x0926261E, 0x298 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd3_2. { 0x0800090D, 0x294 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_cmd_mapping_cmd3_1.
{ 0x2A080624, 0x29C / 4, DRAM_ID2(22) }, // emc_cmd_mapping_byte. { 0x0926261E, 0x298 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_cmd_mapping_cmd3_2.
{ 0x88161414, 0x2E0 / 4, DRAM_ID2(22) }, // emc_mrw14. { 0x2A080624, 0x29C / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_cmd_mapping_byte.
{ 0x80000713, 0x32C / 4, DRAM_ID2(22) }, // emc_dyn_self_ref_control. { 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_mrw14.
{ 0x00140010, 0x3AC / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dq_rank0_4. { 0x80000713, 0x32C / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_dyn_self_ref_control.
{ 0x0013000B, 0x3B0 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dq_rank0_5. { 0x00140010, 0x3AC / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_pmacro_ob_ddll_long_dq_rank0_4.
{ 0x00140010, 0x3C4 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dq_rank1_4. { 0x0013000B, 0x3B0 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_pmacro_ob_ddll_long_dq_rank0_5.
{ 0x0013000B, 0x3C8 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dq_rank1_5. { 0x00140010, 0x3C4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_pmacro_ob_ddll_long_dq_rank1_4.
{ 0x00450047, 0x3CC / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank0_0. { 0x0013000B, 0x3C8 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_pmacro_ob_ddll_long_dq_rank1_5.
{ 0x004D004F, 0x3D0 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank0_1. { 0x00450047, 0x3CC / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_pmacro_ob_ddll_long_dqs_rank0_0.
{ 0x00460046, 0x3D4 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank0_2. { 0x004D004F, 0x3D0 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_pmacro_ob_ddll_long_dqs_rank0_1.
{ 0x00480048, 0x3D8 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank0_3. { 0x00460046, 0x3D4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_pmacro_ob_ddll_long_dqs_rank0_2.
{ 0x000C0008, 0x3DC / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank0_4. { 0x00480048, 0x3D8 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_pmacro_ob_ddll_long_dqs_rank0_3.
{ 0x000B000C, 0x3E0 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank0_5. { 0x000C0008, 0x3DC / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_pmacro_ob_ddll_long_dqs_rank0_4.
{ 0x00450047, 0x3E4 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank1_0. { 0x000B000C, 0x3E0 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_pmacro_ob_ddll_long_dqs_rank0_5.
{ 0x004D004F, 0x3E8 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank1_1. { 0x00450047, 0x3E4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_pmacro_ob_ddll_long_dqs_rank1_0.
{ 0x00460046, 0x3EC / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank1_2. { 0x004D004F, 0x3E8 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_pmacro_ob_ddll_long_dqs_rank1_1.
{ 0x00480048, 0x3F0 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank1_3. { 0x00460046, 0x3EC / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_pmacro_ob_ddll_long_dqs_rank1_2.
{ 0x000C0008, 0x3F4 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank1_4. { 0x00480048, 0x3F0 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_pmacro_ob_ddll_long_dqs_rank1_3.
{ 0x000B000C, 0x3F8 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank1_5. { 0x000C0008, 0x3F4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_pmacro_ob_ddll_long_dqs_rank1_4.
{ 0x00100010, 0x41C / 4, DRAM_ID2(22) }, // emc_pmacro_ddll_long_cmd_0. { 0x000B000C, 0x3F8 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_pmacro_ob_ddll_long_dqs_rank1_5.
{ 0x00140014, 0x420 / 4, DRAM_ID2(22) }, // emc_pmacro_ddll_long_cmd_1. { 0x00100010, 0x41C / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_pmacro_ddll_long_cmd_0.
{ 0x00130013, 0x428 / 4, DRAM_ID2(22) }, // emc_pmacro_ddll_long_cmd_3. { 0x00140014, 0x420 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_pmacro_ddll_long_cmd_1.
{ 0x00000010, 0x42C / 4, DRAM_ID2(22) }, // emc_pmacro_ddll_long_cmd_4. { 0x00130013, 0x428 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_pmacro_ddll_long_cmd_3.
{ 0x40280100, 0x4B4 / 4, DRAM_ID2(22) }, // pmc_ddr_cfg. { 0x00000010, 0x42C / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_pmacro_ddll_long_cmd_4.
{ 0x4F9F9FFF, 0x4B8 / 4, DRAM_ID2(22) }, // pmc_io_dpd3_req. { 0x40280100, 0x4B4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // pmc_ddr_cfg.
{ 0x64032157, 0x4D8 / 4, DRAM_ID2(22) }, // emc_swizzle_rank0_byte0. { 0x4F9F9FFF, 0x4B8 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // pmc_io_dpd3_req.
{ 0x51320467, 0x4DC / 4, DRAM_ID2(22) }, // emc_swizzle_rank0_byte1. { 0x64032157, 0x4D8 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_swizzle_rank0_byte0.
{ 0x04735621, 0x4E0 / 4, DRAM_ID2(22) }, // emc_swizzle_rank0_byte2. { 0x51320467, 0x4DC / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_swizzle_rank0_byte1.
{ 0x47356012, 0x4E4 / 4, DRAM_ID2(22) }, // emc_swizzle_rank0_byte3. { 0x04735621, 0x4E0 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_swizzle_rank0_byte2.
{ 0x12045673, 0x4E8 / 4, DRAM_ID2(22) }, // emc_swizzle_rank1_byte0. { 0x47356012, 0x4E4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_swizzle_rank0_byte3.
{ 0x43657210, 0x4EC / 4, DRAM_ID2(22) }, // emc_swizzle_rank1_byte1. { 0x12045673, 0x4E8 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_swizzle_rank1_byte0.
{ 0x65402137, 0x4F0 / 4, DRAM_ID2(22) }, // emc_swizzle_rank1_byte2. { 0x43657210, 0x4EC / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_swizzle_rank1_byte1.
{ 0x57302164, 0x4F4 / 4, DRAM_ID2(22) }, // emc_swizzle_rank1_byte3. { 0x65402137, 0x4F0 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_swizzle_rank1_byte2.
{ 0x4F9F9FFF, 0x534 / 4, DRAM_ID2(22) }, // emc_pmc_scratch1. { 0x57302164, 0x4F4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_swizzle_rank1_byte3.
{ 0x4033CF1F, 0x53C / 4, DRAM_ID2(22) }, // emc_pmc_scratch3. { 0x4F9F9FFF, 0x534 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_pmc_scratch1.
{ 0x10000000, 0x590 / 4, DRAM_ID2(22) }, // emc_pmacro_tx_pwrd3. { 0x4033CF1F, 0x53C / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_pmc_scratch3.
{ 0x00030108, 0x594 / 4, DRAM_ID2(22) }, // emc_pmacro_tx_pwrd4. { 0x10000000, 0x590 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_pmacro_tx_pwrd3.
{ 0x01400050, 0x598 / 4, DRAM_ID2(22) }, // emc_pmacro_tx_pwrd5. { 0x00030108, 0x594 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_pmacro_tx_pwrd4.
{ 0x29081081, 0x5A0 / 4, DRAM_ID2(22) }, // emc_pmacro_brick_mapping0. { 0x01400050, 0x598 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_pmacro_tx_pwrd5.
{ 0x54A59332, 0x5A4 / 4, DRAM_ID2(22) }, // emc_pmacro_brick_mapping1. { 0x29081081, 0x5A0 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_pmacro_brick_mapping0.
{ 0x87766B4A, 0x5A8 / 4, DRAM_ID2(22) }, // emc_pmacro_brick_mapping2. { 0x54A59332, 0x5A4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_pmacro_brick_mapping1.
{ 0x00000001, 0x670 / 4, DRAM_ID2(22) }, // mc_emem_arb_timing_faw. { 0x87766B4A, 0x5A8 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // emc_pmacro_brick_mapping2.
{ 0xE4FACB43, 0x6D4 / 4, DRAM_ID2(22) }, // mc_video_protect_vpr_override. + TSEC, NVENC. { 0x00000001, 0x670 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // mc_emem_arb_timing_faw.
{ 0x0600FED3, 0x6D8 / 4, DRAM_ID2(22) }, // mc_video_protect_vpr_override1. + TSECB, TSEC1, TSECB1. { 0xE4FACB43, 0x6D4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // mc_video_protect_vpr_override. + TSEC, NVENC.
{ 0x2A800000, 0x6DC / 4, DRAM_ID2(22) }, // mc_video_protect_gpu_override0. { 0x0600FED3, 0x6D8 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // mc_video_protect_vpr_override1. + TSECB, TSEC1, TSECB1.
{ 0x00000002, 0x6E0 / 4, DRAM_ID2(22) }, // mc_video_protect_gpu_override1. { 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // mc_video_protect_gpu_override0.
{ 0x0000009C, 0x814 / 4, DRAM_ID2(22) }, // swizzle_rank_byte_encode. { 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // mc_video_protect_gpu_override1.
{ 0x0000009C, 0x814 / 4, LPDDR4X_4GB_SAMSUNG_1Y_A }, // swizzle_rank_byte_encode.
*/
// Micron LPDDR4X 4GB 10nm-class (1y-01) Die-A for Unknown Iowa/Hoag/Aula.
{ 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_MICRON_1Y_A }, // emc_auto_cal_config2.
{ 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_MICRON_1Y_A }, // emc_auto_cal_vref_sel0.
{ 0x00000006, 0x1CC / 4, LPDDR4X_4GB_MICRON_1Y_A }, // emc_quse.
{ 0x00000005, 0x1D0 / 4, LPDDR4X_4GB_MICRON_1Y_A }, // emc_quse_width.
{ 0x00000003, 0x1DC / 4, LPDDR4X_4GB_MICRON_1Y_A }, // emc_einput.
{ 0x0000000C, 0x1E0 / 4, LPDDR4X_4GB_MICRON_1Y_A }, // emc_einput_duration.
{ 0x00000008, 0x24C / 4, LPDDR4X_4GB_MICRON_1Y_A }, // emc_tfaw.
{ 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_MICRON_1Y_A }, // emc_mrw14.
{ 0x80000713, 0x32C / 4, LPDDR4X_4GB_MICRON_1Y_A }, // emc_dyn_self_ref_control.
{ 0x00000001, 0x670 / 4, LPDDR4X_4GB_MICRON_1Y_A }, // mc_emem_arb_timing_faw.
{ 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_MICRON_1Y_A }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_MICRON_1Y_A }, // mc_video_protect_gpu_override1.
// Micron LPDDR4X 4GB 10nm-class (1y) Die-A for Unknown Iowa/Hoag/Aula. // Hynix LPDDR4X 4GB 10nm-class (1y-01) Die-A for Unknown Iowa/Hoag/Aula.
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_auto_cal_config2. { 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_auto_cal_config2.
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_auto_cal_vref_sel0. { 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_auto_cal_vref_sel0.
{ 0x00000006, 0x1CC / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_quse. { 0x00000006, 0x1CC / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_quse.
{ 0x00000005, 0x1D0 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_quse_width. { 0x00000005, 0x1D0 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_quse_width.
{ 0x00000003, 0x1DC / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_einput. { 0x00000003, 0x1DC / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_einput.
{ 0x0000000C, 0x1E0 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_einput_duration. { 0x0000000C, 0x1E0 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_einput_duration.
{ 0x00000008, 0x24C / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_tfaw. { 0x00000008, 0x24C / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_tfaw.
{ 0x88161414, 0x2E0 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_mrw14. { 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_mrw14.
{ 0x80000713, 0x32C / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_dyn_self_ref_control. { 0x80000713, 0x32C / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_dyn_self_ref_control.
{ 0x00000001, 0x670 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // mc_emem_arb_timing_faw. { 0x00000001, 0x670 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // mc_emem_arb_timing_faw.
{ 0x2A800000, 0x6DC / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // mc_video_protect_gpu_override0. { 0xE4FACB43, 0x6D4 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // mc_video_protect_vpr_override. + TSEC, NVENC.
{ 0x00000002, 0x6E0 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // mc_video_protect_gpu_override1. { 0x0600FED3, 0x6D8 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // mc_video_protect_vpr_override1. + TSECB, TSEC1, TSECB1.
{ 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // mc_video_protect_gpu_override1.
//!TODO: Too many duplicates.
}; };

View file

@ -21,25 +21,25 @@
#include <utils/types.h> #include <utils/types.h>
static u8 reg_5v_dev = 0; static u8 reg_5v_dev = 0;
static bool batt_src = false; static bool usb_src = false;
void regulator_5v_enable(u8 dev) void regulator_5v_enable(u8 dev)
{ {
// The power supply selection from battery or USB is automatic. // The power supply selection from battery or USB is automatic.
if (!reg_5v_dev) if (!reg_5v_dev)
{ {
// Fan and Rail power from internal 5V regulator (battery). // Fan and Rail power from battery 5V regulator.
PINMUX_AUX(PINMUX_AUX_SATA_LED_ACTIVE) = 1; PINMUX_AUX(PINMUX_AUX_SATA_LED_ACTIVE) = 1;
gpio_config(GPIO_PORT_A, GPIO_PIN_5, GPIO_MODE_GPIO); gpio_config(GPIO_PORT_A, GPIO_PIN_5, GPIO_MODE_GPIO);
gpio_output_enable(GPIO_PORT_A, GPIO_PIN_5, GPIO_OUTPUT_ENABLE); gpio_output_enable(GPIO_PORT_A, GPIO_PIN_5, GPIO_OUTPUT_ENABLE);
gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_HIGH); gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_HIGH);
batt_src = true;
// Fan and Rail power from USB 5V VDD. // Fan and Rail power from USB 5V VBUS.
PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN0) = PINMUX_LPDR | 1; PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN0) = PINMUX_LPDR | 1;
gpio_config(GPIO_PORT_CC, GPIO_PIN_4, GPIO_MODE_GPIO); gpio_config(GPIO_PORT_CC, GPIO_PIN_4, GPIO_MODE_GPIO);
gpio_output_enable(GPIO_PORT_CC, GPIO_PIN_4, GPIO_OUTPUT_ENABLE); gpio_output_enable(GPIO_PORT_CC, GPIO_PIN_4, GPIO_OUTPUT_ENABLE);
gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_HIGH); gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW);
usb_src = false;
// Make sure GPIO power is enabled. // Make sure GPIO power is enabled.
PMC(APBDEV_PMC_NO_IOPOWER) &= ~PMC_NO_IOPOWER_GPIO_IO_EN; PMC(APBDEV_PMC_NO_IOPOWER) &= ~PMC_NO_IOPOWER_GPIO_IO_EN;
@ -55,18 +55,18 @@ void regulator_5v_disable(u8 dev)
if (!reg_5v_dev) if (!reg_5v_dev)
{ {
// Rail power from internal 5V regulator (battery). // Rail power from battery 5V regulator.
gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_LOW); gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_LOW);
gpio_output_enable(GPIO_PORT_A, GPIO_PIN_5, GPIO_OUTPUT_DISABLE); gpio_output_enable(GPIO_PORT_A, GPIO_PIN_5, GPIO_OUTPUT_DISABLE);
gpio_config(GPIO_PORT_A, GPIO_PIN_5, GPIO_MODE_SPIO); gpio_config(GPIO_PORT_A, GPIO_PIN_5, GPIO_MODE_SPIO);
PINMUX_AUX(PINMUX_AUX_SATA_LED_ACTIVE) = PINMUX_PARKED | PINMUX_INPUT_ENABLE; PINMUX_AUX(PINMUX_AUX_SATA_LED_ACTIVE) = PINMUX_PARKED | PINMUX_INPUT_ENABLE;
batt_src = false;
// Rail power from USB 5V VDD. // Rail power from USB 5V VBUS.
gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW); gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW);
gpio_output_enable(GPIO_PORT_CC, GPIO_PIN_4, GPIO_OUTPUT_DISABLE); gpio_output_enable(GPIO_PORT_CC, GPIO_PIN_4, GPIO_OUTPUT_DISABLE);
gpio_config(GPIO_PORT_CC, GPIO_PIN_4, GPIO_MODE_SPIO); gpio_config(GPIO_PORT_CC, GPIO_PIN_4, GPIO_MODE_SPIO);
PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN0) = PINMUX_IO_HV | PINMUX_LPDR | PINMUX_PARKED | PINMUX_INPUT_ENABLE; PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN0) = PINMUX_IO_HV | PINMUX_LPDR | PINMUX_PARKED | PINMUX_INPUT_ENABLE;
usb_src = false;
// GPIO AO IO rails. // GPIO AO IO rails.
PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_GPIO_IO_EN; PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_GPIO_IO_EN;
@ -78,16 +78,16 @@ bool regulator_5v_get_dev_enabled(u8 dev)
return (reg_5v_dev & dev); return (reg_5v_dev & dev);
} }
void regulator_5v_batt_src_enable(bool enable) void regulator_5v_usb_src_enable(bool enable)
{ {
if (enable && !batt_src) if (enable && !usb_src)
{ {
gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_HIGH); gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_HIGH);
batt_src = true; usb_src = true;
} }
else if (!enable && batt_src) else if (!enable && usb_src)
{ {
gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_LOW); gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW);
batt_src = false; usb_src = false;
} }
} }

View file

@ -30,6 +30,6 @@ enum
void regulator_5v_enable(u8 dev); void regulator_5v_enable(u8 dev);
void regulator_5v_disable(u8 dev); void regulator_5v_disable(u8 dev);
bool regulator_5v_get_dev_enabled(u8 dev); bool regulator_5v_get_dev_enabled(u8 dev);
void regulator_5v_batt_src_enable(bool enable); void regulator_5v_usb_src_enable(bool enable);
#endif #endif

View file

@ -255,7 +255,7 @@ int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_siz
// Copy output hash. // Copy output hash.
u32 *dst32 = (u32 *)dst; u32 *dst32 = (u32 *)dst;
for (u32 i = 0; i < dst_size / 4; i++) for (u32 i = 0; i < dst_size / 4; i++)
dst32[dst_size / 4 - i - 1] = byte_swap_32(SE(SE_RSA_OUTPUT_REG + (i << 2))); dst32[dst_size / 4 - i - 1] = byte_swap_32(SE(SE_RSA_OUTPUT_REG + (i * 4)));
return res; return res;
} }
@ -485,7 +485,7 @@ int se_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst
tweak[i] = sec & 0xFF; tweak[i] = sec & 0xFF;
sec >>= 8; sec >>= 8;
} }
if (!se_aes_crypt_block_ecb(tweak_ks, 1, tweak, tweak)) if (!se_aes_crypt_block_ecb(tweak_ks, ENCRYPT, tweak, tweak))
return 0; return 0;
memcpy(orig_tweak, tweak, 0x10); memcpy(orig_tweak, tweak, 0x10);
@ -538,7 +538,7 @@ int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size)
u8 *last_block = (u8 *)calloc(0x10, 1); u8 *last_block = (u8 *)calloc(0x10, 1);
// generate derived key // generate derived key
if (!se_aes_crypt_block_ecb(ks, 1, key, key)) if (!se_aes_crypt_block_ecb(ks, ENCRYPT, key, key))
goto out; goto out;
_gf256_mul_x(key); _gf256_mul_x(key);
if (src_size & 0xF) if (src_size & 0xF)
@ -668,7 +668,7 @@ int se_calc_sha256_finalize(void *hash, u32 *msg_left)
// Copy output hash. // Copy output hash.
for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++) for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++)
hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG + (i << 2))); hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG + (i * 4)));
memcpy(hash, hash32, SE_SHA_256_SIZE); memcpy(hash, hash32, SE_SHA_256_SIZE);
return res; return res;
@ -841,6 +841,6 @@ void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize)
// Decrypt context. // Decrypt context.
se_aes_key_clear(3); se_aes_key_clear(3);
se_aes_key_set(3, srk, SE_KEY_128_SIZE); se_aes_key_set(3, srk, SE_KEY_128_SIZE);
se_aes_crypt_cbc(3, 0, keys, SE_AES_KEYSLOT_COUNT * keysize, keys, SE_AES_KEYSLOT_COUNT * keysize); se_aes_crypt_cbc(3, DECRYPT, keys, SE_AES_KEYSLOT_COUNT * keysize, keys, SE_AES_KEYSLOT_COUNT * keysize);
se_aes_key_clear(3); se_aes_key_clear(3);
} }

View file

@ -50,6 +50,9 @@
#define SE_RSA1536_DIGEST_SIZE 192 #define SE_RSA1536_DIGEST_SIZE 192
#define SE_RSA2048_DIGEST_SIZE 256 #define SE_RSA2048_DIGEST_SIZE 256
#define DECRYPT 0
#define ENCRYPT 1
/* SE register definitions */ /* SE register definitions */
#define SE_SE_SECURITY_REG 0x000 #define SE_SE_SECURITY_REG 0x000
#define SE_HARD_SETTING BIT(0) #define SE_HARD_SETTING BIT(0)

View file

@ -33,7 +33,8 @@
// #include <gfx_utils.h> // #include <gfx_utils.h>
#define PKG11_MAGIC 0x31314B50 #define PKG11_MAGIC 0x31314B50
#define KB_TSEC_FW_EMU_COMPAT 6 // KB ID for HOS 6.2.0.
#define TSEC_HOS_KB_620 6
static int _tsec_dma_wait_idle() static int _tsec_dma_wait_idle()
{ {
@ -62,10 +63,13 @@ static int _tsec_dma_pa_to_internal_100(int not_imem, int i_offset, int pa_offse
return _tsec_dma_wait_idle(); return _tsec_dma_wait_idle();
} }
int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt) int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt)
{ {
int res = 0; int res = 0;
u8 *fwbuf = NULL; u8 *fwbuf = NULL;
u32 type = tsec_ctxt->type;
u32 *pdir, *car, *fuse, *pmc, *flowctrl, *se, *mc, *iram, *evec;
u32 *pkg11_magic_off;
bpmp_mmu_disable(); bpmp_mmu_disable();
bpmp_freq_t prev_fid = bpmp_clk_rate_set(BPMP_CLK_NORMAL); bpmp_freq_t prev_fid = bpmp_clk_rate_set(BPMP_CLK_NORMAL);
@ -81,7 +85,10 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
kfuse_wait_ready(); kfuse_wait_ready();
//Configure Falcon. if (type == TSEC_FW_TYPE_NEW)
mc_enable_ahb_redirect(true);
// Configure Falcon.
TSEC(TSEC_DMACTL) = 0; TSEC(TSEC_DMACTL) = 0;
TSEC(TSEC_IRQMSET) = TSEC(TSEC_IRQMSET) =
TSEC_IRQMSET_EXT(0xFF) | TSEC_IRQMSET_EXT(0xFF) |
@ -103,8 +110,8 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
goto out; goto out;
} }
//Load firmware or emulate memio environment for newer TSEC fw. // Load firmware or emulate memio environment for newer TSEC fw.
if (kb == KB_TSEC_FW_EMU_COMPAT) if (type == TSEC_FW_TYPE_EMU)
TSEC(TSEC_DMATRFBASE) = (u32)tsec_ctxt->fw >> 8; TSEC(TSEC_DMATRFBASE) = (u32)tsec_ctxt->fw >> 8;
else else
{ {
@ -123,40 +130,159 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
} }
} }
//Execute firmware. if (type == TSEC_FW_TYPE_EMU)
{
// Init SMMU translation for TSEC.
pdir = smmu_init_for_tsec();
smmu_init(tsec_ctxt->secmon_base);
// Enable SMMU
if (!smmu_is_used())
smmu_enable();
// Clock reset controller.
car = page_alloc(1);
memcpy(car, (void *)CLOCK_BASE, 0x1000);
car[CLK_RST_CONTROLLER_CLK_SOURCE_TSEC / 4] = 2;
smmu_map(pdir, CLOCK_BASE, (u32)car, 1, _WRITABLE | _READABLE | _NONSECURE);
// Fuse driver.
fuse = page_alloc(1);
memcpy((void *)&fuse[0x800/4], (void *)FUSE_BASE, 0x400);
fuse[0x82C / 4] = 0;
fuse[0x9E0 / 4] = (1 << (TSEC_HOS_KB_620 + 2)) - 1;
fuse[0x9E4 / 4] = (1 << (TSEC_HOS_KB_620 + 2)) - 1;
smmu_map(pdir, (FUSE_BASE - 0x800), (u32)fuse, 1, _READABLE | _NONSECURE);
// Power management controller.
pmc = page_alloc(1);
smmu_map(pdir, RTC_BASE, (u32)pmc, 1, _READABLE | _NONSECURE);
// Flow control.
flowctrl = page_alloc(1);
smmu_map(pdir, FLOW_CTLR_BASE, (u32)flowctrl, 1, _WRITABLE | _NONSECURE);
// Security engine.
se = page_alloc(1);
memcpy(se, (void *)SE_BASE, 0x1000);
smmu_map(pdir, SE_BASE, (u32)se, 1, _READABLE | _WRITABLE | _NONSECURE);
// Memory controller.
mc = page_alloc(1);
memcpy(mc, (void *)MC_BASE, 0x1000);
mc[MC_IRAM_BOM / 4] = 0;
mc[MC_IRAM_TOM / 4] = 0x80000000;
smmu_map(pdir, MC_BASE, (u32)mc, 1, _READABLE | _NONSECURE);
// IRAM
iram = page_alloc(0x30);
memcpy(iram, tsec_ctxt->pkg1, 0x30000);
// PKG1.1 magic offset.
pkg11_magic_off = (u32 *)(iram + ((tsec_ctxt->pkg11_off + 0x20) / 4));
smmu_map(pdir, 0x40010000, (u32)iram, 0x30, _READABLE | _WRITABLE | _NONSECURE);
// Exception vectors
evec = page_alloc(1);
smmu_map(pdir, EXCP_VEC_BASE, (u32)evec, 1, _READABLE | _WRITABLE | _NONSECURE);
}
// Execute firmware.
HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0x34C2E1DA; HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0x34C2E1DA;
TSEC(TSEC_STATUS) = 0; TSEC(TSEC_STATUS) = 0;
TSEC(TSEC_BOOTKEYVER) = 1; // HOS uses key version 1. TSEC(TSEC_BOOTKEYVER) = 1; // HOS uses key version 1.
TSEC(TSEC_BOOTVEC) = 0; TSEC(TSEC_BOOTVEC) = 0;
TSEC(TSEC_CPUCTL) = TSEC_CPUCTL_STARTCPU; TSEC(TSEC_CPUCTL) = TSEC_CPUCTL_STARTCPU;
if (!_tsec_dma_wait_idle()) if (type == TSEC_FW_TYPE_EMU)
{ {
res = -3; u32 start = get_tmr_us();
goto out_free; u32 k = se[SE_CRYPTO_KEYTABLE_DATA_REG / 4];
} u32 key[16] = {0};
u32 timeout = get_tmr_ms() + 4000; u32 kidx = 0;
while (!(TSEC(TSEC_CPUCTL) & TSEC_CPUCTL_KEYGEN_DONE))
if (get_tmr_ms() > timeout) while (*pkg11_magic_off != PKG11_MAGIC)
{ {
res = -4; smmu_flush_all();
if (k != se[SE_CRYPTO_KEYTABLE_DATA_REG / 4])
{
k = se[SE_CRYPTO_KEYTABLE_DATA_REG / 4];
key[kidx++] = k;
}
// Failsafe.
if ((u32)get_tmr_us() - start > 125000)
break;
}
if (kidx != 8)
{
res = -6;
smmu_deinit_for_tsec();
goto out_free; goto out_free;
} }
if (TSEC(TSEC_STATUS) != 0xB0B0B0B0)
{
res = -5;
goto out_free;
}
//Fetch result. // Give some extra time to make sure PKG1.1 is decrypted.
HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0; msleep(50);
memcpy(tsec_keys, &key, 0x20);
memcpy(tsec_ctxt->pkg1, iram, 0x30000);
smmu_deinit_for_tsec();
// for (int i = 0; i < kidx; i++)
// gfx_printf("key %08X\n", key[i]);
// gfx_printf("cpuctl (%08X) mbox (%08X)\n", TSEC(TSEC_CPUCTL), TSEC(TSEC_STATUS));
// u32 errst = MC(MC_ERR_STATUS);
// gfx_printf(" MC %08X %08X %08X\n", MC(MC_INTSTATUS), errst, MC(MC_ERR_ADR));
// gfx_printf(" type: %02X\n", errst >> 28);
// gfx_printf(" smmu: %02X\n", (errst >> 25) & 3);
// gfx_printf(" dir: %s\n", (errst >> 16) & 1 ? "W" : "R");
// gfx_printf(" cid: %02x\n", errst & 0xFF);
}
else
{
if (!_tsec_dma_wait_idle())
{
res = -3;
goto out_free;
}
u32 timeout = get_tmr_ms() + 2000;
while (!TSEC(TSEC_STATUS))
if (get_tmr_ms() > timeout)
{
res = -4;
goto out_free;
}
if (TSEC(TSEC_STATUS) != 0xB0B0B0B0)
{
res = -5;
goto out_free;
}
// Fetch result.
HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0;
u32 buf[4];
buf[0] = SOR1(SOR_NV_PDISP_SOR_DP_HDCP_BKSV_LSB);
buf[1] = SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_BKSV_LSB);
buf[2] = SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_MSB);
buf[3] = SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_LSB);
SOR1(SOR_NV_PDISP_SOR_DP_HDCP_BKSV_LSB) = 0;
SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_BKSV_LSB) = 0;
SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_MSB) = 0;
SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_LSB) = 0;
memcpy(tsec_keys, &buf, SE_KEY_128_SIZE);
}
out_free:; out_free:;
free(fwbuf); free(fwbuf);
out:; out:;
//Disable clocks. // Disable clocks.
clock_disable_kfuse(); clock_disable_kfuse();
clock_disable_sor1(); clock_disable_sor1();
clock_disable_sor0(); clock_disable_sor0();
@ -165,28 +291,8 @@ out:;
bpmp_mmu_enable(); bpmp_mmu_enable();
bpmp_clk_rate_set(prev_fid); bpmp_clk_rate_set(prev_fid);
return res; if (type == TSEC_FW_TYPE_NEW)
} mc_disable_ahb_redirect();
int tsec_run_fw(tsec_ctxt_t *tsec_ctxt)
{
/* Ensure that the ahb redirect is enabled. */
mc_enable_ahb_redirect();
/* Get bom/tom */
u32 bom = MC(MC_IRAM_BOM);
u32 tom = MC(MC_IRAM_TOM);
/* Override the ahb redirect extents. */
MC(MC_IRAM_BOM) = 0x40000000;
MC(MC_IRAM_TOM) = 0x80000000;
/* Run the fw. */
int res = tsec_query(NULL, 0, tsec_ctxt);
/* Reset the ahb redirect extents. */
MC(MC_IRAM_BOM) = bom;
MC(MC_IRAM_TOM) = tom;
return res; return res;
} }

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer * Copyright (c) 2018-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -20,33 +20,24 @@
#include <utils/types.h> #include <utils/types.h>
#define TSEC_KEY_DATA_OFFSET 0x300 enum tsec_fw_type
{
// Retail Hovi Keygen.
TSEC_FW_TYPE_OLD = 0, // 1.0.0 - 6.1.0.
TSEC_FW_TYPE_EMU = 1, // 6.2.0 emulated enviroment.
TSEC_FW_TYPE_NEW = 2, // 7.0.0+.
};
typedef struct _tsec_ctxt_t typedef struct _tsec_ctxt_t
{ {
const void *fw; const void *fw;
u32 size; u32 size;
u32 type;
void *pkg1; void *pkg1;
u32 pkg11_off;
u32 secmon_base;
} tsec_ctxt_t; } tsec_ctxt_t;
typedef struct _tsec_key_data_t int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt);
{
u8 debug_key[0x10];
u8 blob0_auth_hash[0x10];
u8 blob1_auth_hash[0x10];
u8 blob2_auth_hash[0x10];
u8 blob2_aes_iv[0x10];
u8 hovi_eks_seed[0x10];
u8 hovi_common_seed[0x10];
u32 blob0_size;
u32 blob1_size;
u32 blob2_size;
u32 blob3_size;
u32 blob4_size;
u8 reserved[0x7C];
} tsec_key_data_t;
int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt);
int tsec_run_fw(tsec_ctxt_t *tsec_ctxt);
#endif #endif

View file

@ -37,7 +37,6 @@
#define TSEC_IRQDEST_EXT(val) (((val) & 0xFF) << 8) #define TSEC_IRQDEST_EXT(val) (((val) & 0xFF) << 8)
#define TSEC_CPUCTL 0x1100 #define TSEC_CPUCTL 0x1100
#define TSEC_CPUCTL_STARTCPU BIT(1) #define TSEC_CPUCTL_STARTCPU BIT(1)
#define TSEC_CPUCTL_KEYGEN_DONE BIT(4)
#define TSEC_BOOTVEC 0x1104 #define TSEC_BOOTVEC 0x1104
#define TSEC_DMACTL 0x110C #define TSEC_DMACTL 0x110C
#define TSEC_DMATRFBASE 0x1110 #define TSEC_DMATRFBASE 0x1110

View file

@ -2,7 +2,8 @@
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018 shuffle2 * Copyright (c) 2018 shuffle2
* Copyright (c) 2018 balika011 * Copyright (c) 2018 balika011
* Copyright (c) 2019-2020 CTCaer * Copyright (c) 2019-2021 CTCaer
* Copyright (c) 2021 shchmue
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -19,6 +20,8 @@
#include <string.h> #include <string.h>
#include <sec/se.h>
#include <sec/se_t210.h>
#include <soc/fuse.h> #include <soc/fuse.h>
#include <soc/hw_init.h> #include <soc/hw_init.h>
#include <soc/t210.h> #include <soc/t210.h>
@ -99,7 +102,7 @@ u32 fuse_read_dramid(bool raw_id)
} }
else else
{ {
if (dramid > 27) if (dramid > 28)
dramid = 8; dramid = 8;
} }
@ -120,26 +123,41 @@ u32 fuse_read_hw_type()
{ {
switch ((fuse_read_odm(4) & 0xF0000) >> 16) switch ((fuse_read_odm(4) & 0xF0000) >> 16)
{ {
case 1:
return FUSE_NX_HW_TYPE_IOWA;
case 2: case 2:
return FUSE_NX_HW_TYPE_HOAG; return FUSE_NX_HW_TYPE_HOAG;
case 4:
return FUSE_NX_HW_TYPE_AULA;
case 1:
default:
return FUSE_NX_HW_TYPE_IOWA;
} }
} }
return FUSE_NX_HW_TYPE_ICOSA; return FUSE_NX_HW_TYPE_ICOSA;
} }
u8 fuse_count_burnt(u32 val) int fuse_set_sbk()
{ {
u8 burnt_fuses = 0; if (FUSE(FUSE_PRIVATE_KEY0) != 0xFFFFFFFF)
for (u32 i = 0; i < 32; i++)
{ {
if ((val >> i) & 1) // Read SBK from fuses.
burnt_fuses++; u32 sbk[4] = {
FUSE(FUSE_PRIVATE_KEY0),
FUSE(FUSE_PRIVATE_KEY1),
FUSE(FUSE_PRIVATE_KEY2),
FUSE(FUSE_PRIVATE_KEY3)
};
// Set SBK to slot 14.
se_aes_key_set(14, sbk, SE_KEY_128_SIZE);
// Lock SBK from being read.
se_key_acc_ctrl(14, SE_KEY_TBL_DIS_KEYREAD_FLAG);
return 1;
} }
return burnt_fuses; return 0;
} }
void fuse_wait_idle() void fuse_wait_idle()

View file

@ -2,7 +2,8 @@
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018 shuffle2 * Copyright (c) 2018 shuffle2
* Copyright (c) 2018 balika011 * Copyright (c) 2018 balika011
* Copyright (c) 2019-2020 CTCaer * Copyright (c) 2019-2021 CTCaer
* Copyright (c) 2021 shchmue
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -82,7 +83,8 @@ enum
{ {
FUSE_NX_HW_TYPE_ICOSA, FUSE_NX_HW_TYPE_ICOSA,
FUSE_NX_HW_TYPE_IOWA, FUSE_NX_HW_TYPE_IOWA,
FUSE_NX_HW_TYPE_HOAG FUSE_NX_HW_TYPE_HOAG,
FUSE_NX_HW_TYPE_AULA
}; };
enum enum
@ -98,7 +100,7 @@ u32 fuse_read_bootrom_rev();
u32 fuse_read_dramid(bool raw_id); u32 fuse_read_dramid(bool raw_id);
u32 fuse_read_hw_state(); u32 fuse_read_hw_state();
u32 fuse_read_hw_type(); u32 fuse_read_hw_type();
u8 fuse_count_burnt(u32 val); int fuse_set_sbk();
void fuse_wait_idle(); void fuse_wait_idle();
int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value)); 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_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len);

View file

@ -250,28 +250,14 @@ static void _mbist_workaround()
static void _config_se_brom() static void _config_se_brom()
{ {
// Enable fuse clock. // Enable Fuse visibility.
clock_enable_fuse(true); clock_enable_fuse(true);
// Skip SBK/SSK if running on patched Erista. // Try to set SBK from fuses. If patched, skip.
if (!(FUSE(FUSE_PRIVATE_KEY0) == 0xFFFFFFFF)) fuse_set_sbk();
{
// Bootrom part we skipped.
u32 sbk[4] = {
FUSE(FUSE_PRIVATE_KEY0),
FUSE(FUSE_PRIVATE_KEY1),
FUSE(FUSE_PRIVATE_KEY2),
FUSE(FUSE_PRIVATE_KEY3)
};
// Set SBK to slot 14.
se_aes_key_set(14, sbk, SE_KEY_128_SIZE);
// Lock SBK from being read. // Lock SSK (although it's not set and unused anyways).
se_key_acc_ctrl(14, SE_KEY_TBL_DIS_KEYREAD_FLAG); // se_key_acc_ctrl(15, SE_KEY_TBL_DIS_KEYREAD_FLAG);
// Lock SSK (although it's not set and unused anyways).
se_key_acc_ctrl(15, SE_KEY_TBL_DIS_KEYREAD_FLAG);
}
// This memset needs to happen here, else TZRAM will behave weirdly later on. // This memset needs to happen here, else TZRAM will behave weirdly later on.
memset((void *)TZRAM_BASE, 0, 0x10000); memset((void *)TZRAM_BASE, 0, 0x10000);
@ -351,7 +337,7 @@ void hw_init()
// Enable Security Engine clock. // Enable Security Engine clock.
clock_enable_se(); clock_enable_se();
// Enable Fuse clock. // Enable Fuse visibility.
clock_enable_fuse(true); clock_enable_fuse(true);
// Disable Fuse programming. // Disable Fuse programming.

View file

@ -2,6 +2,7 @@
* Header for MultiMediaCard (MMC) * Header for MultiMediaCard (MMC)
* *
* Copyright 2002 Hewlett-Packard Company * Copyright 2002 Hewlett-Packard Company
* Copyright 2018-2021 CTCaer
* *
* Use consistent with the GNU GPL is permitted, * Use consistent with the GNU GPL is permitted,
* provided that this copyright notice is * provided that this copyright notice is
@ -21,8 +22,8 @@
* 15 May 2002 * 15 May 2002
*/ */
#ifndef LINUX_MMC_MMC_H #ifndef MMC_H
#define LINUX_MMC_MMC_H #define MMC_H
/* Standard MMC commands (4.1) type argument response */ /* Standard MMC commands (4.1) type argument response */
/* class 1 */ /* class 1 */
@ -97,29 +98,29 @@
#define MMC_CMDQ_TASK_MGMT 48 /* ac [20:16] task id R1b */ #define MMC_CMDQ_TASK_MGMT 48 /* ac [20:16] task id R1b */
/* /*
* MMC_SWITCH argument format: * MMC_SWITCH argument format:
* *
* [31:26] Always 0 * [31:26] Always 0
* [25:24] Access Mode * [25:24] Access Mode
* [23:16] Location of target Byte in EXT_CSD * [23:16] Location of target Byte in EXT_CSD
* [15:08] Value Byte * [15:08] Value Byte
* [07:03] Always 0 * [07:03] Always 0
* [02:00] Command Set * [02:00] Command Set
*/ */
/* /*
MMC status in R1, for native mode (SPI bits are different) * MMC status in R1, for native mode (SPI bits are different)
Type * Type
e : error bit * e : error bit
s : status bit * s : status bit
r : detected and set for the actual command response * r : detected and set for the actual command response
x : detected and set during command execution. the host must poll * x : detected and set during command execution. the host must poll
the card by sending status command in order to read these bits. * the card by sending status command in order to read these bits.
Clear condition * Clear condition
a : according to the card state * a : according to the card state
b : always related to the previous command. Reception of * b : always related to the previous command. Reception of a valid
a valid command will clear it (with a delay of one command) * command will clear it (with a delay of one command)
c : clear by read * c : clear by read
*/ */
#define R1_OUT_OF_RANGE (1 << 31) /* er, c */ #define R1_OUT_OF_RANGE (1 << 31) /* er, c */
@ -151,6 +152,7 @@ c : clear by read
#define R1_AKE_SEQ_ERROR (1 << 3) #define R1_AKE_SEQ_ERROR (1 << 3)
/* R1_CURRENT_STATE 12:9 */ /* R1_CURRENT_STATE 12:9 */
#define R1_STATE(x) ((x) << 9)
#define R1_STATE_IDLE 0 #define R1_STATE_IDLE 0
#define R1_STATE_READY 1 #define R1_STATE_READY 1
#define R1_STATE_IDENT 2 #define R1_STATE_IDENT 2
@ -162,9 +164,9 @@ c : clear by read
#define R1_STATE_DIS 8 #define R1_STATE_DIS 8
/* /*
* MMC/SD in SPI mode reports R1 status always, and R2 for SEND_STATUS * MMC/SD in SPI mode reports R1 status always, and R2 for SEND_STATUS
* R1 is the low order byte; R2 is the next highest byte, when present. * R1 is the low order byte; R2 is the next highest byte, when present.
*/ */
#define R1_SPI_IDLE (1 << 0) #define R1_SPI_IDLE (1 << 0)
#define R1_SPI_ERASE_RESET (1 << 1) #define R1_SPI_ERASE_RESET (1 << 1)
#define R1_SPI_ILLEGAL_COMMAND (1 << 2) #define R1_SPI_ILLEGAL_COMMAND (1 << 2)
@ -185,16 +187,16 @@ c : clear by read
#define R2_SPI_CSD_OVERWRITE R2_SPI_OUT_OF_RANGE #define R2_SPI_CSD_OVERWRITE R2_SPI_OUT_OF_RANGE
/* /*
* OCR bits are mostly in host.h * OCR bits are mostly in host.h
*/ */
#define MMC_CARD_VDD_18 (1 << 7) /* Card VDD voltage 1.8 */ #define MMC_CARD_VDD_18 (1 << 7) /* Card VDD voltage 1.8 */
#define MMC_CARD_VDD_27_34 (0x7F << 15) /* Card VDD voltage 2.7 ~ 3.4 */ #define MMC_CARD_VDD_27_34 (0x7F << 15) /* Card VDD voltage 2.7 ~ 3.4 */
#define MMC_CARD_CCS (1 << 30) /* Card Capacity status bit */ #define MMC_CARD_CCS (1 << 30) /* Card Capacity status bit */
#define MMC_CARD_BUSY (1 << 31) /* Card Power up status bit */ #define MMC_CARD_BUSY (1 << 31) /* Card Power up status bit */
/* /*
* Card Command Classes (CCC) * Card Command Classes (CCC)
*/ */
#define CCC_BASIC (1<<0) /* (0) Basic protocol functions */ #define CCC_BASIC (1<<0) /* (0) Basic protocol functions */
/* (CMD0,1,2,3,4,7,9,10,12,13,15) */ /* (CMD0,1,2,3,4,7,9,10,12,13,15) */
/* (and for SPI, CMD58,59) */ /* (and for SPI, CMD58,59) */
@ -222,8 +224,8 @@ c : clear by read
/* (CMD?) */ /* (CMD?) */
/* /*
* CSD field definitions * CSD field definitions
*/ */
#define CSD_STRUCT_VER_1_0 0 /* Valid for system specification 1.0 - 1.2 */ #define CSD_STRUCT_VER_1_0 0 /* Valid for system specification 1.0 - 1.2 */
#define CSD_STRUCT_VER_1_1 1 /* Valid for system specification 1.4 - 2.2 */ #define CSD_STRUCT_VER_1_1 1 /* Valid for system specification 1.4 - 2.2 */
@ -237,8 +239,8 @@ c : clear by read
#define CSD_SPEC_VER_4 4 /* Implements system specification 4.0 - 4.1 */ #define CSD_SPEC_VER_4 4 /* Implements system specification 4.0 - 4.1 */
/* /*
* EXT_CSD fields * EXT_CSD fields
*/ */
#define EXT_CSD_CMDQ_MODE_EN 15 /* R/W */ #define EXT_CSD_CMDQ_MODE_EN 15 /* R/W */
#define EXT_CSD_FLUSH_CACHE 32 /* W */ #define EXT_CSD_FLUSH_CACHE 32 /* W */
@ -316,8 +318,8 @@ c : clear by read
#define EXT_CSD_HPI_FEATURES 503 /* RO */ #define EXT_CSD_HPI_FEATURES 503 /* RO */
/* /*
* EXT_CSD field definitions * EXT_CSD field definitions
*/ */
#define EXT_CSD_WR_REL_PARAM_EN (1<<2) #define EXT_CSD_WR_REL_PARAM_EN (1<<2)
@ -393,8 +395,8 @@ c : clear by read
#define EXT_CSD_PACKED_EVENT_EN (1<<3) #define EXT_CSD_PACKED_EVENT_EN (1<<3)
/* /*
* EXCEPTION_EVENT_STATUS field * EXCEPTION_EVENT_STATUS field
*/ */
#define EXT_CSD_URGENT_BKOPS (1<<0) #define EXT_CSD_URGENT_BKOPS (1<<0)
#define EXT_CSD_DYNCAP_NEEDED (1<<1) #define EXT_CSD_DYNCAP_NEEDED (1<<1)
#define EXT_CSD_SYSPOOL_EXHAUSTED (1<<2) #define EXT_CSD_SYSPOOL_EXHAUSTED (1<<2)
@ -404,34 +406,34 @@ c : clear by read
#define EXT_CSD_PACKED_INDEXED_ERROR (1<<1) #define EXT_CSD_PACKED_INDEXED_ERROR (1<<1)
/* /*
* BKOPS status level * BKOPS status level
*/ */
#define EXT_CSD_BKOPS_LEVEL_2 0x2 #define EXT_CSD_BKOPS_LEVEL_2 0x2
/* /*
* BKOPS modes * BKOPS modes
*/ */
#define EXT_CSD_MANUAL_BKOPS_MASK 0x01 #define EXT_CSD_MANUAL_BKOPS_MASK 0x01
#define EXT_CSD_AUTO_BKOPS_MASK 0x02 #define EXT_CSD_AUTO_BKOPS_MASK 0x02
/* /*
* Command Queue * Command Queue
*/ */
#define EXT_CSD_CMDQ_MODE_ENABLED (1<<0) #define EXT_CSD_CMDQ_MODE_ENABLED (1<<0)
#define EXT_CSD_CMDQ_DEPTH_MASK 0x1F #define EXT_CSD_CMDQ_DEPTH_MASK 0x1F
#define EXT_CSD_CMDQ_SUPPORTED (1<<0) #define EXT_CSD_CMDQ_SUPPORTED (1<<0)
/* /*
* MMC_SWITCH access modes * MMC_SWITCH access modes
*/ */
#define MMC_SWITCH_MODE_CMD_SET 0x00 /* Change the command set */ #define MMC_SWITCH_MODE_CMD_SET 0x00 /* Change the command set */
#define MMC_SWITCH_MODE_SET_BITS 0x01 /* Set bits which are 1 in value */ #define MMC_SWITCH_MODE_SET_BITS 0x01 /* Set bits which are 1 in value */
#define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits which are 1 in value */ #define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits which are 1 in value */
#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */ #define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */
/* /*
* Erase/trim/discard * Erase/trim/discard
*/ */
#define MMC_ERASE_ARG 0x00000000 #define MMC_ERASE_ARG 0x00000000
#define MMC_SECURE_ERASE_ARG 0x80000000 #define MMC_SECURE_ERASE_ARG 0x80000000
#define MMC_TRIM_ARG 0x00000001 #define MMC_TRIM_ARG 0x00000001
@ -441,4 +443,9 @@ c : clear by read
#define MMC_SECURE_ARGS 0x80000000 #define MMC_SECURE_ARGS 0x80000000
#define MMC_TRIM_ARGS 0x00008001 #define MMC_TRIM_ARGS 0x00008001
#endif /* LINUX_MMC_MMC_H */ /*
* Vendor definitions and structs
*/
#define MMC_SANDISK_HEALTH_REPORT 0x96C9D71C
#endif /* MMC_H */

View file

@ -139,6 +139,60 @@ static int _sdmmc_storage_check_status(sdmmc_storage_t *storage)
return _sdmmc_storage_get_status(storage, &tmp, 0); return _sdmmc_storage_get_status(storage, &tmp, 0);
} }
int sdmmc_storage_execute_vendor_cmd(sdmmc_storage_t *storage, u32 arg)
{
sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmdbuf, MMC_VENDOR_62_CMD, arg, SDMMC_RSP_TYPE_1, 1);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0))
return 0;
u32 resp;
sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_1);
resp = -1;
u32 timeout = get_tmr_ms() + 1500;
while (resp != (R1_READY_FOR_DATA | R1_STATE(R1_STATE_TRAN)))
{
_sdmmc_storage_get_status(storage, &resp, 0);
if (get_tmr_ms() > timeout)
break;
}
return _sdmmc_storage_check_card_status(resp);
}
int sdmmc_storage_vendor_sandisk_report(sdmmc_storage_t *storage, void *buf)
{
// Request health report.
if (!sdmmc_storage_execute_vendor_cmd(storage, MMC_SANDISK_HEALTH_REPORT))
return 2;
u32 tmp = 0;
sdmmc_cmd_t cmdbuf;
sdmmc_req_t reqbuf;
sdmmc_init_cmd(&cmdbuf, MMC_VENDOR_63_CMD, 0, SDMMC_RSP_TYPE_1, 0); // similar to CMD17 with arg 0x0.
reqbuf.buf = buf;
reqbuf.num_sectors = 1;
reqbuf.blksize = 512;
reqbuf.is_write = 0;
reqbuf.is_multi_block = 0;
reqbuf.is_auto_stop_trn = 0;
u32 blkcnt_out;
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, &blkcnt_out))
{
sdmmc_stop_transmission(storage->sdmmc, &tmp);
_sdmmc_storage_get_status(storage, &tmp, 0);
return 0;
}
return 1;
}
static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out, u32 sector, u32 num_sectors, void *buf, u32 is_write) static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out, u32 sector, u32 num_sectors, void *buf, u32 is_write)
{ {
u32 tmp = 0; u32 tmp = 0;
@ -1360,8 +1414,6 @@ DPRINTF("[SD] SD does not support wide bus width\n");
if (!_sd_storage_enable_uhs_low_volt(storage, type, buf)) if (!_sd_storage_enable_uhs_low_volt(storage, type, buf))
return 0; return 0;
DPRINTF("[SD] enabled UHS\n"); DPRINTF("[SD] enabled UHS\n");
sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE);
} }
else if (type != SDHCI_TIMING_SD_DS12 && storage->scr.sda_vsn) // Not default speed and not SD Version 1.0. else if (type != SDHCI_TIMING_SD_DS12 && storage->scr.sda_vsn) // Not default speed and not SD Version 1.0.
{ {
@ -1387,6 +1439,8 @@ DPRINTF("[SD] enabled HS\n");
DPRINTF("[SD] got sd status\n"); DPRINTF("[SD] got sd status\n");
} }
sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE);
storage->initialized = 1; storage->initialized = 1;
return 1; return 1;

View file

@ -34,6 +34,81 @@ typedef enum _sdmmc_type
EMMC_RPMB = 3 EMMC_RPMB = 3
} sdmmc_type; } sdmmc_type;
typedef struct _mmc_sandisk_advanced_report_t
{
u32 power_inits;
u32 max_erase_cycles_sys;
u32 max_erase_cycles_slc;
u32 max_erase_cycles_mlc;
u32 min_erase_cycles_sys;
u32 min_erase_cycles_slc;
u32 min_erase_cycles_mlc;
u32 max_erase_cycles_euda;
u32 min_erase_cycles_euda;
u32 avg_erase_cycles_euda;
u32 read_reclaim_cnt_euda;
u32 bad_blocks_euda;
u32 pre_eol_euda;
u32 pre_eol_sys;
u32 pre_eol_mlc;
u32 uncorrectable_ecc;
u32 temperature_now;
u32 temperature_min;
u32 temperature_max;
u32 health_pct_euda;
u32 health_pct_sys;
u32 health_pct_mlc;
u32 unk0;
u32 unk1;
u32 unk2;
u32 reserved[78];
} mmc_sandisk_advanced_report_t;
typedef struct _mmc_sandisk_report_t
{
u32 avg_erase_cycles_sys;
u32 avg_erase_cycles_slc;
u32 avg_erase_cycles_mlc;
u32 read_reclaim_cnt_sys;
u32 read_reclaim_cnt_slc;
u32 read_reclaim_cnt_mlc;
u32 bad_blocks_factory;
u32 bad_blocks_sys;
u32 bad_blocks_slc;
u32 bad_blocks_mlc;
u32 fw_updates_cnt;
u8 fw_update_date[12];
u8 fw_update_time[8];
u32 total_writes_100mb;
u32 vdrops;
u32 vdroops;
u32 vdrops_failed_data_rec;
u32 vdrops_data_rec_ops;
u32 total_writes_slc_100mb;
u32 total_writes_mlc_100mb;
u32 mlc_bigfile_mode_limit_exceeded;
u32 avg_erase_cycles_hybrid;
mmc_sandisk_advanced_report_t advanced;
} mmc_sandisk_report_t;
typedef struct _mmc_cid typedef struct _mmc_cid
{ {
u32 manfid; u32 manfid;
@ -131,6 +206,9 @@ void sdmmc_storage_init_wait_sd();
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type); int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type);
int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc); int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc);
int sdmmc_storage_execute_vendor_cmd(sdmmc_storage_t *storage, u32 arg);
int sdmmc_storage_vendor_sandisk_report(sdmmc_storage_t *storage, void *buf);
int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf); int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf);
u32 sd_storage_get_ssr_au(sdmmc_storage_t *storage); u32 sd_storage_get_ssr_au(sdmmc_storage_t *storage);

View file

@ -4,7 +4,7 @@
* Copyright (c) 2003-2008 Alan Stern * Copyright (c) 2003-2008 Alan Stern
* Copyright (c) 2009 Samsung Electronics * Copyright (c) 2009 Samsung Electronics
* Author: Michal Nazarewicz <m.nazarewicz@samsung.com> * Author: Michal Nazarewicz <m.nazarewicz@samsung.com>
* Copyright (c) 2019-2020 CTCaer * Copyright (c) 2019-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -109,7 +109,7 @@
#define SS_WRITE_ERROR 0x30C02 #define SS_WRITE_ERROR 0x30C02
#define SS_WRITE_PROTECTED 0x72700 #define SS_WRITE_PROTECTED 0x72700
#define SK(x) ((u8) ((x) >> 16)) /* Sense Key byte, etc. */ #define SK(x) ((u8) ((x) >> 16)) // Sense Key byte, etc.
#define ASC(x) ((u8) ((x) >> 8)) #define ASC(x) ((u8) ((x) >> 8))
#define ASCQ(x) ((u8) (x)) #define ASCQ(x) ((u8) (x))
@ -217,6 +217,7 @@ typedef struct _usbd_gadget_ums_t {
u32 tag; u32 tag;
u32 residue; u32 residue;
u32 usb_amount_left; u32 usb_amount_left;
bool cbw_req_queued;
u32 phase_error; u32 phase_error;
u32 short_packet_received; u32 short_packet_received;
@ -368,12 +369,12 @@ static void _ums_transfer_out_big_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk
bulk_ctxt->bulk_out_buf_state = BUF_STATE_FULL; bulk_ctxt->bulk_out_buf_state = BUF_STATE_FULL;
} }
static void _ums_transfer_finish(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32 ep) static void _ums_transfer_finish(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32 ep, u32 sync_timeout)
{ {
if (ep == bulk_ctxt->bulk_in) if (ep == bulk_ctxt->bulk_in)
{ {
bulk_ctxt->bulk_in_status = usb_ops.usb_device_ep1_in_writing_finish( bulk_ctxt->bulk_in_status = usb_ops.usb_device_ep1_in_writing_finish(
&bulk_ctxt->bulk_in_length_actual); &bulk_ctxt->bulk_in_length_actual, sync_timeout);
if (bulk_ctxt->bulk_in_status == USB_ERROR_XFER_ERROR) if (bulk_ctxt->bulk_in_status == USB_ERROR_XFER_ERROR)
{ {
@ -386,7 +387,7 @@ static void _ums_transfer_finish(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt,
else else
{ {
bulk_ctxt->bulk_out_status = usb_ops.usb_device_ep1_out_reading_finish( bulk_ctxt->bulk_out_status = usb_ops.usb_device_ep1_out_reading_finish(
&bulk_ctxt->bulk_out_length_actual); &bulk_ctxt->bulk_out_length_actual, sync_timeout);
if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR) if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR)
{ {
@ -460,6 +461,7 @@ static int _scsi_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
} }
if (lba_offset >= ums->lun.num_sectors) if (lba_offset >= ums->lun.num_sectors)
{ {
ums->set_text(ums->label, "#FF8000 Warn:# Read - Out of range! Host notified.");
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
return UMS_RES_INVALID_ARG; return UMS_RES_INVALID_ARG;
@ -497,7 +499,7 @@ static int _scsi_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
// Wait for the async USB transfer to finish. // Wait for the async USB transfer to finish.
if (!first_read) if (!first_read)
_ums_transfer_finish(ums, bulk_ctxt, bulk_ctxt->bulk_in); _ums_transfer_finish(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED);
lba_offset += amount; lba_offset += amount;
amount_left -= amount; amount_left -= amount;
@ -548,6 +550,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
if (ums->lun.ro) if (ums->lun.ro)
{ {
ums->set_text(ums->label, "#FF8000 Warn:# Write - Read only! Host notified.");
ums->lun.sense_data = SS_WRITE_PROTECTED; ums->lun.sense_data = SS_WRITE_PROTECTED;
return UMS_RES_INVALID_ARG; return UMS_RES_INVALID_ARG;
@ -571,19 +574,20 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
// Check that starting LBA is not past the end sector offset. // Check that starting LBA is not past the end sector offset.
if (lba_offset >= ums->lun.num_sectors) if (lba_offset >= ums->lun.num_sectors)
{ {
ums->set_text(ums->label, "#FF8000 Warn:# Write - Out of range! Host notified.");
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
return UMS_RES_INVALID_ARG; return UMS_RES_INVALID_ARG;
} }
/* Carry out the file writes */ // Carry out the file writes.
usb_lba_offset = lba_offset; usb_lba_offset = lba_offset;
amount_left_to_req = ums->data_size_from_cmnd; amount_left_to_req = ums->data_size_from_cmnd;
amount_left_to_write = ums->data_size_from_cmnd; amount_left_to_write = ums->data_size_from_cmnd;
while (amount_left_to_write > 0) while (amount_left_to_write > 0)
{ {
/* Queue a request for more data from the host */ // Queue a request for more data from the host.
if (amount_left_to_req > 0) if (amount_left_to_req > 0)
{ {
@ -638,12 +642,12 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
*/ */
amount = MIN(amount, bulk_ctxt->bulk_out_length); amount = MIN(amount, bulk_ctxt->bulk_out_length);
/* Don't write a partial block */ // Don't write a partial block.
amount -= (amount & 511); amount -= (amount & 511);
if (amount == 0) if (amount == 0)
goto empty_write; goto empty_write;
/* Perform the write */ // Perform the write.
if (!sdmmc_storage_write(ums->lun.storage, ums->lun.offset + lba_offset, if (!sdmmc_storage_write(ums->lun.storage, ums->lun.offset + lba_offset,
amount >> UMS_DISK_LBA_SHIFT, (u8 *)bulk_ctxt->bulk_out_buf)) amount >> UMS_DISK_LBA_SHIFT, (u8 *)bulk_ctxt->bulk_out_buf))
amount = 0; amount = 0;
@ -654,7 +658,7 @@ DPRINTF("file write %X @ %X\n", amount, lba_offset);
amount_left_to_write -= amount; amount_left_to_write -= amount;
ums->residue -= amount; ums->residue -= amount;
/* If an error occurred, report it and its position */ // If an error occurred, report it and its position.
if (!amount) if (!amount)
{ {
ums->set_text(ums->label, "#FFDD00 Error:# SDMMC Write!"); ums->set_text(ums->label, "#FFDD00 Error:# SDMMC Write!");
@ -684,6 +688,7 @@ static int _scsi_verify(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
u32 lba_offset = get_array_be_to_le32(&ums->cmnd[2]); u32 lba_offset = get_array_be_to_le32(&ums->cmnd[2]);
if (lba_offset >= ums->lun.num_sectors) if (lba_offset >= ums->lun.num_sectors)
{ {
ums->set_text(ums->label, "#FF8000 Warn:# Verif - Out of range! Host notified.");
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
return UMS_RES_INVALID_ARG; return UMS_RES_INVALID_ARG;
@ -1005,7 +1010,7 @@ static int _scsi_mode_sense(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
return UMS_RES_INVALID_ARG; return UMS_RES_INVALID_ARG;
} }
/* Store the mode data length */ // Store the mode data length.
if (ums->cmnd[0] == SC_MODE_SENSE_6) if (ums->cmnd[0] == SC_MODE_SENSE_6)
buf0[0] = len - 1; buf0[0] = len - 1;
else else
@ -1538,12 +1543,12 @@ static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{ {
/* Was this a real packet? Should it be ignored? */ // Was this a real packet? Should it be ignored?
if (bulk_ctxt->bulk_out_status || bulk_ctxt->bulk_out_ignore || ums->lun.unmounted) if (bulk_ctxt->bulk_out_status || bulk_ctxt->bulk_out_ignore || ums->lun.unmounted)
{ {
if (bulk_ctxt->bulk_out_status || ums->lun.unmounted) if (bulk_ctxt->bulk_out_status || ums->lun.unmounted)
{ {
DPRINTF("USB: EP timeout\n"); DPRINTF("USB: EP timeout (%d)\n", bulk_ctxt->bulk_out_status);
// In case we disconnected, exit UMS. // In case we disconnected, exit UMS.
// Raise timeout if removable and didn't got a unit ready command inside 4s. // Raise timeout if removable and didn't got a unit ready command inside 4s.
if (bulk_ctxt->bulk_out_status == USB2_ERROR_XFER_EP_DISABLED || if (bulk_ctxt->bulk_out_status == USB2_ERROR_XFER_EP_DISABLED ||
@ -1574,6 +1579,8 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{ {
ums->set_text(ums->label, "#C7EA46 Status:# Medium unmounted"); ums->set_text(ums->label, "#C7EA46 Status:# Medium unmounted");
ums->timeouts++; ums->timeouts++;
if (!bulk_ctxt->bulk_out_status)
ums->timeouts += 3;
} }
if (ums->timeouts > 20) if (ums->timeouts > 20)
@ -1584,27 +1591,32 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
return UMS_RES_INVALID_ARG; return UMS_RES_INVALID_ARG;
} }
/* Is the CBW valid? */ // Clear request flag to allow a new one to be queued.
ums->cbw_req_queued = false;
// Is the CBW valid?
bulk_recv_pkt_t *cbw = (bulk_recv_pkt_t *)bulk_ctxt->bulk_out_buf; bulk_recv_pkt_t *cbw = (bulk_recv_pkt_t *)bulk_ctxt->bulk_out_buf;
if (bulk_ctxt->bulk_out_length_actual != USB_BULK_CB_WRAP_LEN || cbw->Signature != USB_BULK_CB_SIG) if (bulk_ctxt->bulk_out_length_actual != USB_BULK_CB_WRAP_LEN || cbw->Signature != USB_BULK_CB_SIG)
{ {
gfx_printf("USB: invalid CBW: len %X sig 0x%X\n", bulk_ctxt->bulk_out_length_actual, cbw->Signature); gfx_printf("USB: invalid CBW: len %X sig 0x%X\n", bulk_ctxt->bulk_out_length_actual, cbw->Signature);
// The Bulk-only spec says we MUST stall the IN endpoint /*
// (6.6.1), so it's unavoidable. It also says we must * The Bulk-only spec says we MUST stall the IN endpoint
// retain this state until the next reset, but there's * (6.6.1), so it's unavoidable. It also says we must
// no way to tell the controller driver it should ignore * retain this state until the next reset, but there's
// Clear-Feature(HALT) requests. * no way to tell the controller driver it should ignore
// * Clear-Feature(HALT) requests.
// We aren't required to halt the OUT endpoint; instead *
// we can simply accept and discard any data received * We aren't required to halt the OUT endpoint; instead
// until the next reset. * we can simply accept and discard any data received
* until the next reset.
*/
ums_wedge_bulk_in_endpoint(ums); ums_wedge_bulk_in_endpoint(ums);
bulk_ctxt->bulk_out_ignore = 1; bulk_ctxt->bulk_out_ignore = 1;
return UMS_RES_INVALID_ARG; return UMS_RES_INVALID_ARG;
} }
/* Is the CBW meaningful? */ // Is the CBW meaningful?
if (cbw->Lun >= UMS_MAX_LUN || cbw->Flags & ~USB_BULK_IN_FLAG || if (cbw->Lun >= UMS_MAX_LUN || cbw->Flags & ~USB_BULK_IN_FLAG ||
cbw->Length == 0 || cbw->Length > SCSI_MAX_CMD_SZ) cbw->Length == 0 || cbw->Length > SCSI_MAX_CMD_SZ)
{ {
@ -1623,7 +1635,7 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
return UMS_RES_INVALID_ARG; return UMS_RES_INVALID_ARG;
} }
/* Save the command for later */ // Save the command for later.
ums->cmnd_size = cbw->Length; ums->cmnd_size = cbw->Length;
memcpy(ums->cmnd, cbw->CDB, ums->cmnd_size); memcpy(ums->cmnd, cbw->CDB, ums->cmnd_size);
@ -1658,8 +1670,20 @@ 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; bulk_ctxt->bulk_out_length = USB_BULK_CB_WRAP_LEN;
/* Queue a request to read a Bulk-only CBW */ // Queue a request to read a Bulk-only CBW.
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED_CMD); if (!ums->cbw_req_queued)
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED_CMD);
else
_ums_transfer_finish(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED_CMD);
/*
* On XUSB do not allow multiple requests for CBW to be done.
* This avoids an issue with some XHCI controllers and OS combos (e.g. ASMedia and Linux/Mac OS)
* which confuse that and concatenate an old CBW request with another write request (SCSI Write)
* and create a babble error (transmit overflow).
*/
if (ums->xusb)
ums->cbw_req_queued = true;
/* We will drain the buffer in software, which means we /* We will drain the buffer in software, which means we
* can reuse it for the next filling. No need to advance * can reuse it for the next filling. No need to advance
@ -1696,7 +1720,7 @@ static void send_status(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
SK(sd), ASC(sd), ASCQ(sd), ums->lun.sense_data_info); SK(sd), ASC(sd), ASCQ(sd), ums->lun.sense_data_info);
} }
/* Store and send the Bulk-only CSW */ // Store and send the Bulk-only CSW.
bulk_send_pkt_t *csw = (bulk_send_pkt_t *)bulk_ctxt->bulk_in_buf; bulk_send_pkt_t *csw = (bulk_send_pkt_t *)bulk_ctxt->bulk_in_buf;
csw->Signature = USB_BULK_CS_SIG; csw->Signature = USB_BULK_CS_SIG;
@ -1712,7 +1736,7 @@ static void handle_exception(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{ {
enum ums_state old_state; enum ums_state old_state;
/* Clear out the controller's fifos */ // Clear out the controller's fifos.
ums_flush_endpoint(bulk_ctxt->bulk_in); ums_flush_endpoint(bulk_ctxt->bulk_in);
ums_flush_endpoint(bulk_ctxt->bulk_out); ums_flush_endpoint(bulk_ctxt->bulk_out);
@ -1735,7 +1759,7 @@ static void handle_exception(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
ums->state = UMS_STATE_NORMAL; ums->state = UMS_STATE_NORMAL;
/* Carry out any extra actions required for the exception */ // Carry out any extra actions required for the exception.
switch (old_state) switch (old_state)
{ {
case UMS_STATE_NORMAL: case UMS_STATE_NORMAL:
@ -1757,7 +1781,7 @@ static void handle_exception(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
break; break;
case UMS_STATE_EXIT: case UMS_STATE_EXIT:
ums->state = UMS_STATE_TERMINATED; /* Stop the thread */ ums->state = UMS_STATE_TERMINATED; // Stop the thread.
break; break;
default: default:

View file

@ -1,7 +1,7 @@
/* /*
* Enhanced & eXtensible USB device (EDCI & XDCI) driver for Tegra X1 * Enhanced & eXtensible USB device (EDCI & XDCI) driver for Tegra X1
* *
* Copyright (c) 2019-2020 CTCaer * Copyright (c) 2019-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -200,6 +200,8 @@ typedef struct _t210_usb2d_t
#define XHCI_ST_IP BIT(4) #define XHCI_ST_IP BIT(4)
#define XUSB_DEV_XHCI_RT_IMOD 0x38 #define XUSB_DEV_XHCI_RT_IMOD 0x38
#define XUSB_DEV_XHCI_PORTSC 0x3C #define XUSB_DEV_XHCI_PORTSC 0x3C
#define XHCI_PORTSC_CCS BIT(0)
#define XHCI_PORTSC_PED BIT(1)
#define XHCI_PORTSC_PR BIT(4) #define XHCI_PORTSC_PR BIT(4)
#define XHCI_PORTSC_PLS_MASK (0xF << 5) #define XHCI_PORTSC_PLS_MASK (0xF << 5)
#define XHCI_PORTSC_PLS_U0 (0 << 5) #define XHCI_PORTSC_PLS_U0 (0 << 5)
@ -226,11 +228,12 @@ typedef struct _t210_usb2d_t
#define XUSB_DEV_XHCI_ECPLO 0x40 #define XUSB_DEV_XHCI_ECPLO 0x40
#define XUSB_DEV_XHCI_ECPHI 0x44 #define XUSB_DEV_XHCI_ECPHI 0x44
#define XUSB_DEV_XHCI_EP_HALT 0x50 #define XUSB_DEV_XHCI_EP_HALT 0x50
#define XHCI_EP_HALT_DCI BIT(0) #define XHCI_EP_HALT_DCI_EP0_IN BIT(0)
#define XUSB_DEV_XHCI_EP_PAUSE 0x54 #define XUSB_DEV_XHCI_EP_PAUSE 0x54
#define XUSB_DEV_XHCI_EP_RELOAD 0x58 #define XUSB_DEV_XHCI_EP_RELOAD 0x58
#define XUSB_DEV_XHCI_EP_STCHG 0x5C #define XUSB_DEV_XHCI_EP_STCHG 0x5C
#define XUSB_DEV_XHCI_PORTHALT 0x6C #define XUSB_DEV_XHCI_PORTHALT 0x6C
#define XUSB_DEV_XHCI_EP_STOPPED 0x78
#define XHCI_PORTHALT_HALT_LTSSM BIT(0) #define XHCI_PORTHALT_HALT_LTSSM BIT(0)
#define XHCI_PORTHALT_STCHG_REQ BIT(20) #define XHCI_PORTHALT_STCHG_REQ BIT(20)
#define XUSB_DEV_XHCI_CFG_DEV_FE 0x85C #define XUSB_DEV_XHCI_CFG_DEV_FE 0x85C

View file

@ -1,7 +1,7 @@
/* /*
* Enhanced USB Device (EDCI) driver for Tegra X1 * Enhanced USB Device (EDCI) driver for Tegra X1
* *
* Copyright (c) 2019-2020 CTCaer * Copyright (c) 2019-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -1455,7 +1455,7 @@ static int _usbd_get_ep1_out_bytes_read()
return (usbdaemon->ep_bytes_requested[USB_EP_BULK_OUT] - (usbdaemon->qhs[USB_EP_BULK_OUT].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, u32 sync_timeout)
{ {
usb_ep_status_t ep_status; usb_ep_status_t ep_status;
do do
@ -1504,7 +1504,7 @@ static int _usbd_get_ep1_in_bytes_written()
return (usbdaemon->ep_bytes_requested[USB_EP_BULK_IN] - (usbdaemon->qhs[USB_EP_BULK_IN].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) int usb_device_ep1_in_writing_finish(u32 *pending_bytes, u32 sync_timeout)
{ {
usb_ep_status_t ep_status; usb_ep_status_t ep_status;
do do

View file

@ -1,7 +1,7 @@
/* /*
* Enhanced & eXtensible USB Device (EDCI & XDCI) driver for Tegra X1 * Enhanced & eXtensible USB Device (EDCI & XDCI) driver for Tegra X1
* *
* Copyright (c) 2019 CTCaer * Copyright (c) 2019-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -148,6 +148,7 @@ typedef enum _usb_error_t
XUSB_ERROR_INVALID_EP = USB_ERROR_XFER_ERROR, // From 2. XUSB_ERROR_INVALID_EP = USB_ERROR_XFER_ERROR, // From 2.
XUSB_ERROR_XFER_BULK_IN_RESIDUE = 7, XUSB_ERROR_XFER_BULK_IN_RESIDUE = 7,
XUSB_ERROR_INVALID_CYCLE = USB2_ERROR_XFER_EP_DISABLED, // From 8. XUSB_ERROR_INVALID_CYCLE = USB2_ERROR_XFER_EP_DISABLED, // From 8.
XUSB_ERROR_BABBLE_DETECTED = 50,
XUSB_ERROR_SEQ_NUM = 51, XUSB_ERROR_SEQ_NUM = 51,
XUSB_ERROR_XFER_DIR = 52, XUSB_ERROR_XFER_DIR = 52,
XUSB_ERROR_PORT_CFG = 54 XUSB_ERROR_PORT_CFG = 54
@ -175,9 +176,9 @@ typedef struct _usb_ops_t
int (*usb_device_ep1_out_read)(u8 *, u32, u32 *, u32); int (*usb_device_ep1_out_read)(u8 *, u32, u32 *, u32);
int (*usb_device_ep1_out_read_big)(u8 *, u32, u32 *); int (*usb_device_ep1_out_read_big)(u8 *, u32, u32 *);
int (*usb_device_ep1_out_reading_finish)(u32 *); int (*usb_device_ep1_out_reading_finish)(u32 *, u32);
int (*usb_device_ep1_in_write)(u8 *, u32, u32 *, u32); int (*usb_device_ep1_in_write)(u8 *, u32, u32 *, u32);
int (*usb_device_ep1_in_writing_finish)(u32 *); int (*usb_device_ep1_in_writing_finish)(u32 *, u32);
bool (*usb_device_get_suspended)(); bool (*usb_device_get_suspended)();
bool (*usb_device_get_port_in_sleep)(); bool (*usb_device_get_port_in_sleep)();
} usb_ops_t; } usb_ops_t;

View file

@ -1,7 +1,7 @@
/* /*
* eXtensible USB Device driver (XDCI) for Tegra X1 * eXtensible USB Device driver (XDCI) for Tegra X1
* *
* Copyright (c) 2020 CTCaer * Copyright (c) 2020-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -368,7 +368,7 @@ typedef struct _xusbd_controller_t
event_trb_t *event_dequeue_ptr; event_trb_t *event_dequeue_ptr;
u32 event_ccs; u32 event_ccs;
u32 device_state; u32 device_state;
u32 bytes_remaining[2]; u32 tx_bytes[2];
u32 tx_count[2]; u32 tx_count[2];
u32 ctrl_seq_num; u32 ctrl_seq_num;
u32 config_num; u32 config_num;
@ -881,7 +881,7 @@ int xusb_device_init()
_xusbd_init_device_clocks(); _xusbd_init_device_clocks();
// Enable AHB redirect for access to IRAM for Event/EP ring buffers. // Enable AHB redirect for access to IRAM for Event/EP ring buffers.
mc_enable_ahb_redirect(); // Can be skipped if IRAM is not used. mc_enable_ahb_redirect(false); // Can be skipped if IRAM is not used.
// Enable XUSB device IPFS. // Enable XUSB device IPFS.
XUSB_DEV_DEV(XUSB_DEV_CONFIGURATION) |= DEV_CONFIGURATION_EN_FPCI; XUSB_DEV_DEV(XUSB_DEV_CONFIGURATION) |= DEV_CONFIGURATION_EN_FPCI;
@ -927,7 +927,7 @@ int xusb_device_init()
return USB_RES_OK; return USB_RES_OK;
} }
static int _xusb_queue_trb(int ep_idx, void *trb, bool ring_doorbell) static int _xusb_queue_trb(u32 ep_idx, void *trb, bool ring_doorbell)
{ {
int res = USB_RES_OK; int res = USB_RES_OK;
data_trb_t *next_trb; data_trb_t *next_trb;
@ -1073,7 +1073,7 @@ static int _xusb_issue_normal_trb(u8 *buf, u32 len, usb_dir_t direction)
normal_trb_t trb = {0}; normal_trb_t trb = {0};
_xusb_create_normal_trb(&trb, buf, len, direction); _xusb_create_normal_trb(&trb, buf, len, direction);
int ep_idx = USB_EP_BULK_IN; u32 ep_idx = USB_EP_BULK_IN;
if (direction == USB_DIR_OUT) if (direction == USB_DIR_OUT)
ep_idx = USB_EP_BULK_OUT; ep_idx = USB_EP_BULK_OUT;
int res = _xusb_queue_trb(ep_idx, &trb, EP_RING_DOORBELL); int res = _xusb_queue_trb(ep_idx, &trb, EP_RING_DOORBELL);
@ -1100,19 +1100,32 @@ static int _xusb_issue_data_trb(u8 *buf, u32 len, usb_dir_t direction)
int xusb_set_ep_stall(u32 endpoint, int ep_stall) int xusb_set_ep_stall(u32 endpoint, int ep_stall)
{ {
int ep_idx = BIT(endpoint); u32 ep_mask = BIT(endpoint);
if (ep_stall) if (ep_stall)
XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_HALT) |= ep_idx; XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_HALT) |= ep_mask;
else else
XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_HALT) &= ~ep_idx; XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_HALT) &= ~ep_mask;
// Wait for EP status to change. // Wait for EP status to change.
int res = _xusb_xhci_mask_wait(XUSB_DEV_XHCI_EP_STCHG, ep_idx, ep_idx, 1000); int res = _xusb_xhci_mask_wait(XUSB_DEV_XHCI_EP_STCHG, ep_mask, ep_mask, 1000);
if (res) if (res)
return res; return res;
// Clear status change. // Clear status change.
XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_STCHG) = ep_idx; XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_STCHG) = ep_mask;
return USB_RES_OK;
}
static int _xusb_wait_ep_stopped(u32 endpoint)
{
u32 ep_mask = BIT(endpoint);
// Wait for EP status to change.
_xusb_xhci_mask_wait(XUSB_DEV_XHCI_EP_STOPPED, ep_mask, ep_mask, 1000);
// Clear status change.
XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_STOPPED) = ep_mask;
return USB_RES_OK; return USB_RES_OK;
} }
@ -1158,20 +1171,27 @@ static int _xusb_handle_transfer_event(transfer_event_trb_t *trb)
return _xusb_issue_status_trb(USB_DIR_OUT); return _xusb_issue_status_trb(USB_DIR_OUT);
else if (usbd_xotg->wait_for_event_trb == XUSB_TRB_STATUS) else if (usbd_xotg->wait_for_event_trb == XUSB_TRB_STATUS)
{ {
if (usbd_xotg->device_state == XUSB_ADDRESSED_STS_WAIT) switch (usbd_xotg->device_state)
{
case XUSB_ADDRESSED_STS_WAIT:
usbd_xotg->device_state = XUSB_ADDRESSED; usbd_xotg->device_state = XUSB_ADDRESSED;
else if (usbd_xotg->device_state == XUSB_CONFIGURED_STS_WAIT) break;
case XUSB_CONFIGURED_STS_WAIT:
usbd_xotg->device_state = XUSB_CONFIGURED; usbd_xotg->device_state = XUSB_CONFIGURED;
else if (usbd_xotg->device_state == XUSB_LUN_CONFIGURED_STS_WAIT) break;
case XUSB_LUN_CONFIGURED_STS_WAIT:
usbd_xotg->device_state = XUSB_LUN_CONFIGURED; usbd_xotg->device_state = XUSB_LUN_CONFIGURED;
else if (usbd_xotg->device_state == XUSB_HID_CONFIGURED_STS_WAIT) break;
case XUSB_HID_CONFIGURED_STS_WAIT:
usbd_xotg->device_state = XUSB_HID_CONFIGURED; usbd_xotg->device_state = XUSB_HID_CONFIGURED;
break;
}
} }
break; break;
case USB_EP_BULK_IN: case USB_EP_BULK_IN:
usbd_xotg->bytes_remaining[USB_DIR_IN] -= trb->trb_tx_len; usbd_xotg->tx_bytes[USB_DIR_IN] -= trb->trb_tx_len;
if (usbd_xotg->tx_count[USB_DIR_IN])/////////// if (usbd_xotg->tx_count[USB_DIR_IN])
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 bytes remaining for a Bulk IN transfer, return error.
@ -1181,8 +1201,8 @@ static int _xusb_handle_transfer_event(transfer_event_trb_t *trb)
case USB_EP_BULK_OUT: case USB_EP_BULK_OUT:
// If short packet and Bulk OUT, it's not an error because we prime EP for 4KB. // 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; usbd_xotg->tx_bytes[USB_DIR_OUT] -= trb->trb_tx_len;
if (usbd_xotg->tx_count[USB_DIR_OUT])/////////// if (usbd_xotg->tx_count[USB_DIR_OUT])
usbd_xotg->tx_count[USB_DIR_OUT]--; usbd_xotg->tx_count[USB_DIR_OUT]--;
break; break;
} }
@ -1196,6 +1216,11 @@ static int _xusb_handle_transfer_event(transfer_event_trb_t *trb)
xusb_set_ep_stall(trb->ep_id, USB_EP_CFG_STALL); xusb_set_ep_stall(trb->ep_id, USB_EP_CFG_STALL);
return USB_RES_OK; return USB_RES_OK;
*/ */
case XUSB_COMP_BABBLE_DETECTED_ERROR:
_xusb_wait_ep_stopped(trb->ep_id);
xusb_set_ep_stall(trb->ep_id, USB_EP_CFG_STALL);
return XUSB_ERROR_BABBLE_DETECTED;
case XUSB_COMP_CTRL_DIR_ERROR: case XUSB_COMP_CTRL_DIR_ERROR:
return XUSB_ERROR_XFER_DIR; return XUSB_ERROR_XFER_DIR;
@ -1216,11 +1241,52 @@ static int _xusb_handle_transfer_event(transfer_event_trb_t *trb)
static int _xusb_handle_port_change() static int _xusb_handle_port_change()
{ {
u32 res = USB_RES_OK;
u32 status = XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC); u32 status = XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC);
u32 halt = XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTHALT); u32 halt = XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTHALT);
u32 clear_mask = XHCI_PORTSC_CEC | XHCI_PORTSC_PLC | XHCI_PORTSC_PRC | XHCI_PORTSC_WRC | XHCI_PORTSC_CSC;
// Connect status change (CSC). // Port reset (PR).
if (status & XHCI_PORTSC_PR)
{
//! TODO:
// XHCI_PORTSC_PR: device_state = XUSB_RESET
//_disable_usb_wdt4();
}
// Port Reset Change (PRC).
if (status & XHCI_PORTSC_PRC)
{
// Clear PRC bit.
status &= ~clear_mask;
status |= XHCI_PORTSC_PRC;
XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) = status;
}
// Warm Port Reset (WPR).
if (status & XHCI_PORTSC_WPR)
{
//_disable_usb_wdt4();
XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTHALT) &= ~XHCI_PORTHALT_HALT_LTSSM;
(void)XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTHALT);
//! TODO: XHCI_PORTSC_WPR: device_state = XUSB_RESET
}
// Warm Port Reset Change (WRC).
if (status & XHCI_PORTSC_WRC)
{
// Clear WRC bit.
status &= ~clear_mask;
status |= XHCI_PORTSC_WRC;
XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) = status;
}
// Reread port status to handle more changes.
status = XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC);
// Connect Status Change (CSC).
if (status & XHCI_PORTSC_CSC) if (status & XHCI_PORTSC_CSC)
{ {
//! TODO: Check CCS. //! TODO: Check CCS.
@ -1238,90 +1304,64 @@ static int _xusb_handle_port_change()
volatile xusb_ep_ctx_t *ep_ctxt = &xusb_evtq->xusb_ep_ctxt[XUSB_EP_CTRL_IN]; volatile xusb_ep_ctx_t *ep_ctxt = &xusb_evtq->xusb_ep_ctxt[XUSB_EP_CTRL_IN];
ep_ctxt->avg_trb_len = 8; ep_ctxt->avg_trb_len = 8;
ep_ctxt->max_packet_size = 64; ep_ctxt->max_packet_size = 64;
//! TODO: If super speed is supported, ep context reload, unpause and unhalt must happen.
} }
// Clear CSC bit. // Clear CSC bit.
status &= ~clear_mask;
status |= XHCI_PORTSC_CSC; status |= XHCI_PORTSC_CSC;
XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) = status; 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). // Handle Config Request (STCHG_REQ).
if (halt & XHCI_PORTHALT_STCHG_REQ) if (halt & XHCI_PORTHALT_STCHG_REQ)
{ {
// Clear Link Training Status. // Clear Link Training Status and pending request/reject.
status = XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTHALT) & ~XHCI_PORTHALT_HALT_LTSSM;
XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTHALT) &= ~XHCI_PORTHALT_HALT_LTSSM; XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTHALT) &= ~XHCI_PORTHALT_HALT_LTSSM;
(void)XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTHALT);
} }
// Reread port status to handle more changes.
status = XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC);
// Port link state change (PLC). // Port link state change (PLC).
if (status & XHCI_PORTSC_PLC) if (status & XHCI_PORTSC_PLC)
{ {
//! WAR: Sometimes port speed changes without a CSC event. Set again. // check XHCI_PORTSC_PLS_MASK
usbd_xotg->port_speed = (status & XHCI_PORTSC_PS) >> 10; // if XHCI_PORTSC_PLS_U3
// check PLS
// if U3
// device_state = XUSB_SUSPENDED // device_state = XUSB_SUSPENDED
// else if U0 and XUSB_SUSPENDED // else if XHCI_PORTSC_PLS_U0 and XUSB_SUSPENDED
// val = XUSB_DEV_XHCI_EP_PAUSE // val = XUSB_DEV_XHCI_EP_PAUSE
// XUSB_DEV_XHCI_EP_PAUSE = 0 // XUSB_DEV_XHCI_EP_PAUSE = 0
// XUSB_DEV_XHCI_EP_STCHG = val; // XUSB_DEV_XHCI_EP_STCHG = val;
// Clear PLC bit. // Clear PLC bit.
status = XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) | XHCI_PORTSC_PLC; status &= ~clear_mask;
XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) |= XHCI_PORTSC_PLC; status |= XHCI_PORTSC_PLC;
XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) = status;
} }
// Port configuration link error (CEC). // Port configuration link error (CEC).
if (status & XHCI_PORTSC_CEC) if (status & XHCI_PORTSC_CEC)
{ {
XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) |= XHCI_PORTSC_CEC; status = XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC);
res = XUSB_ERROR_PORT_CFG; status &= ~clear_mask;
status |= XHCI_PORTSC_CEC;
XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) = status;
return XUSB_ERROR_PORT_CFG;
} }
return res; return USB_RES_OK;
} }
static int _xusb_handle_get_ep_status(usb_ctrl_setup_t *ctrl_setup) static int _xusb_handle_get_ep_status(u32 ep_idx)
{ {
u32 ep_mask = BIT(ep_idx);
static u8 xusb_ep_status_descriptor[2] = {0}; static u8 xusb_ep_status_descriptor[2] = {0};
// Get EP context pointer. xusb_ep_status_descriptor[0] =
volatile xusb_ep_ctx_t *ep_ctxt = (volatile xusb_ep_ctx_t *)(XUSB_DEV_XHCI(XUSB_DEV_XHCI_ECPLO) & 0xFFFFFFF0); (XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_HALT) & ep_mask) ? USB_STATUS_EP_HALTED : USB_STATUS_EP_OK;
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); return _xusb_issue_data_trb(xusb_ep_status_descriptor, 2, USB_DIR_IN);
} }
@ -1536,8 +1576,9 @@ static int _xusbd_handle_ep0_control_transfer(usb_ctrl_setup_t *ctrl_setup)
//gfx_printf("ctrl: %02X %02X %04X %04X %04X\n", _bmRequestType, _bRequest, _wValue, _wIndex, _wLength); //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; // Unhalt EP0 IN.
u32 res = _xusb_xhci_mask_wait(XUSB_DEV_XHCI_EP_HALT, XHCI_EP_HALT_DCI, 0, 1000); XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_HALT) &= ~XHCI_EP_HALT_DCI_EP0_IN;
u32 res = _xusb_xhci_mask_wait(XUSB_DEV_XHCI_EP_HALT, XHCI_EP_HALT_DCI_EP0_IN, 0, 1000);
if (res) if (res)
return res; return res;
@ -1557,14 +1598,33 @@ static int _xusbd_handle_ep0_control_transfer(usb_ctrl_setup_t *ctrl_setup)
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT): case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT):
if ((_wValue & 0xFF) == USB_FEATURE_ENDPOINT_HALT) if ((_wValue & 0xFF) == USB_FEATURE_ENDPOINT_HALT)
{ {
if (_bRequest == USB_REQUEST_CLEAR_FEATURE) if (_bRequest == USB_REQUEST_CLEAR_FEATURE || _bRequest == USB_REQUEST_SET_FEATURE)
{ {
xusb_set_ep_stall(_wIndex, USB_EP_CFG_CLEAR); u32 ep = 0;
return _xusb_issue_status_trb(USB_DIR_IN); switch (_wIndex) // endpoint
} {
else if (_bRequest == USB_REQUEST_SET_FEATURE) case USB_EP_ADDR_CTRL_OUT:
{ ep = XUSB_EP_CTRL_OUT;
xusb_set_ep_stall(_wIndex, USB_EP_CFG_STALL); break;
case USB_EP_ADDR_CTRL_IN:
ep = XUSB_EP_CTRL_IN;
break;
case USB_EP_ADDR_BULK_OUT:
ep = USB_EP_BULK_OUT;
break;
case USB_EP_ADDR_BULK_IN:
ep = USB_EP_BULK_IN;
break;
default:
xusb_set_ep_stall(XUSB_EP_CTRL_IN, USB_EP_CFG_STALL);
return USB_RES_OK;
}
if (_bRequest == USB_REQUEST_CLEAR_FEATURE)
xusb_set_ep_stall(ep, USB_EP_CFG_CLEAR);
else if (_bRequest == USB_REQUEST_SET_FEATURE)
xusb_set_ep_stall(ep, USB_EP_CFG_STALL);
return _xusb_issue_status_trb(USB_DIR_IN); return _xusb_issue_status_trb(USB_DIR_IN);
} }
} }
@ -1631,7 +1691,28 @@ static int _xusbd_handle_ep0_control_transfer(usb_ctrl_setup_t *ctrl_setup)
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT): case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT):
if (_bRequest == USB_REQUEST_GET_STATUS) if (_bRequest == USB_REQUEST_GET_STATUS)
return _xusb_handle_get_ep_status(ctrl_setup); {
u32 ep = 0;
switch (_wIndex) // endpoint
{
case USB_EP_ADDR_CTRL_OUT:
ep = XUSB_EP_CTRL_OUT;
break;
case USB_EP_ADDR_CTRL_IN:
ep = XUSB_EP_CTRL_IN;
break;
case USB_EP_ADDR_BULK_OUT:
ep = USB_EP_BULK_OUT;
break;
case USB_EP_ADDR_BULK_IN:
ep = USB_EP_BULK_IN;
break;
default:
xusb_set_ep_stall(XUSB_EP_CTRL_IN, USB_EP_CFG_STALL);
return USB_RES_OK;
}
return _xusb_handle_get_ep_status(ep);
}
ep_stall = true; ep_stall = true;
break; break;
@ -1821,6 +1902,7 @@ int xusb_device_enumerate(usb_gadget_type gadget)
return USB_RES_OK; return USB_RES_OK;
} }
//! TODO: Do a full deinit.
void xusb_end(bool reset_ep, bool only_controller) 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_RST_DEV_W_SET) = BIT(CLK_W_XUSB_SS);
@ -1855,7 +1937,7 @@ int xusb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, u32 sync_tries)
int res = USB_RES_OK; int res = USB_RES_OK;
usbd_xotg->tx_count[USB_DIR_OUT] = 0; usbd_xotg->tx_count[USB_DIR_OUT] = 0;
usbd_xotg->bytes_remaining[USB_DIR_OUT] = len; usbd_xotg->tx_bytes[USB_DIR_OUT] = len;
_xusb_issue_normal_trb(buf, len, USB_DIR_OUT); _xusb_issue_normal_trb(buf, len, USB_DIR_OUT);
usbd_xotg->tx_count[USB_DIR_OUT]++; usbd_xotg->tx_count[USB_DIR_OUT]++;
@ -1865,7 +1947,7 @@ int xusb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, u32 sync_tries)
res = _xusb_ep_operation(sync_tries); res = _xusb_ep_operation(sync_tries);
if (bytes_read) if (bytes_read)
*bytes_read = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_OUT]; *bytes_read = res ? 0 : usbd_xotg->tx_bytes[USB_DIR_OUT];
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
} }
@ -1898,14 +1980,14 @@ int xusb_device_ep1_out_read_big(u8 *buf, u32 len, u32 *bytes_read)
return USB_RES_OK; return USB_RES_OK;
} }
int xusb_device_ep1_out_reading_finish(u32 *pending_bytes) int xusb_device_ep1_out_reading_finish(u32 *pending_bytes, u32 sync_tries)
{ {
int res = USB_RES_OK; int res = USB_RES_OK;
while (!res && usbd_xotg->tx_count[USB_DIR_OUT]) while (!res && usbd_xotg->tx_count[USB_DIR_OUT])
res = _xusb_ep_operation(USB_XFER_SYNCED); // Infinite retries. res = _xusb_ep_operation(sync_tries); // Infinite retries.
if (pending_bytes) if (pending_bytes)
*pending_bytes = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_OUT]; *pending_bytes = res ? 0 : usbd_xotg->tx_bytes[USB_DIR_OUT];
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
@ -1921,7 +2003,7 @@ int xusb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, u32 sync_trie
int res = USB_RES_OK; int res = USB_RES_OK;
usbd_xotg->tx_count[USB_DIR_IN] = 0; usbd_xotg->tx_count[USB_DIR_IN] = 0;
usbd_xotg->bytes_remaining[USB_DIR_IN] = len; usbd_xotg->tx_bytes[USB_DIR_IN] = len;
_xusb_issue_normal_trb(buf, len, USB_DIR_IN); _xusb_issue_normal_trb(buf, len, USB_DIR_IN);
usbd_xotg->tx_count[USB_DIR_IN]++; usbd_xotg->tx_count[USB_DIR_IN]++;
@ -1931,7 +2013,7 @@ int xusb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, u32 sync_trie
res = _xusb_ep_operation(sync_tries); res = _xusb_ep_operation(sync_tries);
if (bytes_written) if (bytes_written)
*bytes_written = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_IN]; *bytes_written = res ? 0 : usbd_xotg->tx_bytes[USB_DIR_IN];
} }
else else
{ {
@ -1947,14 +2029,14 @@ int xusb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, u32 sync_trie
return res; return res;
} }
int xusb_device_ep1_in_writing_finish(u32 *pending_bytes) int xusb_device_ep1_in_writing_finish(u32 *pending_bytes, u32 sync_tries)
{ {
int res = USB_RES_OK; int res = USB_RES_OK;
while (!res && usbd_xotg->tx_count[USB_DIR_IN]) while (!res && usbd_xotg->tx_count[USB_DIR_IN])
res = _xusb_ep_operation(USB_XFER_SYNCED); // Infinite retries. res = _xusb_ep_operation(sync_tries); // Infinite retries.
if (pending_bytes) if (pending_bytes)
*pending_bytes = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_IN]; *pending_bytes = res ? 0 : usbd_xotg->tx_bytes[USB_DIR_IN];
return res; return res;
} }
@ -2010,7 +2092,7 @@ void xusb_device_get_ops(usb_ops_t *ops)
ops->usbd_flush_endpoint = NULL; ops->usbd_flush_endpoint = NULL;
ops->usbd_set_ep_stall = xusb_set_ep_stall; ops->usbd_set_ep_stall = xusb_set_ep_stall;
ops->usbd_handle_ep0_ctrl_setup = xusb_handle_ep0_ctrl_setup; ops->usbd_handle_ep0_ctrl_setup = xusb_handle_ep0_ctrl_setup;
ops->usbd_end = xusb_end;////////////////// ops->usbd_end = xusb_end;
ops->usb_device_init = xusb_device_init; ops->usb_device_init = xusb_device_init;
ops->usb_device_enumerate = xusb_device_enumerate; 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_max_lun = xusb_device_class_send_max_lun;

View file

@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer * Copyright (c) 2018-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -30,6 +30,27 @@
extern volatile nyx_storage_t *nyx_str; extern volatile nyx_storage_t *nyx_str;
u8 bit_count(u32 val)
{
u8 cnt = 0;
for (u32 i = 0; i < 32; i++)
{
if ((val >> i) & 1)
cnt++;
}
return cnt;
}
u32 bit_count_mask(u8 bits)
{
u32 val = 0;
for (u32 i = 0; i < bits; i++)
val |= 1 << i;
return val;
}
u32 get_tmr_s() u32 get_tmr_s()
{ {
return RTC(APBDEV_RTC_SECONDS); return RTC(APBDEV_RTC_SECONDS);

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer * Copyright (c) 2018-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -81,6 +81,9 @@ typedef struct _nyx_storage_t
emc_table_t mtc_table[10]; emc_table_t mtc_table[10];
} nyx_storage_t; } nyx_storage_t;
u8 bit_count(u32 val);
u32 bit_count_mask(u8 bits);
void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops); void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops);
u32 crc32_calc(u32 crc, const u8 *buf, u32 len); u32 crc32_calc(u32 crc, const u8 *buf, u32 len);

View file

@ -38,19 +38,14 @@ void set_default_configuration()
h_cfg.autoboot = 0; h_cfg.autoboot = 0;
h_cfg.autoboot_list = 0; h_cfg.autoboot_list = 0;
h_cfg.bootwait = 3; h_cfg.bootwait = 3;
h_cfg.se_keygen_done = 0;
h_cfg.backlight = 100; h_cfg.backlight = 100;
h_cfg.autohosoff = 0; h_cfg.autohosoff = 0;
h_cfg.autonogc = 1; h_cfg.autonogc = 1;
h_cfg.updater2p = 0; h_cfg.updater2p = 0;
h_cfg.bootprotect = 0; h_cfg.bootprotect = 0;
h_cfg.errors = 0; h_cfg.errors = 0;
h_cfg.eks = NULL;
h_cfg.aes_slots_new = false; h_cfg.aes_slots_new = false;
h_cfg.rcm_patched = fuse_check_patched_rcm(); h_cfg.rcm_patched = fuse_check_patched_rcm();
h_cfg.sbk_set = FUSE(FUSE_PRIVATE_KEY0) == 0xFFFFFFFF;
h_cfg.emummc_force_disable = false; h_cfg.emummc_force_disable = false;
h_cfg.t210b01 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01; h_cfg.t210b01 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01;
sd_power_cycle_time_start = 0;
} }

View file

@ -17,7 +17,6 @@
#ifndef _CONFIG_H_ #ifndef _CONFIG_H_
#define _CONFIG_H_ #define _CONFIG_H_
#include "hos/hos.h"
#include <utils/types.h> #include <utils/types.h>
typedef struct _hekate_config typedef struct _hekate_config
@ -33,13 +32,10 @@ typedef struct _hekate_config
u32 bootprotect; u32 bootprotect;
// Global temporary config. // Global temporary config.
bool t210b01; bool t210b01;
bool se_keygen_done;
bool aes_slots_new; bool aes_slots_new;
bool emummc_force_disable; bool emummc_force_disable;
bool rcm_patched; bool rcm_patched;
bool sbk_set;
u32 errors; u32 errors;
hos_eks_mbr_t *eks;
} hekate_config; } hekate_config;
void set_default_configuration(); void set_default_configuration();

View file

@ -18,122 +18,18 @@
#ifndef _HOS_H_ #ifndef _HOS_H_
#define _HOS_H_ #define _HOS_H_
#include "pkg1.h" #define KB_FIRMWARE_VERSION_100 0
#include "pkg2.h" #define KB_FIRMWARE_VERSION_300 1
#include <sec/se_t210.h> #define KB_FIRMWARE_VERSION_301 2
#include <utils/types.h> #define KB_FIRMWARE_VERSION_400 3
#include <utils/ini.h> #define KB_FIRMWARE_VERSION_500 4
#include <sec/tsec.h> #define KB_FIRMWARE_VERSION_600 5
#define KB_FIRMWARE_VERSION_620 6
#include <assert.h> #define KB_FIRMWARE_VERSION_700 7
#define KB_FIRMWARE_VERSION_810 8
#define KB_FIRMWARE_VERSION_100_200 0 #define KB_FIRMWARE_VERSION_900 9
#define KB_FIRMWARE_VERSION_300 1 #define KB_FIRMWARE_VERSION_910 10
#define KB_FIRMWARE_VERSION_301 2
#define KB_FIRMWARE_VERSION_400 3
#define KB_FIRMWARE_VERSION_500 4
#define KB_FIRMWARE_VERSION_600 5
#define KB_FIRMWARE_VERSION_620 6
#define KB_FIRMWARE_VERSION_700 7
#define KB_FIRMWARE_VERSION_810 8
#define KB_FIRMWARE_VERSION_900 9
#define KB_FIRMWARE_VERSION_910 10
#define KB_FIRMWARE_VERSION_1210 11 #define KB_FIRMWARE_VERSION_1210 11
#define KB_FIRMWARE_VERSION_MAX KB_FIRMWARE_VERSION_1210 #define KB_FIRMWARE_VERSION_MAX KB_FIRMWARE_VERSION_1210 //!TODO: Update on mkey changes.
#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;
bool no_user_exceptions;
bool user_pmu;
bool *usb3_force;
bool *cal0_blank;
bool *cal0_allow_writes_sys;
} exo_ctxt_t;
typedef struct _hos_eks_keys_t
{
u8 mkk[SE_KEY_128_SIZE];
u8 fdk[SE_KEY_128_SIZE];
} hos_eks_keys_t;
typedef struct _hos_eks_bis_keys_t
{
u8 crypt[SE_KEY_128_SIZE];
u8 tweak[SE_KEY_128_SIZE];
} hos_eks_bis_keys_t;
typedef struct _hos_eks_mbr_t
{
u32 magic;
u8 enabled[5];
u8 enabled_bis;
u8 rsvd[2];
u32 lot0;
u8 dkg[SE_KEY_128_SIZE];
u8 dkk[SE_KEY_128_SIZE];
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) == 304, "HOS EKS size is wrong!");
typedef struct _launch_ctxt_t
{
void *keyblob;
void *pkg1;
const pkg1_id_t *pkg1_id;
const pkg2_kernel_id_t *pkg2_kernel_id;
void *warmboot;
u32 warmboot_size;
void *secmon;
u32 secmon_size;
void *exofatal;
u32 exofatal_size;
void *pkg2;
u32 pkg2_size;
bool new_pkg2;
void *kernel;
u32 kernel_size;
link_t kip1_list;
char* kip1_patches;
bool svcperm;
bool debugmode;
bool stock;
bool emummc_forced;
char *fss0_main_path;
u32 fss0_hosver;
bool fss0_experimental;
bool atmosphere;
exo_ctxt_t exo_ctx;
ini_sec_t *cfg;
} launch_ctxt_t;
typedef struct _merge_kip_t
{
void *kip1;
link_t link;
} merge_kip_t;
void hos_eks_get();
void hos_eks_save(u32 kb);
void hos_eks_clear(u32 kb);
int hos_launch(ini_sec_t *cfg);
int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt);
#endif #endif

View file

@ -1,210 +0,0 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018 Atmosphère-NX
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "pkg2.h"
#include <libs/compr/blz.h>
#include <mem/heap.h>
#include <sec/se.h>
#include <utils/aarch64_util.h>
#include <gfx_utils.h>
u32 pkg2_newkern_ini1_val;
u32 pkg2_newkern_ini1_start;
u32 pkg2_newkern_ini1_end;
/*#include "util.h"
#define DPRINTF(...) gfx_printf(__VA_ARGS__)
#define DEBUG_PRINTING*/
#define DPRINTF(...)
static u32 _pkg2_calc_kip1_size(pkg2_kip1_t *kip1)
{
u32 size = sizeof(pkg2_kip1_t);
for (u32 j = 0; j < KIP1_NUM_SECTIONS; j++)
size += kip1->sections[j].size_comp;
return size;
}
void pkg2_get_newkern_info(u8 *kern_data)
{
u32 pkg2_newkern_ini1_off = 0;
pkg2_newkern_ini1_start = 0;
// Find static OP offset that is close to INI1 offset.
u32 counter_ops = 0x100;
while (counter_ops)
{
if (*(u32 *)(kern_data + 0x100 - counter_ops) == PKG2_NEWKERN_GET_INI1_HEURISTIC)
{
pkg2_newkern_ini1_off = 0x100 - counter_ops + 12; // OP found. Add 12 for the INI1 offset.
break;
}
counter_ops -= 4;
}
// Offset not found?
if (!counter_ops)
return;
u32 info_op = *(u32 *)(kern_data + pkg2_newkern_ini1_off);
pkg2_newkern_ini1_val = ((info_op & 0xFFFF) >> 3) + pkg2_newkern_ini1_off; // Parse ADR and PC.
pkg2_newkern_ini1_start = *(u32 *)(kern_data + pkg2_newkern_ini1_val);
pkg2_newkern_ini1_end = *(u32 *)(kern_data + pkg2_newkern_ini1_val + 0x8);
}
bool pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2)
{
u8 *ptr;
// Check for new pkg2 type.
if (!pkg2->sec_size[PKG2_SEC_INI1])
{
pkg2_get_newkern_info(pkg2->data);
if (!pkg2_newkern_ini1_start)
return false;
ptr = pkg2->data + pkg2_newkern_ini1_start;
*new_pkg2 = true;
}
else
ptr = pkg2->data + pkg2->sec_size[PKG2_SEC_KERNEL];
pkg2_ini1_t *ini1 = (pkg2_ini1_t *)ptr;
ptr += sizeof(pkg2_ini1_t);
for (u32 i = 0; i < ini1->num_procs; i++)
{
pkg2_kip1_t *kip1 = (pkg2_kip1_t *)ptr;
pkg2_kip1_info_t *ki = (pkg2_kip1_info_t *)malloc(sizeof(pkg2_kip1_info_t));
ki->kip1 = kip1;
ki->size = _pkg2_calc_kip1_size(kip1);
list_append(info, &ki->link);
ptr += ki->size;
DPRINTF(" kip1 %d:%s @ %08X (%08X)\n", i, kip1->name, (u32)kip1, ki->size);
}
return true;
}
int pkg2_decompress_kip(pkg2_kip1_info_t* ki, u32 sectsToDecomp)
{
u32 compClearMask = ~sectsToDecomp;
if ((ki->kip1->flags & compClearMask) == ki->kip1->flags)
return 0; // Already decompressed, nothing to do.
pkg2_kip1_t hdr;
memcpy(&hdr, ki->kip1, sizeof(hdr));
unsigned int newKipSize = sizeof(hdr);
for (u32 sectIdx = 0; sectIdx < KIP1_NUM_SECTIONS; sectIdx++)
{
u32 sectCompBit = 1u << sectIdx;
// For compressed, cant get actual decompressed size without doing it, so use safe "output size".
if (sectIdx < 3 && (sectsToDecomp & sectCompBit) && (hdr.flags & sectCompBit))
newKipSize += hdr.sections[sectIdx].size_decomp;
else
newKipSize += hdr.sections[sectIdx].size_comp;
}
pkg2_kip1_t* newKip = malloc(newKipSize);
unsigned char* dstDataPtr = newKip->data;
const unsigned char* srcDataPtr = ki->kip1->data;
for (u32 sectIdx = 0; sectIdx < KIP1_NUM_SECTIONS; sectIdx++)
{
u32 sectCompBit = 1u << sectIdx;
// Easy copy path for uncompressed or ones we dont want to uncompress.
if (sectIdx >= 3 || !(sectsToDecomp & sectCompBit) || !(hdr.flags & sectCompBit))
{
unsigned int dataSize = hdr.sections[sectIdx].size_comp;
if (dataSize == 0)
continue;
memcpy(dstDataPtr, srcDataPtr, dataSize);
srcDataPtr += dataSize;
dstDataPtr += dataSize;
continue;
}
unsigned int compSize = hdr.sections[sectIdx].size_comp;
unsigned int outputSize = hdr.sections[sectIdx].size_decomp;
//gfx_printf("Decomping %s KIP1 sect %d of size %d...\n", (const char*)hdr.name, sectIdx, compSize);
if (blz_uncompress_srcdest(srcDataPtr, compSize, dstDataPtr, outputSize) == 0)
{
gfx_printf("%kERROR decomping sect %d of %s KIP!%k\n", 0xFFFF0000, sectIdx, (char*)hdr.name, 0xFFCCCCCC);
free(newKip);
return 1;
}
else
{
DPRINTF("Done! Decompressed size is %d!\n", outputSize);
}
hdr.sections[sectIdx].size_comp = outputSize;
srcDataPtr += compSize;
dstDataPtr += outputSize;
}
hdr.flags &= compClearMask;
memcpy(newKip, &hdr, sizeof(hdr));
newKipSize = dstDataPtr-(unsigned char*)(newKip);
free(ki->kip1);
ki->kip1 = newKip;
ki->size = newKipSize;
return 0;
}
pkg2_hdr_t *pkg2_decrypt(void *data)
{
u8 *pdata = (u8 *)data;
// Skip signature.
pdata += 0x100;
pkg2_hdr_t *hdr = (pkg2_hdr_t *)pdata;
// Skip header.
pdata += sizeof(pkg2_hdr_t);
// Decrypt header.
se_aes_crypt_ctr(8, hdr, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr);
//gfx_hexdump((u32)hdr, hdr, 0x100);
if (hdr->magic != PKG2_MAGIC)
return NULL;
for (u32 i = 0; i < 4; i++)
{
DPRINTF("sec %d has size %08X\n", i, hdr->sec_size[i]);
if (!hdr->sec_size[i])
continue;
se_aes_crypt_ctr(8, pdata, hdr->sec_size[i], pdata, hdr->sec_size[i], &hdr->sec_ctr[i * 0x10]);
//gfx_hexdump((u32)pdata, pdata, 0x100);
pdata += hdr->sec_size[i];
}
return hdr;
}

View file

@ -1,109 +0,0 @@
/*
* 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,
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef _PKG2_H_
#define _PKG2_H_
#include <utils/types.h>
#include <utils/list.h>
#define PKG2_MAGIC 0x31324B50
#define PKG2_SEC_BASE 0x80000000
#define PKG2_SEC_KERNEL 0
#define PKG2_SEC_INI1 1
#define PKG2_NEWKERN_GET_INI1_HEURISTIC 0xD2800015 // Offset of OP + 12 is the INI1 offset.
extern u32 pkg2_newkern_ini1_val;
extern u32 pkg2_newkern_ini1_start;
extern u32 pkg2_newkern_ini1_end;
typedef struct _kernel_patch_t
{
u32 id;
u32 off;
u32 val;
u32 *ptr;
} kernel_patch_t;
typedef struct _pkg2_hdr_t
{
u8 ctr[0x10];
u8 sec_ctr[0x40];
u32 magic;
u32 base;
u32 pad0;
u8 pkg2_ver;
u8 bl_ver;
u16 pad1;
u32 sec_size[4];
u32 sec_off[4];
u8 sec_sha256[0x80];
u8 data[];
} pkg2_hdr_t;
typedef struct _pkg2_ini1_t
{
u32 magic;
u32 size;
u32 num_procs;
u32 pad;
} pkg2_ini1_t;
typedef struct _pkg2_kip1_sec_t
{
u32 offset;
u32 size_decomp;
u32 size_comp;
u32 attrib;
} pkg2_kip1_sec_t;
#define KIP1_NUM_SECTIONS 6
typedef struct _pkg2_kip1_t
{
u32 magic;
u8 name[12];
u64 tid;
u32 proc_cat;
u8 main_thrd_prio;
u8 def_cpu_core;
u8 res;
u8 flags;
pkg2_kip1_sec_t sections[KIP1_NUM_SECTIONS];
u32 caps[0x20];
u8 data[];
} pkg2_kip1_t;
typedef struct _pkg2_kip1_info_t
{
pkg2_kip1_t *kip1;
u32 size;
link_t link;
} pkg2_kip1_info_t;
typedef struct _pkg2_kernel_id_t
{
u8 hash[8];
kernel_patch_t *kernel_patchset;
} pkg2_kernel_id_t;
bool pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2);
int pkg2_decompress_kip(pkg2_kip1_info_t* ki, u32 sectsToDecomp);
pkg2_hdr_t *pkg2_decrypt(void *data);
#endif

View file

@ -23,7 +23,6 @@
#include <gfx_utils.h> #include <gfx_utils.h>
#include "../gfx/tui.h" #include "../gfx/tui.h"
#include "../hos/pkg1.h" #include "../hos/pkg1.h"
#include "../hos/pkg2.h"
#include <libs/fatfs/ff.h> #include <libs/fatfs/ff.h>
#include <libs/nx_savedata/save.h> #include <libs/nx_savedata/save.h>
#include <mem/heap.h> #include <mem/heap.h>
@ -79,21 +78,6 @@ static void _get_device_key(u32 ks, key_derivation_ctx_t *keys, void *out_device
// titlekey functions // titlekey functions
static bool _test_key_pair(const void *E, const void *D, const void *N); static bool _test_key_pair(const void *E, const void *D, const void *N);
static ALWAYS_INLINE u8 *_find_tsec_fw(const u8 *pkg1) {
const u32 tsec_fw_align = 0x100;
const u32 tsec_fw_first_instruction = 0xCF42004D;
for (const u32 *pos = (const u32 *)pkg1; (u8 *)pos < pkg1 + PKG1_MAX_SIZE; pos += tsec_fw_align / sizeof(u32))
if (*pos == tsec_fw_first_instruction)
return (u8 *)pos;
return NULL;
}
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(const pkg1_id_t **pkg1_id) { static u8 *_read_pkg1(const pkg1_id_t **pkg1_id) {
if (emummc_storage_init_mmc()) { if (emummc_storage_init_mmc()) {
EPRINTF("Unable to init MMC."); EPRINTF("Unable to init MMC.");
@ -125,17 +109,18 @@ static u8 *_read_pkg1(const pkg1_id_t **pkg1_id) {
static void _derive_master_key_mariko(key_derivation_ctx_t *keys, bool is_dev) { static void _derive_master_key_mariko(key_derivation_ctx_t *keys, bool is_dev) {
// Relies on the SBK being properly set in slot 14 // 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); se_aes_crypt_block_ecb(14, DECRYPT, keys->device_key_4x, device_master_key_source_kek_source);
// Relies on the Mariko KEK being properly set in slot 12 // Relies on the Mariko KEK being properly set in slot 12
se_aes_unwrap_key(8, 12, is_dev ? &mariko_master_kek_sources_dev[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_600] : &mariko_master_kek_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_600]); se_aes_unwrap_key(8, 12, is_dev ? &mariko_master_kek_sources_dev[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_600] : &mariko_master_kek_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_600]);
se_aes_crypt_block_ecb(8, 0, keys->master_key[KB_FIRMWARE_VERSION_MAX], master_key_source); se_aes_crypt_block_ecb(8, DECRYPT, keys->master_key[KB_FIRMWARE_VERSION_MAX], master_key_source);
} }
static int _run_ams_keygen(key_derivation_ctx_t *keys) { static int _run_ams_keygen(key_derivation_ctx_t *keys) {
tsec_ctxt_t tsec_ctxt; tsec_ctxt_t tsec_ctxt;
tsec_ctxt.fw = tsec_keygen; tsec_ctxt.fw = tsec_keygen;
tsec_ctxt.size = sizeof(tsec_keygen); tsec_ctxt.size = sizeof(tsec_keygen);
int res = tsec_run_fw(&tsec_ctxt); tsec_ctxt.type = TSEC_FW_TYPE_NEW;
int res = tsec_query(keys->temp_key, &tsec_ctxt);
if (res) { if (res) {
EPRINTFARGS("ERROR %d running keygen.\n", res); EPRINTFARGS("ERROR %d running keygen.\n", res);
@ -149,19 +134,19 @@ static void _derive_master_keys_from_latest_key(key_derivation_ctx_t *keys, bool
u32 tsec_root_key_slot = is_dev ? 11 : 13; u32 tsec_root_key_slot = is_dev ? 11 : 13;
// Derive all master keys based on current root key // Derive all master keys based on current root key
for (u32 i = KB_FIRMWARE_VERSION_810 - KB_FIRMWARE_VERSION_620; i < ARRAY_SIZE(master_kek_sources); i++) { for (u32 i = KB_FIRMWARE_VERSION_810 - KB_FIRMWARE_VERSION_620; i < ARRAY_SIZE(master_kek_sources); i++) {
se_aes_crypt_block_ecb(tsec_root_key_slot, 0, keys->master_kek[i + KB_FIRMWARE_VERSION_620], master_kek_sources[i]); // mkek = unwrap(tsec_root, mkeks) se_aes_crypt_block_ecb(tsec_root_key_slot, DECRYPT, keys->master_kek[i + KB_FIRMWARE_VERSION_620], master_kek_sources[i]); // mkek = unwrap(tsec_root, mkeks)
se_aes_key_set(8, keys->master_kek[i + KB_FIRMWARE_VERSION_620], AES_128_KEY_SIZE); // mkey = unwrap(mkek, mkeys) se_aes_key_set(8, keys->master_kek[i + KB_FIRMWARE_VERSION_620], AES_128_KEY_SIZE); // mkey = unwrap(mkek, mkeys)
se_aes_crypt_block_ecb(8, 0, keys->master_key[i + KB_FIRMWARE_VERSION_620], master_key_source); se_aes_crypt_block_ecb(8, DECRYPT, keys->master_key[i + KB_FIRMWARE_VERSION_620], master_key_source);
} }
} }
// Derive all lower master keys // Derive all lower master keys
for (u32 i = KB_FIRMWARE_VERSION_MAX; i > 0; i--) { for (u32 i = KB_FIRMWARE_VERSION_MAX; i > 0; i--) {
se_aes_key_set(8, keys->master_key[i], AES_128_KEY_SIZE); 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], is_dev ? master_key_vectors_dev[i] : master_key_vectors[i]); se_aes_crypt_block_ecb(8, DECRYPT, keys->master_key[i - 1], is_dev ? master_key_vectors_dev[i] : master_key_vectors[i]);
} }
se_aes_key_set(8, keys->master_key[0], AES_128_KEY_SIZE); se_aes_key_set(8, keys->master_key[0], AES_128_KEY_SIZE);
se_aes_crypt_block_ecb(8, 0, keys->temp_key, is_dev ? master_key_vectors_dev[0] : master_key_vectors[0]); se_aes_crypt_block_ecb(8, DECRYPT, keys->temp_key, is_dev ? master_key_vectors_dev[0] : master_key_vectors[0]);
if (_key_exists(keys->temp_key)) { if (_key_exists(keys->temp_key)) {
EPRINTFARGS("Unable to derive master keys for %s.", is_dev ? "dev" : "prod"); EPRINTFARGS("Unable to derive master keys for %s.", is_dev ? "dev" : "prod");
@ -174,7 +159,7 @@ static void _derive_keyblob_keys(key_derivation_ctx_t *keys) {
encrypted_keyblob_t *current_keyblob = (encrypted_keyblob_t *)keyblob_block; encrypted_keyblob_t *current_keyblob = (encrypted_keyblob_t *)keyblob_block;
u32 keyblob_mac[AES_128_KEY_SIZE / 4] = {0}; u32 keyblob_mac[AES_128_KEY_SIZE / 4] = {0};
if (h_cfg.sbk_set) { if (FUSE(FUSE_PRIVATE_KEY0) == 0xFFFFFFFF) {
u8 *aes_keys = (u8 *)calloc(0x1000, 1); u8 *aes_keys = (u8 *)calloc(0x1000, 1);
se_get_aes_keys(aes_keys + 0x800, aes_keys, AES_128_KEY_SIZE); 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); memcpy(keys->sbk, aes_keys + 14 * AES_128_KEY_SIZE, AES_128_KEY_SIZE);
@ -192,13 +177,13 @@ static void _derive_keyblob_keys(key_derivation_ctx_t *keys) {
for (u32 i = 0; i <= KB_FIRMWARE_VERSION_600; i++, current_keyblob++) { for (u32 i = 0; i <= KB_FIRMWARE_VERSION_600; i++, current_keyblob++) {
minerva_periodic_training(); minerva_periodic_training();
se_aes_crypt_block_ecb(12, 0, keys->keyblob_key[i], keyblob_key_sources[i]); // temp = unwrap(kbks, tsec) se_aes_crypt_block_ecb(12, DECRYPT, keys->keyblob_key[i], keyblob_key_sources[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_crypt_block_ecb(14, DECRYPT, 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_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) se_aes_crypt_block_ecb(7, DECRYPT, keys->keyblob_mac_key[i], keyblob_mac_key_source); // kbm = unwrap(kbms, kbk)
if (i == 0) { 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, DECRYPT, 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); se_aes_crypt_block_ecb(7, DECRYPT, keys->device_key_4x, device_master_key_source_kek_source);
} }
// verify keyblob is not corrupt // verify keyblob is not corrupt
@ -217,7 +202,7 @@ static void _derive_keyblob_keys(key_derivation_ctx_t *keys) {
memcpy(keys->master_kek[i], keys->keyblob[i].master_kek, sizeof(keys->master_kek[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])); se_aes_key_set(7, keys->master_kek[i], sizeof(keys->master_kek[i]));
if (!_key_exists(keys->master_key[i])) { if (!_key_exists(keys->master_key[i])) {
se_aes_crypt_block_ecb(7, 0, keys->master_key[i], master_key_source); se_aes_crypt_block_ecb(7, DECRYPT, keys->master_key[i], master_key_source);
} }
} }
free(keyblob_block); free(keyblob_block);
@ -238,15 +223,15 @@ static void _derive_bis_keys(key_derivation_ctx_t *keys) {
_generate_specific_aes_key(8, keys, &keys->bis_key[0], &bis_key_sources[0], key_generation); _generate_specific_aes_key(8, keys, &keys->bis_key[0], &bis_key_sources[0], key_generation);
// kek = generate_kek(bkeks, devkey, aeskek, aeskey) // kek = generate_kek(bkeks, devkey, aeskek, aeskey)
_generate_kek(8, bis_kek_source, keys->temp_key, aes_kek_generation_source, aes_key_generation_source); _generate_kek(8, bis_kek_source, keys->temp_key, aes_kek_generation_source, aes_key_generation_source);
se_aes_crypt_ecb(8, 0, keys->bis_key[1], AES_128_KEY_SIZE * 2, bis_key_sources[1], AES_128_KEY_SIZE * 2); // bkey = unwrap(bkeys, kek) se_aes_crypt_ecb(8, DECRYPT, keys->bis_key[1], AES_128_KEY_SIZE * 2, bis_key_sources[1], AES_128_KEY_SIZE * 2); // bkey = unwrap(bkeys, kek)
se_aes_crypt_ecb(8, 0, keys->bis_key[2], AES_128_KEY_SIZE * 2, bis_key_sources[2], AES_128_KEY_SIZE * 2); se_aes_crypt_ecb(8, DECRYPT, keys->bis_key[2], AES_128_KEY_SIZE * 2, bis_key_sources[2], AES_128_KEY_SIZE * 2);
memcpy(keys->bis_key[3], keys->bis_key[2], 0x20); memcpy(keys->bis_key[3], keys->bis_key[2], 0x20);
} }
static void _derive_non_unique_keys(key_derivation_ctx_t *keys, bool is_dev) { static void _derive_non_unique_keys(key_derivation_ctx_t *keys, bool is_dev) {
if (_key_exists(keys->master_key[0])) { 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); _generate_kek(8, header_kek_source, keys->master_key[0], aes_kek_generation_source, aes_key_generation_source);
se_aes_crypt_ecb(8, 0, keys->header_key, AES_128_KEY_SIZE * 2, header_key_source, AES_128_KEY_SIZE * 2); se_aes_crypt_ecb(8, DECRYPT, keys->header_key, AES_128_KEY_SIZE * 2, header_key_source, AES_128_KEY_SIZE * 2);
} }
} }
@ -254,19 +239,19 @@ static void _derive_misc_keys(key_derivation_ctx_t *keys, bool is_dev) {
if (_key_exists(keys->device_key) || (_key_exists(keys->master_key[0]) && _key_exists(keys->device_key_4x))) { if (_key_exists(keys->device_key) || (_key_exists(keys->master_key[0]) && _key_exists(keys->device_key_4x))) {
_get_device_key(8, keys, keys->temp_key, 0); _get_device_key(8, keys, keys->temp_key, 0);
_generate_kek(8, save_mac_kek_source, keys->temp_key, aes_kek_generation_source, NULL); _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); se_aes_crypt_block_ecb(8, DECRYPT, keys->save_mac_key, save_mac_key_source);
} }
if (_key_exists(keys->master_key[0])) { if (_key_exists(keys->master_key[0])) {
for (u32 i = 0; i < AES_128_KEY_SIZE; i++) for (u32 i = 0; i < AES_128_KEY_SIZE; i++)
keys->temp_key[i] = aes_kek_generation_source[i] ^ aes_kek_seed_03[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); _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, is_dev ? eticket_rsa_kek_source_dev : eticket_rsa_kek_source); se_aes_crypt_block_ecb(8, DECRYPT, keys->eticket_rsa_kek, is_dev ? eticket_rsa_kek_source_dev : eticket_rsa_kek_source);
for (u32 i = 0; i < AES_128_KEY_SIZE; i++) for (u32 i = 0; i < AES_128_KEY_SIZE; i++)
keys->temp_key[i] = aes_kek_generation_source[i] ^ aes_kek_seed_01[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); _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); se_aes_crypt_block_ecb(8, DECRYPT, keys->ssl_rsa_kek, ssl_rsa_kek_source_y);
} }
} }
@ -276,11 +261,11 @@ static void _derive_master_key_per_generation_keys(key_derivation_ctx_t *keys) {
continue; continue;
for (u32 j = 0; j < 3; j++) { for (u32 j = 0; j < 3; j++) {
_generate_kek(8, key_area_key_sources[j], keys->master_key[i], aes_kek_generation_source, NULL); _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_crypt_block_ecb(8, DECRYPT, 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_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, DECRYPT, keys->package2_key[i], package2_key_source);
se_aes_crypt_block_ecb(8, 0, keys->titlekek[i], titlekek_source); se_aes_crypt_block_ecb(8, DECRYPT, keys->titlekek[i], titlekek_source);
} }
} }
@ -478,7 +463,7 @@ static bool _derive_titlekeys(key_derivation_ctx_t *keys, titlekey_buffer_t *tit
return false; 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); se_aes_xts_crypt(1, 0, DECRYPT, 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; nx_emmc_cal0_t *cal0 = (nx_emmc_cal0_t *)titlekey_buffer->read_buffer;
if (cal0->magic != MAGIC_CAL0) { if (cal0->magic != MAGIC_CAL0) {
@ -496,7 +481,7 @@ static bool _derive_titlekeys(key_derivation_ctx_t *keys, titlekey_buffer_t *tit
u32 temp_device_key[AES_128_KEY_SIZE / 4] = {0}; u32 temp_device_key[AES_128_KEY_SIZE / 4] = {0};
_get_device_key(7, keys, temp_device_key, keypair_generation); _get_device_key(7, keys, temp_device_key, keypair_generation);
_generate_kek(7, eticket_rsa_kekek_source, temp_device_key, keys->temp_key, NULL); _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); se_aes_crypt_block_ecb(7, DECRYPT, keys->eticket_rsa_kek_personalized, eticket_rsa_kek_source);
memcpy(keys->temp_key, keys->eticket_rsa_kek_personalized, sizeof(keys->temp_key)); memcpy(keys->temp_key, keys->eticket_rsa_kek_personalized, sizeof(keys->temp_key));
} else { } else {
memcpy(keys->temp_key, keys->eticket_rsa_kek, sizeof(keys->temp_key)); memcpy(keys->temp_key, keys->eticket_rsa_kek, sizeof(keys->temp_key));
@ -594,21 +579,21 @@ static void _save_mariko_partial_keys(u32 start, u32 count, bool append) {
for (u32 ks = start; ks < start + count; ks++) { for (u32 ks = start; ks < start + count; ks++) {
// Check if key is as expected // Check if key is as expected
if (ks < ARRAY_SIZE(mariko_key_vectors)) { if (ks < ARRAY_SIZE(mariko_key_vectors)) {
se_aes_crypt_block_ecb(ks, 0, &data[0], mariko_key_vectors[ks]); se_aes_crypt_block_ecb(ks, DECRYPT, &data[0], mariko_key_vectors[ks]);
if (_key_exists(data)) { if (_key_exists(data)) {
continue; continue;
} }
} }
// Encrypt zeros with complete key // Encrypt zeros with complete key
se_aes_crypt_block_ecb(ks, 1, &data[3 * AES_128_KEY_SIZE], zeros); se_aes_crypt_block_ecb(ks, ENCRYPT, &data[3 * AES_128_KEY_SIZE], zeros);
// We only need to overwrite 3 of the dwords of the key // We only need to overwrite 3 of the dwords of the key
for (u32 i = 0; i < 3; i++) { for (u32 i = 0; i < 3; i++) {
// Overwrite ith dword of key with zeros // Overwrite ith dword of key with zeros
se_aes_key_partial_set(ks, i, 0); se_aes_key_partial_set(ks, i, 0);
// Encrypt zeros with more of the key zeroed out // Encrypt zeros with more of the key zeroed out
se_aes_crypt_block_ecb(ks, 1, &data[(2 - i) * AES_128_KEY_SIZE], zeros); se_aes_crypt_block_ecb(ks, ENCRYPT, &data[(2 - i) * AES_128_KEY_SIZE], zeros);
} }
// Skip saving key if two results are the same indicating unsuccessful overwrite or empty slot // Skip saving key if two results are the same indicating unsuccessful overwrite or empty slot
@ -785,7 +770,7 @@ static bool _check_keyslot_access() {
u8 test_data[AES_128_KEY_SIZE] = {0}; u8 test_data[AES_128_KEY_SIZE] = {0};
const u8 test_ciphertext[AES_128_KEY_SIZE] = {0}; const u8 test_ciphertext[AES_128_KEY_SIZE] = {0};
se_aes_key_set(8, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", SE_KEY_128_SIZE); se_aes_key_set(8, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", SE_KEY_128_SIZE);
se_aes_crypt_block_ecb(8, 0, test_data, test_ciphertext); se_aes_crypt_block_ecb(8, DECRYPT, test_data, test_ciphertext);
return memcmp(test_data, "\x7b\x1d\x29\xa1\x6c\xf8\xcc\xab\x84\xf0\xb8\xa5\x98\xe4\x2f\xa6", SE_KEY_128_SIZE) == 0; return memcmp(test_data, "\x7b\x1d\x29\xa1\x6c\xf8\xcc\xab\x84\xf0\xb8\xa5\x98\xe4\x2f\xa6", SE_KEY_128_SIZE) == 0;
} }
@ -944,14 +929,14 @@ static void _generate_specific_aes_key(u32 ks, key_derivation_ctx_t *keys, void
_get_device_key(ks, keys, keys->temp_key, key_generation); _get_device_key(ks, keys, keys->temp_key, key_generation);
se_aes_key_set(ks, keys->temp_key, AES_128_KEY_SIZE); se_aes_key_set(ks, keys->temp_key, AES_128_KEY_SIZE);
se_aes_unwrap_key(ks, ks, retail_specific_aes_key_source); // kek = unwrap(rsaks, devkey) se_aes_unwrap_key(ks, ks, retail_specific_aes_key_source); // kek = unwrap(rsaks, devkey)
se_aes_crypt_ecb(ks, 0, out_key, AES_128_KEY_SIZE * 2, key_source, AES_128_KEY_SIZE * 2); // bkey = unwrap(bkeys, kek) se_aes_crypt_ecb(ks, DECRYPT, out_key, AES_128_KEY_SIZE * 2, key_source, AES_128_KEY_SIZE * 2); // bkey = unwrap(bkeys, kek)
} else { } else {
_get_secure_data(keys, out_key); _get_secure_data(keys, out_key);
} }
} }
static void _get_device_key(u32 ks, key_derivation_ctx_t *keys, void *out_device_key, u32 revision) { static void _get_device_key(u32 ks, key_derivation_ctx_t *keys, void *out_device_key, u32 revision) {
if (revision == KB_FIRMWARE_VERSION_100_200 && !h_cfg.t210b01) { if (revision == KB_FIRMWARE_VERSION_100 && !h_cfg.t210b01) {
memcpy(out_device_key, keys->device_key, AES_128_KEY_SIZE); memcpy(out_device_key, keys->device_key, AES_128_KEY_SIZE);
return; return;
} }
@ -963,11 +948,11 @@ static void _get_device_key(u32 ks, key_derivation_ctx_t *keys, void *out_device
} }
u32 temp_key[AES_128_KEY_SIZE / 4] = {0}; u32 temp_key[AES_128_KEY_SIZE / 4] = {0};
se_aes_key_set(ks, keys->device_key_4x, AES_128_KEY_SIZE); se_aes_key_set(ks, keys->device_key_4x, AES_128_KEY_SIZE);
se_aes_crypt_block_ecb(ks, 0, temp_key, device_master_key_source_sources[revision]); se_aes_crypt_block_ecb(ks, DECRYPT, temp_key, device_master_key_source_sources[revision]);
se_aes_key_set(ks, keys->master_key[0], AES_128_KEY_SIZE); se_aes_key_set(ks, keys->master_key[0], AES_128_KEY_SIZE);
const void *kek_source = fuse_read_hw_state() == FUSE_NX_HW_STATE_PROD ? device_master_kek_sources[revision] : device_master_kek_sources_dev[revision]; const void *kek_source = fuse_read_hw_state() == FUSE_NX_HW_STATE_PROD ? device_master_kek_sources[revision] : device_master_kek_sources_dev[revision];
se_aes_unwrap_key(ks, ks, kek_source); se_aes_unwrap_key(ks, ks, kek_source);
se_aes_crypt_block_ecb(ks, 0, out_device_key, temp_key); se_aes_crypt_block_ecb(ks, DECRYPT, out_device_key, temp_key);
} }
static bool _test_key_pair(const void *public_exponent, const void *private_exponent, const void *modulus) { static bool _test_key_pair(const void *public_exponent, const void *private_exponent, const void *modulus) {

View file

@ -23,6 +23,7 @@
#include <display/di.h> #include <display/di.h>
#include <gfx_utils.h> #include <gfx_utils.h>
#include "gfx/tui.h" #include "gfx/tui.h"
#include "hos/pkg1.h"
#include <libs/fatfs/ff.h> #include <libs/fatfs/ff.h>
#include <mem/heap.h> #include <mem/heap.h>
#include <mem/minerva.h> #include <mem/minerva.h>

View file

@ -160,7 +160,7 @@ static int nx_emmc_bis_write_block(u32 sector, u32 count, void *buff, bool force
} }
// Encrypt and write. // Encrypt and write.
if (!_nx_aes_xts_crypt_sec(ks_tweak, ks_crypt, 1, tweak, true, sector_index_in_cluster, cluster, bis_cache->emmc_buffer, buff, count * NX_EMMC_BLOCKSIZE) || if (!_nx_aes_xts_crypt_sec(ks_tweak, ks_crypt, ENCRYPT, tweak, true, sector_index_in_cluster, cluster, bis_cache->emmc_buffer, buff, count * NX_EMMC_BLOCKSIZE) ||
!nx_emmc_part_write(&emmc_storage, system_part, sector, count, bis_cache->emmc_buffer) !nx_emmc_part_write(&emmc_storage, system_part, sector, count, bis_cache->emmc_buffer)
) )
return 1; // R/W error. return 1; // R/W error.
@ -227,7 +227,7 @@ static int nx_emmc_bis_read_block(u32 sector, u32 count, void *buff)
// Read and decrypt the whole cluster the sector resides in. // Read and decrypt the whole cluster the sector resides in.
if (!nx_emmc_part_read(&emmc_storage, system_part, aligned_sector, SECTORS_PER_CLUSTER, bis_cache->emmc_buffer) || if (!nx_emmc_part_read(&emmc_storage, system_part, aligned_sector, SECTORS_PER_CLUSTER, bis_cache->emmc_buffer) ||
!_nx_aes_xts_crypt_sec(ks_tweak, ks_crypt, 0, cache_tweak, true, 0, cluster, bis_cache->emmc_buffer, bis_cache->emmc_buffer, XTS_CLUSTER_SIZE) !_nx_aes_xts_crypt_sec(ks_tweak, ks_crypt, DECRYPT, cache_tweak, true, 0, cluster, bis_cache->emmc_buffer, bis_cache->emmc_buffer, XTS_CLUSTER_SIZE)
) )
return 1; // R/W error. return 1; // R/W error.
@ -257,7 +257,7 @@ static int nx_emmc_bis_read_block(u32 sector, u32 count, void *buff)
tweak_exp = sector_index_in_cluster; tweak_exp = sector_index_in_cluster;
// Maximum one cluster (1 XTS crypto block 16KB). // Maximum one cluster (1 XTS crypto block 16KB).
if (!_nx_aes_xts_crypt_sec(ks_tweak, ks_crypt, 0, tweak, regen_tweak, tweak_exp, prev_cluster, buff, bis_cache->emmc_buffer, count * NX_EMMC_BLOCKSIZE)) if (!_nx_aes_xts_crypt_sec(ks_tweak, ks_crypt, DECRYPT, tweak, regen_tweak, tweak_exp, prev_cluster, buff, bis_cache->emmc_buffer, count * NX_EMMC_BLOCKSIZE))
return 1; // R/W error. return 1; // R/W error.
prev_sector = sector + count - 1; prev_sector = sector + count - 1;