update bdk

Signed-off-by: Damien Zhao <zdm65477730@126.com>
This commit is contained in:
Damien Zhao
2022-11-08 22:29:07 +08:00
parent 049845227d
commit f1db80024c
76 changed files with 2567 additions and 1831 deletions

View File

@@ -8,7 +8,7 @@ include $(DEVKITARM)/base_rules
################################################################################ ################################################################################
IPL_LOAD_ADDR := 0x40003000 IPL_LOAD_ADDR := 0x40008000
LPVERSION_MAJOR := 0 LPVERSION_MAJOR := 0
LPVERSION_MINOR := 3 LPVERSION_MINOR := 3
LPVERSION_BUGFX := 4 LPVERSION_BUGFX := 4

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_AMS699VC01;
// Initialize display panel. // Initialize display panel.
switch (_display_id) switch (_display_id)
{ {
case PANEL_SAM_AMS699VC01:
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 180000);
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE_PARAM, 0xA0, 0); // Write 0 to 0xA0.
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE_PARAM, MIPI_DCS_SET_CONTROL_DISPLAY | (DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL << 8), 0); // Enable brightness control.
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_AMS699VC01)
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,27 @@ 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)
{
// Normalize brightness value by 82% and a base of 45 duty.
if (brightness)
brightness = (brightness * PANEL_OLED_BL_COEFF / 100) + PANEL_OLED_BL_OFFSET;
u16 bl_ctrl = byte_swap_16((u16)(brightness * 8));
display_dsi_vblank_write(MIPI_DCS_SET_BRIGHTNESS, 2, &bl_ctrl);
}
void display_pwm_backlight_brightness(u32 brightness, u32 step_delay)
{ {
u32 old_value = (PWM(PWM_CONTROLLER_PWM_CSR_0) >> 16) & 0xFF; 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 +583,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 +591,22 @@ 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_AMS699VC01)
display_pwm_backlight_brightness(brightness, step_delay);
else
display_dsi_backlight_brightness(brightness);
}
u32 display_get_backlight_brightness()
{
return ((PWM(PWM_CONTROLLER_PWM_CSR_0) >> 16) & 0xFF);
}
static void _display_panel_and_hw_end(bool no_panel_deinit) static void _display_panel_and_hw_end(bool no_panel_deinit)
{ {
if (no_panel_deinit) if (no_panel_deinit)
@@ -527,7 +627,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_AMS699VC01)
usleep(10000);
// De-initialize display panel. // De-initialize display panel.
switch (_display_id) switch (_display_id)
@@ -579,16 +681,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_AMS699VC01) ? 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);
@@ -601,9 +710,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); };
@@ -615,11 +727,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_AMS699VC01;
} }
void display_color_screen(u32 color) void display_color_screen(u32 color)
@@ -632,9 +751,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_AMS699VC01)
display_backlight(true);
else
display_backlight_brightness(255, 0);
} }
u32 *display_init_framebuffer_pitch() u32 *display_init_framebuffer_pitch()
@@ -644,7 +766,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;
} }
@@ -653,8 +775,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;
} }
@@ -663,8 +784,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)
@@ -644,21 +652,29 @@
#define DCS_CONTROL_DISPLAY_DIMMING_CTRL BIT(3) #define DCS_CONTROL_DISPLAY_DIMMING_CTRL BIT(3)
#define DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL BIT(5) #define DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL BIT(5)
#define PANEL_OLED_BL_COEFF 82 // 82%.
#define PANEL_OLED_BL_OFFSET 45 // Least legible backlight duty.
/* Switch Panels: /* Switch Panels:
* *
* 6.2" panels for Icosa and Iowa skus: * 6.2" panels for Icosa and Iowa skus:
* [10] 81 [26]: JDI LPM062M326A * [10] 81 [26]: JDI LPM062M326A
* [10] 96 [09]: JDI LAM062M109A * [10] 96 [09]: JDI LAM062M109A
* [20] 93 [0F]: InnoLux P062CCA-AZ1 (Rev A1) * [20] 93 [0F]: InnoLux P062CCA-AZ1 (Rev A1)
* [20] 95 [0F]: InnoLux P062CCA-AZ2 * [20] 95 [0F]: InnoLux P062CCA-AZ2 (Rev B1)
* [20] 96 [0F]: InnoLux P062CCA-AZ3 * [20] 96 [0F]: InnoLux P062CCA-AZ3 [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] 9B [20]: Samsung AMS699VC01-0 (Rev 2.5)
*/ */
/* Display ID Decoding: /* Display ID Decoding:
@@ -671,13 +687,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
@@ -689,7 +705,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_AMS699VC01 = 0x2050
}; };
void display_init(); void display_init();
@@ -706,6 +723,7 @@ void display_color_screen(u32 color);
/*! Switches screen backlight ON/OFF. */ /*! Switches screen backlight ON/OFF. */
void display_backlight(bool enable); void display_backlight(bool enable);
void display_backlight_brightness(u32 brightness, u32 step_delay); void display_backlight_brightness(u32 brightness, u32 step_delay);
u32 display_get_backlight_brightness();
/*! Init display in full 1280x720 resolution (B8G8R8A8, line stride 768, framebuffer size = 1280*768*4 bytes). */ /*! Init display in full 1280x720 resolution (B8G8R8A8, line stride 768, framebuffer size = 1280*768*4 bytes). */
u32 *display_init_framebuffer_pitch(); u32 *display_init_framebuffer_pitch();

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

@@ -21,6 +21,7 @@
#include "elfload/elfload.h" #include "elfload/elfload.h"
#include <module.h> #include <module.h>
#include <mem/heap.h> #include <mem/heap.h>
#include <power/max7762x.h>
#include <storage/nx_sd.h> #include <storage/nx_sd.h>
#include <utils/types.h> #include <utils/types.h>
@@ -43,6 +44,10 @@ static void _ianos_call_ep(moduleEntrypoint_t entrypoint, void *moduleConfig)
bdkParameters->memset = (memset_t)&memset; bdkParameters->memset = (memset_t)&memset;
bdkParameters->sharedHeap = &_heap; bdkParameters->sharedHeap = &_heap;
// Extra functions.
bdkParameters->extension_magic = IANOS_EXT0;
bdkParameters->reg_voltage_set = (reg_voltage_set_t)&max7762x_regulator_set_voltage;
entrypoint(moduleConfig, bdkParameters); entrypoint(moduleConfig, bdkParameters);
} }

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

@@ -1,7 +1,7 @@
/* /*
* Joy-Con UART driver for Nintendo Switch * Joy-Con UART driver for Nintendo Switch
* *
* 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,
@@ -463,7 +463,7 @@ static void jc_rcv_pkt(joycon_ctxt_t *jc)
// Check if device stopped sending data. // Check if device stopped sending data.
u32 uart_irq = uart_get_IIR(jc->uart); u32 uart_irq = uart_get_IIR(jc->uart);
if ((uart_irq & 0x8) != 0x8) if (uart_irq != UART_IIR_REDI)
return; return;
u32 len = uart_recv(jc->uart, (u8 *)jc->buf, 0x100); u32 len = uart_recv(jc->uart, (u8 *)jc->buf, 0x100);
@@ -694,9 +694,15 @@ retry:
void jc_deinit() void jc_deinit()
{ {
// Disable power.
jc_power_supply(UART_B, false);
jc_power_supply(UART_C, false);
// Turn off Joy-Con detect.
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO); gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO);
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO); gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO);
// Send sleep command.
u8 data = HCI_STATE_SLEEP; u8 data = HCI_STATE_SLEEP;
if (jc_r.connected && !(jc_r.type & JC_ID_HORI)) if (jc_r.connected && !(jc_r.type & JC_ID_HORI))
@@ -710,8 +716,9 @@ void jc_deinit()
jc_rcv_pkt(&jc_l); jc_rcv_pkt(&jc_l);
} }
jc_power_supply(UART_B, false); // Disable UART B and C clocks.
jc_power_supply(UART_C, false); clock_disable_uart(UART_B);
clock_disable_uart(UART_C);
} }
static void jc_init_conn(joycon_ctxt_t *jc) static void jc_init_conn(joycon_ctxt_t *jc)
@@ -878,14 +885,14 @@ void jc_init_hw()
pinmux_config_uart(UART_C); pinmux_config_uart(UART_C);
// Ease the stress to APB. // Ease the stress to APB.
bpmp_clk_rate_set(BPMP_CLK_NORMAL); bpmp_freq_t prev_fid = bpmp_clk_rate_set(BPMP_CLK_NORMAL);
// Enable UART B and C clocks. // Enable UART B and C clocks.
clock_enable_uart(UART_B); clock_enable_uart(UART_B);
clock_enable_uart(UART_C); clock_enable_uart(UART_C);
// Restore OC. // Restore OC.
bpmp_clk_rate_set(BPMP_CLK_DEFAULT_BOOST); bpmp_clk_rate_set(prev_fid);
// Turn Joy-Con detect on. // Turn Joy-Con detect on.
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_GPIO); gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_GPIO);

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, "Samsung BH2109" },
{ -1, 1, 0, 1, "GiS VA 6.2\"" } { -1, 1, 0, 1, "GiS VA 6.2\"" }
}; };
@@ -206,6 +206,7 @@ touch_panel_info_t *touch_get_panel_vendor()
{ {
u8 buf[5] = {0}; u8 buf[5] = {0};
u8 cmd = STMFTS_VENDOR_GPIO_STATE; u8 cmd = STMFTS_VENDOR_GPIO_STATE;
static touch_panel_info_t panel_info = { -2, 0, 0, 0, ""};
if (touch_command(STMFTS_VENDOR, &cmd, 1)) if (touch_command(STMFTS_VENDOR, &cmd, 1))
return NULL; return NULL;
@@ -220,13 +221,20 @@ touch_panel_info_t *touch_get_panel_vendor()
return panel; return panel;
} }
return NULL; // Touch panel not found, return current gpios.
panel_info.gpio0 = buf[0];
panel_info.gpio1 = buf[1];
panel_info.gpio2 = buf[2];
return &panel_info;
} }
int touch_get_fw_info(touch_fw_info_t *fw) int touch_get_fw_info(touch_fw_info_t *fw)
{ {
u8 buf[8] = {0}; u8 buf[8] = {0};
memset(fw, 0, sizeof(touch_fw_info_t));
// Get fw address info. // Get fw address info.
u8 cmd[3] = { STMFTS_RW_FRAMEBUFFER_REG, 0, 0x60 }; u8 cmd[3] = { STMFTS_RW_FRAMEBUFFER_REG, 0, 0x60 };
int res = touch_read_reg(cmd, 3, buf, 3); int res = touch_read_reg(cmd, 3, buf, 3);
@@ -318,7 +326,7 @@ int touch_get_fb_info(u8 *buf)
int res = 0; int res = 0;
for (u32 i = 0; i < 0x10000; i+=4) for (u32 i = 0; i < 0x10000; i += 4)
{ {
if (!res) if (!res)
{ {
@@ -392,11 +400,11 @@ static int touch_init()
int touch_power_on() int touch_power_on()
{ {
// Enable LDO6 for touchscreen VDD/AVDD supply. // Enable LDO6 for touchscreen AVDD supply.
max7762x_regulator_set_voltage(REGULATOR_LDO6, 2900000); max7762x_regulator_set_voltage(REGULATOR_LDO6, 2900000);
max7762x_regulator_enable(REGULATOR_LDO6, true); max7762x_regulator_enable(REGULATOR_LDO6, true);
// Configure touchscreen GPIO. // Configure touchscreen VDD GPIO.
PINMUX_AUX(PINMUX_AUX_DAP4_SCLK) = PINMUX_PULL_DOWN | 1; PINMUX_AUX(PINMUX_AUX_DAP4_SCLK) = PINMUX_PULL_DOWN | 1;
gpio_config(GPIO_PORT_J, GPIO_PIN_7, GPIO_MODE_GPIO); gpio_config(GPIO_PORT_J, GPIO_PIN_7, GPIO_MODE_GPIO);
gpio_output_enable(GPIO_PORT_J, GPIO_PIN_7, GPIO_OUTPUT_ENABLE); gpio_output_enable(GPIO_PORT_J, GPIO_PIN_7, GPIO_OUTPUT_ENABLE);
@@ -410,7 +418,7 @@ int touch_power_on()
// Configure Touscreen and GCAsic shared GPIO. // Configure Touscreen and GCAsic shared GPIO.
PINMUX_AUX(PINMUX_AUX_CAM_I2C_SDA) = PINMUX_LPDR | PINMUX_INPUT_ENABLE | PINMUX_TRISTATE | PINMUX_PULL_UP | 2; PINMUX_AUX(PINMUX_AUX_CAM_I2C_SDA) = PINMUX_LPDR | PINMUX_INPUT_ENABLE | PINMUX_TRISTATE | PINMUX_PULL_UP | 2;
PINMUX_AUX(PINMUX_AUX_CAM_I2C_SCL) = PINMUX_IO_HV | PINMUX_LPDR | PINMUX_TRISTATE | PINMUX_PULL_DOWN | 2; PINMUX_AUX(PINMUX_AUX_CAM_I2C_SCL) = PINMUX_IO_HV | PINMUX_LPDR | PINMUX_TRISTATE | PINMUX_PULL_DOWN | 2;
gpio_config(GPIO_PORT_S, GPIO_PIN_3, GPIO_MODE_GPIO); gpio_config(GPIO_PORT_S, GPIO_PIN_3, GPIO_MODE_GPIO); // GC detect.
// Initialize I2C3. // Initialize I2C3.
pinmux_config_i2c(I2C_3); pinmux_config_i2c(I2C_3);

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

@@ -839,10 +839,12 @@ int LZ4_compress_fast_extState_fastReset(void* state, const char* src, char* dst
int LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) int LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
{ {
int result; int result;
LZ4_stream_t ctx; LZ4_stream_t* ctx = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t));
LZ4_stream_t* const ctxPtr = &ctx; LZ4_stream_t* const ctxPtr = ctx;
result = LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration); result = LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration);
FREEMEM(ctx);
return result; return result;
} }
@@ -857,13 +859,18 @@ int LZ4_compress_default(const char* source, char* dest, int inputSize, int maxO
/* strangely enough, gcc generates faster code when this function is uncommented, even if unused */ /* strangely enough, gcc generates faster code when this function is uncommented, even if unused */
int LZ4_compress_fast_force(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) int LZ4_compress_fast_force(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
{ {
LZ4_stream_t ctx; int result;
LZ4_resetStream(&ctx); LZ4_stream_t* ctx = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t));
LZ4_resetStream(ctx);
if (inputSize < LZ4_64Klimit) if (inputSize < LZ4_64Klimit)
return LZ4_compress_generic(&ctx.internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration); result = LZ4_compress_generic(&ctx->internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration);
else else
return LZ4_compress_generic(&ctx.internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, sizeof(void*)==8 ? byU32 : byPtr, noDict, noDictIssue, acceleration); result = LZ4_compress_generic(&ctx->internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, sizeof(void*)==8 ? byU32 : byPtr, noDict, noDictIssue, acceleration);
FREEMEM(ctx);
return result;
} }
@@ -1045,11 +1052,13 @@ static int LZ4_compress_destSize_extState (LZ4_stream_t* state, const char* src,
int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize) int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize)
{ {
LZ4_stream_t ctxBody; LZ4_stream_t* ctxBody = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t));;
LZ4_stream_t* ctx = &ctxBody; LZ4_stream_t* ctx = ctxBody;
int result = LZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize); int result = LZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize);
FREEMEM(ctxBody);
return result; return result;
} }

View File

@@ -27,7 +27,8 @@ typedef enum {
DRIVE_SD = 0, DRIVE_SD = 0,
DRIVE_RAM = 1, DRIVE_RAM = 1,
DRIVE_EMMC = 2, DRIVE_EMMC = 2,
DRIVE_BIS = 3 DRIVE_BIS = 3,
DRIVE_EMU = 4
} DDRIVE; } DDRIVE;
@@ -59,6 +60,7 @@ DRESULT disk_set_info (BYTE pdrv, BYTE cmd, void *buff);
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */ #define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */ #define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */ #define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */
#define SET_SECTOR_OFFSET 5 /* Set media logical offset */
/* Generic command (Not used by FatFs) */ /* Generic command (Not used by FatFs) */
#define CTRL_POWER 5 /* Get/Set power status */ #define CTRL_POWER 5 /* Get/Set power status */

View File

@@ -155,7 +155,7 @@
/*Log settings*/ /*Log settings*/
#ifdef DEBUG_UART_PORT #ifdef DEBUG_UART_LV_LOG
# define USE_LV_LOG 1 /*Enable/disable the log module*/ # define USE_LV_LOG 1 /*Enable/disable the log module*/
#else #else
# define USE_LV_LOG 0 /*Enable/disable the log module*/ # define USE_LV_LOG 0 /*Enable/disable the log module*/

View File

@@ -63,7 +63,7 @@ void lv_log_add(lv_log_level_t level, const char * file, int line, const char *
if(level >= LV_LOG_LEVEL) { if(level >= LV_LOG_LEVEL) {
#if LV_LOG_PRINTF #if LV_LOG_PRINTF && defined(DEBUG_UART_PORT)
static const char * lvl_prefix[] = {"Trace", "Info", "Warn", "Error"}; static const char * lvl_prefix[] = {"Trace", "Info", "Warn", "Error"};
char *log = (char *)malloc(0x1000); char *log = (char *)malloc(0x1000);
s_printf(log, "%s: %s \t(%s #%d)\r\n", lvl_prefix[level], dsc, file, line); s_printf(log, "%s: %s \t(%s #%d)\r\n", lvl_prefix[level], dsc, file, line);

View File

@@ -99,10 +99,9 @@ bool save_data_file_write(save_data_file_ctx_t *ctx, uint64_t *out_bytes_written
if (!save_data_file_validate_write_params(ctx, offset, count, ctx->mode, &is_resize_needed)) if (!save_data_file_validate_write_params(ctx, offset, count, ctx->mode, &is_resize_needed))
return false; return false;
if (is_resize_needed) { if (!save_data_file_set_size(ctx, offset + count))
if (!save_data_file_set_size(ctx, offset + count)) return false;
return false;
}
*out_bytes_written = save_allocation_table_storage_write(&ctx->base_storage, buffer, offset, count); *out_bytes_written = save_allocation_table_storage_write(&ctx->base_storage, buffer, offset, count);
return true; return true;

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

@@ -104,21 +104,21 @@ u32 minerva_init()
} }
mtc_cfg->rate_from = mtc_cfg->mtc_table[curr_ram_idx].rate_khz; mtc_cfg->rate_from = mtc_cfg->mtc_table[curr_ram_idx].rate_khz;
mtc_cfg->rate_to = 204000; mtc_cfg->rate_to = FREQ_204;
mtc_cfg->train_mode = OP_TRAIN; mtc_cfg->train_mode = OP_TRAIN;
minerva_cfg(mtc_cfg, NULL); minerva_cfg(mtc_cfg, NULL);
mtc_cfg->rate_to = 800000; mtc_cfg->rate_to = FREQ_800;
minerva_cfg(mtc_cfg, NULL); minerva_cfg(mtc_cfg, NULL);
mtc_cfg->rate_to = 1600000; mtc_cfg->rate_to = FREQ_1600;
minerva_cfg(mtc_cfg, NULL); minerva_cfg(mtc_cfg, NULL);
// FSP WAR. // FSP WAR.
mtc_cfg->train_mode = OP_SWITCH; mtc_cfg->train_mode = OP_SWITCH;
mtc_cfg->rate_to = 800000; mtc_cfg->rate_to = FREQ_800;
minerva_cfg(mtc_cfg, NULL); minerva_cfg(mtc_cfg, NULL);
// Switch to max. // Switch to max.
mtc_cfg->rate_to = 1600000; mtc_cfg->rate_to = FREQ_1600;
minerva_cfg(mtc_cfg, NULL); minerva_cfg(mtc_cfg, NULL);
return 0; return 0;
@@ -139,6 +139,23 @@ void minerva_change_freq(minerva_freq_t freq)
} }
} }
void minerva_prep_boot_freq()
{
if (!minerva_cfg)
return;
mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
// Check if there's RAM OC. If not exit.
if (mtc_cfg->mtc_table[mtc_cfg->table_entries - 1].rate_khz == FREQ_1600)
return;
// FSP WAR.
minerva_change_freq(FREQ_204);
// Scale down to 800 MHz boot freq.
minerva_change_freq(FREQ_800);
}
void minerva_periodic_training() void minerva_periodic_training()
{ {
if (!minerva_cfg) if (!minerva_cfg)

View File

@@ -27,8 +27,8 @@
typedef struct typedef struct
{ {
s32 rate_to; u32 rate_to;
s32 rate_from; u32 rate_from;
emc_table_t *mtc_table; emc_table_t *mtc_table;
u32 table_entries; u32 table_entries;
emc_table_t *current_emc_table; emc_table_t *current_emc_table;
@@ -60,6 +60,7 @@ typedef enum
extern void (*minerva_cfg)(mtc_config_t *mtc_cfg, void *); extern void (*minerva_cfg)(mtc_config_t *mtc_cfg, void *);
u32 minerva_init(); u32 minerva_init();
void minerva_change_freq(minerva_freq_t freq); void minerva_change_freq(minerva_freq_t freq);
void minerva_prep_boot_freq();
void minerva_periodic_training(); void minerva_periodic_training();
#endif #endif

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_WTE,
LPDDR4X_NO_PATCH,
LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ,
LPDDR4X_NO_PATCH,
LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE,
LPDDR4X_4GB_SAMSUNG_Y,
LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL,
LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL,
LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL,
LPDDR4X_4GB_SAMSUNG_1Y_Y,
LPDDR4X_8GB_SAMSUNG_1Y_Y,
LPDDR4X_UNUSED, // Removed.
LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL,
LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL,
LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF,
LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF,
LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF,
LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL,
};
#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
@@ -44,46 +50,74 @@ enum sdram_ids_erista
// LPDDR4 3200Mbps. // LPDDR4 3200Mbps.
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, // WT:C.
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_WTE = 11, // 4266Mbps. 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_WTE = 15, // 4266Mbps. 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_8GB_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_MT53E512M32D2NP_046_WTF = 25, // 4266Mbps. Die-F.
LPDDR4X_HOAG_4GB_MICRON_1Y_A = 26, LPDDR4X_HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTF = 26, // 4266Mbps. Die-F.
LPDDR4X_AULA_4GB_MICRON_1Y_A = 27 LPDDR4X_AULA_4GB_MICRON_MT53E512M32D2NP_046_WTF = 27, // 4266Mbps. Die-F.
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_WTE = 3, // DRAM IDs: 11, 15.
LPDDR4X_4GB_SAMSUNG_Y = 4, // DRAM IDs: 16.
LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 5, // DRAM IDs: 17, 19, 24.
LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 6, // DRAM IDs: 18, 23, 28.
LPDDR4X_4GB_SAMSUNG_1Y_Y = 7, // DRAM IDs: 20.
LPDDR4X_8GB_SAMSUNG_1Y_Y = 8, // DRAM IDs: 21.
//LPDDR4X_8GB_SAMSUNG_1Y_A = 9, // DRAM IDs: 22. Unused.
LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF = 10, // DRAM IDs: 25, 26, 27.
LPDDR4X_4GB_HYNIX_1Y_A = 11, // DRAM IDs: 03, 05, 06.
}; };
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,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,287 @@ 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:E 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_WTE }, // 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_WTE }, // emc_auto_cal_vref_sel0.
{ 0x88161414, 0x2E0 / 4, DRAM_ID2(11) | DRAM_ID2(15) }, // emc_mrw14. { 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE }, // emc_mrw14.
{ 0x80000713, 0x32C / 4, DRAM_ID2(11) | DRAM_ID2(15) }, // emc_dyn_self_ref_control. { 0x80000713, 0x32C / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE }, // 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_WTE }, // 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_WTE }, // 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 8GB 10nm-class (1y-A01) Die-? for SDEV Aula?
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(22) }, // emc_auto_cal_vref_sel0. { 0x00000001, 0x134 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_adr_cfg. 2 Ranks.
{ 0x00000008, 0x24C / 4, DRAM_ID2(22) }, // emc_tfaw. { 0x08010004, 0x2B8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw1.
{ 0x1C041B06, 0x26C / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd0_0. { 0x08020000, 0x2BC / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw2.
{ 0x02050307, 0x270 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd0_1. { 0x080D0000, 0x2C0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw3.
{ 0x03252500, 0x274 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd0_2. { 0x08033131, 0x2C8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw6.
{ 0x081D1E00, 0x278 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd1_0. { 0x080B0000, 0x2CC / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw8.
{ 0x090C0A0D, 0x27C / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd1_1. { 0x0C0E5D5D, 0x2D0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw9.
{ 0x0526260B, 0x280 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd1_2. { 0x080C5D5D, 0x2D4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw10.
{ 0x05030402, 0x284 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd2_0. { 0x0C0D0808, 0x2D8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw12.
{ 0x1B1C0600, 0x288 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd2_1. { 0x0C0D0000, 0x2DC / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw13.
{ 0x07252507, 0x28C / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd2_2. { 0x08161414, 0x2E0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw14.
{ 0x0C1D0B0A, 0x290 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd3_0. { 0x08010004, 0x2E4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw_extra.
{ 0x0800090D, 0x294 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd3_1. { 0x00000000, 0x340 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_dev_select. Both devices.
{ 0x0926261E, 0x298 / 4, DRAM_ID2(22) }, // emc_cmd_mapping_cmd3_2. { 0x35353535, 0x350 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_vref_dq_0.
{ 0x2A080624, 0x29C / 4, DRAM_ID2(22) }, // emc_cmd_mapping_byte. { 0x35353535, 0x354 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_vref_dq_1.
{ 0x88161414, 0x2E0 / 4, DRAM_ID2(22) }, // emc_mrw14. { 0x35353535, 0x358 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_vref_dqs_0.
{ 0x80000713, 0x32C / 4, DRAM_ID2(22) }, // emc_dyn_self_ref_control. { 0x35353535, 0x35C / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_vref_dqs_1.
{ 0x00140010, 0x3AC / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dq_rank0_4. { 0x00480048, 0x3FC / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank0_0.
{ 0x0013000B, 0x3B0 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dq_rank0_5. { 0x00480048, 0x400 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank0_1.
{ 0x00140010, 0x3C4 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dq_rank1_4. { 0x00480048, 0x404 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank0_2.
{ 0x0013000B, 0x3C8 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dq_rank1_5. { 0x00480048, 0x408 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank0_3.
{ 0x00450047, 0x3CC / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank0_0. { 0x00480048, 0x40C / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank1_0.
{ 0x004D004F, 0x3D0 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank0_1. { 0x00480048, 0x410 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank1_1.
{ 0x00460046, 0x3D4 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank0_2. { 0x00480048, 0x414 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank1_2.
{ 0x00480048, 0x3D8 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank0_3. { 0x00480048, 0x418 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank1_3.
{ 0x000C0008, 0x3DC / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank0_4. { 0x0051004F, 0x450 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_zcal_mrw_cmd.
{ 0x000B000C, 0x3E0 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank0_5. { 0x40000001, 0x45C / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_zcal_init_dev1.
{ 0x00450047, 0x3E4 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank1_0. { 0x00010100, 0x594 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_tx_pwrd4.
{ 0x004D004F, 0x3E8 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank1_1. { 0x00400010, 0x598 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_tx_pwrd5.
{ 0x00460046, 0x3EC / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank1_2. { 0x00000001, 0x630 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // mc_emem_adr_cfg. 2 Ranks.
{ 0x00480048, 0x3F0 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank1_3. { 0x00002000, 0x64C / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // mc_emem_cfg. 8GB total density.
{ 0x000C0008, 0x3F4 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank1_4. { 0x00000002, 0x670 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // mc_emem_arb_timing_faw.
{ 0x000B000C, 0x3F8 / 4, DRAM_ID2(22) }, // emc_pmacro_ob_ddll_long_dqs_rank1_5. { 0x00000002, 0x680 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // mc_emem_arb_timing_r2r.
{ 0x00100010, 0x41C / 4, DRAM_ID2(22) }, // emc_pmacro_ddll_long_cmd_0. { 0x02020001, 0x694 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // mc_emem_arb_da_turns.
{ 0x00140014, 0x420 / 4, DRAM_ID2(22) }, // emc_pmacro_ddll_long_cmd_1. */
{ 0x00130013, 0x428 / 4, DRAM_ID2(22) }, // emc_pmacro_ddll_long_cmd_3.
{ 0x00000010, 0x42C / 4, DRAM_ID2(22) }, // emc_pmacro_ddll_long_cmd_4.
{ 0x40280100, 0x4B4 / 4, DRAM_ID2(22) }, // pmc_ddr_cfg.
{ 0x4F9F9FFF, 0x4B8 / 4, DRAM_ID2(22) }, // pmc_io_dpd3_req.
{ 0x64032157, 0x4D8 / 4, DRAM_ID2(22) }, // emc_swizzle_rank0_byte0.
{ 0x51320467, 0x4DC / 4, DRAM_ID2(22) }, // emc_swizzle_rank0_byte1.
{ 0x04735621, 0x4E0 / 4, DRAM_ID2(22) }, // emc_swizzle_rank0_byte2.
{ 0x47356012, 0x4E4 / 4, DRAM_ID2(22) }, // emc_swizzle_rank0_byte3.
{ 0x12045673, 0x4E8 / 4, DRAM_ID2(22) }, // emc_swizzle_rank1_byte0.
{ 0x43657210, 0x4EC / 4, DRAM_ID2(22) }, // emc_swizzle_rank1_byte1.
{ 0x65402137, 0x4F0 / 4, DRAM_ID2(22) }, // emc_swizzle_rank1_byte2.
{ 0x57302164, 0x4F4 / 4, DRAM_ID2(22) }, // emc_swizzle_rank1_byte3.
{ 0x4F9F9FFF, 0x534 / 4, DRAM_ID2(22) }, // emc_pmc_scratch1.
{ 0x4033CF1F, 0x53C / 4, DRAM_ID2(22) }, // emc_pmc_scratch3.
{ 0x10000000, 0x590 / 4, DRAM_ID2(22) }, // emc_pmacro_tx_pwrd3.
{ 0x00030108, 0x594 / 4, DRAM_ID2(22) }, // emc_pmacro_tx_pwrd4.
{ 0x01400050, 0x598 / 4, DRAM_ID2(22) }, // emc_pmacro_tx_pwrd5.
{ 0x29081081, 0x5A0 / 4, DRAM_ID2(22) }, // emc_pmacro_brick_mapping0.
{ 0x54A59332, 0x5A4 / 4, DRAM_ID2(22) }, // emc_pmacro_brick_mapping1.
{ 0x87766B4A, 0x5A8 / 4, DRAM_ID2(22) }, // emc_pmacro_brick_mapping2.
{ 0x00000001, 0x670 / 4, DRAM_ID2(22) }, // mc_emem_arb_timing_faw.
{ 0xE4FACB43, 0x6D4 / 4, DRAM_ID2(22) }, // mc_video_protect_vpr_override. + TSEC, NVENC.
{ 0x0600FED3, 0x6D8 / 4, DRAM_ID2(22) }, // mc_video_protect_vpr_override1. + TSECB, TSEC1, TSECB1.
{ 0x2A800000, 0x6DC / 4, DRAM_ID2(22) }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, DRAM_ID2(22) }, // mc_video_protect_gpu_override1.
{ 0x0000009C, 0x814 / 4, DRAM_ID2(22) }, // swizzle_rank_byte_encode.
// Micron LPDDR4X 4GB 10nm-class (1y) Die-A for Unknown Iowa/Hoag/Aula. // Micron LPDDR4X 4GB MT53D1024M32D1NP-053-WT:F 10nm-class (1y-01) Die-F for Newer Iowa/Hoag/Aula.
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_auto_cal_config2. { 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // 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_MICRON_MT53E512M32D2NP_046_WTF }, // emc_auto_cal_vref_sel0.
{ 0x00000006, 0x1CC / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_quse. { 0x00000006, 0x1CC / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_quse.
{ 0x00000005, 0x1D0 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_quse_width. { 0x00000005, 0x1D0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_quse_width.
{ 0x00000003, 0x1DC / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_einput. { 0x00000003, 0x1DC / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_einput.
{ 0x0000000C, 0x1E0 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_einput_duration. { 0x0000000C, 0x1E0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_einput_duration.
{ 0x00000008, 0x24C / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_tfaw. { 0x00000008, 0x24C / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_tfaw.
{ 0x88161414, 0x2E0 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_mrw14. { 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_mrw14.
{ 0x80000713, 0x32C / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_dyn_self_ref_control. { 0x80000713, 0x32C / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // 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_MICRON_MT53E512M32D2NP_046_WTF }, // mc_emem_arb_timing_faw.
{ 0x2A800000, 0x6DC / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // mc_video_protect_gpu_override0. { 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // mc_video_protect_gpu_override1. { 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // mc_video_protect_gpu_override1.
// Hynix LPDDR4X 4GB 10nm-class (1y-01) Die-A for Unknown Iowa/Hoag/Aula.
{ 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_auto_cal_config2.
{ 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_auto_cal_vref_sel0.
{ 0x00000006, 0x1CC / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_quse.
{ 0x00000005, 0x1D0 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_quse_width.
{ 0x00000003, 0x1DC / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_einput.
{ 0x0000000C, 0x1E0 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_einput_duration.
{ 0x00000008, 0x24C / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_tfaw.
{ 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_mrw14.
{ 0x80000713, 0x32C / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_dyn_self_ref_control.
{ 0x00000001, 0x670 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // mc_emem_arb_timing_faw.
{ 0xE4FACB43, 0x6D4 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // mc_video_protect_vpr_override. + TSEC, NVENC.
{ 0x0600FED3, 0x6D8 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // mc_video_protect_vpr_override1. + TSECB, TSEC1, TSECB1.
{ 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // mc_video_protect_gpu_override1.
//!TODO: Too many duplicates.
}; };

View File

@@ -48,8 +48,8 @@ u8 smmu_payload[] __attribute__((aligned(16))) = {
void *page_alloc(u32 num) void *page_alloc(u32 num)
{ {
u8 *res = _pageheap; u8 *res = _pageheap;
_pageheap += 0x1000 * num; _pageheap += SZ_PAGE * num;
memset(res, 0, 0x1000 * num); memset(res, 0, SZ_PAGE * num);
return res; return res;
} }
@@ -150,8 +150,8 @@ void smmu_map(u32 *pdir, u32 addr, u32 page, int cnt, u32 attr)
{ {
u32 *pte = smmu_get_pte(pdir, addr); u32 *pte = smmu_get_pte(pdir, addr);
*pte = SMMU_ADDR_TO_PFN(page) | attr; *pte = SMMU_ADDR_TO_PFN(page) | attr;
addr += 0x1000; addr += SZ_PAGE;
page += 0x1000; page += SZ_PAGE;
} }
smmu_flush_all(); smmu_flush_all();
} }

View File

@@ -1,5 +1,5 @@
/* /*
* 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,
@@ -19,11 +19,11 @@
//#define IPL_STACK_TOP 0x4003FF00 //#define IPL_STACK_TOP 0x4003FF00
/* --- BIT/BCT: 0x40000000 - 0x40003000 --- */ /* --- BIT/BCT: 0x40000000 - 0x40003000 --- */
/* --- IPL: 0x40003000 - 0x40028000 --- */ /* --- IPL: 0x40008000 - 0x40028000 --- */
#define LDR_LOAD_ADDR 0x40007000 #define LDR_LOAD_ADDR 0x40007000
#define IPL_LOAD_ADDR 0x40003000 #define IPL_LOAD_ADDR 0x40008000
#define IPL_SZ_MAX 0x20000 // 128KB. #define IPL_SZ_MAX SZ_128K
/* --- XUSB EP context and TRB ring buffers --- */ /* --- XUSB EP context and TRB ring buffers --- */
#define XUSB_RING_ADDR 0x40020000 #define XUSB_RING_ADDR 0x40020000
@@ -35,45 +35,51 @@
/* --- DRAM START --- */ /* --- DRAM START --- */
#define DRAM_START 0x80000000 #define DRAM_START 0x80000000
#define HOS_RSVD 0x1000000 // Do not write anything in this area. #define HOS_RSVD SZ_16M // Do not write anything in this area.
#define NYX_LOAD_ADDR 0x81000000 #define NYX_LOAD_ADDR 0x81000000
#define NYX_SZ_MAX 0x1000000 // 16MB #define NYX_SZ_MAX SZ_16M
/* --- Gap: 0x82000000 - 0x82FFFFFF --- */ /* --- Gap: 0x82000000 - 0x82FFFFFF --- */
/* Stack theoretical max: 33MB */ /* Stack theoretical max: 33MB */
#define IPL_STACK_TOP 0x83100000 #define IPL_STACK_TOP 0x83100000
#define IPL_HEAP_START 0x84000000 #define IPL_HEAP_START 0x84000000
#define IPL_HEAP_SZ 0x20000000 // 512MB. #define IPL_HEAP_SZ SZ_512M
/* --- Gap: 1040MB 0xA4000000 - 0xE4FFFFFF --- */ /* --- Gap: 1040MB 0xA4000000 - 0xE4FFFFFF --- */
// Virtual disk / Chainloader buffers. // Virtual disk / Chainloader buffers.
#define RAM_DISK_ADDR 0xA4000000 #define RAM_DISK_ADDR 0xA4000000
#define NX_BIS_CACHE_ADDR RAM_DISK_ADDR #define RAM_DISK_SZ 0x41000000 // 1040MB.
#define RAM_DISK_SZ 0x41000000 // 1040MB. #define RAM_DISK2_SZ 0x21000000 // 528MB.
// NX BIS driver sector cache.
#define NX_BIS_CACHE_ADDR 0xC5000000
#define NX_BIS_CACHE_SZ 0x10020000 // 256MB.
#define NX_BIS_LOOKUP_ADDR 0xD6000000
#define NX_BIS_LOOKUP_SZ 0xF000000 // 240MB.
// L4T Kernel Panic Storage (PSTORE). // L4T Kernel Panic Storage (PSTORE).
#define PSTORE_ADDR 0xB0000000 #define PSTORE_ADDR 0xB0000000
#define PSTORE_SZ 0x200000 // 2MB. #define PSTORE_SZ SZ_2M
//#define DRAM_LIB_ADDR 0xE0000000 //#define DRAM_LIB_ADDR 0xE0000000
/* --- Chnldr: 252MB 0xC03C0000 - 0xCFFFFFFF --- */ //! Only used when chainloading. /* --- Chnldr: 252MB 0xC03C0000 - 0xCFFFFFFF --- */ //! Only used when chainloading.
// SDMMC DMA buffers 1 // SDMMC DMA buffers 1
#define SDMMC_UPPER_BUFFER 0xE5000000 #define SDMMC_UPPER_BUFFER 0xE5000000
#define SDMMC_UP_BUF_SZ 0x8000000 // 128MB. #define SDMMC_UP_BUF_SZ SZ_128M
// Nyx buffers. // Nyx buffers.
#define NYX_STORAGE_ADDR 0xED000000 #define NYX_STORAGE_ADDR 0xED000000
#define NYX_RES_ADDR 0xEE000000 #define NYX_RES_ADDR 0xEE000000
#define NYX_RES_SZ 0x1000000 // 16MB. #define NYX_RES_SZ SZ_16M
// SDMMC DMA buffers 2 // SDMMC DMA buffers 2
#define SDXC_BUF_ALIGNED 0xEF000000 #define SDXC_BUF_ALIGNED 0xEF000000
#define MIXD_BUF_ALIGNED 0xF0000000 #define MIXD_BUF_ALIGNED 0xF0000000
#define TITLEKEY_BUF_ADR MIXD_BUF_ALIGNED #define TITLEKEY_BUF_ADR MIXD_BUF_ALIGNED
#define EMMC_BUF_ALIGNED MIXD_BUF_ALIGNED #define EMMC_BUF_ALIGNED MIXD_BUF_ALIGNED
#define SDMMC_DMA_BUF_SZ 0x1000000 // 16MB (4MB currently used). #define SDMMC_DMA_BUF_SZ SZ_16M // 4MB currently used.
// Nyx LvGL buffers. // Nyx LvGL buffers.
#define NYX_LV_VDB_ADR 0xF1000000 #define NYX_LV_VDB_ADR 0xF1000000
@@ -106,7 +112,7 @@
#define USB_EP_CONTROL_BUF_ADDR 0xFEF80000 #define USB_EP_CONTROL_BUF_ADDR 0xFEF80000
#define USB_EP_BULK_IN_BUF_ADDR 0xFF000000 #define USB_EP_BULK_IN_BUF_ADDR 0xFF000000
#define USB_EP_BULK_OUT_BUF_ADDR 0xFF800000 #define USB_EP_BULK_OUT_BUF_ADDR 0xFF800000
#define USB_EP_BULK_OUT_MAX_XFER 0x800000 #define USB_EP_BULK_OUT_MAX_XFER SZ_8M
// #define EXT_PAYLOAD_ADDR 0xC0000000 // #define EXT_PAYLOAD_ADDR 0xC0000000
// #define RCM_PAYLOAD_ADDR (EXT_PAYLOAD_ADDR + ALIGN(PATCHED_RELOC_SZ, 0x10)) // #define RCM_PAYLOAD_ADDR (EXT_PAYLOAD_ADDR + ALIGN(PATCHED_RELOC_SZ, 0x10))

View File

@@ -21,10 +21,13 @@
#include <stddef.h> #include <stddef.h>
#include <mem/heap.h> #include <mem/heap.h>
#define IANOS_EXT0 0x304E4149
// Module Callback // Module Callback
typedef void (*cbMainModule_t)(const char *s); typedef void (*cbMainModule_t)(const char *s);
typedef void (*memcpy_t)(void *, void *, size_t); typedef void (*memcpy_t)(void *, void *, size_t);
typedef void (*memset_t)(void *, int, size_t); typedef void (*memset_t)(void *, int, size_t);
typedef int (*reg_voltage_set_t)(u32, u32);
typedef struct _bdkParams_t typedef struct _bdkParams_t
{ {
@@ -33,6 +36,8 @@ typedef struct _bdkParams_t
heap_t *sharedHeap; heap_t *sharedHeap;
memcpy_t memcpy; memcpy_t memcpy;
memset_t memset; memset_t memset;
u32 extension_magic;
reg_voltage_set_t reg_voltage_set;
} *bdkParams_t; } *bdkParams_t;
// Module Entrypoint // Module Entrypoint

View File

@@ -75,7 +75,7 @@ typedef struct _max77620_regulator_t
static const max77620_regulator_t _pmic_regulators[] = { static const max77620_regulator_t _pmic_regulators[] = {
{ "sd0", 12500, 600000, 625000, 1400000, REGULATOR_SD, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, MAX77620_SD0_VOLT_MASK, {{ MAX77620_REG_FPS_SD0, 1, 7, 1 }} }, { "sd0", 12500, 600000, 625000, 1400000, REGULATOR_SD, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, MAX77620_SD0_VOLT_MASK, {{ MAX77620_REG_FPS_SD0, 1, 7, 1 }} },
{ "sd1", 12500, 600000, 1125000, 1125000, REGULATOR_SD, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, MAX77620_SD1_VOLT_MASK, {{ MAX77620_REG_FPS_SD1, 0, 1, 5 }} }, { "sd1", 12500, 600000, 1125000, 1250000, REGULATOR_SD, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, MAX77620_SD1_VOLT_MASK, {{ MAX77620_REG_FPS_SD1, 0, 1, 5 }} },
{ "sd2", 12500, 600000, 1325000, 1350000, REGULATOR_SD, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD2, 1, 5, 2 }} }, { "sd2", 12500, 600000, 1325000, 1350000, REGULATOR_SD, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD2, 1, 5, 2 }} },
{ "sd3", 12500, 600000, 1800000, 1800000, REGULATOR_SD, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD3, 0, 3, 3 }} }, { "sd3", 12500, 600000, 1800000, 1800000, REGULATOR_SD, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD3, 0, 3, 3 }} },
{ "ldo0", 25000, 800000, 1200000, 1200000, REGULATOR_LDO, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO0, 3, 7, 0 }} }, { "ldo0", 25000, 800000, 1200000, 1200000, REGULATOR_LDO, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO0, 3, 7, 0 }} },
@@ -328,6 +328,7 @@ void max77620_config_default()
_max7762x_set_reg(MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, MAX77620_SD_CNF2_ROVS_EN_SD0); _max7762x_set_reg(MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, MAX77620_SD_CNF2_ROVS_EN_SD0);
} }
// Stock HOS: disabled.
void max77620_low_battery_monitor_config(bool enable) void max77620_low_battery_monitor_config(bool enable)
{ {
_max7762x_set_reg(MAX77620_I2C_ADDR, MAX77620_REG_CNFGGLBL1, _max7762x_set_reg(MAX77620_I2C_ADDR, MAX77620_REG_CNFGGLBL1,

View File

@@ -32,11 +32,11 @@
* ldo1 | XUSB, PCIE | 25000 | 800000 | 1050000 | 1050000 | 1.05V (pcv) * ldo1 | XUSB, PCIE | 25000 | 800000 | 1050000 | 1050000 | 1.05V (pcv)
* ldo2 | SDMMC1 | 50000 | 800000 | 1800000 | 3300000 | * ldo2 | SDMMC1 | 50000 | 800000 | 1800000 | 3300000 |
* ldo3 | GC ASIC | 50000 | 800000 | 3100000 | 3100000 | 3.1V (pcv) * ldo3 | GC ASIC | 50000 | 800000 | 3100000 | 3100000 | 3.1V (pcv)
* ldo4 | RTC | 12500 | 800000 | 850000 | 850000 | * ldo4 | RTC | 12500 | 800000 | 850000 | 850000 | 0.85V (AO, pcv)
* ldo5 | GC Card | 50000 | 800000 | 1800000 | 1800000 | 1.8V (pcv) * ldo5 | GC Card | 50000 | 800000 | 1800000 | 1800000 | 1.8V (pcv)
* ldo6 | Touch, ALS | 50000 | 800000 | 2900000 | 2900000 | 2.9V * ldo6 | Touch, ALS | 50000 | 800000 | 2900000 | 2900000 | 2.9V (pcv)
* ldo7 | XUSB | 50000 | 800000 | 1050000 | 1050000 | * ldo7 | XUSB | 50000 | 800000 | 1050000 | 1050000 | 1.05V (pcv)
* ldo8 | XUSB, DC | 50000 | 800000 | 1050000 | 1050000 | * ldo8 | XUSB, DP, MCU | 50000 | 800000 | 1050000 | 2800000 | 1.05V/2.8V (pcv)
*/ */
/* /*
@@ -135,10 +135,10 @@
#define MAX77621_CTRL_HOS_CFG 0 #define MAX77621_CTRL_HOS_CFG 0
#define MAX77621_CTRL_POR_CFG 1 #define MAX77621_CTRL_POR_CFG 1
int max77620_regulator_get_status(u32 id); int max77620_regulator_get_status(u32 id);
int max77620_regulator_config_fps(u32 id); int max77620_regulator_config_fps(u32 id);
int max7762x_regulator_set_voltage(u32 id, u32 mv); int max7762x_regulator_set_voltage(u32 id, u32 mv);
int max7762x_regulator_enable(u32 id, bool enable); int max7762x_regulator_enable(u32 id, bool enable);
void max77620_config_gpio(u32 id, bool enable); void max77620_config_gpio(u32 id, bool enable);
void max77620_config_default(); void max77620_config_default();
void max77620_low_battery_monitor_config(bool enable); void max77620_low_battery_monitor_config(bool enable);

View File

@@ -1,5 +1,5 @@
/* /*
* 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,
@@ -14,37 +14,52 @@
* 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 <soc/fuse.h>
#include <soc/gpio.h> #include <soc/gpio.h>
#include <soc/hw_init.h>
#include <soc/pinmux.h> #include <soc/pinmux.h>
#include <soc/pmc.h> #include <soc/pmc.h>
#include <soc/t210.h> #include <soc/t210.h>
#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. // Only Icosa and Iowa have USB 5V VBUS rails. Skip on Hoag/Aula.
PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN0) = PINMUX_LPDR | 1; u32 hw_type = fuse_read_hw_type();
gpio_config(GPIO_PORT_CC, GPIO_PIN_4, GPIO_MODE_GPIO); if (hw_type == FUSE_NX_HW_TYPE_ICOSA ||
gpio_output_enable(GPIO_PORT_CC, GPIO_PIN_4, GPIO_OUTPUT_ENABLE); hw_type == FUSE_NX_HW_TYPE_IOWA)
gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_HIGH); {
// Fan and Rail power from USB 5V VBUS.
PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN0) = PINMUX_LPDR | 1;
gpio_config(GPIO_PORT_CC, GPIO_PIN_4, GPIO_MODE_GPIO);
gpio_output_enable(GPIO_PORT_CC, GPIO_PIN_4, GPIO_OUTPUT_ENABLE);
gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW);
}
// Make sure GPIO power is enabled. // Enable GPIO AO IO rail for T210.
PMC(APBDEV_PMC_NO_IOPOWER) &= ~PMC_NO_IOPOWER_GPIO_IO_EN; if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210)
// Override power detect for GPIO AO IO rails. {
PMC(APBDEV_PMC_PWR_DET_VAL) &= ~PMC_PWR_DET_GPIO_IO_EN; // Make sure GPIO power is enabled.
PMC(APBDEV_PMC_NO_IOPOWER) &= ~PMC_NO_IOPOWER_GPIO_IO_EN;
(void)PMC(APBDEV_PMC_NO_IOPOWER); // Commit write.
// Override power detect for GPIO AO IO rails.
PMC(APBDEV_PMC_PWR_DET_VAL) &= ~PMC_PWR_DET_GPIO_IO_EN;
(void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write.
}
usb_src = false;
} }
reg_5v_dev |= dev; reg_5v_dev |= dev;
} }
@@ -55,21 +70,32 @@ 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. // Only Icosa and Iowa have USB 5V VBUS rails. Skip on Hoag/Aula.
gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW); u32 hw_type = fuse_read_hw_type();
gpio_output_enable(GPIO_PORT_CC, GPIO_PIN_4, GPIO_OUTPUT_DISABLE); if (hw_type == FUSE_NX_HW_TYPE_ICOSA ||
gpio_config(GPIO_PORT_CC, GPIO_PIN_4, GPIO_MODE_SPIO); hw_type == FUSE_NX_HW_TYPE_IOWA)
PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN0) = PINMUX_IO_HV | PINMUX_LPDR | PINMUX_PARKED | PINMUX_INPUT_ENABLE; {
// Rail power from USB 5V VBUS.
gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW);
gpio_output_enable(GPIO_PORT_CC, GPIO_PIN_4, GPIO_OUTPUT_DISABLE);
gpio_config(GPIO_PORT_CC, GPIO_PIN_4, GPIO_MODE_SPIO);
PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN0) = PINMUX_IO_HV | PINMUX_LPDR | PINMUX_PARKED | PINMUX_INPUT_ENABLE;
usb_src = false;
}
// GPIO AO IO rails. // GPIO AO IO rails.
PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_GPIO_IO_EN; if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210)
{
PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_GPIO_IO_EN;
(void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write.
}
} }
} }
@@ -78,10 +104,22 @@ 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) // Only for Icosa/Iowa. Skip on Hoag/Aula.
gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_HIGH); u32 hw_type = fuse_read_hw_type();
else if (!enable && batt_src) if (hw_type != FUSE_NX_HW_TYPE_ICOSA &&
gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_LOW); hw_type != FUSE_NX_HW_TYPE_IOWA)
return;
if (enable && !usb_src)
{
gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_HIGH);
usb_src = true;
}
else if (!enable && usb_src)
{
gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW);
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

@@ -1,8 +1,8 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer * Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2018 Atmosphère-NX * Copyright (c) 2018 Atmosphère-NX
* Copyright (c) 2019-2020 shchmue * Copyright (c) 2019-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,
@@ -35,8 +35,8 @@ typedef struct _se_ll_t
vu32 size; vu32 size;
} se_ll_t; } se_ll_t;
static u32 _se_rsa_mod_sizes[TEGRA_SE_RSA_KEYSLOT_COUNT]; static u32 _se_rsa_mod_sizes[SE_RSA_KEYSLOT_COUNT];
static u32 _se_rsa_exp_sizes[TEGRA_SE_RSA_KEYSLOT_COUNT]; static u32 _se_rsa_exp_sizes[SE_RSA_KEYSLOT_COUNT];
static void _gf256_mul_x(void *block) static void _gf256_mul_x(void *block)
{ {
@@ -79,17 +79,17 @@ static void _se_ll_init(se_ll_t *ll, u32 addr, u32 size)
static void _se_ll_set(se_ll_t *dst, se_ll_t *src) static void _se_ll_set(se_ll_t *dst, se_ll_t *src)
{ {
SE(SE_IN_LL_ADDR_REG_OFFSET) = (u32)src; SE(SE_IN_LL_ADDR_REG) = (u32)src;
SE(SE_OUT_LL_ADDR_REG_OFFSET) = (u32)dst; SE(SE_OUT_LL_ADDR_REG) = (u32)dst;
} }
static int _se_wait() static int _se_wait()
{ {
while (!(SE(SE_INT_STATUS_REG_OFFSET) & SE_INT_OP_DONE(INT_SET))) while (!(SE(SE_INT_STATUS_REG) & SE_INT_OP_DONE))
; ;
if (SE(SE_INT_STATUS_REG_OFFSET) & SE_INT_ERROR(INT_SET) || if (SE(SE_INT_STATUS_REG) & SE_INT_ERR_STAT ||
SE(SE_STATUS_0) & SE_STATUS_0_STATE_WAIT_IN || (SE(SE_STATUS_REG) & SE_STATUS_STATE_MASK) != SE_STATUS_STATE_IDLE ||
SE(SE_ERR_STATUS_0) != SE_ERR_STATUS_0_SE_NS_ACCESS_CLEAR) SE(SE_ERR_STATUS_REG) != 0)
return 0; return 0;
return 1; return 1;
} }
@@ -114,12 +114,12 @@ static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src
_se_ll_set(ll_dst, ll_src); _se_ll_set(ll_dst, ll_src);
SE(SE_ERR_STATUS_0) = SE(SE_ERR_STATUS_0); SE(SE_ERR_STATUS_REG) = SE(SE_ERR_STATUS_REG);
SE(SE_INT_STATUS_REG_OFFSET) = SE(SE_INT_STATUS_REG_OFFSET); SE(SE_INT_STATUS_REG) = SE(SE_INT_STATUS_REG);
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
SE(SE_OPERATION_REG_OFFSET) = SE_OPERATION(op); SE(SE_OPERATION_REG) = op;
if (is_oneshot) if (is_oneshot)
{ {
@@ -168,13 +168,13 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr
if (!src || !dst) if (!src || !dst)
return 0; return 0;
u8 *block = (u8 *)malloc(0x10); u8 *block = (u8 *)malloc(SE_AES_BLOCK_SIZE);
memset(block, 0, 0x10); memset(block, 0, SE_AES_BLOCK_SIZE);
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
memcpy(block, src, src_size); memcpy(block, src, src_size);
int res = _se_execute_oneshot(op, block, 0x10, block, 0x10); int res = _se_execute_oneshot(op, block, SE_AES_BLOCK_SIZE, block, SE_AES_BLOCK_SIZE);
memcpy(dst, block, dst_size); memcpy(dst, block, dst_size);
free(block); free(block);
@@ -183,21 +183,21 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr
static void _se_aes_ctr_set(void *ctr) static void _se_aes_ctr_set(void *ctr)
{ {
u32 data[TEGRA_SE_AES_BLOCK_SIZE / 4]; u32 data[SE_AES_IV_SIZE / 4];
memcpy(data, ctr, TEGRA_SE_AES_BLOCK_SIZE); memcpy(data, ctr, SE_AES_IV_SIZE);
for (u32 i = 0; i < (TEGRA_SE_AES_BLOCK_SIZE / 4); i++) for (u32 i = 0; i < SE_CRYPTO_LINEAR_CTR_REG_COUNT; i++)
SE(SE_CRYPTO_CTR_REG_OFFSET + (4 * i)) = data[i]; SE(SE_CRYPTO_LINEAR_CTR_REG + (4 * i)) = data[i];
} }
void se_rsa_acc_ctrl(u32 rs, u32 flags) void se_rsa_acc_ctrl(u32 rs, u32 flags)
{ {
if (flags & SE_RSA_KEY_TBL_DIS_KEY_ALL_FLAG) if (flags & SE_RSA_KEY_TBL_DIS_KEY_ACCESS_FLAG)
SE(SE_RSA_KEYTABLE_ACCESS_REG_OFFSET + 4 * rs) = SE(SE_RSA_KEYTABLE_ACCESS_REG + 4 * rs) =
((flags >> SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG_SHIFT) & SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG) | (((flags >> 4) & SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG) |(flags & SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG)) ^
((flags & SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG) ^ SE_RSA_KEY_TBL_DIS_KEY_ALL_COMMON_FLAG); SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_USE_FLAG;
if (flags & SE_RSA_KEY_TBL_DIS_KEY_LOCK_FLAG) if (flags & SE_RSA_KEY_LOCK_FLAG)
SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) &= ~BIT(rs); SE(SE_RSA_SECURITY_PERKEY_REG) &= ~BIT(rs);
} }
// se_rsa_key_set() was derived from Atmosphère's set_rsa_keyslot // se_rsa_key_set() was derived from Atmosphère's set_rsa_keyslot
@@ -206,15 +206,15 @@ void se_rsa_key_set(u32 ks, const void *mod, u32 mod_size, const void *exp, u32
u32 *data = (u32 *)mod; u32 *data = (u32 *)mod;
for (u32 i = 0; i < mod_size / 4; i++) for (u32 i = 0; i < mod_size / 4; i++)
{ {
SE(SE_RSA_KEYTABLE_ADDR) = RSA_KEY_NUM(ks) | RSA_KEY_TYPE(RSA_KEY_TYPE_MOD) | i; SE(SE_RSA_KEYTABLE_ADDR_REG) = RSA_KEY_NUM(ks) | SE_RSA_KEYTABLE_TYPE(RSA_KEY_TYPE_MOD) | i;
SE(SE_RSA_KEYTABLE_DATA) = byte_swap_32(data[mod_size / 4 - i - 1]); SE(SE_RSA_KEYTABLE_DATA_REG) = byte_swap_32(data[mod_size / 4 - i - 1]);
} }
data = (u32 *)exp; data = (u32 *)exp;
for (u32 i = 0; i < exp_size / 4; i++) for (u32 i = 0; i < exp_size / 4; i++)
{ {
SE(SE_RSA_KEYTABLE_ADDR) = RSA_KEY_NUM(ks) | RSA_KEY_TYPE(RSA_KEY_TYPE_EXP) | i; SE(SE_RSA_KEYTABLE_ADDR_REG) = RSA_KEY_NUM(ks) | SE_RSA_KEYTABLE_TYPE(RSA_KEY_TYPE_EXP) | i;
SE(SE_RSA_KEYTABLE_DATA) = byte_swap_32(data[exp_size / 4 - i - 1]); SE(SE_RSA_KEYTABLE_DATA_REG) = byte_swap_32(data[exp_size / 4 - i - 1]);
} }
_se_rsa_mod_sizes[ks] = mod_size; _se_rsa_mod_sizes[ks] = mod_size;
@@ -224,15 +224,15 @@ void se_rsa_key_set(u32 ks, const void *mod, u32 mod_size, const void *exp, u32
// se_rsa_key_clear() was derived from Atmosphère's clear_rsa_keyslot // se_rsa_key_clear() was derived from Atmosphère's clear_rsa_keyslot
void se_rsa_key_clear(u32 ks) void se_rsa_key_clear(u32 ks)
{ {
for (u32 i = 0; i < TEGRA_SE_RSA2048_DIGEST_SIZE / 4; i++) for (u32 i = 0; i < SE_RSA2048_DIGEST_SIZE / 4; i++)
{ {
SE(SE_RSA_KEYTABLE_ADDR) = RSA_KEY_NUM(ks) | RSA_KEY_TYPE(RSA_KEY_TYPE_MOD) | i; SE(SE_RSA_KEYTABLE_ADDR_REG) = RSA_KEY_NUM(ks) | SE_RSA_KEYTABLE_TYPE(RSA_KEY_TYPE_MOD) | i;
SE(SE_RSA_KEYTABLE_DATA) = 0; SE(SE_RSA_KEYTABLE_DATA_REG) = 0;
} }
for (u32 i = 0; i < TEGRA_SE_RSA2048_DIGEST_SIZE / 4; i++) for (u32 i = 0; i < SE_RSA2048_DIGEST_SIZE / 4; i++)
{ {
SE(SE_RSA_KEYTABLE_ADDR) = RSA_KEY_NUM(ks) | RSA_KEY_TYPE(RSA_KEY_TYPE_EXP) | i; SE(SE_RSA_KEYTABLE_ADDR_REG) = RSA_KEY_NUM(ks) | SE_RSA_KEYTABLE_TYPE(RSA_KEY_TYPE_EXP) | i;
SE(SE_RSA_KEYTABLE_DATA) = 0; SE(SE_RSA_KEYTABLE_DATA_REG) = 0;
} }
} }
@@ -240,22 +240,22 @@ void se_rsa_key_clear(u32 ks)
int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size) int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size)
{ {
int res; int res;
u8 stack_buf[TEGRA_SE_RSA2048_DIGEST_SIZE]; u8 stack_buf[SE_RSA2048_DIGEST_SIZE];
for (u32 i = 0; i < src_size; i++) for (u32 i = 0; i < src_size; i++)
stack_buf[i] = *((u8 *)src + src_size - i - 1); stack_buf[i] = *((u8 *)src + src_size - i - 1);
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_RSA) | SE_CONFIG_DST(DST_RSAREG); SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_RSA) | SE_CONFIG_DST(DST_RSAREG);
SE(SE_RSA_CONFIG) = RSA_KEY_SLOT(ks); SE(SE_RSA_CONFIG) = RSA_KEY_SLOT(ks);
SE(SE_RSA_KEY_SIZE_REG_OFFSET) = (_se_rsa_mod_sizes[ks] >> 6) - 1; SE(SE_RSA_KEY_SIZE_REG) = (_se_rsa_mod_sizes[ks] >> 6) - 1;
SE(SE_RSA_EXP_SIZE_REG_OFFSET) = _se_rsa_exp_sizes[ks] >> 2; SE(SE_RSA_EXP_SIZE_REG) = _se_rsa_exp_sizes[ks] >> 2;
res = _se_execute_oneshot(OP_START, NULL, 0, stack_buf, src_size); res = _se_execute_oneshot(SE_OP_START, NULL, 0, stack_buf, src_size);
// 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 + (i << 2))); dst32[dst_size / 4 - i - 1] = byte_swap_32(SE(SE_RSA_OUTPUT_REG + (i << 2)));
return res; return res;
} }
@@ -263,54 +263,54 @@ int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_siz
void se_key_acc_ctrl(u32 ks, u32 flags) void se_key_acc_ctrl(u32 ks, u32 flags)
{ {
if (flags & SE_KEY_TBL_DIS_KEY_ACCESS_FLAG) if (flags & SE_KEY_TBL_DIS_KEY_ACCESS_FLAG)
SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 4 * ks) = ~flags; SE(SE_CRYPTO_KEYTABLE_ACCESS_REG + 4 * ks) = ~flags;
if (flags & SE_KEY_TBL_DIS_KEY_LOCK_FLAG) if (flags & SE_KEY_LOCK_FLAG)
SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) &= ~BIT(ks); SE(SE_CRYPTO_SECURITY_PERKEY_REG) &= ~BIT(ks);
} }
u32 se_key_acc_ctrl_get(u32 ks) u32 se_key_acc_ctrl_get(u32 ks)
{ {
return SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 4 * ks); return SE(SE_CRYPTO_KEYTABLE_ACCESS_REG + 4 * ks);
} }
void se_aes_key_set(u32 ks, const void *key, u32 size) void se_aes_key_set(u32 ks, const void *key, u32 size)
{ {
u32 data[TEGRA_SE_AES_MAX_KEY_SIZE / 4]; u32 data[SE_AES_MAX_KEY_SIZE / 4];
memcpy(data, key, size); memcpy(data, key, size);
for (u32 i = 0; i < (size / 4); i++) for (u32 i = 0; i < (size / 4); i++)
{ {
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i; SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_PKT(i); // QUAD is automatically set by PKT.
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data[i]; SE(SE_CRYPTO_KEYTABLE_DATA_REG) = data[i];
} }
} }
void se_aes_key_partial_set(u32 ks, u32 index, u32 data) void se_aes_key_partial_set(u32 ks, u32 index, u32 data)
{ {
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | index; SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | index;
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data; SE(SE_CRYPTO_KEYTABLE_DATA_REG) = data;
} }
void se_aes_iv_set(u32 ks, const void *iv) void se_aes_iv_set(u32 ks, const void *iv)
{ {
u32 data[TEGRA_SE_AES_BLOCK_SIZE / 4]; u32 data[SE_AES_IV_SIZE / 4];
memcpy(data, iv, TEGRA_SE_AES_BLOCK_SIZE); memcpy(data, iv, SE_AES_IV_SIZE);
for (u32 i = 0; i < (TEGRA_SE_AES_BLOCK_SIZE / 4); i++) for (u32 i = 0; i < (SE_AES_IV_SIZE / 4); i++)
{ {
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(QUAD_ORG_IV) | i; SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(ORIGINAL_IV) | SE_KEYTABLE_PKT(i);
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data[i]; SE(SE_CRYPTO_KEYTABLE_DATA_REG) = data[i];
} }
} }
void se_aes_key_get(u32 ks, void *key, u32 size) void se_aes_key_get(u32 ks, void *key, u32 size)
{ {
u32 data[TEGRA_SE_AES_MAX_KEY_SIZE / 4]; u32 data[SE_AES_MAX_KEY_SIZE / 4];
for (u32 i = 0; i < (size / 4); i++) for (u32 i = 0; i < (size / 4); i++)
{ {
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i; SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_PKT(i); // QUAD is automatically set by PKT.
data[i] = SE(SE_KEYTABLE_DATA0_REG_OFFSET); data[i] = SE(SE_CRYPTO_KEYTABLE_DATA_REG);
} }
memcpy(key, data, size); memcpy(key, data, size);
@@ -318,77 +318,77 @@ void se_aes_key_get(u32 ks, void *key, u32 size)
void se_aes_key_clear(u32 ks) void se_aes_key_clear(u32 ks)
{ {
for (u32 i = 0; i < (TEGRA_SE_AES_MAX_KEY_SIZE / 4); i++) for (u32 i = 0; i < (SE_AES_MAX_KEY_SIZE / 4); i++)
{ {
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i; SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_PKT(i); // QUAD is automatically set by PKT.
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = 0; SE(SE_CRYPTO_KEYTABLE_DATA_REG) = 0;
} }
} }
void se_aes_iv_clear(u32 ks) void se_aes_iv_clear(u32 ks)
{ {
for (u32 i = 0; i < (TEGRA_SE_AES_BLOCK_SIZE / 4); i++) for (u32 i = 0; i < (SE_AES_IV_SIZE / 4); i++)
{ {
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(QUAD_ORG_IV) | i; SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(ORIGINAL_IV) | SE_KEYTABLE_PKT(i);
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = 0; SE(SE_CRYPTO_KEYTABLE_DATA_REG) = 0;
} }
} }
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input) int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input)
{ {
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_KEYTAB); SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_KEYTABLE);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT); SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst); SE(SE_CRYPTO_KEYTABLE_DST_REG) = SE_KEYTABLE_DST_KEY_INDEX(ks_dst) | SE_KEYTABLE_DST_WORD_QUAD(KEYS_0_3);
return _se_execute_oneshot(OP_START, NULL, 0, input, 0x10); return _se_execute_oneshot(SE_OP_START, NULL, 0, input, SE_KEY_128_SIZE);
} }
int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size) int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size)
{ {
if (enc) if (enc)
{ {
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT); SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT);
} }
else else
{ {
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY); SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT); SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
} }
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1; SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1;
return _se_execute_oneshot(OP_START, dst, dst_size, src, src_size); return _se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size);
} }
int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size) int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size)
{ {
if (enc) if (enc)
{ {
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) | SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) |
SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_XOR_POS(XOR_TOP); SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_XOR_POS(XOR_TOP);
} }
else else
{ {
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY); SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVAHB) | SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVMEM) |
SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM); SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM);
} }
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1; SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1;
return _se_execute_oneshot(OP_START, dst, dst_size, src, src_size); return _se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size);
} }
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src) int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src)
{ {
return se_aes_crypt_ecb(ks, enc, dst, 0x10, src, 0x10); return se_aes_crypt_ecb(ks, enc, dst, SE_AES_BLOCK_SIZE, src, SE_AES_BLOCK_SIZE);
} }
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr) int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr)
{ {
SE(SE_SPARE_0_REG_OFFSET) = 1; SE(SE_SPARE_REG) = SE_ECO(SE_ERRATA_FIX_ENABLE);
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) |
SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_LNR_CTR) | SE_CRYPTO_CTR_VAL(1); SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_LNR_CTR) | SE_CRYPTO_CTR_CNTN(1);
_se_aes_ctr_set(ctr); _se_aes_ctr_set(ctr);
u32 src_size_aligned = src_size & 0xFFFFFFF0; u32 src_size_aligned = src_size & 0xFFFFFFF0;
@@ -396,13 +396,13 @@ int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_s
if (src_size_aligned) if (src_size_aligned)
{ {
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1; SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1;
if (!_se_execute_oneshot(OP_START, dst, dst_size, src, src_size_aligned)) if (!_se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size_aligned))
return 0; return 0;
} }
if (src_size - src_size_aligned && src_size_aligned < dst_size) if (src_size - src_size_aligned && src_size_aligned < dst_size)
return _se_execute_one_block(OP_START, dst + src_size_aligned, return _se_execute_one_block(SE_OP_START, dst + src_size_aligned,
MIN(src_size_delta, dst_size - src_size_aligned), MIN(src_size_delta, dst_size - src_size_aligned),
src + src_size_aligned, src_size_delta); src + src_size_aligned, src_size_delta);
@@ -419,15 +419,15 @@ int se_initialize_rng()
u8 *output_buf = (u8 *)malloc(0x10); u8 *output_buf = (u8 *)malloc(0x10);
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY); SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM); SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_MODE(RNG_MODE_FORCE_INSTANTION) | SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY); SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_MODE(MODE_FORCE_INSTANTION) | SE_RNG_CONFIG_SRC(SRC_ENTROPY);
SE(SE_RNG_RESEED_INTERVAL_REG_OFFSET) = 70001; SE(SE_RNG_RESEED_INTERVAL_REG) = 70001;
SE(SE_RNG_SRC_CONFIG_REG_OFFSET) = SE_RNG_SRC_CONFIG_ENT_SRC(RNG_SRC_RO_ENT_ENABLE) | SE(SE_RNG_SRC_CONFIG_REG) = SE_RNG_SRC_CONFIG_ENTR_SRC(RO_ENTR_ENABLE) |
SE_RNG_SRC_CONFIG_ENT_SRC_LOCK(RNG_SRC_RO_ENT_LOCK_ENABLE); SE_RNG_SRC_CONFIG_ENTR_SRC_LOCK(RO_ENTR_LOCK_ENABLE);
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; SE(SE_CRYPTO_BLOCK_COUNT_REG) = 0;
int res =_se_execute_oneshot(OP_START, output_buf, 0x10, NULL, 0); int res =_se_execute_oneshot(SE_OP_START, output_buf, 0x10, NULL, 0);
free(output_buf); free(output_buf);
if (res) if (res)
@@ -437,35 +437,35 @@ int se_initialize_rng()
int se_generate_random(void *dst, u32 size) int se_generate_random(void *dst, u32 size)
{ {
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY); SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM); SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_MODE(RNG_MODE_NORMAL) | SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY); SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_MODE(MODE_NORMAL) | SE_RNG_CONFIG_SRC(SRC_ENTROPY);
u32 num_blocks = size >> 4; u32 num_blocks = size >> 4;
u32 aligned_size = num_blocks << 4; u32 aligned_size = num_blocks << 4;
if (num_blocks) if (num_blocks)
{ {
SE(SE_BLOCK_COUNT_REG_OFFSET) = num_blocks - 1; SE(SE_CRYPTO_BLOCK_COUNT_REG) = num_blocks - 1;
if (!_se_execute_oneshot(OP_START, dst, aligned_size, NULL, 0)) if (!_se_execute_oneshot(SE_OP_START, dst, aligned_size, NULL, 0))
return 0; return 0;
} }
if (size > aligned_size) if (size > aligned_size)
return _se_execute_one_block(OP_START, dst + aligned_size, size - aligned_size, NULL, 0); return _se_execute_one_block(SE_OP_START, dst + aligned_size, size - aligned_size, NULL, 0);
return 1; return 1;
} }
int se_generate_random_key(u32 ks_dst, u32 ks_src) int se_generate_random_key(u32 ks_dst, u32 ks_src)
{ {
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY); SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) |
SE_CRYPTO_INPUT_SEL(INPUT_RANDOM); SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_MODE(RNG_MODE_NORMAL) | SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY); SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_MODE(MODE_NORMAL) | SE_RNG_CONFIG_SRC(SRC_ENTROPY);
SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst); SE(SE_CRYPTO_KEYTABLE_DST_REG) = SE_KEYTABLE_DST_KEY_INDEX(ks_dst);
if (!_se_execute_oneshot(OP_START, NULL, 0, NULL, 0)) if (!_se_execute_oneshot(SE_OP_START, NULL, 0, NULL, 0))
return 0; return 0;
SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst) | 1; SE(SE_CRYPTO_KEYTABLE_DST_REG) = SE_KEYTABLE_DST_KEY_INDEX(ks_dst) | 1;
if (!_se_execute_oneshot(OP_START, NULL, 0, NULL, 0)) if (!_se_execute_oneshot(SE_OP_START, NULL, 0, NULL, 0))
return 0; return 0;
return 1; return 1;
@@ -544,8 +544,8 @@ int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size)
if (src_size & 0xF) if (src_size & 0xF)
_gf256_mul_x(key); _gf256_mul_x(key);
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_HASHREG); SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_HASHREG);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_INPUT_SEL(INPUT_AHB) | SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_INPUT_SEL(INPUT_MEMORY) |
SE_CRYPTO_XOR_POS(XOR_TOP) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) | SE_CRYPTO_HASH(HASH_ENABLE) | SE_CRYPTO_XOR_POS(XOR_TOP) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) | SE_CRYPTO_HASH(HASH_ENABLE) |
SE_CRYPTO_CORE_SEL(CORE_ENCRYPT); SE_CRYPTO_CORE_SEL(CORE_ENCRYPT);
se_aes_iv_clear(ks); se_aes_iv_clear(ks);
@@ -553,10 +553,10 @@ int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size)
u32 num_blocks = (src_size + 0xf) >> 4; u32 num_blocks = (src_size + 0xf) >> 4;
if (num_blocks > 1) if (num_blocks > 1)
{ {
SE(SE_BLOCK_COUNT_REG_OFFSET) = num_blocks - 2; SE(SE_CRYPTO_BLOCK_COUNT_REG) = num_blocks - 2;
if (!_se_execute_oneshot(OP_START, NULL, 0, src, src_size)) if (!_se_execute_oneshot(SE_OP_START, NULL, 0, src, src_size))
goto out; goto out;
SE(SE_CRYPTO_REG_OFFSET) |= SE_CRYPTO_IV_SEL(IV_UPDATED); SE(SE_CRYPTO_CONFIG_REG) |= SE_CRYPTO_IV_SEL(IV_UPDATED);
} }
if (src_size & 0xf) if (src_size & 0xf)
@@ -572,12 +572,12 @@ int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size)
for (u32 i = 0; i < 0x10; i++) for (u32 i = 0; i < 0x10; i++)
last_block[i] ^= key[i]; last_block[i] ^= key[i];
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; SE(SE_CRYPTO_BLOCK_COUNT_REG) = 0;
res = _se_execute_oneshot(OP_START, NULL, 0, last_block, 0x10); res = _se_execute_oneshot(SE_OP_START, NULL, 0, last_block, 0x10);
u32 *dst32 = (u32 *)dst; u32 *dst32 = (u32 *)dst;
for (u32 i = 0; i < (dst_size >> 2); i++) for (u32 i = 0; i < (dst_size >> 2); i++)
dst32[i] = SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)); dst32[i] = SE(SE_HASH_RESULT_REG + (i << 2));
out:; out:;
free(key); free(key);
@@ -588,62 +588,62 @@ out:;
int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot) int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot)
{ {
int res; int res;
u32 hash32[TEGRA_SE_SHA_256_SIZE / 4]; u32 hash32[SE_SHA_256_SIZE / 4];
//! TODO: src_size must be 512 bit aligned if continuing and not last block for SHA256. //! TODO: src_size must be 512 bit aligned if continuing and not last block for SHA256.
if (src_size > 0xFFFFFF || !hash) // Max 16MB - 1 chunks and aligned x4 hash buffer. if (src_size > 0xFFFFFF || !hash) // Max 16MB - 1 chunks and aligned x4 hash buffer.
return 0; return 0;
// Setup config for SHA256. // Setup config for SHA256.
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_SHA256) | SE_CONFIG_ENC_ALG(ALG_SHA) | SE_CONFIG_DST(DST_HASHREG); SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_SHA256) | SE_CONFIG_ENC_ALG(ALG_SHA) | SE_CONFIG_DST(DST_HASHREG);
SE(SE_SHA_CONFIG_REG_OFFSET) = sha_cfg; SE(SE_SHA_CONFIG_REG) = sha_cfg;
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
// Set total size to current buffer size if empty. // Set total size to current buffer size if empty.
if (!total_size) if (!total_size)
total_size = src_size; total_size = src_size;
// Set total size: BITS(src_size), up to 2 EB. // Set total size: BITS(src_size), up to 2 EB.
SE(SE_SHA_MSG_LENGTH_0_REG_OFFSET) = (u32)(total_size << 3); SE(SE_SHA_MSG_LENGTH_0_REG) = (u32)(total_size << 3);
SE(SE_SHA_MSG_LENGTH_1_REG_OFFSET) = (u32)(total_size >> 29); SE(SE_SHA_MSG_LENGTH_1_REG) = (u32)(total_size >> 29);
SE(SE_SHA_MSG_LENGTH_2_REG_OFFSET) = 0; SE(SE_SHA_MSG_LENGTH_2_REG) = 0;
SE(SE_SHA_MSG_LENGTH_3_REG_OFFSET) = 0; SE(SE_SHA_MSG_LENGTH_3_REG) = 0;
// Set size left to hash. // Set size left to hash.
SE(SE_SHA_MSG_LEFT_0_REG_OFFSET) = (u32)(total_size << 3); SE(SE_SHA_MSG_LEFT_0_REG) = (u32)(total_size << 3);
SE(SE_SHA_MSG_LEFT_1_REG_OFFSET) = (u32)(total_size >> 29); SE(SE_SHA_MSG_LEFT_1_REG) = (u32)(total_size >> 29);
SE(SE_SHA_MSG_LEFT_2_REG_OFFSET) = 0; SE(SE_SHA_MSG_LEFT_2_REG) = 0;
SE(SE_SHA_MSG_LEFT_3_REG_OFFSET) = 0; SE(SE_SHA_MSG_LEFT_3_REG) = 0;
// If we hash in chunks, copy over the intermediate. // If we hash in chunks, copy over the intermediate.
if (sha_cfg == SHA_CONTINUE && msg_left) if (sha_cfg == SHA_CONTINUE && msg_left)
{ {
// Restore message left to process. // Restore message left to process.
SE(SE_SHA_MSG_LEFT_0_REG_OFFSET) = msg_left[0]; SE(SE_SHA_MSG_LEFT_0_REG) = msg_left[0];
SE(SE_SHA_MSG_LEFT_1_REG_OFFSET) = msg_left[1]; SE(SE_SHA_MSG_LEFT_1_REG) = msg_left[1];
// Restore hash reg. // Restore hash reg.
memcpy(hash32, hash, TEGRA_SE_SHA_256_SIZE); memcpy(hash32, hash, SE_SHA_256_SIZE);
for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++) for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++)
SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)) = byte_swap_32(hash32[i]); SE(SE_HASH_RESULT_REG + (i * 4)) = byte_swap_32(hash32[i]);
} }
// Trigger the operation. // Trigger the operation.
res = _se_execute(OP_START, NULL, 0, src, src_size, is_oneshot); res = _se_execute(SE_OP_START, NULL, 0, src, src_size, is_oneshot);
if (is_oneshot) if (is_oneshot)
{ {
// Backup message left. // Backup message left.
if (msg_left) if (msg_left)
{ {
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG_OFFSET); msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG);
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG_OFFSET); msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG);
} }
// Copy output hash. // Copy output hash.
for (u32 i = 0; i < (TEGRA_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_OFFSET + (i << 2))); hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG + (i * 4)));
memcpy(hash, hash32, TEGRA_SE_SHA_256_SIZE); memcpy(hash, hash32, SE_SHA_256_SIZE);
} }
return res; return res;
@@ -656,20 +656,20 @@ int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size)
int se_calc_sha256_finalize(void *hash, u32 *msg_left) int se_calc_sha256_finalize(void *hash, u32 *msg_left)
{ {
u32 hash32[TEGRA_SE_SHA_256_SIZE / 4]; u32 hash32[SE_SHA_256_SIZE / 4];
int res = _se_execute_finalize(); int res = _se_execute_finalize();
// Backup message left. // Backup message left.
if (msg_left) if (msg_left)
{ {
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG_OFFSET); msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG);
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG_OFFSET); msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG);
} }
// Copy output hash. // Copy output hash.
for (u32 i = 0; i < (TEGRA_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_OFFSET + (i << 2))); hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG + (i << 2)));
memcpy(hash, hash32, TEGRA_SE_SHA_256_SIZE); memcpy(hash, hash32, SE_SHA_256_SIZE);
return res; return res;
} }
@@ -793,43 +793,43 @@ void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize)
u8 *aligned_buf = (u8 *)ALIGN((u32)buf, 0x40); u8 *aligned_buf = (u8 *)ALIGN((u32)buf, 0x40);
// Set Secure Random Key. // Set Secure Random Key.
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_SRK); SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_SRK);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(0) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM); SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(0) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY) | SE_RNG_CONFIG_MODE(RNG_MODE_FORCE_RESEED); SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_SRC(SRC_ENTROPY) | SE_RNG_CONFIG_MODE(MODE_FORCE_RESEED);
SE(SE_CRYPTO_LAST_BLOCK) = 0; SE(SE_CRYPTO_LAST_BLOCK) = 0;
_se_execute_oneshot(OP_START, NULL, 0, NULL, 0); _se_execute_oneshot(SE_OP_START, NULL, 0, NULL, 0);
// Save AES keys. // Save AES keys.
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
for (u32 i = 0; i < TEGRA_SE_KEYSLOT_COUNT; i++) for (u32 i = 0; i < SE_AES_KEYSLOT_COUNT; i++)
{ {
SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(AES_KEYTABLE) | SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(AES_KEYTABLE) | SE_KEYTABLE_DST_KEY_INDEX(i) |
(i << SE_KEY_INDEX_SHIFT) | SE_CONTEXT_SAVE_WORD_QUAD(KEYS_0_3); SE_CONTEXT_AES_KEY_INDEX(0) | SE_CONTEXT_AES_WORD_QUAD(KEYS_0_3);
SE(SE_CRYPTO_LAST_BLOCK) = 0; SE(SE_CRYPTO_LAST_BLOCK) = 0;
_se_execute_oneshot(OP_CTX_SAVE, aligned_buf, 0x10, NULL, 0); _se_execute_oneshot(SE_OP_CTX_SAVE, aligned_buf, SE_AES_BLOCK_SIZE, NULL, 0);
memcpy(keys + i * keysize, aligned_buf, 0x10); memcpy(keys + i * keysize, aligned_buf, SE_AES_BLOCK_SIZE);
if (keysize > 0x10) if (keysize > SE_KEY_128_SIZE)
{ {
SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(AES_KEYTABLE) | SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(AES_KEYTABLE) | SE_KEYTABLE_DST_KEY_INDEX(i) |
(i << SE_KEY_INDEX_SHIFT) | SE_CONTEXT_SAVE_WORD_QUAD(KEYS_4_7); SE_CONTEXT_AES_KEY_INDEX(0) | SE_CONTEXT_AES_WORD_QUAD(KEYS_4_7);
SE(SE_CRYPTO_LAST_BLOCK) = 0; SE(SE_CRYPTO_LAST_BLOCK) = 0;
_se_execute_oneshot(OP_CTX_SAVE, aligned_buf, 0x10, NULL, 0); _se_execute_oneshot(SE_OP_CTX_SAVE, aligned_buf, SE_AES_BLOCK_SIZE, NULL, 0);
memcpy(keys + i * keysize + 0x10, aligned_buf, 0x10); memcpy(keys + i * keysize + SE_AES_BLOCK_SIZE, aligned_buf, SE_AES_BLOCK_SIZE);
} }
} }
// Save SRK to PMC secure scratches. // Save SRK to PMC secure scratches.
SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(SRK); SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(SRK);
SE(SE_CRYPTO_LAST_BLOCK) = 0; SE(SE_CRYPTO_LAST_BLOCK) = 0;
_se_execute_oneshot(OP_CTX_SAVE, NULL, 0, NULL, 0); _se_execute_oneshot(SE_OP_CTX_SAVE, NULL, 0, NULL, 0);
// End context save. // End context save.
SE(SE_CONFIG_REG_OFFSET) = 0; SE(SE_CONFIG_REG) = 0;
_se_execute_oneshot(OP_CTX_SAVE, NULL, 0, NULL, 0); _se_execute_oneshot(SE_OP_CTX_SAVE, NULL, 0, NULL, 0);
// Get SRK. // Get SRK.
u32 srk[4]; u32 srk[4];
@@ -840,7 +840,7 @@ 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, 0x10); se_aes_key_set(3, srk, SE_KEY_128_SIZE);
se_aes_crypt_cbc(3, 0, keys, TEGRA_SE_KEYSLOT_COUNT * keysize, keys, TEGRA_SE_KEYSLOT_COUNT * keysize); se_aes_crypt_cbc(3, 0, keys, SE_AES_KEYSLOT_COUNT * keysize, keys, SE_AES_KEYSLOT_COUNT * keysize);
se_aes_key_clear(3); se_aes_key_clear(3);
} }

View File

@@ -1,5 +1,7 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2019-2021 CTCaer
* Copyright (c) 2019-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,
@@ -25,6 +27,7 @@ void se_rsa_key_clear(u32 ks);
int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size); int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size);
void se_key_acc_ctrl(u32 ks, u32 flags); void se_key_acc_ctrl(u32 ks, u32 flags);
u32 se_key_acc_ctrl_get(u32 ks); u32 se_key_acc_ctrl_get(u32 ks);
void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize);
void se_aes_key_set(u32 ks, const void *key, u32 size); void se_aes_key_set(u32 ks, const void *key, u32 size);
void se_aes_iv_set(u32 ks, const void *iv); void se_aes_iv_set(u32 ks, const void *iv);
void se_aes_key_partial_set(u32 ks, u32 index, u32 data); void se_aes_key_partial_set(u32 ks, u32 index, u32 data);
@@ -35,10 +38,10 @@ int se_initialize_rng();
int se_generate_random(void *dst, u32 size); int se_generate_random(void *dst, u32 size);
int se_generate_random_key(u32 ks_dst, u32 ks_src); int se_generate_random_key(u32 ks_dst, u32 ks_src);
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input); int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input);
int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size);
int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size); int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size);
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src); int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src);
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr); int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr);
int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size);
int se_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, const void *src, u32 sec_size); int se_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, const void *src, u32 sec_size);
int se_aes_xts_crypt(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, const void *src, u32 sec_size, u32 num_secs); int se_aes_xts_crypt(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, const void *src, u32 sec_size, u32 num_secs);
int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size); int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size);
@@ -47,6 +50,5 @@ int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size);
int se_calc_sha256_finalize(void *hash, u32 *msg_left); int se_calc_sha256_finalize(void *hash, u32 *msg_left);
int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size); int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size);
u32 se_rsa_oaep_decode(void *dst, u32 dst_size, const void *label_digest, u32 label_digest_size, u8 *buf, u32 buf_size); u32 se_rsa_oaep_decode(void *dst, u32 dst_size, const void *label_digest, u32 label_digest_size, u8 *buf, u32 buf_size);
void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize);
#endif #endif

View File

@@ -1,400 +1,323 @@
/* /*
* Driver for Tegra Security Engine * Copyright (c) 2018 naehrwert
* * Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2011-2013, NVIDIA Corporation. All Rights Reserved. *
* * 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 * under the terms and conditions of the GNU General Public License,
* it under the terms of the GNU General Public License as published by * version 2, as published by the Free Software Foundation.
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. * This program is distributed in the hope it will be useful, but WITHOUT
* * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* This program is distributed in the hope that it will be useful, but WITHOUT * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * more details.
* 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/>.
* You should have received a copy of the GNU General Public License along */
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef _CRYPTO_TEGRA_SE_H #ifndef _SE_T210_H
#define _CRYPTO_TEGRA_SE_H #define _SE_T210_H
#include <utils/types.h> #include <utils/types.h>
#define TEGRA_SE_CRA_PRIORITY 300 #define SE_CRYPTO_QUEUE_LENGTH 50
#define TEGRA_SE_COMPOSITE_PRIORITY 400 #define SE_MAX_SRC_SG_COUNT 50
#define TEGRA_SE_CRYPTO_QUEUE_LENGTH 50 #define SE_MAX_DST_SG_COUNT 50
#define SE_MAX_SRC_SG_COUNT 50
#define SE_MAX_DST_SG_COUNT 50
#define TEGRA_SE_KEYSLOT_COUNT 16 #define SE_AES_KEYSLOT_COUNT 16
#define SE_MAX_LAST_BLOCK_SIZE 0xFFFFF #define SE_RSA_KEYSLOT_COUNT 2
#define SE_MAX_LAST_BLOCK_SIZE 0xFFFFF
#define SE_AES_BLOCK_SIZE 16
#define SE_AES_IV_SIZE 16
#define SE_AES_MIN_KEY_SIZE 16
#define SE_AES_MAX_KEY_SIZE 32
#define SE_KEY_128_SIZE 16
#define SE_KEY_192_SIZE 24
#define SE_KEY_256_SIZE 32
#define SE_SHA_192_SIZE 24
#define SE_SHA_256_SIZE 32
#define SE_SHA_384_SIZE 48
#define SE_SHA_512_SIZE 64
#define SE_RNG_IV_SIZE 16
#define SE_RNG_DT_SIZE 16
#define SE_RNG_KEY_SIZE 16
#define SE_RNG_SEED_SIZE (SE_RNG_IV_SIZE + SE_RNG_KEY_SIZE + SE_RNG_DT_SIZE)
#define SE_AES_CMAC_DIGEST_SIZE 16
#define SE_RSA512_DIGEST_SIZE 64
#define SE_RSA1024_DIGEST_SIZE 128
#define SE_RSA1536_DIGEST_SIZE 192
#define SE_RSA2048_DIGEST_SIZE 256
/* SE register definitions */ /* SE register definitions */
#define SE_SECURITY_0 0x000 #define SE_SE_SECURITY_REG 0x000
#define SE_KEY_SCHED_READ_SHIFT 3 #define SE_HARD_SETTING BIT(0)
#define SE_ENG_DIS BIT(1)
#define SE_PERKEY_SETTING BIT(2)
#define SE_SOFT_SETTING BIT(16)
#define SE_TZRAM_SECURITY_0 0x004 #define SE_TZRAM_SECURITY_REG 0x004
#define SE_TZRAM_HARD_SETTING BIT(0)
#define SE_TZRAM_ENG_DIS BIT(1)
#define SE_CONFIG_REG_OFFSET 0x014 #define SE_OPERATION_REG 0x008
#define SE_CONFIG_ENC_ALG_SHIFT 12 #define SE_OP_ABORT 0
#define SE_CONFIG_DEC_ALG_SHIFT 8 #define SE_OP_START 1
#define ALG_AES_ENC 1 #define SE_OP_RESTART_OUT 2
#define ALG_RNG 2 #define SE_OP_CTX_SAVE 3
#define ALG_SHA 3 #define SE_OP_RESTART_IN 4
#define ALG_RSA 4
#define ALG_NOP 0
#define ALG_AES_DEC 1
#define SE_CONFIG_ENC_ALG(x) ((x) << SE_CONFIG_ENC_ALG_SHIFT)
#define SE_CONFIG_DEC_ALG(x) ((x) << SE_CONFIG_DEC_ALG_SHIFT)
#define SE_CONFIG_DST_SHIFT 2
#define DST_MEMORY 0
#define DST_HASHREG 1
#define DST_KEYTAB 2
#define DST_SRK 3
#define DST_RSAREG 4
#define SE_CONFIG_DST(x) ((x) << SE_CONFIG_DST_SHIFT)
#define SE_CONFIG_ENC_MODE_SHIFT 24
#define SE_CONFIG_DEC_MODE_SHIFT 16
#define MODE_KEY128 0
#define MODE_KEY192 1
#define MODE_KEY256 2
#define MODE_SHA1 0
#define MODE_SHA224 4
#define MODE_SHA256 5
#define MODE_SHA384 6
#define MODE_SHA512 7
#define SE_CONFIG_ENC_MODE(x) ((x) << SE_CONFIG_ENC_MODE_SHIFT)
#define SE_CONFIG_DEC_MODE(x) ((x) << SE_CONFIG_DEC_MODE_SHIFT)
#define SE_RNG_CONFIG_REG_OFFSET 0x340 #define SE_INT_ENABLE_REG 0x00C
#define RNG_MODE_SHIFT 0 #define SE_INT_STATUS_REG 0x010
#define RNG_MODE_NORMAL 0 #define SE_INT_IN_LL_BUF_RD BIT(0)
#define RNG_MODE_FORCE_INSTANTION 1 #define SE_INT_IN_DONE BIT(1)
#define RNG_MODE_FORCE_RESEED 2 #define SE_INT_OUT_LL_BUF_WR BIT(2)
#define SE_RNG_CONFIG_MODE(x) ((x) << RNG_MODE_SHIFT) #define SE_INT_OUT_DONE BIT(3)
#define RNG_SRC_SHIFT 2 #define SE_INT_OP_DONE BIT(4)
#define RNG_SRC_NONE 0 #define SE_INT_RESEED_NEEDED BIT(5)
#define RNG_SRC_ENTROPY 1 #define SE_INT_ERR_STAT BIT(16)
#define RNG_SRC_LFSR 2
#define SE_RNG_CONFIG_SRC(x) ((x) << RNG_SRC_SHIFT)
#define SE_RNG_SRC_CONFIG_REG_OFFSET 0x344 #define SE_CONFIG_REG 0x014
#define RNG_SRC_RO_ENT_SHIFT 1 #define DST_MEMORY 0
#define RNG_SRC_RO_ENT_ENABLE 1 #define DST_HASHREG 1
#define RNG_SRC_RO_ENT_DISABLE 0 #define DST_KEYTABLE 2
#define SE_RNG_SRC_CONFIG_ENT_SRC(x) ((x) << RNG_SRC_RO_ENT_SHIFT) #define DST_SRK 3
#define RNG_SRC_RO_ENT_LOCK_SHIFT 0 #define DST_RSAREG 4
#define RNG_SRC_RO_ENT_LOCK_ENABLE 1 #define SE_CONFIG_DST(x) ((x) << 2)
#define RNG_SRC_RO_ENT_LOCK_DISABLE 0 #define ALG_NOP 0
#define SE_RNG_SRC_CONFIG_ENT_SRC_LOCK(x) ((x) << RNG_SRC_RO_ENT_LOCK_SHIFT) #define ALG_AES_DEC 1
#define SE_CONFIG_DEC_ALG(x) ((x) << 8)
#define ALG_NOP 0
#define ALG_AES_ENC 1
#define ALG_RNG 2
#define ALG_SHA 3
#define ALG_RSA 4
#define SE_CONFIG_ENC_ALG(x) ((x) << 12)
#define MODE_KEY128 0
#define MODE_KEY192 1
#define MODE_KEY256 2
#define MODE_SHA1 0
#define MODE_SHA224 4
#define MODE_SHA256 5
#define MODE_SHA384 6
#define MODE_SHA512 7
#define SE_CONFIG_DEC_MODE(x) ((x) << 16)
#define SE_CONFIG_ENC_MODE(x) ((x) << 24)
#define SE_RNG_RESEED_INTERVAL_REG_OFFSET 0x348 #define SE_IN_LL_ADDR_REG 0x018
#define SE_IN_CUR_BYTE_ADDR_REG 0x01C
#define SE_IN_CUR_LL_ID_REG 0x020
#define SE_OUT_LL_ADDR_REG 0x024
#define SE_OUT_CUR_BYTE_ADDR_REG 0x028
#define SE_OUT_CUR_LL_ID_REG 0x02C
#define SE_KEYTABLE_REG_OFFSET 0x31c #define SE_HASH_RESULT_REG 0x030
#define SE_KEYTABLE_SLOT_SHIFT 4 #define SE_HASH_RESULT_REG_COUNT 16
#define SE_KEYTABLE_SLOT(x) ((x) << SE_KEYTABLE_SLOT_SHIFT)
#define SE_KEYTABLE_QUAD_SHIFT 2
#define QUAD_KEYS_128 0
#define QUAD_KEYS_192 1
#define QUAD_KEYS_256 1
#define QUAD_ORG_IV 2
#define QUAD_UPDTD_IV 3
#define SE_KEYTABLE_QUAD(x) ((x) << SE_KEYTABLE_QUAD_SHIFT)
#define SE_KEYTABLE_OP_TYPE_SHIFT 9
#define OP_READ 0
#define OP_WRITE 1
#define SE_KEYTABLE_OP_TYPE(x) ((x) << SE_KEYTABLE_OP_TYPE_SHIFT)
#define SE_KEYTABLE_TABLE_SEL_SHIFT 8
#define TABLE_KEYIV 0
#define TABLE_SCHEDULE 1
#define SE_KEYTABLE_TABLE_SEL(x) ((x) << SE_KEYTABLE_TABLE_SEL_SHIFT)
#define SE_KEYTABLE_PKT_SHIFT 0
#define SE_KEYTABLE_PKT(x) ((x) << SE_KEYTABLE_PKT_SHIFT)
#define SE_OP_DONE_SHIFT 4 #define SE_CONTEXT_SAVE_CONFIG_REG 0x070
#define OP_DONE 1 #define KEYS_0_3 0
#define SE_OP_DONE(x, y) ((x) && ((y) << SE_OP_DONE_SHIFT)) #define KEYS_4_7 1
#define ORIGINAL_IV 2
#define UPDATED_IV 3
#define SE_CONTEXT_AES_WORD_QUAD(x) ((x) << 0)
#define SE_CONTEXT_AES_KEY_INDEX(x) ((x) << 8)
#define KEYS_0_3 0
#define KEYS_4_7 1
#define KEYS_8_11 2
#define KEYS_12_15 3
#define SE_CONTEXT_RSA_WORD_QUAD(x) ((x) << 12)
#define SLOT0_EXPONENT 0
#define SLOT0_MODULUS 1
#define SLOT1_EXPONENT 2
#define SLOT1_MODULUS 3
#define SE_CONTEXT_RSA_KEY_INDEX(x) ((x) << 16)
#define STICKY_0_3 0
#define STICKY_4_7 1
#define SE_CONTEXT_STICKY_WORD_QUAD(x) ((x) << 24)
#define STICKY_BITS 0
#define RSA_KEYTABLE 1
#define AES_KEYTABLE 2
#define MEM 4
#define SRK 6
#define SE_CONTEXT_SRC(x) ((x) << 29)
#define SE_CRYPTO_LAST_BLOCK 0x080 #define SE_CTX_SAVE_AUTO_T210B01_REG 0x074
#define SE_CTX_SAVE_AUTO_ENABLE BIT(0)
#define SE_CTX_SAVE_AUTO_LOCK BIT(8)
#define SE_CTX_SAVE_AUTO_CURR_CNT_MASK (0x3FF << 16)
#define SE_CRYPTO_REG_OFFSET 0x304 #define SE_CRYPTO_LAST_BLOCK 0x080
#define SE_CRYPTO_HASH_SHIFT 0
#define HASH_DISABLE 0
#define HASH_ENABLE 1
#define SE_CRYPTO_HASH(x) ((x) << SE_CRYPTO_HASH_SHIFT)
#define SE_CRYPTO_XOR_POS_SHIFT 1
#define XOR_BYPASS 0
#define XOR_TOP 2
#define XOR_BOTTOM 3
#define SE_CRYPTO_XOR_POS(x) ((x) << SE_CRYPTO_XOR_POS_SHIFT)
#define SE_CRYPTO_INPUT_SEL_SHIFT 3
#define INPUT_AHB 0
#define INPUT_RANDOM 1
#define INPUT_AESOUT 2
#define INPUT_LNR_CTR 3
#define SE_CRYPTO_INPUT_SEL(x) ((x) << SE_CRYPTO_INPUT_SEL_SHIFT)
#define SE_CRYPTO_VCTRAM_SEL_SHIFT 5
#define VCTRAM_AHB 0
#define VCTRAM_AESOUT 2
#define VCTRAM_PREVAHB 3
#define SE_CRYPTO_VCTRAM_SEL(x) ((x) << SE_CRYPTO_VCTRAM_SEL_SHIFT)
#define SE_CRYPTO_IV_SEL_SHIFT 7
#define IV_ORIGINAL 0
#define IV_UPDATED 1
#define SE_CRYPTO_IV_SEL(x) ((x) << SE_CRYPTO_IV_SEL_SHIFT)
#define SE_CRYPTO_CORE_SEL_SHIFT 8
#define CORE_DECRYPT 0
#define CORE_ENCRYPT 1
#define SE_CRYPTO_CORE_SEL(x) ((x) << SE_CRYPTO_CORE_SEL_SHIFT)
#define SE_CRYPTO_CTR_VAL_SHIFT 11
#define SE_CRYPTO_CTR_VAL(x) ((x) << SE_CRYPTO_CTR_VAL_SHIFT)
#define SE_CRYPTO_KEY_INDEX_SHIFT 24
#define SE_CRYPTO_KEY_INDEX(x) ((x) << SE_CRYPTO_KEY_INDEX_SHIFT)
#define SE_CRYPTO_CTR_CNTN_SHIFT 11
#define SE_CRYPTO_CTR_CNTN(x) ((x) << SE_CRYPTO_CTR_CNTN_SHIFT)
#define SE_CRYPTO_CTR_REG_COUNT 4 #define SE_SHA_CONFIG_REG 0x200
#define SE_CRYPTO_CTR_REG_OFFSET 0x308
#define SE_OPERATION_REG_OFFSET 0x008
#define SE_OPERATION_SHIFT 0
#define OP_ABORT 0
#define OP_START 1
#define OP_RESTART 2
#define OP_CTX_SAVE 3
#define OP_RESTART_IN 4
#define SE_OPERATION(x) ((x) << SE_OPERATION_SHIFT)
#define SE_CONTEXT_SAVE_CONFIG_REG_OFFSET 0x070
#define SE_CONTEXT_SAVE_WORD_QUAD_SHIFT 0
#define KEYS_0_3 0
#define KEYS_4_7 1
#define ORIG_IV 2
#define UPD_IV 3
#define SE_CONTEXT_SAVE_WORD_QUAD(x) ((x) << SE_CONTEXT_SAVE_WORD_QUAD_SHIFT)
#define SE_CONTEXT_SAVE_KEY_INDEX_SHIFT 8
#define SE_CONTEXT_SAVE_KEY_INDEX(x) ((x) << SE_CONTEXT_SAVE_KEY_INDEX_SHIFT)
#define SE_CONTEXT_SAVE_STICKY_WORD_QUAD_SHIFT 24
#define STICKY_0_3 0
#define STICKY_4_7 1
#define SE_CONTEXT_SAVE_STICKY_WORD_QUAD(x) \
((x) << SE_CONTEXT_SAVE_STICKY_WORD_QUAD_SHIFT)
#define SE_CONTEXT_SAVE_SRC_SHIFT 29
#define STICKY_BITS 0
#define KEYTABLE 2
#define MEM 4
#define SRK 6
#define RSA_KEYTABLE 1
#define AES_KEYTABLE 2
#define SE_CONTEXT_SAVE_SRC(x) ((x) << SE_CONTEXT_SAVE_SRC_SHIFT)
#define SE_CONTEXT_SAVE_RSA_KEY_INDEX_SHIFT 16
#define SE_CONTEXT_SAVE_RSA_KEY_INDEX(x) \
((x) << SE_CONTEXT_SAVE_RSA_KEY_INDEX_SHIFT)
#define SE_CONTEXT_RSA_WORD_QUAD_SHIFT 12
#define SE_CONTEXT_RSA_WORD_QUAD(x) \
((x) << SE_CONTEXT_RSA_WORD_QUAD_SHIFT)
#define SE_CTX_SAVE_AUTO 0x074
#define CTX_SAVE_AUTO_ENABLE BIT(0)
#define CTX_SAVE_AUTO_LOCK BIT(8)
#define CTX_SAVE_AUTO_CURR_CNT_MASK (0x3FF << 16)
#define SE_INT_ENABLE_REG_OFFSET 0x00c
#define SE_INT_STATUS_REG_OFFSET 0x010
#define INT_DISABLE 0
#define INT_ENABLE 1
#define INT_UNSET 0
#define INT_SET 1
#define SE_INT_OP_DONE_SHIFT 4
#define SE_INT_OP_DONE(x) ((x) << SE_INT_OP_DONE_SHIFT)
#define SE_INT_ERROR_SHIFT 16
#define SE_INT_ERROR(x) ((x) << SE_INT_ERROR_SHIFT)
#define SE_STATUS_0 0x800
#define SE_STATUS_0_STATE_WAIT_IN 3
#define SE_ERR_STATUS_0 0x804
#define SE_ERR_STATUS_0_SE_NS_ACCESS_CLEAR 0
#define SE_CRYPTO_KEYTABLE_DST_REG_OFFSET 0X330
#define SE_CRYPTO_KEYTABLE_DST_WORD_QUAD_SHIFT 0
#define SE_CRYPTO_KEYTABLE_DST_WORD_QUAD(x) \
((x) << SE_CRYPTO_KEYTABLE_DST_WORD_QUAD_SHIFT)
#define SE_KEY_INDEX_SHIFT 8
#define SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(x) ((x) << SE_KEY_INDEX_SHIFT)
#define SE_IN_LL_ADDR_REG_OFFSET 0x018
#define SE_OUT_LL_ADDR_REG_OFFSET 0x024
#define SE_KEYTABLE_DATA0_REG_OFFSET 0x320
#define SE_KEYTABLE_REG_MAX_DATA 16
#define SE_BLOCK_COUNT_REG_OFFSET 0x318
#define SE_SPARE_0_REG_OFFSET 0x80c
#define SE_SHA_CONFIG_REG_OFFSET 0x200
#define SHA_CONTINUE 0 #define SHA_CONTINUE 0
#define SHA_INIT_HASH 1 #define SHA_INIT_HASH 1
#define SE_SHA_MSG_LENGTH_0_REG_OFFSET 0x204 #define SE_SHA_MSG_LENGTH_0_REG 0x204
#define SE_SHA_MSG_LENGTH_1_REG_OFFSET 0x208 #define SE_SHA_MSG_LENGTH_1_REG 0x208
#define SE_SHA_MSG_LENGTH_2_REG_OFFSET 0x20C #define SE_SHA_MSG_LENGTH_2_REG 0x20C
#define SE_SHA_MSG_LENGTH_3_REG_OFFSET 0x210 #define SE_SHA_MSG_LENGTH_3_REG 0x210
#define SE_SHA_MSG_LEFT_0_REG_OFFSET 0x214 #define SE_SHA_MSG_LEFT_0_REG 0x214
#define SE_SHA_MSG_LEFT_1_REG_OFFSET 0x218 #define SE_SHA_MSG_LEFT_1_REG 0x218
#define SE_SHA_MSG_LEFT_2_REG_OFFSET 0x21C #define SE_SHA_MSG_LEFT_2_REG 0x21C
#define SE_SHA_MSG_LEFT_3_REG_OFFSET 0x220 #define SE_SHA_MSG_LEFT_3_REG 0x220
#define SE_HASH_RESULT_REG_COUNT 16 #define SE_CRYPTO_SECURITY_PERKEY_REG 0x280
#define SE_HASH_RESULT_REG_OFFSET 0x030 #define SE_KEY_LOCK_FLAG 0x80
#define TEGRA_SE_KEY_256_SIZE 32 #define SE_CRYPTO_KEYTABLE_ACCESS_REG 0x284
#define TEGRA_SE_KEY_192_SIZE 24 #define SE_CRYPTO_KEYTABLE_ACCESS_REG_COUNT 16
#define TEGRA_SE_KEY_128_SIZE 16 #define SE_KEY_TBL_DIS_KEYREAD_FLAG BIT(0)
#define TEGRA_SE_AES_BLOCK_SIZE 16 #define SE_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1)
#define TEGRA_SE_AES_MIN_KEY_SIZE 16 #define SE_KEY_TBL_DIS_OIVREAD_FLAG BIT(2)
#define TEGRA_SE_AES_MAX_KEY_SIZE 32 #define SE_KEY_TBL_DIS_OIVUPDATE_FLAG BIT(3)
#define TEGRA_SE_AES_IV_SIZE 16 #define SE_KEY_TBL_DIS_UIVREAD_FLAG BIT(4)
#define TEGRA_SE_SHA_512_SIZE 64 #define SE_KEY_TBL_DIS_UIVUPDATE_FLAG BIT(5)
#define TEGRA_SE_SHA_384_SIZE 48 #define SE_KEY_TBL_DIS_KEYUSE_FLAG BIT(6)
#define TEGRA_SE_SHA_256_SIZE 32 #define SE_KEY_TBL_DIS_KEY_ACCESS_FLAG 0x7F
#define TEGRA_SE_SHA_192_SIZE 24
#define TEGRA_SE_RNG_IV_SIZE 16
#define TEGRA_SE_RNG_DT_SIZE 16
#define TEGRA_SE_RNG_KEY_SIZE 16
#define TEGRA_SE_RNG_SEED_SIZE (TEGRA_SE_RNG_IV_SIZE + \
TEGRA_SE_RNG_KEY_SIZE + \
TEGRA_SE_RNG_DT_SIZE)
#define TEGRA_SE_AES_CMAC_DIGEST_SIZE 16 #define SE_CRYPTO_CONFIG_REG 0x304
#define TEGRA_SE_RSA512_DIGEST_SIZE 64 #define HASH_DISABLE 0
#define TEGRA_SE_RSA1024_DIGEST_SIZE 128 #define HASH_ENABLE 1
#define TEGRA_SE_RSA1536_DIGEST_SIZE 192 #define SE_CRYPTO_HASH(x) ((x) << 0)
#define TEGRA_SE_RSA2048_DIGEST_SIZE 256 #define XOR_BYPASS 0
#define XOR_TOP 2
#define XOR_BOTTOM 3
#define SE_CRYPTO_XOR_POS(x) ((x) << 1)
#define INPUT_MEMORY 0
#define INPUT_RANDOM 1
#define INPUT_AESOUT 2
#define INPUT_LNR_CTR 3
#define SE_CRYPTO_INPUT_SEL(x) ((x) << 3)
#define VCTRAM_MEM 0
#define VCTRAM_AESOUT 2
#define VCTRAM_PREVMEM 3
#define SE_CRYPTO_VCTRAM_SEL(x) ((x) << 5)
#define IV_ORIGINAL 0
#define IV_UPDATED 1
#define SE_CRYPTO_IV_SEL(x) ((x) << 7)
#define CORE_DECRYPT 0
#define CORE_ENCRYPT 1
#define SE_CRYPTO_CORE_SEL(x) ((x) << 8)
#define SE_CRYPTO_KEYSCH_BYPASS BIT(10)
#define SE_CRYPTO_CTR_CNTN(x) ((x) << 11)
#define SE_CRYPTO_KEY_INDEX(x) ((x) << 24)
#define MEMIF_AHB 0
#define MEMIF_MCCIF 1
#define SE_CRYPTO_MEMIF(x) ((x) << 31)
#define SE_KEY_TABLE_ACCESS_LOCK_OFFSET 0x280 #define SE_CRYPTO_LINEAR_CTR_REG 0x308
#define SE_KEY_TBL_DIS_KEY_LOCK_FLAG 0x80 #define SE_CRYPTO_LINEAR_CTR_REG_COUNT 4
#define SE_KEY_TABLE_ACCESS_REG_OFFSET 0x284 #define SE_CRYPTO_BLOCK_COUNT_REG 0x318
#define SE_KEY_TBL_DIS_KEYREAD_FLAG BIT(0)
#define SE_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1)
#define SE_KEY_TBL_DIS_OIVREAD_FLAG BIT(2)
#define SE_KEY_TBL_DIS_OIVUPDATE_FLAG BIT(3)
#define SE_KEY_TBL_DIS_UIVREAD_FLAG BIT(4)
#define SE_KEY_TBL_DIS_UIVUPDATE_FLAG BIT(5)
#define SE_KEY_TBL_DIS_KEYUSE_FLAG BIT(6)
#define SE_KEY_TBL_DIS_KEY_ACCESS_FLAG 0x7F
#define SE_KEY_READ_DISABLE_SHIFT 0 #define SE_CRYPTO_KEYTABLE_ADDR_REG 0x31C
#define SE_KEY_UPDATE_DISABLE_SHIFT 1 #define SE_KEYTABLE_PKT(x) ((x) << 0)
#define KEYS_0_3 0
#define KEYS_4_7 1
#define ORIGINAL_IV 2
#define UPDATED_IV 3
#define SE_KEYTABLE_QUAD(x) ((x) << 2)
#define SE_KEYTABLE_SLOT(x) ((x) << 4)
#define SE_CONTEXT_BUFER_SIZE 1072 #define SE_CRYPTO_KEYTABLE_DATA_REG 0x320
#define SE_CONTEXT_DRBG_BUFER_SIZE 2112
#define SE_CONTEXT_SAVE_RANDOM_DATA_OFFSET 0 #define SE_CRYPTO_KEYTABLE_DST_REG 0x330
#define SE_CONTEXT_SAVE_RANDOM_DATA_SIZE 16 #define KEYS_0_3 0
#define SE_CONTEXT_SAVE_STICKY_BITS_OFFSET \ #define KEYS_4_7 1
(SE_CONTEXT_SAVE_RANDOM_DATA_OFFSET + SE_CONTEXT_SAVE_RANDOM_DATA_SIZE) #define ORIGINAL_IV 2
#define SE_CONTEXT_SAVE_STICKY_BITS_SIZE 16 #define UPDATED_IV 3
#define SE_KEYTABLE_DST_WORD_QUAD(x) ((x) << 0)
#define SE_KEYTABLE_DST_KEY_INDEX(x) ((x) << 8)
#define SE_CONTEXT_SAVE_KEYS_OFFSET (SE_CONTEXT_SAVE_STICKY_BITS_OFFSET + \ #define SE_RNG_CONFIG_REG 0x340
SE_CONTEXT_SAVE_STICKY_BITS_SIZE) #define MODE_NORMAL 0
#define SE11_CONTEXT_SAVE_KEYS_OFFSET (SE_CONTEXT_SAVE_STICKY_BITS_OFFSET + \ #define MODE_FORCE_INSTANTION 1
SE_CONTEXT_SAVE_STICKY_BITS_SIZE + \ #define MODE_FORCE_RESEED 2
SE_CONTEXT_SAVE_STICKY_BITS_SIZE) #define SE_RNG_CONFIG_MODE(x) ((x) << 0)
#define SRC_NONE 0
#define SRC_ENTROPY 1
#define SRC_LFSR 2
#define SE_RNG_CONFIG_SRC(x) ((x) << 2)
#define SE_CONTEXT_SAVE_KEY_LENGTH 512 #define SE_RNG_SRC_CONFIG_REG 0x344
#define SE_CONTEXT_ORIGINAL_IV_OFFSET (SE_CONTEXT_SAVE_KEYS_OFFSET + \ #define RO_ENTR_LOCK_DISABLE 0
SE_CONTEXT_SAVE_KEY_LENGTH) #define RO_ENTR_LOCK_ENABLE 1
#define SE11_CONTEXT_ORIGINAL_IV_OFFSET (SE11_CONTEXT_SAVE_KEYS_OFFSET + \ #define SE_RNG_SRC_CONFIG_ENTR_SRC_LOCK(x) ((x) << 0)
SE_CONTEXT_SAVE_KEY_LENGTH) #define RO_ENTR_DISABLE 0
#define RO_ENTR_ENABLE 1
#define SE_RNG_SRC_CONFIG_ENTR_SRC(x) ((x) << 1)
#define RO_HW_DIS_CYA_DISABLE 0
#define RO_HW_DIS_CYA_ENABLE 1
#define SE_RNG_SRC_CONFIG_HW_DIS_CYA(x) ((x) << 2)
#define SE_RNG_SRC_CONFIG_ENTR_SUBSMPL(x) ((x) << 4)
#define SE_RNG_SRC_CONFIG_ENTR_DATA_FLUSH BIT(8)
#define SE_CONTEXT_ORIGINAL_IV_LENGTH 256 #define SE_RNG_RESEED_INTERVAL_REG 0x348
#define SE_CONTEXT_UPDATED_IV_OFFSET (SE_CONTEXT_ORIGINAL_IV_OFFSET + \ #define SE_RSA_CONFIG 0x400
SE_CONTEXT_ORIGINAL_IV_LENGTH) #define RSA_KEY_SLOT_ONE 0
#define SE11_CONTEXT_UPDATED_IV_OFFSET (SE11_CONTEXT_ORIGINAL_IV_OFFSET + \ #define RSA_KEY_SLOT_TW0 1
SE_CONTEXT_ORIGINAL_IV_LENGTH) #define RSA_KEY_SLOT(x) ((x) << 24)
#define SE_CONTEXT_UPDATED_IV_LENGTH 256 #define SE_RSA_KEY_SIZE_REG 0x404
#define RSA_KEY_WIDTH_512 0
#define RSA_KEY_WIDTH_1024 1
#define RSA_KEY_WIDTH_1536 2
#define RSA_KEY_WIDTH_2048 3
#define SE_CONTEXT_SAVE_KNOWN_PATTERN_OFFSET (SE_CONTEXT_UPDATED_IV_OFFSET + \ #define SE_RSA_EXP_SIZE_REG 0x408
SE_CONTEXT_UPDATED_IV_LENGTH)
#define SE11_CONTEXT_SAVE_KNOWN_PATTERN_OFFSET \
(SE11_CONTEXT_UPDATED_IV_OFFSET + \
SE_CONTEXT_UPDATED_IV_LENGTH)
#define SE_CONTEXT_SAVE_RSA_KEYS_OFFSET SE11_CONTEXT_SAVE_KNOWN_PATTERN_OFFSET #define SE_RSA_SECURITY_PERKEY_REG 0x40C
#define SE_RSA_KEY_LOCK_FLAG 0x80
#define SE_RSA_KEYTABLE_ACCESS_REG 0x410
#define SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG BIT(0)
#define SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1)
#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG BIT(2)
#define SE_RSA_KEY_TBL_DIS_KEY_ACCESS_FLAG 0x7F
#define SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG (SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG | SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG)
#define SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_USE_FLAG (SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG | SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG | SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG)
#define SE_CONTEXT_SAVE_RSA_KEY_LENGTH 1024 #define SE_RSA_KEYTABLE_ADDR_REG 0x420
#define SE_RSA_KEYTABLE_PKT(x) ((x) << 0)
#define RSA_KEY_TYPE_EXP 0
#define RSA_KEY_TYPE_MOD 1
#define SE_RSA_KEYTABLE_TYPE(x) ((x) << 6)
#define RSA_KEY_NUM(x) ((x) << 7)
#define RSA_KEY_INPUT_MODE_REG 0
#define RSA_KEY_INPUT_MODE_DMA 1
#define SE_RSA_KEYTABLE_INPUT_MODE(x) ((x) << 8)
#define RSA_KEY_READ 0
#define RSA_KEY_WRITE 1
#define SE_RSA_KEY_OP(x) ((x) << 10)
#define SE_CONTEXT_SAVE_RSA_KNOWN_PATTERN_OFFSET \ #define SE_RSA_KEYTABLE_DATA_REG 0x424
(SE_CONTEXT_SAVE_RSA_KEYS_OFFSET + SE_CONTEXT_SAVE_RSA_KEY_LENGTH)
#define SE_CONTEXT_KNOWN_PATTERN_SIZE 16 #define SE_RSA_OUTPUT_REG 0x428
#define SE_RSA_OUTPUT_REG_COUNT 64
#define TEGRA_SE_RSA_KEYSLOT_COUNT 2 #define SE_STATUS_REG 0x800
#define SE_STATUS_STATE_IDLE 0
#define SE_STATUS_STATE_BUSY 1
#define SE_STATUS_STATE_WAIT_OUT 2
#define SE_STATUS_STATE_WAIT_IN 3
#define SE_STATUS_STATE_MASK 3
#define SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET 0x40C #define SE_ERR_STATUS_REG 0x804
#define SE_RSA_KEY_TBL_DIS_KEY_LOCK_FLAG 0x80 #define SE_ERR_STATUS_SE_NS_ACCESS BIT(0)
#define SE_ERR_STATUS_BUSY_REG_WR BIT(1)
#define SE_ERR_STATUS_DST BIT(2)
#define SE_ERR_STATUS_SRK_USAGE_LIMIT BIT(3)
#define SE_ERR_STATUS_TZRAM_NS_ACCESS BIT(24)
#define SE_ERR_STATUS_TZRAM_ADDRESS BIT(25)
#define SE_RSA_KEYTABLE_ACCESS_REG_OFFSET 0x410 #define SE_MISC_REG 0x808
#define SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG BIT(0) #define SE_ENTROPY_NEXT_192BIT BIT(0)
#define SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1) #define SE_ENTROPY_VN_BYPASS BIT(1)
#define SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG (SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG | SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG) #define SE_CLK_OVR_ON BIT(2)
#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG BIT(2)
#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG_SHIFT BIT(2)
#define SE_RSA_KEY_TBL_DIS_KEY_ALL_COMMON_FLAG 7
#define SE_RSA_KEY_TBL_DIS_KEY_ALL_FLAG 0x7F
#define SE_RSA_KEYTABLE_ADDR 0x420 #define SE_SPARE_REG 0x80C
#define SE_RSA_KEYTABLE_DATA 0x424 #define SE_ERRATA_FIX_DISABLE 0
#define SE_RSA_OUTPUT 0x428 #define SE_ERRATA_FIX_ENABLE 1
#define SE_ECO(x) ((x) << 0)
#define RSA_KEY_READ 0 #endif
#define RSA_KEY_WRITE 1
#define SE_RSA_KEY_OP_SHIFT 10
#define SE_RSA_KEY_OP(x) ((x) << SE_RSA_KEY_OP_SHIFT)
#define RSA_KEY_INPUT_MODE_REG 0
#define RSA_KEY_INPUT_MODE_DMA 1
#define RSA_KEY_INPUT_MODE_SHIFT 8
#define RSA_KEY_INPUT_MODE(x) ((x) << RSA_KEY_INPUT_MODE_SHIFT)
#define RSA_KEY_SLOT_ONE 0
#define RSA_KEY_SLOT_TW0 1
#define RSA_KEY_NUM_SHIFT 7
#define RSA_KEY_NUM(x) ((x) << RSA_KEY_NUM_SHIFT)
#define RSA_KEY_TYPE_EXP 0
#define RSA_KEY_TYPE_MOD 1
#define RSA_KEY_TYPE_SHIFT 6
#define RSA_KEY_TYPE(x) ((x) << RSA_KEY_TYPE_SHIFT)
#define SE_RSA_KEY_SIZE_REG_OFFSET 0x404
#define SE_RSA_EXP_SIZE_REG_OFFSET 0x408
#define RSA_KEY_SLOT_SHIFT 24
#define RSA_KEY_SLOT(x) ((x) << RSA_KEY_SLOT_SHIFT)
#define SE_RSA_CONFIG 0x400
#define RSA_KEY_PKT_WORD_ADDR_SHIFT 0
#define RSA_KEY_PKT_WORD_ADDR(x) ((x) << RSA_KEY_PKT_WORD_ADDR_SHIFT)
#define RSA_KEY_WORD_ADDR_SHIFT 0
#define RSA_KEY_WORD_ADDR(x) ((x) << RSA_KEY_WORD_ADDR_SHIFT)
#define SE_RSA_KEYTABLE_PKT_SHIFT 0
#define SE_RSA_KEYTABLE_PKT(x) ((x) << SE_RSA_KEYTABLE_PKT_SHIFT)
#endif /* _CRYPTO_TEGRA_SE_H */

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2019 CTCaer * Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2018 balika011 * Copyright (c) 2018 balika011
* *
* 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
@@ -70,7 +70,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
u32 *pkg11_magic_off; u32 *pkg11_magic_off;
bpmp_mmu_disable(); bpmp_mmu_disable();
bpmp_clk_rate_set(BPMP_CLK_NORMAL); bpmp_freq_t prev_fid = bpmp_clk_rate_set(BPMP_CLK_NORMAL);
// Enable clocks. // Enable clocks.
clock_enable_host1x(); clock_enable_host1x();
@@ -190,7 +190,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
if (kb == KB_TSEC_FW_EMU_COMPAT) if (kb == KB_TSEC_FW_EMU_COMPAT)
{ {
u32 start = get_tmr_us(); u32 start = get_tmr_us();
u32 k = se[SE_KEYTABLE_DATA0_REG_OFFSET / 4]; u32 k = se[SE_CRYPTO_KEYTABLE_DATA_REG / 4];
u32 key[16] = {0}; u32 key[16] = {0};
u32 kidx = 0; u32 kidx = 0;
@@ -198,9 +198,9 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
{ {
smmu_flush_all(); smmu_flush_all();
if (k != se[SE_KEYTABLE_DATA0_REG_OFFSET / 4]) if (k != se[SE_CRYPTO_KEYTABLE_DATA_REG / 4])
{ {
k = se[SE_KEYTABLE_DATA0_REG_OFFSET / 4]; k = se[SE_CRYPTO_KEYTABLE_DATA_REG / 4];
key[kidx++] = k; key[kidx++] = k;
} }
@@ -269,7 +269,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_MSB) = 0; SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_MSB) = 0;
SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_LSB) = 0; SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_LSB) = 0;
memcpy(tsec_keys, &buf, 0x10); memcpy(tsec_keys, &buf, SE_KEY_128_SIZE);
} }
out_free:; out_free:;
@@ -284,7 +284,7 @@ out:;
clock_disable_sor_safe(); clock_disable_sor_safe();
clock_disable_tsec(); clock_disable_tsec();
bpmp_mmu_enable(); bpmp_mmu_enable();
bpmp_clk_rate_set(BPMP_CLK_DEFAULT_BOOST); bpmp_clk_rate_set(prev_fid);
return res; return res;
} }

View File

@@ -1,7 +1,7 @@
/* /*
* BPMP-Lite Cache/MMU and Frequency driver for Tegra X1 * BPMP-Lite Cache/MMU and Frequency 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,
@@ -212,43 +212,45 @@ const u8 pll_divn[] = {
//95 // BPMP_CLK_DEV_BOOST: 608MHz 49% - 152MHz APB. //95 // BPMP_CLK_DEV_BOOST: 608MHz 49% - 152MHz APB.
}; };
bpmp_freq_t bpmp_clock_set = BPMP_CLK_NORMAL; bpmp_freq_t bpmp_fid_current = BPMP_CLK_NORMAL;
void bpmp_clk_rate_get() void bpmp_clk_rate_get()
{ {
bool clk_src_is_pllp = ((CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) >> 4) & 7) == 3; bool clk_src_is_pllp = ((CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) >> 4) & 7) == 3;
if (clk_src_is_pllp) if (clk_src_is_pllp)
bpmp_clock_set = BPMP_CLK_NORMAL; bpmp_fid_current = BPMP_CLK_NORMAL;
else else
{ {
bpmp_clock_set = BPMP_CLK_HIGH_BOOST; bpmp_fid_current = BPMP_CLK_HIGH_BOOST;
u8 pll_divn_curr = (CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) >> 10) & 0xFF; u8 pll_divn_curr = (CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) >> 10) & 0xFF;
for (u32 i = 1; i < sizeof(pll_divn); i++) for (u32 i = 1; i < sizeof(pll_divn); i++)
{ {
if (pll_divn[i] == pll_divn_curr) if (pll_divn[i] == pll_divn_curr)
{ {
bpmp_clock_set = i; bpmp_fid_current = i;
break; break;
} }
} }
} }
} }
void bpmp_clk_rate_set(bpmp_freq_t fid) bpmp_freq_t bpmp_clk_rate_set(bpmp_freq_t fid)
{ {
bpmp_freq_t prev_fid = bpmp_fid_current;
if (fid > (BPMP_CLK_MAX - 1)) if (fid > (BPMP_CLK_MAX - 1))
fid = BPMP_CLK_MAX - 1; fid = BPMP_CLK_MAX - 1;
if (bpmp_clock_set == fid) if (prev_fid == fid)
return; return prev_fid;
if (fid) if (fid)
{ {
if (bpmp_clock_set) if (prev_fid)
{ {
// Restore to PLLP source during PLLC4 configuration. // Restore to PLLP source during PLLC configuration.
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003333; // PLLP_OUT. CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003333; // PLLP_OUT.
msleep(1); // Wait a bit for clock source change. msleep(1); // Wait a bit for clock source change.
} }
@@ -269,7 +271,10 @@ void bpmp_clk_rate_set(bpmp_freq_t fid)
// Disable PLLC to save power. // Disable PLLC to save power.
clock_disable_pllc(); clock_disable_pllc();
} }
bpmp_clock_set = fid; bpmp_fid_current = fid;
// Return old fid in case of temporary swap.
return prev_fid;
} }
// The following functions halt BPMP to reduce power while sleeping. // The following functions halt BPMP to reduce power while sleeping.

View File

@@ -1,7 +1,7 @@
/* /*
* BPMP-Lite Cache/MMU and Frequency driver for Tegra X1 * BPMP-Lite Cache/MMU and Frequency 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,
@@ -53,6 +53,7 @@ typedef enum
BPMP_CLK_MAX BPMP_CLK_MAX
} bpmp_freq_t; } bpmp_freq_t;
#define BPMP_CLK_LOWER_BOOST BPMP_CLK_SUPER_BOOST
#define BPMP_CLK_DEFAULT_BOOST BPMP_CLK_HYPER_BOOST #define BPMP_CLK_DEFAULT_BOOST BPMP_CLK_HYPER_BOOST
void bpmp_mmu_maintenance(u32 op, bool force); void bpmp_mmu_maintenance(u32 op, bool force);
@@ -60,7 +61,7 @@ void bpmp_mmu_set_entry(int idx, bpmp_mmu_entry_t *entry, bool apply);
void bpmp_mmu_enable(); void bpmp_mmu_enable();
void bpmp_mmu_disable(); void bpmp_mmu_disable();
void bpmp_clk_rate_get(); void bpmp_clk_rate_get();
void bpmp_clk_rate_set(bpmp_freq_t fid); bpmp_freq_t bpmp_clk_rate_set(bpmp_freq_t fid);
void bpmp_usleep(u32 us); void bpmp_usleep(u32 us);
void bpmp_msleep(u32 ms); void bpmp_msleep(u32 ms);
void bpmp_halt(); void bpmp_halt();

View File

@@ -58,24 +58,7 @@ void ccplex_boot_cpu0(u32 entry)
else else
_ccplex_enable_power_t210b01(); _ccplex_enable_power_t210b01();
// Enable PLLX and set it to 300 MHz. clock_enable_pllx();
if (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & PLLX_BASE_ENABLE)) // PLLX_ENABLE.
{
CLOCK(CLK_RST_CONTROLLER_PLLX_MISC_3) &= 0xFFFFFFF7; // Disable IDDQ.
usleep(2);
// Bypass dividers.
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = PLLX_BASE_BYPASS | (4 << 20) | (78 << 8) | 2; // P div: 4 (5), N div: 78, M div: 2.
// Disable bypass
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = (4 << 20) | (78 << 8) | 2;
// Set PLLX_LOCK_ENABLE.
CLOCK(CLK_RST_CONTROLLER_PLLX_MISC) = (CLOCK(CLK_RST_CONTROLLER_PLLX_MISC) & 0xFFFBFFFF) | 0x40000;
// Enable PLLX.
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = PLLX_BASE_ENABLE | (4 << 20) | (78 << 8) | 2;
}
// Wait for PLL to stabilize.
while (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & PLLX_BASE_LOCK))
;
// Configure MSELECT source and enable clock to 102MHz. // Configure MSELECT source and enable clock to 102MHz.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) & 0x1FFFFF00) | 6; CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) & 0x1FFFFF00) | 6;

View File

@@ -279,6 +279,32 @@ void clock_disable_pwm()
clock_disable(&_clock_pwm); clock_disable(&_clock_pwm);
} }
void clock_enable_pllx()
{
// Configure and enable PLLX if disabled.
if (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & PLLX_BASE_ENABLE)) // PLLX_ENABLE.
{
CLOCK(CLK_RST_CONTROLLER_PLLX_MISC_3) &= ~PLLX_MISC3_IDDQ; // Disable IDDQ.
usleep(2);
// Set div configuration.
const u32 pllx_div_cfg = (2 << 20) | (156 << 8) | 2; // P div: 2 (3), N div: 156, M div: 2. 998.4 MHz.
// Bypass dividers.
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = PLLX_BASE_BYPASS | pllx_div_cfg;
// Disable bypass
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = pllx_div_cfg;
// Set PLLX_LOCK_ENABLE.
CLOCK(CLK_RST_CONTROLLER_PLLX_MISC) |= PLLX_MISC_LOCK_EN;
// Enable PLLX.
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = PLLX_BASE_ENABLE | pllx_div_cfg;
}
// Wait for PLL to stabilize.
while (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & PLLX_BASE_LOCK))
;
}
void clock_enable_pllc(u32 divn) void clock_enable_pllc(u32 divn)
{ {
u8 pll_divn_curr = (CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) >> 10) & 0xFF; u8 pll_divn_curr = (CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) >> 10) & 0xFF;
@@ -757,15 +783,25 @@ u32 clock_get_osc_freq()
u32 clock_get_dev_freq(clock_pto_id_t id) u32 clock_get_dev_freq(clock_pto_id_t id)
{ {
u32 val = ((id & PTO_SRC_SEL_MASK) << PTO_SRC_SEL_SHIFT) | PTO_DIV_SEL_DIV1 | PTO_CLK_ENABLE | (16 - 1); // 16 periods of 32.76KHz window. const u32 pto_win = 16;
const u32 pto_osc = 32768;
u32 val = ((id & PTO_SRC_SEL_MASK) << PTO_SRC_SEL_SHIFT) | PTO_DIV_SEL_DIV1 | PTO_CLK_ENABLE | (pto_win - 1);
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val; CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val;
(void)CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL);
usleep(2); usleep(2);
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val | PTO_CNT_RST; CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val | PTO_CNT_RST;
(void)CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL);
usleep(2); usleep(2);
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val; CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val;
(void)CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL);
usleep(2); usleep(2);
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val | PTO_CNT_EN; CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val | PTO_CNT_EN;
usleep(502); (void)CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL);
usleep((1000000 * pto_win / pto_osc) + 12 + 2);
while (CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_STATUS) & PTO_CLK_CNT_BUSY) while (CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_STATUS) & PTO_CLK_CNT_BUSY)
; ;
@@ -773,9 +809,11 @@ u32 clock_get_dev_freq(clock_pto_id_t id)
u32 cnt = CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_STATUS) & PTO_CLK_CNT; u32 cnt = CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_STATUS) & PTO_CLK_CNT;
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = 0; CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = 0;
(void)CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL);
usleep(2);
u32 freq = ((cnt << 8) | 0x3E) / 125; u32 freq_khz = (u64)cnt * pto_osc / pto_win / 1000;
return freq; return freq_khz;
} }

View File

@@ -167,6 +167,8 @@
#define PLLX_BASE_REF_DIS BIT(29) #define PLLX_BASE_REF_DIS BIT(29)
#define PLLX_BASE_ENABLE BIT(30) #define PLLX_BASE_ENABLE BIT(30)
#define PLLX_BASE_BYPASS BIT(31) #define PLLX_BASE_BYPASS BIT(31)
#define PLLX_MISC_LOCK_EN BIT(18)
#define PLLX_MISC3_IDDQ BIT(3)
#define PLLCX_BASE_LOCK BIT(27) #define PLLCX_BASE_LOCK BIT(27)
#define PLLCX_BASE_REF_DIS BIT(29) #define PLLCX_BASE_REF_DIS BIT(29)
@@ -215,7 +217,7 @@
#define OSC_FREQ_DET_BUSY BIT(31) #define OSC_FREQ_DET_BUSY BIT(31)
#define OSC_FREQ_DET_CNT 0xFFFF #define OSC_FREQ_DET_CNT 0xFFFF
/*! PLLs omitted as they need PTO enabled in MISC registers. Norm div is 2. */ /*! PTO IDs. */
typedef enum _clock_pto_id_t typedef enum _clock_pto_id_t
{ {
CLK_PTO_PCLK_SYS = 0x06, CLK_PTO_PCLK_SYS = 0x06,
@@ -239,6 +241,9 @@ typedef enum _clock_pto_id_t
CLK_PTO_SDMMC4 = 0x23, CLK_PTO_SDMMC4 = 0x23,
CLK_PTO_EMC = 0x24, CLK_PTO_EMC = 0x24,
CLK_PTO_CCLK_LP = 0x2B,
CLK_PTO_CCLK_LP_DIV2 = 0x2C,
CLK_PTO_MSELECT = 0x2F, CLK_PTO_MSELECT = 0x2F,
CLK_PTO_VIC = 0x36, CLK_PTO_VIC = 0x36,
@@ -321,6 +326,32 @@ typedef enum _clock_pto_id_t
CLK_PTO_XUSB_SS_HOST_DEV = 0x137, CLK_PTO_XUSB_SS_HOST_DEV = 0x137,
CLK_PTO_XUSB_CORE_HOST = 0x138, CLK_PTO_XUSB_CORE_HOST = 0x138,
CLK_PTO_XUSB_CORE_DEV = 0x139, CLK_PTO_XUSB_CORE_DEV = 0x139,
/*
* PLL need PTO enabled in MISC registers.
* Normal div is 2 so result is multiplied with it.
*/
CLK_PTO_PLLC_DIV2 = 0x01,
CLK_PTO_PLLM_DIV2 = 0x02,
CLK_PTO_PLLP_DIV2 = 0x03,
CLK_PTO_PLLA_DIV2 = 0x04,
CLK_PTO_PLLX_DIV2 = 0x05,
CLK_PTO_PLLMB_DIV2 = 0x25,
CLK_PTO_PLLC4_DIV2 = 0x51,
CLK_PTO_PLLA1_DIV2 = 0x55,
CLK_PTO_PLLC2_DIV2 = 0x58,
CLK_PTO_PLLC3_DIV2 = 0x5A,
CLK_PTO_PLLD_DIV2 = 0xCB,
CLK_PTO_PLLD2_DIV2 = 0xCD,
CLK_PTO_PLLDP_DIV2 = 0xCF,
CLK_PTO_PLLU_DIV2 = 0x10D,
CLK_PTO_PLLREFE_DIV2 = 0x10F,
} clock_pto_id_t; } clock_pto_id_t;
/* /*
@@ -628,6 +659,7 @@ void clock_enable_coresight();
void clock_disable_coresight(); void clock_disable_coresight();
void clock_enable_pwm(); void clock_enable_pwm();
void clock_disable_pwm(); void clock_disable_pwm();
void clock_enable_pllx();
void clock_enable_pllc(u32 divn); void clock_enable_pllc(u32 divn);
void clock_disable_pllc(); void clock_disable_pllc();
void clock_enable_pllu(); void clock_enable_pllu();

View File

@@ -2,7 +2,7 @@
* 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
* *
* 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,11 +19,15 @@
#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>
#include <utils/types.h> #include <utils/types.h>
extern boot_cfg_t b_cfg;
static const u32 evp_thunk_template[] = { static const u32 evp_thunk_template[] = {
0xe92d0007, // STMFD SP!, {R0-R2} 0xe92d0007, // STMFD SP!, {R0-R2}
0xe1a0200e, // MOV R2, LR 0xe1a0200e, // MOV R2, LR
@@ -90,7 +94,7 @@ u32 fuse_read_dramid(bool raw_id)
} }
else else
{ {
if (dramid > 27) if (dramid > 28)
dramid = 8; dramid = 8;
} }
@@ -111,26 +115,43 @@ 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; // Skip SBK/SSK if sept was run.
for (u32 i = 0; i < 32; i++) bool sbk_skip = b_cfg.boot_cfg & BOOT_CFG_SEPT_RUN || FUSE(FUSE_PRIVATE_KEY0) == 0xFFFFFFFF;
if (!sbk_skip)
{ {
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,7 @@
* 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
* *
* 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 +82,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
@@ -97,7 +98,7 @@ u32 fuse_read_odm_keygen_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

@@ -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,
@@ -42,11 +42,23 @@
#include <storage/nx_sd.h> #include <storage/nx_sd.h>
#include <storage/sdmmc.h> #include <storage/sdmmc.h>
#include <thermal/fan.h> #include <thermal/fan.h>
#include <thermal/tmp451.h>
#include <utils/util.h> #include <utils/util.h>
extern boot_cfg_t b_cfg; extern boot_cfg_t b_cfg;
extern volatile nyx_storage_t *nyx_str; extern volatile nyx_storage_t *nyx_str;
u32 hw_rst_status;
u32 hw_rst_reason;
u32 hw_get_chip_id()
{
if (((APB_MISC(APB_MISC_GP_HIDREV) >> 4) & 0xF) >= GP_HIDREV_MAJOR_T210B01)
return GP_HIDREV_MAJOR_T210B01;
else
return GP_HIDREV_MAJOR_T210;
}
/* /*
* CLK_OSC - 38.4 MHz crystal. * CLK_OSC - 38.4 MHz crystal.
* CLK_M - 19.2 MHz (osc/2). * CLK_M - 19.2 MHz (osc/2).
@@ -56,14 +68,6 @@ extern volatile nyx_storage_t *nyx_str;
* PCLK - 68MHz init (-> 136MHz -> OC/4). * PCLK - 68MHz init (-> 136MHz -> OC/4).
*/ */
u32 hw_get_chip_id()
{
if (((APB_MISC(APB_MISC_GP_HIDREV) >> 4) & 0xF) >= GP_HIDREV_MAJOR_T210B01)
return GP_HIDREV_MAJOR_T210B01;
else
return GP_HIDREV_MAJOR_T210;
}
static void _config_oscillators() static void _config_oscillators()
{ {
CLOCK(CLK_RST_CONTROLLER_SPARE_REG0) = (CLOCK(CLK_RST_CONTROLLER_SPARE_REG0) & 0xFFFFFFF3) | 4; // Set CLK_M_DIVISOR to 2. CLOCK(CLK_RST_CONTROLLER_SPARE_REG0) = (CLOCK(CLK_RST_CONTROLLER_SPARE_REG0) & 0xFFFFFFF3) | 4; // Set CLK_M_DIVISOR to 2.
@@ -87,6 +91,7 @@ static void _config_oscillators()
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // Set HCLK div to 1 and PCLK div to 3. CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // Set HCLK div to 1 and PCLK div to 3.
} }
// The uart is skipped for Copper, Hoag and Calcio. Used in Icosa, Iowa and Aula.
static void _config_gpios(bool nx_hoag) static void _config_gpios(bool nx_hoag)
{ {
// Clamp inputs when tristated. // Clamp inputs when tristated.
@@ -248,36 +253,25 @@ 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 sept was run. // Try to set SBK from fuses. If patched, skip.
bool sbk_skip = b_cfg.boot_cfg & BOOT_CFG_SEPT_RUN || FUSE(FUSE_PRIVATE_KEY0) == 0xFFFFFFFF; fuse_set_sbk();
if (!sbk_skip)
{
// 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, 0x10);
// 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, SZ_64K);
PMC(APBDEV_PMC_CRYPTO_OP) = PMC_CRYPTO_OP_SE_ENABLE; PMC(APBDEV_PMC_CRYPTO_OP) = PMC_CRYPTO_OP_SE_ENABLE;
SE(SE_INT_STATUS_REG_OFFSET) = 0x1F; SE(SE_INT_STATUS_REG) = 0x1F; // Clear all SE interrupts.
// Clear the boot reason to avoid problems later // Save reset reason.
hw_rst_status = PMC(APBDEV_PMC_SCRATCH200);
hw_rst_reason = PMC(APBDEV_PMC_RST_STATUS) & PMC_RST_STATUS_MASK;
// Clear the boot reason to avoid problems later.
PMC(APBDEV_PMC_SCRATCH200) = 0x0; PMC(APBDEV_PMC_SCRATCH200) = 0x0;
PMC(APBDEV_PMC_RST_STATUS) = 0x0; PMC(APBDEV_PMC_RST_STATUS) = 0x0;
APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) = (APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) & 0xF0) | (7 << 10); APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) = (APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) & 0xF0) | (7 << 10);
@@ -350,7 +344,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.
@@ -419,19 +413,18 @@ void hw_init()
bpmp_mmu_enable(); bpmp_mmu_enable();
} }
void hw_reinit_workaround(bool coreboot, u32 magic) void hw_reinit_workaround(bool coreboot, u32 bl_magic)
{ {
// Disable BPMP max clock. // Disable BPMP max clock.
bpmp_clk_rate_set(BPMP_CLK_NORMAL); bpmp_clk_rate_set(BPMP_CLK_NORMAL);
#ifdef NYX #ifdef NYX
// Deinit touchscreen, 5V regulators and Joy-Con. // Disable temperature sensor, touchscreen, 5V regulators and Joy-Con.
touch_power_off(); tmp451_end();
set_fan_duty(0); set_fan_duty(0);
touch_power_off();
jc_deinit(); jc_deinit();
regulator_5v_disable(REGULATOR_5V_ALL); regulator_5v_disable(REGULATOR_5V_ALL);
clock_disable_uart(UART_B);
clock_disable_uart(UART_C);
#endif #endif
// Flush/disable MMU cache and set DRAM clock to 204MHz. // Flush/disable MMU cache and set DRAM clock to 204MHz.
@@ -460,11 +453,22 @@ void hw_reinit_workaround(bool coreboot, u32 magic)
PMC(APBDEV_PMC_NO_IOPOWER) &= ~(PMC_NO_IOPOWER_SDMMC1_IO_EN); PMC(APBDEV_PMC_NO_IOPOWER) &= ~(PMC_NO_IOPOWER_SDMMC1_IO_EN);
} }
// Power off display. // Seamless display or display power off.
display_end(); switch (bl_magic)
{
case BL_MAGIC_CRBOOT_SLD:;
// Set pwm to 0%, switch to gpio mode and restore pwm duty.
u32 brightness = display_get_backlight_brightness();
display_backlight_brightness(0, 1000);
gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_GPIO);
display_backlight_brightness(brightness, 0);
break;
default:
display_end();
}
// Enable clock to USBD and init SDMMC1 to avoid hangs with bad hw inits. // Enable clock to USBD and init SDMMC1 to avoid hangs with bad hw inits.
if (magic == 0xBAADF00D) if (bl_magic == BL_MAGIC_BROKEN_HWI)
{ {
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_USBD); CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_USBD);
sdmmc_init(&sd_sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID, 0); sdmmc_init(&sd_sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID, 0);

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,6 +20,12 @@
#include <utils/types.h> #include <utils/types.h>
#define BL_MAGIC_CRBOOT_SLD 0x30444C53 // SLD0, seamless display type 0.
#define BL_MAGIC_BROKEN_HWI 0xBAADF00D // Broken hwinit.
extern u32 hw_rst_status;
extern u32 hw_rst_reason;
void hw_init(); void hw_init();
void hw_reinit_workaround(bool coreboot, u32 magic); void hw_reinit_workaround(bool coreboot, u32 magic);
u32 hw_get_chip_id(); u32 hw_get_chip_id();

View File

@@ -60,6 +60,13 @@
#define APBDEV_PMC_CLK_OUT_CNTRL 0x1A8 #define APBDEV_PMC_CLK_OUT_CNTRL 0x1A8
#define PMC_CLK_OUT_CNTRL_CLK1_FORCE_EN BIT(2) #define PMC_CLK_OUT_CNTRL_CLK1_FORCE_EN BIT(2)
#define APBDEV_PMC_RST_STATUS 0x1B4 #define APBDEV_PMC_RST_STATUS 0x1B4
#define PMC_RST_STATUS_MASK 0x7
#define PMC_RST_STATUS_POR 0
#define PMC_RST_STATUS_WATCHDOG 1
#define PMC_RST_STATUS_SENSOR 2
#define PMC_RST_STATUS_SW_MAIN 3
#define PMC_RST_STATUS_LP0 4
#define PMC_RST_STATUS_AOTAG 5
#define APBDEV_PMC_IO_DPD_REQ 0x1B8 #define APBDEV_PMC_IO_DPD_REQ 0x1B8
#define PMC_IO_DPD_REQ_DPD_OFF BIT(30) #define PMC_IO_DPD_REQ_DPD_OFF BIT(30)
#define APBDEV_PMC_IO_DPD2_REQ 0x1C0 #define APBDEV_PMC_IO_DPD2_REQ 0x1C0

View File

@@ -122,7 +122,12 @@ u32 uart_get_IIR(u32 idx)
{ {
uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]); uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]);
return uart->UART_IIR_FCR; u32 iir = uart->UART_IIR_FCR & UART_IIR_INT_MASK;
if (iir & UART_IIR_NO_INT)
return 0;
else
return ((iir >> 1) + 1); // Return encoded interrupt.
} }
void uart_set_IIR(u32 idx) void uart_set_IIR(u32 idx)

View File

@@ -54,6 +54,17 @@
#define UART_IIR_FCR_RX_CLR 0x2 #define UART_IIR_FCR_RX_CLR 0x2
#define UART_IIR_FCR_EN_FIFO 0x1 #define UART_IIR_FCR_EN_FIFO 0x1
#define UART_IIR_NO_INT BIT(0)
#define UART_IIR_INT_MASK 0xF
/* Custom returned interrupt results. Actual interrupts are -1 */
#define UART_IIR_NOI 0 // No interrupt.
#define UART_IIR_MSI 1 // Modem status interrupt.
#define UART_IIR_THRI 2 // Transmitter holding register empty.
#define UART_IIR_RDI 3 // Receiver data interrupt.
#define UART_IIR_ERROR 4 // Overrun Error, Parity Error, Framing Error, Break.
#define UART_IIR_REDI 5 // Receiver end of data interrupt.
#define UART_IIR_RDTI 7 // Receiver data timeout interrupt.
#define UART_MCR_RTS 0x2 #define UART_MCR_RTS 0x2
#define UART_MCR_DTR 0x1 #define UART_MCR_DTR 0x1

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 */
@@ -84,6 +85,11 @@
#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */ #define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */
#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */ #define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */
#define MMC_VENDOR_60_CMD 60 /* Vendor Defined */
#define MMC_VENDOR_61_CMD 61 /* Vendor Defined */
#define MMC_VENDOR_62_CMD 62 /* Vendor Defined */
#define MMC_VENDOR_63_CMD 63 /* Vendor Defined */
/* class 11 */ /* class 11 */
#define MMC_QUE_TASK_PARAMS 44 /* ac [20:16] task id R1 */ #define MMC_QUE_TASK_PARAMS 44 /* ac [20:16] task id R1 */
#define MMC_QUE_TASK_ADDR 45 /* ac [31:0] data addr R1 */ #define MMC_QUE_TASK_ADDR 45 /* ac [31:0] data addr R1 */
@@ -92,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 */
@@ -146,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
@@ -157,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)
@@ -180,13 +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_BUSY 0x80000000 /* Card Power up status bit */ #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_CCS (1 << 30) /* Card Capacity 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) */
@@ -214,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 */
@@ -229,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 */
@@ -244,6 +254,7 @@ c : clear by read
#define EXT_CSD_GP_SIZE_MULT 143 /* R/W */ #define EXT_CSD_GP_SIZE_MULT 143 /* R/W */
#define EXT_CSD_PARTITION_SETTING_COMPLETED 155 /* R/W */ #define EXT_CSD_PARTITION_SETTING_COMPLETED 155 /* R/W */
#define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */ #define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */
#define EXT_CSD_MAX_ENH_SIZE_MULT 157 /* RO, 3 bytes */
#define EXT_CSD_PARTITION_SUPPORT 160 /* RO */ #define EXT_CSD_PARTITION_SUPPORT 160 /* RO */
#define EXT_CSD_HPI_MGMT 161 /* R/W */ #define EXT_CSD_HPI_MGMT 161 /* R/W */
#define EXT_CSD_RST_N_FUNCTION 162 /* R/W */ #define EXT_CSD_RST_N_FUNCTION 162 /* R/W */
@@ -307,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)
@@ -384,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)
@@ -395,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
@@ -432,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

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2019 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,
@@ -45,12 +45,15 @@ extern FATFS sd_fs;
void sd_error_count_increment(u8 type); void sd_error_count_increment(u8 type);
u16 *sd_get_error_count(); u16 *sd_get_error_count();
bool sd_get_card_removed(); bool sd_get_card_removed();
bool sd_get_card_initialized();
bool sd_get_card_mounted();
u32 sd_get_mode(); u32 sd_get_mode();
int sd_init_retry(bool power_cycle); int sd_init_retry(bool power_cycle);
bool sd_initialize(bool power_cycle); bool sd_initialize(bool power_cycle);
bool sd_mount(); bool sd_mount();
void sd_unmount(); void sd_unmount();
void sd_end(); void sd_end();
bool sd_is_gpt();
void *sd_file_read(const char *path, u32 *fsize); void *sd_file_read(const char *path, u32 *fsize);
int sd_save_to_file(void *buf, u32 size, const char *filename); int sd_save_to_file(void *buf, u32 size, const char *filename);

View File

@@ -1,7 +1,7 @@
/* /*
* Ramdisk driver for Tegra X1 * Ramdisk 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,
@@ -19,23 +19,40 @@
#include <string.h> #include <string.h>
#include "ramdisk.h" #include "ramdisk.h"
#include <libs/fatfs/diskio.h>
#include <mem/heap.h> #include <mem/heap.h>
#include <utils/types.h> #include <utils/types.h>
#include <memory_map.h> #include <memory_map.h>
int ram_disk_init(FATFS *ram_fs) static u32 disk_size = 0;
int ram_disk_init(FATFS *ram_fs, u32 ramdisk_size)
{ {
int res; int res = 0;
u8 *buf = malloc(0x400000); disk_size = ramdisk_size;
f_mount(NULL, "ram:", 1); // Unmount ramdisk. // If ramdisk is not raw, format it.
if (ram_fs)
{
u8 *buf = malloc(0x400000);
res = f_mkfs("ram:", FM_EXFAT, RAMDISK_CLUSTER_SZ, buf, 0x400000); // Format as exFAT w/ 32KB cluster. // Set ramdisk size.
if (!res) ramdisk_size >>= 9;
res = f_mount(ram_fs, "ram:", 1); // Mount ramdisk. disk_set_info(DRIVE_RAM, SET_SECTOR_COUNT, &ramdisk_size);
free(buf); // Unmount ramdisk.
f_mount(NULL, "ram:", 1);
// Format as exFAT w/ 32KB cluster with no MBR.
res = f_mkfs("ram:", FM_EXFAT | FM_SFD, RAMDISK_CLUSTER_SZ, buf, 0x400000);
// Mount ramdisk.
if (!res)
res = f_mount(ram_fs, "ram:", 1);
free(buf);
}
return res; return res;
} }
@@ -45,7 +62,7 @@ int ram_disk_read(u32 sector, u32 sector_count, void *buf)
u32 sector_off = RAM_DISK_ADDR + (sector << 9); u32 sector_off = RAM_DISK_ADDR + (sector << 9);
u32 bytes_count = sector_count << 9; u32 bytes_count = sector_count << 9;
if ((sector_off - RAM_DISK_ADDR) > RAM_DISK_SZ) if ((sector_off - RAM_DISK_ADDR) > disk_size)
return 1; return 1;
memcpy(buf, (void *)sector_off, bytes_count); memcpy(buf, (void *)sector_off, bytes_count);
@@ -58,7 +75,7 @@ int ram_disk_write(u32 sector, u32 sector_count, const void *buf)
u32 sector_off = RAM_DISK_ADDR + (sector << 9); u32 sector_off = RAM_DISK_ADDR + (sector << 9);
u32 bytes_count = sector_count << 9; u32 bytes_count = sector_count << 9;
if ((sector_off - RAM_DISK_ADDR) > RAM_DISK_SZ) if ((sector_off - RAM_DISK_ADDR) > disk_size)
return 1; return 1;
memcpy((void *)sector_off, buf, bytes_count); memcpy((void *)sector_off, buf, bytes_count);

View File

@@ -1,7 +1,7 @@
/* /*
* Ramdisk driver for Tegra X1 * Ramdisk 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,
@@ -23,7 +23,7 @@
#define RAMDISK_CLUSTER_SZ 32768 #define RAMDISK_CLUSTER_SZ 32768
int ram_disk_init(FATFS *ram_fs); int ram_disk_init(FATFS *ram_fs, u32 ramdisk_size);
int ram_disk_read(u32 sector, u32 sector_count, void *buf); int ram_disk_read(u32 sector, u32 sector_count, void *buf);
int ram_disk_write(u32 sector, u32 sector_count, const void *buf); int ram_disk_write(u32 sector, u32 sector_count, const void *buf);

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2005-2007 Pierre Ossman, All Rights Reserved. * Copyright (c) 2005-2007 Pierre Ossman, All Rights Reserved.
* Copyright (c) 2018 CTCaer * Copyright (c) 2018-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -14,60 +14,79 @@
/* SD commands type argument response */ /* SD commands type argument response */
/* class 0 */ /* class 0 */
/* This is basically the same command as for MMC with some quirks. */ /* This is basically the same command as for MMC with some quirks. */
#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */ #define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */
#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */ #define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */
#define SD_SWITCH_VOLTAGE 11 /* ac R1 */ #define SD_SWITCH_VOLTAGE 11 /* ac R1 */
/* class 10 */ /* class 10 */
#define SD_SWITCH 6 /* adtc [31:0] See below R1 */ #define SD_SWITCH 6 /* adtc [31:0] See below R1 */
/* class 5 */ /* class 5 */
#define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */ #define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */
#define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */ #define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */
/* Application commands */ /* Application commands */
#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */ #define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */
#define SD_APP_SD_STATUS 13 /* adtc R1 */ #define SD_APP_SD_STATUS 13 /* adtc R1 */
#define SD_APP_SEND_NUM_WR_BLKS 22 /* adtc R1 */ #define SD_APP_SEND_NUM_WR_BLKS 22 /* adtc R1 */
#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */ #define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */
#define SD_APP_SET_CLR_CARD_DETECT 42 #define SD_APP_SET_CLR_CARD_DETECT 42 /* adtc R1 */
#define SD_APP_SEND_SCR 51 /* adtc R1 */ #define SD_APP_SEND_SCR 51 /* adtc R1 */
/* Application secure commands */
#define SD_APP_SECURE_READ_MULTI_BLOCK 18 /* adtc R1 */
#define SD_APP_SECURE_WRITE_MULTI_BLOCK 25 /* adtc R1 */
#define SD_APP_SECURE_WRITE_MKB 26 /* adtc R1 */
#define SD_APP_SECURE_ERASE 38 /* adtc R1b */
#define SD_APP_GET_MKB 43 /* adtc [31:0] See below R1 */
#define SD_APP_GET_MID 44 /* adtc R1 */
#define SD_APP_SET_CER_RN1 45 /* adtc R1 */
#define SD_APP_GET_CER_RN2 46 /* adtc R1 */
#define SD_APP_SET_CER_RES2 47 /* adtc R1 */
#define SD_APP_GET_CER_RES1 48 /* adtc R1 */
#define SD_APP_CHANGE_SECURE_AREA 49 /* adtc R1b */
/* OCR bit definitions */ /* OCR bit definitions */
#define SD_OCR_CCS (1 << 30) /* Card Capacity Status */ #define SD_OCR_VDD_18 (1 << 7) /* VDD voltage 1.8 */
#define SD_OCR_XPC (1 << 28) /* SDXC power control */ #define SD_VHD_27_36 (1 << 8) /* VDD voltage 2.7 ~ 3.6 */
#define SD_OCR_S18R (1 << 24) /* 1.8V switching request */
#define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */
#define SD_OCR_VDD_27_34 (0x7F << 15) /* VDD voltage 2.7 ~ 3.4 */ #define SD_OCR_VDD_27_34 (0x7F << 15) /* VDD voltage 2.7 ~ 3.4 */
#define SD_OCR_VDD_32_33 (1 << 20) /* VDD voltage 3.2 ~ 3.3 */ #define SD_OCR_VDD_32_33 (1 << 20) /* VDD voltage 3.2 ~ 3.3 */
#define SD_OCR_VDD_18 (1 << 7) /* VDD voltage 1.8 */ #define SD_OCR_S18R (1 << 24) /* 1.8V switching request */
#define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */
#define SD_VHD_27_36 (1 << 8) /* VDD voltage 2.7 ~ 3.6 */ #define SD_OCR_XPC (1 << 28) /* SDXC power control */
#define SD_OCR_CCS (1 << 30) /* Card Capacity Status */
#define SD_OCR_BUSY (1 << 31) /* Card Power up Status */
/* /*
* SD_SWITCH argument format: * SD_SWITCH argument format:
* *
* [31] Check (0) or switch (1) * [31] Check (0) or switch (1)
* [30:24] Reserved (0) * [30:24] Reserved (0)
* [23:20] Function group 6 * [23:20] Function group 6
* [19:16] Function group 5 * [19:16] Function group 5
* [15:12] Function group 4 * [15:12] Function group 4
* [11:8] Function group 3 * [11:8] Function group 3
* [7:4] Function group 2 * [7:4] Function group 2
* [3:0] Function group 1 * [3:0] Function group 1
*/ */
/* /*
* SD_SEND_IF_COND argument format: * SD_SEND_IF_COND argument format:
* *
* [31:12] Reserved (0) * [31:12] Reserved (0)
* [11:8] Host Voltage Supply Flags * [11:8] Host Voltage Supply Flags
* [7:0] Check Pattern (0xAA) * [7:0] Check Pattern (0xAA)
*/ */
/* /*
* SCR field definitions * SD_APP_GET_MKB argument format:
*/ *
* [31:24] Number of blocks to read (512 block size)
* [23:16] MKB ID
* [15:0] Block offset
*/
/*
* SCR field definitions
*/
#define SCR_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.01 */ #define SCR_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.01 */
#define SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */ #define SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */
#define SCR_SPEC_VER_2 2 /* Implements system specification 2.00-3.0X */ #define SCR_SPEC_VER_2 2 /* Implements system specification 2.00-3.0X */
@@ -75,14 +94,14 @@
#define SD_SCR_BUS_WIDTH_4 (1<<2) #define SD_SCR_BUS_WIDTH_4 (1<<2)
/* /*
* SD bus widths * SD bus widths
*/ */
#define SD_BUS_WIDTH_1 0 #define SD_BUS_WIDTH_1 0
#define SD_BUS_WIDTH_4 2 #define SD_BUS_WIDTH_4 2
/* /*
* SD bus speeds * SD bus speeds
*/ */
#define UHS_SDR12_BUS_SPEED 0 #define UHS_SDR12_BUS_SPEED 0
#define HIGH_SPEED_BUS_SPEED 1 #define HIGH_SPEED_BUS_SPEED 1
#define UHS_SDR25_BUS_SPEED 1 #define UHS_SDR25_BUS_SPEED 1
@@ -112,19 +131,19 @@
#define SD_MAX_CURRENT_800 (1 << SD_SET_CURRENT_LIMIT_800) #define SD_MAX_CURRENT_800 (1 << SD_SET_CURRENT_LIMIT_800)
/* /*
* SD_SWITCH mode * SD_SWITCH mode
*/ */
#define SD_SWITCH_CHECK 0 #define SD_SWITCH_CHECK 0
#define SD_SWITCH_SET 1 #define SD_SWITCH_SET 1
/* /*
* SD_SWITCH function groups * SD_SWITCH function groups
*/ */
#define SD_SWITCH_GRP_ACCESS 0 #define SD_SWITCH_GRP_ACCESS 0
/* /*
* SD_SWITCH access modes * SD_SWITCH access modes
*/ */
#define SD_SWITCH_ACCESS_DEF 0 #define SD_SWITCH_ACCESS_DEF 0
#define SD_SWITCH_ACCESS_HS 1 #define SD_SWITCH_ACCESS_HS 1

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,
@@ -42,8 +42,8 @@ static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size)
} }
/* /*
* Common functions for SD and MMC. * Common functions for SD and MMC.
*/ */
static int _sdmmc_storage_check_card_status(u32 res) static int _sdmmc_storage_check_card_status(u32 res)
{ {
@@ -88,20 +88,20 @@ static int _sdmmc_storage_execute_cmd_type1(sdmmc_storage_t *storage, u32 cmd, u
static int _sdmmc_storage_go_idle_state(sdmmc_storage_t *storage) static int _sdmmc_storage_go_idle_state(sdmmc_storage_t *storage)
{ {
sdmmc_cmd_t cmd; sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmd, MMC_GO_IDLE_STATE, 0, SDMMC_RSP_TYPE_0, 0); sdmmc_init_cmd(&cmdbuf, MMC_GO_IDLE_STATE, 0, SDMMC_RSP_TYPE_0, 0);
return sdmmc_execute_cmd(storage->sdmmc, &cmd, NULL, NULL); return sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL);
} }
static int _sdmmc_storage_get_cid(sdmmc_storage_t *storage, void *buf) static int _sdmmc_storage_get_cid(sdmmc_storage_t *storage)
{ {
sdmmc_cmd_t cmd; sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmd, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0); sdmmc_init_cmd(&cmdbuf, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, NULL, NULL)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0; return 0;
sdmmc_get_rsp(storage->sdmmc, buf, 16, SDMMC_RSP_TYPE_2); sdmmc_get_rsp(storage->sdmmc, (u32 *)storage->raw_cid, 16, SDMMC_RSP_TYPE_2);
return 1; return 1;
} }
@@ -111,14 +111,14 @@ static int _sdmmc_storage_select_card(sdmmc_storage_t *storage)
return _sdmmc_storage_execute_cmd_type1(storage, MMC_SELECT_CARD, storage->rca << 16, 1, R1_SKIP_STATE_CHECK); return _sdmmc_storage_execute_cmd_type1(storage, MMC_SELECT_CARD, storage->rca << 16, 1, R1_SKIP_STATE_CHECK);
} }
static int _sdmmc_storage_get_csd(sdmmc_storage_t *storage, void *buf) static int _sdmmc_storage_get_csd(sdmmc_storage_t *storage)
{ {
sdmmc_cmd_t cmdbuf; sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmdbuf, MMC_SEND_CSD, storage->rca << 16, SDMMC_RSP_TYPE_2, 0); sdmmc_init_cmd(&cmdbuf, MMC_SEND_CSD, storage->rca << 16, SDMMC_RSP_TYPE_2, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0; return 0;
sdmmc_get_rsp(storage->sdmmc, buf, 16, SDMMC_RSP_TYPE_2); sdmmc_get_rsp(storage->sdmmc, (u32 *)storage->raw_csd, 16, SDMMC_RSP_TYPE_2);
return 1; return 1;
} }
@@ -139,12 +139,70 @@ 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;
sdmmc_cmd_t cmdbuf; sdmmc_cmd_t cmdbuf;
sdmmc_req_t reqbuf; sdmmc_req_t reqbuf;
// If SDSC convert block address to byte address.
if (!storage->has_sector_access)
sector <<= 9;
sdmmc_init_cmd(&cmdbuf, is_write ? MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK, sector, SDMMC_RSP_TYPE_1, 0); sdmmc_init_cmd(&cmdbuf, is_write ? MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK, sector, SDMMC_RSP_TYPE_1, 0);
reqbuf.buf = buf; reqbuf.buf = buf;
@@ -152,7 +210,7 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out
reqbuf.blksize = 512; reqbuf.blksize = 512;
reqbuf.is_write = is_write; reqbuf.is_write = is_write;
reqbuf.is_multi_block = 1; reqbuf.is_multi_block = 1;
reqbuf.is_auto_cmd12 = 1; reqbuf.is_auto_stop_trn = 1;
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, blkcnt_out)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, blkcnt_out))
{ {
@@ -288,25 +346,25 @@ int sdmmc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, v
static int _mmc_storage_get_op_cond_inner(sdmmc_storage_t *storage, u32 *pout, u32 power) static int _mmc_storage_get_op_cond_inner(sdmmc_storage_t *storage, u32 *pout, u32 power)
{ {
sdmmc_cmd_t cmd; sdmmc_cmd_t cmdbuf;
u32 arg = 0; u32 arg = 0;
switch (power) switch (power)
{ {
case SDMMC_POWER_1_8: case SDMMC_POWER_1_8:
arg = SD_OCR_CCS | SD_OCR_VDD_18; arg = MMC_CARD_CCS | MMC_CARD_VDD_18;
break; break;
case SDMMC_POWER_3_3: case SDMMC_POWER_3_3:
arg = SD_OCR_CCS | SD_OCR_VDD_27_34; arg = MMC_CARD_CCS | MMC_CARD_VDD_27_34;
break; break;
default: default:
return 0; return 0;
} }
sdmmc_init_cmd(&cmd, MMC_SEND_OP_COND, arg, SDMMC_RSP_TYPE_3, 0); sdmmc_init_cmd(&cmdbuf, MMC_SEND_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, NULL, NULL)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0; return 0;
return sdmmc_get_rsp(storage->sdmmc, pout, 4, SDMMC_RSP_TYPE_3); return sdmmc_get_rsp(storage->sdmmc, pout, 4, SDMMC_RSP_TYPE_3);
@@ -316,15 +374,17 @@ static int _mmc_storage_get_op_cond(sdmmc_storage_t *storage, u32 power)
{ {
u32 timeout = get_tmr_ms() + 1500; u32 timeout = get_tmr_ms() + 1500;
while (1) while (true)
{ {
u32 cond = 0; u32 cond = 0;
if (!_mmc_storage_get_op_cond_inner(storage, &cond, power)) if (!_mmc_storage_get_op_cond_inner(storage, &cond, power))
break; break;
// Check if power up is done.
if (cond & MMC_CARD_BUSY) if (cond & MMC_CARD_BUSY)
{ {
if (cond & SD_OCR_CCS) // Check if card is high capacity.
if (cond & MMC_CARD_CCS)
storage->has_sector_access = 1; storage->has_sector_access = 1;
return 1; return 1;
@@ -362,7 +422,6 @@ static void _mmc_storage_parse_cid(sdmmc_storage_t *storage)
case 3: /* MMC v3.1 - v3.3 */ case 3: /* MMC v3.1 - v3.3 */
case 4: /* MMC v4 */ case 4: /* MMC v4 */
storage->cid.manfid = unstuff_bits(raw_cid, 120, 8); storage->cid.manfid = unstuff_bits(raw_cid, 120, 8);
storage->cid.card_bga = unstuff_bits(raw_cid, 112, 2);
storage->cid.oemid = unstuff_bits(raw_cid, 104, 8); storage->cid.oemid = unstuff_bits(raw_cid, 104, 8);
storage->cid.prv = unstuff_bits(raw_cid, 48, 8); storage->cid.prv = unstuff_bits(raw_cid, 48, 8);
storage->cid.serial = unstuff_bits(raw_cid, 16, 32); storage->cid.serial = unstuff_bits(raw_cid, 16, 32);
@@ -390,13 +449,14 @@ static void _mmc_storage_parse_cid(sdmmc_storage_t *storage)
static void _mmc_storage_parse_csd(sdmmc_storage_t *storage) static void _mmc_storage_parse_csd(sdmmc_storage_t *storage)
{ {
u32 *raw_csd = (u32 *)&(storage->raw_csd); u32 *raw_csd = (u32 *)storage->raw_csd;
storage->csd.mmca_vsn = unstuff_bits(raw_csd, 122, 4); storage->csd.mmca_vsn = unstuff_bits(raw_csd, 122, 4);
storage->csd.structure = unstuff_bits(raw_csd, 126, 2); storage->csd.structure = unstuff_bits(raw_csd, 126, 2);
storage->csd.cmdclass = unstuff_bits(raw_csd, 84, 12); storage->csd.cmdclass = unstuff_bits(raw_csd, 84, 12);
storage->csd.read_blkbits = unstuff_bits(raw_csd, 80, 4); storage->csd.read_blkbits = unstuff_bits(raw_csd, 80, 4);
storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2); storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2);
storage->sec_cnt = storage->csd.capacity;
} }
static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf) static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf)
@@ -407,16 +467,26 @@ static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf)
storage->ext_csd.dev_version = *(u16 *)&buf[EXT_CSD_DEVICE_VERSION]; storage->ext_csd.dev_version = *(u16 *)&buf[EXT_CSD_DEVICE_VERSION];
storage->ext_csd.boot_mult = buf[EXT_CSD_BOOT_MULT]; storage->ext_csd.boot_mult = buf[EXT_CSD_BOOT_MULT];
storage->ext_csd.rpmb_mult = buf[EXT_CSD_RPMB_MULT]; storage->ext_csd.rpmb_mult = buf[EXT_CSD_RPMB_MULT];
storage->ext_csd.sectors = *(u32 *)&buf[EXT_CSD_SEC_CNT]; //storage->ext_csd.bkops = buf[EXT_CSD_BKOPS_SUPPORT];
storage->ext_csd.bkops = buf[EXT_CSD_BKOPS_SUPPORT]; //storage->ext_csd.bkops_en = buf[EXT_CSD_BKOPS_EN];
storage->ext_csd.bkops_en = buf[EXT_CSD_BKOPS_EN]; //storage->ext_csd.bkops_status = buf[EXT_CSD_BKOPS_STATUS];
storage->ext_csd.bkops_status = buf[EXT_CSD_BKOPS_STATUS];
storage->ext_csd.pre_eol_info = buf[EXT_CSD_PRE_EOL_INFO]; storage->ext_csd.pre_eol_info = buf[EXT_CSD_PRE_EOL_INFO];
storage->ext_csd.dev_life_est_a = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A]; storage->ext_csd.dev_life_est_a = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A];
storage->ext_csd.dev_life_est_b = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B]; storage->ext_csd.dev_life_est_b = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B];
storage->sec_cnt = *(u32 *)&buf[EXT_CSD_SEC_CNT]; storage->ext_csd.cache_size =
buf[EXT_CSD_CACHE_SIZE] |
(buf[EXT_CSD_CACHE_SIZE + 1] << 8) |
(buf[EXT_CSD_CACHE_SIZE + 2] << 16) |
(buf[EXT_CSD_CACHE_SIZE + 3] << 24);
storage->ext_csd.max_enh_mult =
(buf[EXT_CSD_MAX_ENH_SIZE_MULT] |
(buf[EXT_CSD_MAX_ENH_SIZE_MULT + 1] << 8) |
(buf[EXT_CSD_MAX_ENH_SIZE_MULT + 2] << 16)) *
buf[EXT_CSD_HC_WP_GRP_SIZE] * buf[EXT_CSD_HC_ERASE_GRP_SIZE];
storage->sec_cnt = *(u32 *)&buf[EXT_CSD_SEC_CNT];
} }
static int _mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf) static int _mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf)
@@ -430,7 +500,7 @@ static int _mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf)
reqbuf.num_sectors = 1; reqbuf.num_sectors = 1;
reqbuf.is_write = 0; reqbuf.is_write = 0;
reqbuf.is_multi_block = 0; reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0; reqbuf.is_auto_stop_trn = 0;
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
return 0; return 0;
@@ -559,19 +629,21 @@ out:
return 1; return 1;
} }
/*
static int _mmc_storage_enable_bkops(sdmmc_storage_t *storage) static int _mmc_storage_enable_bkops(sdmmc_storage_t *storage)
{ {
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_SET_BITS, EXT_CSD_BKOPS_EN, EXT_CSD_BKOPS_LEVEL_2))) if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_SET_BITS, EXT_CSD_BKOPS_EN, EXT_CSD_AUTO_BKOPS_MASK)))
return 0; return 0;
return _sdmmc_storage_check_status(storage); return _sdmmc_storage_check_status(storage);
} }
*/
int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type) int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type)
{ {
memset(storage, 0, sizeof(sdmmc_storage_t)); memset(storage, 0, sizeof(sdmmc_storage_t));
storage->sdmmc = sdmmc; storage->sdmmc = sdmmc;
storage->rca = 2; //TODO: this could be a config item. storage->rca = 2; // Set default device address. This could be a config item.
if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_MMC_ID, SDMMC_POWER_SAVE_DISABLE)) if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_MMC_ID, SDMMC_POWER_SAVE_DISABLE))
return 0; return 0;
@@ -587,7 +659,7 @@ DPRINTF("[MMC] went to idle state\n");
return 0; return 0;
DPRINTF("[MMC] got op cond\n"); DPRINTF("[MMC] got op cond\n");
if (!_sdmmc_storage_get_cid(storage, storage->raw_cid)) if (!_sdmmc_storage_get_cid(storage))
return 0; return 0;
DPRINTF("[MMC] got cid\n"); DPRINTF("[MMC] got cid\n");
@@ -595,7 +667,7 @@ DPRINTF("[MMC] got cid\n");
return 0; return 0;
DPRINTF("[MMC] set relative addr\n"); DPRINTF("[MMC] set relative addr\n");
if (!_sdmmc_storage_get_csd(storage, storage->raw_csd)) if (!_sdmmc_storage_get_csd(storage))
return 0; return 0;
DPRINTF("[MMC] got csd\n"); DPRINTF("[MMC] got csd\n");
_mmc_storage_parse_csd(storage); _mmc_storage_parse_csd(storage);
@@ -612,13 +684,9 @@ DPRINTF("[MMC] card selected\n");
return 0; return 0;
DPRINTF("[MMC] set blocklen to 512\n"); DPRINTF("[MMC] set blocklen to 512\n");
u32 *csd = (u32 *)storage->raw_csd; // Check system specification version, only version 4.0 and later support below features.
//Check system specification version, only version 4.0 and later support below features. if (storage->csd.mmca_vsn < CSD_SPEC_VER_4)
if (unstuff_bits(csd, 122, 4) < CSD_SPEC_VER_4)
{
storage->sec_cnt = (1 + unstuff_bits(csd, 62, 12)) << (unstuff_bits(csd, 47, 3) + 2);
return 1; return 1;
}
if (!_mmc_storage_switch_buswidth(storage, bus_width)) if (!_mmc_storage_switch_buswidth(storage, bus_width))
return 0; return 0;
@@ -628,21 +696,20 @@ DPRINTF("[MMC] switched buswidth\n");
return 0; return 0;
DPRINTF("[MMC] got ext_csd\n"); DPRINTF("[MMC] got ext_csd\n");
_mmc_storage_parse_cid(storage); //This needs to be after csd and ext_csd _mmc_storage_parse_cid(storage); // This needs to be after csd and ext_csd.
//gfx_hexdump(0, ext_csd, 512); //gfx_hexdump(0, ext_csd, 512);
/* When auto BKOPS is enabled the mmc device should be powered all the time until we disable this and check status. /*
Disable it for now until BKOPS disable added to power down sequence at sdmmc_storage_end(). if (storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_AUTO_BKOPS_MASK))
Additionally this works only when we put the device in idle mode which we don't after enabling it. */
if (0 && storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_BKOPS_LEVEL_2))
{ {
_mmc_storage_enable_bkops(storage); _mmc_storage_enable_bkops(storage);
DPRINTF("[MMC] BKOPS enabled\n"); DPRINTF("[MMC] BKOPS enabled\n");
} }
*/
if (!_mmc_storage_enable_highspeed(storage, storage->ext_csd.card_type, type)) if (!_mmc_storage_enable_highspeed(storage, storage->ext_csd.card_type, type))
return 0; return 0;
DPRINTF("[MMC] succesfully switched to HS mode\n"); DPRINTF("[MMC] successfully switched to HS mode\n");
sdmmc_card_clock_powersave(storage->sdmmc, SDMMC_POWER_SAVE_ENABLE); sdmmc_card_clock_powersave(storage->sdmmc, SDMMC_POWER_SAVE_ENABLE);
@@ -665,16 +732,16 @@ int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition)
} }
/* /*
* SD specific functions. * SD specific functions.
*/ */
static int _sd_storage_execute_app_cmd(sdmmc_storage_t *storage, u32 expected_state, u32 mask, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *blkcnt_out) static int _sd_storage_execute_app_cmd(sdmmc_storage_t *storage, u32 expected_state, u32 mask, sdmmc_cmd_t *cmdbuf, sdmmc_req_t *req, u32 *blkcnt_out)
{ {
u32 tmp; u32 tmp;
if (!_sdmmc_storage_execute_cmd_type1_ex(storage, &tmp, MMC_APP_CMD, storage->rca << 16, 0, expected_state, mask)) if (!_sdmmc_storage_execute_cmd_type1_ex(storage, &tmp, MMC_APP_CMD, storage->rca << 16, 0, expected_state, mask))
return 0; return 0;
return sdmmc_execute_cmd(storage->sdmmc, cmd, req, blkcnt_out); return sdmmc_execute_cmd(storage->sdmmc, cmdbuf, req, blkcnt_out);
} }
static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp, u32 cmd, u32 arg, u32 check_busy, u32 expected_state) static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp, u32 cmd, u32 arg, u32 check_busy, u32 expected_state)
@@ -685,67 +752,70 @@ static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp
return _sdmmc_storage_execute_cmd_type1_ex(storage, resp, cmd, arg, check_busy, expected_state, 0); return _sdmmc_storage_execute_cmd_type1_ex(storage, resp, cmd, arg, check_busy, expected_state, 0);
} }
static int _sd_storage_send_if_cond(sdmmc_storage_t *storage) static int _sd_storage_send_if_cond(sdmmc_storage_t *storage, bool *is_sdsc)
{ {
sdmmc_cmd_t cmdbuf; sdmmc_cmd_t cmdbuf;
u16 vhd_pattern = SD_VHD_27_36 | 0xAA; u16 vhd_pattern = SD_VHD_27_36 | 0xAA;
sdmmc_init_cmd(&cmdbuf, SD_SEND_IF_COND, vhd_pattern, SDMMC_RSP_TYPE_5, 0); sdmmc_init_cmd(&cmdbuf, SD_SEND_IF_COND, vhd_pattern, SDMMC_RSP_TYPE_5, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 1; // The SD Card is version 1.X {
*is_sdsc = 1; // The SD Card is version 1.X
return 1;
}
// Card version is >= 2.0, parse results. // For Card version >= 2.0, parse results.
u32 resp = 0; u32 resp = 0;
if (!sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_5)) sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_5);
return 2; // Failed.
// Check if VHD was accepted and pattern was properly returned. // Check if VHD was accepted and pattern was properly returned.
if ((resp & 0xFFF) == vhd_pattern) if ((resp & 0xFFF) == vhd_pattern)
return 0; return 1;
// Failed. return 0;
return 2;
} }
static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, int is_version_1, int bus_uhs_support) static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, bool is_sdsc, int bus_uhs_support)
{ {
sdmmc_cmd_t cmdbuf; sdmmc_cmd_t cmdbuf;
// Support for Current > 150mA // Support for Current > 150mA
u32 arg = !is_version_1 ? SD_OCR_XPC : 0; u32 arg = !is_sdsc ? SD_OCR_XPC : 0;
// Support for handling block-addressed SDHC cards // Support for handling block-addressed SDHC cards
arg |= !is_version_1 ? SD_OCR_CCS : 0; arg |= !is_sdsc ? SD_OCR_CCS : 0;
// Support for 1.8V // Support for 1.8V
arg |= (bus_uhs_support && !is_version_1) ? SD_OCR_S18R : 0; arg |= (bus_uhs_support && !is_sdsc) ? SD_OCR_S18R : 0;
// This is needed for most cards. Do not set bit7 even if 1.8V is supported. // This is needed for most cards. Do not set bit7 even if 1.8V is supported.
arg |= SD_OCR_VDD_32_33; arg |= SD_OCR_VDD_32_33;
sdmmc_init_cmd(&cmdbuf, SD_APP_OP_COND, arg, SDMMC_RSP_TYPE_3, 0); sdmmc_init_cmd(&cmdbuf, SD_APP_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
if (!_sd_storage_execute_app_cmd(storage, R1_SKIP_STATE_CHECK, is_version_1 ? R1_ILLEGAL_COMMAND : 0, &cmdbuf, NULL, NULL)) if (!_sd_storage_execute_app_cmd(storage, R1_SKIP_STATE_CHECK, is_sdsc ? R1_ILLEGAL_COMMAND : 0, &cmdbuf, NULL, NULL))
return 0; return 0;
return sdmmc_get_rsp(storage->sdmmc, cond, 4, SDMMC_RSP_TYPE_3); return sdmmc_get_rsp(storage->sdmmc, cond, 4, SDMMC_RSP_TYPE_3);
} }
static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, int is_version_1, int bus_uhs_support) static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, bool is_sdsc, int bus_uhs_support)
{ {
u32 timeout = get_tmr_ms() + 1500; u32 timeout = get_tmr_ms() + 1500;
while (1) while (true)
{ {
u32 cond = 0; u32 cond = 0;
if (!_sd_storage_get_op_cond_once(storage, &cond, is_version_1, bus_uhs_support)) if (!_sd_storage_get_op_cond_once(storage, &cond, is_sdsc, bus_uhs_support))
break; break;
if (cond & MMC_CARD_BUSY)
// Check if power up is done.
if (cond & SD_OCR_BUSY)
{ {
DPRINTF("[SD] op cond: %08X, lv: %d\n", cond, bus_uhs_support); DPRINTF("[SD] op cond: %08X, lv: %d\n", cond, bus_uhs_support);
// Check if card is high capacity.
if (cond & SD_OCR_CCS) if (cond & SD_OCR_CCS)
storage->has_sector_access = 1; storage->has_sector_access = 1;
// Check if card supports 1.8V signaling. // Check if card supports 1.8V signaling.
if (cond & SD_ROCR_S18A && bus_uhs_support) if (cond & SD_ROCR_S18A && bus_uhs_support)
{ {
//The low voltage regulator configuration is valid for SDMMC1 only. // Switch to 1.8V signaling.
if (storage->sdmmc->id == SDMMC_1 && if (_sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY))
_sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY))
{ {
if (!sdmmc_enable_low_voltage(storage->sdmmc)) if (!sdmmc_enable_low_voltage(storage->sdmmc))
return 0; return 0;
@@ -776,7 +846,7 @@ static int _sd_storage_get_rca(sdmmc_storage_t *storage)
u32 timeout = get_tmr_ms() + 1500; u32 timeout = get_tmr_ms() + 1500;
while (1) while (true)
{ {
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
break; break;
@@ -809,8 +879,9 @@ static void _sd_storage_parse_scr(sdmmc_storage_t *storage)
storage->scr.sda_vsn = unstuff_bits(resp, 56, 4); storage->scr.sda_vsn = unstuff_bits(resp, 56, 4);
storage->scr.bus_widths = unstuff_bits(resp, 48, 4); storage->scr.bus_widths = unstuff_bits(resp, 48, 4);
/* If v2.0 is supported, check if Physical Layer Spec v3.0 is supported */
if (storage->scr.sda_vsn == SCR_SPEC_VER_2) if (storage->scr.sda_vsn == SCR_SPEC_VER_2)
/* Check if Physical Layer Spec v3.0 is supported */
storage->scr.sda_spec3 = unstuff_bits(resp, 47, 1); storage->scr.sda_spec3 = unstuff_bits(resp, 47, 1);
if (storage->scr.sda_spec3) if (storage->scr.sda_spec3)
storage->scr.cmds = unstuff_bits(resp, 32, 2); storage->scr.cmds = unstuff_bits(resp, 32, 2);
@@ -827,7 +898,7 @@ int _sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf)
reqbuf.num_sectors = 1; reqbuf.num_sectors = 1;
reqbuf.is_write = 0; reqbuf.is_write = 0;
reqbuf.is_multi_block = 0; reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0; reqbuf.is_auto_stop_trn = 0;
if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, NULL)) if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, NULL))
return 0; return 0;
@@ -859,7 +930,7 @@ int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf)
reqbuf.num_sectors = 1; reqbuf.num_sectors = 1;
reqbuf.is_write = 0; reqbuf.is_write = 0;
reqbuf.is_multi_block = 0; reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0; reqbuf.is_auto_stop_trn = 0;
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
return 0; return 0;
@@ -883,7 +954,7 @@ int _sd_storage_switch(sdmmc_storage_t *storage, void *buf, int mode, int group,
reqbuf.num_sectors = 1; reqbuf.num_sectors = 1;
reqbuf.is_write = 0; reqbuf.is_write = 0;
reqbuf.is_multi_block = 0; reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0; reqbuf.is_auto_stop_trn = 0;
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
return 0; return 0;
@@ -1064,7 +1135,7 @@ int _sd_storage_enable_hs_high_volt(sdmmc_storage_t *storage, u8 *buf)
return sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_HS25); return sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_HS25);
} }
u32 sd_storage_ssr_get_au(sdmmc_storage_t *storage) u32 sd_storage_get_ssr_au(sdmmc_storage_t *storage)
{ {
u32 au_size = storage->ssr.uhs_au_size; u32 au_size = storage->ssr.uhs_au_size;
@@ -1104,39 +1175,24 @@ u32 sd_storage_ssr_get_au(sdmmc_storage_t *storage)
static void _sd_storage_parse_ssr(sdmmc_storage_t *storage) static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
{ {
// unstuff_bits supports only 4 u32 so break into 2 x 16byte groups // unstuff_bits supports only 4 u32 so break into 2 x u32x4 groups.
u32 raw_ssr1[4]; u32 raw_ssr1[4];
u32 raw_ssr2[4]; u32 raw_ssr2[4];
raw_ssr1[3] = *(u32 *)&storage->raw_ssr[12]; memcpy(raw_ssr1, &storage->raw_ssr[0], 16);
raw_ssr1[2] = *(u32 *)&storage->raw_ssr[8]; memcpy(raw_ssr2, &storage->raw_ssr[16], 16);
raw_ssr1[1] = *(u32 *)&storage->raw_ssr[4];
raw_ssr1[0] = *(u32 *)&storage->raw_ssr[0];
raw_ssr2[3] = *(u32 *)&storage->raw_ssr[28];
raw_ssr2[2] = *(u32 *)&storage->raw_ssr[24];
raw_ssr2[1] = *(u32 *)&storage->raw_ssr[20];
raw_ssr2[0] = *(u32 *)&storage->raw_ssr[16];
storage->ssr.bus_width = (unstuff_bits(raw_ssr1, 510 - 384, 2) & SD_BUS_WIDTH_4) ? 4 : 1; storage->ssr.bus_width = (unstuff_bits(raw_ssr1, 510 - 384, 2) & SD_BUS_WIDTH_4) ? 4 : 1;
storage->ssr.protected_size = unstuff_bits(raw_ssr1, 448 - 384, 32); storage->ssr.protected_size = unstuff_bits(raw_ssr1, 448 - 384, 32);
switch(unstuff_bits(raw_ssr1, 440 - 384, 8)) u32 speed_class = unstuff_bits(raw_ssr1, 440 - 384, 8);
switch(speed_class)
{ {
case 0: case 0:
storage->ssr.speed_class = 0;
break;
case 1: case 1:
storage->ssr.speed_class = 2;
break;
case 2: case 2:
storage->ssr.speed_class = 4;
break;
case 3: case 3:
storage->ssr.speed_class = 6; storage->ssr.speed_class = speed_class << 1;
break; break;
case 4: case 4:
@@ -1144,19 +1200,18 @@ static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
break; break;
default: default:
storage->ssr.speed_class = unstuff_bits(raw_ssr1, 440 - 384, 8); storage->ssr.speed_class = speed_class;
break; break;
} }
storage->ssr.uhs_grade = unstuff_bits(raw_ssr1, 396 - 384, 4); storage->ssr.uhs_grade = unstuff_bits(raw_ssr1, 396 - 384, 4);
storage->ssr.video_class = unstuff_bits(raw_ssr1, 384 - 384, 8); storage->ssr.video_class = unstuff_bits(raw_ssr1, 384 - 384, 8);
storage->ssr.app_class = unstuff_bits(raw_ssr2, 336 - 256, 4);
storage->ssr.app_class = unstuff_bits(raw_ssr2, 336 - 256, 4); storage->ssr.au_size = unstuff_bits(raw_ssr1, 428 - 384, 4);
storage->ssr.au_size = unstuff_bits(raw_ssr1, 428 - 384, 4);
storage->ssr.uhs_au_size = unstuff_bits(raw_ssr1, 392 - 384, 4); storage->ssr.uhs_au_size = unstuff_bits(raw_ssr1, 392 - 384, 4);
} }
static int _sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf) int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
{ {
sdmmc_cmd_t cmdbuf; sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmdbuf, SD_APP_SD_STATUS, 0, SDMMC_RSP_TYPE_1, 0); sdmmc_init_cmd(&cmdbuf, SD_APP_SD_STATUS, 0, SDMMC_RSP_TYPE_1, 0);
@@ -1167,11 +1222,11 @@ static int _sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
reqbuf.num_sectors = 1; reqbuf.num_sectors = 1;
reqbuf.is_write = 0; reqbuf.is_write = 0;
reqbuf.is_multi_block = 0; reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0; reqbuf.is_auto_stop_trn = 0;
if (!(storage->csd.cmdclass & CCC_APP_SPEC)) if (!(storage->csd.cmdclass & CCC_APP_SPEC))
{ {
DPRINTF("[SD] ssr: Card lacks mandatory SD Status function\n"); DPRINTF("[SD] ssr: Not supported\n");
return 0; return 0;
} }
@@ -1180,14 +1235,16 @@ DPRINTF("[SD] ssr: Card lacks mandatory SD Status function\n");
u32 tmp = 0; u32 tmp = 0;
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1); sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
//Prepare buffer for unstuff_bits
for (int i = 0; i < 64; i+=4) // Convert buffer to LE.
for (int i = 0; i < 64; i += 4)
{ {
storage->raw_ssr[i + 3] = buf[i]; storage->raw_ssr[i + 3] = buf[i];
storage->raw_ssr[i + 2] = buf[i + 1]; storage->raw_ssr[i + 2] = buf[i + 1];
storage->raw_ssr[i + 1] = buf[i + 2]; storage->raw_ssr[i + 1] = buf[i + 2];
storage->raw_ssr[i] = buf[i + 3]; storage->raw_ssr[i] = buf[i + 3];
} }
_sd_storage_parse_ssr(storage); _sd_storage_parse_ssr(storage);
//gfx_hexdump(0, storage->raw_ssr, 64); //gfx_hexdump(0, storage->raw_ssr, 64);
@@ -1198,18 +1255,18 @@ static void _sd_storage_parse_cid(sdmmc_storage_t *storage)
{ {
u32 *raw_cid = (u32 *)&(storage->raw_cid); u32 *raw_cid = (u32 *)&(storage->raw_cid);
storage->cid.manfid = unstuff_bits(raw_cid, 120, 8); storage->cid.manfid = unstuff_bits(raw_cid, 120, 8);
storage->cid.oemid = unstuff_bits(raw_cid, 104, 16); storage->cid.oemid = unstuff_bits(raw_cid, 104, 16);
storage->cid.prod_name[0] = unstuff_bits(raw_cid, 96, 8); storage->cid.prod_name[0] = unstuff_bits(raw_cid, 96, 8);
storage->cid.prod_name[1] = unstuff_bits(raw_cid, 88, 8); storage->cid.prod_name[1] = unstuff_bits(raw_cid, 88, 8);
storage->cid.prod_name[2] = unstuff_bits(raw_cid, 80, 8); storage->cid.prod_name[2] = unstuff_bits(raw_cid, 80, 8);
storage->cid.prod_name[3] = unstuff_bits(raw_cid, 72, 8); storage->cid.prod_name[3] = unstuff_bits(raw_cid, 72, 8);
storage->cid.prod_name[4] = unstuff_bits(raw_cid, 64, 8); storage->cid.prod_name[4] = unstuff_bits(raw_cid, 64, 8);
storage->cid.hwrev = unstuff_bits(raw_cid, 60, 4); storage->cid.hwrev = unstuff_bits(raw_cid, 60, 4);
storage->cid.fwrev = unstuff_bits(raw_cid, 56, 4); storage->cid.fwrev = unstuff_bits(raw_cid, 56, 4);
storage->cid.serial = unstuff_bits(raw_cid, 24, 32); storage->cid.serial = unstuff_bits(raw_cid, 24, 32);
storage->cid.month = unstuff_bits(raw_cid, 8, 4); storage->cid.year = unstuff_bits(raw_cid, 12, 8) + 2000;
storage->cid.year = unstuff_bits(raw_cid, 12, 8) + 2000; storage->cid.month = unstuff_bits(raw_cid, 8, 4);
} }
static void _sd_storage_parse_csd(sdmmc_storage_t *storage) static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
@@ -1224,6 +1281,7 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
{ {
case 0: case 0:
storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2); storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2);
storage->csd.capacity <<= unstuff_bits(raw_csd, 80, 4) - 9; // Convert native block size to LBA 512B.
break; break;
case 1: case 1:
@@ -1231,7 +1289,13 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
storage->csd.capacity = storage->csd.c_size << 10; storage->csd.capacity = storage->csd.c_size << 10;
storage->csd.read_blkbits = 9; storage->csd.read_blkbits = 9;
break; break;
default:
DPRINTF("[SD] unknown CSD structure %d\n", storage->csd.structure);
break;
} }
storage->sec_cnt = storage->csd.capacity;
} }
static bool _sdmmc_storage_get_bus_uhs_support(u32 bus_width, u32 type) static bool _sdmmc_storage_get_bus_uhs_support(u32 bus_width, u32 type)
@@ -1261,8 +1325,10 @@ 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 is_version_1 = 0; u32 tmp = 0;
u8 *buf = (u8 *)SDMMC_UPPER_BUFFER; int is_sdsc = 0;
u8 *buf = (u8 *)SDMMC_UPPER_BUFFER;
bool bus_uhs_support = _sdmmc_storage_get_bus_uhs_support(bus_width, type);
DPRINTF("[SD] init: bus: %d, type: %d\n", bus_width, type); DPRINTF("[SD] init: bus: %d, type: %d\n", bus_width, type);
@@ -1282,18 +1348,15 @@ DPRINTF("[SD] after init\n");
return 0; return 0;
DPRINTF("[SD] went to idle state\n"); DPRINTF("[SD] went to idle state\n");
is_version_1 = _sd_storage_send_if_cond(storage); if (!_sd_storage_send_if_cond(storage, &is_sdsc))
if (is_version_1 == 2) // Failed.
return 0; return 0;
DPRINTF("[SD] after send if cond\n"); DPRINTF("[SD] after send if cond\n");
bool bus_uhs_support = _sdmmc_storage_get_bus_uhs_support(bus_width, type); if (!_sd_storage_get_op_cond(storage, is_sdsc, bus_uhs_support))
if (!_sd_storage_get_op_cond(storage, is_version_1, bus_uhs_support))
return 0; return 0;
DPRINTF("[SD] got op cond\n"); DPRINTF("[SD] got op cond\n");
if (!_sdmmc_storage_get_cid(storage, storage->raw_cid)) if (!_sdmmc_storage_get_cid(storage))
return 0; return 0;
DPRINTF("[SD] got cid\n"); DPRINTF("[SD] got cid\n");
_sd_storage_parse_cid(storage); _sd_storage_parse_cid(storage);
@@ -1302,30 +1365,16 @@ DPRINTF("[SD] got cid\n");
return 0; return 0;
DPRINTF("[SD] got rca (= %04X)\n", storage->rca); DPRINTF("[SD] got rca (= %04X)\n", storage->rca);
if (!_sdmmc_storage_get_csd(storage, storage->raw_csd)) if (!_sdmmc_storage_get_csd(storage))
return 0; return 0;
DPRINTF("[SD] got csd\n"); DPRINTF("[SD] got csd\n");
//Parse CSD.
_sd_storage_parse_csd(storage); _sd_storage_parse_csd(storage);
switch (storage->csd.structure)
{
case 0:
storage->sec_cnt = storage->csd.capacity;
break;
case 1:
storage->sec_cnt = storage->csd.c_size << 10;
break;
default:
DPRINTF("[SD] unknown CSD structure %d\n", storage->csd.structure);
break;
}
if (!storage->is_low_voltage) if (!storage->is_low_voltage)
{ {
if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_DS12)) if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_DS12))
return 0; return 0;
DPRINTF("[SD] after setup clock\n"); DPRINTF("[SD] after setup default clock\n");
} }
if (!_sdmmc_storage_select_card(storage)) if (!_sdmmc_storage_select_card(storage))
@@ -1336,19 +1385,17 @@ DPRINTF("[SD] card selected\n");
return 0; return 0;
DPRINTF("[SD] set blocklen to 512\n"); DPRINTF("[SD] set blocklen to 512\n");
u32 tmp = 0; // Disconnect Card Detect resistor from DAT3.
if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_CLR_CARD_DETECT, 0, 0, R1_STATE_TRAN)) if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_CLR_CARD_DETECT, 0, 0, R1_STATE_TRAN))
return 0; return 0;
DPRINTF("[SD] cleared card detect\n"); DPRINTF("[SD] cleared card detect\n");
if (!_sd_storage_get_scr(storage, buf)) if (!_sd_storage_get_scr(storage, buf))
return 0; return 0;
//gfx_hexdump(0, storage->raw_scr, 8);
DPRINTF("[SD] got scr\n"); DPRINTF("[SD] got scr\n");
// Check if card supports a wider bus and if it's not SD Version 1.X // If card supports a wider bus and if it's not SD Version 1.0 switch bus width.
if (bus_width == SDMMC_BUS_WIDTH_4 && (storage->scr.bus_widths & 4) && (storage->scr.sda_vsn & 0xF)) if (bus_width == SDMMC_BUS_WIDTH_4 && (storage->scr.bus_widths & BIT(SD_BUS_WIDTH_4)) && storage->scr.sda_vsn)
{ {
if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_BUS_WIDTH, SD_BUS_WIDTH_4, 0, R1_STATE_TRAN)) if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_BUS_WIDTH, SD_BUS_WIDTH_4, 0, R1_STATE_TRAN))
return 0; return 0;
@@ -1367,10 +1414,8 @@ 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 & 0xF)) // Not default speed and not SD Version 1.x else if (type != SDHCI_TIMING_SD_DS12 && storage->scr.sda_vsn) // Not default speed and not SD Version 1.0.
{ {
if (!_sd_storage_enable_hs_high_volt(storage, buf)) if (!_sd_storage_enable_hs_high_volt(storage, buf))
return 0; return 0;
@@ -1389,25 +1434,27 @@ DPRINTF("[SD] enabled HS\n");
} }
// Parse additional card info from sd status. // Parse additional card info from sd status.
if (_sd_storage_get_ssr(storage, buf)) if (sd_storage_get_ssr(storage, buf))
{ {
DPRINTF("[SD] got sd status\n"); DPRINTF("[SD] got sd status\n");
} }
sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE);
storage->initialized = 1; storage->initialized = 1;
return 1; return 1;
} }
/* /*
* Gamecard specific functions. * Gamecard specific functions.
*/ */
int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf) int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf)
{ {
u32 resp; u32 resp;
sdmmc_cmd_t cmdbuf; sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmdbuf, 60, 0, SDMMC_RSP_TYPE_1, 1); sdmmc_init_cmd(&cmdbuf, MMC_VENDOR_60_CMD, 0, SDMMC_RSP_TYPE_1, 1);
sdmmc_req_t reqbuf; sdmmc_req_t reqbuf;
reqbuf.buf = buf; reqbuf.buf = buf;
@@ -1415,7 +1462,7 @@ int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf)
reqbuf.num_sectors = 1; reqbuf.num_sectors = 1;
reqbuf.is_write = 1; reqbuf.is_write = 1;
reqbuf.is_multi_block = 0; reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0; reqbuf.is_auto_stop_trn = 0;
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
{ {

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,18 +30,93 @@ typedef enum _sdmmc_type
EMMC_GPP = 0, EMMC_GPP = 0,
EMMC_BOOT0 = 1, EMMC_BOOT0 = 1,
EMMC_BOOT1 = 2 EMMC_BOOT1 = 2,
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;
u8 prod_name[8]; u8 prod_name[8];
u8 card_bga;
u8 prv;
u32 serial; u32 serial;
u16 oemid; u16 oemid;
u16 year; u16 year;
u8 prv;
u8 hwrev; u8 hwrev;
u8 fwrev; u8 fwrev;
u8 month; u8 month;
@@ -65,19 +140,20 @@ typedef struct _mmc_csd
typedef struct _mmc_ext_csd typedef struct _mmc_ext_csd
{ {
u32 sectors; //u8 bkops; /* background support bit */
int bkops; /* background support bit */ //u8 bkops_en; /* manual bkops enable bit */
int bkops_en; /* manual bkops enable bit */ //u8 bkops_status; /* 246 */
u8 rev; u8 rev;
u8 ext_struct; /* 194 */ u8 ext_struct; /* 194 */
u8 card_type; /* 196 */ u8 card_type; /* 196 */
u8 bkops_status; /* 246 */
u8 pre_eol_info; u8 pre_eol_info;
u8 dev_life_est_a; u8 dev_life_est_a;
u8 dev_life_est_b; u8 dev_life_est_b;
u8 boot_mult; u8 boot_mult;
u8 rpmb_mult; u8 rpmb_mult;
u16 dev_version; u16 dev_version;
u32 cache_size;
u32 max_enh_mult;
} mmc_ext_csd_t; } mmc_ext_csd_t;
typedef struct _sd_scr typedef struct _sd_scr
@@ -90,13 +166,13 @@ typedef struct _sd_scr
typedef struct _sd_ssr typedef struct _sd_ssr
{ {
u8 bus_width; u8 bus_width;
u8 speed_class; u8 speed_class;
u8 uhs_grade; u8 uhs_grade;
u8 video_class; u8 video_class;
u8 app_class; u8 app_class;
u8 au_size; u8 au_size;
u8 uhs_au_size; u8 uhs_au_size;
u32 protected_size; u32 protected_size;
} sd_ssr_t; } sd_ssr_t;
@@ -130,6 +206,10 @@ 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);
u32 sd_storage_ssr_get_au(sdmmc_storage_t *storage); 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);
u32 sd_storage_get_ssr_au(sdmmc_storage_t *storage);
#endif #endif

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,
@@ -934,12 +934,20 @@ static int _sdmmc_config_dma(sdmmc_t *sdmmc, u32 *blkcnt_out, sdmmc_req_t *req)
*blkcnt_out = blkcnt; *blkcnt_out = blkcnt;
u32 trnmode = SDHCI_TRNS_DMA; u32 trnmode = SDHCI_TRNS_DMA;
// Set mulitblock request.
if (req->is_multi_block) if (req->is_multi_block)
trnmode = SDHCI_TRNS_MULTI | SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_DMA; trnmode = SDHCI_TRNS_MULTI | SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_DMA;
// Set request direction.
if (!req->is_write) if (!req->is_write)
trnmode |= SDHCI_TRNS_READ; trnmode |= SDHCI_TRNS_READ;
if (req->is_auto_cmd12)
trnmode = (trnmode & ~(SDHCI_TRNS_AUTO_CMD12 | SDHCI_TRNS_AUTO_CMD23)) | SDHCI_TRNS_AUTO_CMD12; // Automatic send of stop transmission or set block count cmd.
if (req->is_auto_stop_trn)
trnmode |= SDHCI_TRNS_AUTO_CMD12;
//else if (req->is_auto_set_blkcnt)
// trnmode |= SDHCI_TRNS_AUTO_CMD23;
sdmmc->regs->trnmod = trnmode; sdmmc->regs->trnmod = trnmode;
@@ -1025,12 +1033,10 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
} }
int result = _sdmmc_wait_response(sdmmc); int result = _sdmmc_wait_response(sdmmc);
if (!result)
{
#ifdef ERROR_EXTRA_PRINTING #ifdef ERROR_EXTRA_PRINTING
if (!result)
EPRINTF("SDMMC: Transfer timeout!"); EPRINTF("SDMMC: Transfer timeout!");
#endif #endif
}
DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result, DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result,
sdmmc->regs->rspreg0, sdmmc->regs->rspreg1, sdmmc->regs->rspreg2, sdmmc->regs->rspreg3); sdmmc->regs->rspreg0, sdmmc->regs->rspreg1, sdmmc->regs->rspreg2, sdmmc->regs->rspreg3);
if (result) if (result)
@@ -1039,22 +1045,18 @@ DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result,
{ {
sdmmc->expected_rsp_type = cmd->rsp_type; sdmmc->expected_rsp_type = cmd->rsp_type;
result = _sdmmc_cache_rsp(sdmmc, sdmmc->rsp, 0x10, cmd->rsp_type); result = _sdmmc_cache_rsp(sdmmc, sdmmc->rsp, 0x10, cmd->rsp_type);
if (!result)
{
#ifdef ERROR_EXTRA_PRINTING #ifdef ERROR_EXTRA_PRINTING
if (!result)
EPRINTF("SDMMC: Unknown response type!"); EPRINTF("SDMMC: Unknown response type!");
#endif #endif
}
} }
if (req && result) if (req && result)
{ {
result = _sdmmc_update_dma(sdmmc); result = _sdmmc_update_dma(sdmmc);
if (!result)
{
#ifdef ERROR_EXTRA_PRINTING #ifdef ERROR_EXTRA_PRINTING
if (!result)
EPRINTF("SDMMC: DMA Update failed!"); EPRINTF("SDMMC: DMA Update failed!");
#endif #endif
}
} }
} }
@@ -1070,19 +1072,17 @@ DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result,
if (blkcnt_out) if (blkcnt_out)
*blkcnt_out = blkcnt; *blkcnt_out = blkcnt;
if (req->is_auto_cmd12) if (req->is_auto_stop_trn)
sdmmc->rsp3 = sdmmc->regs->rspreg3; sdmmc->rsp3 = sdmmc->regs->rspreg3;
} }
if (cmd->check_busy || req) if (cmd->check_busy || req)
{ {
result = _sdmmc_wait_card_busy(sdmmc); result = _sdmmc_wait_card_busy(sdmmc);
if (!result)
{
#ifdef ERROR_EXTRA_PRINTING #ifdef ERROR_EXTRA_PRINTING
if (!result)
EPRINTF("SDMMC: Busy timeout!"); EPRINTF("SDMMC: Busy timeout!");
#endif #endif
}
return result; return result;
} }
} }
@@ -1371,12 +1371,12 @@ void sdmmc_end(sdmmc_t *sdmmc)
_sdmmc_sd_clock_disable(sdmmc); _sdmmc_sd_clock_disable(sdmmc);
// Disable SDMMC power. // Disable SDMMC power.
_sdmmc_set_io_power(sdmmc, SDMMC_POWER_OFF); _sdmmc_set_io_power(sdmmc, SDMMC_POWER_OFF);
_sdmmc_commit_changes(sdmmc);
// Disable SD card power. // Disable SD card power.
if (sdmmc->id == SDMMC_1) if (sdmmc->id == SDMMC_1)
sdmmc1_disable_power(); sdmmc1_disable_power();
_sdmmc_commit_changes(sdmmc);
clock_sdmmc_disable(sdmmc->id); clock_sdmmc_disable(sdmmc->id);
sdmmc->clock_stopped = 1; sdmmc->clock_stopped = 1;
} }

View File

@@ -242,7 +242,7 @@ typedef struct _sdmmc_req_t
u32 num_sectors; u32 num_sectors;
int is_write; int is_write;
int is_multi_block; int is_multi_block;
int is_auto_cmd12; int is_auto_stop_trn;
} sdmmc_req_t; } sdmmc_req_t;
int sdmmc_get_io_power(sdmmc_t *sdmmc); int sdmmc_get_io_power(sdmmc_t *sdmmc);

View File

@@ -1,7 +1,7 @@
/* /*
* Fan driver for Nintendo Switch * Fan driver for Nintendo Switch
* *
* 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,
@@ -18,6 +18,7 @@
#include <thermal/fan.h> #include <thermal/fan.h>
#include <power/regulator_5v.h> #include <power/regulator_5v.h>
#include <soc/fuse.h>
#include <soc/gpio.h> #include <soc/gpio.h>
#include <soc/pinmux.h> #include <soc/pinmux.h>
#include <soc/t210.h> #include <soc/t210.h>
@@ -26,11 +27,22 @@
void set_fan_duty(u32 duty) void set_fan_duty(u32 duty)
{ {
static bool fan_init = false; static bool fan_init = false;
static u16 curr_duty = -1; static u16 curr_duty = -1;
if (duty > 236)
duty = 236;
if (curr_duty == duty) if (curr_duty == duty)
return; return;
curr_duty = duty;
//! TODO: Add HOAG/AULA support.
u32 hw_type = fuse_read_hw_type();
if (hw_type != FUSE_NX_HW_TYPE_ICOSA &&
hw_type != FUSE_NX_HW_TYPE_IOWA)
return;
if (!fan_init) if (!fan_init)
{ {
// Fan tachometer. // Fan tachometer.
@@ -46,9 +58,6 @@ void set_fan_duty(u32 duty)
fan_init = true; fan_init = true;
} }
if (duty > 236)
duty = 236;
// Inverted polarity. // Inverted polarity.
u32 inv_duty = 236 - duty; u32 inv_duty = 236 - duty;
@@ -71,23 +80,20 @@ void set_fan_duty(u32 duty)
// Enable fan. // Enable fan.
PINMUX_AUX(PINMUX_AUX_LCD_GPIO2) = 1; // Set source to PWM1. PINMUX_AUX(PINMUX_AUX_LCD_GPIO2) = 1; // Set source to PWM1.
} }
curr_duty = duty;
} }
void get_fan_speed(u32 *duty, u32 *rpm) void get_fan_speed(u32 *duty, u32 *rpm)
{ {
if (rpm) if (rpm)
{ {
u32 irq_count = 1; u32 irq_count = 0;
bool should_read = true; bool should_read = true;
bool irq_val = 0;
// Poll irqs for 2 seconds. // Poll irqs for 2 seconds. (5 seconds for accurate count).
int timer = get_tmr_us() + 1000000; int timer = get_tmr_us() + 2000000;
while (timer - get_tmr_us()) while ((timer - get_tmr_us()) > 0)
{ {
irq_val = gpio_read(GPIO_PORT_S, GPIO_PIN_7); bool irq_val = gpio_read(GPIO_PORT_S, GPIO_PIN_7);
if (irq_val && should_read) if (irq_val && should_read)
{ {
irq_count++; irq_count++;
@@ -97,8 +103,11 @@ void get_fan_speed(u32 *duty, u32 *rpm)
should_read = true; should_read = true;
} }
// Halve the irq count.
irq_count /= 2;
// Calculate rpm based on triggered interrupts. // Calculate rpm based on triggered interrupts.
*rpm = 60000000 / ((1000000 * 2) / irq_count); *rpm = irq_count * (60 / 2);
} }
if (duty) if (duty)

View File

@@ -1,7 +1,7 @@
/* /*
* SOC/PCB Temperature driver for Nintendo Switch's TI TMP451 * SOC/PCB Temperature driver for Nintendo Switch's TI TMP451
* *
* Copyright (c) 2018 CTCaer * Copyright (c) 2018-2020 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,7 +16,9 @@
* 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 <soc/hw_init.h>
#include <soc/i2c.h> #include <soc/i2c.h>
#include <soc/t210.h>
#include <thermal/tmp451.h> #include <thermal/tmp451.h>
u16 tmp451_get_soc_temp(bool intenger) u16 tmp451_get_soc_temp(bool intenger)
@@ -56,6 +58,20 @@ void tmp451_init()
// Disable ALARM and Range to 0 - 127 oC. // Disable ALARM and Range to 0 - 127 oC.
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CONFIG_REG, 0x80); i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CONFIG_REG, 0x80);
// Set remote sensor offsets based on SoC.
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210)
{
// Set offset to 0 oC for Erista.
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TMP_OFH_REG, 0);
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TMP_OFL_REG, 0);
}
else
{
// Set offset to -12.5 oC for Mariko.
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TMP_OFH_REG, 0xF3); // - 13 oC.
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TMP_OFL_REG, 0x80); // + 0.5 oC.
}
// Set conversion rate to 32/s and make a read to update the reg. // Set conversion rate to 32/s and make a read to update the reg.
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CNV_RATE_REG, 9); i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CNV_RATE_REG, 9);
tmp451_get_soc_temp(false); tmp451_get_soc_temp(false);
@@ -63,3 +79,9 @@ void tmp451_init()
// Set rate to every 4 seconds. // Set rate to every 4 seconds.
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CNV_RATE_REG, 2); i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CNV_RATE_REG, 2);
} }
void tmp451_end()
{
// Place into shutdown mode to conserve power.
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CONFIG_REG, 0xC0);
}

View File

@@ -32,11 +32,15 @@
#define TMP451_SOC_TMP_DEC_REG 0x10 #define TMP451_SOC_TMP_DEC_REG 0x10
#define TMP451_PCB_TMP_DEC_REG 0x15 #define TMP451_PCB_TMP_DEC_REG 0x15
#define TMP451_SOC_TMP_OFH_REG 0x11
#define TMP451_SOC_TMP_OFL_REG 0x12
// If input is false, the return value is packed. MSByte is the integer in oC // If input is false, the return value is packed. MSByte is the integer in oC
// and the LSByte is the decimal point truncated to 2 decimal places. // and the LSByte is the decimal point truncated to 2 decimal places.
// Otherwise it's an integer oC. // Otherwise it's an integer oC.
u16 tmp451_get_soc_temp(bool integer); u16 tmp451_get_soc_temp(bool integer);
u16 tmp451_get_pcb_temp(bool integer); u16 tmp451_get_pcb_temp(bool integer);
void tmp451_init(); void tmp451_init();
void tmp451_end();
#endif /* __TMP451_H_ */ #endif /* __TMP451_H_ */

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))
@@ -203,7 +203,7 @@ typedef struct _bulk_ctxt_t {
typedef struct _usbd_gadget_ums_t { typedef struct _usbd_gadget_ums_t {
bulk_ctxt_t bulk_ctxt; bulk_ctxt_t bulk_ctxt;
int cmnd_size; u32 cmnd_size;
u8 cmnd[SCSI_MAX_CMD_SZ]; u8 cmnd[SCSI_MAX_CMD_SZ];
u32 lun_idx; // lun index u32 lun_idx; // lun index
@@ -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,34 +574,33 @@ 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)
{ {
// Limit write to max supported read from EP OUT. // Limit write to max supported read from EP OUT.
amount = MIN(amount_left_to_req, UMS_EP_OUT_MAX_XFER); amount = MIN(amount_left_to_req, UMS_EP_OUT_MAX_XFER);
if (usb_lba_offset >= ums->lun.num_sectors) //////////Check if it works with concurrency if (usb_lba_offset >= ums->lun.num_sectors)
{ {
ums->set_text(ums->label, "#FFDD00 Error:# Write - Past last sector!"); ums->set_text(ums->label, "#FFDD00 Error:# Write - Past last sector!");
amount_left_to_req = 0;
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
ums->lun.sense_data_info = usb_lba_offset; ums->lun.sense_data_info = usb_lba_offset;
ums->lun.info_valid = 1; ums->lun.info_valid = 1;
continue; break;
} }
// Get the next buffer. // Get the next buffer.
@@ -640,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;
@@ -656,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!");
@@ -686,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;
@@ -1007,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
@@ -1089,8 +1092,7 @@ static int _scsi_prevent_allow_removal(usbd_gadget_ums_t *ums)
// Notify for possible unmounting? // Notify for possible unmounting?
// Normally we sync here but we do synced writes to SDMMC. // Normally we sync here but we do synced writes to SDMMC.
if (ums->lun.prevent_medium_removal && !prevent) if (ums->lun.prevent_medium_removal && !prevent) { /* Do nothing */ }
;
ums->lun.prevent_medium_removal = prevent; ums->lun.prevent_medium_removal = prevent;
@@ -1114,7 +1116,7 @@ static int _scsi_read_format_capacities(usbd_gadget_ums_t *ums, bulk_ctxt_t *bul
// Check whether the command is properly formed and whether its data size // Check whether the command is properly formed and whether its data size
// and direction agree with the values we already have. // and direction agree with the values we already have.
static int _ums_check_scsi_cmd(usbd_gadget_ums_t *ums, int cmnd_size, static int _ums_check_scsi_cmd(usbd_gadget_ums_t *ums, u32 cmnd_size,
enum data_direction data_dir, u32 mask, int needs_medium) enum data_direction data_dir, u32 mask, int needs_medium)
{ {
//const char dirletter[4] = {'u', 'o', 'i', 'n'}; //const char dirletter[4] = {'u', 'o', 'i', 'n'};
@@ -1540,12 +1542,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 ||
@@ -1576,6 +1578,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)
@@ -1586,29 +1590,34 @@ 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)
{ {
gfx_printf("USB: non-meaningful CBW: lun = %X, flags = 0x%X, cmdlen %X\n", gfx_printf("USB: non-meaningful CBW: lun = %X, flags = 0x%X, cmdlen %X\n",
cbw->Lun, cbw->Flags, cbw->Length); cbw->Lun, cbw->Flags, cbw->Length);
@@ -1625,7 +1634,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);
@@ -1660,8 +1669,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
@@ -1698,7 +1719,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;
@@ -1714,7 +1735,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);
@@ -1737,7 +1758,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:
@@ -1759,7 +1780,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:
@@ -1837,6 +1858,7 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
// Initialize sdmmc. // Initialize sdmmc.
if (usbs->type == MMC_SD) if (usbs->type == MMC_SD)
{ {
sd_end();
sd_mount(); sd_mount();
sd_unmount(); sd_unmount();
ums.lun.sdmmc = &sd_sdmmc; ums.lun.sdmmc = &sd_sdmmc;
@@ -1907,7 +1929,10 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
send_status(&ums, &ums.bulk_ctxt); send_status(&ums, &ums.bulk_ctxt);
} while (ums.state != UMS_STATE_TERMINATED); } while (ums.state != UMS_STATE_TERMINATED);
ums.set_text(ums.label, "#C7EA46 Status:# Disk ejected"); if (ums.lun.prevent_medium_removal)
ums.set_text(ums.label, "#FFDD00 Error:# Disk unsafely ejected");
else
ums.set_text(ums.label, "#C7EA46 Status:# Disk ejected");
goto exit; goto exit;
error: error:

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

@@ -29,7 +29,7 @@ u8 btn_read()
res |= BTN_VOL_DOWN; res |= BTN_VOL_DOWN;
if (!gpio_read(GPIO_PORT_X, GPIO_PIN_6)) if (!gpio_read(GPIO_PORT_X, GPIO_PIN_6))
res |= BTN_VOL_UP; res |= BTN_VOL_UP;
if (i2c_recv_byte(4, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFSTAT) & 0x4) if (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFSTAT) & MAX77620_ONOFFSTAT_EN0)
res |= BTN_POWER; res |= BTN_POWER;
return res; return res;
} }

View File

@@ -21,16 +21,16 @@
#include <mem/heap.h> #include <mem/heap.h>
#include <utils/types.h> #include <utils/types.h>
#define MAX_ENTRIES 64
char *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles, bool parse_dirs) char *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles, bool parse_dirs)
{ {
u8 max_entries = 61;
int res = 0; int res = 0;
u32 i = 0, j = 0, k = 0; u32 i = 0, j = 0, k = 0;
DIR dir; DIR dir;
FILINFO fno; FILINFO fno;
char *dir_entries = (char *)calloc(max_entries, 256); char *dir_entries = (char *)calloc(MAX_ENTRIES, 256);
char *temp = (char *)calloc(1, 256); char *temp = (char *)calloc(1, 256);
if (!pattern && !f_opendir(&dir, directory)) if (!pattern && !f_opendir(&dir, directory))
@@ -49,7 +49,7 @@ char *dirlist(const char *directory, const char *pattern, bool includeHiddenFile
{ {
strcpy(dir_entries + (k * 256), fno.fname); strcpy(dir_entries + (k * 256), fno.fname);
k++; k++;
if (k > (max_entries - 1)) if (k > (MAX_ENTRIES - 1))
break; break;
} }
} }
@@ -64,7 +64,7 @@ char *dirlist(const char *directory, const char *pattern, bool includeHiddenFile
{ {
strcpy(dir_entries + (k * 256), fno.fname); strcpy(dir_entries + (k * 256), fno.fname);
k++; k++;
if (k > (max_entries - 1)) if (k > (MAX_ENTRIES - 1))
break; break;
} }
res = f_findnext(&dir, &fno); res = f_findnext(&dir, &fno);

View File

@@ -56,7 +56,7 @@ static u32 _putn(char *buffer, u32 v, int base, char fill, int fcnt) {
return _puts(buffer, p); return _puts(buffer, p);
} }
u32 sprintf(char *buffer, const char *fmt, ...) { u32 s_printf(char *buffer, const char *fmt, ...) {
va_list ap; va_list ap;
int fill, fcnt; int fill, fcnt;
u32 count = 0; u32 count = 0;

View File

@@ -19,6 +19,6 @@
#include "types.h" #include "types.h"
u32 sprintf(char *buffer, const char *fmt, ...); u32 s_printf(char *buffer, const char *fmt, ...);
#endif #endif

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,
@@ -17,23 +18,11 @@
#ifndef _TYPES_H_ #ifndef _TYPES_H_
#define _TYPES_H_ #define _TYPES_H_
#define NULL ((void *)0) #include <assert.h>
#define ALWAYS_INLINE inline __attribute__((always_inline)) #define ALWAYS_INLINE inline __attribute__((always_inline))
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
#define ALIGN_DOWN(x, a) (((x) - ((a) - 1)) & ~((a) - 1))
#define BIT(n) (1U << (n))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define DIV_ROUND_UP(a, b) ((a + b - 1) / b)
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
#define LOG2(n) (32 - __builtin_clz(n) - 1) #define LOG2(n) (32 - __builtin_clz(n) - 1)
#define OFFSET_OF(t, m) ((u32)&((t *)NULL)->m)
#define CONTAINER_OF(mp, t, mn) ((t *)((u32)mp - OFFSET_OF(t, mn)))
#define COLOR_RED 0xFFE70000 #define COLOR_RED 0xFFE70000
#define COLOR_ORANGE 0xFFFF8C00 #define COLOR_ORANGE 0xFFFF8C00
#define COLOR_YELLOW 0xFFFFFF40 #define COLOR_YELLOW 0xFFFFFF40
@@ -41,13 +30,16 @@
#define COLOR_BLUE 0xFF00DDFF #define COLOR_BLUE 0xFF00DDFF
#define COLOR_VIOLET 0xFF8040FF #define COLOR_VIOLET 0xFF8040FF
/* Types */
typedef signed char s8; typedef signed char s8;
typedef short s16; typedef short s16;
typedef short SHORT; typedef short SHORT;
typedef int s32; typedef int s32;
typedef int INT; typedef int INT;
typedef int bool;
typedef long LONG; typedef long LONG;
typedef long long int s64; typedef long long int s64;
typedef unsigned char u8; typedef unsigned char u8;
typedef unsigned char BYTE; typedef unsigned char BYTE;
typedef unsigned short u16; typedef unsigned short u16;
@@ -58,6 +50,7 @@ typedef unsigned int UINT;
typedef unsigned long DWORD; typedef unsigned long DWORD;
typedef unsigned long long QWORD; typedef unsigned long long QWORD;
typedef unsigned long long int u64; typedef unsigned long long int u64;
typedef volatile unsigned char vu8; typedef volatile unsigned char vu8;
typedef volatile unsigned short vu16; typedef volatile unsigned short vu16;
typedef volatile unsigned int vu32; typedef volatile unsigned int vu32;
@@ -70,13 +63,60 @@ typedef u32 uptr;
static const u32 colors[6] = {COLOR_RED, COLOR_ORANGE, COLOR_YELLOW, COLOR_GREEN, COLOR_BLUE, COLOR_VIOLET}; static const u32 colors[6] = {COLOR_RED, COLOR_ORANGE, COLOR_YELLOW, COLOR_GREEN, COLOR_BLUE, COLOR_VIOLET};
typedef int bool; /* Important */
#define true 1
#define false 0 #define false 0
#define true 1
#define NULL ((void *)0)
/* Misc */
#define DISABLE 0 #define DISABLE 0
#define ENABLE 1 #define ENABLE 1
/* Sizes */
#define SZ_1K 0x400
#define SZ_2K 0x800
#define SZ_4K 0x1000
#define SZ_8K 0x2000
#define SZ_16K 0x4000
#define SZ_32K 0x8000
#define SZ_64K 0x10000
#define SZ_128K 0x20000
#define SZ_256K 0x40000
#define SZ_512K 0x80000
#define SZ_1M 0x100000
#define SZ_2M 0x200000
#define SZ_4M 0x400000
#define SZ_8M 0x800000
#define SZ_16M 0x1000000
#define SZ_32M 0x2000000
#define SZ_64M 0x4000000
#define SZ_128M 0x8000000
#define SZ_256M 0x10000000
#define SZ_512M 0x20000000
#define SZ_1G 0x40000000
#define SZ_2G 0x80000000
#define SZ_PAGE SZ_4K
/* Macros */
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
#define ALIGN_DOWN(x, a) ((x) & ~((a) - 1))
#define BIT(n) (1U << (n))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define DIV_ROUND_UP(a, b) ((a + b - 1) / b)
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
#define OFFSET_OF(t, m) ((uptr)&((t *)NULL)->m)
#define CONTAINER_OF(mp, t, mn) ((t *)((uptr)mp - OFFSET_OF(t, mn)))
#define byte_swap_16(num) ((((num) >> 8) & 0xff) | (((num) << 8) & 0xff00))
#define byte_swap_32(num) ((((num) >> 24) & 0xff) | (((num) << 8) & 0xff0000) | \
(((num) >> 8 )& 0xff00) | (((num) << 24) & 0xff000000))
/* Bootloader/Nyx */
#define BOOT_CFG_AUTOBOOT_EN BIT(0) #define BOOT_CFG_AUTOBOOT_EN BIT(0)
#define BOOT_CFG_FROM_LAUNCH BIT(1) #define BOOT_CFG_FROM_LAUNCH BIT(1)
#define BOOT_CFG_FROM_ID BIT(2) #define BOOT_CFG_FROM_ID BIT(2)
@@ -85,6 +125,24 @@ typedef int bool;
#define EXTRA_CFG_DUMP_EMUMMC BIT(0) #define EXTRA_CFG_DUMP_EMUMMC BIT(0)
#define EXTRA_CFG_KEYS BIT(0)
#define EXTRA_CFG_PAYLOAD BIT(1)
#define EXTRA_CFG_MODULE BIT(2)
#define EXTRA_CFG_NYX_UMS BIT(5)
#define EXTRA_CFG_NYX_RELOAD BIT(6)
typedef enum _nyx_ums_type
{
NYX_UMS_SD_CARD = 0,
NYX_UMS_EMMC_BOOT0,
NYX_UMS_EMMC_BOOT1,
NYX_UMS_EMMC_GPP,
NYX_UMS_EMUMMC_BOOT0,
NYX_UMS_EMUMMC_BOOT1,
NYX_UMS_EMUMMC_GPP
} nyx_ums_type;
typedef struct __attribute__((__packed__)) _boot_cfg_t typedef struct __attribute__((__packed__)) _boot_cfg_t
{ {
u8 boot_cfg; u8 boot_cfg;
@@ -103,6 +161,16 @@ typedef struct __attribute__((__packed__)) _boot_cfg_t
}; };
} boot_cfg_t; } boot_cfg_t;
static_assert(sizeof(boot_cfg_t) == 0x84, "Boot cfg storage size is wrong!");
typedef struct __attribute__((__packed__)) _ipl_ver_meta_t
{
u32 magic;
u32 version;
u16 rsvd0;
u16 rsvd1;
} ipl_ver_meta_t;
typedef struct __attribute__((__packed__)) _reloc_meta_t typedef struct __attribute__((__packed__)) _reloc_meta_t
{ {
u32 start; u32 start;

View File

@@ -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);
@@ -167,10 +188,10 @@ void power_set_state(power_state_t state)
default: default:
// Enable/Disable soft reset wake event. // Enable/Disable soft reset wake event.
reg = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2); reg = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2);
if (state == POWER_OFF_RESET) if (state == POWER_OFF_RESET) // Do not wake up after power off.
reg &= ~MAX77620_ONOFFCNFG2_SFT_RST_WK; // Do not wake up after power off. reg &= ~(MAX77620_ONOFFCNFG2_SFT_RST_WK | MAX77620_ONOFFCNFG2_WK_ALARM1 | MAX77620_ONOFFCNFG2_WK_ALARM2);
else // POWER_OFF_REBOOT. else // POWER_OFF_REBOOT. Wake up after power off.
reg |= MAX77620_ONOFFCNFG2_SFT_RST_WK; // Wake up after power off. reg |= MAX77620_ONOFFCNFG2_SFT_RST_WK;
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2, reg); i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2, reg);
// Initiate power down sequence and generate a reset (regulators' state resets). // Initiate power down sequence and generate a reset (regulators' state resets).

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,
@@ -38,6 +38,7 @@ typedef enum
NYX_CFG_BIS = BIT(5), NYX_CFG_BIS = BIT(5),
NYX_CFG_UMS = BIT(6), NYX_CFG_UMS = BIT(6),
NYX_CFG_DUMP = BIT(7), NYX_CFG_DUMP = BIT(7),
NYX_CFG_EXTRA = 0xFF << 24
} nyx_cfg_t; } nyx_cfg_t;
typedef enum typedef enum
@@ -46,6 +47,7 @@ typedef enum
ERR_SYSOLD_NYX = BIT(1), ERR_SYSOLD_NYX = BIT(1),
ERR_LIBSYS_MTC = BIT(2), ERR_LIBSYS_MTC = BIT(2),
ERR_SD_BOOT_EN = BIT(3), ERR_SD_BOOT_EN = BIT(3),
ERR_PANIC_CODE = BIT(4),
ERR_L4T_KERNEL = BIT(24), ERR_L4T_KERNEL = BIT(24),
ERR_EXCEPTION = BIT(31), ERR_EXCEPTION = BIT(31),
} hekate_errors_t; } hekate_errors_t;
@@ -53,6 +55,8 @@ typedef enum
#define byte_swap_32(num) ((((num) >> 24) & 0xff) | (((num) << 8) & 0xff0000) | \ #define byte_swap_32(num) ((((num) >> 24) & 0xff) | (((num) << 8) & 0xff0000) | \
(((num) >> 8 )& 0xff00) | (((num) << 24) & 0xff000000)) (((num) >> 8 )& 0xff00) | (((num) << 24) & 0xff000000))
#define byte_swap_16(num) ((((num) >> 8) & 0xff) | (((num) << 8) & 0xff00))
typedef struct _cfg_op_t typedef struct _cfg_op_t
{ {
u32 off; u32 off;
@@ -75,12 +79,15 @@ typedef struct _nyx_storage_t
u32 cfg; u32 cfg;
u8 irama[0x8000]; u8 irama[0x8000];
u8 hekate[0x30000]; u8 hekate[0x30000];
u8 rsvd[0x800000 - sizeof(nyx_info_t)]; u8 rsvd[SZ_8M - sizeof(nyx_info_t)];
nyx_info_t info; nyx_info_t info;
mtc_config_t mtc_cfg; mtc_config_t mtc_cfg;
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

@@ -12,7 +12,7 @@ char *CombinePaths(const char *current, const char *add){
size_t size = strlen(current) + strlen(add) + 2; size_t size = strlen(current) + strlen(add) + 2;
ret = (char*) malloc (size); ret = (char*) malloc (size);
sprintf(ret, (current[strlen(current) - 1] == '/') ? "%s%s" : "%s/%s", current, add); s_printf(ret, (current[strlen(current) - 1] == '/') ? "%s%s" : "%s/%s", current, add);
return ret; return ret;
} }

View File

@@ -180,7 +180,7 @@ void FileMenu(char *path, FSEntry_t entry){
FileMenuEntries[0].sizeUnion = entry.sizeUnion; FileMenuEntries[0].sizeUnion = entry.sizeUnion;
char attribs[16]; char attribs[16];
char *attribList = GetFileAttribs(entry); char *attribList = GetFileAttribs(entry);
sprintf(attribs, "Attribs:%s\n", attribList); s_printf(attribs, "Attribs:%s\n", attribList);
free(attribList); free(attribList);
FileMenuEntries[2].name = attribs; FileMenuEntries[2].name = attribs;

View File

@@ -114,7 +114,7 @@ int FolderMenu(const char *path){
char attribs[16]; char attribs[16];
char *attribList = GetFileAttribs(file); char *attribList = GetFileAttribs(file);
sprintf(attribs, "Attribs:%s\n", attribList); s_printf(attribs, "Attribs:%s\n", attribList);
free(attribList); free(attribList);
FolderMenuEntries[2].name = attribs; FolderMenuEntries[2].name = attribs;

View File

@@ -72,7 +72,7 @@ int newMenu(Vector_t* vec, int startIndex, int screenLenX, int screenLenY, u8 op
if (options & ENABLEPAGECOUNT){ if (options & ENABLEPAGECOUNT){
SETCOLOR(COLOR_DEFAULT, COLOR_WHITE); SETCOLOR(COLOR_DEFAULT, COLOR_WHITE);
char temp[40] = ""; char temp[40] = "";
sprintf(temp, " Page %d / %d | Total %d entries", (selected / screenLenY) + 1, ((vec->count - 1) / screenLenY) + 1, entryCount); s_printf(temp, " Page %d / %d | Total %d entries", (selected / screenLenY) + 1, ((vec->count - 1) / screenLenY) + 1, entryCount);
gfx_con_setpos(YLEFT - strlen(temp) * 18, 0); gfx_con_setpos(YLEFT - strlen(temp) * 18, 0);
gfx_printf(temp); gfx_printf(temp);
} }

View File

@@ -204,7 +204,7 @@ static bool _derive_tsec_keys(tsec_ctxt_t *tsec_ctxt, u32 kb, key_derivation_ctx
} }
} }
mc_enable_ahb_redirect(); mc_enable_ahb_redirect(true);
if (res < 0) { if (res < 0) {
//EPRINTFARGS("ERROR %x dumping TSEC.\n", res); //EPRINTFARGS("ERROR %x dumping TSEC.\n", res);

View File

@@ -41,7 +41,7 @@ void DumpSysFw(){
} }
baseSdPath = malloc(36 + 16); baseSdPath = malloc(36 + 16);
sprintf(baseSdPath, "sd:/tegraexplorer/Firmware/%d (%s)", TConf.pkg1ver, TConf.pkg1ID); s_printf(baseSdPath, "sd:/tegraexplorer/Firmware/%d (%s)", TConf.pkg1ver, TConf.pkg1ID);
int baseSdPathLen = strlen(baseSdPath); int baseSdPathLen = strlen(baseSdPath);
f_mkdir("sd:/tegraexplorer"); f_mkdir("sd:/tegraexplorer");
@@ -81,7 +81,7 @@ void DumpSysFw(){
int total = 1; int total = 1;
vecDefArray(FSEntry_t*, fsEntries, fileVec); vecDefArray(FSEntry_t*, fsEntries, fileVec);
for (int i = 0; i < fileVec.count; i++){ for (int i = 0; i < fileVec.count; i++){
sprintf(sysPath, (fsEntries[i].isDir) ? "%s/%s/00" : "%s/%s", "bis:/Contents/registered", fsEntries[i].name); s_printf(sysPath, (fsEntries[i].isDir) ? "%s/%s/00" : "%s/%s", "bis:/Contents/registered", fsEntries[i].name);
int contentType = GetNcaType(sysPath); int contentType = GetNcaType(sysPath);
if (contentType < 0){ if (contentType < 0){
@@ -90,7 +90,7 @@ void DumpSysFw(){
} }
char *sdPath = malloc(baseSdPathLen + 45); char *sdPath = malloc(baseSdPathLen + 45);
sprintf(sdPath, "%s/%s", baseSdPath, fsEntries[i].name); s_printf(sdPath, "%s/%s", baseSdPath, fsEntries[i].name);
if (contentType == Meta) if (contentType == Meta)
memcpy(sdPath + strlen(sdPath) - 4, ".cnmt.nca", 10); memcpy(sdPath + strlen(sdPath) - 4, ".cnmt.nca", 10);
@@ -214,7 +214,7 @@ void TakeScreenshot(){
char *name, *path; char *name, *path;
const char basepath[] = "sd:/tegraexplorer/screenshots"; const char basepath[] = "sd:/tegraexplorer/screenshots";
name = malloc(40); name = malloc(40);
sprintf(name, "Screenshot_%08X.bmp", get_tmr_us()); s_printf(name, "Screenshot_%08X.bmp", get_tmr_us());
f_mkdir("sd:/tegraexplorer"); f_mkdir("sd:/tegraexplorer");
f_mkdir(basepath); f_mkdir(basepath);