Compare commits
65 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
13e5216a4e | ||
|
|
147ccd3070 | ||
|
|
dc5c26e7c6 | ||
|
|
4914af1200 | ||
|
|
b57d26e99a | ||
|
|
f196b8bb0e | ||
|
|
7b460f7e56 | ||
|
|
9daa14abec | ||
|
|
bf8fd9a33b | ||
|
|
1f37b96359 | ||
|
|
46921aca22 | ||
|
|
41f96d4305 | ||
|
|
0959dc3a2d | ||
|
|
31baf3d19a | ||
|
|
f4696da0ef | ||
|
|
83ab79c51e | ||
|
|
745ac609d2 | ||
|
|
0f9aa51afe | ||
|
|
9fbb28e887 | ||
|
|
adf2045896 | ||
|
|
1a797bf93a | ||
|
|
1a9372b4ce | ||
|
|
87b91174ec | ||
|
|
26fff275ce | ||
|
|
53b44a525d | ||
|
|
8ce5d55eb8 | ||
|
|
afb749560a | ||
|
|
7a66e0298a | ||
|
|
e491a4cf57 | ||
|
|
b7789f1edb | ||
|
|
4949331f4c | ||
|
|
2c695e9a96 | ||
|
|
faaf801534 | ||
|
|
3fa775e3ad | ||
|
|
6663330de3 | ||
|
|
ed916360eb | ||
|
|
e4bc5c41ce | ||
|
|
d0d943c9c3 | ||
|
|
60b629e57f | ||
|
|
df80339060 | ||
|
|
cbbd427d3a | ||
|
|
dfcdb2e1e6 | ||
|
|
11ca6caf5f | ||
|
|
15afdf53e4 | ||
|
|
d15f958b48 | ||
|
|
5fd3bdede7 | ||
|
|
e2dd218f33 | ||
|
|
a85891ae00 | ||
|
|
2628044ba8 | ||
|
|
e620783a89 | ||
|
|
2fba9848ae | ||
|
|
52c65661d8 | ||
|
|
601c85c23e | ||
|
|
9d79f39897 | ||
|
|
2a7a3452ba | ||
|
|
f1386c60af | ||
|
|
b6ec217484 | ||
|
|
ad560b650e | ||
|
|
14a048a496 | ||
|
|
ba984d02eb | ||
|
|
fce59fba43 | ||
|
|
685663dcf6 | ||
|
|
cb61e856ad | ||
|
|
5b8fb9fb6b | ||
|
|
8249d9e1a2 |
9
Makefile
9
Makefile
@@ -67,11 +67,12 @@ CUSTOMDEFINES += -DBL_VER_MJ=$(BLVERSION_MAJOR) -DBL_VER_MN=$(BLVERSION_MINOR) -
|
||||
CUSTOMDEFINES += -DNYX_VER_MJ=$(NYXVERSION_MAJOR) -DNYX_VER_MN=$(NYXVERSION_MINOR) -DNYX_VER_HF=$(NYXVERSION_HOTFX) -DNYX_RESERVED=$(NYXVERSION_RSVD)
|
||||
CUSTOMDEFINES += -DGFX_INC=$(GFX_INC) -DFFCFG_INC=$(FFCFG_INC)
|
||||
|
||||
# 0: UART_A, 1: UART_B.
|
||||
#CUSTOMDEFINES += -DDEBUG_UART_PORT=0
|
||||
|
||||
#CUSTOMDEFINES += -DDEBUG
|
||||
|
||||
# UART Logging: Max baudrate 12.5M.
|
||||
# DEBUG_UART_PORT - 0: UART_A, 1: UART_B, 2: UART_C.
|
||||
#CUSTOMDEFINES += -DDEBUG_UART_BAUDRATE=115200 -DDEBUG_UART_INVERT=0 -DDEBUG_UART_PORT=0
|
||||
|
||||
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork
|
||||
CFLAGS = $(ARCH) -O2 -g -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -std=gnu11 -Wall $(CUSTOMDEFINES)
|
||||
LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defsym=IPL_LOAD_ADDR=$(IPL_LOAD_ADDR)
|
||||
@@ -102,7 +103,7 @@ all: $(TARGET).bin $(LDRDIR)
|
||||
@if [ ${BIN_SIZE} -gt 126296 ]; then echo "\e[1;33mPayload size exceeds limit!\e[0m"; fi
|
||||
@echo "--------------------------------------"
|
||||
|
||||
clean:
|
||||
clean: $(TOOLS)
|
||||
@rm -rf $(OBJS)
|
||||
@rm -rf $(BUILDDIR)
|
||||
@rm -rf $(OUTPUTDIR)
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# IPL Version.
|
||||
BLVERSION_MAJOR := 5
|
||||
BLVERSION_MINOR := 5
|
||||
BLVERSION_HOTFX := 0
|
||||
BLVERSION_HOTFX := 2
|
||||
BLVERSION_RSVD := 0
|
||||
|
||||
# Nyx Version.
|
||||
NYXVERSION_MAJOR := 0
|
||||
NYXVERSION_MINOR := 9
|
||||
NYXVERSION_HOTFX := 6
|
||||
NYXVERSION_HOTFX := 8
|
||||
NYXVERSION_RSVD := 0
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "di.h"
|
||||
#include <power/max77620.h>
|
||||
#include <power/max7762x.h>
|
||||
#include <mem/heap.h>
|
||||
#include <soc/clock.h>
|
||||
#include <soc/gpio.h>
|
||||
#include <soc/hw_init.h>
|
||||
@@ -170,9 +171,9 @@ int display_dsi_read(u8 cmd, u32 len, void *data, bool video_enabled)
|
||||
|
||||
void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled)
|
||||
{
|
||||
u8 *fifo8;
|
||||
u32 *fifo32;
|
||||
u32 host_control;
|
||||
u32 fifo32[DSI_STATUS_RX_FIFO_SIZE] = {0};
|
||||
u8 *fifo8 = (u8 *)fifo32;
|
||||
|
||||
// Enable host cmd packets during video and save host control.
|
||||
if (video_enabled)
|
||||
@@ -193,6 +194,8 @@ void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled)
|
||||
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);
|
||||
@@ -200,6 +203,7 @@ void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled)
|
||||
for (u32 i = 0; i < (ALIGN(len, 4) / 4); i++)
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = fifo32[i];
|
||||
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
|
||||
free(fifo32);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -215,29 +219,30 @@ void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled)
|
||||
void display_init()
|
||||
{
|
||||
// Check if display is already initialized.
|
||||
if (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) & BIT(CLK_L_DISP1))
|
||||
if (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & BIT(CLK_L_DISP1))
|
||||
_display_panel_and_hw_end(true);
|
||||
|
||||
// Get Chip ID.
|
||||
bool tegra_t210 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210;
|
||||
|
||||
// T210B01: Power on SD2 regulator for supplying LD0.
|
||||
// T210B01: Power on SD2 regulator for supplying LDO0.
|
||||
if (!tegra_t210)
|
||||
{
|
||||
// Set SD2 regulator voltage.
|
||||
max77620_regulator_set_voltage(REGULATOR_SD2, 1325000);
|
||||
max7762x_regulator_set_voltage(REGULATOR_SD2, 1325000);
|
||||
|
||||
// Set slew rate and enable SD2 regulator.
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD2_CFG, (1 << MAX77620_SD_SR_SHIFT) | MAX77620_SD_CFG1_FSRADE_SD_ENABLE);
|
||||
max77620_regulator_enable(REGULATOR_SD2, 1);
|
||||
max7762x_regulator_enable(REGULATOR_SD2, true);
|
||||
|
||||
}
|
||||
|
||||
// Enable power to display panel controller.
|
||||
max77620_regulator_set_volt_and_flags(REGULATOR_LDO0, 1200000, MAX77620_POWER_MODE_NORMAL); // Configure to 1.2V.
|
||||
max7762x_regulator_set_voltage(REGULATOR_LDO0, 1200000);
|
||||
max7762x_regulator_enable(REGULATOR_LDO0, true);
|
||||
|
||||
if (tegra_t210)
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO7,
|
||||
MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH | MAX77620_CNFG_GPIO_DRV_PUSHPULL); // T210: LD0 -> GPIO7 -> Display panel.
|
||||
max77620_config_gpio(7, MAX77620_GPIO_OUTPUT_ENABLE); // T210: LD0 -> GPIO7 -> Display panel.
|
||||
|
||||
// Enable Display Interface specific clocks.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_MIPI_CAL) | BIT(CLK_H_DSI);
|
||||
@@ -293,7 +298,7 @@ void display_init()
|
||||
|
||||
// Set DISP1 clock source and parent clock.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DISP1) = 0x40000000; // PLLD_OUT.
|
||||
u32 plld_div = (3 << 20) | (20 << 11) | 1; // DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 96 MHz.
|
||||
u32 plld_div = (3 << 20) | (20 << 11) | 1; // DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 97.5 MHz (offset).
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div;
|
||||
|
||||
if (tegra_t210)
|
||||
@@ -335,9 +340,12 @@ void display_init()
|
||||
|
||||
#if 0
|
||||
// Get Display ID.
|
||||
_display_id = 0xCCCCCC;
|
||||
_display_id = 0xCCCCCC; // Set initial value. 4th byte cleared.
|
||||
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);
|
||||
@@ -407,11 +415,11 @@ void display_init()
|
||||
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_SET_DISPLAY_ON, 20000);
|
||||
|
||||
// Configure PLLD for DISP1.
|
||||
plld_div = (1 << 20) | (24 << 11) | 1; // DIVM: 1, DIVN: 24, DIVP: 1. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 230.4 MHz.
|
||||
plld_div = (1 << 20) | (24 << 11) | 1; // DIVM: 1, DIVN: 24, DIVP: 1. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 234 MHz (offset).
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div;
|
||||
|
||||
if (tegra_t210)
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0x20; // PLLD_SETUP
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0x20; // PLLD_SETUP.
|
||||
else
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0;
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC) = 0x2DFC00; // Use new PLLD_SDM_DIN.
|
||||
@@ -420,7 +428,7 @@ void display_init()
|
||||
DSI(_DSIREG(DSI_PAD_CONTROL_1)) = 0;
|
||||
DSI(_DSIREG(DSI_PHY_TIMING_0)) = tegra_t210 ? 0x6070601 : 0x6070603;
|
||||
exec_cfg((u32 *)DSI_BASE, _display_dsi_packet_config, 19);
|
||||
// Set pixel clock dividers: 230.4 / 3 / 1 = 76.8 MHz. 60 Hz.
|
||||
// Set pixel clock dividers: 234 / 3 / 1 = 78 MHz (offset) for 60 Hz.
|
||||
DISPLAY_A(_DIREG(DC_DISP_DISP_CLOCK_CONTROL)) = PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(4); // 4: div3.
|
||||
exec_cfg((u32 *)DSI_BASE, _display_dsi_mode_config, 10);
|
||||
usleep(10000);
|
||||
@@ -600,11 +608,20 @@ skip_panel_deinit:
|
||||
|
||||
void display_end() { _display_panel_and_hw_end(false); };
|
||||
|
||||
u16 display_get_decoded_lcd_id()
|
||||
u16 display_get_decoded_panel_id()
|
||||
{
|
||||
return _display_id;
|
||||
}
|
||||
|
||||
void display_set_decoded_panel_id(u32 id)
|
||||
{
|
||||
// Decode Display ID.
|
||||
_display_id = ((id >> 8) & 0xFF00) | (id & 0xFF);
|
||||
|
||||
if ((_display_id & 0xFF) == PANEL_JDI_XXX062M)
|
||||
_display_id = PANEL_JDI_XXX062M;
|
||||
}
|
||||
|
||||
void display_color_screen(u32 color)
|
||||
{
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_one_color, 8);
|
||||
@@ -651,6 +651,7 @@
|
||||
* [10] 96 [09]: JDI LAM062M109A
|
||||
* [20] 93 [0F]: InnoLux P062CCA-AZ1 (Rev A1)
|
||||
* [20] 95 [0F]: InnoLux P062CCA-AZ2
|
||||
* [20] 96 [0F]: InnoLux P062CCA-AZ3
|
||||
* [30] 94 [0F]: AUO A062TAN01 (59.06A33.001)
|
||||
* [30] 95 [0F]: AUO A062TAN02 (59.06A33.002)
|
||||
*
|
||||
@@ -671,10 +672,12 @@
|
||||
* 20h: InnoLux Corporation
|
||||
* 30h: AU Optronics
|
||||
* 40h: Unknown1
|
||||
* 50h: Unknown2 (OLED? Samsung? LG?)
|
||||
*
|
||||
* Boards, Panel Size:
|
||||
* 0Fh: Icosa/Iowa, 6.2"
|
||||
* 10h: Hoag, 5.5"
|
||||
* 20h: Unknown, x.x"
|
||||
*/
|
||||
|
||||
enum
|
||||
@@ -693,8 +696,9 @@ void display_init();
|
||||
void display_backlight_pwm_init();
|
||||
void display_end();
|
||||
|
||||
/*! Get Display panel ID. */
|
||||
u16 display_get_decoded_lcd_id();
|
||||
/*! Get/Set Display panel ID. */
|
||||
u16 display_get_decoded_panel_id();
|
||||
void display_set_decoded_panel_id(u32 id);
|
||||
|
||||
/*! Show one single color on the display. */
|
||||
void display_color_screen(u32 color);
|
||||
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
|
||||
#include "als.h"
|
||||
#include <power/max77620.h>
|
||||
#include <power/max7762x.h>
|
||||
#include <soc/clock.h>
|
||||
#include <soc/i2c.h>
|
||||
#include <soc/pinmux.h>
|
||||
@@ -97,14 +97,16 @@ void get_als_lux(als_table_t *als_val)
|
||||
|
||||
u8 als_init(als_table_t *als_val)
|
||||
{
|
||||
// Enable power to ALS IC.
|
||||
max7762x_regulator_set_voltage(REGULATOR_LDO6, 2900000);
|
||||
max7762x_regulator_enable(REGULATOR_LDO6, true);
|
||||
|
||||
// Init I2C2.
|
||||
pinmux_config_i2c(I2C_2);
|
||||
clock_enable_i2c(I2C_2);
|
||||
i2c_init(I2C_2);
|
||||
|
||||
max77620_regulator_set_volt_and_flags(REGULATOR_LDO6, 2900000, MAX77620_POWER_MODE_NORMAL);
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_LDO6_CFG2,
|
||||
(MAX77620_POWER_MODE_NORMAL << MAX77620_LDO_POWER_MODE_SHIFT | (3 << 3) | MAX77620_LDO_CFG2_ADE_ENABLE));
|
||||
|
||||
// Initialize ALS.
|
||||
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_ADDR(BH1730_GAIN_REG), HOS_GAIN);
|
||||
|
||||
@@ -39,6 +39,9 @@
|
||||
#define JC_WIRED_INIT_REPLY 0x94
|
||||
#define JC_INIT_HANDSHAKE 0xA5
|
||||
|
||||
#define JC_HORI_INPUT_RPT_CMD 0x9A
|
||||
#define JC_HORI_INPUT_RPT 0x00
|
||||
|
||||
#define JC_WIRED_CMD_MAC 0x01
|
||||
#define JC_WIRED_CMD_10 0x10
|
||||
|
||||
@@ -61,8 +64,12 @@
|
||||
#define JC_BTN_MASK_L 0xFF2900 // 0xFFE900: with charge status.
|
||||
#define JC_BTN_MASK_R 0x0056FF
|
||||
|
||||
#define JC_ID_L 1
|
||||
#define JC_ID_R 2
|
||||
#define JC_ID_L 0x01
|
||||
#define JC_ID_R 0x02
|
||||
#define JC_ID_HORI 0x20
|
||||
|
||||
#define JC_CRC8_INIT 0x00
|
||||
#define JC_CRC8_POLY 0x8D
|
||||
|
||||
enum
|
||||
{
|
||||
@@ -80,25 +87,31 @@ static const u8 init_jc[] = {
|
||||
static const u8 init_handshake[] = {
|
||||
0x19, 0x01, 0x03, 0x07, 0x00, // Uart header.
|
||||
JC_INIT_HANDSHAKE, 0x02, // Wired cmd and wired subcmd.
|
||||
0x01, 0x7E, 0x00, 0x00, 0x00 // Wired subcmd data.
|
||||
0x01, 0x7E, 0x00, 0x00, 0x00 // Wired subcmd data and crc.
|
||||
};
|
||||
|
||||
static const u8 init_get_info[] = {
|
||||
0x19, 0x01, 0x03, 0x07, 0x00, // Uart header.
|
||||
JC_WIRED_CMD, JC_WIRED_CMD_MAC, // Wired cmd and subcmd.
|
||||
0x00, 0x00, 0x00, 0x00, 0x24 // Wired subcmd data.
|
||||
0x00, 0x00, 0x00, 0x00, 0x24 // Wired subcmd data and crc.
|
||||
};
|
||||
|
||||
static const u8 init_finilize[] = {
|
||||
static const u8 init_finalize[] = {
|
||||
0x19, 0x01, 0x03, 0x07, 0x00, // Uart header.
|
||||
JC_WIRED_CMD, JC_WIRED_CMD_10, // Wired cmd and subcmd.
|
||||
0x00, 0x00, 0x00, 0x00, 0x3D // Wired subcmd data.
|
||||
0x00, 0x00, 0x00, 0x00, 0x3D // Wired subcmd data and crc.
|
||||
};
|
||||
|
||||
static const u8 nx_pad_status[] = {
|
||||
0x19, 0x01, 0x03, 0x08, 0x00, // Uart header.
|
||||
JC_WIRED_HID, 0x00, // Wired cmd and hid cmd.
|
||||
0x01, 0x00, 0x00, 0x69, 0x2D, 0x1F // hid data.
|
||||
0x01, 0x00, 0x00, 0x69, 0x2D, 0x1F // hid data and crc.
|
||||
};
|
||||
|
||||
static const u8 hori_pad_status[] = {
|
||||
0x19, 0x01, 0x03, 0x07, 0x00, // Uart header.
|
||||
JC_HORI_INPUT_RPT_CMD, 0x01, // Hori cmd and hori subcmd.
|
||||
0x00, 0x00, 0x00, 0x00, 0x48 // Hori cmd data and crc.
|
||||
};
|
||||
|
||||
typedef struct _jc_uart_hdr_t
|
||||
@@ -185,8 +198,8 @@ typedef struct _joycon_ctxt_t
|
||||
u8 connected;
|
||||
} joycon_ctxt_t;
|
||||
|
||||
static joycon_ctxt_t jc_l;
|
||||
static joycon_ctxt_t jc_r;
|
||||
static joycon_ctxt_t jc_l = {0};
|
||||
static joycon_ctxt_t jc_r = {0};
|
||||
|
||||
static bool jc_init_done = false;
|
||||
static u32 hid_pkt_inc = 0;
|
||||
@@ -195,13 +208,29 @@ static jc_gamepad_rpt_t jc_gamepad;
|
||||
|
||||
void jc_power_supply(u8 uart, bool enable);
|
||||
|
||||
static u8 jc_crc(u8 *data, u16 len)
|
||||
{
|
||||
u8 crc = JC_CRC8_INIT;
|
||||
u16 i, j;
|
||||
for (i = 0; i < len; i++) {
|
||||
crc ^= data[i];
|
||||
for (j = 0; j < 8; j++) {
|
||||
if ((crc & 0x80) != 0)
|
||||
crc = (u8)((crc << 1) ^ JC_CRC8_POLY);
|
||||
else
|
||||
crc <<= 1;
|
||||
}
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
void joycon_send_raw(u8 uart_port, const u8 *buf, u16 size)
|
||||
{
|
||||
uart_send(uart_port, buf, size);
|
||||
uart_wait_idle(uart_port, UART_TX_IDLE);
|
||||
}
|
||||
|
||||
static u16 jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, u8 *data, u16 size)
|
||||
static u16 jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, u8 *data, u16 size, bool crc)
|
||||
{
|
||||
out->uart_hdr.magic[0] = 0x19;
|
||||
out->uart_hdr.magic[1] = 0x01;
|
||||
@@ -214,14 +243,14 @@ static u16 jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, u8 *data, u
|
||||
if (data)
|
||||
memcpy(out->data, data, size);
|
||||
|
||||
out->crc = 0; // wired crc8ccit can be skipped.
|
||||
out->crc = crc ? jc_crc(&out->uart_hdr.total_size_msb, sizeof(out->uart_hdr.total_size_msb) + sizeof(out->cmd) + sizeof(out->data)) : 0;
|
||||
|
||||
return sizeof(jc_wired_hdr_t);
|
||||
}
|
||||
|
||||
static u16 jc_hid_output_rpt_craft(jc_wired_hdr_t *rpt, u8 *payload, u16 size)
|
||||
static u16 jc_hid_output_rpt_craft(jc_wired_hdr_t *rpt, u8 *payload, u16 size, bool crc)
|
||||
{
|
||||
u16 pkt_size = jc_packet_add_uart_hdr(rpt, JC_WIRED_HID, NULL, 0);
|
||||
u16 pkt_size = jc_packet_add_uart_hdr(rpt, JC_WIRED_HID, NULL, 0, crc);
|
||||
pkt_size += size;
|
||||
|
||||
rpt->uart_hdr.total_size_lsb += size;
|
||||
@@ -234,12 +263,12 @@ static u16 jc_hid_output_rpt_craft(jc_wired_hdr_t *rpt, u8 *payload, u16 size)
|
||||
return pkt_size;
|
||||
}
|
||||
|
||||
void jc_send_hid_output_rpt(u8 uart, u8 *payload, u16 size)
|
||||
void jc_send_hid_output_rpt(u8 uart, u8 *payload, u16 size, bool crc)
|
||||
{
|
||||
u8 rpt[0x50];
|
||||
memset(rpt, 0, sizeof(rpt));
|
||||
|
||||
u32 rpt_size = jc_hid_output_rpt_craft((jc_wired_hdr_t *)rpt, payload, size);
|
||||
u32 rpt_size = jc_hid_output_rpt_craft((jc_wired_hdr_t *)rpt, payload, size, crc);
|
||||
|
||||
joycon_send_raw(uart, rpt, rpt_size);
|
||||
}
|
||||
@@ -275,18 +304,18 @@ void jc_send_hid_cmd(u8 uart, u8 subcmd, u8 *data, u16 size)
|
||||
hid_pkt->subcmd = JC_HID_SUBCMD_RUMBLE_CTL;
|
||||
hid_pkt->subcmd_data[0] = 1;
|
||||
if (send_r_rumble)
|
||||
jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 0x10);
|
||||
jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 0x10, false);
|
||||
if (send_l_rumble)
|
||||
jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 0x10);
|
||||
jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 0x10, false);
|
||||
|
||||
// Send rumble.
|
||||
hid_pkt->cmd = JC_HID_RUMBLE_RPT;
|
||||
hid_pkt->pkt_id = jc_hid_pkt_id_incr();
|
||||
memcpy(hid_pkt->rumble, rumble_init, sizeof(rumble_init));
|
||||
if (send_r_rumble)
|
||||
jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 10);
|
||||
jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 10, false);
|
||||
if (send_l_rumble)
|
||||
jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 10);
|
||||
jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 10, false);
|
||||
|
||||
msleep(15);
|
||||
|
||||
@@ -297,21 +326,21 @@ void jc_send_hid_cmd(u8 uart, u8 subcmd, u8 *data, u16 size)
|
||||
hid_pkt->subcmd_data[0] = 0;
|
||||
memcpy(hid_pkt->rumble, rumble_neutral, sizeof(rumble_neutral));
|
||||
if (send_r_rumble)
|
||||
jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 0x10);
|
||||
jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 0x10, false);
|
||||
if (send_l_rumble)
|
||||
jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 0x10);
|
||||
jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 0x10, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool crc_needed = (jc_l.uart == uart) ? (jc_l.type & JC_ID_HORI) : (jc_r.type & JC_ID_HORI);
|
||||
|
||||
hid_pkt->cmd = JC_HID_OUTPUT_RPT;
|
||||
hid_pkt->pkt_id = jc_hid_pkt_id_incr();
|
||||
hid_pkt->subcmd = subcmd;
|
||||
if (data)
|
||||
memcpy(hid_pkt->subcmd_data, data, size);
|
||||
|
||||
u8 pkt_size = sizeof(jc_hid_out_rpt_t) + size;
|
||||
|
||||
jc_send_hid_output_rpt(uart, (u8 *)hid_pkt, pkt_size);
|
||||
jc_send_hid_output_rpt(uart, (u8 *)hid_pkt, sizeof(jc_hid_out_rpt_t) + size, crc_needed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -333,6 +362,7 @@ static void jc_parse_wired_hid(joycon_ctxt_t *jc, const u8* packet, u32 size)
|
||||
|
||||
switch (hid_pkt->cmd)
|
||||
{
|
||||
case JC_HORI_INPUT_RPT:
|
||||
case JC_HID_INPUT_RPT:
|
||||
btn_tmp = hid_pkt->btn_right | hid_pkt->btn_shared << 8 | hid_pkt->btn_left << 16;
|
||||
|
||||
@@ -412,6 +442,7 @@ static void jc_uart_pkt_parse(joycon_ctxt_t *jc, const u8* packet, size_t size)
|
||||
jc_wired_hdr_t *pkt = (jc_wired_hdr_t *)packet;
|
||||
switch (pkt->cmd)
|
||||
{
|
||||
case JC_HORI_INPUT_RPT_CMD:
|
||||
case JC_WIRED_HID:
|
||||
jc_parse_wired_hid(jc, pkt->payload, (pkt->data[0] << 8) | pkt->data[1]);
|
||||
break;
|
||||
@@ -474,10 +505,15 @@ static bool jc_send_init_rumble(joycon_ctxt_t *jc)
|
||||
|
||||
static void jc_req_nx_pad_status(joycon_ctxt_t *jc)
|
||||
{
|
||||
bool sent_rumble = jc_send_init_rumble(jc);
|
||||
bool is_nxpad = !(jc->type & JC_ID_HORI);
|
||||
|
||||
if (sent_rumble)
|
||||
return;
|
||||
if (is_nxpad)
|
||||
{
|
||||
bool sent_rumble = jc_send_init_rumble(jc);
|
||||
|
||||
if (sent_rumble)
|
||||
return;
|
||||
}
|
||||
|
||||
if (jc->last_status_req_time > get_tmr_ms() || !jc->connected)
|
||||
return;
|
||||
@@ -488,7 +524,10 @@ static void jc_req_nx_pad_status(joycon_ctxt_t *jc)
|
||||
else
|
||||
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO);
|
||||
|
||||
joycon_send_raw(jc->uart, nx_pad_status, sizeof(nx_pad_status));
|
||||
if (is_nxpad)
|
||||
joycon_send_raw(jc->uart, nx_pad_status, sizeof(nx_pad_status));
|
||||
else
|
||||
joycon_send_raw(jc->uart, hori_pad_status, sizeof(hori_pad_status));
|
||||
|
||||
// Turn Joy-Con detect on.
|
||||
if (jc->uart == UART_B)
|
||||
@@ -660,12 +699,12 @@ void jc_deinit()
|
||||
|
||||
u8 data = HCI_STATE_SLEEP;
|
||||
|
||||
if (jc_r.connected)
|
||||
if (jc_r.connected && !(jc_r.type & JC_ID_HORI))
|
||||
{
|
||||
jc_send_hid_cmd(UART_B, JC_HID_SUBCMD_HCI_STATE, &data, 1);
|
||||
jc_rcv_pkt(&jc_r);
|
||||
}
|
||||
if (jc_l.connected)
|
||||
if (jc_l.connected && !(jc_l.type & JC_ID_HORI))
|
||||
{
|
||||
jc_send_hid_cmd(UART_C, JC_HID_SUBCMD_HCI_STATE, &data, 1);
|
||||
jc_rcv_pkt(&jc_l);
|
||||
@@ -709,9 +748,12 @@ static void jc_init_conn(joycon_ctxt_t *jc)
|
||||
msleep(5);
|
||||
jc_rcv_pkt(jc);
|
||||
|
||||
joycon_send_raw(jc->uart, init_finilize, sizeof(init_finilize));
|
||||
msleep(5);
|
||||
jc_rcv_pkt(jc);
|
||||
if (!(jc->type & JC_ID_HORI))
|
||||
{
|
||||
joycon_send_raw(jc->uart, init_finalize, sizeof(init_finalize));
|
||||
msleep(5);
|
||||
jc_rcv_pkt(jc);
|
||||
}
|
||||
|
||||
// Turn Joy-Con detect on.
|
||||
if (jc->uart == UART_B)
|
||||
@@ -816,10 +858,10 @@ void jc_init_hw()
|
||||
jc_l.uart = UART_C;
|
||||
jc_r.uart = UART_B;
|
||||
|
||||
#if !defined(DEBUG_UART_PORT) || !(DEBUG_UART_PORT)
|
||||
if (fuse_read_hw_type() == FUSE_NX_HW_TYPE_HOAG)
|
||||
return;
|
||||
|
||||
#ifndef DEBUG_UART_PORT
|
||||
jc_power_supply(UART_C, true);
|
||||
jc_power_supply(UART_B, true);
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include <soc/i2c.h>
|
||||
#include <soc/pinmux.h>
|
||||
#include <power/max7762x.h>
|
||||
#include <power/max77620.h>
|
||||
#include <soc/gpio.h>
|
||||
#include <soc/t210.h>
|
||||
#include <utils/btn.h>
|
||||
@@ -34,6 +33,16 @@
|
||||
#include <gfx_utils.h>
|
||||
#define DPRINTF(...) gfx_printf(__VA_ARGS__)
|
||||
|
||||
static touch_panel_info_t _panels[] =
|
||||
{
|
||||
{ 0, 1, 1, 1, "NISSHA NFT-K12D" },
|
||||
{ 1, 0, 1, 1, "GiS GGM6 B2X" },
|
||||
{ 2, 0, 0, 0, "NISSHA NBF-K9A" },
|
||||
{ 3, 1, 0, 0, "GiS 5.5\"" },
|
||||
{ 4, 0, 0, 1, "Unknown" },
|
||||
{ -1, 1, 0, 1, "GiS VA 6.2\"" }
|
||||
};
|
||||
|
||||
static int touch_command(u8 cmd, u8 *buf, u8 size)
|
||||
{
|
||||
int res = i2c_send_buf_small(I2C_3, STMFTS_I2C_ADDR, cmd, buf, size);
|
||||
@@ -53,7 +62,7 @@ static int touch_read_reg(u8 *cmd, u32 csize, u8 *buf, u32 size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int touch_wait_event(u8 event, u8 status, u32 timeout)
|
||||
static int touch_wait_event(u8 event, u8 status, u32 timeout, u8 *buf)
|
||||
{
|
||||
u32 timer = get_tmr_ms() + timeout;
|
||||
while (true)
|
||||
@@ -61,7 +70,11 @@ static int touch_wait_event(u8 event, u8 status, u32 timeout)
|
||||
u8 tmp[8] = {0};
|
||||
i2c_recv_buf_small(tmp, 8, I2C_3, STMFTS_I2C_ADDR, STMFTS_READ_ONE_EVENT);
|
||||
if (tmp[1] == event && tmp[2] == status)
|
||||
{
|
||||
if (buf)
|
||||
memcpy(buf, &tmp[3], 5);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (get_tmr_ms() > timer)
|
||||
return 1;
|
||||
@@ -147,10 +160,10 @@ static void _touch_parse_event(touch_event *event)
|
||||
event->type = STMFTS_EV_MULTI_TOUCH_LEAVE;
|
||||
}
|
||||
|
||||
// gfx_con_setpos(&gfx_con, 0, 300);
|
||||
// gfx_con_setpos(0, 300);
|
||||
// DPRINTF("x = %d \ny = %d \nz = %d \n", event->x, event->y, event->z);
|
||||
// DPRINTF("0 = %02X\n1 = %02x\n2 = %02x\n3 = %02x\n", event->raw[0], event->raw[1], event->raw[2], event->raw[3]);
|
||||
// DPRINTF("4 = %02X\n5 = %02x\n6 = %02x\n7 = %02x\n", event->raw[4], event->raw[5], event->raw[6], event->raw[7]);
|
||||
// DPRINTF("0 = %02X\n1 = %02X\n2 = %02X\n3 = %02X\n", event->raw[0], event->raw[1], event->raw[2], event->raw[3]);
|
||||
// DPRINTF("4 = %02X\n5 = %02X\n6 = %02X\n7 = %02X\n", event->raw[4], event->raw[5], event->raw[6], event->raw[7]);
|
||||
}
|
||||
|
||||
void touch_poll(touch_event *event)
|
||||
@@ -183,12 +196,33 @@ touch_info touch_get_info()
|
||||
info.config_id = buf[4];
|
||||
info.config_ver = buf[5];
|
||||
|
||||
//DPRINTF("ID: %04X, FW Ver: %d.%02d\nCfg ID: %02x, Cfg Ver: %d\n",
|
||||
//DPRINTF("ID: %04X, FW Ver: %d.%02d\nCfg ID: %02X, Cfg Ver: %d\n",
|
||||
// info.chip_id, info.fw_ver >> 8, info.fw_ver & 0xFF, info.config_id, info.config_ver);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
touch_panel_info_t *touch_get_panel_vendor()
|
||||
{
|
||||
u8 buf[5] = {0};
|
||||
u8 cmd = STMFTS_VENDOR_GPIO_STATE;
|
||||
|
||||
if (touch_command(STMFTS_VENDOR, &cmd, 1))
|
||||
return NULL;
|
||||
|
||||
if (touch_wait_event(STMFTS_EV_VENDOR, STMFTS_VENDOR_GPIO_STATE, 2000, buf))
|
||||
return NULL;
|
||||
|
||||
for (u32 i = 0; i < ARRAY_SIZE(_panels); i++)
|
||||
{
|
||||
touch_panel_info_t *panel = &_panels[i];
|
||||
if (buf[0] == panel->gpio0 && buf[1] == panel->gpio1 && buf[2] == panel->gpio2)
|
||||
return panel;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int touch_get_fw_info(touch_fw_info_t *fw)
|
||||
{
|
||||
u8 buf[8] = {0};
|
||||
@@ -227,7 +261,7 @@ int touch_sys_reset()
|
||||
continue;
|
||||
}
|
||||
msleep(10);
|
||||
if (touch_wait_event(STMFTS_EV_CONTROLLER_READY, 0, 20))
|
||||
if (touch_wait_event(STMFTS_EV_CONTROLLER_READY, 0, 20, NULL))
|
||||
continue;
|
||||
else
|
||||
return 0;
|
||||
@@ -301,9 +335,9 @@ int touch_get_fb_info(u8 *buf)
|
||||
|
||||
int touch_sense_enable()
|
||||
{
|
||||
// Enable auto tuning calibration and multi-touch sensing.
|
||||
u8 cmd = 1;
|
||||
if (touch_command(STMFTS_AUTO_CALIBRATION, &cmd, 1))
|
||||
// Switch sense mode and enable multi-touch sensing.
|
||||
u8 cmd = STMFTS_FINGER_MODE;
|
||||
if (touch_command(STMFTS_SWITCH_SENSE_MODE, &cmd, 1))
|
||||
return 0;
|
||||
|
||||
if (touch_command(STMFTS_MS_MT_SENSE_ON, NULL, 0))
|
||||
@@ -329,19 +363,19 @@ int touch_execute_autotune()
|
||||
// Apply Mutual Sense Compensation tuning.
|
||||
if (touch_command(STMFTS_MS_CX_TUNING, NULL, 0))
|
||||
return 0;
|
||||
if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_MS_CX_TUNING_DONE, 2000))
|
||||
if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_MS_CX_TUNING_DONE, 2000, NULL))
|
||||
return 0;
|
||||
|
||||
// Apply Self Sense Compensation tuning.
|
||||
if (touch_command(STMFTS_SS_CX_TUNING, NULL, 0))
|
||||
return 0;
|
||||
if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_SS_CX_TUNING_DONE, 2000))
|
||||
if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_SS_CX_TUNING_DONE, 2000, NULL))
|
||||
return 0;
|
||||
|
||||
// Save Compensation data to EEPROM.
|
||||
if (touch_command(STMFTS_SAVE_CX_TUNING, NULL, 0))
|
||||
return 0;
|
||||
if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_WRITE_CX_TUNE_DONE, 2000))
|
||||
if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_WRITE_CX_TUNE_DONE, 2000, NULL))
|
||||
return 0;
|
||||
|
||||
return touch_sense_enable();
|
||||
@@ -358,10 +392,9 @@ static int touch_init()
|
||||
|
||||
int touch_power_on()
|
||||
{
|
||||
// Enables LDO6 for touchscreen VDD/AVDD supply
|
||||
max77620_regulator_set_volt_and_flags(REGULATOR_LDO6, 2900000, MAX77620_POWER_MODE_NORMAL);
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_LDO6_CFG2,
|
||||
(MAX77620_POWER_MODE_NORMAL << MAX77620_LDO_POWER_MODE_SHIFT | (3 << 3) | MAX77620_LDO_CFG2_ADE_ENABLE));
|
||||
// Enable LDO6 for touchscreen VDD/AVDD supply.
|
||||
max7762x_regulator_set_voltage(REGULATOR_LDO6, 2900000);
|
||||
max7762x_regulator_enable(REGULATOR_LDO6, true);
|
||||
|
||||
// Configure touchscreen GPIO.
|
||||
PINMUX_AUX(PINMUX_AUX_DAP4_SCLK) = PINMUX_PULL_DOWN | 1;
|
||||
@@ -385,7 +418,7 @@ int touch_power_on()
|
||||
i2c_init(I2C_3);
|
||||
|
||||
// Wait for the touchscreen module to get ready.
|
||||
touch_wait_event(STMFTS_EV_CONTROLLER_READY, 0, 20);
|
||||
touch_wait_event(STMFTS_EV_CONTROLLER_READY, 0, 20, NULL);
|
||||
|
||||
// Check for forced boot time calibration.
|
||||
if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
|
||||
@@ -414,9 +447,7 @@ void touch_power_off()
|
||||
gpio_write(GPIO_PORT_J, GPIO_PIN_7, GPIO_LOW);
|
||||
|
||||
// Disables LDO6 for touchscreen VDD, AVDD supply
|
||||
max77620_regulator_enable(REGULATOR_LDO6, 0);
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_LDO6_CFG2,
|
||||
MAX77620_LDO_CFG2_ADE_ENABLE | (2 << 3) | (MAX77620_POWER_MODE_NORMAL << MAX77620_LDO_POWER_MODE_SHIFT));
|
||||
max7762x_regulator_enable(REGULATOR_LDO6, false);
|
||||
|
||||
clock_disable_i2c(I2C_3);
|
||||
}
|
||||
@@ -47,19 +47,26 @@
|
||||
#define STMFTS_ITO_CHECK 0xA7
|
||||
#define STMFTS_RELEASEINFO 0xAA
|
||||
#define STMFTS_WRITE_REG 0xB6
|
||||
#define STMFTS_AUTO_CALIBRATION 0xC3
|
||||
#define STMFTS_SWITCH_SENSE_MODE 0xC3
|
||||
#define STMFTS_NOISE_WRITE 0xC7
|
||||
#define STMFTS_NOISE_READ 0xC8
|
||||
#define STMFTS_RW_FRAMEBUFFER_REG 0xD0
|
||||
#define STMFTS_SAVE_CX_TUNING 0xFC
|
||||
|
||||
#define STMFTS_UNK0 0xB8 //Request compensation
|
||||
#define STMFTS_UNK1 0xCF
|
||||
#define STMFTS_UNK2 0xF7
|
||||
#define STMFTS_UNK3 0xFA
|
||||
#define STMFTS_UNK4 0xF9
|
||||
#define STMFTS_REQU_COMP_DATA 0xB8
|
||||
#define STMFTS_VENDOR 0xCF
|
||||
#define STMFTS_FLASH_UNLOCK 0xF7
|
||||
#define STMFTS_FLASH_WRITE_64K 0xF8
|
||||
#define STMFTS_FLASH_STATUS 0xF9
|
||||
#define STMFTS_FLASH_OP 0xFA
|
||||
#define STMFTS_UNK5 0x62
|
||||
|
||||
/* cmd parameters */
|
||||
#define STMFTS_VENDOR_GPIO_STATE 0x01
|
||||
#define STMFTS_VENDOR_SENSE_MODE 0x02
|
||||
#define STMFTS_STYLUS_MODE 0x00
|
||||
#define STMFTS_FINGER_MODE 0x01
|
||||
#define STMFTS_HOVER_MODE 0x02
|
||||
|
||||
/* events */
|
||||
#define STMFTS_EV_NO_EVENT 0x00
|
||||
@@ -74,6 +81,7 @@
|
||||
#define STMFTS_EV_ERROR 0x0f
|
||||
#define STMFTS_EV_NOISE_READ 0x17
|
||||
#define STMFTS_EV_NOISE_WRITE 0x18
|
||||
#define STMFTS_EV_VENDOR 0x20
|
||||
|
||||
#define STMFTS_EV_CONTROLLER_READY 0x10
|
||||
#define STMFTS_EV_STATUS 0x16
|
||||
@@ -131,6 +139,15 @@ typedef struct _touch_event {
|
||||
bool touch;
|
||||
} touch_event;
|
||||
|
||||
typedef struct _touch_panel_info_t
|
||||
{
|
||||
u8 idx;
|
||||
u8 gpio0;
|
||||
u8 gpio1;
|
||||
u8 gpio2;
|
||||
char *vendor;
|
||||
} touch_panel_info_t;
|
||||
|
||||
typedef struct _touch_info {
|
||||
u16 chip_id;
|
||||
u16 fw_ver;
|
||||
@@ -146,6 +163,7 @@ typedef struct _touch_fw_info_t {
|
||||
|
||||
void touch_poll(touch_event *event);
|
||||
touch_event touch_poll_wait();
|
||||
touch_panel_info_t *touch_get_panel_vendor();
|
||||
int touch_get_fw_info(touch_fw_info_t *fw);
|
||||
touch_info touch_get_info();
|
||||
int touch_panel_ito_test(u8 *err);
|
||||
|
||||
@@ -155,7 +155,7 @@
|
||||
|
||||
|
||||
/*Log settings*/
|
||||
#ifdef DEBUG_UART_PORT
|
||||
#ifdef DEBUG_UART_LV_LOG
|
||||
# define USE_LV_LOG 1 /*Enable/disable the log module*/
|
||||
#else
|
||||
# define USE_LV_LOG 0 /*Enable/disable the log module*/
|
||||
|
||||
@@ -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 LV_LOG_PRINTF
|
||||
#if LV_LOG_PRINTF && defined(DEBUG_UART_PORT)
|
||||
static const char * lvl_prefix[] = {"Trace", "Info", "Warn", "Error"};
|
||||
char *log = (char *)malloc(0x1000);
|
||||
s_printf(log, "%s: %s \t(%s #%d)\r\n", lvl_prefix[level], dsc, file, line);
|
||||
|
||||
18
bdk/mem/mc.c
18
bdk/mem/mc.c
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 CTCaer
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -20,6 +20,8 @@
|
||||
#include <soc/clock.h>
|
||||
#include <utils/util.h>
|
||||
|
||||
//#define CONFIG_ENABLE_AHB_REDIRECT
|
||||
|
||||
void mc_config_tsec_carveout(u32 bom, u32 size1mb, bool lock)
|
||||
{
|
||||
MC(MC_SEC_CARVEOUT_BOM) = bom;
|
||||
@@ -143,17 +145,19 @@ void mc_disable_ahb_redirect()
|
||||
|
||||
void mc_enable()
|
||||
{
|
||||
// Reset EMC source to PLLP.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) & 0x1FFFFFFF) | 0x40000000;
|
||||
// Enable memory clocks.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & ~BIT(CLK_H_EMC)) | BIT(CLK_H_EMC);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & ~BIT(CLK_H_MEM)) | BIT(CLK_H_MEM);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) & ~BIT(CLK_X_EMC_DLL)) | BIT(CLK_X_EMC_DLL);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_EMC);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_MEM);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = BIT(CLK_X_EMC_DLL);
|
||||
// Clear clock resets for memory.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_EMC) | BIT(CLK_H_MEM);
|
||||
usleep(5);
|
||||
|
||||
//#ifdef CONFIG_ENABLE_AHB_REDIRECT
|
||||
#ifdef CONFIG_ENABLE_AHB_REDIRECT
|
||||
mc_enable_ahb_redirect();
|
||||
#else
|
||||
mc_disable_ahb_redirect();
|
||||
//mc_enable_ahb_redirect();
|
||||
//#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ u32 minerva_init()
|
||||
mtc_config_t mtc_tmp;
|
||||
|
||||
mtc_tmp.mtc_table = mtc_cfg->mtc_table;
|
||||
mtc_tmp.sdram_id = (fuse_read_odm(4) >> 3) & 0x1F;
|
||||
mtc_tmp.sdram_id = fuse_read_dramid(false);
|
||||
mtc_tmp.init_done = MTC_NEW_MAGIC;
|
||||
|
||||
u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)&mtc_tmp);
|
||||
@@ -81,7 +81,7 @@ u32 minerva_init()
|
||||
// Set table to nyx storage.
|
||||
mtc_cfg->mtc_table = (emc_table_t *)nyx_str->mtc_table;
|
||||
|
||||
mtc_cfg->sdram_id = (fuse_read_odm(4) >> 3) & 0x1F;
|
||||
mtc_cfg->sdram_id = fuse_read_dramid(false);
|
||||
mtc_cfg->init_done = MTC_NEW_MAGIC; // Initialize mtc table.
|
||||
|
||||
u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)mtc_cfg);
|
||||
@@ -129,6 +129,7 @@ void minerva_change_freq(minerva_freq_t freq)
|
||||
if (!minerva_cfg)
|
||||
return;
|
||||
|
||||
// Check if requested frequency is different. Do not allow otherwise because it will hang.
|
||||
mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
|
||||
if (mtc_cfg->rate_from != freq)
|
||||
{
|
||||
|
||||
@@ -54,11 +54,6 @@ typedef struct _sdram_vendor_patch_t
|
||||
|
||||
#include "sdram_config_t210b01.inl"
|
||||
|
||||
static u32 _sdram_get_id()
|
||||
{
|
||||
return ((fuse_read_odm(4) & 0xF8) >> 3);
|
||||
}
|
||||
|
||||
static bool _sdram_wait_emc_status(u32 reg_offset, u32 bit_mask, bool updated_state, s32 emc_channel)
|
||||
{
|
||||
bool err = true;
|
||||
@@ -1374,9 +1369,7 @@ static void _sdram_patch_model_params_t210b01(u32 dramid, u32 *params)
|
||||
static void *_sdram_get_params_t210()
|
||||
{
|
||||
// Check if id is proper.
|
||||
u32 dramid = _sdram_get_id();
|
||||
if (dramid > 6)
|
||||
dramid = 0;
|
||||
u32 dramid = fuse_read_dramid(false);
|
||||
|
||||
#ifdef CONFIG_SDRAM_COMPRESS_CFG
|
||||
|
||||
@@ -1413,9 +1406,7 @@ static void *_sdram_get_params_t210()
|
||||
void *sdram_get_params_t210b01()
|
||||
{
|
||||
// Check if id is proper.
|
||||
u32 dramid = _sdram_get_id();
|
||||
if (dramid > 27)
|
||||
dramid = 8;
|
||||
u32 dramid = fuse_read_dramid(false);
|
||||
|
||||
u32 *buf = (u32 *)SDRAM_PARAMS_ADDR;
|
||||
memcpy(buf, &_dram_cfg_08_10_12_14_samsung_hynix_4gb, sizeof(sdram_params_t210b01_t));
|
||||
@@ -1439,12 +1430,12 @@ void *sdram_get_params_t210b01()
|
||||
case LPDDR4X_HOAG_4GB_SAMSUNG_1Y_X:
|
||||
case LPDDR4X_IOWA_4GB_SAMSUNG_1Y_Y:
|
||||
case LPDDR4X_IOWA_8GB_SAMSUNG_1Y_Y:
|
||||
case LPDDR4X_SDS_4GB_SAMSUNG_1Y_A:
|
||||
case LPDDR4X_SDS_8GB_SAMSUNG_1Y_X:
|
||||
case LPDDR4X_SDS_4GB_SAMSUNG_1Y_X:
|
||||
case LPDDR4X_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_SDS_4GB_MICRON_1Y_A:
|
||||
case LPDDR4X_AULA_4GB_MICRON_1Y_A:
|
||||
_sdram_patch_model_params_t210b01(dramid, (u32 *)buf);
|
||||
break;
|
||||
}
|
||||
@@ -1494,7 +1485,7 @@ static void _sdram_init_t210()
|
||||
const sdram_params_t210_t *params = (const sdram_params_t210_t *)_sdram_get_params_t210();
|
||||
|
||||
// Set DRAM voltage.
|
||||
max77620_regulator_set_voltage(REGULATOR_SD1, 1100000);
|
||||
max7762x_regulator_set_voltage(REGULATOR_SD1, 1100000);
|
||||
|
||||
// VDDP Select.
|
||||
PMC(APBDEV_PMC_VDDP_SEL) = params->pmc_vddp_sel;
|
||||
@@ -1539,8 +1530,8 @@ static void _sdram_init_t210b01()
|
||||
|
||||
void sdram_init()
|
||||
{
|
||||
// Configure SD regulator for DRAM.
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, 0x05);
|
||||
// Disable remote sense for SD1.
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, MAX77620_SD_CNF2_ROVS_EN_SD0 | MAX77620_SD_CNF2_RSVD);
|
||||
|
||||
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210)
|
||||
_sdram_init_t210();
|
||||
|
||||
@@ -45,7 +45,7 @@ enum sdram_ids_erista
|
||||
LPDDR4_ICOSA_4GB_SAMSUNG_K4F6E304HB_MGCH = 0,
|
||||
LPDDR4_ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 1,
|
||||
LPDDR4_ICOSA_4GB_MICRON_MT53B512M32D2NP_062_WT = 2,
|
||||
LPDDR4_COPPER_4GB_SAMSUNG_K4F6E304HB_MGCH = 3,
|
||||
LPDDR4_COPPER_4GB_SAMSUNG_K4F6E304HB_MGCH = 3, // Changed to AULA Hynix 4GB 1Y-A.
|
||||
LPDDR4_ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH = 4,
|
||||
LPDDR4_COPPER_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 5,
|
||||
LPDDR4_COPPER_4GB_MICRON_MT53B512M32D2NP_062_WT = 6,
|
||||
@@ -76,14 +76,14 @@ enum sdram_ids_mariko
|
||||
LPDDR4X_IOWA_4GB_SAMSUNG_1Y_Y = 20,
|
||||
LPDDR4X_IOWA_8GB_SAMSUNG_1Y_Y = 21,
|
||||
|
||||
LPDDR4X_SDS_4GB_SAMSUNG_1Y_A = 22,
|
||||
LPDDR4X_AULA_4GB_SAMSUNG_1Y_A = 22,
|
||||
|
||||
LPDDR4X_SDS_8GB_SAMSUNG_1Y_X = 23,
|
||||
LPDDR4X_SDS_4GB_SAMSUNG_1Y_X = 24,
|
||||
LPDDR4X_AULA_8GB_SAMSUNG_1Y_X = 23,
|
||||
LPDDR4X_AULA_4GB_SAMSUNG_1Y_X = 24,
|
||||
|
||||
LPDDR4X_IOWA_4GB_MICRON_1Y_A = 25,
|
||||
LPDDR4X_HOAG_4GB_MICRON_1Y_A = 26,
|
||||
LPDDR4X_SDS_4GB_MICRON_1Y_A = 27
|
||||
LPDDR4X_AULA_4GB_MICRON_1Y_A = 27
|
||||
};
|
||||
|
||||
void sdram_init();
|
||||
|
||||
@@ -97,7 +97,7 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = {
|
||||
* DRAM size information
|
||||
* Specifies the value for EMC_ADR_CFG
|
||||
*/
|
||||
.emc_adr_cfg = 0x00000001, // 2 populated DRAM Devices.
|
||||
.emc_adr_cfg = 0x00000001, // 2 Ranks.
|
||||
|
||||
/*
|
||||
* Specifies the time to wait after asserting pin
|
||||
@@ -243,7 +243,7 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = {
|
||||
.emc_cfg_dig_dll = 0x002C00A0,
|
||||
.emc_cfg_dig_dll_1 = 0x00003701,
|
||||
.emc_cfg_dig_dll_period = 0x00008000,
|
||||
.emc_dev_select = 0x00000000, // Both devices.
|
||||
.emc_dev_select = 0x00000000, // Both Ranks.
|
||||
.emc_sel_dpd_ctrl = 0x00040008,
|
||||
|
||||
/* Pads trimmer delays */
|
||||
@@ -406,7 +406,7 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = {
|
||||
.pmc_ddr_ctrl = 0x0007FF8B,
|
||||
.emc_acpd_control = 0x00000000,
|
||||
|
||||
.emc_swizzle_rank0_byte0 = 0x76543201,
|
||||
.emc_swizzle_rank0_byte0 = 0x76543201, // Overridden to 0x76543201 by spare6/7.
|
||||
.emc_swizzle_rank0_byte1 = 0x65324710,
|
||||
.emc_swizzle_rank0_byte2 = 0x25763410,
|
||||
.emc_swizzle_rank0_byte3 = 0x25673401,
|
||||
@@ -454,7 +454,7 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = {
|
||||
.emc_pmacro_data_rx_term_mode = 0x00000010,
|
||||
.emc_pmacro_cmd_rx_term_mode = 0x00003000,
|
||||
.emc_pmacro_data_pad_tx_ctrl = 0x02000111,
|
||||
.emc_pmacro_common_pad_tx_ctrl = 0x00000008,
|
||||
.emc_pmacro_common_pad_tx_ctrl = 0x00000008, // Overridden to 0x0000000A by spare4/5.
|
||||
.emc_pmacro_cmd_pad_tx_ctrl = 0x0A000000,
|
||||
|
||||
.emc_cfg3 = 0x00000040,
|
||||
@@ -490,9 +490,9 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = {
|
||||
.emc_pmacro_cmd_ctrl2 = 0x0A0A0A0A,
|
||||
|
||||
/* DRAM size information */
|
||||
.mc_emem_adr_cfg = 0x00000001, // 2 populated DRAM Devices.
|
||||
.mc_emem_adr_cfg_dev0 = 0x00070302, // Density 512MB.
|
||||
.mc_emem_adr_cfg_dev1 = 0x00070302, // Density 512MB.
|
||||
.mc_emem_adr_cfg = 0x00000001, // 2 Ranks.
|
||||
.mc_emem_adr_cfg_dev0 = 0x00070302, // Rank 0 Density 512MB.
|
||||
.mc_emem_adr_cfg_dev1 = 0x00070302, // Rank 1 Density 512MB.
|
||||
.mc_emem_adr_cfg_channel_mask = 0xFFFF2400,
|
||||
.mc_emem_adr_cfg_bank_mask0 = 0x6E574400,
|
||||
.mc_emem_adr_cfg_bank_mask1 = 0x39722800,
|
||||
@@ -653,8 +653,8 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210[] = {
|
||||
{ 0x00000005, 368, DRAM_ID(1) | DRAM_ID(5) }, // mc_emem_arb_timing_r2w.
|
||||
|
||||
// Samsung 6GB density config.
|
||||
{ 0x000C0302, 347, DRAM_ID(4) }, // mc_emem_adr_cfg_dev0. 768MB sub-partition density.
|
||||
{ 0x000C0302, 348, DRAM_ID(4) }, // mc_emem_adr_cfg_dev1. 768MB sub-partition density.
|
||||
{ 0x000C0302, 347, 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.
|
||||
{ 0x00001800, 353, DRAM_ID(4) }, // mc_emem_cfg. 6GB total density.
|
||||
|
||||
#ifdef CONFIG_SDRAM_COPPER_SUPPORT
|
||||
|
||||
@@ -122,7 +122,7 @@ static const sdram_params_t210b01_t _dram_cfg_08_10_12_14_samsung_hynix_4gb = {
|
||||
* DRAM size information
|
||||
* Specifies the value for EMC_ADR_CFG
|
||||
*/
|
||||
.emc_adr_cfg = 0x00000000, // 1 populated DRAM Device.
|
||||
.emc_adr_cfg = 0x00000000, // 1 Rank.
|
||||
|
||||
/*
|
||||
* Specifies the time to wait after asserting pin
|
||||
@@ -273,7 +273,7 @@ static const sdram_params_t210b01_t _dram_cfg_08_10_12_14_samsung_hynix_4gb = {
|
||||
.emc_cfg_dig_dll = 0x002C00A0,
|
||||
.emc_cfg_dig_dll_1 = 0x000F3701,
|
||||
.emc_cfg_dig_dll_period = 0x00008000,
|
||||
.emc_dev_select = 0x00000002, // Dev0 only.
|
||||
.emc_dev_select = 0x00000002, // Rank 0 only.
|
||||
.emc_sel_dpd_ctrl = 0x0004000C,
|
||||
|
||||
/* Pads trimmer delays */
|
||||
@@ -543,9 +543,9 @@ static const sdram_params_t210b01_t _dram_cfg_08_10_12_14_samsung_hynix_4gb = {
|
||||
.emc_pmacro_cmd_ctrl2 = 0x00000000,
|
||||
|
||||
/* DRAM size information */
|
||||
.mc_emem_adr_cfg = 0x00000000, // 1 populated DRAM Device.
|
||||
.mc_emem_adr_cfg_dev0 = 0x00080302, // Density 1024MB.
|
||||
.mc_emem_adr_cfg_dev1 = 0x00080302, // Density 1024MB.
|
||||
.mc_emem_adr_cfg = 0x00000000, // 1 Rank.
|
||||
.mc_emem_adr_cfg_dev0 = 0x00080302, // Rank 0 Density 1024MB.
|
||||
.mc_emem_adr_cfg_dev1 = 0x00080302, // Rank 1 Density 1024MB.
|
||||
.mc_emem_adr_cfg_channel_mask = 0xFFFF2400,
|
||||
.mc_emem_adr_cfg_bank_mask0 = 0x6E574400,
|
||||
.mc_emem_adr_cfg_bank_mask1 = 0x39722800,
|
||||
@@ -733,7 +733,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = {
|
||||
// Samsung LPDDR4X 8GB K4UBE3D4AM-MGCJ for SDEV Iowa and Hoag.
|
||||
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_auto_cal_config2.
|
||||
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_auto_cal_vref_sel0.
|
||||
{ 0x00000001, 0x134 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_adr_cfg. 2 populated DRAM Devices.
|
||||
{ 0x00000001, 0x134 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_adr_cfg. 2 Ranks.
|
||||
{ 0x00000006, 0x1CC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_quse.
|
||||
{ 0x00000005, 0x1D0 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_quse_width.
|
||||
{ 0x00000003, 0x1DC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_einput.
|
||||
@@ -764,7 +764,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = {
|
||||
{ 0x40000001, 0x45C / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_zcal_init_dev1.
|
||||
{ 0x00000000, 0x594 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_tx_pwrd4.
|
||||
{ 0x00001000, 0x598 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_tx_pwrd5.
|
||||
{ 0x00000001, 0x630 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_adr_cfg. 2 populated DRAM Devices.
|
||||
{ 0x00000001, 0x630 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_adr_cfg. 2 Ranks.
|
||||
{ 0x00002000, 0x64C / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_cfg. 8GB total density.
|
||||
{ 0x00000002, 0x680 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_arb_timing_r2r.
|
||||
{ 0x02020001, 0x694 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_arb_da_turns.
|
||||
@@ -810,7 +810,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = {
|
||||
{ 0x2A800000, 0x6DC / 4, DRAM_ID2(16) }, // mc_video_protect_gpu_override0.
|
||||
{ 0x00000002, 0x6E0 / 4, DRAM_ID2(16) }, // mc_video_protect_gpu_override1.
|
||||
|
||||
// Samsung LPDDR4X 4GB 10nm-class (1y) Die-X for Iowa, Hoag and SDS.
|
||||
// Samsung LPDDR4X 4GB 10nm-class (1y) Die-X for Iowa, Hoag and Aula.
|
||||
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_auto_cal_config2.
|
||||
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_auto_cal_vref_sel0.
|
||||
{ 0x00000006, 0x1CC / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_quse.
|
||||
@@ -822,10 +822,10 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = {
|
||||
{ 0x2A800000, 0x6DC / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // mc_video_protect_gpu_override0.
|
||||
{ 0x00000002, 0x6E0 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // mc_video_protect_gpu_override1.
|
||||
|
||||
// Samsung LPDDR4X 8GB 10nm-class (1y) Die-X for SDEV Iowa and SDS.
|
||||
// Samsung LPDDR4X 8GB 10nm-class (1y) Die-X for SDEV Iowa and Aula.
|
||||
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_auto_cal_config2.
|
||||
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_auto_cal_vref_sel0.
|
||||
{ 0x00000001, 0x134 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_adr_cfg. 2 populated DRAM Devices.
|
||||
{ 0x00000001, 0x134 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_adr_cfg. 2 Ranks.
|
||||
{ 0x00000006, 0x1CC / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_quse.
|
||||
{ 0x00000005, 0x1D0 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_quse_width.
|
||||
{ 0x00000003, 0x1DC / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_einput.
|
||||
@@ -847,7 +847,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = {
|
||||
{ 0x40000001, 0x45C / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_zcal_init_dev1.
|
||||
{ 0x00000000, 0x594 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_pmacro_tx_pwrd4.
|
||||
{ 0x00001000, 0x598 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_pmacro_tx_pwrd5.
|
||||
{ 0x00000001, 0x630 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_adr_cfg. 2 populated DRAM Devices.
|
||||
{ 0x00000001, 0x630 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_adr_cfg. 2 Ranks.
|
||||
{ 0x00002000, 0x64C / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_cfg. 8GB total density.
|
||||
{ 0x00000001, 0x670 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_arb_timing_faw.
|
||||
{ 0x00000002, 0x680 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_arb_timing_r2r.
|
||||
@@ -881,7 +881,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = {
|
||||
// Samsung LPDDR4X 8GB 10nm-class (1y) Die-Y for SDEV Iowa.
|
||||
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(21) }, // emc_auto_cal_config2.
|
||||
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(21) }, // emc_auto_cal_vref_sel0.
|
||||
{ 0x00000001, 0x134 / 4, DRAM_ID2(21) }, // emc_adr_cfg. 2 populated DRAM Devices.
|
||||
{ 0x00000001, 0x134 / 4, DRAM_ID2(21) }, // emc_adr_cfg. 2 Ranks.
|
||||
{ 0x00000008, 0x24C / 4, DRAM_ID2(21) }, // emc_tfaw.
|
||||
{ 0x08010004, 0x2B8 / 4, DRAM_ID2(21) }, // emc_mrw1.
|
||||
{ 0x08020000, 0x2BC / 4, DRAM_ID2(21) }, // emc_mrw2.
|
||||
@@ -914,7 +914,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = {
|
||||
{ 0x40000001, 0x45C / 4, DRAM_ID2(21) }, // emc_zcal_init_dev1.
|
||||
{ 0x00000000, 0x594 / 4, DRAM_ID2(21) }, // emc_pmacro_tx_pwrd4.
|
||||
{ 0x00001000, 0x598 / 4, DRAM_ID2(21) }, // emc_pmacro_tx_pwrd5.
|
||||
{ 0x00000001, 0x630 / 4, DRAM_ID2(21) }, // mc_emem_adr_cfg. 2 populated DRAM Devices.
|
||||
{ 0x00000001, 0x630 / 4, DRAM_ID2(21) }, // mc_emem_adr_cfg. 2 Ranks.
|
||||
{ 0x00002000, 0x64C / 4, DRAM_ID2(21) }, // mc_emem_cfg. 8GB total density.
|
||||
{ 0x00000001, 0x670 / 4, DRAM_ID2(21) }, // mc_emem_arb_timing_faw.
|
||||
{ 0x00000002, 0x680 / 4, DRAM_ID2(21) }, // mc_emem_arb_timing_r2r.
|
||||
@@ -922,7 +922,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = {
|
||||
{ 0x2A800000, 0x6DC / 4, DRAM_ID2(21) }, // mc_video_protect_gpu_override0.
|
||||
{ 0x00000002, 0x6E0 / 4, DRAM_ID2(21) }, // mc_video_protect_gpu_override1.
|
||||
|
||||
// Samsung LPDDR4X 4GB 10nm-class (1y) Die-A for Unknown SDS.
|
||||
// Samsung LPDDR4X 4GB 10nm-class (1y) Die-A for Unknown Aula.
|
||||
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(22) }, // emc_auto_cal_config2.
|
||||
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(22) }, // emc_auto_cal_vref_sel0.
|
||||
{ 0x00000008, 0x24C / 4, DRAM_ID2(22) }, // emc_tfaw.
|
||||
@@ -986,7 +986,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = {
|
||||
{ 0x00000002, 0x6E0 / 4, DRAM_ID2(22) }, // mc_video_protect_gpu_override1.
|
||||
{ 0x0000009C, 0x814 / 4, DRAM_ID2(22) }, // swizzle_rank_byte_encode.
|
||||
|
||||
// Micron LPDDR4X 4GB 10nm-class (1y) Die-A for Unknown Iowa/Hoag/SDS.
|
||||
// Micron LPDDR4X 4GB 10nm-class (1y) Die-A for Unknown Iowa/Hoag/Aula.
|
||||
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_auto_cal_config2.
|
||||
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_auto_cal_vref_sel0.
|
||||
{ 0x00000006, 0x1CC / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_quse.
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
/*
|
||||
* Defining registers address and its bit definitions of MAX77620 and MAX20024
|
||||
*
|
||||
* Copyright (c) 2016 NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2019 CTCaer
|
||||
* Copyright (c) 2019-2020 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -30,24 +29,33 @@
|
||||
#define MAX77620_CNFGGLBL1_LBHYST_200 (1 << 4)
|
||||
#define MAX77620_CNFGGLBL1_LBHYST_300 (2 << 4)
|
||||
#define MAX77620_CNFGGLBL1_LBHYST_400 (3 << 4)
|
||||
#define MAX77620_CNFGGLBL1_LBHYST (BIT(5) | BIT(4))
|
||||
#define MAX77620_CNFGGLBL1_MPPLD BIT(6)
|
||||
#define MAX77620_CNFGGLBL1_LBDAC_EN BIT(7)
|
||||
|
||||
#define MAX77620_REG_CNFGGLBL2 0x01
|
||||
#define MAX77620_REG_CNFGGLBL3 0x02
|
||||
#define MAX77620_WDTC_MASK 0x3
|
||||
#define MAX77620_WDTEN BIT(2)
|
||||
#define MAX77620_WDTSLPC BIT(3)
|
||||
#define MAX77620_WDTOFFC BIT(4)
|
||||
#define MAX77620_TWD_MASK 0x3
|
||||
#define MAX77620_TWD_2s 0x0
|
||||
#define MAX77620_TWD_16s 0x1
|
||||
#define MAX77620_TWD_64s 0x2
|
||||
#define MAX77620_TWD_128s 0x3
|
||||
#define MAX77620_WDTEN BIT(2)
|
||||
#define MAX77620_WDTSLPC BIT(3)
|
||||
#define MAX77620_WDTOFFC BIT(4)
|
||||
#define MAX77620_GLBL_LPM BIT(5)
|
||||
#define MAX77620_I2CTWD_MASK 0xC0
|
||||
#define MAX77620_I2CTWD_DISABLED 0x00
|
||||
#define MAX77620_I2CTWD_1_33ms 0x40
|
||||
#define MAX77620_I2CTWD_35_7ms 0x80
|
||||
#define MAX77620_I2CTWD_41_7ms 0xC0
|
||||
|
||||
#define MAX77620_REG_CNFGGLBL3 0x02
|
||||
#define MAX77620_WDTC_MASK 0x3
|
||||
|
||||
#define MAX77620_REG_CNFG1_32K 0x03
|
||||
#define MAX77620_CNFG1_PWR_MD_32K_MASK 0x3
|
||||
#define MAX77620_CNFG1_32K_OUT0_EN BIT(2)
|
||||
#define MAX77620_CNFG1_32KLOAD_MASK 0x30
|
||||
#define MAX77620_CNFG1_32K_OK BIT(7)
|
||||
|
||||
#define MAX77620_REG_CNFGBBC 0x04
|
||||
#define MAX77620_CNFGBBC_ENABLE BIT(0)
|
||||
@@ -64,6 +72,7 @@
|
||||
#define MAX77620_CNFGBBC_RESISTOR_6K (3 << MAX77620_CNFGBBC_RESISTOR_SHIFT)
|
||||
|
||||
#define MAX77620_REG_IRQTOP 0x05
|
||||
#define MAX77620_REG_IRQTOPM 0x0D
|
||||
#define MAX77620_IRQ_TOP_ONOFF_MASK BIT(1)
|
||||
#define MAX77620_IRQ_TOP_32K_MASK BIT(2)
|
||||
#define MAX77620_IRQ_TOP_RTC_MASK BIT(3)
|
||||
@@ -73,28 +82,53 @@
|
||||
#define MAX77620_IRQ_TOP_GLBL_MASK BIT(7)
|
||||
|
||||
#define MAX77620_REG_INTLBT 0x06
|
||||
#define MAX77620_REG_IRQTOPM 0x0D
|
||||
#define MAX77620_REG_INTENLBT 0x0E
|
||||
#define MAX77620_IRQ_GLBLM_MASK BIT(0)
|
||||
#define MAX77620_IRQ_TJALRM2_MASK BIT(1)
|
||||
#define MAX77620_IRQ_TJALRM1_MASK BIT(2)
|
||||
#define MAX77620_IRQ_LBM_MASK BIT(3)
|
||||
|
||||
#define MAX77620_REG_IRQSD 0x07
|
||||
#define MAX77620_REG_IRQ_LVL2_L0_7 0x08
|
||||
#define MAX77620_REG_IRQ_LVL2_L8 0x09
|
||||
#define MAX77620_REG_IRQ_LVL2_GPIO 0x0A
|
||||
#define MAX77620_REG_ONOFFIRQ 0x0B
|
||||
#define MAX77620_REG_NVERC 0x0C
|
||||
|
||||
#define MAX77620_REG_INTENLBT 0x0E
|
||||
#define MAX77620_GLBLM_MASK BIT(0)
|
||||
|
||||
#define MAX77620_REG_IRQMASKSD 0x0F
|
||||
#define MAX77620_IRQSD_PFI_SD3 BIT(4)
|
||||
#define MAX77620_IRQSD_PFI_SD2 BIT(5)
|
||||
#define MAX77620_IRQSD_PFI_SD1 BIT(6)
|
||||
#define MAX77620_IRQSD_PFI_SD0 BIT(7)
|
||||
|
||||
#define MAX77620_REG_IRQ_LVL2_L0_7 0x08 // LDO number that irq occured.
|
||||
#define MAX77620_REG_IRQ_MSK_L0_7 0x10
|
||||
#define MAX77620_REG_IRQ_LVL2_L8 0x09 // LDO number that irq occured. Only bit0: LDO8 is valid.
|
||||
#define MAX77620_REG_IRQ_MSK_L8 0x11
|
||||
#define MAX77620_REG_IRQ_LVL2_GPIO 0x0A // Edge detection interrupt.
|
||||
|
||||
#define MAX77620_REG_ONOFFIRQ 0x0B
|
||||
#define MAX77620_REG_ONOFFIRQM 0x12
|
||||
#define MAX77620_ONOFFIRQ_MRWRN BIT(0)
|
||||
#define MAX77620_ONOFFIRQ_EN0_1SEC BIT(1)
|
||||
#define MAX77620_ONOFFIRQ_EN0_F BIT(2)
|
||||
#define MAX77620_ONOFFIRQ_EN0_R BIT(3)
|
||||
#define MAX77620_ONOFFIRQ_LID_F BIT(4)
|
||||
#define MAX77620_ONOFFIRQ_LID_R BIT(5)
|
||||
#define MAX77620_ONOFFIRQ_ACOK_F BIT(6)
|
||||
#define MAX77620_ONOFFIRQ_ACOK_R BIT(7)
|
||||
|
||||
#define MAX77620_REG_NVERC 0x0C // Shutdown reason (non-volatile).
|
||||
#define MAX77620_NVERC_SHDN BIT(0)
|
||||
#define MAX77620_NVERC_WTCHDG BIT(1)
|
||||
#define MAX77620_NVERC_HDRST BIT(2)
|
||||
#define MAX77620_NVERC_TOVLD BIT(3)
|
||||
#define MAX77620_NVERC_MBLSD BIT(4)
|
||||
#define MAX77620_NVERC_MBO BIT(5)
|
||||
#define MAX77620_NVERC_MBU BIT(6)
|
||||
#define MAX77620_NVERC_RSTIN BIT(7)
|
||||
|
||||
#define MAX77620_REG_STATLBT 0x13
|
||||
#define MAX77620_REG_STATSD 0x14
|
||||
|
||||
#define MAX77620_REG_ONOFFSTAT 0x15
|
||||
#define MAX77620_ONOFFSTAT_LID BIT(0)
|
||||
#define MAX77620_ONOFFSTAT_ACOK BIT(1)
|
||||
#define MAX77620_ONOFFSTAT_EN0 BIT(2)
|
||||
|
||||
/* SD and LDO Registers */
|
||||
#define MAX77620_REG_SD0 0x16
|
||||
@@ -102,18 +136,42 @@
|
||||
#define MAX77620_REG_SD2 0x18
|
||||
#define MAX77620_REG_SD3 0x19
|
||||
#define MAX77620_REG_SD4 0x1A
|
||||
#define MAX77620_REG_DVSSD0 0x1B
|
||||
#define MAX77620_REG_DVSSD1 0x1C
|
||||
#define MAX77620_SDX_VOLT_MASK 0xFF
|
||||
#define MAX77620_SD0_VOLT_MASK 0x3F
|
||||
#define MAX77620_SD1_VOLT_MASK 0x7F
|
||||
#define MAX77620_LDO_VOLT_MASK 0x3F
|
||||
#define MAX77620_REG_DVSSD0 0x1B
|
||||
#define MAX77620_REG_DVSSD1 0x1C
|
||||
#define MAX77620_REG_SD0_CFG 0x1D // SD CNFG1.
|
||||
#define MAX77620_REG_SD1_CFG 0x1E // SD CNFG1.
|
||||
#define MAX77620_REG_SD2_CFG 0x1F // SD CNFG1.
|
||||
#define MAX77620_REG_SD3_CFG 0x20 // SD CNFG1.
|
||||
#define MAX77620_REG_SD4_CFG 0x21 // SD CNFG1.
|
||||
|
||||
#define MAX77620_REG_SD0_CFG 0x1D
|
||||
#define MAX77620_REG_SD1_CFG 0x1E
|
||||
#define MAX77620_REG_SD2_CFG 0x1F
|
||||
#define MAX77620_REG_SD3_CFG 0x20
|
||||
#define MAX77620_REG_SD4_CFG 0x21
|
||||
#define MAX77620_SD_SR_MASK 0xC0
|
||||
#define MAX77620_SD_SR_SHIFT 6
|
||||
#define MAX77620_SD_POWER_MODE_MASK 0x30
|
||||
#define MAX77620_SD_POWER_MODE_SHIFT 4
|
||||
#define MAX77620_SD_CFG1_ADE_MASK BIT(3)
|
||||
#define MAX77620_SD_CFG1_ADE_DISABLE 0
|
||||
#define MAX77620_SD_CFG1_ADE_ENABLE BIT(3)
|
||||
#define MAX77620_SD_FPWM_MASK 0x04
|
||||
#define MAX77620_SD_FPWM_SHIFT 2
|
||||
#define MAX77620_SD_FSRADE_MASK 0x01
|
||||
#define MAX77620_SD_FSRADE_SHIFT 0
|
||||
#define MAX77620_SD_CFG1_FPWM_SD_MASK BIT(2)
|
||||
#define MAX77620_SD_CFG1_FPWM_SD_SKIP 0
|
||||
#define MAX77620_SD_CFG1_FPWM_SD_FPWM BIT(2)
|
||||
#define MAX77620_SD_CFG1_MPOK_MASK BIT(1)
|
||||
#define MAX77620_SD_CFG1_FSRADE_SD_MASK BIT(0)
|
||||
#define MAX77620_SD_CFG1_FSRADE_SD_DISABLE 0
|
||||
#define MAX77620_SD_CFG1_FSRADE_SD_ENABLE BIT(0)
|
||||
|
||||
#define MAX77620_REG_SD_CFG2 0x22
|
||||
#define MAX77620_SD_CNF2_RSVD BIT(0)
|
||||
#define MAX77620_SD_CNF2_ROVS_EN_SD1 BIT(1)
|
||||
#define MAX77620_SD_CNF2_ROVS_EN_SD0 BIT(2)
|
||||
|
||||
#define MAX77620_REG_LDO0_CFG 0x23
|
||||
#define MAX77620_REG_LDO0_CFG2 0x24
|
||||
#define MAX77620_REG_LDO1_CFG 0x25
|
||||
@@ -132,26 +190,36 @@
|
||||
#define MAX77620_REG_LDO7_CFG2 0x32
|
||||
#define MAX77620_REG_LDO8_CFG 0x33
|
||||
#define MAX77620_REG_LDO8_CFG2 0x34
|
||||
#define MAX77620_LDO_CFG2_SS_MASK (1 << 0)
|
||||
#define MAX77620_LDO_CFG2_SS_FAST (1 << 0)
|
||||
#define MAX77620_LDO_CFG2_SS_SLOW 0
|
||||
#define MAX77620_LDO_CFG2_ADE_MASK (1 << 1)
|
||||
#define MAX77620_LDO_CFG2_ADE_DISABLE (0 << 1)
|
||||
#define MAX77620_LDO_CFG2_ADE_ENABLE (1 << 1)
|
||||
#define MAX20024_LDO_CFG2_MPOK_MASK BIT(2)
|
||||
#define MAX77620_LDO_POWER_MODE_MASK 0xC0
|
||||
/*! LDO CFG */
|
||||
#define MAX77620_LDO_POWER_MODE_SHIFT 6
|
||||
#define MAX77620_LDO_POWER_MODE_MASK (3 << MAX77620_LDO_POWER_MODE_SHIFT)
|
||||
#define MAX77620_POWER_MODE_NORMAL 3
|
||||
#define MAX77620_POWER_MODE_LPM 2
|
||||
#define MAX77620_POWER_MODE_GLPM 1
|
||||
#define MAX77620_POWER_MODE_DISABLE 0
|
||||
/*! LDO CFG2 */
|
||||
#define MAX77620_LDO_CFG2_SS_MASK (1 << 0)
|
||||
#define MAX77620_LDO_CFG2_SS_FAST (0 << 0)
|
||||
#define MAX77620_LDO_CFG2_SS_SLOW (1 << 0)
|
||||
#define MAX77620_LDO_CFG2_ADE_MASK (1 << 1)
|
||||
#define MAX77620_LDO_CFG2_ADE_DISABLE (0 << 1)
|
||||
#define MAX77620_LDO_CFG2_ADE_ENABLE (1 << 1)
|
||||
#define MAX77620_LDO_CFG2_MPOK_MASK BIT(2)
|
||||
#define MAX77620_LDO_CFG2_POK_MASK BIT(3)
|
||||
#define MAX77620_LDO_CFG2_COMP_SHIFT 4
|
||||
#define MAX77620_LDO_CFG2_COMP_MASK (3 << MAX77620_LDO_COMP_SHIFT)
|
||||
#define MAX77620_LDO_CFG2_COMP_SLOW 3
|
||||
#define MAX77620_LDO_CFG2_COMP_MID_SLOW 2
|
||||
#define MAX77620_LDO_CFG2_COMP_MID_FAST 1
|
||||
#define MAX77620_LDO_CFG2_COMP_FAST 0
|
||||
#define MAX77620_LDO_CFG2_ALPM_EN_MASK BIT(6)
|
||||
#define MAX77620_LDO_CFG2_OVCLMP_MASK BIT(7)
|
||||
|
||||
#define MAX77620_REG_LDO_CFG3 0x35
|
||||
#define MAX77620_LDO_BIAS_EN BIT(0)
|
||||
#define MAX77620_TRACK4_SHIFT 5
|
||||
#define MAX77620_TRACK4_MASK (1 << MAX77620_TRACK4_SHIFT)
|
||||
|
||||
#define MAX77620_LDO_SLEW_RATE_MASK 0x1
|
||||
|
||||
#define MAX77620_REG_GPIO0 0x36
|
||||
#define MAX77620_REG_GPIO1 0x37
|
||||
#define MAX77620_REG_GPIO2 0x38
|
||||
@@ -160,9 +228,6 @@
|
||||
#define MAX77620_REG_GPIO5 0x3B
|
||||
#define MAX77620_REG_GPIO6 0x3C
|
||||
#define MAX77620_REG_GPIO7 0x3D
|
||||
#define MAX77620_REG_PUE_GPIO 0x3E
|
||||
#define MAX77620_REG_PDE_GPIO 0x3F
|
||||
#define MAX77620_REG_AME_GPIO 0x40
|
||||
#define MAX77620_CNFG_GPIO_DRV_MASK (1 << 0)
|
||||
#define MAX77620_CNFG_GPIO_DRV_PUSHPULL (1 << 0)
|
||||
#define MAX77620_CNFG_GPIO_DRV_OPENDRAIN (0 << 0)
|
||||
@@ -181,6 +246,13 @@
|
||||
#define MAX77620_CNFG_GPIO_DBNC_8ms (0x1 << 6)
|
||||
#define MAX77620_CNFG_GPIO_DBNC_16ms (0x2 << 6)
|
||||
#define MAX77620_CNFG_GPIO_DBNC_32ms (0x3 << 6)
|
||||
#define MAX77620_GPIO_OUTPUT_DISABLE 0
|
||||
#define MAX77620_GPIO_OUTPUT_ENABLE 1
|
||||
|
||||
#define MAX77620_REG_PUE_GPIO 0x3E // Gpio Pullup resistor enable.
|
||||
#define MAX77620_REG_PDE_GPIO 0x3F // Gpio Pulldown resistor enable.
|
||||
|
||||
#define MAX77620_REG_AME_GPIO 0x40 // Gpio pinmuxing. Clear bits are Standard GPIO.
|
||||
|
||||
#define MAX77620_REG_ONOFFCNFG1 0x41
|
||||
#define MAX20024_ONOFFCNFG1_CLRSE 0x18
|
||||
@@ -188,19 +260,30 @@
|
||||
#define MAX77620_ONOFFCNFG1_SLPEN BIT(2)
|
||||
#define MAX77620_ONOFFCNFG1_MRT_SHIFT 0x3
|
||||
#define MAX77620_ONOFFCNFG1_MRT_MASK 0x38
|
||||
#define MAX77620_ONOFFCNFG1_RSVD BIT(6)
|
||||
#define MAX77620_ONOFFCNFG1_SFT_RST BIT(7)
|
||||
|
||||
#define MAX77620_REG_ONOFFCNFG2 0x42
|
||||
#define MAX77620_ONOFFCNFG2_WK_EN0 BIT(0)
|
||||
#define MAX77620_ONOFFCNFG2_WK_ALARM2 BIT(1)
|
||||
#define MAX77620_ONOFFCNFG2_WK_ALARM1 BIT(2)
|
||||
#define MAX77620_ONOFFCNFG2_WK_MBATT BIT(3) // MBATT event generates a wakeup signal. use it in android/l4t?
|
||||
#define MAX77620_ONOFFCNFG2_WK_ACOK BIT(4)
|
||||
#define MAX77620_ONOFFCNFG2_SLP_LPM_MSK BIT(5)
|
||||
#define MAX77620_ONOFFCNFG2_WD_RST_WK BIT(6)
|
||||
#define MAX77620_ONOFFCNFG2_SFT_RST_WK BIT(7)
|
||||
|
||||
/* FPS Registers */
|
||||
#define MAX77620_REG_FPS_CFG0 0x43
|
||||
#define MAX77620_REG_FPS_CFG1 0x44
|
||||
#define MAX77620_REG_FPS_CFG2 0x45
|
||||
#define MAX77620_REG_FPS_CFG0 0x43 // FPS0.
|
||||
#define MAX77620_REG_FPS_CFG1 0x44 // FPS1.
|
||||
#define MAX77620_REG_FPS_CFG2 0x45 // FPS2.
|
||||
#define MAX77620_FPS_ENFPS_SW_MASK 0x01
|
||||
#define MAX77620_FPS_ENFPS_SW 0x01
|
||||
#define MAX77620_FPS_EN_SRC_SHIFT 1
|
||||
#define MAX77620_FPS_EN_SRC_MASK 0x06
|
||||
#define MAX77620_FPS_TIME_PERIOD_SHIFT 3
|
||||
#define MAX77620_FPS_TIME_PERIOD_MASK 0x38
|
||||
|
||||
#define MAX77620_REG_FPS_LDO0 0x46
|
||||
#define MAX77620_REG_FPS_LDO1 0x47
|
||||
#define MAX77620_REG_FPS_LDO2 0x48
|
||||
@@ -215,77 +298,39 @@
|
||||
#define MAX77620_REG_FPS_SD2 0x51
|
||||
#define MAX77620_REG_FPS_SD3 0x52
|
||||
#define MAX77620_REG_FPS_SD4 0x53
|
||||
#define MAX77620_REG_FPS_NONE 0
|
||||
#define MAX77620_FPS_SRC_MASK 0xC0
|
||||
#define MAX77620_FPS_SRC_SHIFT 6
|
||||
#define MAX77620_FPS_PU_PERIOD_MASK 0x38
|
||||
#define MAX77620_FPS_PU_PERIOD_SHIFT 3
|
||||
#define MAX77620_FPS_PD_PERIOD_MASK 0x07
|
||||
#define MAX77620_FPS_PD_PERIOD_SHIFT 0
|
||||
|
||||
/* Minimum and maximum FPS period time (in microseconds) are
|
||||
* different for MAX77620 and Max20024.
|
||||
*/
|
||||
#define MAX77620_FPS_COUNT 3
|
||||
|
||||
#define MAX77620_FPS_PERIOD_MIN_US 40
|
||||
#define MAX20024_FPS_PERIOD_MIN_US 20
|
||||
|
||||
#define MAX77620_FPS_PERIOD_MAX_US 2560
|
||||
#define MAX20024_FPS_PERIOD_MAX_US 5120
|
||||
|
||||
#define MAX77620_REG_FPS_GPIO1 0x54
|
||||
#define MAX77620_REG_FPS_GPIO2 0x55
|
||||
#define MAX77620_REG_FPS_GPIO3 0x56
|
||||
#define MAX77620_FPS_TIME_PERIOD_MASK 0x38
|
||||
#define MAX77620_FPS_TIME_PERIOD_SHIFT 3
|
||||
#define MAX77620_FPS_EN_SRC_MASK 0x06
|
||||
#define MAX77620_FPS_EN_SRC_SHIFT 1
|
||||
#define MAX77620_FPS_ENFPS_SW_MASK 0x01
|
||||
#define MAX77620_FPS_ENFPS_SW 0x01
|
||||
|
||||
#define MAX77620_REG_FPS_RSO 0x57
|
||||
#define MAX77620_FPS_PD_PERIOD_SHIFT 0
|
||||
#define MAX77620_FPS_PD_PERIOD_MASK 0x07
|
||||
#define MAX77620_FPS_PU_PERIOD_SHIFT 3
|
||||
#define MAX77620_FPS_PU_PERIOD_MASK 0x38
|
||||
#define MAX77620_FPS_SRC_SHIFT 6
|
||||
#define MAX77620_FPS_SRC_MASK 0xC0
|
||||
|
||||
#define MAX77620_FPS_COUNT 3
|
||||
#define MAX77620_FPS_PERIOD_MIN_US 40
|
||||
#define MAX77620_FPS_PERIOD_MAX_US 2560
|
||||
|
||||
#define MAX77620_REG_CID0 0x58
|
||||
#define MAX77620_REG_CID1 0x59
|
||||
#define MAX77620_REG_CID2 0x5A
|
||||
#define MAX77620_REG_CID3 0x5B
|
||||
#define MAX77620_REG_CID4 0x5C
|
||||
#define MAX77620_REG_CID4 0x5C // OTP version.
|
||||
#define MAX77620_REG_CID5 0x5D
|
||||
|
||||
#define MAX77620_REG_DVSSD4 0x5E
|
||||
#define MAX20024_REG_MAX_ADD 0x70
|
||||
|
||||
#define MAX77620_CID_DIDM_MASK 0xF0
|
||||
#define MAX77620_CID_DIDM_SHIFT 4
|
||||
|
||||
/* CNCG2SD */
|
||||
#define MAX77620_SD_CNF2_ROVS_EN_SD1 BIT(1)
|
||||
#define MAX77620_SD_CNF2_ROVS_EN_SD0 BIT(2)
|
||||
#define MAX77620_CID_DIDO_MASK 0xF
|
||||
#define MAX77620_CID_DIDO_SHIFT 0
|
||||
#define MAX77620_CID_DIDM_MASK 0xF0
|
||||
#define MAX77620_CID_DIDM_SHIFT 4
|
||||
|
||||
/* Device Identification Metal */
|
||||
#define MAX77620_CID5_DIDM(n) (((n) >> 4) & 0xF)
|
||||
/* Device Indentification OTP */
|
||||
#define MAX77620_CID5_DIDO(n) ((n) & 0xF)
|
||||
|
||||
/* SD CNFG1 */
|
||||
#define MAX77620_SD_SR_MASK 0xC0
|
||||
#define MAX77620_SD_SR_SHIFT 6
|
||||
#define MAX77620_SD_POWER_MODE_MASK 0x30
|
||||
#define MAX77620_SD_POWER_MODE_SHIFT 4
|
||||
#define MAX77620_SD_CFG1_ADE_MASK BIT(3)
|
||||
#define MAX77620_SD_CFG1_ADE_DISABLE 0
|
||||
#define MAX77620_SD_CFG1_ADE_ENABLE BIT(3)
|
||||
#define MAX77620_SD_FPWM_MASK 0x04
|
||||
#define MAX77620_SD_FPWM_SHIFT 2
|
||||
#define MAX77620_SD_FSRADE_MASK 0x01
|
||||
#define MAX77620_SD_FSRADE_SHIFT 0
|
||||
#define MAX77620_SD_CFG1_FPWM_SD_MASK BIT(2)
|
||||
#define MAX77620_SD_CFG1_FPWM_SD_SKIP 0
|
||||
#define MAX77620_SD_CFG1_FPWM_SD_FPWM BIT(2)
|
||||
#define MAX20024_SD_CFG1_MPOK_MASK BIT(1)
|
||||
#define MAX77620_SD_CFG1_FSRADE_SD_MASK BIT(0)
|
||||
#define MAX77620_SD_CFG1_FSRADE_SD_DISABLE 0
|
||||
#define MAX77620_SD_CFG1_FSRADE_SD_ENABLE BIT(0)
|
||||
#define MAX77620_REG_DVSSD4 0x5E
|
||||
#define MAX20024_REG_MAX_ADD 0x70
|
||||
|
||||
#define MAX77620_IRQ_LVL2_GPIO_EDGE0 BIT(0)
|
||||
#define MAX77620_IRQ_LVL2_GPIO_EDGE1 BIT(1)
|
||||
@@ -332,9 +377,4 @@ enum max77620_fps_src {
|
||||
MAX77620_FPS_SRC_DEF,
|
||||
};
|
||||
|
||||
enum max77620_chip_id {
|
||||
MAX77620,
|
||||
MAX20024,
|
||||
};
|
||||
|
||||
#endif /* _MFD_MAX77620_H_ */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2019 CTCaer
|
||||
* Copyright (c) 2019-2020 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -17,163 +17,322 @@
|
||||
|
||||
#include <power/max7762x.h>
|
||||
#include <power/max77620.h>
|
||||
#include <power/max77812.h>
|
||||
#include <soc/fuse.h>
|
||||
#include <soc/i2c.h>
|
||||
#include <soc/t210.h>
|
||||
#include <utils/util.h>
|
||||
|
||||
#define REGULATOR_SD 0
|
||||
#define REGULATOR_SD 0
|
||||
#define REGULATOR_LDO 1
|
||||
#define REGULATOR_BC0 2
|
||||
#define REGULATOR_BC1 3
|
||||
|
||||
typedef struct _max77620_regulator_t
|
||||
typedef struct _max77620_fps_t
|
||||
{
|
||||
u8 type;
|
||||
const char *name;
|
||||
u8 reg_sd;
|
||||
|
||||
u32 mv_step;
|
||||
u32 mv_min;
|
||||
u32 mv_default;
|
||||
u32 mv_max;
|
||||
|
||||
u8 volt_addr;
|
||||
u8 cfg_addr;
|
||||
|
||||
u8 volt_mask;
|
||||
u8 enable_mask;
|
||||
u8 enable_shift;
|
||||
u8 status_mask;
|
||||
|
||||
u8 fps_addr;
|
||||
u8 fps_src;
|
||||
u8 pd_period;
|
||||
u8 pu_period;
|
||||
} max77620_fps_t;
|
||||
|
||||
typedef struct _max77621_ctrl_t
|
||||
{
|
||||
u8 ctrl1_por;
|
||||
u8 ctrl1_hos;
|
||||
u8 ctrl2_por;
|
||||
u8 ctrl2_hos;
|
||||
} max77621_ctrl_t;
|
||||
|
||||
typedef struct _max77812_ctrl_t
|
||||
{
|
||||
u8 mask;
|
||||
u8 shift;
|
||||
u8 rsvd0;
|
||||
u8 rsvd1;
|
||||
} max77812_en_t;
|
||||
|
||||
typedef struct _max77620_regulator_t
|
||||
{
|
||||
const char *name;
|
||||
|
||||
u32 uv_step;
|
||||
u32 uv_min;
|
||||
u32 uv_default;
|
||||
u32 uv_max;
|
||||
|
||||
u8 type;
|
||||
u8 volt_addr;
|
||||
u8 cfg_addr;
|
||||
u8 volt_mask;
|
||||
|
||||
union {
|
||||
max77620_fps_t fps;
|
||||
max77621_ctrl_t ctrl;
|
||||
max77812_en_t enable;
|
||||
};
|
||||
} max77620_regulator_t;
|
||||
|
||||
static const max77620_regulator_t _pmic_regulators[] = {
|
||||
{ REGULATOR_SD, "sd0", 0x16, 12500, 600000, 625000, 1400000, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, MAX77620_SD0_VOLT_MASK, MAX77620_SD_POWER_MODE_MASK, MAX77620_SD_POWER_MODE_SHIFT, 0x80, MAX77620_REG_FPS_SD0, 1, 7, 1 },
|
||||
{ REGULATOR_SD, "sd1", 0x17, 12500, 600000, 1125000, 1125000, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, MAX77620_SD1_VOLT_MASK, MAX77620_SD_POWER_MODE_MASK, MAX77620_SD_POWER_MODE_SHIFT, 0x40, MAX77620_REG_FPS_SD1, 0, 1, 5 },
|
||||
{ REGULATOR_SD, "sd2", 0x18, 12500, 600000, 1325000, 1350000, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, MAX77620_SDX_VOLT_MASK, MAX77620_SD_POWER_MODE_MASK, MAX77620_SD_POWER_MODE_SHIFT, 0x20, MAX77620_REG_FPS_SD2, 1, 5, 2 },
|
||||
{ REGULATOR_SD, "sd3", 0x19, 12500, 600000, 1800000, 1800000, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, MAX77620_SDX_VOLT_MASK, MAX77620_SD_POWER_MODE_MASK, MAX77620_SD_POWER_MODE_SHIFT, 0x10, MAX77620_REG_FPS_SD3, 0, 3, 3 },
|
||||
{ REGULATOR_LDO, "ldo0", 0x00, 25000, 800000, 1200000, 1200000, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO0, 3, 7, 0 },
|
||||
{ REGULATOR_LDO, "ldo1", 0x00, 25000, 800000, 1050000, 1050000, MAX77620_REG_LDO1_CFG, MAX77620_REG_LDO1_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO1, 3, 7, 0 },
|
||||
{ REGULATOR_LDO, "ldo2", 0x00, 50000, 800000, 1800000, 3300000, MAX77620_REG_LDO2_CFG, MAX77620_REG_LDO2_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO2, 3, 7, 0 },
|
||||
{ REGULATOR_LDO, "ldo3", 0x00, 50000, 800000, 3100000, 3100000, MAX77620_REG_LDO3_CFG, MAX77620_REG_LDO3_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO3, 3, 7, 0 },
|
||||
{ REGULATOR_LDO, "ldo4", 0x00, 12500, 800000, 850000, 850000, MAX77620_REG_LDO4_CFG, MAX77620_REG_LDO4_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO4, 0, 7, 1 },
|
||||
{ REGULATOR_LDO, "ldo5", 0x00, 50000, 800000, 1800000, 1800000, MAX77620_REG_LDO5_CFG, MAX77620_REG_LDO5_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO5, 3, 7, 0 },
|
||||
{ REGULATOR_LDO, "ldo6", 0x00, 50000, 800000, 2900000, 2900000, MAX77620_REG_LDO6_CFG, MAX77620_REG_LDO6_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO6, 3, 7, 0 },
|
||||
{ REGULATOR_LDO, "ldo7", 0x00, 50000, 800000, 1050000, 1050000, MAX77620_REG_LDO7_CFG, MAX77620_REG_LDO7_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO7, 1, 4, 3 },
|
||||
{ REGULATOR_LDO, "ldo8", 0x00, 50000, 800000, 1050000, 2800000, MAX77620_REG_LDO8_CFG, MAX77620_REG_LDO8_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO8, 3, 7, 0 }
|
||||
{ "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 }} },
|
||||
{ "sd2", 12500, 600000, 1325000, 1350000, REGULATOR_SD, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD2, 1, 5, 2 }} },
|
||||
{ "sd3", 12500, 600000, 1800000, 1800000, REGULATOR_SD, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD3, 0, 3, 3 }} },
|
||||
{ "ldo0", 25000, 800000, 1200000, 1200000, REGULATOR_LDO, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO0, 3, 7, 0 }} },
|
||||
{ "ldo1", 25000, 800000, 1050000, 1050000, REGULATOR_LDO, MAX77620_REG_LDO1_CFG, MAX77620_REG_LDO1_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO1, 3, 7, 0 }} },
|
||||
{ "ldo2", 50000, 800000, 1800000, 3300000, REGULATOR_LDO, MAX77620_REG_LDO2_CFG, MAX77620_REG_LDO2_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO2, 3, 7, 0 }} },
|
||||
{ "ldo3", 50000, 800000, 3100000, 3100000, REGULATOR_LDO, MAX77620_REG_LDO3_CFG, MAX77620_REG_LDO3_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO3, 3, 7, 0 }} },
|
||||
{ "ldo4", 12500, 800000, 850000, 1000000, REGULATOR_LDO, MAX77620_REG_LDO4_CFG, MAX77620_REG_LDO4_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO4, 0, 7, 1 }} },
|
||||
{ "ldo5", 50000, 800000, 1800000, 1800000, REGULATOR_LDO, MAX77620_REG_LDO5_CFG, MAX77620_REG_LDO5_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO5, 3, 7, 0 }} },
|
||||
{ "ldo6", 50000, 800000, 2900000, 2900000, REGULATOR_LDO, MAX77620_REG_LDO6_CFG, MAX77620_REG_LDO6_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO6, 3, 7, 0 }} },
|
||||
{ "ldo7", 50000, 800000, 1050000, 1050000, REGULATOR_LDO, MAX77620_REG_LDO7_CFG, MAX77620_REG_LDO7_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO7, 1, 4, 3 }} },
|
||||
{ "ldo8", 50000, 800000, 1050000, 2800000, REGULATOR_LDO, MAX77620_REG_LDO8_CFG, MAX77620_REG_LDO8_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO8, 3, 7, 0 }} },
|
||||
|
||||
{ "max77621_CPU", 6250, 606250, 1000000, 1400000, REGULATOR_BC0, MAX77621_VOUT_REG, MAX77621_VOUT_DVS_REG, MAX77621_DVC_DVS_VOLT_MASK, {{ MAX77621_CPU_CTRL1_POR_DEFAULT, MAX77621_CPU_CTRL1_HOS_DEFAULT, MAX77621_CPU_CTRL2_POR_DEFAULT, MAX77621_CPU_CTRL2_HOS_DEFAULT }} },
|
||||
{ "max77621_GPU", 6250, 606250, 1200000, 1400000, REGULATOR_BC0, MAX77621_VOUT_REG, MAX77621_VOUT_DVS_REG, MAX77621_DVC_DVS_VOLT_MASK, {{ MAX77621_CPU_CTRL1_POR_DEFAULT, MAX77621_CPU_CTRL1_HOS_DEFAULT, MAX77621_CPU_CTRL2_POR_DEFAULT, MAX77621_CPU_CTRL2_HOS_DEFAULT }} },
|
||||
{ "max77812_CPU", 5000, 250000, 600000, 1525000, REGULATOR_BC1, MAX77812_REG_M4_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M4_MASK, MAX77812_EN_CTRL_EN_M4_SHIFT, 0, 0 }} },
|
||||
//{ "max77812_GPU", 5000, 250000, 600000, 1525000, REGULATOR_BC1, MAX77812_REG_M1_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M1_MASK, MAX77812_EN_CTRL_EN_M1_SHIFT, 0, 0 }} },
|
||||
//{ "max77812_RAM", 5000, 250000, 600000, 1525000, REGULATOR_BC1, MAX77812_REG_M3_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M3_MASK, MAX77812_EN_CTRL_EN_M3_SHIFT, 0, 0 }} } // Only on PHASE211 configuration.
|
||||
};
|
||||
|
||||
static void _max77620_set_reg(u8 reg, u8 val)
|
||||
static u8 _max77812_get_address()
|
||||
{
|
||||
static u8 max77812_i2c_addr = 0;
|
||||
|
||||
if (max77812_i2c_addr)
|
||||
return max77812_i2c_addr;
|
||||
|
||||
max77812_i2c_addr =
|
||||
!(FUSE(FUSE_RESERVED_ODM28_T210B01) & 1) ? MAX77812_PHASE31_CPU_I2C_ADDR : MAX77812_PHASE211_CPU_I2C_ADDR;
|
||||
|
||||
return max77812_i2c_addr;
|
||||
}
|
||||
|
||||
static u8 _max7762x_get_i2c_address(u32 id)
|
||||
{
|
||||
const max77620_regulator_t *reg = &_pmic_regulators[id];
|
||||
|
||||
// Choose the correct i2c address.
|
||||
switch (reg->type)
|
||||
{
|
||||
case REGULATOR_SD:
|
||||
case REGULATOR_LDO:
|
||||
return MAX77620_I2C_ADDR;
|
||||
case REGULATOR_BC0:
|
||||
return (id == REGULATOR_CPU0 ? MAX77621_CPU_I2C_ADDR : MAX77621_GPU_I2C_ADDR);
|
||||
case REGULATOR_BC1:
|
||||
return _max77812_get_address();
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void _max7762x_set_reg(u8 addr, u8 reg, u8 val)
|
||||
{
|
||||
u32 retries = 100;
|
||||
while (retries)
|
||||
{
|
||||
if (i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, reg, val))
|
||||
if (i2c_send_byte(I2C_5, addr, reg, val))
|
||||
break;
|
||||
usleep(100);
|
||||
|
||||
usleep(50);
|
||||
retries--;
|
||||
}
|
||||
}
|
||||
|
||||
int max77620_regulator_get_status(u32 id)
|
||||
{
|
||||
if (id > REGULATOR_MAX)
|
||||
if (id > REGULATOR_LDO8)
|
||||
return 0;
|
||||
|
||||
const max77620_regulator_t *reg = &_pmic_regulators[id];
|
||||
|
||||
// SD power OK status.
|
||||
if (reg->type == REGULATOR_SD)
|
||||
return (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_STATSD) & reg->status_mask) ? 0 : 1;
|
||||
return (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, reg->cfg_addr) & 8) ? 1 : 0;
|
||||
{
|
||||
u8 mask = 1u << (7 - id);
|
||||
return (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_STATSD) & mask) ? 0 : 1;
|
||||
}
|
||||
|
||||
// LDO power OK status.
|
||||
return (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, reg->cfg_addr) & MAX77620_LDO_CFG2_POK_MASK) ? 1 : 0;
|
||||
}
|
||||
|
||||
int max77620_regulator_config_fps(u32 id)
|
||||
{
|
||||
if (id > REGULATOR_MAX)
|
||||
if (id > REGULATOR_LDO8)
|
||||
return 0;
|
||||
|
||||
const max77620_regulator_t *reg = &_pmic_regulators[id];
|
||||
|
||||
_max77620_set_reg(reg->fps_addr,
|
||||
(reg->fps_src << MAX77620_FPS_SRC_SHIFT) | (reg->pu_period << MAX77620_FPS_PU_PERIOD_SHIFT) | (reg->pd_period));
|
||||
// Set FPS configuration.
|
||||
_max7762x_set_reg(MAX77620_I2C_ADDR,
|
||||
reg->fps.fps_addr,
|
||||
(reg->fps.fps_src << MAX77620_FPS_SRC_SHIFT) |
|
||||
(reg->fps.pu_period << MAX77620_FPS_PU_PERIOD_SHIFT) |
|
||||
(reg->fps.pd_period << MAX77620_FPS_PD_PERIOD_SHIFT));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int max77620_regulator_set_voltage(u32 id, u32 mv)
|
||||
int max7762x_regulator_set_voltage(u32 id, u32 mv)
|
||||
{
|
||||
if (id > REGULATOR_MAX)
|
||||
return 0;
|
||||
|
||||
const max77620_regulator_t *reg = &_pmic_regulators[id];
|
||||
|
||||
if (mv < reg->mv_min || mv > reg->mv_max)
|
||||
if (mv < reg->uv_min || mv > reg->uv_max)
|
||||
return 0;
|
||||
|
||||
u32 mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step;
|
||||
u8 val = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, reg->volt_addr);
|
||||
u8 addr = _max7762x_get_i2c_address(id);
|
||||
|
||||
// Calculate voltage multiplier.
|
||||
u32 mult = (mv + reg->uv_step - 1 - reg->uv_min) / reg->uv_step;
|
||||
u8 val = i2c_recv_byte(I2C_5, addr, reg->volt_addr);
|
||||
val = (val & ~reg->volt_mask) | (mult & reg->volt_mask);
|
||||
_max77620_set_reg(reg->volt_addr, val);
|
||||
|
||||
// Set voltage.
|
||||
_max7762x_set_reg(addr, reg->volt_addr, val);
|
||||
|
||||
// If max77621 set DVS voltage also.
|
||||
if (reg->type == REGULATOR_BC0)
|
||||
_max7762x_set_reg(addr, reg->cfg_addr, MAX77621_VOUT_ENABLE_MASK | val);
|
||||
|
||||
// Wait for ramp up/down delay.
|
||||
usleep(1000);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int max77620_regulator_enable(u32 id, int enable)
|
||||
int max7762x_regulator_enable(u32 id, bool enable)
|
||||
{
|
||||
u8 reg_addr;
|
||||
u8 enable_val;
|
||||
u8 enable_mask;
|
||||
u8 enable_shift;
|
||||
|
||||
if (id > REGULATOR_MAX)
|
||||
return 0;
|
||||
|
||||
const max77620_regulator_t *reg = &_pmic_regulators[id];
|
||||
|
||||
u32 addr = reg->type == REGULATOR_SD ? reg->cfg_addr : reg->volt_addr;
|
||||
u8 val = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, addr);
|
||||
// Choose the correct i2c and register addresses and mask/shift for each type.
|
||||
switch (reg->type)
|
||||
{
|
||||
case REGULATOR_SD:
|
||||
reg_addr = reg->cfg_addr;
|
||||
enable_val = MAX77620_POWER_MODE_NORMAL;
|
||||
enable_mask = MAX77620_SD_POWER_MODE_MASK;
|
||||
enable_shift = MAX77620_SD_POWER_MODE_SHIFT;
|
||||
break;
|
||||
case REGULATOR_LDO:
|
||||
reg_addr = reg->volt_addr;
|
||||
enable_val = MAX77620_POWER_MODE_NORMAL;
|
||||
enable_mask = MAX77620_LDO_POWER_MODE_MASK;
|
||||
enable_shift = MAX77620_LDO_POWER_MODE_SHIFT;
|
||||
break;
|
||||
case REGULATOR_BC0:
|
||||
reg_addr = reg->volt_addr;
|
||||
enable_val = MAX77621_VOUT_ENABLE;
|
||||
enable_mask = MAX77621_DVC_DVS_ENABLE_MASK;
|
||||
enable_shift = MAX77621_DVC_DVS_ENABLE_SHIFT;
|
||||
break;
|
||||
case REGULATOR_BC1:
|
||||
reg_addr = reg->cfg_addr;
|
||||
enable_val = MAX77812_EN_CTRL_ENABLE;
|
||||
enable_mask = reg->enable.mask;
|
||||
enable_shift = reg->enable.shift;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
u8 addr = _max7762x_get_i2c_address(id);
|
||||
|
||||
// Read and enable/disable.
|
||||
u8 val = i2c_recv_byte(I2C_5, addr, reg_addr);
|
||||
val &= ~enable_mask;
|
||||
|
||||
if (enable)
|
||||
val = (val & ~reg->enable_mask) | ((MAX77620_POWER_MODE_NORMAL << reg->enable_shift) & reg->enable_mask);
|
||||
else
|
||||
val &= ~reg->enable_mask;
|
||||
_max77620_set_reg(addr, val);
|
||||
val |= (enable_val << enable_shift);
|
||||
|
||||
// Set enable.
|
||||
_max7762x_set_reg(addr, reg_addr, val);
|
||||
|
||||
// Wait for enable/disable ramp delay.
|
||||
usleep(1000);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// LDO only.
|
||||
int max77620_regulator_set_volt_and_flags(u32 id, u32 mv, u8 flags)
|
||||
void max77620_config_gpio(u32 gpio_id, bool enable)
|
||||
{
|
||||
if (id > REGULATOR_MAX)
|
||||
return 0;
|
||||
if (gpio_id > 7)
|
||||
return;
|
||||
|
||||
// Configure as standard GPIO.
|
||||
u8 val = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO);
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO, val & ~BIT(gpio_id));
|
||||
|
||||
// Set GPIO configuration.
|
||||
if (enable)
|
||||
val = MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH | MAX77620_CNFG_GPIO_DIR_OUTPUT | MAX77620_CNFG_GPIO_DRV_PUSHPULL;
|
||||
else
|
||||
val = MAX77620_CNFG_GPIO_DIR_INPUT | MAX77620_CNFG_GPIO_DRV_OPENDRAIN;
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO0 + gpio_id, val);
|
||||
}
|
||||
|
||||
void max77621_config_default(u32 id, bool por)
|
||||
{
|
||||
const max77620_regulator_t *reg = &_pmic_regulators[id];
|
||||
|
||||
if (mv < reg->mv_min || mv > reg->mv_max)
|
||||
return 0;
|
||||
if (reg->type != REGULATOR_BC0)
|
||||
return;
|
||||
|
||||
u32 mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step;
|
||||
u8 val = ((flags << reg->enable_shift) & ~reg->volt_mask) | (mult & reg->volt_mask);
|
||||
_max77620_set_reg(reg->volt_addr, val);
|
||||
usleep(1000);
|
||||
u8 addr = _max7762x_get_i2c_address(id);
|
||||
|
||||
return 1;
|
||||
if (por)
|
||||
{
|
||||
// Set voltage and disable power before changing the inductor.
|
||||
max7762x_regulator_set_voltage(id, 1000000);
|
||||
max7762x_regulator_enable(id, false);
|
||||
|
||||
// Configure to default.
|
||||
i2c_send_byte(I2C_5, addr, MAX77621_CONTROL1_REG, reg->ctrl.ctrl1_por);
|
||||
i2c_send_byte(I2C_5, addr, MAX77621_CONTROL2_REG, reg->ctrl.ctrl2_por);
|
||||
}
|
||||
else
|
||||
{
|
||||
i2c_send_byte(I2C_5, addr, MAX77621_CONTROL1_REG, reg->ctrl.ctrl1_hos);
|
||||
i2c_send_byte(I2C_5, addr, MAX77621_CONTROL2_REG, reg->ctrl.ctrl2_hos);
|
||||
}
|
||||
}
|
||||
|
||||
void max77620_config_default()
|
||||
{
|
||||
for (u32 i = 1; i <= REGULATOR_MAX; i++)
|
||||
// Check if Erista OTP.
|
||||
if (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CID4) != 0x35)
|
||||
return;
|
||||
|
||||
// Set default voltages and enable regulators.
|
||||
for (u32 i = 1; i <= REGULATOR_LDO8; i++)
|
||||
{
|
||||
i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CID4);
|
||||
max77620_regulator_config_fps(i);
|
||||
max77620_regulator_set_voltage(i, _pmic_regulators[i].mv_default);
|
||||
if (_pmic_regulators[i].fps_src != MAX77620_FPS_SRC_NONE)
|
||||
max77620_regulator_enable(i, 1);
|
||||
max7762x_regulator_set_voltage(i, _pmic_regulators[i].uv_default);
|
||||
if (_pmic_regulators[i].fps.fps_src != MAX77620_FPS_SRC_NONE)
|
||||
max7762x_regulator_enable(i, true);
|
||||
}
|
||||
_max77620_set_reg(MAX77620_REG_SD_CFG2, 4);
|
||||
|
||||
// Enable SD0 output voltage sense and disable for SD1. Additionally disable the reserved bit.
|
||||
_max7762x_set_reg(MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, MAX77620_SD_CNF2_ROVS_EN_SD0);
|
||||
}
|
||||
|
||||
void max77620_low_battery_monitor_config(bool enable)
|
||||
{
|
||||
_max77620_set_reg(MAX77620_REG_CNFGGLBL1,
|
||||
MAX77620_CNFGGLBL1_LBDAC_EN | (enable ? MAX77620_CNFGGLBL1_MPPLD : 0) |
|
||||
MAX77620_CNFGGLBL1_LBHYST_200 | MAX77620_CNFGGLBL1_LBDAC_2800);
|
||||
_max7762x_set_reg(MAX77620_I2C_ADDR, MAX77620_REG_CNFGGLBL1,
|
||||
MAX77620_CNFGGLBL1_LBDAC_EN |
|
||||
(enable ? MAX77620_CNFGGLBL1_MPPLD : 0) |
|
||||
MAX77620_CNFGGLBL1_LBHYST_200 |
|
||||
MAX77620_CNFGGLBL1_LBDAC_2800);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2019 CTCaer
|
||||
* Copyright (c) 2019-2020 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -45,10 +45,10 @@
|
||||
*/
|
||||
|
||||
/*! MAX77620 partitions. */
|
||||
#define REGULATOR_SD0 0
|
||||
#define REGULATOR_SD1 1
|
||||
#define REGULATOR_SD2 2
|
||||
#define REGULATOR_SD3 3
|
||||
#define REGULATOR_SD0 0
|
||||
#define REGULATOR_SD1 1
|
||||
#define REGULATOR_SD2 2
|
||||
#define REGULATOR_SD3 3
|
||||
#define REGULATOR_LDO0 4
|
||||
#define REGULATOR_LDO1 5
|
||||
#define REGULATOR_LDO2 6
|
||||
@@ -58,26 +58,40 @@
|
||||
#define REGULATOR_LDO6 10
|
||||
#define REGULATOR_LDO7 11
|
||||
#define REGULATOR_LDO8 12
|
||||
#define REGULATOR_MAX 12
|
||||
#define REGULATOR_CPU0 13
|
||||
#define REGULATOR_GPU0 14
|
||||
#define REGULATOR_CPU1 15
|
||||
//#define REGULATOR_GPU1 16
|
||||
//#define REGULATOR_GPU1 17
|
||||
#define REGULATOR_MAX 15
|
||||
|
||||
#define MAX77621_CPU_I2C_ADDR 0x1B
|
||||
#define MAX77621_GPU_I2C_ADDR 0x1C
|
||||
|
||||
#define MAX77621_VOUT_REG 0
|
||||
#define MAX77621_VOUT_DVS_REG 1
|
||||
#define MAX77621_CONTROL1_REG 2
|
||||
#define MAX77621_CONTROL2_REG 3
|
||||
|
||||
/* MAX77621_VOUT */
|
||||
#define MAX77621_VOUT_ENABLE BIT(7)
|
||||
#define MAX77621_VOUT_MASK 0x7F
|
||||
#define MAX77621_VOUT_0_95V 0x37
|
||||
#define MAX77621_VOUT_1_09V 0x4F
|
||||
#define MAX77621_VOUT_REG 0x00
|
||||
#define MAX77621_VOUT_DVS_REG 0x01
|
||||
#define MAX77621_CONTROL1_REG 0x02
|
||||
#define MAX77621_CONTROL2_REG 0x03
|
||||
#define MAX77621_CHIPID1_REG 0x04
|
||||
#define MAX77621_CHIPID2_REG 0x05
|
||||
|
||||
/* MAX77621_VOUT_DVC_DVS */
|
||||
#define MAX77621_DVS_VOUT_MASK 0x7F
|
||||
#define MAX77621_DVC_DVS_VOLT_MASK 0x7F
|
||||
#define MAX77621_DVC_DVS_ENABLE_SHIFT 7
|
||||
#define MAX77621_DVC_DVS_ENABLE_MASK (1 << MAX77621_DVC_DVS_ENABLE_SHIFT)
|
||||
|
||||
/* MAX77621_VOUT */
|
||||
#define MAX77621_VOUT_DISABLE 0
|
||||
#define MAX77621_VOUT_ENABLE 1
|
||||
#define MAX77621_VOUT_ENABLE_MASK (MAX77621_VOUT_ENABLE << MAX77621_DVC_DVS_ENABLE_SHIFT)
|
||||
|
||||
/* MAX77621_CONTROL1 */
|
||||
#define MAX77621_RAMP_12mV_PER_US 0x0
|
||||
#define MAX77621_RAMP_25mV_PER_US 0x1
|
||||
#define MAX77621_RAMP_50mV_PER_US 0x2
|
||||
#define MAX77621_RAMP_200mV_PER_US 0x3
|
||||
#define MAX77621_RAMP_MASK 0x3
|
||||
|
||||
#define MAX77621_FREQSHIFT_9PER BIT(2)
|
||||
#define MAX77621_BIAS_ENABLE BIT(3)
|
||||
#define MAX77621_AD_ENABLE BIT(4)
|
||||
@@ -85,34 +99,50 @@
|
||||
#define MAX77621_FPWM_EN_M BIT(6)
|
||||
#define MAX77621_SNS_ENABLE BIT(7)
|
||||
|
||||
#define MAX77621_RAMP_12mV_PER_US 0x0
|
||||
#define MAX77621_RAMP_25mV_PER_US 0x1
|
||||
#define MAX77621_RAMP_50mV_PER_US 0x2
|
||||
#define MAX77621_RAMP_200mV_PER_US 0x3
|
||||
#define MAX77621_RAMP_MASK 0x3
|
||||
|
||||
/* MAX77621_CONTROL2 */
|
||||
#define MAX77621_FT_ENABLE BIT(4)
|
||||
#define MAX77621_DISCH_ENBABLE BIT(5)
|
||||
#define MAX77621_WDTMR_ENABLE BIT(6)
|
||||
#define MAX77621_T_JUNCTION_120 BIT(7)
|
||||
#define MAX77621_INDUCTOR_MIN_30_PER 0
|
||||
#define MAX77621_INDUCTOR_NOMINAL 1
|
||||
#define MAX77621_INDUCTOR_PLUS_30_PER 2
|
||||
#define MAX77621_INDUCTOR_PLUS_60_PER 3
|
||||
#define MAX77621_INDUCTOR_MASK 3
|
||||
|
||||
#define MAX77621_CKKADV_TRIP_DISABLE 0xC
|
||||
#define MAX77621_CKKADV_TRIP_75mV_PER_US 0x0
|
||||
#define MAX77621_CKKADV_TRIP_150mV_PER_US 0x4
|
||||
#define MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS 0x8
|
||||
#define MAX77621_CKKADV_TRIP_150mV_PER_US BIT(2)
|
||||
#define MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS BIT(3)
|
||||
#define MAX77621_CKKADV_TRIP_DISABLE (BIT(2) | BIT(3))
|
||||
#define MAX77621_CKKADV_TRIP_MASK (BIT(2) | BIT(3))
|
||||
|
||||
#define MAX77621_INDUCTOR_MIN_30_PER 0x0
|
||||
#define MAX77621_INDUCTOR_NOMINAL 0x1
|
||||
#define MAX77621_INDUCTOR_PLUS_30_PER 0x2
|
||||
#define MAX77621_INDUCTOR_PLUS_60_PER 0x3
|
||||
#define MAX77621_FT_ENABLE BIT(4)
|
||||
#define MAX77621_DISCH_ENABLE BIT(5)
|
||||
#define MAX77621_WDTMR_ENABLE BIT(6)
|
||||
#define MAX77621_T_JUNCTION_120 BIT(7)
|
||||
|
||||
#define MAX77621_CPU_CTRL1_POR_DEFAULT (MAX77621_RAMP_50mV_PER_US)
|
||||
#define MAX77621_CPU_CTRL1_HOS_DEFAULT (MAX77621_AD_ENABLE | \
|
||||
MAX77621_NFSR_ENABLE | \
|
||||
MAX77621_SNS_ENABLE | \
|
||||
MAX77621_RAMP_12mV_PER_US)
|
||||
#define MAX77621_CPU_CTRL2_POR_DEFAULT (MAX77621_T_JUNCTION_120 | \
|
||||
MAX77621_FT_ENABLE | \
|
||||
MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS | \
|
||||
MAX77621_CKKADV_TRIP_150mV_PER_US | \
|
||||
MAX77621_INDUCTOR_NOMINAL)
|
||||
#define MAX77621_CPU_CTRL2_HOS_DEFAULT (MAX77621_T_JUNCTION_120 | \
|
||||
MAX77621_WDTMR_ENABLE | \
|
||||
MAX77621_CKKADV_TRIP_75mV_PER_US | \
|
||||
MAX77621_INDUCTOR_NOMINAL)
|
||||
|
||||
#define MAX77621_CTRL_HOS_CFG 0
|
||||
#define MAX77621_CTRL_POR_CFG 1
|
||||
|
||||
int max77620_regulator_get_status(u32 id);
|
||||
int max77620_regulator_config_fps(u32 id);
|
||||
int max77620_regulator_set_voltage(u32 id, u32 mv);
|
||||
int max77620_regulator_enable(u32 id, int enable);
|
||||
int max77620_regulator_set_volt_and_flags(u32 id, u32 mv, u8 flags);
|
||||
int max7762x_regulator_set_voltage(u32 id, u32 mv);
|
||||
int max7762x_regulator_enable(u32 id, bool enable);
|
||||
void max77620_config_gpio(u32 id, bool enable);
|
||||
void max77620_config_default();
|
||||
void max77620_low_battery_monitor_config(bool enable);
|
||||
|
||||
void max77621_config_default(u32 id, bool por);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
#ifndef _MAX77812_H_
|
||||
#define _MAX77812_H_
|
||||
|
||||
#define MAX77812_PHASE31_CPU_I2C_ADDR 0x31
|
||||
#define MAX77812_PHASE211_CPU_I2C_ADDR 0x33
|
||||
#define MAX77812_PHASE31_CPU_I2C_ADDR 0x31 // 2 Outputs: 3-phase M1 + 1-phase M4.
|
||||
#define MAX77812_PHASE211_CPU_I2C_ADDR 0x33 // 3 Outputs: 2-phase M1 + 1-phase M3 + 1-phase M4.
|
||||
|
||||
#define MAX77812_REG_RSET 0x00
|
||||
#define MAX77812_REG_INT_SRC 0x01
|
||||
@@ -27,7 +27,15 @@
|
||||
#define MAX77812_REG_TOPSYS_INT_M 0x04
|
||||
#define MAX77812_REG_TOPSYS_STAT 0x05
|
||||
#define MAX77812_REG_EN_CTRL 0x06
|
||||
#define MAX77812_EN_CTRL_EN_M4 BIT(6)
|
||||
#define MAX77812_EN_CTRL_ENABLE 1
|
||||
#define MAX77812_EN_CTRL_EN_M1_SHIFT 0
|
||||
#define MAX77812_EN_CTRL_EN_M1_MASK (1 << MAX77812_EN_CTRL_EN_M1_SHIFT)
|
||||
#define MAX77812_EN_CTRL_EN_M2_SHIFT 2
|
||||
#define MAX77812_EN_CTRL_EN_M2_MASK (1 << MAX77812_EN_CTRL_EN_M2_SHIFT)
|
||||
#define MAX77812_EN_CTRL_EN_M3_SHIFT 4
|
||||
#define MAX77812_EN_CTRL_EN_M3_MASK (1 << MAX77812_EN_CTRL_EN_M3_SHIFT)
|
||||
#define MAX77812_EN_CTRL_EN_M4_SHIFT 6
|
||||
#define MAX77812_EN_CTRL_EN_M4_MASK (1 << MAX77812_EN_CTRL_EN_M4_SHIFT)
|
||||
#define MAX77812_REG_STUP_DLY2 0x07
|
||||
#define MAX77812_REG_STUP_DLY3 0x08
|
||||
#define MAX77812_REG_STUP_DLY4 0x09
|
||||
@@ -46,11 +54,10 @@
|
||||
#define MAX77812_REG_BUCK_INT 0x20
|
||||
#define MAX77812_REG_BUCK_INT_M 0x21
|
||||
#define MAX77812_REG_BUCK_STAT 0x22
|
||||
#define MAX77812_REG_M1_VOUT 0x23
|
||||
#define MAX77812_REG_M1_VOUT 0x23 // GPU.
|
||||
#define MAX77812_REG_M2_VOUT 0x24
|
||||
#define MAX77812_REG_M3_VOUT 0x25
|
||||
#define MAX77812_REG_M4_VOUT 0x26
|
||||
#define MAX77812_M4_VOUT_0_80V 0x6E
|
||||
#define MAX77812_REG_M3_VOUT 0x25 // DRAM on PHASE211.
|
||||
#define MAX77812_REG_M4_VOUT 0x26 // CPU.
|
||||
#define MAX77812_REG_M1_VOUT_D 0x27
|
||||
#define MAX77812_REG_M2_VOUT_D 0x28
|
||||
#define MAX77812_REG_M3_VOUT_D 0x29
|
||||
@@ -66,6 +73,8 @@
|
||||
#define MAX77812_REG_GLB_CFG1 0x33
|
||||
#define MAX77812_REG_GLB_CFG2 0x34
|
||||
#define MAX77812_REG_GLB_CFG3 0x35
|
||||
|
||||
/*! Protected area and settings only for MAX77812_REG_VERSION 4 */
|
||||
#define MAX77812_REG_GLB_CFG4 0x36
|
||||
#define MAX77812_REG_GLB_CFG5 0x37
|
||||
#define MAX77812_REG_GLB_CFG6 0x38
|
||||
@@ -91,10 +100,6 @@
|
||||
#define MAX77812_ES2_VERSION 0x04
|
||||
#define MAX77812_QS_VERSION 0x05
|
||||
|
||||
#define MAX77812_VOUT_MASK 0xFF
|
||||
#define MAX77812_VOUT_N_VOLTAGE 0xFF
|
||||
#define MAX77812_VOUT_VMIN 250000
|
||||
#define MAX77812_VOUT_VMAX 1525000
|
||||
#define MAX77812_VOUT_STEP 5000
|
||||
#define MAX77812_BUCK_VOLT_MASK 0xFF
|
||||
|
||||
#endif
|
||||
|
||||
58
bdk/sec/se.c
58
bdk/sec/se.c
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 CTCaer
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "se_t210.h"
|
||||
#include <mem/heap.h>
|
||||
#include <soc/bpmp.h>
|
||||
#include <soc/pmc.h>
|
||||
#include <soc/t210.h>
|
||||
#include <utils/util.h>
|
||||
|
||||
@@ -160,9 +161,11 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr
|
||||
|
||||
static void _se_aes_ctr_set(void *ctr)
|
||||
{
|
||||
u32 *data = (u32 *)ctr;
|
||||
for (u32 i = 0; i < 4; i++)
|
||||
SE(SE_CRYPTO_CTR_REG_OFFSET + 4 * i) = data[i];
|
||||
u32 data[TEGRA_SE_AES_BLOCK_SIZE / 4];
|
||||
memcpy(data, ctr, TEGRA_SE_AES_BLOCK_SIZE);
|
||||
|
||||
for (u32 i = 0; i < (TEGRA_SE_AES_BLOCK_SIZE / 4); i++)
|
||||
SE(SE_CRYPTO_CTR_REG_OFFSET + (4 * i)) = data[i];
|
||||
}
|
||||
|
||||
void se_rsa_acc_ctrl(u32 rs, u32 flags)
|
||||
@@ -190,8 +193,10 @@ u32 se_key_acc_ctrl_get(u32 ks)
|
||||
|
||||
void se_aes_key_set(u32 ks, void *key, u32 size)
|
||||
{
|
||||
u32 *data = (u32 *)key;
|
||||
for (u32 i = 0; i < size / 4; i++)
|
||||
u32 data[TEGRA_SE_AES_MAX_KEY_SIZE / 4];
|
||||
memcpy(data, key, size);
|
||||
|
||||
for (u32 i = 0; i < (size / 4); i++)
|
||||
{
|
||||
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i;
|
||||
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data[i];
|
||||
@@ -200,9 +205,10 @@ void se_aes_key_set(u32 ks, void *key, u32 size)
|
||||
|
||||
void se_aes_iv_set(u32 ks, void *iv)
|
||||
{
|
||||
u32 *data = (u32 *)iv;
|
||||
u32 data[TEGRA_SE_AES_BLOCK_SIZE / 4];
|
||||
memcpy(data, iv, TEGRA_SE_AES_BLOCK_SIZE);
|
||||
|
||||
for (u32 i = 0; i < TEGRA_SE_AES_MIN_KEY_SIZE / 4; i++)
|
||||
for (u32 i = 0; i < (TEGRA_SE_AES_BLOCK_SIZE / 4); i++)
|
||||
{
|
||||
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(QUAD_ORG_IV) | i;
|
||||
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data[i];
|
||||
@@ -211,17 +217,20 @@ void se_aes_iv_set(u32 ks, void *iv)
|
||||
|
||||
void se_aes_key_get(u32 ks, void *key, u32 size)
|
||||
{
|
||||
u32 *data = (u32 *)key;
|
||||
for (u32 i = 0; i < size / 4; i++)
|
||||
u32 data[TEGRA_SE_AES_MAX_KEY_SIZE / 4];
|
||||
|
||||
for (u32 i = 0; i < (size / 4); i++)
|
||||
{
|
||||
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i;
|
||||
data[i] = SE(SE_KEYTABLE_DATA0_REG_OFFSET);
|
||||
}
|
||||
|
||||
memcpy(key, data, size);
|
||||
}
|
||||
|
||||
void se_aes_key_clear(u32 ks)
|
||||
{
|
||||
for (u32 i = 0; i < TEGRA_SE_AES_MAX_KEY_SIZE / 4; i++)
|
||||
for (u32 i = 0; i < (TEGRA_SE_AES_MAX_KEY_SIZE / 4); i++)
|
||||
{
|
||||
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i;
|
||||
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = 0;
|
||||
@@ -230,7 +239,7 @@ void se_aes_key_clear(u32 ks)
|
||||
|
||||
void se_aes_iv_clear(u32 ks)
|
||||
{
|
||||
for (u32 i = 0; i < TEGRA_SE_AES_MIN_KEY_SIZE / 4; i++)
|
||||
for (u32 i = 0; i < (TEGRA_SE_AES_BLOCK_SIZE / 4); i++)
|
||||
{
|
||||
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(QUAD_ORG_IV) | i;
|
||||
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = 0;
|
||||
@@ -365,10 +374,10 @@ int se_aes_xts_crypt(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, void *src, u
|
||||
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;
|
||||
u32 *hash32 = (u32 *)hash;
|
||||
u32 hash32[TEGRA_SE_SHA_256_SIZE / 4];
|
||||
|
||||
//! TODO: src_size must be 512 bit aligned if continuing and not last block for SHA256.
|
||||
if (src_size > 0xFFFFFF || (u32)hash % 4 || !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;
|
||||
|
||||
// Setup config for SHA256.
|
||||
@@ -400,7 +409,8 @@ int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64
|
||||
SE(SE_SHA_MSG_LEFT_1_REG_OFFSET) = msg_left[1];
|
||||
|
||||
// Restore hash reg.
|
||||
for (u32 i = 0; i < 8; i++)
|
||||
memcpy(hash32, hash, TEGRA_SE_SHA_256_SIZE);
|
||||
for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++)
|
||||
SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)) = byte_swap_32(hash32[i]);
|
||||
}
|
||||
|
||||
@@ -417,8 +427,9 @@ int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64
|
||||
}
|
||||
|
||||
// Copy output hash.
|
||||
for (u32 i = 0; i < 8; i++)
|
||||
for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++)
|
||||
hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)));
|
||||
memcpy(hash, hash32, TEGRA_SE_SHA_256_SIZE);
|
||||
}
|
||||
|
||||
return res;
|
||||
@@ -431,7 +442,7 @@ int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size)
|
||||
|
||||
int se_calc_sha256_finalize(void *hash, u32 *msg_left)
|
||||
{
|
||||
u32 *hash32 = (u32 *)hash;
|
||||
u32 hash32[TEGRA_SE_SHA_256_SIZE / 4];
|
||||
int res = _se_execute_finalize();
|
||||
|
||||
// Backup message left.
|
||||
@@ -442,8 +453,9 @@ int se_calc_sha256_finalize(void *hash, u32 *msg_left)
|
||||
}
|
||||
|
||||
// Copy output hash.
|
||||
for (u32 i = 0; i < 8; i++)
|
||||
for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++)
|
||||
hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)));
|
||||
memcpy(hash, hash32, TEGRA_SE_SHA_256_SIZE);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -501,7 +513,7 @@ void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize)
|
||||
|
||||
// Save SRK to PMC secure scratches.
|
||||
SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(SRK);
|
||||
SE(0x80) = 0; // SE_CRYPTO_LAST_BLOCK
|
||||
SE(SE_CRYPTO_LAST_BLOCK) = 0;
|
||||
_se_execute_oneshot(OP_CTX_SAVE, NULL, 0, NULL, 0);
|
||||
|
||||
// End context save.
|
||||
@@ -510,10 +522,10 @@ void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize)
|
||||
|
||||
// Get SRK.
|
||||
u32 srk[4];
|
||||
srk[0] = PMC(0xC0);
|
||||
srk[1] = PMC(0xC4);
|
||||
srk[2] = PMC(0x224);
|
||||
srk[3] = PMC(0x228);
|
||||
srk[0] = PMC(APBDEV_PMC_SECURE_SCRATCH4);
|
||||
srk[1] = PMC(APBDEV_PMC_SECURE_SCRATCH5);
|
||||
srk[2] = PMC(APBDEV_PMC_SECURE_SCRATCH6);
|
||||
srk[3] = PMC(APBDEV_PMC_SECURE_SCRATCH7);
|
||||
|
||||
// Decrypt context.
|
||||
se_aes_key_clear(3);
|
||||
|
||||
@@ -265,6 +265,10 @@
|
||||
#define TEGRA_SE_AES_MIN_KEY_SIZE 16
|
||||
#define TEGRA_SE_AES_MAX_KEY_SIZE 32
|
||||
#define TEGRA_SE_AES_IV_SIZE 16
|
||||
#define TEGRA_SE_SHA_512_SIZE 64
|
||||
#define TEGRA_SE_SHA_384_SIZE 48
|
||||
#define TEGRA_SE_SHA_256_SIZE 32
|
||||
#define TEGRA_SE_SHA_192_SIZE 24
|
||||
#define TEGRA_SE_RNG_IV_SIZE 16
|
||||
#define TEGRA_SE_RNG_DT_SIZE 16
|
||||
#define TEGRA_SE_RNG_KEY_SIZE 16
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
*/
|
||||
|
||||
#include <soc/ccplex.h>
|
||||
#include <soc/fuse.h>
|
||||
#include <soc/hw_init.h>
|
||||
#include <soc/i2c.h>
|
||||
#include <soc/clock.h>
|
||||
@@ -29,27 +28,24 @@
|
||||
|
||||
void _ccplex_enable_power_t210()
|
||||
{
|
||||
u8 tmp = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO); // Get current pinmuxing
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO, tmp & ~BIT(5)); // Disable GPIO5 pinmuxing.
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO5, MAX77620_CNFG_GPIO_DRV_PUSHPULL | MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH);
|
||||
// Configure GPIO5 and enable output in order to power CPU pmic.
|
||||
max77620_config_gpio(5, MAX77620_GPIO_OUTPUT_ENABLE);
|
||||
|
||||
// Enable cores power.
|
||||
// Configure CPU pmic.
|
||||
// 1-3.x: MAX77621_NFSR_ENABLE.
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL1_REG,
|
||||
MAX77621_AD_ENABLE | MAX77621_NFSR_ENABLE | MAX77621_SNS_ENABLE | MAX77621_RAMP_12mV_PER_US);
|
||||
// 1.0.0-3.x: MAX77621_T_JUNCTION_120 | MAX77621_CKKADV_TRIP_DISABLE | MAX77621_INDUCTOR_NOMINAL.
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL2_REG,
|
||||
MAX77621_T_JUNCTION_120 | MAX77621_WDTMR_ENABLE | MAX77621_CKKADV_TRIP_75mV_PER_US| MAX77621_INDUCTOR_NOMINAL);
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_0_95V);
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_DVS_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_0_95V);
|
||||
max77621_config_default(REGULATOR_CPU0, MAX77621_CTRL_HOS_CFG);
|
||||
|
||||
// Set voltage and enable cores power.
|
||||
max7762x_regulator_set_voltage(REGULATOR_CPU0, 950000);
|
||||
max7762x_regulator_enable(REGULATOR_CPU0, true);
|
||||
}
|
||||
|
||||
void _ccplex_enable_power_t210b01()
|
||||
{
|
||||
u8 pmic_cpu_addr = !(FUSE(FUSE_RESERVED_ODM28) & 1) ? MAX77812_PHASE31_CPU_I2C_ADDR : MAX77812_PHASE211_CPU_I2C_ADDR;
|
||||
u8 tmp = i2c_recv_byte(I2C_5, pmic_cpu_addr, MAX77812_REG_EN_CTRL);
|
||||
i2c_send_byte(I2C_5, pmic_cpu_addr, MAX77812_REG_EN_CTRL, tmp | MAX77812_EN_CTRL_EN_M4);
|
||||
i2c_send_byte(I2C_5, pmic_cpu_addr, MAX77812_REG_M4_VOUT, MAX77812_M4_VOUT_0_80V);
|
||||
// Set voltage and enable cores power.
|
||||
max7762x_regulator_set_voltage(REGULATOR_CPU1, 800000);
|
||||
max7762x_regulator_enable(REGULATOR_CPU1, true);
|
||||
}
|
||||
|
||||
void ccplex_boot_cpu0(u32 entry)
|
||||
@@ -62,24 +58,31 @@ void ccplex_boot_cpu0(u32 entry)
|
||||
else
|
||||
_ccplex_enable_power_t210b01();
|
||||
|
||||
if (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & 0x40000000)) // PLLX_ENABLE.
|
||||
// Enable PLLX and set it to 300 MHz.
|
||||
if (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & PLLX_BASE_ENABLE)) // PLLX_ENABLE.
|
||||
{
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLX_MISC_3) &= 0xFFFFFFF7; // Disable IDDQ.
|
||||
usleep(2);
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x80404E02;
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x404E02;
|
||||
|
||||
// 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;
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x40404E02;
|
||||
// Enable PLLX.
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = PLLX_BASE_ENABLE | (4 << 20) | (78 << 8) | 2;
|
||||
}
|
||||
while (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & 0x8000000))
|
||||
// Wait for PLL to stabilize.
|
||||
while (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & PLLX_BASE_LOCK))
|
||||
;
|
||||
|
||||
// Configure MSELECT source and enable clock.
|
||||
// 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_OUT_ENB_V) = (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) & ~BIT(CLK_V_MSELECT)) | BIT(CLK_V_MSELECT);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = BIT(CLK_V_MSELECT);
|
||||
|
||||
// Configure initial CPU clock frequency and enable clock.
|
||||
CLOCK(CLK_RST_CONTROLLER_CCLK_BURST_POLICY) = 0x20008888;
|
||||
CLOCK(CLK_RST_CONTROLLER_CCLK_BURST_POLICY) = 0x20008888; // PLLX_OUT0_LJ.
|
||||
CLOCK(CLK_RST_CONTROLLER_SUPER_CCLK_DIVIDER) = 0x80000000;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = BIT(CLK_V_CPUG);
|
||||
|
||||
@@ -88,12 +91,12 @@ void ccplex_boot_cpu0(u32 entry)
|
||||
// CAR2PMC_CPU_ACK_WIDTH should be set to 0.
|
||||
CLOCK(CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2) &= 0xFFFFF000;
|
||||
|
||||
// Enable CPU rail.
|
||||
pmc_enable_partition(0, 1);
|
||||
// Enable CPU main rail.
|
||||
pmc_enable_partition(POWER_RAIL_CRAIL, ENABLE);
|
||||
// Enable cluster 0 non-CPU rail.
|
||||
pmc_enable_partition(15, 1);
|
||||
// Enable CE0 rail.
|
||||
pmc_enable_partition(14, 1);
|
||||
pmc_enable_partition(POWER_RAIL_C0NC, ENABLE);
|
||||
// Enable CPU0 rail.
|
||||
pmc_enable_partition(POWER_RAIL_CE0, ENABLE);
|
||||
|
||||
// Request and wait for RAM repair.
|
||||
FLOW_CTLR(FLOW_CTLR_RAM_REPAIR) = 1;
|
||||
@@ -113,7 +116,7 @@ void ccplex_boot_cpu0(u32 entry)
|
||||
// MC(MC_TZ_SECURITY_CTRL) = 1;
|
||||
|
||||
// Clear MSELECT reset.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_V) &= ~BIT(CLK_V_MSELECT);
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_V_CLR) = BIT(CLK_V_MSELECT);
|
||||
// Clear NONCPU reset.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR) = 0x20000000;
|
||||
// Clear CPU0 reset.
|
||||
|
||||
@@ -21,6 +21,23 @@
|
||||
#include <storage/sdmmc.h>
|
||||
#include <utils/util.h>
|
||||
|
||||
typedef struct _clock_osc_t
|
||||
{
|
||||
u32 freq;
|
||||
u16 min;
|
||||
u16 max;
|
||||
} clock_osc_t;
|
||||
|
||||
static const clock_osc_t _clock_osc_cnt[] = {
|
||||
{ 12000, 706, 757 },
|
||||
{ 13000, 766, 820 },
|
||||
{ 16800, 991, 1059 },
|
||||
{ 19200, 1133, 1210 },
|
||||
{ 26000, 1535, 1638 },
|
||||
{ 38400, 2268, 2418 },
|
||||
{ 48000, 2836, 3023 }
|
||||
};
|
||||
|
||||
/* clock_t: reset, enable, source, index, clk_src, clk_div */
|
||||
|
||||
static const clock_t _clock_uart[] = {
|
||||
@@ -42,7 +59,7 @@ static const clock_t _clock_i2c[] = {
|
||||
};
|
||||
|
||||
static clock_t _clock_se = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_SE, CLK_V_SE, 0, 0
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_SE, CLK_V_SE, 0, 0 // 408MHz.
|
||||
};
|
||||
|
||||
static clock_t _clock_tzram = {
|
||||
@@ -50,19 +67,19 @@ static clock_t _clock_tzram = {
|
||||
};
|
||||
|
||||
static clock_t _clock_host1x = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X, CLK_L_HOST1X, 4, 3
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X, CLK_L_HOST1X, 4, 3 // 163.2MHz.
|
||||
};
|
||||
static clock_t _clock_tsec = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_TSEC, CLK_U_TSEC, 0, 2
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_TSEC, CLK_U_TSEC, 0, 2 // 204MHz.
|
||||
};
|
||||
static clock_t _clock_sor_safe = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_NO_SOURCE, CLK_Y_SOR_SAFE, 0, 0
|
||||
};
|
||||
static clock_t _clock_sor0 = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_NO_SOURCE, CLK_X_SOR0, 0, 0
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_NOT_USED, CLK_X_SOR0, 0, 0
|
||||
};
|
||||
static clock_t _clock_sor1 = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_SOR1, CLK_X_SOR1, 0, 2
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_SOR1, CLK_X_SOR1, 0, 2 //204MHz.
|
||||
};
|
||||
static clock_t _clock_kfuse = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_KFUSE, 0, 0
|
||||
@@ -72,11 +89,11 @@ static clock_t _clock_cl_dvfs = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_W, CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_NO_SOURCE, CLK_W_DVFS, 0, 0
|
||||
};
|
||||
static clock_t _clock_coresight = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_CSITE, CLK_U_CSITE, 0, 4
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_CSITE, CLK_U_CSITE, 0, 4 // 136MHz.
|
||||
};
|
||||
|
||||
static clock_t _clock_pwm = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, CLK_L_PWM, 6, 4 // Fref: 6.4MHz. Stock PLLP / 54: 7.55MHz.
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, CLK_L_PWM, 6, 4 // Fref: 6.4MHz. HOS: PLLP / 54 = 7.55MHz.
|
||||
};
|
||||
|
||||
static clock_t _clock_sdmmc_legacy_tm = {
|
||||
@@ -218,13 +235,13 @@ void clock_disable_sor1()
|
||||
|
||||
void clock_enable_kfuse()
|
||||
{
|
||||
u32 kfuse_clk_unmask = ~BIT(CLK_H_KFUSE);
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) = (CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) & kfuse_clk_unmask) | BIT(CLK_H_KFUSE);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) &= kfuse_clk_unmask;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) = (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) & kfuse_clk_unmask) | BIT(CLK_H_KFUSE);
|
||||
usleep(10);
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) &= kfuse_clk_unmask;
|
||||
usleep(20);
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = BIT(CLK_H_KFUSE);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_CLR) = BIT(CLK_H_KFUSE);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_KFUSE);
|
||||
usleep(10); // Wait 10s to prevent glitching.
|
||||
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_KFUSE);
|
||||
usleep(20); // Wait 20s fo kfuse hw to init.
|
||||
}
|
||||
|
||||
void clock_disable_kfuse()
|
||||
@@ -721,3 +738,44 @@ void clock_sdmmc_disable(u32 id)
|
||||
_clock_sdmmc_is_reset(id);
|
||||
_clock_disable_pllc4(BIT(id));
|
||||
}
|
||||
|
||||
u32 clock_get_osc_freq()
|
||||
{
|
||||
CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET) = OSC_FREQ_DET_TRIG | (2 - 1); // 2 periods of 32.76KHz window.
|
||||
while (CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_BUSY)
|
||||
;
|
||||
u32 cnt = (CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_CNT);
|
||||
CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET) = 0;
|
||||
|
||||
// Return frequency in KHz.
|
||||
for (u32 i = 0; i < ARRAY_SIZE(_clock_osc_cnt); i++)
|
||||
if (cnt >= _clock_osc_cnt[i].min && cnt <= _clock_osc_cnt[i].max)
|
||||
return _clock_osc_cnt[i].freq;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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.
|
||||
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val;
|
||||
usleep(2);
|
||||
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val | PTO_CNT_RST;
|
||||
usleep(2);
|
||||
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val;
|
||||
usleep(2);
|
||||
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val | PTO_CNT_EN;
|
||||
usleep(502);
|
||||
|
||||
while (CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_STATUS) & PTO_CLK_CNT_BUSY)
|
||||
;
|
||||
|
||||
u32 cnt = CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_STATUS) & PTO_CLK_CNT;
|
||||
|
||||
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = 0;
|
||||
|
||||
u32 freq = ((cnt << 8) | 0x3E) / 125;
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
|
||||
164
bdk/soc/clock.h
164
bdk/soc/clock.h
@@ -35,6 +35,10 @@
|
||||
#define CLK_RST_CONTROLLER_CLK_SYSTEM_RATE 0x30
|
||||
#define CLK_RST_CONTROLLER_MISC_CLK_ENB 0x48
|
||||
#define CLK_RST_CONTROLLER_OSC_CTRL 0x50
|
||||
#define CLK_RST_CONTROLLER_OSC_FREQ_DET 0x58
|
||||
#define CLK_RST_CONTROLLER_OSC_FREQ_DET_STATUS 0x5C
|
||||
#define CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL 0x60
|
||||
#define CLK_RST_CONTROLLER_PTO_CLK_CNT_STATUS 0x64
|
||||
#define CLK_RST_CONTROLLER_PLLC_BASE 0x80
|
||||
#define CLK_RST_CONTROLLER_PLLC_OUT 0x84
|
||||
#define CLK_RST_CONTROLLER_PLLC_MISC 0x88
|
||||
@@ -156,11 +160,18 @@
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTAPE 0x710
|
||||
|
||||
#define CLK_NO_SOURCE 0x0
|
||||
#define CLK_NOT_USED 0x0
|
||||
|
||||
/*! PLL control and status bits */
|
||||
#define PLLX_BASE_LOCK BIT(27)
|
||||
#define PLLX_BASE_REF_DIS BIT(29)
|
||||
#define PLLX_BASE_ENABLE BIT(30)
|
||||
#define PLLX_BASE_BYPASS BIT(31)
|
||||
|
||||
#define PLLCX_BASE_LOCK BIT(27)
|
||||
#define PLLCX_BASE_REF_DIS BIT(29)
|
||||
#define PLLCX_BASE_ENABLE BIT(30)
|
||||
#define PLLCX_BASE_BYPASS BIT(31)
|
||||
|
||||
#define PLLA_OUT0_RSTN_CLR BIT(0)
|
||||
#define PLLA_OUT0_CLKEN BIT(1)
|
||||
@@ -178,6 +189,140 @@
|
||||
|
||||
#define UTMIPLL_LOCK BIT(31)
|
||||
|
||||
/*! PTO_CLK_CNT */
|
||||
#define PTO_REF_CLK_WIN_CFG_MASK 0xF
|
||||
#define PTO_REF_CLK_WIN_CFG_16P 0xF
|
||||
#define PTO_CNT_EN BIT(9)
|
||||
#define PTO_CNT_RST BIT(10)
|
||||
#define PTO_CLK_ENABLE BIT(13)
|
||||
#define PTO_SRC_SEL_SHIFT 14
|
||||
#define PTO_SRC_SEL_MASK 0x1FF
|
||||
#define PTO_DIV_SEL_MASK (3 << 23)
|
||||
#define PTO_DIV_SEL_GATED (0 << 23)
|
||||
#define PTO_DIV_SEL_DIV1 (1 << 23)
|
||||
#define PTO_DIV_SEL_DIV2_RISING (2 << 23)
|
||||
#define PTO_DIV_SEL_DIV2_FALLING (3 << 23)
|
||||
#define PTO_DIV_SEL_CPU_EARLY (0 << 23)
|
||||
#define PTO_DIV_SEL_CPU_LATE (1 << 23)
|
||||
|
||||
#define PTO_CLK_CNT_BUSY BIT(31)
|
||||
#define PTO_CLK_CNT 0xFFFFFF
|
||||
|
||||
/*! OSC_FREQ_DET */
|
||||
#define OSC_REF_CLK_WIN_CFG_MASK 0xF
|
||||
#define OSC_FREQ_DET_TRIG BIT(31)
|
||||
|
||||
#define OSC_FREQ_DET_BUSY BIT(31)
|
||||
#define OSC_FREQ_DET_CNT 0xFFFF
|
||||
|
||||
/*! PLLs omitted as they need PTO enabled in MISC registers. Norm div is 2. */
|
||||
typedef enum _clock_pto_id_t
|
||||
{
|
||||
CLK_PTO_PCLK_SYS = 0x06,
|
||||
CLK_PTO_HCLK_SYS = 0x07,
|
||||
|
||||
CLK_PTO_UTMIP_240 = 0x0C,
|
||||
|
||||
CLK_PTO_CCLK_G = 0x12,
|
||||
CLK_PTO_CCLK_G_DIV2 = 0x13,
|
||||
|
||||
CLK_PTO_SPI1 = 0x17,
|
||||
CLK_PTO_SPI2 = 0x18,
|
||||
CLK_PTO_SPI3 = 0x19,
|
||||
CLK_PTO_SPI4 = 0x1A,
|
||||
CLK_PTO_MAUD = 0x1B,
|
||||
CLK_PTO_SCLK = 0x1C,
|
||||
|
||||
CLK_PTO_SDMMC1 = 0x20,
|
||||
CLK_PTO_SDMMC2 = 0x21,
|
||||
CLK_PTO_SDMMC3 = 0x22,
|
||||
CLK_PTO_SDMMC4 = 0x23,
|
||||
CLK_PTO_EMC = 0x24,
|
||||
|
||||
CLK_PTO_MSELECT = 0x2F,
|
||||
|
||||
CLK_PTO_VIC = 0x36,
|
||||
|
||||
CLK_PTO_NVDEC = 0x39,
|
||||
|
||||
CLK_PTO_NVENC = 0x3A,
|
||||
CLK_PTO_NVJPG = 0x3B,
|
||||
CLK_PTO_TSEC = 0x3C,
|
||||
CLK_PTO_TSECB = 0x3D,
|
||||
CLK_PTO_SE = 0x3E,
|
||||
|
||||
CLK_PTO_DSIA_LP = 0x62,
|
||||
|
||||
CLK_PTO_ISP = 0x64,
|
||||
CLK_PTO_MC = 0x6A,
|
||||
|
||||
CLK_PTO_ACTMON = 0x6B,
|
||||
CLK_PTO_CSITE = 0x6C,
|
||||
|
||||
CLK_PTO_HOST1X = 0x6F,
|
||||
|
||||
CLK_PTO_SE_2 = 0x74, // Same as CLK_PTO_SE.
|
||||
CLK_PTO_SOC_THERM = 0x75,
|
||||
|
||||
CLK_PTO_TSEC_2 = 0x77, // Same as CLK_PTO_TSEC.
|
||||
|
||||
CLK_PTO_ACLK = 0x7C,
|
||||
CLK_PTO_QSPI = 0x7D,
|
||||
|
||||
CLK_PTO_I2S1 = 0x80,
|
||||
CLK_PTO_I2S2 = 0x81,
|
||||
CLK_PTO_I2S3 = 0x82,
|
||||
CLK_PTO_I2S4 = 0x83,
|
||||
CLK_PTO_I2S5 = 0x84,
|
||||
CLK_PTO_AHUB = 0x85,
|
||||
CLK_PTO_APE = 0x86,
|
||||
|
||||
CLK_PTO_DVFS_SOC = 0x88,
|
||||
CLK_PTO_DVFS_REF = 0x89,
|
||||
|
||||
CLK_PTO_SPDIF = 0x8F,
|
||||
CLK_PTO_SPDIF_IN = 0x90,
|
||||
CLK_PTO_UART_FST_MIPI_CAL = 0x91,
|
||||
|
||||
CLK_PTO_PWM = 0x93,
|
||||
CLK_PTO_I2C1 = 0x94,
|
||||
CLK_PTO_I2C2 = 0x95,
|
||||
CLK_PTO_I2C3 = 0x96,
|
||||
CLK_PTO_I2C4 = 0x97,
|
||||
CLK_PTO_I2C5 = 0x98,
|
||||
CLK_PTO_I2C6 = 0x99,
|
||||
CLK_PTO_I2C_SLOW = 0x9A,
|
||||
CLK_PTO_UARTAPE = 0x9B,
|
||||
|
||||
CLK_PTO_EXTPERIPH1 = 0x9D,
|
||||
CLK_PTO_EXTPERIPH2 = 0x9E,
|
||||
|
||||
CLK_PTO_ENTROPY = 0xA0,
|
||||
CLK_PTO_UARTA = 0xA1,
|
||||
CLK_PTO_UARTB = 0xA2,
|
||||
CLK_PTO_UARTC = 0xA3,
|
||||
CLK_PTO_UARTD = 0xA4,
|
||||
CLK_PTO_OWR = 0xA5,
|
||||
|
||||
CLK_PTO_HDA2CODEC_2X = 0xA7,
|
||||
CLK_PTO_HDA = 0xA8,
|
||||
|
||||
CLK_PTO_SDMMC_LEGACY_TM = 0xAB,
|
||||
|
||||
CLK_PTO_SOR0 = 0xC0,
|
||||
CLK_PTO_SOR1 = 0xC1,
|
||||
|
||||
CLK_PTO_DISP2 = 0xC4,
|
||||
CLK_PTO_DISP1 = 0xC5,
|
||||
|
||||
CLK_PTO_XUSB_FALCON = 0x110,
|
||||
|
||||
CLK_PTO_XUSB_FS = 0x136,
|
||||
CLK_PTO_XUSB_SS_HOST_DEV = 0x137,
|
||||
CLK_PTO_XUSB_CORE_HOST = 0x138,
|
||||
CLK_PTO_XUSB_CORE_DEV = 0x139,
|
||||
} clock_pto_id_t;
|
||||
|
||||
/*
|
||||
* CLOCK Peripherals:
|
||||
* L 0 - 31
|
||||
@@ -216,7 +361,7 @@ enum CLK_L_DEV
|
||||
CLK_L_USBD = 22,
|
||||
CLK_L_ISP = 23,
|
||||
CLK_L_3D = 24, // HIDDEN.
|
||||
//CLK_L_ = 25,
|
||||
CLK_L_IDE = 25, // RESERVED.
|
||||
CLK_L_DISP2 = 26,
|
||||
CLK_L_DISP1 = 27,
|
||||
CLK_L_HOST1X = 28,
|
||||
@@ -244,11 +389,11 @@ enum CLK_H_DEV
|
||||
CLK_H_SPI3 = 14,
|
||||
CLK_H_I2C5 = 15,
|
||||
CLK_H_DSI = 16,
|
||||
//CLK_H_ = 17,
|
||||
CLK_H_TVO = 17, // RESERVED.
|
||||
CLK_H_HSI = 18, // HIDDEN.
|
||||
CLK_H_HDMI = 19, // HIDDEN.
|
||||
CLK_H_CSI = 20,
|
||||
//CLK_H_ = 21,
|
||||
CLK_H_TVDAC = 21, // RESERVED.
|
||||
CLK_H_I2C2 = 22,
|
||||
CLK_H_UARTC = 23,
|
||||
CLK_H_MIPI_CAL = 24,
|
||||
@@ -263,14 +408,14 @@ enum CLK_H_DEV
|
||||
|
||||
enum CLK_U_DEV
|
||||
{
|
||||
//CLK_U_ = 0,
|
||||
CLK_U_SPEEDO = 0, // RESERVED.
|
||||
CLK_U_UARTD = 1,
|
||||
CLK_U_UARTE = 2, // HIDDEN.
|
||||
CLK_U_I2C3 = 3,
|
||||
CLK_U_SPI4 = 4,
|
||||
CLK_U_SDMMC3 = 5,
|
||||
CLK_U_PCIE = 6,
|
||||
CLK_U_UNUSED = 7, // RESERVED
|
||||
CLK_U_OWR = 7, // RESERVED.
|
||||
CLK_U_AFI = 8,
|
||||
CLK_U_CSITE = 9,
|
||||
CLK_U_PCIEXCLK = 10, // Only reset.
|
||||
@@ -444,9 +589,9 @@ enum CLK_Y_DEV
|
||||
/*! Generic clock descriptor. */
|
||||
typedef struct _clock_t
|
||||
{
|
||||
u32 reset;
|
||||
u32 enable;
|
||||
u32 source;
|
||||
u16 reset;
|
||||
u16 enable;
|
||||
u16 source;
|
||||
u8 index;
|
||||
u8 clk_src;
|
||||
u8 clk_div;
|
||||
@@ -494,4 +639,7 @@ int clock_sdmmc_is_not_reset_and_enabled(u32 id);
|
||||
void clock_sdmmc_enable(u32 id, u32 val);
|
||||
void clock_sdmmc_disable(u32 id);
|
||||
|
||||
u32 clock_get_osc_freq();
|
||||
u32 clock_get_dev_freq(clock_pto_id_t id);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 shuffle2
|
||||
* Copyright (c) 2018 balika011
|
||||
* Copyright (c) 2019 CTCaer
|
||||
* Copyright (c) 2019-2020 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -76,6 +76,35 @@ u32 fuse_read_odm_keygen_rev()
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 fuse_read_dramid(bool raw_id)
|
||||
{
|
||||
u32 dramid = (fuse_read_odm(4) & 0xF8) >> 3;
|
||||
|
||||
if (raw_id)
|
||||
return dramid;
|
||||
|
||||
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210)
|
||||
{
|
||||
if (dramid > 6)
|
||||
dramid = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dramid > 27)
|
||||
dramid = 8;
|
||||
}
|
||||
|
||||
return dramid;
|
||||
}
|
||||
|
||||
u32 fuse_read_hw_state()
|
||||
{
|
||||
if ((fuse_read_odm(4) & 3) != 3)
|
||||
return FUSE_NX_HW_STATE_PROD;
|
||||
else
|
||||
return FUSE_NX_HW_STATE_DEV;
|
||||
}
|
||||
|
||||
u32 fuse_read_hw_type()
|
||||
{
|
||||
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01)
|
||||
@@ -118,6 +147,7 @@ u32 fuse_read(u32 addr)
|
||||
FUSE(FUSE_ADDR) = addr;
|
||||
FUSE(FUSE_CTRL) = (FUSE(FUSE_ADDR) & ~FUSE_CMD_MASK) | FUSE_READ;
|
||||
fuse_wait_idle();
|
||||
|
||||
return FUSE(FUSE_RDATA);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 shuffle2
|
||||
* Copyright (c) 2018 balika011
|
||||
* Copyright (c) 2019-2020 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -64,9 +65,10 @@
|
||||
#define FUSE_OPT_X_COORDINATE 0x214
|
||||
#define FUSE_OPT_Y_COORDINATE 0x218
|
||||
#define FUSE_GPU_IDDQ_CALIB 0x228
|
||||
#define FUSE_RESERVED_ODM28 0x240
|
||||
#define FUSE_USB_CALIB_EXT 0x350
|
||||
|
||||
#define FUSE_RESERVED_ODM28_T210B01 0x240
|
||||
|
||||
/*! Fuse commands. */
|
||||
#define FUSE_READ 0x1
|
||||
#define FUSE_WRITE 0x2
|
||||
@@ -83,9 +85,17 @@ enum
|
||||
FUSE_NX_HW_TYPE_HOAG
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
FUSE_NX_HW_STATE_PROD,
|
||||
FUSE_NX_HW_STATE_DEV
|
||||
};
|
||||
|
||||
void fuse_disable_program();
|
||||
u32 fuse_read_odm(u32 idx);
|
||||
u32 fuse_read_odm_keygen_rev();
|
||||
u32 fuse_read_dramid(bool raw_id);
|
||||
u32 fuse_read_hw_state();
|
||||
u32 fuse_read_hw_type();
|
||||
u8 fuse_count_burnt(u32 val);
|
||||
void fuse_wait_idle();
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <soc/hw_init.h>
|
||||
#include <gfx/di.h>
|
||||
#include <display/di.h>
|
||||
#include <input/joycon.h>
|
||||
#include <input/touch.h>
|
||||
#include <sec/se.h>
|
||||
@@ -285,17 +285,21 @@ static void _config_se_brom()
|
||||
|
||||
static void _config_regulators(bool tegra_t210)
|
||||
{
|
||||
// Set RTC/AO domain to POR voltage.
|
||||
if (tegra_t210)
|
||||
max7762x_regulator_set_voltage(REGULATOR_LDO4, 1000000);
|
||||
|
||||
// Disable low battery shutdown monitor.
|
||||
max77620_low_battery_monitor_config(false);
|
||||
|
||||
// Disable SDMMC1 IO power.
|
||||
gpio_write(GPIO_PORT_E, GPIO_PIN_4, GPIO_LOW);
|
||||
max77620_regulator_enable(REGULATOR_LDO2, 0);
|
||||
max7762x_regulator_enable(REGULATOR_LDO2, false);
|
||||
sd_power_cycle_time_start = get_tmr_ms();
|
||||
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CNFGBBC, MAX77620_CNFGBBC_RESISTOR_1K);
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1,
|
||||
BIT(6) | (3 << MAX77620_ONOFFCNFG1_MRT_SHIFT)); // PWR delay for forced shutdown off.
|
||||
MAX77620_ONOFFCNFG1_RSVD | (3 << MAX77620_ONOFFCNFG1_MRT_SHIFT)); // PWR delay for forced shutdown off.
|
||||
|
||||
if (tegra_t210)
|
||||
{
|
||||
@@ -313,28 +317,18 @@ static void _config_regulators(bool tegra_t210)
|
||||
(4 << MAX77620_FPS_TIME_PERIOD_SHIFT) | (2 << MAX77620_FPS_PD_PERIOD_SHIFT)); // 3.x+
|
||||
|
||||
// Set vdd_core voltage to 1.125V.
|
||||
max77620_regulator_set_voltage(REGULATOR_SD0, 1125000);
|
||||
max7762x_regulator_set_voltage(REGULATOR_SD0, 1125000);
|
||||
|
||||
// Fix CPU/GPU after a L4T warmboot.
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO5, 2);
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO6, 2);
|
||||
// Fix CPU/GPU after L4T warmboot.
|
||||
max77620_config_gpio(5, MAX77620_GPIO_OUTPUT_DISABLE);
|
||||
max77620_config_gpio(6, MAX77620_GPIO_OUTPUT_DISABLE);
|
||||
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_REG, MAX77621_VOUT_0_95V); // Disable power.
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_DVS_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_1_09V); // Enable DVS power.
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL1_REG, MAX77621_RAMP_50mV_PER_US);
|
||||
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL2_REG,
|
||||
MAX77621_T_JUNCTION_120 | MAX77621_FT_ENABLE | MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS |
|
||||
MAX77621_CKKADV_TRIP_150mV_PER_US | MAX77621_INDUCTOR_NOMINAL);
|
||||
|
||||
i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_VOUT_REG, MAX77621_VOUT_0_95V); // Disable power.
|
||||
i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_VOUT_DVS_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_1_09V); // Enable DVS power.
|
||||
i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_CONTROL1_REG, MAX77621_RAMP_50mV_PER_US);
|
||||
i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_CONTROL2_REG,
|
||||
MAX77621_T_JUNCTION_120 | MAX77621_FT_ENABLE | MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS |
|
||||
MAX77621_CKKADV_TRIP_150mV_PER_US | MAX77621_INDUCTOR_NOMINAL);
|
||||
// Set POR configuration.
|
||||
max77621_config_default(REGULATOR_CPU0, MAX77621_CTRL_POR_CFG);
|
||||
max77621_config_default(REGULATOR_GPU0, MAX77621_CTRL_POR_CFG);
|
||||
}
|
||||
else // Tegra X1+ set vdd_core voltage to 1.05V.
|
||||
max77620_regulator_set_voltage(REGULATOR_SD0, 1050000);
|
||||
max7762x_regulator_set_voltage(REGULATOR_SD0, 1050000);
|
||||
}
|
||||
|
||||
void hw_init()
|
||||
@@ -373,7 +367,8 @@ void hw_init()
|
||||
|
||||
#ifdef DEBUG_UART_PORT
|
||||
clock_enable_uart(DEBUG_UART_PORT);
|
||||
uart_init(DEBUG_UART_PORT, 115200);
|
||||
uart_init(DEBUG_UART_PORT, DEBUG_UART_BAUDRATE);
|
||||
uart_invert(DEBUG_UART_PORT, DEBUG_UART_INVERT, UART_INVERT_TXD);
|
||||
#endif
|
||||
|
||||
// Enable Dynamic Voltage and Frequency Scaling device clock.
|
||||
@@ -391,17 +386,20 @@ void hw_init()
|
||||
|
||||
//! TODO: Why? Device is NFC MCU on Lite.
|
||||
if (nx_hoag)
|
||||
max77620_regulator_set_volt_and_flags(REGULATOR_LDO8, 2800000, MAX77620_POWER_MODE_NORMAL);
|
||||
{
|
||||
max7762x_regulator_set_voltage(REGULATOR_LDO8, 2800000);
|
||||
max7762x_regulator_enable(REGULATOR_LDO8, true);
|
||||
}
|
||||
|
||||
// Initialize I2C1 for various power related devices.
|
||||
i2c_init(I2C_1);
|
||||
|
||||
// Enable charger in case it's disabled.
|
||||
bq24193_enable_charger();
|
||||
|
||||
// Initialize various regulators based on Erista/Mariko platform.
|
||||
_config_regulators(tegra_t210);
|
||||
|
||||
// Enable charger in case it's disabled.
|
||||
bq24193_enable_charger();
|
||||
|
||||
_config_pmc_scratch(); // Missing from 4.x+
|
||||
|
||||
// Set BPMP/SCLK to PLLP_OUT (408MHz).
|
||||
@@ -421,7 +419,7 @@ void hw_init()
|
||||
bpmp_mmu_enable();
|
||||
}
|
||||
|
||||
void hw_reinit_workaround(bool extra_reconfig, u32 magic)
|
||||
void hw_reinit_workaround(bool coreboot, u32 magic)
|
||||
{
|
||||
// Disable BPMP max clock.
|
||||
bpmp_clk_rate_set(BPMP_CLK_NORMAL);
|
||||
@@ -445,10 +443,10 @@ void hw_reinit_workaround(bool extra_reconfig, u32 magic)
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= BIT(CLK_V_AHUB);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= BIT(CLK_Y_APE);
|
||||
|
||||
if (extra_reconfig)
|
||||
// Do coreboot mitigations.
|
||||
if (coreboot)
|
||||
{
|
||||
msleep(10);
|
||||
PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_SDMMC1_IO_EN;
|
||||
|
||||
clock_disable_cl_dvfs();
|
||||
|
||||
@@ -457,6 +455,9 @@ void hw_reinit_workaround(bool extra_reconfig, u32 magic)
|
||||
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO);
|
||||
gpio_config(GPIO_PORT_E, GPIO_PIN_6, GPIO_MODE_SPIO);
|
||||
gpio_config(GPIO_PORT_H, GPIO_PIN_6, GPIO_MODE_SPIO);
|
||||
|
||||
// Reinstate SD controller power.
|
||||
PMC(APBDEV_PMC_NO_IOPOWER) &= ~(PMC_NO_IOPOWER_SDMMC1_IO_EN);
|
||||
}
|
||||
|
||||
// Power off display.
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <utils/types.h>
|
||||
|
||||
void hw_init();
|
||||
void hw_reinit_workaround(bool extra_reconfig, u32 magic);
|
||||
void hw_reinit_workaround(bool coreboot, u32 magic);
|
||||
u32 hw_get_chip_id();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -136,10 +136,10 @@ static int _i2c_send_single(u32 i2c_idx, u32 dev_addr, u8 *buf, u32 size)
|
||||
// Initiate transaction on normal mode.
|
||||
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | NORMAL_MODE_GO;
|
||||
|
||||
u32 timeout = get_tmr_ms() + 400; // Actual for max 8 bytes at 100KHz is 0.74ms.
|
||||
u32 timeout = get_tmr_us() + 200000; // Actual for max 8 bytes at 100KHz is 0.74ms.
|
||||
while (base[I2C_STATUS] & I2C_STATUS_BUSY)
|
||||
{
|
||||
if (get_tmr_ms() > timeout)
|
||||
if (get_tmr_us() > timeout)
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -168,10 +168,10 @@ static int _i2c_recv_single(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr)
|
||||
// Initiate transaction on normal mode.
|
||||
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | NORMAL_MODE_GO;
|
||||
|
||||
u32 timeout = get_tmr_ms() + 400; // Actual for max 8 bytes at 100KHz is 0.74ms.
|
||||
u32 timeout = get_tmr_us() + 200000; // Actual for max 8 bytes at 100KHz is 0.74ms.
|
||||
while (base[I2C_STATUS] & I2C_STATUS_BUSY)
|
||||
{
|
||||
if (get_tmr_ms() > timeout)
|
||||
if (get_tmr_us() > timeout)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -133,6 +133,10 @@ static irq_status_t _irq_handle_source(u32 irq)
|
||||
}
|
||||
}
|
||||
|
||||
// Do not re-enable if not handled.
|
||||
if (status == IRQ_NONE)
|
||||
return status;
|
||||
|
||||
if (irqs[idx].flags & IRQ_FLAG_ONE_OFF)
|
||||
irq_free(irq);
|
||||
else
|
||||
@@ -148,7 +152,9 @@ void irq_handler()
|
||||
|
||||
if (!irq_init_done)
|
||||
{
|
||||
_irq_disable_source(irq);
|
||||
_irq_ack_source(irq);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -156,9 +162,10 @@ void irq_handler()
|
||||
|
||||
int err = _irq_handle_source(irq);
|
||||
|
||||
//TODO: disable if unhandhled.
|
||||
if (err == IRQ_NONE)
|
||||
gfx_printf("Unhandled IRQ: %d\n", irq);
|
||||
{
|
||||
DPRINTF("Unhandled IRQ got disabled: %d!\n", irq);
|
||||
}
|
||||
}
|
||||
|
||||
static void _irq_init()
|
||||
@@ -170,6 +177,9 @@ static void _irq_init()
|
||||
|
||||
void irq_end()
|
||||
{
|
||||
if (!irq_init_done)
|
||||
return;
|
||||
|
||||
_irq_free_all();
|
||||
irq_disable_cpu_irq_exceptions();
|
||||
irq_init_done = false;
|
||||
|
||||
@@ -14,11 +14,69 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <soc/hw_init.h>
|
||||
#include <soc/pmc.h>
|
||||
#include <soc/t210.h>
|
||||
#include <utils/util.h>
|
||||
|
||||
int pmc_enable_partition(u32 part, int enable)
|
||||
void pmc_scratch_lock(pmc_sec_lock_t lock_mask)
|
||||
{
|
||||
// Lock Private key disable, Fuse write enable, MC carveout, Warmboot PA id and Warmboot address.
|
||||
if (lock_mask & PMC_SEC_LOCK_MISC)
|
||||
{
|
||||
PMC(APBDEV_PMC_SEC_DISABLE) |= 0x700FF0; // RW lock: 0-3.
|
||||
PMC(APBDEV_PMC_SEC_DISABLE2) |= 0xFC000000; // RW lock: 21-23.
|
||||
PMC(APBDEV_PMC_SEC_DISABLE3) |= 0x3F0FFF00; // RW lock: 28-33, 36-38.
|
||||
PMC(APBDEV_PMC_SEC_DISABLE6) |= 0xC000000; // RW lock: 85.
|
||||
PMC(APBDEV_PMC_SEC_DISABLE8) |= 0xFF00FF00; // RW lock: 108-111, 116-119.
|
||||
|
||||
// SE2 context.
|
||||
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01)
|
||||
{
|
||||
PMC(APBDEV_PMC_SEC_DISABLE9) |= 0x3FF; // RW lock: 120-124. (0xB38)
|
||||
PMC(APBDEV_PMC_SEC_DISABLE10) = 0xFFFFFFFF; // RW lock: 135-150.
|
||||
}
|
||||
}
|
||||
|
||||
if (lock_mask & PMC_SEC_LOCK_LP0_PARAMS)
|
||||
{
|
||||
PMC(APBDEV_PMC_SEC_DISABLE2) |= 0x3FCFFFF; // RW lock: 8-15, 17-20.
|
||||
PMC(APBDEV_PMC_SEC_DISABLE4) |= 0x3F3FFFFF; // RW lock: 40-50, 52-54.
|
||||
PMC(APBDEV_PMC_SEC_DISABLE5) = 0xFFFFFFFF; // RW lock: 56-71.
|
||||
PMC(APBDEV_PMC_SEC_DISABLE6) |= 0xF3FFC00F; // RW lock: 72-73, 79-84, 86-87.
|
||||
PMC(APBDEV_PMC_SEC_DISABLE7) |= 0x3FFFFF; // RW lock: 88-98.
|
||||
PMC(APBDEV_PMC_SEC_DISABLE8) |= 0xFF; // RW lock: 104-107.
|
||||
}
|
||||
|
||||
if (lock_mask & PMC_SEC_LOCK_RST_VECTOR)
|
||||
PMC(APBDEV_PMC_SEC_DISABLE3) |= 0xF00000; // RW lock: 34-35.
|
||||
|
||||
if (lock_mask & PMC_SEC_LOCK_CARVEOUTS)
|
||||
{
|
||||
PMC(APBDEV_PMC_SEC_DISABLE2) |= 0x30000; // RW lock: 16.
|
||||
PMC(APBDEV_PMC_SEC_DISABLE3) |= 0xC0000000; // RW lock: 39.
|
||||
PMC(APBDEV_PMC_SEC_DISABLE4) |= 0xC0C00000; // RW lock: 51, 55.
|
||||
PMC(APBDEV_PMC_SEC_DISABLE6) |= 0x3FF0; // RW lock: 74-78.
|
||||
PMC(APBDEV_PMC_SEC_DISABLE7) |= 0xFFC00000; // RW lock: 99-103.
|
||||
}
|
||||
|
||||
if (lock_mask & PMC_SEC_LOCK_TZ_CMAC_W)
|
||||
PMC(APBDEV_PMC_SEC_DISABLE8) |= 0x550000; // W lock: 112-115.
|
||||
|
||||
if (lock_mask & PMC_SEC_LOCK_TZ_CMAC_R)
|
||||
PMC(APBDEV_PMC_SEC_DISABLE8) |= 0xAA0000; // R lock: 112-115.
|
||||
|
||||
if (lock_mask & PMC_SEC_LOCK_TZ_KEK_W)
|
||||
PMC(APBDEV_PMC_SEC_DISABLE3) |= 0x55; // W lock: 24-27.
|
||||
|
||||
if (lock_mask & PMC_SEC_LOCK_TZ_KEK_R)
|
||||
PMC(APBDEV_PMC_SEC_DISABLE3) |= 0xAA; // R lock: 24-27.
|
||||
|
||||
if (lock_mask & PMC_SEC_LOCK_SE_SRK)
|
||||
PMC(APBDEV_PMC_SEC_DISABLE) |= 0xFF000; // RW lock: 4-7
|
||||
}
|
||||
|
||||
int pmc_enable_partition(pmc_power_rail_t part, u32 enable)
|
||||
{
|
||||
u32 part_mask = BIT(part);
|
||||
u32 desired_state = enable << part;
|
||||
|
||||
@@ -40,6 +40,8 @@
|
||||
#define PMC_SCRATCH0_MODE_CUSTOM_ALL (PMC_SCRATCH0_MODE_RECOVERY | PMC_SCRATCH0_MODE_FASTBOOT | PMC_SCRATCH0_MODE_PAYLOAD)
|
||||
#define APBDEV_PMC_SCRATCH1 0x54
|
||||
#define APBDEV_PMC_SCRATCH20 0xA0
|
||||
#define APBDEV_PMC_SECURE_SCRATCH4 0xC0
|
||||
#define APBDEV_PMC_SECURE_SCRATCH5 0xC4
|
||||
#define APBDEV_PMC_PWR_DET_VAL 0xE4
|
||||
#define PMC_PWR_DET_SDMMC1_IO_EN BIT(12)
|
||||
#define PMC_PWR_DET_AUDIO_HV BIT(18)
|
||||
@@ -63,6 +65,8 @@
|
||||
#define APBDEV_PMC_IO_DPD2_REQ 0x1C0
|
||||
#define APBDEV_PMC_VDDP_SEL 0x1CC
|
||||
#define APBDEV_PMC_DDR_CFG 0x1D0
|
||||
#define APBDEV_PMC_SECURE_SCRATCH6 0x224
|
||||
#define APBDEV_PMC_SECURE_SCRATCH7 0x228
|
||||
#define APBDEV_PMC_SCRATCH45 0x234
|
||||
#define APBDEV_PMC_SCRATCH46 0x238
|
||||
#define APBDEV_PMC_SCRATCH49 0x244
|
||||
@@ -87,6 +91,8 @@
|
||||
#define APBDEV_PMC_SEC_DISABLE6 0x5B8
|
||||
#define APBDEV_PMC_SEC_DISABLE7 0x5BC
|
||||
#define APBDEV_PMC_SEC_DISABLE8 0x5C0
|
||||
#define APBDEV_PMC_SEC_DISABLE9 0x5C4
|
||||
#define APBDEV_PMC_SEC_DISABLE10 0x5C8
|
||||
#define APBDEV_PMC_SCRATCH188 0x810
|
||||
#define APBDEV_PMC_SCRATCH190 0x818
|
||||
#define APBDEV_PMC_SCRATCH200 0x840
|
||||
@@ -94,6 +100,54 @@
|
||||
#define APBDEV_PMC_TZRAM_SEC_DISABLE 0xBEC
|
||||
#define APBDEV_PMC_TZRAM_NON_SEC_DISABLE 0xBF0
|
||||
|
||||
int pmc_enable_partition(u32 part, int enable);
|
||||
typedef enum _pmc_sec_lock_t
|
||||
{
|
||||
PMC_SEC_LOCK_MISC = BIT(0),
|
||||
PMC_SEC_LOCK_LP0_PARAMS = BIT(1),
|
||||
PMC_SEC_LOCK_RST_VECTOR = BIT(2),
|
||||
PMC_SEC_LOCK_CARVEOUTS = BIT(3),
|
||||
PMC_SEC_LOCK_TZ_CMAC_W = BIT(4),
|
||||
PMC_SEC_LOCK_TZ_CMAC_R = BIT(5),
|
||||
PMC_SEC_LOCK_TZ_KEK_W = BIT(6),
|
||||
PMC_SEC_LOCK_TZ_KEK_R = BIT(7),
|
||||
PMC_SEC_LOCK_SE_SRK = BIT(8),
|
||||
} pmc_sec_lock_t;
|
||||
|
||||
typedef enum _pmc_power_rail_t
|
||||
{
|
||||
POWER_RAIL_CRAIL = 0,
|
||||
POWER_RAIL_3D0 = 1,
|
||||
POWER_RAIL_VENC = 2,
|
||||
POWER_RAIL_PCIE = 3,
|
||||
POWER_RAIL_VDEC = 4,
|
||||
POWER_RAIL_L2C = 5,
|
||||
POWER_RAIL_MPE = 6,
|
||||
POWER_RAIL_HEG = 7,
|
||||
POWER_RAIL_SATA = 8,
|
||||
POWER_RAIL_CE1 = 9,
|
||||
POWER_RAIL_CE2 = 10,
|
||||
POWER_RAIL_CE3 = 11,
|
||||
POWER_RAIL_CELP = 12,
|
||||
POWER_RAIL_3D1 = 13,
|
||||
POWER_RAIL_CE0 = 14,
|
||||
POWER_RAIL_C0NC = 15,
|
||||
POWER_RAIL_C1NC = 16,
|
||||
POWER_RAIL_SOR = 17,
|
||||
POWER_RAIL_DIS = 18,
|
||||
POWER_RAIL_DISB = 19,
|
||||
POWER_RAIL_XUSBA = 20,
|
||||
POWER_RAIL_XUSBB = 21,
|
||||
POWER_RAIL_XUSBC = 22,
|
||||
POWER_RAIL_VIC = 23,
|
||||
POWER_RAIL_IRAM = 24,
|
||||
POWER_RAIL_NVDEC = 25,
|
||||
POWER_RAIL_NVJPG = 26,
|
||||
POWER_RAIL_AUD = 27,
|
||||
POWER_RAIL_DFD = 28,
|
||||
POWER_RAIL_VE2 = 29
|
||||
} pmc_power_rail_t;
|
||||
|
||||
void pmc_scratch_lock(pmc_sec_lock_t lock_mask);
|
||||
int pmc_enable_partition(pmc_power_rail_t part, u32 enable);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -142,7 +142,10 @@ c : clear by read
|
||||
#define R1_SWITCH_ERROR (1 << 7) /* sx, c */
|
||||
#define R1_EXCEPTION_EVENT (1 << 6) /* sr, a */
|
||||
#define R1_APP_CMD (1 << 5) /* sr, c */
|
||||
#define R1_SKIP_STATE_CHECK (1 << 4) /* Custom state to skip expected state check */
|
||||
#define R1_AKE_SEQ_ERROR (1 << 3)
|
||||
|
||||
/* R1_CURRENT_STATE 12:9 */
|
||||
#define R1_STATE_IDLE 0
|
||||
#define R1_STATE_READY 1
|
||||
#define R1_STATE_IDENT 2
|
||||
|
||||
@@ -34,14 +34,16 @@
|
||||
#define SD_APP_SEND_SCR 51 /* adtc R1 */
|
||||
|
||||
/* OCR bit definitions */
|
||||
#define SD_OCR_CCS (1 << 30) /* Card Capacity Status */
|
||||
#define SD_OCR_XPC (1 << 28) /* SDXC power control */
|
||||
#define SD_OCR_S18R (1 << 24) /* 1.8V switching request */
|
||||
#define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */
|
||||
#define SD_OCR_XPC (1 << 28) /* SDXC power control */
|
||||
#define SD_OCR_CCS (1 << 30) /* Card Capacity Status */
|
||||
#define SD_OCR_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_18 (1 << 7) /* VDD voltage 1.8 */
|
||||
|
||||
#define SD_VHD_27_36 (1 << 8) /* VDD voltage 2.7 ~ 3.6 */
|
||||
|
||||
/*
|
||||
* SD_SWITCH argument format:
|
||||
*
|
||||
|
||||
@@ -45,7 +45,7 @@ static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size)
|
||||
* Common functions for SD and MMC.
|
||||
*/
|
||||
|
||||
static int _sdmmc_storage_check_result(u32 res)
|
||||
static int _sdmmc_storage_check_card_status(u32 res)
|
||||
{
|
||||
//Error mask:
|
||||
//TODO: R1_SWITCH_ERROR can be skipped for certain card types.
|
||||
@@ -66,15 +66,15 @@ static int _sdmmc_storage_execute_cmd_type1_ex(sdmmc_storage_t *storage, u32 *re
|
||||
{
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
sdmmc_init_cmd(&cmdbuf, cmd, arg, SDMMC_RSP_TYPE_1, check_busy);
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0))
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
||||
return 0;
|
||||
|
||||
sdmmc_get_rsp(storage->sdmmc, resp, 4, SDMMC_RSP_TYPE_1);
|
||||
if (mask)
|
||||
*resp &= ~mask;
|
||||
|
||||
if (_sdmmc_storage_check_result(*resp))
|
||||
if (expected_state == 0x10 || R1_CURRENT_STATE(*resp) == expected_state)
|
||||
if (_sdmmc_storage_check_card_status(*resp))
|
||||
if (expected_state == R1_SKIP_STATE_CHECK || R1_CURRENT_STATE(*resp) == expected_state)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
@@ -91,34 +91,34 @@ static int _sdmmc_storage_go_idle_state(sdmmc_storage_t *storage)
|
||||
sdmmc_cmd_t cmd;
|
||||
sdmmc_init_cmd(&cmd, MMC_GO_IDLE_STATE, 0, SDMMC_RSP_TYPE_0, 0);
|
||||
|
||||
return sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0);
|
||||
return sdmmc_execute_cmd(storage->sdmmc, &cmd, NULL, NULL);
|
||||
}
|
||||
|
||||
static int _sdmmc_storage_get_cid(sdmmc_storage_t *storage, void *buf)
|
||||
{
|
||||
sdmmc_cmd_t cmd;
|
||||
sdmmc_init_cmd(&cmd, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0);
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0))
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, NULL, NULL))
|
||||
return 0;
|
||||
|
||||
sdmmc_get_rsp(storage->sdmmc, buf, 0x10, SDMMC_RSP_TYPE_2);
|
||||
sdmmc_get_rsp(storage->sdmmc, buf, 16, SDMMC_RSP_TYPE_2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _sdmmc_storage_select_card(sdmmc_storage_t *storage)
|
||||
{
|
||||
return _sdmmc_storage_execute_cmd_type1(storage, MMC_SELECT_CARD, storage->rca << 16, 1, 0x10);
|
||||
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)
|
||||
{
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
sdmmc_init_cmd(&cmdbuf, MMC_SEND_CSD, storage->rca << 16, SDMMC_RSP_TYPE_2, 0);
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0))
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
||||
return 0;
|
||||
|
||||
sdmmc_get_rsp(storage->sdmmc, buf, 0x10, SDMMC_RSP_TYPE_2);
|
||||
sdmmc_get_rsp(storage->sdmmc, buf, 16, SDMMC_RSP_TYPE_2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -306,7 +306,7 @@ static int _mmc_storage_get_op_cond_inner(sdmmc_storage_t *storage, u32 *pout, u
|
||||
}
|
||||
|
||||
sdmmc_init_cmd(&cmd, MMC_SEND_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0))
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, NULL, NULL))
|
||||
return 0;
|
||||
|
||||
return sdmmc_get_rsp(storage->sdmmc, pout, 4, SDMMC_RSP_TYPE_3);
|
||||
@@ -340,7 +340,7 @@ static int _mmc_storage_get_op_cond(sdmmc_storage_t *storage, u32 power)
|
||||
|
||||
static int _mmc_storage_set_relative_addr(sdmmc_storage_t *storage)
|
||||
{
|
||||
return _sdmmc_storage_execute_cmd_type1(storage, MMC_SET_RELATIVE_ADDR, storage->rca << 16, 0, 0x10);
|
||||
return _sdmmc_storage_execute_cmd_type1(storage, MMC_SET_RELATIVE_ADDR, storage->rca << 16, 0, R1_SKIP_STATE_CHECK);
|
||||
}
|
||||
|
||||
static void _mmc_storage_parse_cid(sdmmc_storage_t *storage)
|
||||
@@ -432,19 +432,19 @@ static int _mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf)
|
||||
reqbuf.is_multi_block = 0;
|
||||
reqbuf.is_auto_cmd12 = 0;
|
||||
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, 0))
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
|
||||
return 0;
|
||||
|
||||
u32 tmp = 0;
|
||||
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
|
||||
_mmc_storage_parse_ext_csd(storage, buf);
|
||||
|
||||
return _sdmmc_storage_check_result(tmp);
|
||||
return _sdmmc_storage_check_card_status(tmp);
|
||||
}
|
||||
|
||||
static int _mmc_storage_switch(sdmmc_storage_t *storage, u32 arg)
|
||||
{
|
||||
return _sdmmc_storage_execute_cmd_type1(storage, MMC_SWITCH, arg, 1, 0x10);
|
||||
return _sdmmc_storage_execute_cmd_type1(storage, MMC_SWITCH, arg, 1, R1_SKIP_STATE_CHECK);
|
||||
}
|
||||
|
||||
static int _mmc_storage_switch_buswidth(sdmmc_storage_t *storage, u32 bus_width)
|
||||
@@ -688,53 +688,60 @@ static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp
|
||||
static int _sd_storage_send_if_cond(sdmmc_storage_t *storage)
|
||||
{
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
sdmmc_init_cmd(&cmdbuf, SD_SEND_IF_COND, 0x1AA, SDMMC_RSP_TYPE_5, 0);
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0))
|
||||
u16 vhd_pattern = SD_VHD_27_36 | 0xAA;
|
||||
sdmmc_init_cmd(&cmdbuf, SD_SEND_IF_COND, vhd_pattern, SDMMC_RSP_TYPE_5, 0);
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
||||
return 1; // The SD Card is version 1.X
|
||||
|
||||
// Card version is >= 2.0, parse results.
|
||||
u32 resp = 0;
|
||||
if (!sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_5))
|
||||
return 2;
|
||||
return 2; // Failed.
|
||||
|
||||
return (resp & 0xFF) == 0xAA ? 0 : 2;
|
||||
// Check if VHD was accepted and pattern was properly returned.
|
||||
if ((resp & 0xFFF) == vhd_pattern)
|
||||
return 0;
|
||||
|
||||
// Failed.
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, int is_version_1, int bus_low_voltage_support)
|
||||
static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, int is_version_1, int bus_uhs_support)
|
||||
{
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
// Support for Current > 150mA
|
||||
u32 arg = (~is_version_1 & 1) ? SD_OCR_XPC : 0;
|
||||
u32 arg = !is_version_1 ? SD_OCR_XPC : 0;
|
||||
// Support for handling block-addressed SDHC cards
|
||||
arg |= (~is_version_1 & 1) ? SD_OCR_CCS : 0;
|
||||
arg |= !is_version_1 ? SD_OCR_CCS : 0;
|
||||
// Support for 1.8V
|
||||
arg |= (bus_low_voltage_support & ~is_version_1 & 1) ? SD_OCR_S18R : 0;
|
||||
arg |= (bus_uhs_support && !is_version_1) ? SD_OCR_S18R : 0;
|
||||
// This is needed for most cards. Do not set bit7 even if 1.8V is supported.
|
||||
arg |= SD_OCR_VDD_32_33;
|
||||
sdmmc_init_cmd(&cmdbuf, SD_APP_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
|
||||
if (!_sd_storage_execute_app_cmd(storage, 0x10, is_version_1 ? 0x400000 : 0, &cmdbuf, 0, 0))
|
||||
if (!_sd_storage_execute_app_cmd(storage, R1_SKIP_STATE_CHECK, is_version_1 ? R1_ILLEGAL_COMMAND : 0, &cmdbuf, NULL, NULL))
|
||||
return 0;
|
||||
|
||||
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_low_voltage_support)
|
||||
static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, int is_version_1, int bus_uhs_support)
|
||||
{
|
||||
u32 timeout = get_tmr_ms() + 1500;
|
||||
|
||||
while (1)
|
||||
{
|
||||
u32 cond = 0;
|
||||
if (!_sd_storage_get_op_cond_once(storage, &cond, is_version_1, bus_low_voltage_support))
|
||||
if (!_sd_storage_get_op_cond_once(storage, &cond, is_version_1, bus_uhs_support))
|
||||
break;
|
||||
if (cond & MMC_CARD_BUSY)
|
||||
{
|
||||
DPRINTF("[SD] cond: %08X, lv: %d\n", cond, bus_low_voltage_support);
|
||||
DPRINTF("[SD] op cond: %08X, lv: %d\n", cond, bus_uhs_support);
|
||||
|
||||
if (cond & SD_OCR_CCS)
|
||||
storage->has_sector_access = 1;
|
||||
|
||||
// Check if card supports 1.8V signaling.
|
||||
if (cond & SD_ROCR_S18A && bus_low_voltage_support)
|
||||
if (cond & SD_ROCR_S18A && bus_uhs_support)
|
||||
{
|
||||
//The low voltage regulator configuration is valid for SDMMC1 only.
|
||||
if (storage->sdmmc->id == SDMMC_1 &&
|
||||
@@ -771,7 +778,7 @@ static int _sd_storage_get_rca(sdmmc_storage_t *storage)
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0))
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
||||
break;
|
||||
|
||||
u32 resp = 0;
|
||||
@@ -822,7 +829,7 @@ int _sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf)
|
||||
reqbuf.is_multi_block = 0;
|
||||
reqbuf.is_auto_cmd12 = 0;
|
||||
|
||||
if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, 0))
|
||||
if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, NULL))
|
||||
return 0;
|
||||
|
||||
u32 tmp = 0;
|
||||
@@ -838,7 +845,7 @@ int _sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf)
|
||||
_sd_storage_parse_scr(storage);
|
||||
//gfx_hexdump(0, storage->raw_scr, 8);
|
||||
|
||||
return _sdmmc_storage_check_result(tmp);
|
||||
return _sdmmc_storage_check_card_status(tmp);
|
||||
}
|
||||
|
||||
int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf)
|
||||
@@ -854,12 +861,12 @@ int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf)
|
||||
reqbuf.is_multi_block = 0;
|
||||
reqbuf.is_auto_cmd12 = 0;
|
||||
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, 0))
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
|
||||
return 0;
|
||||
|
||||
u32 tmp = 0;
|
||||
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
|
||||
return _sdmmc_storage_check_result(tmp);
|
||||
return _sdmmc_storage_check_card_status(tmp);
|
||||
}
|
||||
|
||||
int _sd_storage_switch(sdmmc_storage_t *storage, void *buf, int mode, int group, u32 arg)
|
||||
@@ -878,12 +885,12 @@ int _sd_storage_switch(sdmmc_storage_t *storage, void *buf, int mode, int group,
|
||||
reqbuf.is_multi_block = 0;
|
||||
reqbuf.is_auto_cmd12 = 0;
|
||||
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, 0))
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
|
||||
return 0;
|
||||
|
||||
u32 tmp = 0;
|
||||
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
|
||||
return _sdmmc_storage_check_result(tmp);
|
||||
return _sdmmc_storage_check_card_status(tmp);
|
||||
}
|
||||
|
||||
void _sd_storage_set_current_limit(sdmmc_storage_t *storage, u16 current_limit, u8 *buf)
|
||||
@@ -1057,6 +1064,44 @@ int _sd_storage_enable_hs_high_volt(sdmmc_storage_t *storage, u8 *buf)
|
||||
return sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_HS25);
|
||||
}
|
||||
|
||||
u32 sd_storage_ssr_get_au(sdmmc_storage_t *storage)
|
||||
{
|
||||
u32 au_size = storage->ssr.uhs_au_size;
|
||||
|
||||
if (!au_size)
|
||||
au_size = storage->ssr.au_size;
|
||||
|
||||
if (au_size <= 10)
|
||||
{
|
||||
u32 shift = au_size;
|
||||
au_size = shift ? 8 : 0;
|
||||
au_size <<= shift;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (au_size)
|
||||
{
|
||||
case 11:
|
||||
au_size = 12288;
|
||||
break;
|
||||
case 12:
|
||||
au_size = 16384;
|
||||
break;
|
||||
case 13:
|
||||
au_size = 24576;
|
||||
break;
|
||||
case 14:
|
||||
au_size = 32768;
|
||||
break;
|
||||
case 15:
|
||||
au_size = 65536;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return au_size;
|
||||
}
|
||||
|
||||
static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
|
||||
{
|
||||
// unstuff_bits supports only 4 u32 so break into 2 x 16byte groups
|
||||
@@ -1106,6 +1151,9 @@ static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
|
||||
storage->ssr.video_class = unstuff_bits(raw_ssr1, 384 - 384, 8);
|
||||
|
||||
storage->ssr.app_class = unstuff_bits(raw_ssr2, 336 - 256, 4);
|
||||
|
||||
storage->ssr.au_size = unstuff_bits(raw_ssr1, 428 - 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)
|
||||
@@ -1127,7 +1175,7 @@ DPRINTF("[SD] ssr: Card lacks mandatory SD Status function\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, 0))
|
||||
if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, NULL))
|
||||
return 0;
|
||||
|
||||
u32 tmp = 0;
|
||||
@@ -1143,7 +1191,7 @@ DPRINTF("[SD] ssr: Card lacks mandatory SD Status function\n");
|
||||
_sd_storage_parse_ssr(storage);
|
||||
//gfx_hexdump(0, storage->raw_ssr, 64);
|
||||
|
||||
return _sdmmc_storage_check_result(tmp);
|
||||
return _sdmmc_storage_check_card_status(tmp);
|
||||
}
|
||||
|
||||
static void _sd_storage_parse_cid(sdmmc_storage_t *storage)
|
||||
@@ -1186,7 +1234,7 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
|
||||
}
|
||||
}
|
||||
|
||||
static bool _sdmmc_storage_get_low_voltage_support(u32 bus_width, u32 type)
|
||||
static bool _sdmmc_storage_get_bus_uhs_support(u32 bus_width, u32 type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
@@ -1235,13 +1283,13 @@ DPRINTF("[SD] after init\n");
|
||||
DPRINTF("[SD] went to idle state\n");
|
||||
|
||||
is_version_1 = _sd_storage_send_if_cond(storage);
|
||||
if (is_version_1 == 2)
|
||||
if (is_version_1 == 2) // Failed.
|
||||
return 0;
|
||||
DPRINTF("[SD] after send if cond\n");
|
||||
|
||||
bool bus_low_voltage_support = _sdmmc_storage_get_low_voltage_support(bus_width, type);
|
||||
bool bus_uhs_support = _sdmmc_storage_get_bus_uhs_support(bus_width, type);
|
||||
|
||||
if (!_sd_storage_get_op_cond(storage, is_version_1, bus_low_voltage_support))
|
||||
if (!_sd_storage_get_op_cond(storage, is_version_1, bus_uhs_support))
|
||||
return 0;
|
||||
DPRINTF("[SD] got op cond\n");
|
||||
|
||||
@@ -1310,6 +1358,7 @@ DPRINTF("[SD] switched to wide bus width\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
bus_width = SDMMC_BUS_WIDTH_1;
|
||||
DPRINTF("[SD] SD does not support wide bus width\n");
|
||||
}
|
||||
|
||||
@@ -1321,7 +1370,7 @@ 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) != 0)
|
||||
else if (type != SDHCI_TIMING_SD_DS12 && (storage->scr.sda_vsn & 0xF)) // Not default speed and not SD Version 1.x
|
||||
{
|
||||
if (!_sd_storage_enable_hs_high_volt(storage, buf))
|
||||
return 0;
|
||||
@@ -1368,7 +1417,7 @@ int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf)
|
||||
reqbuf.is_multi_block = 0;
|
||||
reqbuf.is_auto_cmd12 = 0;
|
||||
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, 0))
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
|
||||
{
|
||||
sdmmc_stop_transmission(storage->sdmmc, &resp);
|
||||
return 0;
|
||||
@@ -1376,7 +1425,7 @@ int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf)
|
||||
|
||||
if (!sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_1))
|
||||
return 0;
|
||||
if (!_sdmmc_storage_check_result(resp))
|
||||
if (!_sdmmc_storage_check_card_status(resp))
|
||||
return 0;
|
||||
return _sdmmc_storage_check_status(storage);
|
||||
}
|
||||
|
||||
@@ -95,6 +95,8 @@ typedef struct _sd_ssr
|
||||
u8 uhs_grade;
|
||||
u8 video_class;
|
||||
u8 app_class;
|
||||
u8 au_size;
|
||||
u8 uhs_au_size;
|
||||
u32 protected_size;
|
||||
} sd_ssr_t;
|
||||
|
||||
@@ -107,6 +109,7 @@ typedef struct _sdmmc_storage_t
|
||||
u32 sec_cnt;
|
||||
int is_low_voltage;
|
||||
u32 partition;
|
||||
int initialized;
|
||||
u8 raw_cid[0x10];
|
||||
u8 raw_csd[0x10];
|
||||
u8 raw_scr[8];
|
||||
@@ -116,16 +119,17 @@ typedef struct _sdmmc_storage_t
|
||||
mmc_ext_csd_t ext_csd;
|
||||
sd_scr_t scr;
|
||||
sd_ssr_t ssr;
|
||||
int initialized;
|
||||
} sdmmc_storage_t;
|
||||
|
||||
int sdmmc_storage_end(sdmmc_storage_t *storage);
|
||||
int sdmmc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf);
|
||||
int sdmmc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf);
|
||||
int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type);
|
||||
int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition);
|
||||
int sdmmc_storage_end(sdmmc_storage_t *storage);
|
||||
int sdmmc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf);
|
||||
int sdmmc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf);
|
||||
int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type);
|
||||
int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition);
|
||||
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_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc);
|
||||
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);
|
||||
|
||||
u32 sd_storage_ssr_get_au(sdmmc_storage_t *storage);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -501,7 +501,7 @@ int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type)
|
||||
break;
|
||||
|
||||
case SDMMC_RSP_TYPE_2:
|
||||
if (size < 0x10)
|
||||
if (size < 16)
|
||||
return 0;
|
||||
rsp[0] = sdmmc->rsp[0];
|
||||
rsp[1] = sdmmc->rsp[1];
|
||||
@@ -1052,7 +1052,7 @@ DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result,
|
||||
if (!result)
|
||||
{
|
||||
#ifdef ERROR_EXTRA_PRINTING
|
||||
EPRINTFARGS("SDMMC: DMA Update failed (%08X)!", result);
|
||||
EPRINTF("SDMMC: DMA Update failed!");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -1200,8 +1200,8 @@ static int _sdmmc_config_sdmmc1(bool t210b01)
|
||||
usleep(10000);
|
||||
|
||||
// Enable SD card IO power.
|
||||
max77620_regulator_set_voltage(REGULATOR_LDO2, 3300000);
|
||||
max77620_regulator_enable(REGULATOR_LDO2, 1);
|
||||
max7762x_regulator_set_voltage(REGULATOR_LDO2, 3300000);
|
||||
max7762x_regulator_enable(REGULATOR_LDO2, true);
|
||||
usleep(1000);
|
||||
|
||||
// Set pad slew codes to get good quality clock.
|
||||
@@ -1332,18 +1332,6 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int p
|
||||
|
||||
void sdmmc1_disable_power()
|
||||
{
|
||||
// Ensure regulator is into default voltage.
|
||||
if (PMC(APBDEV_PMC_PWR_DET_VAL) & PMC_PWR_DET_SDMMC1_IO_EN)
|
||||
{
|
||||
// Switch to 1.8V and wait for regulator to stabilize.
|
||||
max77620_regulator_set_voltage(REGULATOR_LDO2, 1800000);
|
||||
usleep(150);
|
||||
|
||||
// Inform IO pads that we switched to 1.8V.
|
||||
PMC(APBDEV_PMC_PWR_DET_VAL) &= ~(PMC_PWR_DET_SDMMC1_IO_EN);
|
||||
(void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write.
|
||||
}
|
||||
|
||||
// T210B01 WAR: Clear pull down from CLK pad.
|
||||
PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) &= ~PINMUX_PULL_MASK;
|
||||
|
||||
@@ -1351,7 +1339,7 @@ void sdmmc1_disable_power()
|
||||
_sdmmc_config_sdmmc1_pads(true);
|
||||
|
||||
// Disable SD card IO power regulator.
|
||||
max77620_regulator_enable(REGULATOR_LDO2, 0);
|
||||
max7762x_regulator_enable(REGULATOR_LDO2, false);
|
||||
usleep(4000);
|
||||
|
||||
// Disable SD card IO power pin.
|
||||
@@ -1440,7 +1428,7 @@ int sdmmc_enable_low_voltage(sdmmc_t *sdmmc)
|
||||
_sdmmc_commit_changes(sdmmc);
|
||||
|
||||
// Switch to 1.8V and wait for regulator to stabilize. Assume max possible wait needed.
|
||||
max77620_regulator_set_voltage(REGULATOR_LDO2, 1800000);
|
||||
max7762x_regulator_set_voltage(REGULATOR_LDO2, 1800000);
|
||||
usleep(150);
|
||||
|
||||
// Inform IO pads that we switched to 1.8V.
|
||||
|
||||
@@ -309,7 +309,7 @@ static bool _fts_touch_read(touchpad_report_t *rpt)
|
||||
|
||||
static u8 _hid_transfer_start(usb_ctxt_t *usbs, u32 len)
|
||||
{
|
||||
u8 status = usb_ops.usb_device_ep1_in_write((u8 *)USB_EP_BULK_IN_BUF_ADDR, len, NULL, USB_XFER_SYNCED);
|
||||
u8 status = usb_ops.usb_device_ep1_in_write((u8 *)USB_EP_BULK_IN_BUF_ADDR, len, NULL, USB_XFER_SYNCED_CMD);
|
||||
if (status == USB_ERROR_XFER_ERROR)
|
||||
{
|
||||
usbs->set_text(usbs->label, "#FFDD00 Error:# EP IN transfer!");
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
|
||||
#define UMS_SCSI_TRANSFER_512K (0x80000 >> UMS_DISK_LBA_SHIFT)
|
||||
|
||||
#define UMS_EP_OUT_MAX_XFER (USB_EP_BULK_OUT_MAX_XFER >> UMS_DISK_LBA_SHIFT)
|
||||
#define UMS_EP_OUT_MAX_XFER (USB_EP_BULK_OUT_MAX_XFER)
|
||||
|
||||
// Length of a SCSI Command Data Block.
|
||||
#define SCSI_MAX_CMD_SZ 16
|
||||
@@ -121,6 +121,15 @@ enum ums_state {
|
||||
UMS_STATE_TERMINATED
|
||||
};
|
||||
|
||||
enum ums_result {
|
||||
UMS_RES_OK = 0,
|
||||
UMS_RES_IO_ERROR = -5,
|
||||
UMS_RES_TIMEOUT = -3,
|
||||
UMS_RES_PROT_FATAL = -4,
|
||||
UMS_RES_INVALID_ARG = -22
|
||||
};
|
||||
|
||||
|
||||
enum data_direction {
|
||||
DATA_DIR_UNKNOWN = 0,
|
||||
DATA_DIR_FROM_HOST,
|
||||
@@ -283,21 +292,21 @@ static int ums_wedge_bulk_in_endpoint(usbd_gadget_ums_t *ums)
|
||||
{
|
||||
/* usbd_set_ep_wedge(bulk_ctxt->bulk_in); */
|
||||
|
||||
return 0;
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
static int ums_set_stall(u32 ep)
|
||||
{
|
||||
usb_ops.usbd_set_ep_stall(ep, USB_EP_CFG_STALL);
|
||||
|
||||
return 0;
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
static int ums_clear_stall(u32 ep)
|
||||
{
|
||||
usb_ops.usbd_set_ep_stall(ep, USB_EP_CFG_CLEAR);
|
||||
|
||||
return 0;
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
static void ums_flush_endpoint(u32 ep)
|
||||
@@ -306,13 +315,13 @@ static void ums_flush_endpoint(u32 ep)
|
||||
usb_ops.usbd_flush_endpoint(ep);
|
||||
}
|
||||
|
||||
static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32 ep, bool sync)
|
||||
static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32 ep, u32 sync_timeout)
|
||||
{
|
||||
if (ep == bulk_ctxt->bulk_in)
|
||||
{
|
||||
bulk_ctxt->bulk_in_status = usb_ops.usb_device_ep1_in_write(
|
||||
bulk_ctxt->bulk_in_buf, bulk_ctxt->bulk_in_length,
|
||||
&bulk_ctxt->bulk_in_length_actual, sync);
|
||||
&bulk_ctxt->bulk_in_length_actual, sync_timeout);
|
||||
|
||||
if (bulk_ctxt->bulk_in_status == USB_ERROR_XFER_ERROR)
|
||||
{
|
||||
@@ -322,14 +331,14 @@ static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt,
|
||||
else if (bulk_ctxt->bulk_in_status == USB2_ERROR_XFER_NOT_ALIGNED)
|
||||
ums->set_text(ums->label, "#FFDD00 Error:# EP IN Buffer not aligned!");
|
||||
|
||||
if (sync)
|
||||
if (sync_timeout)
|
||||
bulk_ctxt->bulk_in_buf_state = BUF_STATE_EMPTY;
|
||||
}
|
||||
else
|
||||
{
|
||||
bulk_ctxt->bulk_out_status = usb_ops.usb_device_ep1_out_read(
|
||||
bulk_ctxt->bulk_out_buf, bulk_ctxt->bulk_out_length,
|
||||
&bulk_ctxt->bulk_out_length_actual, sync);
|
||||
&bulk_ctxt->bulk_out_length_actual, sync_timeout);
|
||||
|
||||
if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR)
|
||||
{
|
||||
@@ -339,7 +348,7 @@ static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt,
|
||||
else if (bulk_ctxt->bulk_out_status == USB2_ERROR_XFER_NOT_ALIGNED)
|
||||
ums->set_text(ums->label, "#FFDD00 Error:# EP OUT Buffer not aligned!");
|
||||
|
||||
if (sync)
|
||||
if (sync_timeout)
|
||||
bulk_ctxt->bulk_out_buf_state = BUF_STATE_FULL;
|
||||
}
|
||||
}
|
||||
@@ -377,7 +386,7 @@ static void _ums_transfer_finish(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt,
|
||||
else
|
||||
{
|
||||
bulk_ctxt->bulk_out_status = usb_ops.usb_device_ep1_out_reading_finish(
|
||||
&bulk_ctxt->bulk_out_length_actual, 1000000);
|
||||
&bulk_ctxt->bulk_out_length_actual);
|
||||
|
||||
if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR)
|
||||
{
|
||||
@@ -446,20 +455,20 @@ static int _scsi_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
if (lba_offset >= ums->lun.num_sectors)
|
||||
{
|
||||
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
// Check that request data size is not 0.
|
||||
u32 amount_left = ums->data_size_from_cmnd >> UMS_DISK_LBA_SHIFT;
|
||||
if (!amount_left)
|
||||
return -5; // I/O error. /* No default reply */
|
||||
return UMS_RES_IO_ERROR; // No default reply.
|
||||
|
||||
// Limit IO transfers based on request for faster concurrent reads.
|
||||
u32 max_io_transfer = (amount_left >= UMS_SCSI_TRANSFER_512K) ?
|
||||
@@ -520,7 +529,7 @@ static int _scsi_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
sdmmc_buf += amount << UMS_DISK_LBA_SHIFT;
|
||||
}
|
||||
|
||||
return -5; // I/O error no default reply here. /* No default reply */
|
||||
return UMS_RES_IO_ERROR; // No default reply.
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -541,7 +550,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
ums->lun.sense_data = SS_WRITE_PROTECTED;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (ums->cmnd[0] == SC_WRITE_6)
|
||||
@@ -555,7 +564,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -564,7 +573,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* Carry out the file writes */
|
||||
@@ -580,7 +589,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
|
||||
// Limit write to max supported read from EP OUT.
|
||||
amount = MIN(amount_left_to_req, UMS_EP_OUT_MAX_XFER << UMS_DISK_LBA_SHIFT);
|
||||
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
|
||||
{
|
||||
@@ -668,7 +677,7 @@ DPRINTF("file write %X @ %X\n", amount, lba_offset);
|
||||
}
|
||||
}
|
||||
|
||||
return -5; // I/O error. /* No default reply */
|
||||
return UMS_RES_IO_ERROR; // No default reply.
|
||||
}
|
||||
|
||||
static int _scsi_verify(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
@@ -679,7 +688,7 @@ static int _scsi_verify(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
// We allow DPO but we don't implement it. Check that nothing else is enabled.
|
||||
@@ -687,12 +696,12 @@ static int _scsi_verify(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
u32 verification_length = get_array_be_to_le16(&ums->cmnd[7]);
|
||||
if (verification_length == 0)
|
||||
return -5; // I/O error. /* No default reply */
|
||||
return UMS_RES_IO_ERROR; // No default reply.
|
||||
|
||||
u32 amount;
|
||||
while (verification_length > 0)
|
||||
@@ -724,7 +733,7 @@ DPRINTF("File read %X @ %X\n", amount, lba_offset);
|
||||
lba_offset += amount;
|
||||
verification_length -= amount;
|
||||
}
|
||||
return 0;
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
static int _scsi_inquiry(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
@@ -843,7 +852,7 @@ static int _scsi_read_capacity(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
put_array_le_to_be32(ums->lun.num_sectors - 1, &buf[0]); // Max logical block.
|
||||
@@ -866,14 +875,14 @@ static int _scsi_log_sense(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
ums->lun.sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (pc != 1) // Current cumulative values.
|
||||
{
|
||||
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
memset(buf, 0, 8);
|
||||
@@ -915,7 +924,7 @@ static int _scsi_log_sense(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
put_array_le_to_be16(len - 4, &buf0[2]);
|
||||
@@ -938,14 +947,14 @@ static int _scsi_mode_sense(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (pc == 3)
|
||||
{
|
||||
ums->lun.sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* Write the mode parameter header. Fixed values are: default
|
||||
@@ -995,7 +1004,7 @@ static int _scsi_mode_sense(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* Store the mode data length */
|
||||
@@ -1015,14 +1024,14 @@ static int _scsi_start_stop(usbd_gadget_ums_t *ums)
|
||||
{
|
||||
ums->lun.sense_data = SS_INVALID_COMMAND;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
else if ((ums->cmnd[1] & ~0x01) != 0 || // Mask away Immed.
|
||||
(ums->cmnd[4] & ~0x03) != 0) // Mask LoEj, Start.
|
||||
{
|
||||
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
|
||||
|
||||
return -22;
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
loej = ums->cmnd[4] & 0x02;
|
||||
@@ -1035,10 +1044,10 @@ static int _scsi_start_stop(usbd_gadget_ums_t *ums)
|
||||
{
|
||||
ums->lun.sense_data = SS_MEDIUM_NOT_PRESENT;
|
||||
|
||||
return -22;
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
// Check if we are allowed to unload the media.
|
||||
@@ -1047,16 +1056,16 @@ static int _scsi_start_stop(usbd_gadget_ums_t *ums)
|
||||
ums->set_text(ums->label, "#C7EA46 Status:# Unload attempt prevented");
|
||||
ums->lun.sense_data = SS_MEDIUM_REMOVAL_PREVENTED;
|
||||
|
||||
return -22;
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (!loej)
|
||||
return 0;
|
||||
return UMS_RES_OK;
|
||||
|
||||
// Unmount means we exit UMS because of ejection.
|
||||
ums->lun.unmounted = 1;
|
||||
|
||||
return 0;
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
static int _scsi_prevent_allow_removal(usbd_gadget_ums_t *ums)
|
||||
@@ -1067,7 +1076,7 @@ static int _scsi_prevent_allow_removal(usbd_gadget_ums_t *ums)
|
||||
{
|
||||
ums->lun.sense_data = SS_INVALID_COMMAND;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
prevent = ums->cmnd[4] & 0x01;
|
||||
@@ -1075,7 +1084,7 @@ static int _scsi_prevent_allow_removal(usbd_gadget_ums_t *ums)
|
||||
{
|
||||
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
// Notify for possible unmounting?
|
||||
@@ -1085,7 +1094,7 @@ static int _scsi_prevent_allow_removal(usbd_gadget_ums_t *ums)
|
||||
|
||||
ums->lun.prevent_medium_removal = prevent;
|
||||
|
||||
return 0;
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
static int _scsi_read_format_capacities(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
@@ -1132,7 +1141,7 @@ DPRINTF("SCSI command: %X; Dc=%d, D%c=%X; Hc=%d, H%c=%X\n",
|
||||
{
|
||||
ums->phase_error = 1;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
// Cmd length verification.
|
||||
@@ -1146,7 +1155,7 @@ DPRINTF("SCSI command: %X; Dc=%d, D%c=%X; Hc=%d, H%c=%X\n",
|
||||
{
|
||||
ums->phase_error = 1;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1167,7 +1176,7 @@ DPRINTF("SCSI command: %X; Dc=%d, D%c=%X; Hc=%d, H%c=%X\n",
|
||||
ums->lun.sense_data = ums->lun.unit_attention_data;
|
||||
ums->lun.unit_attention_data = SS_NO_SENSE;
|
||||
|
||||
return -22;
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
// Check that only command bytes listed in the mask are set.
|
||||
@@ -1178,7 +1187,7 @@ DPRINTF("SCSI command: %X; Dc=%d, D%c=%X; Hc=%d, H%c=%X\n",
|
||||
{
|
||||
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1187,16 +1196,16 @@ DPRINTF("SCSI command: %X; Dc=%d, D%c=%X; Hc=%d, H%c=%X\n",
|
||||
{
|
||||
ums->lun.sense_data = SS_MEDIUM_NOT_PRESENT;
|
||||
|
||||
return -22;
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
u32 len;
|
||||
int reply = -22; // Invalid argument.
|
||||
int reply = UMS_RES_INVALID_ARG;
|
||||
|
||||
ums->phase_error = 0;
|
||||
ums->short_packet_received = 0;
|
||||
@@ -1227,7 +1236,7 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
// We don't support MODE SELECT.
|
||||
ums->lun.sense_data = SS_INVALID_COMMAND;
|
||||
reply = -22;
|
||||
reply = UMS_RES_INVALID_ARG;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1238,7 +1247,7 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
// We don't support MODE SELECT.
|
||||
ums->lun.sense_data = SS_INVALID_COMMAND;
|
||||
reply = -22;
|
||||
reply = UMS_RES_INVALID_ARG;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1367,12 +1376,12 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
if (reply == 0)
|
||||
{
|
||||
ums->lun.sense_data = SS_INVALID_COMMAND;
|
||||
reply = -22; // Invalid argument.
|
||||
reply = UMS_RES_INVALID_ARG;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (reply == -22) // Invalid argument.
|
||||
if (reply == UMS_RES_INVALID_ARG)
|
||||
reply = 0; // Error reply length.
|
||||
|
||||
// Set up reply buffer for finish_reply(). Otherwise it's already set.
|
||||
@@ -1384,7 +1393,7 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
ums->residue -= reply;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
static int pad_with_zeros(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
@@ -1398,12 +1407,12 @@ static int pad_with_zeros(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
u32 nsend = MIN(ums->usb_amount_left, USB_EP_BUFFER_MAX_SIZE);
|
||||
memset(bulk_ctxt->bulk_in_buf + current_len_to_keep, 0, nsend - current_len_to_keep);
|
||||
bulk_ctxt->bulk_in_length = nsend;
|
||||
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED);
|
||||
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_DATA);
|
||||
ums->usb_amount_left -= nsend;
|
||||
current_len_to_keep = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
static int throw_away_data(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
@@ -1416,10 +1425,10 @@ static int throw_away_data(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
u32 amount = MIN(ums->usb_amount_left, USB_EP_BUFFER_MAX_SIZE);
|
||||
|
||||
bulk_ctxt->bulk_out_length = amount;
|
||||
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED);
|
||||
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED_DATA);
|
||||
ums->usb_amount_left -= amount;
|
||||
|
||||
return 0;
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
// Throw away the data in a filled buffer.
|
||||
@@ -1431,15 +1440,15 @@ static int throw_away_data(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
bulk_ctxt->bulk_out_status != USB_RES_OK)
|
||||
{
|
||||
raise_exception(ums, UMS_STATE_ABORT_BULK_OUT);
|
||||
return -4; // Interrupted system call
|
||||
return UMS_RES_PROT_FATAL;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
int rc = 0;
|
||||
int rc = UMS_RES_OK;
|
||||
|
||||
switch (ums->data_dir) {
|
||||
case DATA_DIR_NONE:
|
||||
@@ -1463,7 +1472,7 @@ static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
// If there's no residue, simply send the last buffer.
|
||||
if (!ums->residue)
|
||||
{
|
||||
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED);
|
||||
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_DATA);
|
||||
|
||||
/* For Bulk-only, if we're allowed to stall then send the
|
||||
* short packet and halt the bulk-in endpoint. If we can't
|
||||
@@ -1471,7 +1480,7 @@ static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
}
|
||||
else if (ums->can_stall)
|
||||
{
|
||||
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED);
|
||||
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_DATA);
|
||||
rc = ums_set_stall(bulk_ctxt->bulk_in);
|
||||
ums->set_text(ums->label, "#FFDD00 Error:# Residue. Stalled EP IN!");
|
||||
}
|
||||
@@ -1491,7 +1500,7 @@ static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
if (ums->short_packet_received) // Did the host stop sending unexpectedly early?
|
||||
{
|
||||
raise_exception(ums, UMS_STATE_ABORT_BULK_OUT);
|
||||
rc = -4; // Interrupted system call
|
||||
rc = UMS_RES_PROT_FATAL;
|
||||
}
|
||||
else // We can't stall. Read in the excess data and throw it away.
|
||||
rc = throw_away_data(ums, bulk_ctxt);
|
||||
@@ -1574,7 +1583,7 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
}
|
||||
|
||||
if (bulk_ctxt->bulk_out_status || bulk_ctxt->bulk_out_ignore)
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* Is the CBW valid? */
|
||||
@@ -1594,7 +1603,7 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
// until the next reset.
|
||||
ums_wedge_bulk_in_endpoint(ums);
|
||||
bulk_ctxt->bulk_out_ignore = 1;
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* Is the CBW meaningful? */
|
||||
@@ -1613,7 +1622,7 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
ums->set_text(ums->label, "#FFDD00 Error:# CBW unknown - Stalled both EP!");
|
||||
}
|
||||
|
||||
return -22; // Invalid argument.
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* Save the command for later */
|
||||
@@ -1636,12 +1645,12 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
if (!ums->lun.unmounted)
|
||||
ums->timeouts = 0;
|
||||
|
||||
return 0;
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
static int get_next_command(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
int rc = 0;
|
||||
int rc = UMS_RES_OK;
|
||||
|
||||
/* Wait for the next buffer to become available */
|
||||
// while (bulk_ctxt->bulk_out_buf_state != BUF_STATE_EMPTY)
|
||||
@@ -1652,7 +1661,7 @@ static int get_next_command(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
bulk_ctxt->bulk_out_length = USB_BULK_CB_WRAP_LEN;
|
||||
|
||||
/* Queue a request to read a Bulk-only CBW */
|
||||
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED);
|
||||
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED_CMD);
|
||||
|
||||
/* We will drain the buffer in software, which means we
|
||||
* can reuse it for the next filling. No need to advance
|
||||
@@ -1698,7 +1707,7 @@ static void send_status(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
csw->Status = status;
|
||||
|
||||
bulk_ctxt->bulk_in_length = USB_BULK_CS_WRAP_LEN;
|
||||
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED);
|
||||
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_CMD);
|
||||
}
|
||||
|
||||
static void handle_exception(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
@@ -1765,16 +1774,16 @@ static inline void _system_maintainance(usbd_gadget_ums_t *ums)
|
||||
|
||||
u32 time = get_tmr_ms();
|
||||
|
||||
if (timer_dram < time)
|
||||
{
|
||||
minerva_periodic_training();
|
||||
timer_dram = get_tmr_ms() + 100;
|
||||
}
|
||||
else if (timer_status_bar < time)
|
||||
if (timer_status_bar < time)
|
||||
{
|
||||
ums->system_maintenance(true);
|
||||
timer_status_bar = get_tmr_ms() + 30000;
|
||||
}
|
||||
else if (timer_dram < time)
|
||||
{
|
||||
minerva_periodic_training();
|
||||
timer_dram = get_tmr_ms() + EMC_PERIODIC_TRAIN_MS;
|
||||
}
|
||||
}
|
||||
|
||||
int usb_device_gadget_ums(usb_ctxt_t *usbs)
|
||||
|
||||
@@ -198,6 +198,7 @@ typedef struct _t210_usb2d_t
|
||||
#define XUSB_DEV_XHCI_ST 0x34
|
||||
#define XHCI_ST_RC BIT(0)
|
||||
#define XHCI_ST_IP BIT(4)
|
||||
#define XUSB_DEV_XHCI_RT_IMOD 0x38
|
||||
#define XUSB_DEV_XHCI_PORTSC 0x3C
|
||||
#define XHCI_PORTSC_PR BIT(4)
|
||||
#define XHCI_PORTSC_PLS_MASK (0xF << 5)
|
||||
|
||||
@@ -724,7 +724,7 @@ static usb_ep_status_t _usbd_get_ep_status(usb_ep_t endpoint)
|
||||
return USB_EP_STATUS_IDLE;
|
||||
}
|
||||
|
||||
static int _usbd_ep_operation(usb_ep_t endpoint, u8 *buf, u32 len, bool sync)
|
||||
static int _usbd_ep_operation(usb_ep_t endpoint, u8 *buf, u32 len, u32 sync_timeout)
|
||||
{
|
||||
if (!buf)
|
||||
len = 0;
|
||||
@@ -797,12 +797,12 @@ static int _usbd_ep_operation(usb_ep_t endpoint, u8 *buf, u32 len, bool sync)
|
||||
|
||||
int res = USB_RES_OK;
|
||||
usb_ep_status_t ep_status;
|
||||
if (sync)
|
||||
if (sync_timeout)
|
||||
{
|
||||
ep_status = _usbd_get_ep_status(endpoint);
|
||||
if (ep_status == USB_EP_STATUS_ACTIVE)
|
||||
{
|
||||
u32 retries = 1000000; // Timeout 2s.
|
||||
u32 retries = sync_timeout;
|
||||
while (retries)
|
||||
{
|
||||
ep_status = _usbd_get_ep_status(endpoint);
|
||||
@@ -834,7 +834,7 @@ out:
|
||||
|
||||
static int _usbd_ep_ack(usb_ep_t ep)
|
||||
{
|
||||
return _usbd_ep_operation(ep, NULL, 0, true);
|
||||
return _usbd_ep_operation(ep, NULL, 0, USB_XFER_SYNCED_ENUM);
|
||||
}
|
||||
|
||||
static void _usbd_set_ep0_stall()
|
||||
@@ -1275,7 +1275,7 @@ static int _usbd_handle_ep0_control_transfer()
|
||||
|
||||
if (_wLength < size)
|
||||
size = _wLength;
|
||||
res = _usbd_ep_operation(USB_EP_CTRL_IN, usb_ep0_ctrl_buf, size, true);
|
||||
res = _usbd_ep_operation(USB_EP_CTRL_IN, usb_ep0_ctrl_buf, size, USB_XFER_SYNCED_ENUM);
|
||||
if (!res)
|
||||
res = _usbd_ep_ack(USB_EP_CTRL_OUT);
|
||||
}
|
||||
@@ -1402,7 +1402,7 @@ static usb_ep_status_t _usbd_get_ep1_status(usb_dir_t dir)
|
||||
return _usbd_get_ep_status(ep);
|
||||
}
|
||||
|
||||
int usb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, bool sync)
|
||||
int usb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, u32 sync_timeout)
|
||||
{
|
||||
if ((u32)buf % USB_EP_BUFFER_ALIGN)
|
||||
return USB2_ERROR_XFER_NOT_ALIGNED;
|
||||
@@ -1410,9 +1410,9 @@ int usb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, bool sync)
|
||||
if (len > USB_EP_BUFFER_MAX_SIZE)
|
||||
len = USB_EP_BUFFER_MAX_SIZE;
|
||||
|
||||
int res = _usbd_ep_operation(USB_EP_BULK_OUT, buf, len, sync);
|
||||
int res = _usbd_ep_operation(USB_EP_BULK_OUT, buf, len, sync_timeout);
|
||||
|
||||
if (sync && bytes_read)
|
||||
if (sync_timeout && bytes_read)
|
||||
*bytes_read = res ? 0 : len;
|
||||
|
||||
return res;
|
||||
@@ -1435,7 +1435,7 @@ int usb_device_ep1_out_read_big(u8 *buf, u32 len, u32 *bytes_read)
|
||||
{
|
||||
u32 len_ep = MIN(len, USB_EP_BUFFER_MAX_SIZE);
|
||||
|
||||
res = usb_device_ep1_out_read(buf_curr, len_ep, &bytes, USB_XFER_SYNCED);
|
||||
res = usb_device_ep1_out_read(buf_curr, len_ep, &bytes, USB_XFER_SYNCED_DATA);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
int usb_device_ep1_out_reading_finish(u32 *pending_bytes, int tries)
|
||||
int usb_device_ep1_out_reading_finish(u32 *pending_bytes)
|
||||
{
|
||||
usb_ep_status_t ep_status;
|
||||
do
|
||||
@@ -1480,7 +1480,7 @@ int usb_device_ep1_out_reading_finish(u32 *pending_bytes, int tries)
|
||||
return USB_ERROR_XFER_ERROR;
|
||||
}
|
||||
|
||||
int usb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, bool sync)
|
||||
int usb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, u32 sync_timeout)
|
||||
{
|
||||
if ((u32)buf % USB_EP_BUFFER_ALIGN)
|
||||
return USB2_ERROR_XFER_NOT_ALIGNED;
|
||||
@@ -1488,9 +1488,9 @@ int usb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, bool sync)
|
||||
if (len > USB_EP_BUFFER_MAX_SIZE)
|
||||
len = USB_EP_BUFFER_MAX_SIZE;
|
||||
|
||||
int res = _usbd_ep_operation(USB_EP_BULK_IN, buf, len, sync);
|
||||
int res = _usbd_ep_operation(USB_EP_BULK_IN, buf, len, sync_timeout);
|
||||
|
||||
if (sync && bytes_written)
|
||||
if (sync_timeout && bytes_written)
|
||||
*bytes_written = res ? 0 : len;
|
||||
|
||||
return res;
|
||||
|
||||
@@ -30,8 +30,12 @@
|
||||
#define USB_EP_BUFFER_MAX_SIZE (USB_EP_BUFFER_4_TD)
|
||||
#define USB_EP_BUFFER_ALIGN (USB_TD_BUFFER_PAGE_SIZE)
|
||||
|
||||
#define USB_XFER_START false
|
||||
#define USB_XFER_SYNCED true
|
||||
#define USB_XFER_START 0
|
||||
#define USB_XFER_SYNCED_ENUM 1000000
|
||||
#define USB_XFER_SYNCED_CMD 1000000
|
||||
#define USB_XFER_SYNCED_DATA 2000000
|
||||
#define USB_XFER_SYNCED_CLASS 5000000
|
||||
#define USB_XFER_SYNCED -1
|
||||
|
||||
typedef enum _usb_hid_type
|
||||
{
|
||||
@@ -169,10 +173,10 @@ typedef struct _usb_ops_t
|
||||
int (*usb_device_class_send_max_lun)(u8);
|
||||
int (*usb_device_class_send_hid_report)();
|
||||
|
||||
int (*usb_device_ep1_out_read)(u8 *, u32, u32 *, bool);
|
||||
int (*usb_device_ep1_out_read)(u8 *, u32, u32 *, u32);
|
||||
int (*usb_device_ep1_out_read_big)(u8 *, u32, u32 *);
|
||||
int (*usb_device_ep1_out_reading_finish)(u32 *, int);
|
||||
int (*usb_device_ep1_in_write)(u8 *, u32, u32 *, bool);
|
||||
int (*usb_device_ep1_out_reading_finish)(u32 *);
|
||||
int (*usb_device_ep1_in_write)(u8 *, u32, u32 *, u32);
|
||||
int (*usb_device_ep1_in_writing_finish)(u32 *);
|
||||
bool (*usb_device_get_suspended)();
|
||||
bool (*usb_device_get_port_in_sleep)();
|
||||
|
||||
@@ -881,7 +881,7 @@ int xusb_device_init()
|
||||
_xusbd_init_device_clocks();
|
||||
|
||||
// Enable AHB redirect for access to IRAM for Event/EP ring buffers.
|
||||
mc_enable_ahb_redirect(); // can be skipped if IRAM is not used/////////////////
|
||||
mc_enable_ahb_redirect(); // Can be skipped if IRAM is not used.
|
||||
|
||||
// Enable XUSB device IPFS.
|
||||
XUSB_DEV_DEV(XUSB_DEV_CONFIGURATION) |= DEV_CONFIGURATION_EN_FPCI;
|
||||
@@ -895,14 +895,11 @@ int xusb_device_init()
|
||||
XUSB_DEV_DEV(XUSB_DEV_INTR_MASK) |= DEV_INTR_MASK_IP_INT_MASK;
|
||||
|
||||
// AHB USB performance cfg.
|
||||
//TODO: Doesn't help..
|
||||
/*
|
||||
AHB_GIZMO(AHB_GIZMO_AHB_MEM) |= AHB_MEM_DONT_SPLIT_AHB_WR | AHB_MEM_ENB_FAST_REARBITRATE;
|
||||
AHB_GIZMO(AHB_GIZMO_USB3) |= AHB_GIZMO_IMMEDIATE;
|
||||
AHB_GIZMO(AHB_ARBITRATION_PRIORITY_CTRL) = PRIORITY_CTRL_WEIGHT(7) | PRIORITY_SELECT_USB3;
|
||||
AHB_GIZMO(AHB_AHB_MEM_PREFETCH_CFG1) =
|
||||
MEM_PREFETCH_ENABLE | MEM_PREFETCH_USB3_MST_ID | MEM_PREFETCH_ADDR_BNDRY(12) | 0x1000; // Addr boundary 64KB, Inactivity 4096 cycles.
|
||||
*/
|
||||
|
||||
// Initialize context.
|
||||
usbd_xotg = &usbd_xotg_controller_ctxt;
|
||||
@@ -1771,6 +1768,13 @@ int xusb_device_enumerate(usb_gadget_type gadget)
|
||||
|
||||
usbd_xotg->gadget = gadget;
|
||||
|
||||
/*
|
||||
* Set interrupt moderation to 0us.
|
||||
* This is important because default value creates a 4.62ms latency.
|
||||
* Effectively hurting transfers by having 15% to 96% performance loss.
|
||||
*/
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_RT_IMOD) = 0;
|
||||
|
||||
// Disable Wake events.
|
||||
XUSB_PADCTL(XUSB_PADCTL_ELPG_PROGRAM_0) = 0;
|
||||
XUSB_PADCTL(XUSB_PADCTL_ELPG_PROGRAM_1) = 0;
|
||||
@@ -1803,7 +1807,7 @@ int xusb_device_enumerate(usb_gadget_type gadget)
|
||||
u32 timer = get_tmr_ms() + 90000;
|
||||
while (true)
|
||||
{
|
||||
int res = _xusb_ep_operation(1000000); // 2s timeout.
|
||||
int res = _xusb_ep_operation(USB_XFER_SYNCED_ENUM); // 2s timeout.
|
||||
if (res && res != USB_ERROR_TIMEOUT)
|
||||
return res;
|
||||
|
||||
@@ -1826,7 +1830,7 @@ void xusb_end(bool reset_ep, bool only_controller)
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB_PADCTL);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_CLR) = BIT(CLK_W_XUSB);
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB);
|
||||
mc_disable_ahb_redirect();///////////////////
|
||||
mc_disable_ahb_redirect(); // Can be skipped if IRAM is not used.
|
||||
}
|
||||
|
||||
int xusb_handle_ep0_ctrl_setup()
|
||||
@@ -1844,7 +1848,7 @@ int xusb_handle_ep0_ctrl_setup()
|
||||
return USB_RES_OK;
|
||||
}
|
||||
|
||||
int xusb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, bool sync)
|
||||
int xusb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, u32 sync_tries)
|
||||
{
|
||||
if (len > USB_EP_BUFFER_MAX_SIZE)
|
||||
len = USB_EP_BUFFER_MAX_SIZE;
|
||||
@@ -1855,10 +1859,10 @@ int xusb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, bool sync)
|
||||
_xusb_issue_normal_trb(buf, len, USB_DIR_OUT);
|
||||
usbd_xotg->tx_count[USB_DIR_OUT]++;
|
||||
|
||||
if (sync)
|
||||
if (sync_tries)
|
||||
{
|
||||
while (!res && usbd_xotg->tx_count[USB_DIR_OUT])
|
||||
res = _xusb_ep_operation(1000000); // 2s timeout.
|
||||
res = _xusb_ep_operation(sync_tries);
|
||||
|
||||
if (bytes_read)
|
||||
*bytes_read = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_OUT];
|
||||
@@ -1882,7 +1886,7 @@ int xusb_device_ep1_out_read_big(u8 *buf, u32 len, u32 *bytes_read)
|
||||
{
|
||||
u32 len_ep = MIN(len, USB_EP_BUFFER_MAX_SIZE);
|
||||
|
||||
int res = xusb_device_ep1_out_read(buf_curr, len_ep, &bytes, USB_XFER_SYNCED);
|
||||
int res = xusb_device_ep1_out_read(buf_curr, len_ep, &bytes, USB_XFER_SYNCED_DATA);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
@@ -1894,11 +1898,11 @@ int xusb_device_ep1_out_read_big(u8 *buf, u32 len, u32 *bytes_read)
|
||||
return USB_RES_OK;
|
||||
}
|
||||
|
||||
int xusb_device_ep1_out_reading_finish(u32 *pending_bytes, int tries)
|
||||
int xusb_device_ep1_out_reading_finish(u32 *pending_bytes)
|
||||
{
|
||||
int res = USB_RES_OK;
|
||||
while (!res && usbd_xotg->tx_count[USB_DIR_OUT])
|
||||
res = _xusb_ep_operation(tries);
|
||||
res = _xusb_ep_operation(USB_XFER_SYNCED); // Infinite retries.
|
||||
|
||||
if (pending_bytes)
|
||||
*pending_bytes = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_OUT];
|
||||
@@ -1908,7 +1912,7 @@ int xusb_device_ep1_out_reading_finish(u32 *pending_bytes, int tries)
|
||||
return res;
|
||||
}
|
||||
|
||||
int xusb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, bool sync)
|
||||
int xusb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, u32 sync_tries)
|
||||
{
|
||||
if (len > USB_EP_BUFFER_MAX_SIZE)
|
||||
len = USB_EP_BUFFER_MAX_SIZE;
|
||||
@@ -1921,10 +1925,10 @@ int xusb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, bool sync)
|
||||
_xusb_issue_normal_trb(buf, len, USB_DIR_IN);
|
||||
usbd_xotg->tx_count[USB_DIR_IN]++;
|
||||
|
||||
if (sync)
|
||||
if (sync_tries)
|
||||
{
|
||||
while (!res && usbd_xotg->tx_count[USB_DIR_IN])
|
||||
res = _xusb_ep_operation(1000000); // 2s timeout.
|
||||
res = _xusb_ep_operation(sync_tries);
|
||||
|
||||
if (bytes_written)
|
||||
*bytes_written = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_IN];
|
||||
@@ -1947,7 +1951,7 @@ int xusb_device_ep1_in_writing_finish(u32 *pending_bytes)
|
||||
{
|
||||
int res = USB_RES_OK;
|
||||
while (!res && usbd_xotg->tx_count[USB_DIR_IN])
|
||||
res = _xusb_ep_operation(1000000); // 2s timeout.
|
||||
res = _xusb_ep_operation(USB_XFER_SYNCED); // Infinite retries.
|
||||
|
||||
if (pending_bytes)
|
||||
*pending_bytes = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_IN];
|
||||
@@ -1973,7 +1977,7 @@ bool xusb_device_class_send_max_lun(u8 max_lun)
|
||||
// Wait for request and transfer start.
|
||||
while (usbd_xotg->device_state != XUSB_LUN_CONFIGURED)
|
||||
{
|
||||
_xusb_ep_operation(500000);
|
||||
_xusb_ep_operation(USB_XFER_SYNCED_CLASS);
|
||||
if (timer < get_tmr_ms() || btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
|
||||
return true;
|
||||
}
|
||||
@@ -1991,7 +1995,7 @@ bool xusb_device_class_send_hid_report()
|
||||
// Wait for request and transfer start.
|
||||
while (usbd_xotg->device_state != XUSB_HID_CONFIGURED)
|
||||
{
|
||||
_xusb_ep_operation(500000);
|
||||
_xusb_ep_operation(USB_XFER_SYNCED_CLASS);
|
||||
if (timer < get_tmr_ms() || btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ u8 btn_read()
|
||||
res |= BTN_VOL_DOWN;
|
||||
if (!gpio_read(GPIO_PORT_X, GPIO_PIN_6))
|
||||
res |= BTN_VOL_UP;
|
||||
if (i2c_recv_byte(4, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFSTAT) & 0x4)
|
||||
if (i2c_recv_byte(4, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFSTAT) & MAX77620_ONOFFSTAT_EN0)
|
||||
res |= BTN_POWER;
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -62,6 +62,9 @@ typedef int bool;
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
#define DISABLE 0
|
||||
#define ENABLE 1
|
||||
|
||||
#define BOOT_CFG_AUTOBOOT_EN BIT(0)
|
||||
#define BOOT_CFG_FROM_LAUNCH BIT(1)
|
||||
#define BOOT_CFG_FROM_ID BIT(2)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 CTCaer
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -44,7 +44,7 @@ u32 get_tmr_ms()
|
||||
|
||||
u32 get_tmr_us()
|
||||
{
|
||||
return TMR(TIMERUS_CNTR_1US); //TIMERUS_CNTR_1US
|
||||
return TMR(TIMERUS_CNTR_1US);
|
||||
}
|
||||
|
||||
void msleep(u32 ms)
|
||||
@@ -132,53 +132,58 @@ void panic(u32 val)
|
||||
usleep(1);
|
||||
}
|
||||
|
||||
void reboot_normal()
|
||||
void power_set_state(power_state_t state)
|
||||
{
|
||||
u8 reg;
|
||||
|
||||
// Unmount and power down sd card.
|
||||
sd_end();
|
||||
hw_reinit_workaround(false, 0);
|
||||
|
||||
panic(0x21); // Bypass fuse programming in package1.
|
||||
}
|
||||
|
||||
void reboot_rcm()
|
||||
{
|
||||
sd_end();
|
||||
hw_reinit_workaround(false, 0);
|
||||
|
||||
PMC(APBDEV_PMC_SCRATCH0) = PMC_SCRATCH0_MODE_RCM;
|
||||
PMC(APBDEV_PMC_CNTRL) |= PMC_CNTRL_MAIN_RST;
|
||||
|
||||
while (true)
|
||||
bpmp_halt();
|
||||
}
|
||||
|
||||
void reboot_full()
|
||||
{
|
||||
sd_end();
|
||||
hw_reinit_workaround(false, 0);
|
||||
|
||||
// Enable soft reset wake event.
|
||||
u8 reg = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2);
|
||||
reg |= MAX77620_ONOFFCNFG2_SFT_RST_WK;
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2, reg);
|
||||
|
||||
// Do a soft reset.
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_SFT_RST);
|
||||
|
||||
while (true)
|
||||
bpmp_halt();
|
||||
}
|
||||
|
||||
void power_off()
|
||||
{
|
||||
sd_end();
|
||||
// De-initialize and power down various hardware.
|
||||
hw_reinit_workaround(false, 0);
|
||||
|
||||
// Stop the alarm, in case we injected and powered off too fast.
|
||||
max77620_rtc_stop_alarm();
|
||||
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_PWR_OFF);
|
||||
// Set power state.
|
||||
switch (state)
|
||||
{
|
||||
case REBOOT_RCM:
|
||||
PMC(APBDEV_PMC_SCRATCH0) = PMC_SCRATCH0_MODE_RCM; // Enable RCM path.
|
||||
PMC(APBDEV_PMC_CNTRL) |= PMC_CNTRL_MAIN_RST; // PMC reset.
|
||||
break;
|
||||
|
||||
case REBOOT_BYPASS_FUSES:
|
||||
panic(0x21); // Bypass fuse programming in package1.
|
||||
break;
|
||||
|
||||
case POWER_OFF:
|
||||
// Initiate power down sequence and do not generate a reset (regulators retain state).
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_PWR_OFF);
|
||||
break;
|
||||
|
||||
case POWER_OFF_RESET:
|
||||
case POWER_OFF_REBOOT:
|
||||
default:
|
||||
// Enable/Disable soft reset wake event.
|
||||
reg = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2);
|
||||
if (state == POWER_OFF_RESET)
|
||||
reg &= ~MAX77620_ONOFFCNFG2_SFT_RST_WK; // Do not wake up after power off.
|
||||
else // POWER_OFF_REBOOT.
|
||||
reg |= MAX77620_ONOFFCNFG2_SFT_RST_WK; // Wake up after power off.
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2, reg);
|
||||
|
||||
// Initiate power down sequence and generate a reset (regulators' state resets).
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_SFT_RST);
|
||||
break;
|
||||
}
|
||||
|
||||
while (true)
|
||||
bpmp_halt();
|
||||
}
|
||||
|
||||
void power_set_state_ex(void *param)
|
||||
{
|
||||
power_state_t *state = (power_state_t *)param;
|
||||
power_set_state(*state);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 CTCaer
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -21,6 +21,18 @@
|
||||
#include <utils/types.h>
|
||||
#include <mem/minerva.h>
|
||||
|
||||
#define NYX_NEW_INFO 0x3058594E
|
||||
|
||||
typedef enum
|
||||
{
|
||||
REBOOT_RCM, // PMC reset. Enter RCM mode.
|
||||
REBOOT_BYPASS_FUSES, // PMC reset via watchdog. Enter Normal mode. Bypass fuse programming in package1.
|
||||
|
||||
POWER_OFF, // Power off PMIC. Do not reset regulators.
|
||||
POWER_OFF_RESET, // Power off PMIC. Reset regulators.
|
||||
POWER_OFF_REBOOT, // Power off PMIC. Reset regulators. Power on.
|
||||
} power_state_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NYX_CFG_BIS = BIT(5),
|
||||
@@ -49,6 +61,10 @@ typedef struct _cfg_op_t
|
||||
|
||||
typedef struct _nyx_info_t
|
||||
{
|
||||
u32 magic;
|
||||
u32 sd_init;
|
||||
u32 sd_errors[3];
|
||||
u8 rsvd[0x1000];
|
||||
u32 disp_id;
|
||||
u32 errors;
|
||||
} nyx_info_t;
|
||||
@@ -65,17 +81,18 @@ typedef struct _nyx_storage_t
|
||||
emc_table_t mtc_table[10];
|
||||
} nyx_storage_t;
|
||||
|
||||
u32 get_tmr_us();
|
||||
u32 get_tmr_ms();
|
||||
u32 get_tmr_s();
|
||||
void usleep(u32 us);
|
||||
void msleep(u32 ms);
|
||||
void panic(u32 val);
|
||||
void reboot_normal();
|
||||
void reboot_rcm();
|
||||
void reboot_full();
|
||||
void power_off();
|
||||
void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops);
|
||||
u32 crc32_calc(u32 crc, const u8 *buf, u32 len);
|
||||
|
||||
u32 get_tmr_us();
|
||||
u32 get_tmr_ms();
|
||||
u32 get_tmr_s();
|
||||
void usleep(u32 us);
|
||||
void msleep(u32 ms);
|
||||
|
||||
void panic(u32 val);
|
||||
void power_set_state(power_state_t state);
|
||||
void power_set_state_ex(void *param);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -49,25 +49,18 @@ void print_fuseinfo()
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
u32 burntFuses = 0;
|
||||
for (u32 i = 0; i < 32; i++)
|
||||
{
|
||||
if ((fuse_read_odm(7) >> i) & 1)
|
||||
burntFuses++;
|
||||
}
|
||||
|
||||
gfx_printf("\nSKU: %X - ", FUSE(FUSE_SKU_INFO));
|
||||
switch (fuse_read_odm(4) & 3)
|
||||
switch (fuse_read_hw_state())
|
||||
{
|
||||
case 0:
|
||||
case FUSE_NX_HW_STATE_PROD:
|
||||
gfx_printf("Retail\n");
|
||||
break;
|
||||
case 3:
|
||||
case FUSE_NX_HW_STATE_DEV:
|
||||
gfx_printf("Dev\n");
|
||||
break;
|
||||
}
|
||||
gfx_printf("Sdram ID: %d\n", (fuse_read_odm(4) >> 3) & 0x1F);
|
||||
gfx_printf("Burnt fuses: %d / 64\n", burntFuses);
|
||||
gfx_printf("Sdram ID: %d\n", fuse_read_dramid(true));
|
||||
gfx_printf("Burnt fuses: %d / 64\n", fuse_count_burnt(fuse_read_odm(7)));
|
||||
gfx_printf("Secure key: %08X%08X%08X%08X\n\n\n",
|
||||
byte_swap_32(FUSE(FUSE_PRIVATE_KEY0)), byte_swap_32(FUSE(FUSE_PRIVATE_KEY1)),
|
||||
byte_swap_32(FUSE(FUSE_PRIVATE_KEY2)), byte_swap_32(FUSE(FUSE_PRIVATE_KEY3)));
|
||||
|
||||
@@ -270,8 +270,6 @@ void _toggle_autorcm(bool enable)
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
|
||||
u8 randomXor = 0;
|
||||
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
@@ -285,28 +283,25 @@ void _toggle_autorcm(bool enable)
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
|
||||
int i, sect = 0;
|
||||
u8 corr_mod_byte0;
|
||||
if ((fuse_read_odm(4) & 3) != 3)
|
||||
corr_mod_byte0 = 0xF7;
|
||||
else
|
||||
corr_mod_byte0 = 0x37;
|
||||
u8 corr_mod0, mod1;
|
||||
|
||||
// Get the correct RSA modulus byte masks.
|
||||
nx_emmc_get_autorcm_masks(&corr_mod0, &mod1);
|
||||
|
||||
// Iterate BCTs.
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
sect = (0x200 + (0x4000 * i)) / NX_EMMC_BLOCKSIZE;
|
||||
sdmmc_storage_read(&storage, sect, 1, tempbuf);
|
||||
|
||||
if (enable)
|
||||
{
|
||||
do
|
||||
{
|
||||
randomXor = get_tmr_us() & 0xFF; // Bricmii style of bricking.
|
||||
} while (!randomXor); // Avoid the lottery.
|
||||
// Check if 2nd byte of modulus is correct.
|
||||
if (tempbuf[0x11] != mod1)
|
||||
continue;
|
||||
|
||||
tempbuf[0x10] ^= randomXor;
|
||||
}
|
||||
if (enable)
|
||||
tempbuf[0x10] = 0;
|
||||
else
|
||||
tempbuf[0x10] = corr_mod_byte0;
|
||||
tempbuf[0x10] = corr_mod0;
|
||||
sdmmc_storage_write(&storage, sect, 1, tempbuf);
|
||||
}
|
||||
|
||||
@@ -354,20 +349,18 @@ void menu_autorcm()
|
||||
return;
|
||||
}
|
||||
|
||||
u8 mod0, mod1;
|
||||
// Get the correct RSA modulus byte masks.
|
||||
nx_emmc_get_autorcm_masks(&mod0, &mod1);
|
||||
|
||||
u8 *tempbuf = (u8 *)malloc(0x200);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
sdmmc_storage_read(&storage, 0x200 / NX_EMMC_BLOCKSIZE, 1, tempbuf);
|
||||
|
||||
if ((fuse_read_odm(4) & 3) != 3)
|
||||
{
|
||||
if (tempbuf[0x10] != 0xF7)
|
||||
// Check if 2nd byte of modulus is correct.
|
||||
if (tempbuf[0x11] == mod1)
|
||||
if (tempbuf[0x10] != mod0)
|
||||
disabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tempbuf[0x10] != 0x37)
|
||||
disabled = false;
|
||||
}
|
||||
|
||||
free(tempbuf);
|
||||
sdmmc_storage_end(&storage);
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
gfx_ctxt_t gfx_ctxt;
|
||||
gfx_con_t gfx_con;
|
||||
|
||||
static bool gfx_con_init_done = false;
|
||||
|
||||
static const u8 _gfx_font[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Char 032 ( )
|
||||
0x00, 0x30, 0x30, 0x18, 0x18, 0x00, 0x0C, 0x00, // Char 033 (!)
|
||||
@@ -157,6 +159,8 @@ void gfx_con_init()
|
||||
gfx_con.fillbg = 1;
|
||||
gfx_con.bgcol = 0xFF1B1B1B;
|
||||
gfx_con.mute = 0;
|
||||
|
||||
gfx_con_init_done = true;
|
||||
}
|
||||
|
||||
void gfx_con_setcol(u32 fgcol, int fillbg, u32 bgcol)
|
||||
@@ -263,7 +267,7 @@ void gfx_putc(char c)
|
||||
|
||||
void gfx_puts(char *s)
|
||||
{
|
||||
if (!s || gfx_con.mute)
|
||||
if (!s || !gfx_con_init_done || gfx_con.mute)
|
||||
return;
|
||||
|
||||
for (; *s; s++)
|
||||
@@ -319,7 +323,7 @@ void gfx_put_big_sep()
|
||||
|
||||
void gfx_printf(const char *fmt, ...)
|
||||
{
|
||||
if (gfx_con.mute)
|
||||
if (!gfx_con_init_done || gfx_con.mute)
|
||||
return;
|
||||
|
||||
va_list ap;
|
||||
@@ -395,7 +399,7 @@ void gfx_printf(const char *fmt, ...)
|
||||
|
||||
void gfx_hexdump(u32 base, const u8 *buf, u32 len)
|
||||
{
|
||||
if (gfx_con.mute)
|
||||
if (!gfx_con_init_done || gfx_con.mute)
|
||||
return;
|
||||
|
||||
u8 prevFontSize = gfx_con.fntsz;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <gfx/di.h>
|
||||
#include <display/di.h>
|
||||
#include "tui.h"
|
||||
#include "../config.h"
|
||||
#include <power/max17050.h>
|
||||
|
||||
@@ -164,7 +164,7 @@ int parse_fss(launch_ctxt_t *ctxt, const char *path, fss0_sept_t *sept_ctxt)
|
||||
|
||||
if (mariko_not_supported)
|
||||
{
|
||||
EPRINTF("Mariko not supported on < 0.17.0!");
|
||||
EPRINTF("\nMariko not supported on < 0.17.0!");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include "sept.h"
|
||||
#include "secmon_exo.h"
|
||||
#include "../config.h"
|
||||
#include <gfx/di.h>
|
||||
#include <display/di.h>
|
||||
#include <gfx_utils.h>
|
||||
#include <mem/heap.h>
|
||||
#include <mem/mc.h>
|
||||
@@ -152,33 +152,6 @@ static void _se_lock(bool lock_se)
|
||||
gfx_hexdump(SE_BASE, (void *)SE_BASE, 0x400);*/
|
||||
}
|
||||
|
||||
void _pmc_scratch_lock(u32 kb)
|
||||
{
|
||||
switch (kb)
|
||||
{
|
||||
case KB_FIRMWARE_VERSION_100_200:
|
||||
case KB_FIRMWARE_VERSION_300:
|
||||
case KB_FIRMWARE_VERSION_301:
|
||||
PMC(APBDEV_PMC_SEC_DISABLE) = 0x7FFFF3;
|
||||
PMC(APBDEV_PMC_SEC_DISABLE2) = 0xFFFFFFFF;
|
||||
PMC(APBDEV_PMC_SEC_DISABLE3) = 0xFFAFFFFF;
|
||||
PMC(APBDEV_PMC_SEC_DISABLE4) = 0xFFFFFFFF;
|
||||
PMC(APBDEV_PMC_SEC_DISABLE5) = 0xFFFFFFFF;
|
||||
PMC(APBDEV_PMC_SEC_DISABLE6) = 0xFFFFFFFF;
|
||||
PMC(APBDEV_PMC_SEC_DISABLE7) = 0xFFFFFFFF;
|
||||
PMC(APBDEV_PMC_SEC_DISABLE8) = 0xFFAAFFFF;
|
||||
break;
|
||||
default:
|
||||
PMC(APBDEV_PMC_SEC_DISABLE2) |= 0x3FCFFFF;
|
||||
PMC(APBDEV_PMC_SEC_DISABLE4) |= 0x3F3FFFFF;
|
||||
PMC(APBDEV_PMC_SEC_DISABLE5) = 0xFFFFFFFF;
|
||||
PMC(APBDEV_PMC_SEC_DISABLE6) |= 0xF3FFC00F;
|
||||
PMC(APBDEV_PMC_SEC_DISABLE7) |= 0x3FFFFF;
|
||||
PMC(APBDEV_PMC_SEC_DISABLE8) |= 0xFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void _sysctr0_reset()
|
||||
{
|
||||
SYSCTR0(SYSCTR0_CNTCR) = 0;
|
||||
@@ -235,7 +208,7 @@ void hos_eks_get()
|
||||
|
||||
// Check if valid and for this unit.
|
||||
if (eks->magic == HOS_EKS_MAGIC &&
|
||||
eks->lot0 == FUSE(FUSE_OPT_LOT_CODE_0))
|
||||
(eks->lot0 == FUSE(FUSE_OPT_LOT_CODE_0) || eks->lot0 == FUSE(FUSE_PRIVATE_KEY0)))
|
||||
{
|
||||
h_cfg.eks = eks;
|
||||
return;
|
||||
@@ -286,10 +259,6 @@ void hos_eks_save(u32 kb)
|
||||
u8 *keys = (u8 *)calloc(0x1000, 1);
|
||||
se_get_aes_keys(keys + 0x800, keys, 0x10);
|
||||
|
||||
// Set SBK back.
|
||||
if (FUSE(FUSE_PRIVATE_KEY0) == 0xFFFFFFFF)
|
||||
se_aes_key_set(14, keys + 14 * 0x10, 0x10);
|
||||
|
||||
// Set magic and personalized info.
|
||||
h_cfg.eks->magic = HOS_EKS_MAGIC;
|
||||
h_cfg.eks->enabled[key_idx] = kb;
|
||||
@@ -787,22 +756,20 @@ int hos_launch(ini_sec_t *cfg)
|
||||
|
||||
// Check if fuses lower than 4.0.0 or 9.0.0 or 11.0.0 and if yes apply NO Gamecard patch.
|
||||
// Additionally check if running emuMMC and disable GC if v3/v4 fuses are burnt and HOS is <= 8.1.0 or != 11.0.0.
|
||||
//TODO: Add better checks for 11.0.0 in case mkey doesn't change.
|
||||
if (!ctxt.stock)
|
||||
{
|
||||
u32 fuses = fuse_read_odm(7);
|
||||
bool is_hos_11000 = !memcmp(ctxt.pkg1_id->id, "20201030110855", 8);
|
||||
if ((h_cfg.autonogc &&
|
||||
(
|
||||
(!(fuses & ~0xF) && (kb >= KB_FIRMWARE_VERSION_400)) || // LAFW v2.
|
||||
(!(fuses & ~0x3FF) && (kb >= KB_FIRMWARE_VERSION_900)) || // LAFW v3.
|
||||
(!(fuses & ~0x1FFF) && is_hos_11000) // LAFW v4.
|
||||
(!(fuses & ~0xF) && (ctxt.pkg1_id->fuses >= 5)) || // LAFW v2, 4.0.0+
|
||||
(!(fuses & ~0x3FF) && (ctxt.pkg1_id->fuses >= 11)) || // LAFW v3, 9.0.0+
|
||||
(!(fuses & ~0x1FFF) && (ctxt.pkg1_id->fuses >= 14)) // LAFW v4, 11.0.0+
|
||||
)
|
||||
)
|
||||
|| ((emummc_enabled) &&
|
||||
(
|
||||
((fuses & 0x400) && (kb <= KB_FIRMWARE_VERSION_810)) || // HOS 9.0.0 fuses burnt.
|
||||
((fuses & 0x2000) && !is_hos_11000) // HOS 11.0.0 fuses burnt.
|
||||
((fuses & 0x400) && (ctxt.pkg1_id->fuses <= 10)) || // HOS 9.0.0+ fuses burnt.
|
||||
((fuses & 0x2000) && (ctxt.pkg1_id->fuses <= 13)) // HOS 11.0.0+ fuses burnt.
|
||||
)
|
||||
))
|
||||
config_kip1patch(&ctxt, "nogc");
|
||||
@@ -876,7 +843,7 @@ int hos_launch(ini_sec_t *cfg)
|
||||
}
|
||||
|
||||
// Configure and manage Warmboot binary.
|
||||
pkg1_warmboot_config(&ctxt, kb, warmboot_base);
|
||||
pkg1_warmboot_config(&ctxt, warmboot_base);
|
||||
|
||||
// Replace 'warmboot.bin' if requested.
|
||||
if (ctxt.warmboot)
|
||||
@@ -1064,13 +1031,13 @@ int hos_launch(ini_sec_t *cfg)
|
||||
if (kb <= KB_FIRMWARE_VERSION_500 && !exo_new)
|
||||
{
|
||||
memset((void *)SECMON_BCT_CFG_ADDR, 0, 0x3000);
|
||||
if ((fuse_read_odm(4) & 3) == 3)
|
||||
if (fuse_read_hw_state() == FUSE_NX_HW_STATE_DEV)
|
||||
memcpy((void *)SECMON_BCT_CFG_ADDR, bootConfigBuf, 0x1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
memset((void *)SECMON6_BCT_CFG_ADDR, 0, 0x800);
|
||||
if ((fuse_read_odm(4) & 3) == 3)
|
||||
if (fuse_read_hw_state() == FUSE_NX_HW_STATE_DEV)
|
||||
memcpy((void *)SECMON6_BCT_CFG_ADDR, bootConfigBuf, 0x800);
|
||||
}
|
||||
free(bootConfigBuf);
|
||||
@@ -1094,8 +1061,8 @@ int hos_launch(ini_sec_t *cfg)
|
||||
if (kb >= KB_FIRMWARE_VERSION_620)
|
||||
_sysctr0_reset();
|
||||
|
||||
// < 4.0.0 pkg1.1 locks PMC scratches.
|
||||
//_pmc_scratch_lock(kb);
|
||||
// NX Bootloader locks LP0 Carveout secure scratch registers.
|
||||
//pmc_scratch_lock(PMC_SEC_LOCK_LP0_PARAMS);
|
||||
|
||||
// Set secmon mailbox address and clear it.
|
||||
if (kb >= KB_FIRMWARE_VERSION_700 || exo_new)
|
||||
|
||||
@@ -77,7 +77,7 @@ PATCHSET_DEF(_secmon_6_patchset,
|
||||
// { 0x1A68 + 0x3A6C, _NOP() } // warmboot UARTA cfg.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_secmon_620_patchset,
|
||||
PATCHSET_DEF(_secmon_62_patchset,
|
||||
// Patch package2 signature/hash checks.
|
||||
{ 0xDC8 + 0xC74, _NOP() }
|
||||
// Fix sleep mode for debug.
|
||||
@@ -153,23 +153,24 @@ static const u8 sec_map_100[3] = { PK11_SECTION_SM, PK11_SECTION_LD, PK11_SECTIO
|
||||
static const u8 sec_map_2xx[3] = { PK11_SECTION_WB, PK11_SECTION_LD, PK11_SECTION_SM };
|
||||
static const u8 sec_map_4xx[3] = { PK11_SECTION_LD, PK11_SECTION_SM, PK11_SECTION_WB };
|
||||
|
||||
// ID (Timestamp), KB, Fuses, TSEC, PK11, SECMON, Warmboot.
|
||||
static const pkg1_id_t _pkg1_ids[] = {
|
||||
{ "20161121183008", 0, 0x1900, 0x3FE0, SM_100_ADR, 0x8000D000, _secmon_1_patchset, _warmboot_1_patchset }, // 1.0.0 (Patched relocator).
|
||||
{ "20170210155124", 0, 0x1900, 0x3FE0, 0x4002D000, 0x8000D000, _secmon_2_patchset, _warmboot_2_patchset }, // 2.0.0 - 2.3.0.
|
||||
{ "20170519101410", 1, 0x1A00, 0x3FE0, 0x4002D000, 0x8000D000, _secmon_3_patchset, _warmboot_3_patchset }, // 3.0.0.
|
||||
{ "20170710161758", 2, 0x1A00, 0x3FE0, 0x4002D000, 0x8000D000, _secmon_3_patchset, _warmboot_3_patchset }, // 3.0.1 - 3.0.2.
|
||||
{ "20170921172629", 3, 0x1800, 0x3FE0, 0x4002B000, 0x4003B000, _secmon_4_patchset, _warmboot_4_patchset }, // 4.0.0 - 4.1.0.
|
||||
{ "20180220163747", 4, 0x1900, 0x3FE0, 0x4002B000, 0x4003B000, _secmon_5_patchset, _warmboot_4_patchset }, // 5.0.0 - 5.1.0.
|
||||
{ "20180802162753", 5, 0x1900, 0x3FE0, 0x4002B000, 0x4003D800, _secmon_6_patchset, _warmboot_4_patchset }, // 6.0.0 - 6.1.0.
|
||||
{ "20181107105733", 6, 0x0E00, 0x6FE0, 0x4002B000, 0x4003D800, _secmon_620_patchset, _warmboot_4_patchset }, // 6.2.0.
|
||||
{ "20181218175730", 7, 0x0F00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 7.0.0.
|
||||
{ "20190208150037", 7, 0x0F00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 7.0.1.
|
||||
{ "20190314172056", 7, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 8.0.0 - 8.0.1.
|
||||
{ "20190531152432", 8, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 8.1.0.
|
||||
{ "20190809135709", 9, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 9.0.0 - 9.0.1.
|
||||
{ "20191021113848", 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 9.1.0.
|
||||
{ "20200303104606", 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 10.0.0.
|
||||
{ "20201030110855", 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 11.0.0.
|
||||
{ "20161121183008", 0, 1, 0x1900, 0x3FE0, SM_100_ADR, 0x8000D000, _secmon_1_patchset, _warmboot_1_patchset }, // 1.0.0 (Patched relocator).
|
||||
{ "20170210155124", 0, 2, 0x1900, 0x3FE0, 0x4002D000, 0x8000D000, _secmon_2_patchset, _warmboot_2_patchset }, // 2.0.0 - 2.3.0.
|
||||
{ "20170519101410", 1, 3, 0x1A00, 0x3FE0, 0x4002D000, 0x8000D000, _secmon_3_patchset, _warmboot_3_patchset }, // 3.0.0.
|
||||
{ "20170710161758", 2, 4, 0x1A00, 0x3FE0, 0x4002D000, 0x8000D000, _secmon_3_patchset, _warmboot_3_patchset }, // 3.0.1 - 3.0.2.
|
||||
{ "20170921172629", 3, 5, 0x1800, 0x3FE0, 0x4002B000, 0x4003B000, _secmon_4_patchset, _warmboot_4_patchset }, // 4.0.0 - 4.1.0.
|
||||
{ "20180220163747", 4, 6, 0x1900, 0x3FE0, 0x4002B000, 0x4003B000, _secmon_5_patchset, _warmboot_4_patchset }, // 5.0.0 - 5.1.0.
|
||||
{ "20180802162753", 5, 7, 0x1900, 0x3FE0, 0x4002B000, 0x4003D800, _secmon_6_patchset, _warmboot_4_patchset }, // 6.0.0 - 6.1.0.
|
||||
{ "20181107105733", 6, 8, 0x0E00, 0x6FE0, 0x4002B000, 0x4003D800, _secmon_62_patchset, _warmboot_4_patchset }, // 6.2.0.
|
||||
{ "20181218175730", 7, 9, 0x0F00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 7.0.0.
|
||||
{ "20190208150037", 7, 9, 0x0F00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 7.0.1.
|
||||
{ "20190314172056", 7, 9, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 8.0.0 - 8.0.1.
|
||||
{ "20190531152432", 8, 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 8.1.0 - 8.1.1.
|
||||
{ "20190809135709", 9, 11, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 9.0.0 - 9.0.1.
|
||||
{ "20191021113848", 10, 12, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 9.1.0 - 9.2.0.
|
||||
{ "20200303104606", 10, 13, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 10.0.0 - 10.2.0.
|
||||
{ "20201030110855", 10, 14, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 11.0.0+
|
||||
{ NULL } // End.
|
||||
};
|
||||
|
||||
@@ -227,11 +228,11 @@ const u8 *pkg1_unpack(void *wm_dst, u32 *wb_sz, void *sm_dst, void *ldr_dst, con
|
||||
//u32 sec_off[3] = { hdr->wb_off, hdr->ldr_off, hdr->sm_off };
|
||||
|
||||
// Get correct header mapping.
|
||||
if (id->kb == KB_FIRMWARE_VERSION_100_200 && !strcmp(id->id, "20161121183008"))
|
||||
if (id->fuses == 1) // 1.0.0.
|
||||
sec_map = sec_map_100;
|
||||
else if (id->kb >= KB_FIRMWARE_VERSION_100_200 && id->kb <= KB_FIRMWARE_VERSION_301)
|
||||
else if (id->fuses >= 2 && id->fuses <= 4) // 2.0.0 - 3.0.2.
|
||||
sec_map = sec_map_2xx;
|
||||
else
|
||||
else // 4.0.0+
|
||||
sec_map = sec_map_4xx;
|
||||
|
||||
// Copy secmon, warmboot and nx bootloader payloads.
|
||||
@@ -329,9 +330,10 @@ static void _warmboot_filename(char *out, u32 fuses)
|
||||
strcat(out, ".bin");
|
||||
}
|
||||
|
||||
void pkg1_warmboot_config(void *hos_ctxt, u32 kb, u32 warmboot_base)
|
||||
void pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base)
|
||||
{
|
||||
launch_ctxt_t *ctxt = (launch_ctxt_t *)hos_ctxt;
|
||||
u32 kb = ctxt->pkg1_id->kb;
|
||||
|
||||
// Set warmboot address in PMC if required.
|
||||
if (kb <= KB_FIRMWARE_VERSION_301)
|
||||
@@ -340,17 +342,10 @@ void pkg1_warmboot_config(void *hos_ctxt, u32 kb, u32 warmboot_base)
|
||||
if (h_cfg.t210b01)
|
||||
{
|
||||
u32 pa_id;
|
||||
u32 fuses_fw = kb + 2;
|
||||
u32 fuses_max = 32; // Current ODM7 max.
|
||||
u32 fuses_fw = ctxt->pkg1_id->fuses;
|
||||
u8 burnt_fuses = fuse_count_burnt(fuse_read_odm(7));
|
||||
|
||||
// Add one more fuse for high versions.
|
||||
//TODO: Add better checks for 10.0.0 and up in case mkey doesn't change.
|
||||
if (kb > KB_FIRMWARE_VERSION_910 || !memcmp(ctxt->pkg1_id->id, "20200303104606", 8)) // 10.0.0.
|
||||
fuses_fw++;
|
||||
if (!memcmp(ctxt->pkg1_id->id, "20201030110855", 8)) // 11.0.0.
|
||||
fuses_fw += 2;
|
||||
|
||||
// Save current warmboot in storage cache and check if another one is needed.
|
||||
if (!ctxt->warmboot)
|
||||
{
|
||||
@@ -379,6 +374,8 @@ void pkg1_warmboot_config(void *hos_ctxt, u32 kb, u32 warmboot_base)
|
||||
tmp_fuses++;
|
||||
}
|
||||
}
|
||||
else // Replace burnt fuses with higher count.
|
||||
burnt_fuses = fuses_fw;
|
||||
}
|
||||
|
||||
// Configure Warmboot parameters. Anything lower is not supported.
|
||||
|
||||
@@ -53,9 +53,10 @@ typedef struct _bl_hdr_t210b01_t
|
||||
typedef struct _pkg1_id_t
|
||||
{
|
||||
const char *id;
|
||||
u32 kb;
|
||||
u32 tsec_off;
|
||||
u32 pkg11_off;
|
||||
u16 kb;
|
||||
u16 fuses;
|
||||
u16 tsec_off;
|
||||
u16 pkg11_off;
|
||||
u32 secmon_base;
|
||||
u32 warmboot_base;
|
||||
patch_t *secmon_patchset;
|
||||
@@ -80,6 +81,6 @@ int pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1);
|
||||
const u8 *pkg1_unpack(void *wm_dst, u32 *wb_sz, void *sm_dst, void *ldr_dst, const pkg1_id_t *id, u8 *pkg1);
|
||||
void pkg1_secmon_patch(void *hos_ctxt, u32 secmon_base, bool t210b01);
|
||||
void pkg1_warmboot_patch(void *hos_ctxt);
|
||||
void pkg1_warmboot_config(void *hos_ctxt, u32 kb, u32 warmboot_base);
|
||||
void pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -77,6 +77,7 @@ u32 pkg2_newkern_ini1_end;
|
||||
#define ID_SND_OFF_900 0x329A0
|
||||
#define ID_SND_OFF_1000 0x34404
|
||||
#define ID_SND_OFF_1100 0x245B4
|
||||
#define ID_SND_OFF_1101 0x245B8
|
||||
|
||||
#define ID_RCV_OFF_100 0x219F0
|
||||
#define ID_RCV_OFF_200 0x3D1A8
|
||||
@@ -90,6 +91,7 @@ u32 pkg2_newkern_ini1_end;
|
||||
#define ID_RCV_OFF_900 0x309B4
|
||||
#define ID_RCV_OFF_1000 0x322F8
|
||||
#define ID_RCV_OFF_1100 0x22B24
|
||||
#define ID_RCV_OFF_1101 0x22B28
|
||||
|
||||
static u32 PRC_ID_SND_100[] =
|
||||
{
|
||||
@@ -384,11 +386,11 @@ KERNEL_PATCHSET_DEF(_kernel_10_patchset,
|
||||
{ ATM_SYSM_INCR, 0x66950, _MOVZW(19, 0x1D80, LSL16), NULL }, // System memory pool increase.
|
||||
{ ATM_GEN_PATCH, ID_SND_OFF_1000, _B(ID_SND_OFF_1000, FREE_CODE_OFF_1ST_1000), NULL}, // Send process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_1ST_1000, sizeof(PRC_ID_SND_1000) >> 2, PRC_ID_SND_1000}, // Send process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_1ST_1000 + sizeof(PRC_ID_SND_1000), // Branch back and skip 4 instructions.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_1ST_1000 + sizeof(PRC_ID_SND_1000), // Branch back and skip 4 instructions.
|
||||
_B(FREE_CODE_OFF_1ST_1000 + sizeof(PRC_ID_SND_1000), ID_SND_OFF_1000 + sizeof(u32) * 4), NULL},
|
||||
{ ATM_GEN_PATCH, ID_RCV_OFF_1000, _B(ID_RCV_OFF_1000, FREE_CODE_OFF_2ND_1000), NULL}, // Receive process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_2ND_1000, sizeof(PRC_ID_RCV_1000) >> 2, PRC_ID_RCV_1000}, // Receive process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_2ND_1000 + sizeof(PRC_ID_RCV_1000), // Branch back and skip 4 instructions.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_2ND_1000 + sizeof(PRC_ID_RCV_1000), // Branch back and skip 4 instructions.
|
||||
_B(FREE_CODE_OFF_2ND_1000 + sizeof(PRC_ID_RCV_1000), ID_RCV_OFF_1000 + sizeof(u32) * 4), NULL}
|
||||
);
|
||||
|
||||
@@ -400,14 +402,30 @@ KERNEL_PATCHSET_DEF(_kernel_11_patchset,
|
||||
{ ATM_SYSM_INCR, 0x490C4, _MOVZW(21, 0x1D80, LSL16), NULL }, // System memory pool increase.
|
||||
{ ATM_GEN_PATCH, ID_SND_OFF_1100, _B(ID_SND_OFF_1100, FREE_CODE_OFF_1ST_1100), NULL}, // Send process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_1ST_1100, sizeof(PRC_ID_SND_1100) >> 2, PRC_ID_SND_1100}, // Send process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_1ST_1100 + sizeof(PRC_ID_SND_1100), // Branch back and skip 4 instructions.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_1ST_1100 + sizeof(PRC_ID_SND_1100), // Branch back and skip 4 instructions.
|
||||
_B(FREE_CODE_OFF_1ST_1100 + sizeof(PRC_ID_SND_1100), ID_SND_OFF_1100 + sizeof(u32) * 4), NULL},
|
||||
{ ATM_GEN_PATCH, ID_RCV_OFF_1100, _B(ID_RCV_OFF_1100, FREE_CODE_OFF_2ND_1100), NULL}, // Receive process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_2ND_1100, sizeof(PRC_ID_RCV_1100) >> 2, PRC_ID_RCV_1100}, // Receive process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_2ND_1100 + sizeof(PRC_ID_RCV_1100), // Branch back and skip 4 instructions.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_2ND_1100 + sizeof(PRC_ID_RCV_1100), // Branch back and skip 4 instructions.
|
||||
_B(FREE_CODE_OFF_2ND_1100 + sizeof(PRC_ID_RCV_1100), ID_RCV_OFF_1100 + sizeof(u32) * 4), NULL}
|
||||
);
|
||||
|
||||
KERNEL_PATCHSET_DEF(_kernel_1101_patchset,
|
||||
{ SVC_GENERIC, 0x2FD04, _NOP(), NULL }, // Allow same process on svcControlCodeMemory.
|
||||
{ SVC_VERIFY_DS, 0x39194, _NOP(), NULL }, // Disable SVC verifications.
|
||||
{ DEBUG_MODE_EN, 0x460C0, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch.
|
||||
// Atmosphère kernel patches.
|
||||
{ ATM_SYSM_INCR, 0x490C4, _MOVZW(21, 0x1D80, LSL16), NULL }, // System memory pool increase.
|
||||
{ ATM_GEN_PATCH, ID_SND_OFF_1101, _B(ID_SND_OFF_1101, FREE_CODE_OFF_1ST_1100), NULL}, // Send process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_1ST_1100, sizeof(PRC_ID_SND_1100) >> 2, PRC_ID_SND_1100}, // Send process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_1ST_1100 + sizeof(PRC_ID_SND_1100), // Branch back and skip 4 instructions.
|
||||
_B(FREE_CODE_OFF_1ST_1100 + sizeof(PRC_ID_SND_1100), ID_SND_OFF_1101 + sizeof(u32) * 4), NULL},
|
||||
{ ATM_GEN_PATCH, ID_RCV_OFF_1101, _B(ID_RCV_OFF_1101, FREE_CODE_OFF_2ND_1100), NULL}, // Receive process id branch.
|
||||
{ ATM_ARR_PATCH, FREE_CODE_OFF_2ND_1100, sizeof(PRC_ID_RCV_1100) >> 2, PRC_ID_RCV_1100}, // Receive process id code.
|
||||
{ ATM_GEN_PATCH, FREE_CODE_OFF_2ND_1100 + sizeof(PRC_ID_RCV_1100), // Branch back and skip 4 instructions.
|
||||
_B(FREE_CODE_OFF_2ND_1100 + sizeof(PRC_ID_RCV_1100), ID_RCV_OFF_1101 + sizeof(u32) * 4), NULL}
|
||||
);
|
||||
|
||||
// Kernel sha256 hashes.
|
||||
static const pkg2_kernel_id_t _pkg2_kernel_ids[] =
|
||||
{
|
||||
@@ -424,6 +442,7 @@ static const pkg2_kernel_id_t _pkg2_kernel_ids[] =
|
||||
{ "\xa2\xe3\xad\x1c\x98\xd8\x7a\x62", _kernel_9_patchset }, // 9.2.0. Kernel only.
|
||||
{ "\x21\xc1\xd7\x24\x8e\xcd\xbd\xa8", _kernel_10_patchset }, // 10.0.0. Kernel only.
|
||||
{ "\xD5\xD0\xBA\x5D\x52\xB9\x77\x85", _kernel_11_patchset }, // 11.0.0. Kernel only.
|
||||
{ "\xF8\x1E\xE0\x30\x3C\x7A\x08\x04", _kernel_1101_patchset },// 11.0.1. Kernel only.
|
||||
};
|
||||
|
||||
enum kip_offset_section
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
#include "hos.h"
|
||||
#include "../config.h"
|
||||
#include <gfx/di.h>
|
||||
#include <display/di.h>
|
||||
#include <gfx_utils.h>
|
||||
#include <libs/fatfs/ff.h>
|
||||
#include <mem/heap.h>
|
||||
@@ -82,8 +82,10 @@ typedef struct _exo_cfg_t
|
||||
u32 fwno;
|
||||
u32 flags[2];
|
||||
u16 display_id;
|
||||
u16 rsvd0;
|
||||
u32 rsvd1[3];
|
||||
u8 uart_port;
|
||||
u8 uart_invert;
|
||||
u32 uart_baudrate;
|
||||
u32 rsvd1[2];
|
||||
exo_emummc_config_t emummc_cfg;
|
||||
} exo_cfg_t;
|
||||
|
||||
@@ -148,9 +150,8 @@ typedef struct _atm_fatal_error_ctx
|
||||
|
||||
void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base, bool exo_new)
|
||||
{
|
||||
u32 exoFwNo = 0;
|
||||
u32 exoFlags = 0;
|
||||
u32 kb = ctxt->pkg1_id->kb;
|
||||
u32 exo_fw_no = 0;
|
||||
u32 exo_flags = 0;
|
||||
bool user_debug = false;
|
||||
bool cal0_blanking = false;
|
||||
bool cal0_allow_writes_sys = false;
|
||||
@@ -159,71 +160,56 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base, bool exo_new)
|
||||
|
||||
volatile exo_cfg_t *exo_cfg = (exo_cfg_t *)EXO_CFG_ADDR;
|
||||
|
||||
// Old exosphere target versioning.
|
||||
switch (kb)
|
||||
{
|
||||
case KB_FIRMWARE_VERSION_100_200:
|
||||
if (!memcmp(ctxt->pkg1_id->id, "20161121183008", 8))
|
||||
exoFwNo = 1;
|
||||
else
|
||||
exoFwNo = 2;
|
||||
break;
|
||||
case KB_FIRMWARE_VERSION_300:
|
||||
exoFwNo = 3;
|
||||
break;
|
||||
default:
|
||||
exoFwNo = kb + 1;
|
||||
if (!memcmp(ctxt->pkg1_id->id, "20190314172056", 8) || (kb >= KB_FIRMWARE_VERSION_810))
|
||||
exoFwNo++; // ATM_TARGET_FW_800 and up.
|
||||
if (!memcmp(ctxt->pkg1_id->id, "20200303104606", 8))
|
||||
exoFwNo++; // ATM_TARGET_FW_1000.
|
||||
else if (!memcmp(ctxt->pkg1_id->id, "20201030110855", 8)) //TODO: Add better checks in case mkey doesn't change.
|
||||
exoFwNo += 2; // ATM_TARGET_FW_1100.
|
||||
break;
|
||||
}
|
||||
// Old exosphere target versioning. Use fuses for a simpler encoding.
|
||||
if (ctxt->pkg1_id->fuses <= 3 || ctxt->pkg1_id->fuses >= 10) // 1.0.0 - 3.0.0, 8.1.0+.
|
||||
exo_fw_no = ctxt->pkg1_id->fuses;
|
||||
else
|
||||
exo_fw_no = ctxt->pkg1_id->fuses - 1; // 3.0.1 - 7.0.1, 8.0.0 - 8.0.1.
|
||||
|
||||
// New exosphere target versioning.
|
||||
if (!memcmp(ctxt->pkg1_id->id, "20190314172056", 8)) // 8.0.0 - 8.0.1.
|
||||
exo_fw_no++;
|
||||
|
||||
// Feed old exosphere target versioning to new.
|
||||
if (exo_new)
|
||||
{
|
||||
// Feed old versioning.
|
||||
switch (exoFwNo)
|
||||
switch (exo_fw_no)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 6:
|
||||
exoFwNo = EXO_FW_VER(exoFwNo, 0, 0);
|
||||
exo_fw_no = EXO_FW_VER(exo_fw_no, 0, 0);
|
||||
break;
|
||||
case 5:
|
||||
if (!ctxt->exo_ctx.fs_is_510)
|
||||
exoFwNo = EXO_FW_VER(5, 0, 0);
|
||||
exo_fw_no = EXO_FW_VER(5, 0, 0);
|
||||
else
|
||||
exoFwNo = EXO_FW_VER(5, 1, 0);
|
||||
exo_fw_no = EXO_FW_VER(5, 1, 0);
|
||||
break;
|
||||
case 7:
|
||||
exoFwNo = EXO_FW_VER(6, 2, 0);
|
||||
exo_fw_no = EXO_FW_VER(6, 2, 0);
|
||||
break;
|
||||
case 8:
|
||||
exoFwNo = EXO_FW_VER(7, 0, 0);
|
||||
exo_fw_no = EXO_FW_VER(7, 0, 0);
|
||||
break;
|
||||
case 9:
|
||||
exoFwNo = EXO_FW_VER(8, 0, 0);
|
||||
exo_fw_no = EXO_FW_VER(8, 0, 0);
|
||||
break;
|
||||
case 10:
|
||||
exoFwNo = EXO_FW_VER(8, 1, 0);
|
||||
exo_fw_no = EXO_FW_VER(8, 1, 0);
|
||||
break;
|
||||
case 11:
|
||||
exoFwNo = EXO_FW_VER(9, 0, 0);
|
||||
exo_fw_no = EXO_FW_VER(9, 0, 0);
|
||||
break;
|
||||
case 12:
|
||||
exoFwNo = EXO_FW_VER(9, 1, 0);
|
||||
exo_fw_no = EXO_FW_VER(9, 1, 0);
|
||||
break;
|
||||
case 13:
|
||||
exoFwNo = EXO_FW_VER(10, 0, 0);
|
||||
exo_fw_no = EXO_FW_VER(10, 0, 0);
|
||||
break;
|
||||
case 14:
|
||||
exoFwNo = EXO_FW_VER(11, 0, 0);
|
||||
exo_fw_no = EXO_FW_VER(11, 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -244,6 +230,12 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base, bool exo_new)
|
||||
{
|
||||
if (!strcmp("debugmode_user", kv->key))
|
||||
user_debug = atoi(kv->val);
|
||||
else if (!strcmp("log_port", kv->key))
|
||||
exo_cfg->uart_port = atoi(kv->val);
|
||||
else if (!strcmp("log_inverted", kv->key))
|
||||
exo_cfg->uart_invert = atoi(kv->val);
|
||||
else if (!strcmp("log_baud_rate", kv->key))
|
||||
exo_cfg->uart_baudrate = atoi(kv->val);
|
||||
else if (emu_cfg.enabled && !h_cfg.emummc_force_disable)
|
||||
{
|
||||
if (!strcmp("blank_prodinfo_emummc", kv->key))
|
||||
@@ -264,54 +256,68 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base, bool exo_new)
|
||||
|
||||
// To avoid problems, make private debug mode always on if not semi-stock.
|
||||
if (!ctxt->stock || (emu_cfg.enabled && !h_cfg.emummc_force_disable))
|
||||
exoFlags |= EXO_FLAG_DBG_PRIV;
|
||||
exo_flags |= EXO_FLAG_DBG_PRIV;
|
||||
|
||||
// Enable user debug.
|
||||
if (user_debug)
|
||||
exoFlags |= EXO_FLAG_DBG_USER;
|
||||
exo_flags |= EXO_FLAG_DBG_USER;
|
||||
|
||||
// Disable proper failure handling.
|
||||
if (ctxt->exo_ctx.no_user_exceptions)
|
||||
exoFlags |= EXO_FLAG_NO_USER_EXC;
|
||||
exo_flags |= EXO_FLAG_NO_USER_EXC;
|
||||
|
||||
// Enable user access to PMU.
|
||||
if (ctxt->exo_ctx.user_pmu)
|
||||
exoFlags |= EXO_FLAG_USER_PMU;
|
||||
exo_flags |= EXO_FLAG_USER_PMU;
|
||||
|
||||
// Enable prodinfo blanking. Check if exo ini value is overridden. If not, check if enabled in exo ini.
|
||||
if ((ctxt->exo_ctx.cal0_blank && *ctxt->exo_ctx.cal0_blank)
|
||||
|| (!ctxt->exo_ctx.cal0_blank && cal0_blanking))
|
||||
exoFlags |= EXO_FLAG_CAL0_BLANKING;
|
||||
exo_flags |= EXO_FLAG_CAL0_BLANKING;
|
||||
|
||||
// Allow prodinfo writes. Check if exo ini value is overridden. If not, check if enabled in exo ini.
|
||||
if ((ctxt->exo_ctx.cal0_allow_writes_sys && *ctxt->exo_ctx.cal0_allow_writes_sys)
|
||||
|| (!ctxt->exo_ctx.cal0_allow_writes_sys && cal0_allow_writes_sys))
|
||||
exoFlags |= EXO_FLAG_CAL0_WRITES_SYS;
|
||||
exo_flags |= EXO_FLAG_CAL0_WRITES_SYS;
|
||||
|
||||
// Set mailbox values.
|
||||
exo_cfg->magic = EXO_MAGIC_VAL;
|
||||
exo_cfg->fwno = exoFwNo;
|
||||
exo_cfg->flags[0] = exoFlags;
|
||||
exo_cfg->flags[1] = 0;
|
||||
exo_cfg->fwno = exo_fw_no;
|
||||
exo_cfg->flags[0] = exo_flags;
|
||||
|
||||
// If warmboot is lp0fw, add in RSA modulus.
|
||||
volatile wb_cfg_t *wb_cfg = (wb_cfg_t *)(warmboot_base + ATM_WB_HEADER_OFF);
|
||||
|
||||
if (wb_cfg->magic == ATM_WB_MAGIC)
|
||||
{
|
||||
wb_cfg->fwno = exoFwNo;
|
||||
wb_cfg->fwno = exo_fw_no;
|
||||
|
||||
// Set warmboot binary rsa modulus.
|
||||
u8 *rsa_mod = (u8 *)malloc(512);
|
||||
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
|
||||
sdmmc_storage_read(&emmc_storage, 1, 1, rsa_mod);
|
||||
|
||||
// Patch AutoRCM out.
|
||||
if ((fuse_read_odm(4) & 3) != 3)
|
||||
rsa_mod[0x10] = 0xF7;
|
||||
else
|
||||
rsa_mod[0x10] = 0x37;
|
||||
u32 sector;
|
||||
u8 mod0, mod1;
|
||||
|
||||
// Get the correct RSA modulus byte masks.
|
||||
nx_emmc_get_autorcm_masks(&mod0, &mod1);
|
||||
|
||||
// Iterate BCTs.
|
||||
for (u32 i = 0; i < 4; i++)
|
||||
{
|
||||
sector = 1 + (32 * i); // 0x4000 bct + 0x200 offset.
|
||||
sdmmc_storage_read(&emmc_storage, sector, 1, rsa_mod);
|
||||
|
||||
// Check if 2nd byte of modulus is correct.
|
||||
if (rsa_mod[0x11] != mod1)
|
||||
continue;
|
||||
|
||||
// Patch AutoRCM out.
|
||||
rsa_mod[0x10] = mod0;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy((void *)(warmboot_base + 0x10), rsa_mod + 0x10, 0x100);
|
||||
}
|
||||
@@ -342,10 +348,20 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base, bool exo_new)
|
||||
memset((void *)ATM_EXO_FATAL_ADDR, 0, ATM_EXO_FATAL_SIZE);
|
||||
if (ctxt->exofatal)
|
||||
memcpy((void *)ATM_EXO_FATAL_ADDR, ctxt->exofatal, ctxt->exofatal_size);
|
||||
|
||||
// Set display id.
|
||||
exo_cfg->display_id = display_get_decoded_panel_id();
|
||||
}
|
||||
|
||||
// Set display id.
|
||||
exo_cfg->display_id = display_get_decoded_lcd_id();
|
||||
#ifdef DEBUG_UART_PORT
|
||||
// Ovverride logging parameters if set in compile time.
|
||||
if (!ctxt->stock)
|
||||
{
|
||||
exo_cfg->uart_port = DEBUG_UART_PORT;
|
||||
exo_cfg->uart_invert = DEBUG_UART_INVERT;
|
||||
exo_cfg->uart_baudrate = DEBUG_UART_BAUDRATE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char *get_error_desc(u32 error_desc)
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include "fss.h"
|
||||
#include "sept.h"
|
||||
#include "../config.h"
|
||||
#include <gfx/di.h>
|
||||
#include <display/di.h>
|
||||
#include <ianos/ianos.h>
|
||||
#include <libs/fatfs/ff.h>
|
||||
#include <mem/heap.h>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <memory_map.h>
|
||||
|
||||
#include "config.h"
|
||||
#include <gfx/di.h>
|
||||
#include <display/di.h>
|
||||
#include <gfx_utils.h>
|
||||
#include "gfx/logos.h"
|
||||
#include "gfx/tui.h"
|
||||
@@ -133,7 +133,7 @@ void check_power_off_from_hos()
|
||||
msleep(600);
|
||||
display_backlight_brightness(0, 20000);
|
||||
}
|
||||
power_off();
|
||||
power_set_state(POWER_OFF_RESET);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,7 +238,7 @@ int launch_payload(char *path, bool update)
|
||||
f_close(&fp);
|
||||
|
||||
gfx_con.mute = 0;
|
||||
EPRINTF("T210B01: Coreboot not allowed!");
|
||||
EPRINTF("Coreboot not allowed on Mariko!");
|
||||
|
||||
goto out;
|
||||
}
|
||||
@@ -689,9 +689,7 @@ void nyx_load_run()
|
||||
|
||||
sd_end();
|
||||
|
||||
u32 expected_nyx_ver = ((NYX_VER_MJ + '0') << 24) | ((NYX_VER_MN + '0') << 16) | ((NYX_VER_HF + '0') << 8);
|
||||
u32 nyx_ver = byte_swap_32(*(u32 *)(nyx + NYX_VER_OFF));
|
||||
|
||||
// Show loading logo.
|
||||
gfx_clear_grey(0x1B);
|
||||
u8 *BOOTLOGO = (void *)malloc(0x4000);
|
||||
blz_uncompress_srcdest(BOOTLOGO_BLZ, SZ_BOOTLOGO_BLZ, BOOTLOGO, SZ_BOOTLOGO);
|
||||
@@ -700,6 +698,8 @@ void nyx_load_run()
|
||||
display_backlight_brightness(h_cfg.backlight, 1000);
|
||||
|
||||
// Check if Nyx version is old.
|
||||
u32 expected_nyx_ver = ((NYX_VER_MJ + '0') << 24) | ((NYX_VER_MN + '0') << 16) | ((NYX_VER_HF + '0') << 8);
|
||||
u32 nyx_ver = byte_swap_32(*(u32 *)(nyx + NYX_VER_OFF));
|
||||
if (nyx_ver < expected_nyx_ver)
|
||||
{
|
||||
h_cfg.errors |= ERR_SYSOLD_NYX;
|
||||
@@ -713,7 +713,10 @@ void nyx_load_run()
|
||||
btn_wait();
|
||||
}
|
||||
|
||||
// Set hekate errors.
|
||||
nyx_str->info.errors = h_cfg.errors;
|
||||
|
||||
// Set Nyx mode.
|
||||
nyx_str->cfg = 0;
|
||||
if (b_cfg.extra_cfg)
|
||||
{
|
||||
@@ -735,8 +738,16 @@ void nyx_load_run()
|
||||
}
|
||||
}
|
||||
|
||||
// Set hekate version used to boot Nyx.
|
||||
nyx_str->version = ipl_ver.version - 0x303030; // Convert ASCII to numbers.
|
||||
|
||||
// Set SD card initialization info.
|
||||
nyx_str->info.magic = NYX_NEW_INFO;
|
||||
nyx_str->info.sd_init = sd_get_mode();
|
||||
u16 *sd_errors = sd_get_error_count();
|
||||
for (u32 i = 0; i < 3; i++)
|
||||
nyx_str->info.sd_errors[i] = sd_errors[i];
|
||||
|
||||
//memcpy((u8 *)nyx_str->irama, (void *)IRAM_BASE, 0x8000);
|
||||
volatile reloc_meta_t *reloc = (reloc_meta_t *)(IPL_LOAD_ADDR + RELOC_META_OFF);
|
||||
memcpy((u8 *)nyx_str->hekate, (u8 *)reloc->start, reloc->end - reloc->start);
|
||||
@@ -1122,32 +1133,31 @@ static void _patched_rcm_protection()
|
||||
u8 *buf = (u8 *)malloc(0x200);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
|
||||
u8 corr_mod_byte0;
|
||||
int i, sect = 0;
|
||||
if ((fuse_read_odm(4) & 3) != 3)
|
||||
corr_mod_byte0 = 0xF7;
|
||||
else
|
||||
corr_mod_byte0 = 0x37;
|
||||
u32 sector;
|
||||
u8 corr_mod0, mod1;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
// Get the correct RSA modulus byte masks.
|
||||
nx_emmc_get_autorcm_masks(&corr_mod0, &mod1);
|
||||
|
||||
// Iterate BCTs.
|
||||
for (u32 i = 0; i < 4; i++)
|
||||
{
|
||||
sect = (0x200 + (0x4000 * i)) / NX_EMMC_BLOCKSIZE;
|
||||
sdmmc_storage_read(&storage, sect, 1, buf);
|
||||
sector = 1 + (32 * i); // 0x4000 bct + 0x200 offset.
|
||||
sdmmc_storage_read(&storage, sector, 1, buf);
|
||||
|
||||
// Check if 2nd byte of modulus is correct.
|
||||
if (buf[0x11] == 0x86)
|
||||
goto out;
|
||||
if (buf[0x11] != mod1)
|
||||
continue;
|
||||
|
||||
// If AutoRCM is enabled, disable it.
|
||||
if (buf[0x10] != corr_mod_byte0)
|
||||
if (buf[0x10] != corr_mod0)
|
||||
{
|
||||
buf[0x10] = corr_mod_byte0;
|
||||
buf[0x10] = corr_mod0;
|
||||
|
||||
sdmmc_storage_write(&storage, sect, 1, buf);
|
||||
sdmmc_storage_write(&storage, sector, 1, buf);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
free(buf);
|
||||
sdmmc_storage_end(&storage);
|
||||
}
|
||||
@@ -1235,6 +1245,9 @@ static void _show_errors()
|
||||
|
||||
static void _check_low_battery()
|
||||
{
|
||||
if (fuse_read_hw_state() == FUSE_NX_HW_STATE_DEV)
|
||||
goto out;
|
||||
|
||||
int enough_battery;
|
||||
int batt_volt = 0;
|
||||
int charge_status = 0;
|
||||
@@ -1294,7 +1307,7 @@ static void _check_low_battery()
|
||||
if (!current_charge_status)
|
||||
{
|
||||
max77620_low_battery_monitor_config(true);
|
||||
power_off();
|
||||
power_set_state(POWER_OFF_RESET);
|
||||
}
|
||||
|
||||
display_end();
|
||||
@@ -1488,23 +1501,27 @@ ment_t ment_tools[] = {
|
||||
|
||||
menu_t menu_tools = { ment_tools, "Tools", 0, 0 };
|
||||
|
||||
power_state_t STATE_POWER_OFF = POWER_OFF_RESET;
|
||||
power_state_t STATE_REBOOT_RCM = REBOOT_RCM;
|
||||
power_state_t STATE_REBOOT_BYPASS_FUSES = REBOOT_BYPASS_FUSES;
|
||||
|
||||
ment_t ment_top[] = {
|
||||
MDEF_HANDLER("Launch", launch_firmware),
|
||||
//MDEF_MENU("Options", &menu_options),
|
||||
MDEF_CAPTION("---------------", 0xFF444444),
|
||||
MDEF_MENU("Tools", &menu_tools),
|
||||
MDEF_MENU("Tools", &menu_tools),
|
||||
MDEF_MENU("Console info", &menu_cinfo),
|
||||
MDEF_CAPTION("---------------", 0xFF444444),
|
||||
MDEF_HANDLER("Reload", ipl_reload),
|
||||
MDEF_HANDLER("Reboot (Normal)", reboot_normal),
|
||||
MDEF_HANDLER("Reboot (RCM)", reboot_rcm),
|
||||
MDEF_HANDLER("Power off", power_off),
|
||||
MDEF_HANDLER_EX("Reboot (Normal)", &STATE_REBOOT_BYPASS_FUSES, power_set_state_ex),
|
||||
MDEF_HANDLER_EX("Reboot (RCM)", &STATE_REBOOT_RCM, power_set_state_ex),
|
||||
MDEF_HANDLER_EX("Power off", &STATE_POWER_OFF, power_set_state_ex),
|
||||
MDEF_CAPTION("---------------", 0xFF444444),
|
||||
MDEF_HANDLER("About", _about),
|
||||
MDEF_END()
|
||||
};
|
||||
|
||||
menu_t menu_top = { ment_top, "hekate - CTCaer mod v5.5.0", 0, 0 };
|
||||
menu_t menu_top = { ment_top, "hekate - CTCaer mod v5.5.2", 0, 0 };
|
||||
|
||||
extern void pivot_stack(u32 stack_top);
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2019-2020 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -19,6 +20,7 @@
|
||||
#include "nx_emmc.h"
|
||||
#include "emummc.h"
|
||||
#include <mem/heap.h>
|
||||
#include <soc/fuse.h>
|
||||
#include <storage/mbr_gpt.h>
|
||||
#include <utils/list.h>
|
||||
|
||||
@@ -66,6 +68,7 @@ emmc_part_t *nx_emmc_part_find(link_t *gpt, const char *name)
|
||||
LIST_FOREACH_ENTRY(emmc_part_t, part, gpt, link)
|
||||
if (!strcmp(part->name, name))
|
||||
return part;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -74,6 +77,7 @@ int nx_emmc_part_read(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_of
|
||||
// The last LBA is inclusive.
|
||||
if (part->lba_start + sector_off > part->lba_end)
|
||||
return 0;
|
||||
|
||||
return emummc_storage_read(storage, part->lba_start + sector_off, num_sectors, buf);
|
||||
}
|
||||
|
||||
@@ -82,5 +86,20 @@ int nx_emmc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_o
|
||||
// The last LBA is inclusive.
|
||||
if (part->lba_start + sector_off > part->lba_end)
|
||||
return 0;
|
||||
|
||||
return sdmmc_storage_write(storage, part->lba_start + sector_off, num_sectors, buf);
|
||||
}
|
||||
|
||||
void nx_emmc_get_autorcm_masks(u8 *mod0, u8 *mod1)
|
||||
{
|
||||
if (fuse_read_hw_state() == FUSE_NX_HW_STATE_PROD)
|
||||
{
|
||||
*mod0 = 0xF7;
|
||||
*mod1 = 0x86;
|
||||
}
|
||||
else
|
||||
{
|
||||
*mod0 = 0x37;
|
||||
*mod1 = 0x84;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2019-2020 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -43,7 +44,9 @@ extern FATFS emmc_fs;
|
||||
void nx_emmc_gpt_parse(link_t *gpt, sdmmc_storage_t *storage);
|
||||
void nx_emmc_gpt_free(link_t *gpt);
|
||||
emmc_part_t *nx_emmc_part_find(link_t *gpt, const char *name);
|
||||
int nx_emmc_part_read(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf);
|
||||
int nx_emmc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf);
|
||||
int nx_emmc_part_read(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf);
|
||||
int nx_emmc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf);
|
||||
|
||||
void nx_emmc_get_autorcm_masks(u8 *mod0, u8 *mod1);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
|
||||
typedef struct
|
||||
{
|
||||
s32 pll_osc_in;
|
||||
s32 pll_out;
|
||||
u32 pll_osc_in;
|
||||
u32 pll_out;
|
||||
u32 pll_feedback_div;
|
||||
u32 pll_input_div;
|
||||
u32 pll_post_div;
|
||||
@@ -256,7 +256,6 @@ typedef struct
|
||||
u32 emc_mrw15_idx;
|
||||
} burst_regs_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 burst_regs[221];
|
||||
|
||||
@@ -28,6 +28,9 @@
|
||||
#define EPRINTF(...)
|
||||
#define EPRINTFARGS(...)
|
||||
|
||||
#define MAX_FREQ_T210 1600000
|
||||
//#define OVERCLOCK_FREQ 1862400
|
||||
|
||||
bool emc_2X_clk_src_is_pllmb;
|
||||
bool fsp_for_src_freq;
|
||||
bool train_ram_patterns;
|
||||
@@ -1061,11 +1064,11 @@ static void _ccfifo_write(u32 addr, u32 data_val, u32 delay) //addr and delay ar
|
||||
EMC(EMC_CCFIFO_ADDR) = (addr & 0xffff) | ((delay & 0x7FFF) << 16) | (1 << 31);
|
||||
}
|
||||
|
||||
static bool _wait_emc_status(u32 reg_offset, u32 bit_mask, bool updated_state, s32 emc_channel)
|
||||
static bool _wait_emc_status(u32 reg_offset, u32 bit_mask, bool updated_state, u32 emc_channel)
|
||||
{
|
||||
bool err = true;
|
||||
|
||||
for (s32 i = 0; i < EMC_STATUS_UPDATE_TIMEOUT; i++)
|
||||
for (u32 i = 0; i < EMC_STATUS_UPDATE_TIMEOUT; i++)
|
||||
{
|
||||
if (emc_channel)
|
||||
{
|
||||
@@ -1105,7 +1108,7 @@ static u32 _start_periodic_compensation()
|
||||
return EMC(EMC_MPC);
|
||||
}
|
||||
|
||||
static bool _timing_update(s32 dual_channel)
|
||||
static bool _timing_update(u32 dual_channel)
|
||||
{
|
||||
bool err = 0;
|
||||
|
||||
@@ -1117,10 +1120,10 @@ static bool _timing_update(s32 dual_channel)
|
||||
return err;
|
||||
}
|
||||
|
||||
static s32 _get_dram_temperature()
|
||||
static u32 _get_dram_temperature()
|
||||
{
|
||||
s32 mr4_0 = 0;
|
||||
s32 mr4_1 = 0;
|
||||
u32 mr4_0 = 0;
|
||||
u32 mr4_1 = 0;
|
||||
|
||||
bool channel1_enabled = (EMC(EMC_FBIO_CFG7) >> 2) & 1;
|
||||
u32 emc_cfg_o = EMC(EMC_CFG);
|
||||
@@ -1168,11 +1171,11 @@ out:
|
||||
return mr4_0;
|
||||
}
|
||||
|
||||
static u32 _pllm_clk_base_cfg(s32 rate_KHz, u32 clk_src_emc, s32 emc_2X_clk_src_is_PLLMB)
|
||||
static u32 _pllm_clk_base_cfg(u32 rate_KHz, u32 clk_src_emc, bool emc_2X_clk_src_is_PLLMB)
|
||||
{
|
||||
u32 dividers = 0;
|
||||
s32 i = 0;
|
||||
s32 pll_ref = 38400; // Only 38.4MHz crystal is supported for T210.
|
||||
u32 i = 0;
|
||||
u32 pll_ref = 38400; // Only 38.4MHz crystal is supported for T210.
|
||||
|
||||
pllm_clk_config_t *pllm_clk_config;
|
||||
|
||||
@@ -1229,22 +1232,24 @@ static void _change_dll_src(emc_table_t *mtc_table_entry, u32 clk_src_emc)
|
||||
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC_DLL) = dll_setting;
|
||||
|
||||
//OLD
|
||||
u32 clk_enb_emc_dll = ((mtc_table_entry->clk_out_enb_x_0_clk_enb_emc_dll & 1) << 14) | (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_X) & 0xFFFFBFFF);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_X) = clk_enb_emc_dll;
|
||||
// Commit clock write.
|
||||
(void)CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_X);
|
||||
_usleep(2);
|
||||
|
||||
//NEW
|
||||
// _usleep(2);
|
||||
// if (mtc_table_entry->clk_out_enb_x_0_clk_enb_emc_dll)
|
||||
// CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) |= 0x4000;
|
||||
// else
|
||||
// CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_CLR) |= 0x4000;
|
||||
// _usleep(2);
|
||||
// Enable/Disable EMC DLL.
|
||||
if (mtc_table_entry->clk_out_enb_x_0_clk_enb_emc_dll)
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = (1 << 14);
|
||||
else
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_CLR) = (1 << 14);
|
||||
|
||||
// Commit clock write.
|
||||
(void)CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_X);
|
||||
_usleep(2);
|
||||
}
|
||||
|
||||
static u32 _digital_dll_prelock(emc_table_t *mtc_table_entry, u32 needs_tristate_training, u32 selected_clk_src_emc)
|
||||
{
|
||||
s32 dual_channel = (EMC(EMC_FBIO_CFG7) >> 1) & ((EMC(EMC_FBIO_CFG7) >> 2) & 1);
|
||||
u32 dual_channel = (EMC(EMC_FBIO_CFG7) >> 1) & ((EMC(EMC_FBIO_CFG7) >> 2) & 1);
|
||||
|
||||
EMC(EMC_CFG_DIG_DLL) = (EMC(EMC_CFG_DIG_DLL) & 0xFFFFF824) | 0x3C8;
|
||||
|
||||
@@ -1305,7 +1310,7 @@ static void _digital_dll_disable()
|
||||
;
|
||||
}
|
||||
|
||||
static void _digital_dll_enable(s32 channel1_enabled)
|
||||
static void _digital_dll_enable(u32 channel1_enabled)
|
||||
{
|
||||
EMC(EMC_CFG_DIG_DLL) |= 1;
|
||||
|
||||
@@ -1318,7 +1323,7 @@ static void _digital_dll_enable(s32 channel1_enabled)
|
||||
;
|
||||
}
|
||||
|
||||
static void _digital_dll_enable_rs(s32 channel1_enabled)
|
||||
static void _digital_dll_enable_rs(u32 channel1_enabled)
|
||||
{
|
||||
EMC(EMC_CFG_DIG_DLL) = (EMC(EMC_CFG_DIG_DLL) & 0xFFFFFF24) | 0x89;
|
||||
|
||||
@@ -1331,7 +1336,7 @@ static void _digital_dll_enable_rs(s32 channel1_enabled)
|
||||
;
|
||||
}
|
||||
|
||||
static u32 _dvfs_power_ramp_down(bool flip_backward, emc_table_t *src_emc_table_entry, emc_table_t *dst_emc_table_entry, s32 src_clock_period)
|
||||
static u32 _dvfs_power_ramp_down(bool flip_backward, emc_table_t *src_emc_table_entry, emc_table_t *dst_emc_table_entry, u32 src_clock_period)
|
||||
{
|
||||
u32 pmacro_cmd_pad;
|
||||
u32 pmacro_rfu1;
|
||||
@@ -1410,7 +1415,7 @@ static u32 _dvfs_power_ramp_down(bool flip_backward, emc_table_t *src_emc_table_
|
||||
return ramp_down_wait;
|
||||
}
|
||||
|
||||
static u32 _dvfs_power_ramp_up(bool flip_backward, emc_table_t *src_emc_table_entry, emc_table_t *dst_emc_table_entry, u8 needs_training, s32 dst_clock_period)
|
||||
static u32 _dvfs_power_ramp_up(bool flip_backward, emc_table_t *src_emc_table_entry, emc_table_t *dst_emc_table_entry, u8 needs_training, u32 dst_clock_period)
|
||||
{
|
||||
u32 pmacro_cmd_pad;
|
||||
u32 pmacro_dq_pad;
|
||||
@@ -1523,62 +1528,53 @@ static u32 _dvfs_power_ramp_up(bool flip_backward, emc_table_t *src_emc_table_en
|
||||
return ramp_up_wait;
|
||||
}
|
||||
|
||||
static u32 _minerva_update_clock_tree_delay(emc_table_t *src_emc_entry, emc_table_t *dst_emc_entry, s32 dram_dev_num, s32 channel1_enabled, enum tree_update_mode_t update_type)
|
||||
static u32 _minerva_update_clock_tree_delay(emc_table_t *src_emc_entry, emc_table_t *dst_emc_entry, u32 dram_dev_num, u32 channel1_enabled, enum tree_update_mode_t update_type)
|
||||
{
|
||||
s32 temp_ch0_0 = 0;
|
||||
s32 temp_ch0_1 = 0;
|
||||
s32 temp_ch1_0 = 0;
|
||||
s32 temp_ch1_1 = 0;
|
||||
|
||||
s32 dst_rate_mhz;
|
||||
|
||||
u32 cval = 0;
|
||||
s32 tdel0_0 = 0;
|
||||
s32 tdel0_1 = 0;
|
||||
s32 tdel1_0 = 0;
|
||||
s32 tdel1_1 = 0;
|
||||
s32 tmp_tdel0_0 = 0;
|
||||
u32 adelta = 0;
|
||||
s32 tdelta = 0;
|
||||
|
||||
u32 temp_ch0_0 = 0;
|
||||
u32 temp_ch0_1 = 0;
|
||||
u32 temp_ch1_0 = 0;
|
||||
u32 temp_ch1_1 = 0;
|
||||
|
||||
temp_ch0_0 = 0x10624DD3; // div 1000 denominator
|
||||
temp_ch0_1 = dst_emc_entry->rate_khz;
|
||||
dst_rate_mhz = dst_emc_entry->rate_khz / 1000;
|
||||
u32 upd_type_bits = 1 << update_type;
|
||||
u32 dst_rate_mhz = dst_emc_entry->rate_khz / 1000;
|
||||
u32 src_rate_mhz_2x = (src_emc_entry->rate_khz / 1000) * 2;
|
||||
|
||||
u32 tval = 1000 * (1000 * _actual_osc_clocks(src_emc_entry->run_clocks) / (src_emc_entry->rate_khz / 1000));
|
||||
if (update_type <= PERIODIC_TRAINING_UPDATE)
|
||||
u32 tval = 1000000 * _actual_osc_clocks(src_emc_entry->run_clocks);
|
||||
|
||||
if (update_type > PERIODIC_TRAINING_UPDATE)
|
||||
return 0;
|
||||
|
||||
if (upd_type_bits & 0x5400)
|
||||
{
|
||||
temp_ch0_1 = 1 << update_type;
|
||||
temp_ch0_0 = 0x5400;
|
||||
if (upd_type_bits & 0x5400)
|
||||
_request_mmr_data(0x80130000, channel1_enabled); // Dev0 MRR 19.
|
||||
temp_ch0_0 = (EMC(EMC_MRR) & 0xFF) << 8;
|
||||
temp_ch0_1 = EMC(EMC_MRR) & 0xFF00;
|
||||
if (channel1_enabled)
|
||||
{
|
||||
_request_mmr_data(0x80130000, channel1_enabled); // Dev0 MRR 19.
|
||||
temp_ch0_0 = (EMC(EMC_MRR) & 0xFF) << 8;
|
||||
temp_ch0_1 = EMC(EMC_MRR) & 0xFF00;
|
||||
if (channel1_enabled)
|
||||
{
|
||||
temp_ch1_0 = (EMC_CH1(EMC_MRR) & 0xFF) << 8;
|
||||
temp_ch1_1 = EMC_CH1(EMC_MRR) & 0xFF00;
|
||||
}
|
||||
temp_ch1_0 = (EMC_CH1(EMC_MRR) & 0xFF) << 8;
|
||||
temp_ch1_1 = EMC_CH1(EMC_MRR) & 0xFF00;
|
||||
}
|
||||
|
||||
_request_mmr_data(0x80120000, channel1_enabled); // Dev0 MRR 18.
|
||||
temp_ch0_0 |= EMC(EMC_MRR) & 0xFF;
|
||||
temp_ch0_1 |= (EMC(EMC_MRR) & 0xFF00) >> 8;
|
||||
if (channel1_enabled)
|
||||
{
|
||||
temp_ch1_0 |= EMC_CH1(EMC_MRR) & 0xFF;
|
||||
temp_ch1_1 |= (EMC_CH1(EMC_MRR) & 0xFF00) >> 8;
|
||||
}
|
||||
_request_mmr_data(0x80120000, channel1_enabled); // Dev0 MRR 18.
|
||||
temp_ch0_0 |= EMC(EMC_MRR) & 0xFF;
|
||||
temp_ch0_1 |= (EMC(EMC_MRR) & 0xFF00) >> 8;
|
||||
if (channel1_enabled)
|
||||
{
|
||||
temp_ch1_0 |= EMC_CH1(EMC_MRR) & 0xFF;
|
||||
temp_ch1_1 |= (EMC_CH1(EMC_MRR) & 0xFF00) >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
//u32 delay = (u64)((u64)_actual_osc_clocks(src_emc_entry->run_clocks) * 1000000) / (u64)(src_emc_entry->rate_khz * 2);
|
||||
cval = tval / (2 * temp_ch0_0);
|
||||
cval = tval / (src_rate_mhz_2x * temp_ch0_0);
|
||||
switch (update_type)
|
||||
{
|
||||
case DVFS_PT1:
|
||||
case TRAINING_PT1:
|
||||
dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c0d0u0_idx += 100 * cval;
|
||||
tdel0_0 = 0;
|
||||
if (update_type > PERIODIC_TRAINING_UPDATE || !(upd_type_bits & 0x6800))
|
||||
goto calc_td0_0;
|
||||
break;
|
||||
@@ -1596,20 +1592,20 @@ static u32 _minerva_update_clock_tree_delay(emc_table_t *src_emc_entry, emc_tabl
|
||||
/ (dst_emc_entry->ptfv_list.ptfv_movavg_weight_idx + 1);
|
||||
break;
|
||||
default:
|
||||
tdel0_0 = 0;
|
||||
if (update_type > PERIODIC_TRAINING_UPDATE || !(upd_type_bits & 0x6800))
|
||||
goto calc_td0_0;
|
||||
break;
|
||||
}
|
||||
|
||||
tdel0_0 = dst_emc_entry->current_dram_clktree_c0d0u0 - (dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c0d0u0_idx / 100);
|
||||
if (tdel0_0 < 0)
|
||||
tdel0_0 = !tdel0_0;
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdel0_0 << 7) / 1000000) > dst_emc_entry->tree_margin)
|
||||
tdelta = dst_emc_entry->current_dram_clktree_c0d0u0 - (dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c0d0u0_idx / 100);
|
||||
if (tdelta < 0)
|
||||
tdelta = -tdelta;
|
||||
adelta = tdelta;
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdelta << 7) / 1000000) > dst_emc_entry->tree_margin)
|
||||
dst_emc_entry->current_dram_clktree_c0d0u0 = dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c0d0u0_idx / 100;
|
||||
|
||||
calc_td0_0:
|
||||
cval = tval / (2 * temp_ch0_1);
|
||||
cval = tval / (src_rate_mhz_2x * temp_ch0_1);
|
||||
switch (update_type)
|
||||
{
|
||||
case DVFS_PT1:
|
||||
@@ -1637,18 +1633,18 @@ calc_td0_0:
|
||||
break;
|
||||
}
|
||||
|
||||
tdel0_1 = dst_emc_entry->current_dram_clktree_c0d0u1 - (dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c0d0u1_idx / 100);
|
||||
if (tdel0_1 < 0)
|
||||
tdel0_1 = !tdel0_1;
|
||||
if (tdel0_1 > tdel0_0)
|
||||
tdel0_0 = tdel0_1;
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdel0_1 << 7) / 1000000) > dst_emc_entry->tree_margin)
|
||||
tdelta = dst_emc_entry->current_dram_clktree_c0d0u1 - (dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c0d0u1_idx / 100);
|
||||
if (tdelta < 0)
|
||||
tdelta = -tdelta;
|
||||
if (tdelta > adelta)
|
||||
adelta = tdelta;
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdelta << 7) / 1000000) > dst_emc_entry->tree_margin)
|
||||
dst_emc_entry->current_dram_clktree_c0d0u1 = dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c0d0u1_idx / 100;
|
||||
|
||||
calc_td1_0:
|
||||
if (channel1_enabled)
|
||||
{
|
||||
cval = tval / (2 * temp_ch1_0);
|
||||
cval = tval / (src_rate_mhz_2x * temp_ch1_0);
|
||||
switch (update_type)
|
||||
{
|
||||
case DVFS_PT1:
|
||||
@@ -1676,16 +1672,16 @@ calc_td1_0:
|
||||
break;
|
||||
}
|
||||
|
||||
tdel1_0 = dst_emc_entry->current_dram_clktree_c1d0u0 - (dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c1d0u0_idx / 100);
|
||||
if (tdel1_0 < 0)
|
||||
tdel1_0 = !tdel1_0;
|
||||
if (tdel1_0 > tdel0_0)
|
||||
tdel0_0 = tdel1_0;
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdel1_0 << 7) / 1000000) > dst_emc_entry->tree_margin)
|
||||
tdelta = dst_emc_entry->current_dram_clktree_c1d0u0 - (dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c1d0u0_idx / 100);
|
||||
if (tdelta < 0)
|
||||
tdelta = -tdelta;
|
||||
if (tdelta > adelta)
|
||||
adelta = tdelta;
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdelta << 7) / 1000000) > dst_emc_entry->tree_margin)
|
||||
dst_emc_entry->current_dram_clktree_c1d0u0 = dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c1d0u0_idx / 100;
|
||||
|
||||
calc_td1_1:
|
||||
cval = tval / (2 * temp_ch1_1);
|
||||
cval = tval / (src_rate_mhz_2x * temp_ch1_1);
|
||||
switch (update_type)
|
||||
{
|
||||
case DVFS_PT1:
|
||||
@@ -1713,12 +1709,12 @@ calc_td1_1:
|
||||
break;
|
||||
}
|
||||
|
||||
tdel1_1 = dst_emc_entry->current_dram_clktree_c1d0u1 - (dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c1d0u1_idx / 100);
|
||||
if (tdel1_1 < 0)
|
||||
tdel1_1 = !tdel1_1;
|
||||
if (tdel1_1 > tdel0_0)
|
||||
tdel0_0 = tdel1_1;
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdel1_1 << 7) / 1000000) > dst_emc_entry->tree_margin)
|
||||
tdelta = dst_emc_entry->current_dram_clktree_c1d0u1 - (dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c1d0u1_idx / 100);
|
||||
if (tdelta < 0)
|
||||
tdelta = -tdelta;
|
||||
if (tdelta > adelta)
|
||||
adelta = tdelta;
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdelta << 7) / 1000000) > dst_emc_entry->tree_margin)
|
||||
dst_emc_entry->current_dram_clktree_c1d0u1 = dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c1d0u1_idx / 100;
|
||||
}
|
||||
|
||||
@@ -1747,7 +1743,7 @@ calc_dev2:
|
||||
}
|
||||
}
|
||||
|
||||
cval = tval / (2 * temp_ch0_0);
|
||||
cval = tval / (src_rate_mhz_2x * temp_ch0_0);
|
||||
switch (update_type )
|
||||
{
|
||||
case DVFS_PT1:
|
||||
@@ -1775,16 +1771,16 @@ calc_dev2:
|
||||
break;
|
||||
}
|
||||
|
||||
tmp_tdel0_0 = dst_emc_entry->current_dram_clktree_c0d1u0 - (dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c0d1u0_idx / 100);
|
||||
if (tmp_tdel0_0 < 0)
|
||||
tmp_tdel0_0 = !tmp_tdel0_0;
|
||||
if (tmp_tdel0_0 > tdel0_0)
|
||||
tdel0_0 = tmp_tdel0_0;
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tmp_tdel0_0 << 7) / 1000000) > dst_emc_entry->tree_margin)
|
||||
tdelta = dst_emc_entry->current_dram_clktree_c0d1u0 - (dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c0d1u0_idx / 100);
|
||||
if (tdelta < 0)
|
||||
tdelta = -tdelta;
|
||||
if (tdelta > adelta)
|
||||
adelta = tdelta;
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdelta << 7) / 1000000) > dst_emc_entry->tree_margin)
|
||||
dst_emc_entry->current_dram_clktree_c0d1u0 = dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c0d1u0_idx / 100;
|
||||
|
||||
calc_tmp_td0_1:
|
||||
cval = tval / (2 * temp_ch0_1);
|
||||
cval = tval / (src_rate_mhz_2x * temp_ch0_1);
|
||||
switch (update_type)
|
||||
{
|
||||
case DVFS_PT1:
|
||||
@@ -1812,18 +1808,18 @@ calc_tmp_td0_1:
|
||||
break;
|
||||
}
|
||||
|
||||
tdel0_1 = dst_emc_entry->current_dram_clktree_c0d1u1 - (dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c0d1u1_idx / 100);
|
||||
if (tdel0_1 < 0)
|
||||
tdel0_1 = !tdel0_1;
|
||||
if (tdel0_1 > tdel0_0)
|
||||
tdel0_0 = tdel0_1;
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdel0_1 << 7) / 1000000) > dst_emc_entry->tree_margin)
|
||||
tdelta = dst_emc_entry->current_dram_clktree_c0d1u1 - (dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c0d1u1_idx / 100);
|
||||
if (tdelta < 0)
|
||||
tdelta = -tdelta;
|
||||
if (tdelta > adelta)
|
||||
adelta = tdelta;
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdelta << 7) / 1000000) > dst_emc_entry->tree_margin)
|
||||
dst_emc_entry->current_dram_clktree_c0d1u1 = dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c0d1u1_idx / 100;
|
||||
|
||||
calc_tmp_td1_0:
|
||||
if (channel1_enabled)
|
||||
{
|
||||
cval = tval / (2 * temp_ch1_0);
|
||||
cval = tval / (src_rate_mhz_2x * temp_ch1_0);
|
||||
switch (update_type)
|
||||
{
|
||||
case DVFS_PT1:
|
||||
@@ -1851,16 +1847,16 @@ calc_tmp_td1_0:
|
||||
break;
|
||||
}
|
||||
|
||||
tdel1_0 = dst_emc_entry->current_dram_clktree_c1d1u0 - (dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c1d1u0_idx / 100);
|
||||
if (tdel1_0 < 0)
|
||||
tdel1_0 = !tdel1_0;
|
||||
if (tdel1_0 > tdel0_0)
|
||||
tdel0_0 = tdel1_0;
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdel1_0 << 7) / 1000000) > dst_emc_entry->tree_margin)
|
||||
tdelta = dst_emc_entry->current_dram_clktree_c1d1u0 - (dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c1d1u0_idx / 100);
|
||||
if (tdelta < 0)
|
||||
tdelta = -tdelta;
|
||||
if (tdelta > adelta)
|
||||
adelta = tdelta;
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdelta << 7) / 1000000) > dst_emc_entry->tree_margin)
|
||||
dst_emc_entry->current_dram_clktree_c1d1u0 = dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c1d1u0_idx / 100;
|
||||
|
||||
calc_tmp_td1_1:
|
||||
cval = tval / (2 * temp_ch1_1);
|
||||
cval = tval / (src_rate_mhz_2x * temp_ch1_1);
|
||||
switch (update_type)
|
||||
{
|
||||
case DVFS_PT1:
|
||||
@@ -1888,12 +1884,12 @@ calc_tmp_td1_1:
|
||||
break;
|
||||
}
|
||||
|
||||
tdel1_1 = dst_emc_entry->current_dram_clktree_c1d1u1 - (dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c1d1u1_idx / 100);
|
||||
if (tdel1_1 < 0)
|
||||
tdel1_1 = !tdel1_1;
|
||||
if (tdel1_1 > tdel0_0)
|
||||
tdel0_0 = tdel1_1;
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdel1_1 << 7) / 1000000) > dst_emc_entry->tree_margin)
|
||||
tdelta = dst_emc_entry->current_dram_clktree_c1d1u1 - (dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c1d1u1_idx / 100);
|
||||
if (tdelta < 0)
|
||||
tdelta = -tdelta;
|
||||
if (tdelta > adelta)
|
||||
adelta = tdelta;
|
||||
if (update_type == TRAINING_UPDATE || ((dst_rate_mhz * tdelta << 7) / 1000000) > dst_emc_entry->tree_margin)
|
||||
dst_emc_entry->current_dram_clktree_c1d1u1 = dst_emc_entry->ptfv_list.ptfv_dqsosc_movavg_c1d1u1_idx / 100;
|
||||
}
|
||||
|
||||
@@ -1910,15 +1906,14 @@ out:
|
||||
dst_emc_entry->trained_dram_clktree_c1d1u1 = dst_emc_entry->current_dram_clktree_c1d1u1;
|
||||
}
|
||||
|
||||
return (u32)tdel0_0;
|
||||
return (u32)adelta;
|
||||
}
|
||||
|
||||
static u32 _minerva_periodic_compensation_handler(emc_table_t *src_emc_entry, emc_table_t *dst_emc_entry, s32 dram_dev_num, s32 channel1_enabled, enum comp_seq_t seq_type)
|
||||
static u32 _minerva_periodic_compensation_handler(emc_table_t *src_emc_entry, emc_table_t *dst_emc_entry, u32 dram_dev_num, u32 channel1_enabled, enum comp_seq_t seq_type)
|
||||
{
|
||||
if (!dst_emc_entry->periodic_training)
|
||||
return seq_type;
|
||||
return 0;
|
||||
|
||||
u32 adel = 0;
|
||||
u32 delay = 1000 * _actual_osc_clocks(src_emc_entry->run_clocks) / src_emc_entry->rate_khz + 2;
|
||||
|
||||
if (seq_type == DVFS_SEQUENCE)
|
||||
@@ -1954,9 +1949,7 @@ static u32 _minerva_periodic_compensation_handler(emc_table_t *src_emc_entry, em
|
||||
}
|
||||
}
|
||||
|
||||
adel = _minerva_update_clock_tree_delay(src_emc_entry, dst_emc_entry, dram_dev_num, channel1_enabled, DVFS_UPDATE);
|
||||
|
||||
return adel;
|
||||
return _minerva_update_clock_tree_delay(src_emc_entry, dst_emc_entry, dram_dev_num, channel1_enabled, DVFS_UPDATE);
|
||||
}
|
||||
else if (seq_type == WRITE_TRAINING_SEQUENCE)
|
||||
{
|
||||
@@ -1976,17 +1969,13 @@ static u32 _minerva_periodic_compensation_handler(emc_table_t *src_emc_entry, em
|
||||
_minerva_update_clock_tree_delay(src_emc_entry, dst_emc_entry, dram_dev_num, channel1_enabled, TRAINING_PT1);
|
||||
}
|
||||
|
||||
adel = _minerva_update_clock_tree_delay(src_emc_entry, dst_emc_entry, dram_dev_num, channel1_enabled, TRAINING_UPDATE);
|
||||
|
||||
return adel;
|
||||
return _minerva_update_clock_tree_delay(src_emc_entry, dst_emc_entry, dram_dev_num, channel1_enabled, TRAINING_UPDATE);
|
||||
}
|
||||
else if (seq_type == PERIODIC_TRAINING_SEQUENCE)
|
||||
{
|
||||
_start_periodic_compensation();
|
||||
_usleep(delay);
|
||||
adel = _minerva_update_clock_tree_delay(src_emc_entry, dst_emc_entry, dram_dev_num, channel1_enabled, PERIODIC_TRAINING_UPDATE);
|
||||
|
||||
return adel;
|
||||
return _minerva_update_clock_tree_delay(src_emc_entry, dst_emc_entry, dram_dev_num, channel1_enabled, PERIODIC_TRAINING_UPDATE);
|
||||
}
|
||||
|
||||
return seq_type;
|
||||
@@ -2044,22 +2033,22 @@ static u32 _minerva_apply_periodic_compensation_trimmer(emc_table_t *mtc_table_e
|
||||
tree_delta_taps[1] = (tree_delta[1] * (s32)dst_rate_mhz) / 1000000;
|
||||
tree_delta_taps[2] = (tree_delta[2] * (s32)dst_rate_mhz) / 1000000;
|
||||
tree_delta_taps[3] = (tree_delta[3] * (s32)dst_rate_mhz) / 1000000;
|
||||
for (s32 i = 0; i < 4; i++)
|
||||
for (u32 i = 0; i < 4; i++)
|
||||
{
|
||||
if ((tree_delta_taps[i] > mtc_table_entry->tree_margin) || (tree_delta_taps[i] < (-1 * mtc_table_entry->tree_margin)))
|
||||
{
|
||||
new_trim[i * 2] += tree_delta_taps[i];
|
||||
new_trim[i * 2] += tree_delta_taps[i];
|
||||
new_trim[i * 2 + 1] += tree_delta_taps[i];
|
||||
}
|
||||
}
|
||||
if (trim_emc_reg_addr == EMC_DATA_BRLSHFT_0)
|
||||
{
|
||||
for (s32 i = 0; i < 8; i++)
|
||||
for (u32 i = 0; i < 8; i++)
|
||||
new_trim[i] /= 64;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (s32 i = 0; i < 8; i++)
|
||||
for (u32 i = 0; i < 8; i++)
|
||||
new_trim[i] %= 64;
|
||||
}
|
||||
break;
|
||||
@@ -2076,25 +2065,27 @@ static u32 _minerva_apply_periodic_compensation_trimmer(emc_table_t *mtc_table_e
|
||||
tree_delta_taps[1] = (tree_delta[1] * (s32)dst_rate_mhz) / 1000000;
|
||||
tree_delta_taps[2] = (tree_delta[2] * (s32)dst_rate_mhz) / 1000000;
|
||||
tree_delta_taps[3] = (tree_delta[3] * (s32)dst_rate_mhz) / 1000000;
|
||||
for (s32 i = 0; i < 4; i++)
|
||||
for (u32 i = 0; i < 4; i++)
|
||||
{
|
||||
if ((tree_delta_taps[i] > mtc_table_entry->tree_margin) || (tree_delta_taps[i] < (-1 * mtc_table_entry->tree_margin)))
|
||||
{
|
||||
new_trim[8 + i * 2] += tree_delta_taps[i];
|
||||
new_trim[8 + i * 2] += tree_delta_taps[i];
|
||||
new_trim[8 + i * 2 + 1] += tree_delta_taps[i];
|
||||
}
|
||||
}
|
||||
if (trim_emc_reg_addr == EMC_DATA_BRLSHFT_1)
|
||||
{
|
||||
for (s32 i = 0; i < 8; i++)
|
||||
for (u32 i = 0; i < 8; i++)
|
||||
new_trim[i + 8] /= 64;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (s32 i = 0; i < 8; i++)
|
||||
for (u32 i = 0; i < 8; i++)
|
||||
new_trim[i + 8] %= 64;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (trim_emc_reg_addr)
|
||||
@@ -2124,24 +2115,24 @@ static u32 _minerva_apply_periodic_compensation_trimmer(emc_table_t *mtc_table_e
|
||||
trimmer = (new_trim[14] & 0x7FF) | ((new_trim[15] & 0x7FF) << 16);
|
||||
break;
|
||||
case EMC_DATA_BRLSHFT_0:
|
||||
trimmer = (new_trim[0] & 7)
|
||||
| ((new_trim[1] & 7) << 3)
|
||||
| ((new_trim[2] & 7) << 6)
|
||||
| ((new_trim[3] & 7) << 9)
|
||||
| ((new_trim[4] & 7) << 12)
|
||||
| ((new_trim[5] & 7) << 15)
|
||||
| ((new_trim[6] & 7) << 18)
|
||||
| ((new_trim[7] & 7) << 21);
|
||||
trimmer = ((new_trim[0] & 7) << EMC_DATA_BRLSHFT_0_RANK0_BYTE0_DATA_BRLSHFT_SHIFT)
|
||||
| ((new_trim[1] & 7) << EMC_DATA_BRLSHFT_0_RANK0_BYTE1_DATA_BRLSHFT_SHIFT)
|
||||
| ((new_trim[2] & 7) << EMC_DATA_BRLSHFT_0_RANK0_BYTE2_DATA_BRLSHFT_SHIFT)
|
||||
| ((new_trim[3] & 7) << EMC_DATA_BRLSHFT_0_RANK0_BYTE3_DATA_BRLSHFT_SHIFT)
|
||||
| ((new_trim[4] & 7) << EMC_DATA_BRLSHFT_0_RANK0_BYTE4_DATA_BRLSHFT_SHIFT)
|
||||
| ((new_trim[5] & 7) << EMC_DATA_BRLSHFT_0_RANK0_BYTE5_DATA_BRLSHFT_SHIFT)
|
||||
| ((new_trim[6] & 7) << EMC_DATA_BRLSHFT_0_RANK0_BYTE6_DATA_BRLSHFT_SHIFT)
|
||||
| ((new_trim[7] & 7) << EMC_DATA_BRLSHFT_0_RANK0_BYTE7_DATA_BRLSHFT_SHIFT);
|
||||
break;
|
||||
case EMC_DATA_BRLSHFT_1:
|
||||
trimmer = (new_trim[8] & 7)
|
||||
| ((new_trim[9] & 7) << 3)
|
||||
| ((new_trim[10] & 7) << 6)
|
||||
| ((new_trim[11] & 7) << 9)
|
||||
| ((new_trim[12] & 7) << 12)
|
||||
| ((new_trim[13] & 7) << 15)
|
||||
| ((new_trim[14] & 7) << 18)
|
||||
| ((new_trim[15] & 7) << 21);
|
||||
trimmer = ((new_trim[8] & 7) << EMC_DATA_BRLSHFT_1_RANK1_BYTE0_DATA_BRLSHFT_SHIFT)
|
||||
| ((new_trim[9] & 7) << EMC_DATA_BRLSHFT_1_RANK1_BYTE1_DATA_BRLSHFT_SHIFT)
|
||||
| ((new_trim[10] & 7) << EMC_DATA_BRLSHFT_1_RANK1_BYTE2_DATA_BRLSHFT_SHIFT)
|
||||
| ((new_trim[11] & 7) << EMC_DATA_BRLSHFT_1_RANK1_BYTE3_DATA_BRLSHFT_SHIFT)
|
||||
| ((new_trim[12] & 7) << EMC_DATA_BRLSHFT_1_RANK1_BYTE4_DATA_BRLSHFT_SHIFT)
|
||||
| ((new_trim[13] & 7) << EMC_DATA_BRLSHFT_1_RANK1_BYTE5_DATA_BRLSHFT_SHIFT)
|
||||
| ((new_trim[14] & 7) << EMC_DATA_BRLSHFT_1_RANK1_BYTE6_DATA_BRLSHFT_SHIFT)
|
||||
| ((new_trim[15] & 7) << EMC_DATA_BRLSHFT_1_RANK1_BYTE7_DATA_BRLSHFT_SHIFT);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -2154,7 +2145,7 @@ static bool _check_freq_changed(u32 dst_entry_rate_KHz, u32 dst_entry_clk_src_em
|
||||
{
|
||||
s64 dst_div_clock;
|
||||
s64 src_div_clock;
|
||||
s32 src_end_div_clk_ratio;
|
||||
u32 src_end_div_clk_ratio;
|
||||
|
||||
u32 src_entry_emc_2X_clk_src = src_entry_clk_src_emc >> EMC_2X_CLK_SRC_SHIFT;
|
||||
u32 dst_entry_emc_2X_clk_src = dst_entry_clk_src_emc >> EMC_2X_CLK_SRC_SHIFT;
|
||||
@@ -2203,7 +2194,7 @@ static bool _check_freq_changed(u32 dst_entry_rate_KHz, u32 dst_entry_clk_src_em
|
||||
return false;
|
||||
}
|
||||
|
||||
static void _save_train_results(emc_table_t *mtc_table_entry, u32 needs_training, s32 dram_dev_num, bool channel1_enabled)
|
||||
static void _save_train_results(emc_table_t *mtc_table_entry, u32 needs_training, u32 dram_dev_num, bool channel1_enabled)
|
||||
{
|
||||
bool needs_ca_training = needs_training & 1;
|
||||
bool needs_ca_vref_training = (needs_training >> 1) & 1;
|
||||
@@ -2564,7 +2555,7 @@ static void _save_train_results(emc_table_t *mtc_table_entry, u32 needs_training
|
||||
}
|
||||
}
|
||||
|
||||
s32 _minerva_set_clock(emc_table_t *src_emc_entry, emc_table_t *dst_emc_entry, u32 needs_training, u32 selected_clk_src_emc)
|
||||
u32 _minerva_set_clock(emc_table_t *src_emc_entry, emc_table_t *dst_emc_entry, u32 needs_training, u32 selected_clk_src_emc)
|
||||
{
|
||||
u32 emc_dbg_o;
|
||||
u32 emc_pin_o;
|
||||
@@ -2610,11 +2601,11 @@ s32 _minerva_set_clock(emc_table_t *src_emc_entry, emc_table_t *dst_emc_entry, u
|
||||
bool zcal_resistor_shared = (src_emc_entry->burst_regs.emc_zcal_wait_cnt_idx >> 31) & 1;
|
||||
bool enable_bg_regulator = (dst_emc_entry->burst_regs.emc_pmacro_bg_bias_ctrl_0_idx & 1) ^ 1;
|
||||
bool channel1_enabled = (src_emc_entry->burst_regs.emc_fbio_cfg7_idx >> 2) & 1;
|
||||
s32 dram_type = EMC(EMC_FBIO_CFG5) & 3;
|
||||
s32 dram_dev_num = (MC(MC_EMEM_ADR_CFG) & 1) + 1;
|
||||
u32 dram_type = EMC(EMC_FBIO_CFG5) & 3;
|
||||
u32 dram_dev_num = (MC(MC_EMEM_ADR_CFG) & 1) + 1;
|
||||
|
||||
s32 src_clock_period = 1000000000 / src_emc_entry->rate_khz;
|
||||
s32 dst_clock_period = 1000000000 / dst_emc_entry->rate_khz;
|
||||
u32 src_clock_period = 1000000000 / src_emc_entry->rate_khz;
|
||||
u32 dst_clock_period = 1000000000 / dst_emc_entry->rate_khz;
|
||||
|
||||
fsp_for_src_freq = !fsp_for_src_freq;
|
||||
|
||||
@@ -2679,9 +2670,9 @@ s32 _minerva_set_clock(emc_table_t *src_emc_entry, emc_table_t *dst_emc_entry, u
|
||||
dst_emc_entry->current_dram_clktree_c1d1u0 = dst_emc_entry->trained_dram_clktree_c1d1u0;
|
||||
dst_emc_entry->current_dram_clktree_c1d1u1 = dst_emc_entry->trained_dram_clktree_c1d1u1;
|
||||
|
||||
u32 adel = _minerva_periodic_compensation_handler(src_emc_entry, dst_emc_entry, dram_dev_num, channel1_enabled, DVFS_SEQUENCE);
|
||||
u32 adelta = _minerva_periodic_compensation_handler(src_emc_entry, dst_emc_entry, dram_dev_num, channel1_enabled, DVFS_SEQUENCE);
|
||||
|
||||
if (((dst_emc_entry->rate_khz / 1000) << 7) * adel / 1000000 > dst_emc_entry->tree_margin)
|
||||
if (((dst_emc_entry->rate_khz / 1000) << 7) * adelta / 1000000 > dst_emc_entry->tree_margin)
|
||||
compensate_trimmer_applicable = true;
|
||||
}
|
||||
|
||||
@@ -2767,7 +2758,7 @@ s32 _minerva_set_clock(emc_table_t *src_emc_entry, emc_table_t *dst_emc_entry, u
|
||||
u32 RP_war = 0;
|
||||
u32 W2P_war = 0;
|
||||
|
||||
s32 nRTP = 8; // <= 1066MHz.
|
||||
u32 nRTP = 8; // <= 1066MHz.
|
||||
if (src_clock_period < 3759 // 1000 / 266MHz.
|
||||
&& src_clock_period < 1876 // 1000 / 533MHz.
|
||||
&& src_clock_period < 1250 // 1000 / 800MHz.
|
||||
@@ -2780,7 +2771,7 @@ s32 _minerva_set_clock(emc_table_t *src_emc_entry, emc_table_t *dst_emc_entry, u
|
||||
if (src_clock_period < 535) // 1000 / 1866MHz.
|
||||
nRTP = 16; // > 1866MHz
|
||||
|
||||
s32 tRPST = (src_emc_entry->emc_mrw >> 7) & 1;
|
||||
u32 tRPST = (src_emc_entry->emc_mrw >> 7) & 1;
|
||||
|
||||
u32 deltaTWATM = div_o3(7500, src_clock_period);
|
||||
if (deltaTWATM < 8)
|
||||
@@ -3057,14 +3048,13 @@ s32 _minerva_set_clock(emc_table_t *src_emc_entry, emc_table_t *dst_emc_entry, u
|
||||
// Writing burst_mc_regs.
|
||||
for (u32 i = 0; dst_emc_entry->num_mc_regs > i; i++)
|
||||
MC(burst_mc_regs_addr_table[i]) = dst_emc_entry->burst_mc_regs[i];
|
||||
}
|
||||
|
||||
// Writing la_scale_regs.
|
||||
//if ((dst_emc_entry->rate_khz < src_emc_entry->rate_khz) && dst_emc_entry->num_up_down) //NEW TODO
|
||||
if ((dst_emc_entry->rate_khz < src_emc_entry->rate_khz) > needs_tristate_training)
|
||||
{
|
||||
for (u32 i = 0; dst_emc_entry->num_up_down > i; i++)
|
||||
MC(la_scale_regs_mc_addr_table[i]) = dst_emc_entry->la_scale_regs[i];
|
||||
// Writing la_scale_regs.
|
||||
if (dst_emc_entry->rate_khz < src_emc_entry->rate_khz)
|
||||
{
|
||||
for (u32 i = 0; dst_emc_entry->num_up_down > i; i++)
|
||||
MC(la_scale_regs_mc_addr_table[i]) = dst_emc_entry->la_scale_regs[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Step 9 - LPDDR4.
|
||||
@@ -3470,8 +3460,7 @@ step_19_2:
|
||||
|
||||
// Step 25 - Program MC updown regs.
|
||||
EPRINTF("Step 25");
|
||||
//if (dst_emc_entry->rate_khz > src_emc_entry->rate_khz) //NEW TODO
|
||||
if ((dst_emc_entry->rate_khz > src_emc_entry->rate_khz) > needs_tristate_training)
|
||||
if ((dst_emc_entry->rate_khz > src_emc_entry->rate_khz) && !needs_tristate_training)
|
||||
{
|
||||
for (u32 i = 0; dst_emc_entry->num_up_down > i; i++)
|
||||
MC(la_scale_regs_mc_addr_table[i]) = dst_emc_entry->la_scale_regs[i];
|
||||
@@ -3637,13 +3626,13 @@ static void _minerva_train_patterns(emc_table_t *src_emc_entry, emc_table_t *dst
|
||||
|
||||
void _minerva_do_over_temp_compensation(mtc_config_t *mtc_cfg)
|
||||
{
|
||||
s32 dram_type = EMC(EMC_FBIO_CFG5) & 3;
|
||||
u32 dram_type = EMC(EMC_FBIO_CFG5) & 3;
|
||||
|
||||
// Only LPDDR chips are supported.
|
||||
if (dram_type != DRAM_TYPE_LPDDR4)
|
||||
return;
|
||||
|
||||
s32 dram_temp = _get_dram_temperature();
|
||||
u32 dram_temp = _get_dram_temperature();
|
||||
|
||||
if (mtc_cfg->prev_temp == dram_temp || dram_temp < 0)
|
||||
return;
|
||||
@@ -3693,7 +3682,7 @@ u32 _minerva_do_periodic_compensation(emc_table_t *mtc_table_entry)
|
||||
if (mtc_table_entry && mtc_table_entry->periodic_training)
|
||||
{
|
||||
u32 val = 0;
|
||||
s32 dram_dev_num = (MC(MC_EMEM_ADR_CFG) & 1) + 1;
|
||||
u32 dram_dev_num = (MC(MC_EMEM_ADR_CFG) & 1) + 1;
|
||||
bool channel1_enabled = (mtc_table_entry->burst_regs.emc_fbio_cfg7_idx >> 2) & 1;
|
||||
|
||||
//u32 emc_dbg_o = EMC(EMC_DBG);
|
||||
@@ -3736,10 +3725,10 @@ u32 _minerva_do_periodic_compensation(emc_table_t *mtc_table_entry)
|
||||
_usleep(1000 * _actual_osc_clocks(mtc_table_entry->run_clocks) / mtc_table_entry->rate_khz + 1);
|
||||
|
||||
// Step 4 - Check delta wrt previous values (save value if margin exceeds what is set in table).
|
||||
u32 adel = _minerva_update_clock_tree_delay(mtc_table_entry, mtc_table_entry, dram_dev_num, channel1_enabled, PERIODIC_TRAINING_UPDATE);
|
||||
u32 adelta = _minerva_update_clock_tree_delay(mtc_table_entry, mtc_table_entry, dram_dev_num, channel1_enabled, PERIODIC_TRAINING_UPDATE);
|
||||
|
||||
// Step 5 - Apply compensation w.r.t. trained values (if clock tree has drifted more than the set margin).
|
||||
if (adel && ((mtc_table_entry->rate_khz / 1000) << 7) * adel / 1000000 > mtc_table_entry->tree_margin)
|
||||
if (adelta && ((mtc_table_entry->rate_khz / 1000) << 7) * adelta / 1000000 > mtc_table_entry->tree_margin)
|
||||
{
|
||||
for (u32 i = 0; i < 10; i++)
|
||||
{
|
||||
@@ -3763,37 +3752,42 @@ u32 _minerva_do_periodic_compensation(emc_table_t *mtc_table_entry)
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 _minerva_set_rate(mtc_config_t *mtc_cfg)
|
||||
u32 _minerva_set_rate(mtc_config_t *mtc_cfg)
|
||||
{
|
||||
s32 src_emc_entry_idx = 0;
|
||||
s32 dst_emc_entry_idx = 999;
|
||||
s32 table_entry_rate;
|
||||
u32 src_emc_entry_idx = 999;
|
||||
u32 dst_emc_entry_idx = 999;
|
||||
u32 selected_clk_src_emc;
|
||||
u32 selected_emc_2x_clk_src;
|
||||
bool freq_changed = false;
|
||||
emc_table_t *src_emc_entry;
|
||||
emc_table_t *dst_emc_entry;
|
||||
|
||||
if (mtc_cfg->table_entries > 900)
|
||||
return 4;
|
||||
|
||||
for (u32 i = 0; i < mtc_cfg->table_entries; i++)
|
||||
{
|
||||
table_entry_rate = mtc_cfg->mtc_table[i].rate_khz;
|
||||
u32 table_entry_rate = mtc_cfg->mtc_table[i].rate_khz;
|
||||
if (mtc_cfg->rate_from == table_entry_rate)
|
||||
src_emc_entry_idx = i;
|
||||
if (mtc_cfg->rate_to == table_entry_rate)
|
||||
dst_emc_entry_idx = i;
|
||||
}
|
||||
|
||||
if (src_emc_entry_idx >= mtc_cfg->table_entries)
|
||||
return 4;
|
||||
|
||||
if (dst_emc_entry_idx >= mtc_cfg->table_entries)
|
||||
return 4;
|
||||
|
||||
src_emc_entry = (emc_table_t *)&mtc_cfg->mtc_table[src_emc_entry_idx];
|
||||
dst_emc_entry = (emc_table_t *)&mtc_cfg->mtc_table[dst_emc_entry_idx];
|
||||
|
||||
s32 src_rate_khz = src_emc_entry->rate_khz;
|
||||
s32 dst_rate_khz = dst_emc_entry->rate_khz;
|
||||
u32 src_rate_khz = src_emc_entry->rate_khz;
|
||||
u32 dst_rate_khz = dst_emc_entry->rate_khz;
|
||||
u32 src_clk_src_emc = src_emc_entry->clk_src_emc;
|
||||
u32 dst_clk_src_emc = dst_emc_entry->clk_src_emc;
|
||||
|
||||
if (mtc_cfg->table_entries > 900)
|
||||
return 4;
|
||||
|
||||
freq_changed = _check_freq_changed(dst_rate_khz, dst_clk_src_emc, src_rate_khz, src_clk_src_emc);
|
||||
EPRINTFARGS("Requested freq change from %d to %d.", src_rate_khz, dst_rate_khz);
|
||||
|
||||
@@ -3897,15 +3891,16 @@ void _minerva_init(mtc_config_t *mtc_cfg, void* bp)
|
||||
return;
|
||||
}
|
||||
|
||||
// If this is set, it needs to be managed. Changing freq from OC to a lower
|
||||
// must have the rate_from set to 2131200 and not 1600000
|
||||
// bool overclock = true;
|
||||
#ifdef OVERCLOCK_FREQ
|
||||
// Change max rate in table.
|
||||
mtc_cfg->mtc_table[mtc_cfg->table_entries - 1].rate_khz = OVERCLOCK_FREQ;
|
||||
|
||||
// if (overclock && mtc_cfg->rate_to == 1600000)
|
||||
// {
|
||||
// mtc_cfg->rate_to = 2131200;
|
||||
// mtc_cfg->mtc_table[9].rate_khz = 2131200;
|
||||
// }
|
||||
// Change rates for OC RAM.
|
||||
if (mtc_cfg->rate_from == MAX_FREQ_T210)
|
||||
mtc_cfg->rate_from = OVERCLOCK_FREQ;
|
||||
if (mtc_cfg->rate_to == MAX_FREQ_T210)
|
||||
mtc_cfg->rate_to = OVERCLOCK_FREQ;
|
||||
#endif
|
||||
|
||||
switch (mtc_cfg->train_mode)
|
||||
{
|
||||
@@ -3931,6 +3926,14 @@ void _minerva_init(mtc_config_t *mtc_cfg, void* bp)
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef OVERCLOCK_FREQ
|
||||
// Restore rates for OC RAM.
|
||||
if (mtc_cfg->rate_from == OVERCLOCK_FREQ)
|
||||
mtc_cfg->rate_from = MAX_FREQ_T210;
|
||||
if (mtc_cfg->rate_to == OVERCLOCK_FREQ)
|
||||
mtc_cfg->rate_to = MAX_FREQ_T210;
|
||||
#endif
|
||||
|
||||
mtc_cfg->train_ram_patterns = train_ram_patterns;
|
||||
mtc_cfg->fsp_for_src_freq = fsp_for_src_freq;
|
||||
mtc_cfg->emc_2X_clk_src_is_pllmb = emc_2X_clk_src_is_pllmb;
|
||||
|
||||
11
nyx/Makefile
11
nyx/Makefile
@@ -80,12 +80,15 @@ CUSTOMDEFINES := -DNYX_LOAD_ADDR=$(NYX_LOAD_ADDR) -DNYX_MAGIC=$(NYX_MAGIC)
|
||||
CUSTOMDEFINES += -DNYX_VER_MJ=$(NYXVERSION_MAJOR) -DNYX_VER_MN=$(NYXVERSION_MINOR) -DNYX_VER_HF=$(NYXVERSION_HOTFX) -DNYX_RESERVED=$(NYXVERSION_RSVD)
|
||||
CUSTOMDEFINES += -DNYX -DGFX_INC=$(GFX_INC) -DFFCFG_INC=$(FFCFG_INC)
|
||||
|
||||
# 0: UART_A, 1: UART_B, 2: UART_C.
|
||||
# Also enables LV LOG.
|
||||
#CUSTOMDEFINES += -DDEBUG_UART_PORT=1
|
||||
|
||||
#CUSTOMDEFINES += -DDEBUG
|
||||
|
||||
# UART Logging: Max baudrate 12.5M. Disables Joycon on Nyx if UARTB or UARTC.
|
||||
# DEBUG_UART_PORT - 0: UART_A, 1: UART_B, 2: UART_C.
|
||||
#CUSTOMDEFINES += -DDEBUG_UART_BAUDRATE=115200 -DDEBUG_UART_INVERT=0 -DDEBUG_UART_PORT=0
|
||||
|
||||
# LvGL UART LOG.
|
||||
#CUSTOMDEFINES += -DDEBUG_UART_LV_LOG
|
||||
|
||||
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb-interwork
|
||||
CFLAGS = $(ARCH) -O2 -g -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -std=gnu11 -Wall $(CUSTOMDEFINES)
|
||||
LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defsym=NYX_LOAD_ADDR=$(NYX_LOAD_ADDR)
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
extern nyx_config n_cfg;
|
||||
|
||||
extern void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage);
|
||||
extern char *emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage);
|
||||
|
||||
static void _get_valid_partition(u32 *sector_start, u32 *sector_size, u32 *part_idx, bool backup)
|
||||
{
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#include "../config.h"
|
||||
#include <utils/ini.h>
|
||||
#include <gfx/di.h>
|
||||
#include <display/di.h>
|
||||
#include <gfx_utils.h>
|
||||
#include <input/joycon.h>
|
||||
#include <input/touch.h>
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <power/max17050.h>
|
||||
#include <rtc/max77620-rtc.h>
|
||||
#include <soc/bpmp.h>
|
||||
#include <soc/fuse.h>
|
||||
#include <soc/hw_init.h>
|
||||
#include <soc/t210.h>
|
||||
#include <storage/nx_sd.h>
|
||||
@@ -718,11 +719,14 @@ lv_res_t mbox_action(lv_obj_t *btns, const char *txt)
|
||||
|
||||
bool nyx_emmc_check_battery_enough()
|
||||
{
|
||||
int batt_volt = 4000;
|
||||
if (fuse_read_hw_state() == FUSE_NX_HW_STATE_DEV)
|
||||
return true;
|
||||
|
||||
int batt_volt = 0;
|
||||
|
||||
max17050_get_property(MAX17050_VCELL, &batt_volt);
|
||||
|
||||
if (batt_volt < 3650)
|
||||
if (batt_volt && batt_volt < 3650)
|
||||
{
|
||||
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
|
||||
lv_obj_set_style(dark_bg, &mbox_darken);
|
||||
@@ -850,7 +854,7 @@ static void _launch_hos(u8 autoboot, u8 autoboot_list)
|
||||
b_cfg->boot_cfg = BOOT_CFG_AUTOBOOT_EN;
|
||||
if (launch_logs_enable)
|
||||
b_cfg->boot_cfg |= BOOT_CFG_FROM_LAUNCH;
|
||||
b_cfg->autoboot = autoboot & ~0x80;
|
||||
b_cfg->autoboot = autoboot;
|
||||
b_cfg->autoboot_list = autoboot_list;
|
||||
|
||||
void (*main_ptr)() = (void *)nyx_str->hekate;
|
||||
@@ -859,10 +863,6 @@ static void _launch_hos(u8 autoboot, u8 autoboot_list)
|
||||
|
||||
hw_reinit_workaround(false, 0);
|
||||
|
||||
// Mitigate L4T Joy-Con driver issue.
|
||||
if ((autoboot & 0x80) && h_cfg.bootwait < 2)
|
||||
msleep((2 - h_cfg.bootwait) * 1000);
|
||||
|
||||
(*main_ptr)();
|
||||
}
|
||||
|
||||
@@ -901,12 +901,12 @@ static lv_res_t _removed_sd_action(lv_obj_t *btns, const char *txt)
|
||||
{
|
||||
case 0:
|
||||
if (h_cfg.rcm_patched)
|
||||
reboot_full();
|
||||
power_set_state(POWER_OFF_REBOOT);
|
||||
else
|
||||
reboot_rcm();
|
||||
power_set_state(REBOOT_RCM);
|
||||
break;
|
||||
case 1:
|
||||
power_off();
|
||||
power_set_state(POWER_OFF_RESET);
|
||||
break;
|
||||
case 2:
|
||||
sd_end();
|
||||
@@ -955,14 +955,14 @@ static lv_res_t _reboot_action(lv_obj_t *btns, const char *txt)
|
||||
{
|
||||
case 0:
|
||||
if (h_cfg.rcm_patched)
|
||||
reboot_full();
|
||||
power_set_state(POWER_OFF_REBOOT);
|
||||
else
|
||||
reboot_normal();
|
||||
power_set_state(REBOOT_BYPASS_FUSES);
|
||||
break;
|
||||
case 1:
|
||||
if (h_cfg.rcm_patched)
|
||||
break;
|
||||
reboot_rcm();
|
||||
power_set_state(REBOOT_RCM);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -972,7 +972,7 @@ static lv_res_t _reboot_action(lv_obj_t *btns, const char *txt)
|
||||
static lv_res_t _poweroff_action(lv_obj_t *btns, const char *txt)
|
||||
{
|
||||
if (!lv_btnm_get_pressed(btns))
|
||||
power_off();
|
||||
power_set_state(POWER_OFF_RESET);
|
||||
|
||||
return mbox_action(btns, txt);
|
||||
}
|
||||
@@ -1626,7 +1626,7 @@ ini_parsing:
|
||||
continue;
|
||||
|
||||
icon_path = NULL;
|
||||
u32 payload = 0;
|
||||
bool payload = false;
|
||||
bool img_colorize = false;
|
||||
lv_img_dsc_t *bmp = NULL;
|
||||
lv_obj_t *img = NULL;
|
||||
@@ -1637,13 +1637,7 @@ ini_parsing:
|
||||
if (!strcmp("icon", kv->key))
|
||||
icon_path = kv->val;
|
||||
else if (!strcmp("payload", kv->key))
|
||||
{
|
||||
payload = 1;
|
||||
|
||||
// Mitigate L4T Joy-Con driver issue.
|
||||
if (!memcmp(kv->val + strlen(kv->val) - 3, "rom", 3))
|
||||
payload = 2;
|
||||
}
|
||||
payload = true;
|
||||
}
|
||||
|
||||
// If icon not found, check res folder for section_name.bmp.
|
||||
@@ -1710,9 +1704,9 @@ ini_parsing:
|
||||
|
||||
// Set autoboot index.
|
||||
ext = lv_obj_get_ext_attr(btn);
|
||||
ext->idx = payload != 2 ? i : (i | 0x80);
|
||||
ext->idx = i;
|
||||
ext = lv_obj_get_ext_attr(launch_ctxt[curr_btn_idx]); // Redundancy.
|
||||
ext->idx = payload != 2 ? i : (i | 0x80);
|
||||
ext->idx = i;
|
||||
|
||||
// Set action.
|
||||
if (!more_cfg)
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
extern boot_cfg_t b_cfg;
|
||||
extern hekate_config h_cfg;
|
||||
|
||||
extern void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage);
|
||||
extern char *emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage);
|
||||
|
||||
lv_obj_t *ums_mbox;
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include <utils/sprintf.h>
|
||||
#include <utils/types.h>
|
||||
|
||||
extern void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage);
|
||||
extern char *emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage);
|
||||
|
||||
typedef struct _mbr_ctxt_t
|
||||
{
|
||||
@@ -214,7 +214,7 @@ static void _create_mbox_emummc_raw()
|
||||
lv_mbox_set_recolor_text(mbox, true);
|
||||
lv_obj_set_width(mbox, LV_HOR_RES / 9 * 6);
|
||||
|
||||
char *txt_buf = (char *)malloc(0x500);
|
||||
char *txt_buf = (char *)malloc(0x4000);
|
||||
mbr_t *mbr = (mbr_t *)malloc(sizeof(mbr_t));
|
||||
|
||||
memset(&mbr_ctx, 0, sizeof(mbr_ctxt_t));
|
||||
@@ -607,8 +607,28 @@ static lv_res_t _create_emummc_mig4_action(lv_obj_t * btns, const char * txt)
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
static lv_res_t _create_mbox_emummc_migrate(lv_obj_t *btn)
|
||||
bool em_raw;
|
||||
bool em_file;
|
||||
static lv_res_t _create_emummc_migrate_action(lv_obj_t * btns, const char * txt)
|
||||
{
|
||||
bool backup = false;
|
||||
bool emummc = false;
|
||||
|
||||
switch (lv_btnm_get_pressed(btns))
|
||||
{
|
||||
case 0:
|
||||
backup = true;
|
||||
break;
|
||||
case 1:
|
||||
emummc = true;
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
mbox_action(btns, txt);
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
|
||||
lv_obj_set_style(dark_bg, &mbox_darken);
|
||||
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
|
||||
@@ -620,7 +640,87 @@ static lv_res_t _create_mbox_emummc_migrate(lv_obj_t *btn)
|
||||
lv_mbox_set_recolor_text(mbox, true);
|
||||
lv_obj_set_width(mbox, LV_HOR_RES / 9 * 6);
|
||||
|
||||
char *txt_buf = (char *)malloc(0x500);
|
||||
char *txt_buf = (char *)malloc(0x4000);
|
||||
|
||||
if (backup)
|
||||
{
|
||||
s_printf(txt_buf,
|
||||
"#C7EA46 Found suitable backup for emuMMC!#\n"
|
||||
"#FF8000 Do you want to migrate it?#\n\n");
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_mig4_action);
|
||||
}
|
||||
else if (emummc)
|
||||
{
|
||||
s_printf(txt_buf,
|
||||
"#C7EA46 Found SD Partition based emuMMC!#\n"
|
||||
"#FF8000 Do you want to repair the config for it?#\n\n");
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_mig3_action);
|
||||
}
|
||||
else if (em_raw && em_file)
|
||||
{
|
||||
s_printf(txt_buf,
|
||||
"#C7EA46 Found both foreign SD File and Partition emunand!#\n"
|
||||
"#FF8000 Choose what to migrate:#\n\n");
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map1, _create_emummc_mig1_action);
|
||||
}
|
||||
else if (em_raw)
|
||||
{
|
||||
s_printf(txt_buf,
|
||||
"#C7EA46 Found foreign SD Partition emunand!#\n"
|
||||
"#FF8000 Do you want to migrate it?#\n\n");
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_mig2_action);
|
||||
}
|
||||
else if (em_file)
|
||||
{
|
||||
s_printf(txt_buf,
|
||||
"#C7EA46 Found foreign SD File emunand!#\n"
|
||||
"#FF8000 Do you want to migrate it?#\n\n");
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_mig0_action);
|
||||
}
|
||||
else
|
||||
{
|
||||
s_printf(txt_buf, "No emuMMC or foreign emunand found!\n\n");
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map3, mbox_action);
|
||||
}
|
||||
|
||||
lv_mbox_set_text(mbox, txt_buf);
|
||||
free(txt_buf);
|
||||
|
||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_top(mbox, true);
|
||||
|
||||
mbox_action(btns, txt);
|
||||
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
typedef struct _emummc_images_t
|
||||
{
|
||||
char *dirlist;
|
||||
u32 part_sector[3];
|
||||
u32 part_type[3];
|
||||
u32 part_end[3];
|
||||
char part_path[3 * 128];
|
||||
lv_obj_t *win;
|
||||
} emummc_images_t;
|
||||
|
||||
static lv_res_t _create_mbox_emummc_migrate(lv_obj_t *btn)
|
||||
{
|
||||
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
|
||||
lv_obj_set_style(dark_bg, &mbox_darken);
|
||||
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
|
||||
|
||||
static char *mbox_btn_map[] = { "\262Backup", "\262Fix RAW", "\262Emunand", "\222Cancel", "" };
|
||||
lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL);
|
||||
lv_mbox_set_recolor_text(mbox, true);
|
||||
lv_obj_set_width(mbox, LV_HOR_RES / 9 * 6);
|
||||
|
||||
lv_mbox_set_text(mbox,
|
||||
"Welcome to #C7EA46 emuMMC# migration tool!\n\n"
|
||||
"Please choose what type of migration you want to do.\n"
|
||||
"Anything that was not found will have the button disabled.");
|
||||
|
||||
char *path_buf = (char *)malloc(0x512);
|
||||
mbr_t *mbr = (mbr_t *)malloc(sizeof(mbr_t));
|
||||
u8 *efi_part = (u8 *)malloc(0x200);
|
||||
|
||||
@@ -631,10 +731,12 @@ static lv_res_t _create_mbox_emummc_migrate(lv_obj_t *btn)
|
||||
sdmmc_t sdmmc;
|
||||
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
|
||||
|
||||
em_raw = false;
|
||||
em_file = false;
|
||||
bool backup = false;
|
||||
bool emummc = false;
|
||||
bool file_based = false;
|
||||
bool em = false;
|
||||
bool rawnand_backup = false;
|
||||
|
||||
mbr_ctx.sector_start = 0;
|
||||
mbr_ctx.part_idx = 0;
|
||||
|
||||
@@ -664,104 +766,61 @@ static lv_res_t _create_mbox_emummc_migrate(lv_obj_t *btn)
|
||||
}
|
||||
}
|
||||
|
||||
//! TODO: What about unallocated
|
||||
|
||||
if (!mbr_ctx.part_idx)
|
||||
{
|
||||
sdmmc_storage_read(&sd_storage, 0x4003, 1, efi_part);
|
||||
if (!memcmp(efi_part, "EFI PART", 8))
|
||||
em = true;
|
||||
em_raw = true;
|
||||
}
|
||||
|
||||
s_printf(txt_buf, "%c%c%c%c%s", 's', 'x', 'o','s', "/emunand/boot0.bin");
|
||||
s_printf(path_buf, "%c%c%c%c%s", 's', 'x', 'o','s', "/emunand/boot0.bin");
|
||||
|
||||
if(!f_stat(txt_buf, NULL))
|
||||
file_based = true;
|
||||
if(!f_stat(path_buf, NULL))
|
||||
em_file = true;
|
||||
|
||||
bool rawnand_backup_found = false;
|
||||
|
||||
emmcsn_path_impl(txt_buf, "", "BOOT0", &storage);
|
||||
if(!f_stat(txt_buf, NULL))
|
||||
emmcsn_path_impl(path_buf, "", "BOOT0", &storage);
|
||||
if(!f_stat(path_buf, NULL))
|
||||
backup = true;
|
||||
|
||||
emmcsn_path_impl(txt_buf, "", "rawnand.bin", &storage);
|
||||
if(!f_stat(txt_buf, NULL))
|
||||
rawnand_backup_found = true;
|
||||
emmcsn_path_impl(path_buf, "", "rawnand.bin", &storage);
|
||||
if(!f_stat(path_buf, NULL))
|
||||
rawnand_backup = true;
|
||||
|
||||
emmcsn_path_impl(txt_buf, "", "rawnand.bin.00", &storage);
|
||||
if(!f_stat(txt_buf, NULL))
|
||||
rawnand_backup_found = true;
|
||||
emmcsn_path_impl(path_buf, "", "rawnand.bin.00", &storage);
|
||||
if(!f_stat(path_buf, NULL))
|
||||
rawnand_backup = true;
|
||||
|
||||
if (backup && rawnand_backup_found)
|
||||
backup = true;
|
||||
else
|
||||
backup = false;
|
||||
backup = backup && rawnand_backup;
|
||||
|
||||
sd_unmount();
|
||||
sdmmc_storage_end(&storage);
|
||||
|
||||
// Check available types and enable the corresponding buttons.
|
||||
if (backup)
|
||||
{
|
||||
s_printf(txt_buf,
|
||||
"#C7EA46 Found suitable backup for emuMMC!#\n"
|
||||
"#FF8000 Do you want to migrate it?#\n\n");
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_mig4_action);
|
||||
}
|
||||
else if (emummc)
|
||||
{
|
||||
s_printf(txt_buf,
|
||||
"#C7EA46 Found SD Partition based emuMMC!#\n"
|
||||
"#FF8000 Do you want to repair the config for it?#\n\n");
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_mig3_action);
|
||||
}
|
||||
else if (em && !file_based)
|
||||
{
|
||||
s_printf(txt_buf,
|
||||
"#C7EA46 Found foreign SD Partition emunand!#\n"
|
||||
"#FF8000 Do you want to migrate it?#\n\n");
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_mig2_action);
|
||||
}
|
||||
else if (!em && file_based)
|
||||
{
|
||||
s_printf(txt_buf,
|
||||
"#C7EA46 Found foreign SD File emunand!#\n"
|
||||
"#FF8000 Do you want to migrate it?#\n\n");
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_mig0_action);
|
||||
}
|
||||
else if (em && file_based)
|
||||
{
|
||||
s_printf(txt_buf,
|
||||
"#C7EA46 Found both foreign SD File and Partition emunand!#\n"
|
||||
"#FF8000 Choose what to migrate:#\n\n");
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map1, _create_emummc_mig1_action);
|
||||
}
|
||||
mbox_btn_map[0][0] = '\222';
|
||||
else
|
||||
{
|
||||
s_printf(txt_buf, "No emuMMC or foreign emunand found!\n\n");
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map3, mbox_action);
|
||||
}
|
||||
mbox_btn_map[0][0] = '\262';
|
||||
if (emummc)
|
||||
mbox_btn_map[1][0] = '\222';
|
||||
else
|
||||
mbox_btn_map[1][0] = '\262';
|
||||
if (em_raw || em_file)
|
||||
mbox_btn_map[2][0] = '\222';
|
||||
else
|
||||
mbox_btn_map[2][0] = '\262';
|
||||
|
||||
lv_mbox_set_text(mbox, txt_buf);
|
||||
free(txt_buf);
|
||||
free(path_buf);
|
||||
free(mbr);
|
||||
free(efi_part);
|
||||
|
||||
lv_mbox_add_btns(mbox, (const char **)mbox_btn_map, _create_emummc_migrate_action);
|
||||
|
||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_top(mbox, true);
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
typedef struct _emummc_images_t
|
||||
{
|
||||
char *dirlist;
|
||||
u32 part_sector[3];
|
||||
u32 part_type[3];
|
||||
u32 part_end[3];
|
||||
char part_path[3 * 128];
|
||||
lv_obj_t *win;
|
||||
} emummc_images_t;
|
||||
|
||||
static emummc_images_t *emummc_img;
|
||||
|
||||
static lv_res_t _save_emummc_cfg_mbox_action(lv_obj_t *btns, const char *txt)
|
||||
@@ -850,7 +909,7 @@ static lv_res_t _create_change_emummc_window(lv_obj_t *btn_caller)
|
||||
emummc_img->win = win;
|
||||
|
||||
mbr_t *mbr = (mbr_t *)malloc(sizeof(mbr_t));
|
||||
char *path = malloc(256);
|
||||
char *path = malloc(512);
|
||||
|
||||
sdmmc_storage_read(&sd_storage, 0, 1, mbr);
|
||||
|
||||
@@ -962,7 +1021,7 @@ out0:;
|
||||
lv_btn_ext_t *ext;
|
||||
lv_obj_t *btn_label = NULL;
|
||||
lv_obj_t *lv_desc = NULL;
|
||||
char *txt_buf = malloc(0x500);
|
||||
char *txt_buf = malloc(0x4000);
|
||||
|
||||
// Create RAW buttons.
|
||||
for (u32 raw_btn_idx = 0; raw_btn_idx < 3; raw_btn_idx++)
|
||||
@@ -1109,7 +1168,7 @@ lv_res_t create_win_emummc_tools(lv_obj_t *btn)
|
||||
|
||||
lv_obj_t *label_txt2 = lv_label_create(h1, NULL);
|
||||
lv_label_set_recolor(label_txt2, true);
|
||||
char *txt_buf = (char *)malloc(0x200);
|
||||
char *txt_buf = (char *)malloc(0x4000);
|
||||
|
||||
if (emu_info.enabled)
|
||||
{
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
|
||||
#include "gui.h"
|
||||
#include <gfx/di.h>
|
||||
#include <display/di.h>
|
||||
#include "../config.h"
|
||||
#include "../hos/hos.h"
|
||||
#include "../hos/pkg1.h"
|
||||
@@ -31,6 +31,9 @@
|
||||
#include <power/bm92t36.h>
|
||||
#include <power/bq24193.h>
|
||||
#include <power/max17050.h>
|
||||
#include <power/max77620.h>
|
||||
#include <power/max7762x.h>
|
||||
#include <power/max77812.h>
|
||||
#include <sec/se.h>
|
||||
#include <sec/tsec.h>
|
||||
#include <soc/fuse.h>
|
||||
@@ -51,7 +54,7 @@ extern hekate_config h_cfg;
|
||||
extern volatile boot_cfg_t *b_cfg;
|
||||
extern volatile nyx_storage_t *nyx_str;
|
||||
|
||||
extern void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage);
|
||||
extern char *emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage);
|
||||
|
||||
static u8 *cal0_buf = NULL;
|
||||
|
||||
@@ -71,7 +74,10 @@ static lv_res_t _create_window_dump_done(int error, char *dump_filenames)
|
||||
if (error)
|
||||
s_printf(txt_buf, "#FFDD00 Failed to dump to# %s#FFDD00 !#\nError: %d", dump_filenames, error);
|
||||
else
|
||||
s_printf(txt_buf, "Dumping to SD card finished!\nFiles: #C7EA46 backup/{emmc_sn}/dumps/#%s", dump_filenames);
|
||||
{
|
||||
char *sn = emmcsn_path_impl(NULL, NULL, NULL, NULL);
|
||||
s_printf(txt_buf, "Dumping to SD card finished!\nFiles: #C7EA46 backup/%s/dumps/#\n%s", sn, dump_filenames);
|
||||
}
|
||||
lv_mbox_set_text(mbox, txt_buf);
|
||||
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action); // Important. After set_text.
|
||||
@@ -204,8 +210,11 @@ static lv_res_t _fuse_dump_window_action(lv_obj_t * btn)
|
||||
}
|
||||
else
|
||||
{
|
||||
emmcsn_path_impl(path, "/dumps", "fuse_cached_t210b01.bin", NULL);
|
||||
error = sd_save_to_file((u8 *)0x7000F898, 0x368, path);
|
||||
emmcsn_path_impl(path, "/dumps", "fuse_cached_t210b01_x898.bin", NULL);
|
||||
error = sd_save_to_file((u8 *)0x7000F898, 0x68, path);
|
||||
emmcsn_path_impl(path, "/dumps", "fuse_cached_t210b01_x900.bin", NULL);
|
||||
if (!error)
|
||||
error = sd_save_to_file((u8 *)0x7000F900, 0x300, path);
|
||||
}
|
||||
|
||||
u32 words[fuse_array_size_t210b01 / sizeof(u32)];
|
||||
@@ -220,7 +229,11 @@ static lv_res_t _fuse_dump_window_action(lv_obj_t * btn)
|
||||
|
||||
sd_unmount();
|
||||
}
|
||||
_create_window_dump_done(error, "fuse_cached.bin, fuse_array_raw.bin");
|
||||
|
||||
if (!h_cfg.t210b01)
|
||||
_create_window_dump_done(error, "fuse_cached_t210.bin, fuse_array_raw_t210.bin");
|
||||
else
|
||||
_create_window_dump_done(error, "fuse_cached_t210b01_partX.bin, fuse_array_raw_t210b01.bin");
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
@@ -438,6 +451,9 @@ t210b01:;
|
||||
case 0x95:
|
||||
strcat(txt_buf, "2");
|
||||
break;
|
||||
case 0x96:
|
||||
strcat(txt_buf, "3");
|
||||
break;
|
||||
default:
|
||||
strcat(txt_buf, "X");
|
||||
break;
|
||||
@@ -516,10 +532,10 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
||||
lv_label_set_style(lb_desc, &monospace_text);
|
||||
|
||||
lv_label_set_static_text(lb_desc,
|
||||
"#00DDFF Detailed Info:#\n"
|
||||
"SKU:\n"
|
||||
"DRAM ID:\n"
|
||||
"#FF8000 Burnt Fuses (ODM 7/6):#\n"
|
||||
"ODM Fields (4, 6, 7):\n"
|
||||
"Secure Boot key (SBK):\n"
|
||||
"Device key (DK):\n"
|
||||
"USB Stack:\n"
|
||||
@@ -556,26 +572,22 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
||||
// Decode fuses.
|
||||
char *sku;
|
||||
char dram_man[32];
|
||||
u32 odm4 = fuse_read_odm(4);
|
||||
u8 dram_id = (odm4 >> 3) & 0x1F;
|
||||
u32 hw_type3 = (odm4 & 0xF0000) >> 16;
|
||||
char fuses_hos_version[64];
|
||||
u8 dram_id = fuse_read_dramid(true);
|
||||
|
||||
switch (hw_type3)
|
||||
switch (fuse_read_hw_type())
|
||||
{
|
||||
case 0:
|
||||
case FUSE_NX_HW_TYPE_ICOSA:
|
||||
sku = "Icosa (Erista)";
|
||||
break;
|
||||
case 1:
|
||||
case FUSE_NX_HW_TYPE_IOWA:
|
||||
sku = "Iowa (Mariko)";
|
||||
break;
|
||||
case 2:
|
||||
case FUSE_NX_HW_TYPE_HOAG:
|
||||
sku = "Hoag (Mariko)";
|
||||
break;
|
||||
case 4:
|
||||
sku = "Calcio (Mariko)";
|
||||
break;
|
||||
default:
|
||||
sku = "Unknown";
|
||||
sku = "#FF8000 Unknown#";
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -625,11 +637,11 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
||||
break;
|
||||
case LPDDR4X_IOWA_4GB_SAMSUNG_1Y_X:
|
||||
case LPDDR4X_HOAG_4GB_SAMSUNG_1Y_X:
|
||||
case LPDDR4X_SDS_4GB_SAMSUNG_1Y_X:
|
||||
case LPDDR4X_AULA_4GB_SAMSUNG_1Y_X:
|
||||
strcpy(dram_man, "Samsung 1y X 4GB");
|
||||
break;
|
||||
case LPDDR4X_IOWA_8GB_SAMSUNG_1Y_X:
|
||||
case LPDDR4X_SDS_8GB_SAMSUNG_1Y_X:
|
||||
case LPDDR4X_AULA_8GB_SAMSUNG_1Y_X:
|
||||
strcpy(dram_man, "Samsung 1y X 8GB");
|
||||
break;
|
||||
case LPDDR4X_IOWA_4GB_SAMSUNG_1Y_Y:
|
||||
@@ -638,16 +650,16 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
||||
case LPDDR4X_IOWA_8GB_SAMSUNG_1Y_Y:
|
||||
strcpy(dram_man, "Samsung 1y Y 8GB");
|
||||
break;
|
||||
case LPDDR4X_SDS_4GB_SAMSUNG_1Y_A:
|
||||
case LPDDR4X_AULA_4GB_SAMSUNG_1Y_A:
|
||||
strcpy(dram_man, "Samsung 1y A 4GB");
|
||||
break;
|
||||
case LPDDR4X_IOWA_4GB_MICRON_1Y_A:
|
||||
case LPDDR4X_HOAG_4GB_MICRON_1Y_A:
|
||||
case LPDDR4X_SDS_4GB_MICRON_1Y_A:
|
||||
case LPDDR4X_AULA_4GB_MICRON_1Y_A:
|
||||
strcpy(dram_man, "Micron 1y A 4GB");
|
||||
break;
|
||||
default:
|
||||
strcpy(dram_man, "Unknown");
|
||||
strcpy(dram_man, "#FF8000 Unknown#");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -655,6 +667,55 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
||||
u8 burnt_fuses_7 = fuse_count_burnt(fuse_read_odm(7));
|
||||
u8 burnt_fuses_6 = fuse_count_burnt(fuse_read_odm(6));
|
||||
|
||||
switch (burnt_fuses_7)
|
||||
{
|
||||
case 1:
|
||||
strcpy(fuses_hos_version, "1.0.0");
|
||||
break;
|
||||
case 2:
|
||||
strcpy(fuses_hos_version, "2.0.0 - 2.3.0");
|
||||
break;
|
||||
case 3:
|
||||
strcpy(fuses_hos_version, "3.0.0");
|
||||
break;
|
||||
case 4:
|
||||
strcpy(fuses_hos_version, "3.0.1 - 3.0.2");
|
||||
break;
|
||||
case 5:
|
||||
strcpy(fuses_hos_version, "4.0.0 - 4.1.0");
|
||||
break;
|
||||
case 6:
|
||||
strcpy(fuses_hos_version, "5.0.0 - 5.1.0");
|
||||
break;
|
||||
case 7:
|
||||
strcpy(fuses_hos_version, "6.0.0 - 6.1.0");
|
||||
break;
|
||||
case 8:
|
||||
strcpy(fuses_hos_version, "6.2.0");
|
||||
break;
|
||||
case 9:
|
||||
strcpy(fuses_hos_version, "7.0.0 - 8.0.1");
|
||||
break;
|
||||
case 10:
|
||||
strcpy(fuses_hos_version, "8.1.0 - 8.1.1");
|
||||
break;
|
||||
case 11:
|
||||
strcpy(fuses_hos_version, "9.0.0 - 9.0.1");
|
||||
break;
|
||||
case 12:
|
||||
strcpy(fuses_hos_version, "9.1.0 - 9.2.0");
|
||||
break;
|
||||
case 13:
|
||||
strcpy(fuses_hos_version, "10.0.0 - 10.2.0");
|
||||
break;
|
||||
case 14:
|
||||
strcpy(fuses_hos_version, "11.0.0+");
|
||||
break;
|
||||
default:
|
||||
strcpy(fuses_hos_version, "#FF8000 Unknown#");
|
||||
break;
|
||||
}
|
||||
|
||||
// Calculate LOT.
|
||||
u32 lot_code0 = (FUSE(FUSE_OPT_LOT_CODE_0) & 0xFFFFFFF) << 2;
|
||||
u32 lot_bin = 0;
|
||||
@@ -669,16 +730,17 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
||||
u32 chip_id = APB_MISC(APB_MISC_GP_HIDREV);
|
||||
// Parse fuses and display them.
|
||||
s_printf(txt_buf,
|
||||
"\n%X - %s - %s\n%02d: %s\n%d - %d\n%08X%08X%08X%08X\n%08X\n"
|
||||
"%X - %s - %s\n%02d: %s\n%d - %d (HOS: %s)\n%08X %08X %08X\n%08X%08X%08X%08X\n%08X\n"
|
||||
"%s\n%d.%02d (0x%X)\n%d.%02d (0x%X)\n%d\n%d\n%d\n%d\n%d\n0x%X\n%d\n%d\n%d\n%d\n"
|
||||
"%d\n%d\n%d (0x%X)\n%d\n%d\n%d\n%d\n"
|
||||
"ID: %02X, Major: A0%d, Minor: %d",
|
||||
FUSE(FUSE_SKU_INFO), sku, (fuse_read_odm(4) & 3) ? "Dev" : "Retail",
|
||||
dram_id, dram_man, burnt_fuses_7, burnt_fuses_6,
|
||||
FUSE(FUSE_SKU_INFO), sku, fuse_read_hw_state() ? "Dev" : "Retail",
|
||||
dram_id, dram_man, burnt_fuses_7, burnt_fuses_6, fuses_hos_version,
|
||||
fuse_read_odm(4), fuse_read_odm(6), fuse_read_odm(7),
|
||||
byte_swap_32(FUSE(FUSE_PRIVATE_KEY0)), byte_swap_32(FUSE(FUSE_PRIVATE_KEY1)),
|
||||
byte_swap_32(FUSE(FUSE_PRIVATE_KEY2)), byte_swap_32(FUSE(FUSE_PRIVATE_KEY3)),
|
||||
byte_swap_32(FUSE(FUSE_PRIVATE_KEY4)),
|
||||
(FUSE(FUSE_RESERVED_SW) & 0x80) ? "XUSB" : "USB 2.0",
|
||||
((FUSE(FUSE_RESERVED_SW) & 0x80) || h_cfg.t210b01) ? "XUSB" : "USB2",
|
||||
(FUSE(FUSE_OPT_FT_REV) >> 5) & 0x3F, FUSE(FUSE_OPT_FT_REV) & 0x1F, FUSE(FUSE_OPT_FT_REV),
|
||||
(FUSE(FUSE_OPT_CP_REV) >> 5) & 0x3F, FUSE(FUSE_OPT_CP_REV) & 0x1F, FUSE(FUSE_OPT_CP_REV),
|
||||
FUSE(FUSE_FIRST_BOOTROM_PATCH_SIZE) & 0x7F,
|
||||
@@ -709,7 +771,7 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
||||
u32 ranks = EMC(EMC_ADR_CFG) + 1;
|
||||
u32 channels = (EMC(EMC_FBIO_CFG7) >> 1) & 3;
|
||||
u32 die_channels = ranks * ((channels & 1) + ((channels & 2) >> 1));
|
||||
s_printf(txt_buf, "#00DDFF %s SDRAM ##FF8000 (Ch 0 | Ch 1):#\n#FF8000 Vendor:# ", hw_type3 ? "LPDDR4X" : "LPDDR4");
|
||||
s_printf(txt_buf, "#00DDFF %s SDRAM ##FF8000 (Ch 0 | Ch 1):#\n#FF8000 Vendor:# ", dram_id > 6 ? "LPDDR4X" : "LPDDR4");
|
||||
switch (ram_vendor.rank0_ch0)
|
||||
{
|
||||
case 1:
|
||||
@@ -722,10 +784,10 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
||||
strcat(txt_buf, "Micron");
|
||||
break;
|
||||
default:
|
||||
strcat(txt_buf, "Unknown");
|
||||
s_printf(txt_buf + strlen(txt_buf), "#FF8000 Unknown# (%d)", ram_vendor.rank0_ch0);
|
||||
break;
|
||||
}
|
||||
s_printf(txt_buf + strlen(txt_buf), " (%d) #FF8000 |# ", ram_vendor.rank0_ch0);
|
||||
strcat(txt_buf, " #FF8000 |# ");
|
||||
switch (ram_vendor.rank0_ch1)
|
||||
{
|
||||
case 1:
|
||||
@@ -738,12 +800,11 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
||||
strcat(txt_buf, "Micron");
|
||||
break;
|
||||
default:
|
||||
strcat(txt_buf, "Unknown");
|
||||
s_printf(txt_buf + strlen(txt_buf), "#FF8000 Unknown# (%d)", ram_vendor.rank0_ch1);
|
||||
break;
|
||||
}
|
||||
s_printf(txt_buf + strlen(txt_buf), " (%d)\n#FF8000 Rev ID:# %X.%02X #FF8000 |# %X.%02X\n#FF8000 Density:# %d",
|
||||
ram_vendor.rank0_ch1, ram_rev0.rank0_ch0, ram_rev1.rank0_ch0, ram_rev0.rank0_ch1, ram_rev1.rank0_ch1,
|
||||
die_channels);
|
||||
s_printf(txt_buf + strlen(txt_buf), "\n#FF8000 Rev ID:# %X.%02X #FF8000 |# %X.%02X\n#FF8000 Density:# %d",
|
||||
ram_rev0.rank0_ch0, ram_rev1.rank0_ch0, ram_rev0.rank0_ch1, ram_rev1.rank0_ch1, die_channels);
|
||||
switch ((ram_density.rank0_ch0 & 0x3C) >> 2)
|
||||
{
|
||||
case 2:
|
||||
@@ -756,10 +817,10 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
||||
strcat(txt_buf, " x 1GB");
|
||||
break;
|
||||
default:
|
||||
strcat(txt_buf, " x Unk");
|
||||
s_printf(txt_buf + strlen(txt_buf), " x Unk (%d)", (ram_density.rank0_ch0 & 0x3C) >> 2);
|
||||
break;
|
||||
}
|
||||
s_printf(txt_buf + strlen(txt_buf), " (%d) #FF8000 |# %d", (ram_density.rank0_ch0 & 0x3C) >> 2, die_channels);
|
||||
s_printf(txt_buf + strlen(txt_buf), " #FF8000 |# %d", die_channels);
|
||||
switch ((ram_density.rank0_ch1 & 0x3C) >> 2)
|
||||
{
|
||||
case 2:
|
||||
@@ -772,10 +833,10 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
||||
strcat(txt_buf, " x 1GB");
|
||||
break;
|
||||
default:
|
||||
strcat(txt_buf, " x Unk");
|
||||
s_printf(txt_buf + strlen(txt_buf), " x Unk (%d)", (ram_density.rank0_ch1 & 0x3C) >> 2);
|
||||
break;
|
||||
}
|
||||
s_printf(txt_buf + strlen(txt_buf), " (%d)\n\n", (ram_density.rank0_ch1 & 0x3C) >> 2);
|
||||
strcat(txt_buf, "\n\n");
|
||||
|
||||
// Display info.
|
||||
u8 display_rev = (nyx_str->info.disp_id >> 8) & 0xFF;
|
||||
@@ -792,32 +853,35 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
||||
strcat(txt_buf, "JDI LPM062M326A");
|
||||
break;
|
||||
case PANEL_INL_P062CCA_AZ1:
|
||||
strcat(txt_buf, "InnoLux P062CCA-AZ");
|
||||
strcat(txt_buf, "InnoLux P062CCA");
|
||||
switch (display_rev)
|
||||
{
|
||||
case 0x93:
|
||||
strcat(txt_buf, "1");
|
||||
strcat(txt_buf, "-AZ1");
|
||||
break;
|
||||
case 0x95:
|
||||
strcat(txt_buf, "2");
|
||||
strcat(txt_buf, "-AZ2");
|
||||
break;
|
||||
case 0x96:
|
||||
strcat(txt_buf, "-AZ3");
|
||||
break;
|
||||
default:
|
||||
strcat(txt_buf, "X #FFDD00 Contact me!#");
|
||||
strcat(txt_buf, " #FFDD00 Contact me!#");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PANEL_AUO_A062TAN01:
|
||||
strcat(txt_buf, "AUO A062TAN0");
|
||||
strcat(txt_buf, "AUO A062");
|
||||
switch (display_rev)
|
||||
{
|
||||
case 0x94:
|
||||
strcat(txt_buf, "1");
|
||||
strcat(txt_buf, "TAN01");
|
||||
break;
|
||||
case 0x95:
|
||||
strcat(txt_buf, "2");
|
||||
strcat(txt_buf, "TAN02");
|
||||
break;
|
||||
default:
|
||||
strcat(txt_buf, "X #FFDD00 Contact me!#");
|
||||
strcat(txt_buf, " #FFDD00 Contact me!#");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -848,37 +912,65 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
||||
nyx_str->info.disp_id & 0xFF, (nyx_str->info.disp_id >> 8) & 0xFF, (nyx_str->info.disp_id >> 16) & 0xFF);
|
||||
|
||||
touch_fw_info_t touch_fw;
|
||||
touch_panel_info_t *touch_panel;
|
||||
bool panel_ic_paired = false;
|
||||
|
||||
if (!touch_get_fw_info(&touch_fw))
|
||||
{
|
||||
strcat(txt_buf, "\n\n#00DDFF Touch Panel:#\n#FF8000 Model:# ");
|
||||
|
||||
touch_panel = touch_get_panel_vendor();
|
||||
if (touch_panel)
|
||||
strcat(txt_buf, touch_panel->vendor);
|
||||
else
|
||||
strcat(txt_buf, "Unknown #FFDD00 Contact me!#");
|
||||
|
||||
s_printf(txt_buf + strlen(txt_buf), "\n#FF8000 ID:# %08X (", touch_fw.fw_id);
|
||||
|
||||
switch (touch_fw.fw_id)
|
||||
{
|
||||
case 0x100100:
|
||||
strcat(txt_buf, "NTD 4CD 1601");
|
||||
case 0x00100100:
|
||||
strcat(txt_buf, "4CD 1601");
|
||||
if (touch_panel)
|
||||
panel_ic_paired = touch_panel->idx == -1;
|
||||
break;
|
||||
case 0x00120100:
|
||||
case 0x32000001:
|
||||
strcat(txt_buf, "NTD 4CD 1801");
|
||||
strcat(txt_buf, "4CD 1801");
|
||||
if (touch_panel)
|
||||
panel_ic_paired = touch_panel->idx == 0;
|
||||
break;
|
||||
case 0x001A0300:
|
||||
case 0x32000102:
|
||||
strcat(txt_buf, "NTD 4CD 2602");
|
||||
strcat(txt_buf, "4CD 2602");
|
||||
if (touch_panel)
|
||||
panel_ic_paired = touch_panel->idx == 1;
|
||||
break;
|
||||
case 0x00290100:
|
||||
case 0x32000302:
|
||||
strcat(txt_buf, "NTD 4CD 3801");
|
||||
strcat(txt_buf, "4CD 3801");
|
||||
if (touch_panel)
|
||||
panel_ic_paired = touch_panel->idx == 2;
|
||||
break;
|
||||
case 0x31051820:
|
||||
case 0x32000402:
|
||||
strcat(txt_buf, "NTD 4CD XXXX");
|
||||
strcat(txt_buf, "4CD XXXX");
|
||||
if (touch_panel)
|
||||
panel_ic_paired = touch_panel->idx == 3;
|
||||
break;
|
||||
case 0x32000501:
|
||||
case 0x33000502:
|
||||
strcat(txt_buf, "4CD UNKN");
|
||||
if (touch_panel)
|
||||
panel_ic_paired = touch_panel->idx == 4;
|
||||
break;
|
||||
default:
|
||||
strcat(txt_buf, "Unknown");
|
||||
strcat(txt_buf, "#FF8000 Unknown#");
|
||||
break;
|
||||
}
|
||||
|
||||
s_printf(txt_buf + strlen(txt_buf), "\n#FF8000 ID:# %X\n#FF8000 FTB ver:# %04X\n#FF8000 FW rev:# %04X",
|
||||
touch_fw.fw_id, touch_fw.ftb_ver, touch_fw.fw_rev);
|
||||
s_printf(txt_buf + strlen(txt_buf), " - %s)\n#FF8000 FTB ver:# %04X\n#FF8000 FW rev:# %04X",
|
||||
panel_ic_paired ? "Paired" : "#FFDD00 Error#", touch_fw.ftb_ver, touch_fw.fw_rev);
|
||||
}
|
||||
|
||||
// Check if patched unit.
|
||||
@@ -1340,7 +1432,7 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
|
||||
rsvd_blocks = "Urgent (> 90%)";
|
||||
break;
|
||||
default:
|
||||
rsvd_blocks = "Unknown";
|
||||
rsvd_blocks = "#FF8000 Unknown#";
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1468,7 +1560,8 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
|
||||
"HW rev:\n"
|
||||
"FW rev:\n"
|
||||
"S/N:\n"
|
||||
"Month/Year:"
|
||||
"Month/Year:\n\n"
|
||||
"Bootloader bus:"
|
||||
);
|
||||
|
||||
lv_obj_t *val = lv_cont_create(win, NULL);
|
||||
@@ -1521,13 +1614,31 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
|
||||
break;
|
||||
}
|
||||
|
||||
s_printf(txt_buf + strlen(txt_buf), "(%02X)\n%c%c\n%c%c%c%c%c\n%X\n%X\n%08x\n%02d/%04d",
|
||||
s_printf(txt_buf + strlen(txt_buf), "(%02X)\n%c%c\n%c%c%c%c%c\n%X\n%X\n%08x\n%02d/%04d\n\n",
|
||||
sd_storage.cid.manfid, (sd_storage.cid.oemid >> 8) & 0xFF, sd_storage.cid.oemid & 0xFF,
|
||||
sd_storage.cid.prod_name[0], sd_storage.cid.prod_name[1], sd_storage.cid.prod_name[2],
|
||||
sd_storage.cid.prod_name[3], sd_storage.cid.prod_name[4],
|
||||
sd_storage.cid.hwrev, sd_storage.cid.fwrev, sd_storage.cid.serial,
|
||||
sd_storage.cid.month, sd_storage.cid.year);
|
||||
|
||||
switch (nyx_str->info.sd_init)
|
||||
{
|
||||
case SD_1BIT_HS25:
|
||||
strcat(txt_buf, "HS25 1bit");
|
||||
break;
|
||||
case SD_4BIT_HS25:
|
||||
strcat(txt_buf, "HS25");
|
||||
break;
|
||||
case SD_UHS_SDR82: // Report as SDR104.
|
||||
case SD_UHS_SDR104:
|
||||
strcat(txt_buf, "SDR104");
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
strcat(txt_buf, "Undefined");
|
||||
break;
|
||||
}
|
||||
|
||||
lv_label_set_text(lb_val, txt_buf);
|
||||
|
||||
lv_obj_set_width(lb_val, lv_obj_get_width(val));
|
||||
@@ -1574,14 +1685,22 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
|
||||
break;
|
||||
}
|
||||
|
||||
bool uhs_au_mb = false;
|
||||
u32 uhs_au_size = sd_storage_ssr_get_au(&sd_storage);
|
||||
if (uhs_au_size >= 1024)
|
||||
{
|
||||
uhs_au_mb = true;
|
||||
uhs_au_size /= 1024;
|
||||
}
|
||||
|
||||
s_printf(txt_buf,
|
||||
"#00DDFF v%d.0#\n%02X\n%d MiB\n%X (CP %X)\n%d\n%d MB/s (%d MHz)\n%d\nU%d\nV%d\nA%d\n%s",
|
||||
"#00DDFF v%d.0#\n%02X\n%d MiB\n%X (CP %X)\n%d\n%d MB/s (%d MHz)\n%d (AU: %d %s\nU%d\nV%d\nA%d\n%s",
|
||||
sd_storage.csd.structure + 1, sd_storage.csd.cmdclass,
|
||||
sd_storage.sec_cnt >> 11, sd_storage.sec_cnt, sd_storage.ssr.protected_size >> 9,
|
||||
sd_storage.ssr.bus_width, sd_storage.csd.busspeed,
|
||||
(sd_storage.csd.busspeed > 10) ? (sd_storage.csd.busspeed * 2) : 50,
|
||||
sd_storage.ssr.speed_class, sd_storage.ssr.uhs_grade, sd_storage.ssr.video_class,
|
||||
sd_storage.ssr.app_class, wp_info);
|
||||
sd_storage.ssr.speed_class, uhs_au_size, uhs_au_mb ? "MiB)" : "KiB)", sd_storage.ssr.uhs_grade,
|
||||
sd_storage.ssr.video_class, sd_storage.ssr.app_class, wp_info);
|
||||
|
||||
lv_label_set_text(lb_val2, txt_buf);
|
||||
|
||||
@@ -1656,7 +1775,8 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
|
||||
lv_obj_t * lb_val4 = lv_label_create(val4, lb_desc);
|
||||
|
||||
u16 *sd_errors = sd_get_error_count();
|
||||
s_printf(txt_buf, "\n%d\n%d\n%d", sd_errors[0], sd_errors[1], sd_errors[2]);
|
||||
s_printf(txt_buf, "\n%d (%d)\n%d (%d)\n%d (%d)",
|
||||
sd_errors[0], nyx_str->info.sd_errors[0], sd_errors[1], nyx_str->info.sd_errors[1], sd_errors[2], nyx_str->info.sd_errors[2]);
|
||||
|
||||
lv_label_set_text(lb_val4, txt_buf);
|
||||
|
||||
@@ -1687,7 +1807,6 @@ static lv_res_t _create_window_battery_status(lv_obj_t *btn)
|
||||
lv_label_set_static_text(lb_desc,
|
||||
"#00DDFF Fuel Gauge IC Info:#\n"
|
||||
"Capacity now:\n"
|
||||
"Capacity now:\n"
|
||||
"Capacity full:\n"
|
||||
"Capacity (design):\n"
|
||||
"Current now:\n"
|
||||
@@ -1698,6 +1817,9 @@ static lv_res_t _create_window_battery_status(lv_obj_t *btn)
|
||||
"Max voltage reached:\n"
|
||||
"Empty voltage:\n"
|
||||
"Battery temp:\n\n"
|
||||
"#00DDFF PMIC IC Info:#\n"
|
||||
"Main PMIC:\n\n"
|
||||
"CPU/GPU PMIC:\n"
|
||||
);
|
||||
lv_obj_set_width(lb_desc, lv_obj_get_width(desc));
|
||||
|
||||
@@ -1708,12 +1830,11 @@ static lv_res_t _create_window_battery_status(lv_obj_t *btn)
|
||||
|
||||
char *txt_buf = (char *)malloc(0x4000);
|
||||
int value = 0;
|
||||
int cap_pct = 0;
|
||||
|
||||
max17050_get_property(MAX17050_RepSOC, &value);
|
||||
s_printf(txt_buf, "\n%d %\n", value >> 8);
|
||||
|
||||
max17050_get_property(MAX17050_RepSOC, &cap_pct);
|
||||
max17050_get_property(MAX17050_RepCap, &value);
|
||||
s_printf(txt_buf + strlen(txt_buf), "%d mAh\n", value);
|
||||
s_printf(txt_buf, "\n%d mAh [%d %]\n", value, cap_pct >> 8);
|
||||
|
||||
max17050_get_property(MAX17050_FullCAP, &value);
|
||||
s_printf(txt_buf + strlen(txt_buf), "%d mAh\n", value);
|
||||
@@ -1752,9 +1873,36 @@ static lv_res_t _create_window_battery_status(lv_obj_t *btn)
|
||||
|
||||
max17050_get_property(MAX17050_TEMP, &value);
|
||||
if (value >= 0)
|
||||
s_printf(txt_buf + strlen(txt_buf), "%d.%d oC\n", value / 10, value % 10);
|
||||
s_printf(txt_buf + strlen(txt_buf), "%d.%d oC\n\n\n", value / 10, value % 10);
|
||||
else
|
||||
s_printf(txt_buf + strlen(txt_buf), "-%d.%d oC\n", (~value + 1) / 10, (~value + 1) % 10);
|
||||
s_printf(txt_buf + strlen(txt_buf), "-%d.%d oC\n\n\n", (~value + 1) / 10, (~value + 1) % 10);
|
||||
|
||||
value = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CID4);
|
||||
u32 main_pmic_version = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CID3) & 0xF;
|
||||
|
||||
if (value == 0x35)
|
||||
s_printf(txt_buf + strlen(txt_buf), "max77620 v%d\nErista OTP\n", main_pmic_version);
|
||||
else if (value == 0x53)
|
||||
s_printf(txt_buf + strlen(txt_buf), "max77620 v%d\nMariko OTP\n", main_pmic_version);
|
||||
else
|
||||
s_printf(txt_buf + strlen(txt_buf), "max77620 v%d\n#FF8000 Unknown OTP# (%02X)\n", main_pmic_version, value);
|
||||
|
||||
u32 cpu_gpu_pmic_type = h_cfg.t210b01 ? (FUSE(FUSE_RESERVED_ODM28_T210B01) & 1) + 1 : 0;
|
||||
switch (cpu_gpu_pmic_type)
|
||||
{
|
||||
case 0:
|
||||
s_printf(txt_buf + strlen(txt_buf), "max77621 v%d",
|
||||
i2c_recv_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CHIPID1_REG));
|
||||
break;
|
||||
case 1:
|
||||
s_printf(txt_buf + strlen(txt_buf), "max77812-2 v%d",
|
||||
i2c_recv_byte(I2C_5, MAX77812_PHASE31_CPU_I2C_ADDR, MAX77812_REG_VERSION) & 7);
|
||||
break;
|
||||
case 2:
|
||||
s_printf(txt_buf + strlen(txt_buf), "max77812-3 v%d.0",
|
||||
i2c_recv_byte(I2C_5, MAX77812_PHASE211_CPU_I2C_ADDR, MAX77812_REG_VERSION) & 7);
|
||||
break;
|
||||
}
|
||||
|
||||
lv_label_set_text(lb_val, txt_buf);
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include "gui.h"
|
||||
#include "../config.h"
|
||||
#include <utils/ini.h>
|
||||
#include <gfx/di.h>
|
||||
#include <display/di.h>
|
||||
#include <input/joycon.h>
|
||||
#include <libs/lvgl/lvgl.h>
|
||||
#include <mem/heap.h>
|
||||
@@ -36,6 +36,7 @@ static lv_obj_t *autoboot_btn;
|
||||
static bool autoboot_first_time = true;
|
||||
|
||||
static bool ini_changes_made = false;
|
||||
static bool nyx_changes_made = false;
|
||||
|
||||
void nyx_options_clear_ini_changes_made()
|
||||
{
|
||||
@@ -298,8 +299,12 @@ static lv_res_t _autoboot_hide_delay_action(lv_obj_t *btn)
|
||||
|
||||
static lv_res_t _autoboot_delay_action(lv_obj_t *ddlist)
|
||||
{
|
||||
h_cfg.bootwait = lv_ddlist_get_selected(ddlist);
|
||||
ini_changes_made = true;
|
||||
u32 new_selection = lv_ddlist_get_selected(ddlist);
|
||||
if (h_cfg.bootwait != new_selection)
|
||||
{
|
||||
h_cfg.bootwait = new_selection;
|
||||
ini_changes_made = true;
|
||||
}
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
@@ -315,7 +320,12 @@ static lv_res_t _slider_brightness_action(lv_obj_t * slider)
|
||||
|
||||
static lv_res_t _data_verification_action(lv_obj_t *ddlist)
|
||||
{
|
||||
n_cfg.verification = lv_ddlist_get_selected(ddlist);
|
||||
u32 new_selection = lv_ddlist_get_selected(ddlist);
|
||||
if (n_cfg.verification != new_selection)
|
||||
{
|
||||
n_cfg.verification = new_selection;
|
||||
nyx_changes_made = true;
|
||||
}
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
@@ -328,6 +338,8 @@ static lv_res_t _save_nyx_options_action(lv_obj_t *btn)
|
||||
|
||||
int res = !create_nyx_config_entry();
|
||||
|
||||
nyx_changes_made = false;
|
||||
|
||||
if (res)
|
||||
lv_mbox_set_text(mbox, "#FF8000 Nyx Configuration#\n\n#96FF00 The configuration was saved to sd card!#");
|
||||
else
|
||||
@@ -610,6 +622,8 @@ static lv_res_t _action_clock_edit(lv_obj_t *btns, const char * txt)
|
||||
u32 new_epoch = max77620_rtc_date_to_epoch(&time);
|
||||
|
||||
n_cfg.timeoff = new_epoch - epoch;
|
||||
|
||||
nyx_changes_made = true;
|
||||
}
|
||||
|
||||
mbox_action(btns, txt);
|
||||
@@ -620,7 +634,10 @@ static lv_res_t _action_clock_edit(lv_obj_t *btns, const char * txt)
|
||||
static lv_res_t _action_clock_edit_save(lv_obj_t *btns, const char * txt)
|
||||
{
|
||||
_action_clock_edit(btns, txt);
|
||||
_save_nyx_options_action(NULL);
|
||||
|
||||
// Save if changes were made.
|
||||
if (nyx_changes_made)
|
||||
_save_nyx_options_action(NULL);
|
||||
|
||||
return LV_RES_INV;
|
||||
}
|
||||
@@ -874,16 +891,70 @@ disabled:;
|
||||
|
||||
static lv_res_t _home_screen_action(lv_obj_t *ddlist)
|
||||
{
|
||||
n_cfg.home_screen = lv_ddlist_get_selected(ddlist);
|
||||
u32 new_selection = lv_ddlist_get_selected(ddlist);
|
||||
if (n_cfg.home_screen != new_selection)
|
||||
{
|
||||
n_cfg.home_screen = new_selection;
|
||||
nyx_changes_made = true;
|
||||
}
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
static lv_res_t _action_nyx_options_save(lv_obj_t *btns, const char * txt)
|
||||
{
|
||||
int btn_idx = lv_btnm_get_pressed(btns);
|
||||
|
||||
mbox_action(btns, txt);
|
||||
|
||||
if (!btn_idx)
|
||||
_save_nyx_options_action(NULL);
|
||||
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
static void _check_nyx_changes()
|
||||
{
|
||||
if (nyx_changes_made)
|
||||
{
|
||||
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
|
||||
lv_obj_set_style(dark_bg, &mbox_darken);
|
||||
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
|
||||
|
||||
static const char * mbox_btn_map[] = { "\222Save", "\222Cancel", "" };
|
||||
lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL);
|
||||
lv_mbox_set_recolor_text(mbox, true);
|
||||
|
||||
lv_mbox_set_text(mbox,
|
||||
"#FF8000 Nyx configuration#\n\n"
|
||||
"You changed your configuration!\n\n"
|
||||
"Do you want to save it?");
|
||||
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map, _action_nyx_options_save);
|
||||
lv_obj_set_width(mbox, LV_HOR_RES / 9 * 5);
|
||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_top(mbox, true);
|
||||
|
||||
nyx_changes_made = false;
|
||||
}
|
||||
}
|
||||
|
||||
static lv_res_t _action_win_nyx_options_close(lv_obj_t *btn)
|
||||
{
|
||||
lv_win_close_action(btn);
|
||||
|
||||
close_btn = NULL;
|
||||
|
||||
_check_nyx_changes();
|
||||
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
lv_res_t create_win_nyx_options(lv_obj_t *parrent_btn)
|
||||
{
|
||||
lv_theme_t *th = lv_theme_get_current();
|
||||
|
||||
lv_obj_t *win = nyx_create_standard_window(SYMBOL_HOME" Nyx Options");
|
||||
lv_obj_t *win = nyx_create_window_custom_close_btn(SYMBOL_HOME" Nyx Options", _action_win_nyx_options_close);
|
||||
|
||||
static lv_style_t h_style;
|
||||
lv_style_copy(&h_style, &lv_style_transp);
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "fe_emummc_tools.h"
|
||||
#include <memory_map.h>
|
||||
#include "../config.h"
|
||||
#include <gfx/di.h>
|
||||
#include <display/di.h>
|
||||
#include "../hos/pkg1.h"
|
||||
#include "../hos/pkg2.h"
|
||||
#include "../hos/hos.h"
|
||||
@@ -48,7 +48,7 @@ extern volatile boot_cfg_t *b_cfg;
|
||||
extern hekate_config h_cfg;
|
||||
extern nyx_config n_cfg;
|
||||
|
||||
extern void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage);
|
||||
extern char *emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage);
|
||||
|
||||
static lv_obj_t *_create_container(lv_obj_t *parent)
|
||||
{
|
||||
@@ -70,7 +70,7 @@ static lv_obj_t *_create_container(lv_obj_t *parent)
|
||||
|
||||
bool get_autorcm_status(bool change)
|
||||
{
|
||||
u8 corr_mod_byte0;
|
||||
u8 corr_mod0, mod1;
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
bool enabled = false;
|
||||
@@ -84,41 +84,37 @@ bool get_autorcm_status(bool change)
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
sdmmc_storage_read(&storage, 0x200 / NX_EMMC_BLOCKSIZE, 1, tempbuf);
|
||||
|
||||
if ((fuse_read_odm(4) & 3) != 3)
|
||||
corr_mod_byte0 = 0xF7;
|
||||
else
|
||||
corr_mod_byte0 = 0x37;
|
||||
// Get the correct RSA modulus byte masks.
|
||||
nx_emmc_get_autorcm_masks(&corr_mod0, &mod1);
|
||||
|
||||
if (tempbuf[0x10] != corr_mod_byte0)
|
||||
// Check if 2nd byte of modulus is correct.
|
||||
if (tempbuf[0x11] != mod1)
|
||||
goto out;
|
||||
|
||||
if (tempbuf[0x10] != corr_mod0)
|
||||
enabled = true;
|
||||
|
||||
// Change autorcm status if requested.
|
||||
if (change)
|
||||
{
|
||||
int i, sect = 0;
|
||||
u8 randomXor = 0;
|
||||
|
||||
// Iterate BCTs.
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
sect = (0x200 + (0x4000 * i)) / NX_EMMC_BLOCKSIZE;
|
||||
sdmmc_storage_read(&storage, sect, 1, tempbuf);
|
||||
|
||||
if (!enabled)
|
||||
{
|
||||
do
|
||||
{
|
||||
randomXor = get_tmr_us() & 0xFF; // Bricmii style of bricking.
|
||||
} while (!randomXor); // Avoid the lottery.
|
||||
|
||||
tempbuf[0x10] ^= randomXor;
|
||||
}
|
||||
tempbuf[0x10] = 0;
|
||||
else
|
||||
tempbuf[0x10] = corr_mod_byte0;
|
||||
tempbuf[0x10] = corr_mod0;
|
||||
sdmmc_storage_write(&storage, sect, 1, tempbuf);
|
||||
}
|
||||
enabled = !(enabled);
|
||||
}
|
||||
|
||||
out:
|
||||
free(tempbuf);
|
||||
sdmmc_storage_end(&storage);
|
||||
|
||||
@@ -297,8 +293,14 @@ static lv_res_t _create_mbox_ums(usb_ctxt_t *usbs)
|
||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_top(mbox, true);
|
||||
|
||||
// Dim backlight.
|
||||
display_backlight_brightness(20, 1000);
|
||||
|
||||
usb_device_gadget_ums(usbs);
|
||||
|
||||
// Restore backlight.
|
||||
display_backlight_brightness(h_cfg.backlight - 20, 1000);
|
||||
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map2, mbox_action);
|
||||
|
||||
ums_mbox = dark_bg;
|
||||
@@ -1190,6 +1192,8 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
|
||||
if (!pkg1_decrypt(pkg1_id, pkg1))
|
||||
{
|
||||
strcat(txt_buf, "#FFDD00 Pkg1 decryption failed!#\n");
|
||||
if (h_cfg.t210b01)
|
||||
strcat(txt_buf, "#FFDD00 Is BEK missing?#\n");
|
||||
lv_label_set_text(lb_desc, txt_buf);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
@@ -48,6 +48,8 @@ typedef struct _partition_ctxt_t
|
||||
u32 l4t_size;
|
||||
u32 and_size;
|
||||
|
||||
mbr_t *mbr_old;
|
||||
|
||||
lv_obj_t *bar_hos;
|
||||
lv_obj_t *bar_emu;
|
||||
lv_obj_t *bar_l4t;
|
||||
@@ -79,6 +81,9 @@ typedef struct _l4t_flasher_ctxt_t
|
||||
partition_ctxt_t part_info;
|
||||
l4t_flasher_ctxt_t l4t_flash_ctxt;
|
||||
|
||||
lv_obj_t *btn_flash_l4t;
|
||||
lv_obj_t *btn_flash_android;
|
||||
|
||||
static int _backup_and_restore_files(char *path, u32 *total_files, u32 *total_size, const char *dst, const char *src, lv_obj_t **labels)
|
||||
{
|
||||
FRESULT res;
|
||||
@@ -214,6 +219,10 @@ static void _prepare_and_flash_mbr_gpt()
|
||||
// Read current MBR.
|
||||
sdmmc_storage_read(&sd_storage, 0, 1, &mbr);
|
||||
|
||||
// Copy over metadata if they exist.
|
||||
if (part_info.mbr_old->bootstrap[0x80])
|
||||
memcpy(&mbr.bootstrap[0x80], &part_info.mbr_old->bootstrap[0x80], 304);
|
||||
|
||||
// Clear the first 16MB.
|
||||
memset((void *)SDMMC_UPPER_BUFFER, 0, 0x8000);
|
||||
sdmmc_storage_write(&sd_storage, 0, 0x8000, (void *)SDMMC_UPPER_BUFFER);
|
||||
@@ -390,10 +399,19 @@ static void _prepare_and_flash_mbr_gpt()
|
||||
curr_part_lba += 0x15E000;
|
||||
gpt_idx++;
|
||||
|
||||
// Android Misc partition.
|
||||
memcpy(gpt.entries[gpt_idx].type_guid, android_part_guid, 16);
|
||||
se_gen_prng128(random_number);
|
||||
memcpy(gpt.entries[gpt_idx].part_guid, random_number, 16);
|
||||
gpt.entries[gpt_idx].lba_start = curr_part_lba;
|
||||
gpt.entries[gpt_idx].lba_end = curr_part_lba + 0x1800 - 1; // 3MB.
|
||||
memcpy(gpt.entries[gpt_idx].name, (char[]) { 'M', 0, 'S', 0, 'C', 0 }, 6);
|
||||
sdmmc_storage_write(&sd_storage, curr_part_lba, 0x800, (void *)SDMMC_UPPER_BUFFER); // Clear the first 1MB.
|
||||
curr_part_lba += 0x1800;
|
||||
gpt_idx++;
|
||||
|
||||
// Android Userdata partition.
|
||||
u32 align_diff = ALIGN(curr_part_lba, 0x8000) - curr_part_lba;
|
||||
curr_part_lba += align_diff; // Align to 16MB.
|
||||
u32 user_size = (part_info.and_size << 11) - 0x796800 - align_diff; // Subtract the other partitions (3885MB).
|
||||
u32 user_size = (part_info.and_size << 11) - 0x798000 - curr_part_lba; // Subtract the other partitions (3888MB).
|
||||
if (!part_info.emu_size)
|
||||
user_size -= 0x800; // Reserve 1MB.
|
||||
memcpy(gpt.entries[gpt_idx].type_guid, android_part_guid, 16);
|
||||
@@ -712,45 +730,13 @@ exit:
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
static lv_res_t _action_check_flash_linux(lv_obj_t *btn)
|
||||
static u32 _get_available_l4t_partition()
|
||||
{
|
||||
FILINFO fno;
|
||||
char path[128];
|
||||
mbr_t mbr = { 0 };
|
||||
gpt_t gpt = { 0 };
|
||||
|
||||
memset(&l4t_flash_ctxt, 0, sizeof(l4t_flasher_ctxt_t));
|
||||
|
||||
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
|
||||
lv_obj_set_style(dark_bg, &mbox_darken);
|
||||
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
|
||||
|
||||
static const char *mbox_btn_map[] = { "\211", "\222OK", "\211", "" };
|
||||
static const char *mbox_btn_map2[] = { "\222Continue", "\222Cancel", "" };
|
||||
lv_obj_t *mbox = lv_mbox_create(dark_bg, NULL);
|
||||
lv_mbox_set_recolor_text(mbox, true);
|
||||
lv_obj_set_width(mbox, LV_HOR_RES / 9 * 6);
|
||||
|
||||
lv_mbox_set_text(mbox, "#FF8000 Linux Flasher#");
|
||||
|
||||
lv_obj_t *lbl_status = lv_label_create(mbox, NULL);
|
||||
lv_label_set_recolor(lbl_status, true);
|
||||
lv_label_set_text(lbl_status, "#C7EA46 Status:# Searching for files and partitions...");
|
||||
|
||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_top(mbox, true);
|
||||
|
||||
manual_system_maintenance(true);
|
||||
|
||||
sd_mount();
|
||||
|
||||
strcpy(path, "switchroot/install/l4t.00");
|
||||
if (f_stat(path, NULL))
|
||||
{
|
||||
lv_label_set_text(lbl_status, "#FFDD00 Error:# Installation files not found!");
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Read MBR.
|
||||
sdmmc_storage_read(&sd_storage, 0, 1, &mbr);
|
||||
|
||||
@@ -787,7 +773,71 @@ static lv_res_t _action_check_flash_linux(lv_obj_t *btn)
|
||||
}
|
||||
}
|
||||
|
||||
if (!l4t_flash_ctxt.offset_sct || size_sct < 0x800000)
|
||||
return size_sct;
|
||||
}
|
||||
|
||||
static bool _get_available_android_partition()
|
||||
{
|
||||
gpt_t gpt = { 0 };
|
||||
|
||||
// Read main GPT.
|
||||
sdmmc_storage_read(&sd_storage, 1, sizeof(gpt_t) >> 9, &gpt);
|
||||
|
||||
// Check if GPT.
|
||||
if (memcmp(&gpt.header.signature, "EFI PART", 8))
|
||||
return false;
|
||||
|
||||
// Find kernel partition.
|
||||
for (u32 i = 0; i < gpt.header.num_part_ents; i++)
|
||||
{
|
||||
if (gpt.entries[i].lba_start && !memcmp(gpt.entries[i].name, (char[]) { 'L', 0, 'N', 0, 'X', 0 }, 6))
|
||||
return true;
|
||||
|
||||
if (i > 126)
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static lv_res_t _action_check_flash_linux(lv_obj_t *btn)
|
||||
{
|
||||
FILINFO fno;
|
||||
char path[128];
|
||||
|
||||
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
|
||||
lv_obj_set_style(dark_bg, &mbox_darken);
|
||||
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
|
||||
|
||||
static const char *mbox_btn_map[] = { "\211", "\222OK", "\211", "" };
|
||||
static const char *mbox_btn_map2[] = { "\222Continue", "\222Cancel", "" };
|
||||
lv_obj_t *mbox = lv_mbox_create(dark_bg, NULL);
|
||||
lv_mbox_set_recolor_text(mbox, true);
|
||||
lv_obj_set_width(mbox, LV_HOR_RES / 9 * 6);
|
||||
|
||||
lv_mbox_set_text(mbox, "#FF8000 Linux Flasher#");
|
||||
|
||||
lv_obj_t *lbl_status = lv_label_create(mbox, NULL);
|
||||
lv_label_set_recolor(lbl_status, true);
|
||||
lv_label_set_text(lbl_status, "#C7EA46 Status:# Searching for files and partitions...");
|
||||
|
||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_top(mbox, true);
|
||||
|
||||
manual_system_maintenance(true);
|
||||
|
||||
sd_mount();
|
||||
|
||||
strcpy(path, "switchroot/install/l4t.00");
|
||||
if (f_stat(path, NULL))
|
||||
{
|
||||
lv_label_set_text(lbl_status, "#FFDD00 Error:# Installation files not found!");
|
||||
goto error;
|
||||
}
|
||||
|
||||
u32 size_sct = _get_available_l4t_partition();
|
||||
|
||||
if (!l4t_flash_ctxt.offset_sct || !size_sct || size_sct < 0x800000)
|
||||
{
|
||||
lv_label_set_text(lbl_status, "#FFDD00 Error:# No partition found!");
|
||||
goto error;
|
||||
@@ -1135,8 +1185,6 @@ error:
|
||||
|
||||
static lv_res_t _action_flash_android(lv_obj_t *btn)
|
||||
{
|
||||
memset(&l4t_flash_ctxt, 0, sizeof(l4t_flasher_ctxt_t));
|
||||
|
||||
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
|
||||
lv_obj_set_style(dark_bg, &mbox_darken);
|
||||
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
|
||||
@@ -1308,6 +1356,10 @@ static lv_res_t _create_mbox_start_partitioning(lv_obj_t *btn)
|
||||
u32 total_files = 0;
|
||||
u32 total_size = 0;
|
||||
|
||||
// Read current MBR.
|
||||
part_info.mbr_old = (mbr_t *)calloc(512, 1);
|
||||
sdmmc_storage_read(&sd_storage, 0, 1, part_info.mbr_old);
|
||||
|
||||
lv_label_set_text(lbl_status, "#00DDFF Status:# Initializing Ramdisk...");
|
||||
lv_label_set_text(lbl_paths[0], "Please wait...");
|
||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
@@ -1449,6 +1501,30 @@ static lv_res_t _create_mbox_start_partitioning(lv_obj_t *btn)
|
||||
manual_system_maintenance(true);
|
||||
_prepare_and_flash_mbr_gpt();
|
||||
|
||||
// Enable/Disable buttons depending on partition layout.
|
||||
if (part_info.l4t_size)
|
||||
{
|
||||
lv_obj_set_click(btn_flash_l4t, true);
|
||||
lv_btn_set_state(btn_flash_l4t, LV_BTN_STATE_REL);
|
||||
}
|
||||
else
|
||||
{
|
||||
lv_obj_set_click(btn_flash_l4t, false);
|
||||
lv_btn_set_state(btn_flash_l4t, LV_BTN_STATE_INA);
|
||||
}
|
||||
|
||||
// Enable/Disable buttons depending on partition layout.
|
||||
if (part_info.and_size)
|
||||
{
|
||||
lv_obj_set_click(btn_flash_android, true);
|
||||
lv_btn_set_state(btn_flash_android, LV_BTN_STATE_REL);
|
||||
}
|
||||
else
|
||||
{
|
||||
lv_obj_set_click(btn_flash_android, false);
|
||||
lv_btn_set_state(btn_flash_android, LV_BTN_STATE_INA);
|
||||
}
|
||||
|
||||
sd_unmount();
|
||||
lv_label_set_text(lbl_status, "#00DDFF Status:# Done!");
|
||||
manual_system_maintenance(true);
|
||||
@@ -1543,7 +1619,7 @@ static lv_res_t _create_mbox_partitioning_next(lv_obj_t *btn)
|
||||
s_printf(txt_buf, "#FFDD00 Warning: This will partition your SD Card!#\n\n");
|
||||
|
||||
if (part_info.backup_possible)
|
||||
strcat(txt_buf, "#C7EA46 Your files will be backed up and restored!#");
|
||||
strcat(txt_buf, "#C7EA46 Your files will be backed up and restored!#\n#FFDD00Any other partition will be wiped!#");
|
||||
else
|
||||
strcat(txt_buf, "#FFDD00 Your files will be wiped!#\n#FFDD00 Use USB UMS to copy them over!#");
|
||||
|
||||
@@ -1790,7 +1866,8 @@ static void create_mbox_check_files_total_size()
|
||||
if (part_info.backup_possible)
|
||||
{
|
||||
s_printf(txt_buf,
|
||||
"#96FF00 Your SD Card files will be backed up automatically!#\n\n"
|
||||
"#96FF00 Your SD Card files will be backed up automatically!#\n"
|
||||
"#FFDD00 Any other partition will be wiped!#\n"
|
||||
"#00DDFF Total files:# %d, #00DDFF Total size:# %d MiB", total_files, total_size >> 20);
|
||||
lv_mbox_set_text(mbox, txt_buf);
|
||||
}
|
||||
@@ -2301,19 +2378,34 @@ lv_res_t create_window_partition_manager(lv_obj_t *btn)
|
||||
lv_obj_align(btn1, h1, LV_ALIGN_IN_TOP_LEFT, 0, LV_DPI * 5);
|
||||
lv_btn_set_action(btn1, LV_BTN_ACTION_CLICK, _action_part_manager_ums_sd);
|
||||
|
||||
lv_obj_t *btn2 = lv_btn_create(h1, NULL);
|
||||
lv_obj_t *label_btn2 = lv_label_create(btn2, NULL);
|
||||
lv_btn_set_fit(btn2, true, true);
|
||||
lv_obj_t *btn_flash_l4t = lv_btn_create(h1, NULL);
|
||||
lv_obj_t *label_btn2 = lv_label_create(btn_flash_l4t, NULL);
|
||||
lv_btn_set_fit(btn_flash_l4t, true, true);
|
||||
lv_label_set_static_text(label_btn2, SYMBOL_DOWNLOAD" Flash Linux");
|
||||
lv_obj_align(btn2, btn1, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 3, 0);
|
||||
lv_btn_set_action(btn2, LV_BTN_ACTION_CLICK, _action_check_flash_linux);
|
||||
lv_obj_align(btn_flash_l4t, btn1, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 3, 0);
|
||||
lv_btn_set_action(btn_flash_l4t, LV_BTN_ACTION_CLICK, _action_check_flash_linux);
|
||||
|
||||
btn1 = lv_btn_create(h1, NULL);
|
||||
label_btn = lv_label_create(btn1, NULL);
|
||||
lv_btn_set_fit(btn1, true, true);
|
||||
// Disable Flash Linux button if partition not found.
|
||||
u32 size_sct = _get_available_l4t_partition();
|
||||
if (!l4t_flash_ctxt.offset_sct || !size_sct || size_sct < 0x800000)
|
||||
{
|
||||
lv_obj_set_click(btn_flash_l4t, false);
|
||||
lv_btn_set_state(btn_flash_l4t, LV_BTN_STATE_INA);
|
||||
}
|
||||
|
||||
btn_flash_android = lv_btn_create(h1, NULL);
|
||||
label_btn = lv_label_create(btn_flash_android, NULL);
|
||||
lv_btn_set_fit(btn_flash_android, true, true);
|
||||
lv_label_set_static_text(label_btn, SYMBOL_DOWNLOAD" Flash Android");
|
||||
lv_obj_align(btn1, btn2, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 3, 0);
|
||||
lv_btn_set_action(btn1, LV_BTN_ACTION_CLICK, _action_flash_android);
|
||||
lv_obj_align(btn_flash_android, btn_flash_l4t, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 3, 0);
|
||||
lv_btn_set_action(btn_flash_android, LV_BTN_ACTION_CLICK, _action_flash_android);
|
||||
|
||||
// Disable Flash Android button if partition not found.
|
||||
if (!_get_available_android_partition())
|
||||
{
|
||||
lv_obj_set_click(btn_flash_android, false);
|
||||
lv_btn_set_state(btn_flash_android, LV_BTN_STATE_INA);
|
||||
}
|
||||
|
||||
btn1 = lv_btn_create(h1, NULL);
|
||||
label_btn = lv_label_create(btn1, NULL);
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "hos.h"
|
||||
#include "sept.h"
|
||||
#include "../config.h"
|
||||
#include <gfx/di.h>
|
||||
#include <display/di.h>
|
||||
#include <gfx_utils.h>
|
||||
#include <mem/heap.h>
|
||||
#include <mem/mc.h>
|
||||
@@ -117,7 +117,7 @@ static const u8 new_console_kekseed[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSIO
|
||||
{ 0x86, 0x61, 0xB0, 0x16, 0xFA, 0x7A, 0x9A, 0xEA, 0xF6, 0xF5, 0xBE, 0x1A, 0x13, 0x5B, 0x6D, 0x9E }, // 7.0.0 New Device Keygen Source.
|
||||
{ 0xA6, 0x81, 0x71, 0xE7, 0xB5, 0x23, 0x74, 0xB0, 0x39, 0x8C, 0xB7, 0xFF, 0xA0, 0x62, 0x9F, 0x8D }, // 8.1.0 New Device Keygen Source.
|
||||
{ 0x03, 0xE7, 0xEB, 0x43, 0x1B, 0xCF, 0x5F, 0xB5, 0xED, 0xDC, 0x97, 0xAE, 0x21, 0x8D, 0x19, 0xED }, // 9.0.0 New Device Keygen Source.
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // TODO: 9.1.0 New Device Keygen Source to be added on next change-of-keys.
|
||||
{ 0xCE, 0xFE, 0x41, 0x0F, 0x46, 0x9A, 0x30, 0xD6, 0xF2, 0xE9, 0x0C, 0x6B, 0xB7, 0x15, 0x91, 0x36 }, // 9.1.0 New Device Keygen Source.
|
||||
};
|
||||
|
||||
static const u8 gen_keyseed[0x10] =
|
||||
@@ -180,7 +180,7 @@ void hos_eks_get()
|
||||
|
||||
// Check if valid and for this unit.
|
||||
if (eks->magic == HOS_EKS_MAGIC &&
|
||||
eks->lot0 == FUSE(FUSE_OPT_LOT_CODE_0))
|
||||
(eks->lot0 == FUSE(FUSE_OPT_LOT_CODE_0) || eks->lot0 == FUSE(FUSE_PRIVATE_KEY0)))
|
||||
{
|
||||
h_cfg.eks = eks;
|
||||
return;
|
||||
@@ -231,10 +231,6 @@ void hos_eks_save(u32 kb)
|
||||
u8 *keys = (u8 *)calloc(0x1000, 1);
|
||||
se_get_aes_keys(keys + 0x800, keys, 0x10);
|
||||
|
||||
// Set SBK back.
|
||||
if (h_cfg.sbk_set)
|
||||
se_aes_key_set(14, keys + 14 * 0x10, 0x10);
|
||||
|
||||
// Set magic and personalized info.
|
||||
h_cfg.eks->magic = HOS_EKS_MAGIC;
|
||||
h_cfg.eks->enabled[key_idx] = kb;
|
||||
@@ -598,6 +594,19 @@ static void _hos_validate_sept_mkey(u32 kb)
|
||||
hos_eks_clear(kb);
|
||||
}
|
||||
|
||||
static void _hos_bis_print_key(u32 idx, u8 *key)
|
||||
{
|
||||
gfx_printf("BIS %d Crypt: ", idx);
|
||||
for (int i = 0; i < 0x10; i++)
|
||||
gfx_printf("%02X", key[((idx * 2 + 0) * 0x10) + i]);
|
||||
gfx_puts("\n");
|
||||
|
||||
gfx_printf("BIS %d Tweak: ", idx);
|
||||
for (int i = 0; i < 0x10; i++)
|
||||
gfx_printf("%02X", key[((idx * 2 + 1) * 0x10) + i]);
|
||||
gfx_puts("\n");
|
||||
}
|
||||
|
||||
int hos_bis_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
{
|
||||
u32 keygen_rev = 0;
|
||||
@@ -614,6 +623,8 @@ int hos_bis_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
// We check unconditionally in order to support downgrades.
|
||||
keygen_rev = fuse_read_odm_keygen_rev();
|
||||
|
||||
gfx_printf("Keygen rev: %d\n", keygen_rev);
|
||||
|
||||
if (keygen_rev)
|
||||
{
|
||||
u8 tmp_mkey[0x10];
|
||||
@@ -690,6 +701,10 @@ int hos_bis_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
memcpy(bis_keys + (5 * 0x10), h_cfg.eks->bis_keys[2].tweak, 0x10);
|
||||
}
|
||||
|
||||
_hos_bis_print_key(0, bis_keys);
|
||||
_hos_bis_print_key(1, bis_keys);
|
||||
_hos_bis_print_key(2, bis_keys);
|
||||
|
||||
// Clear all AES keyslots.
|
||||
for (u32 i = 0; i < 6; i++)
|
||||
se_aes_key_clear(i);
|
||||
|
||||
@@ -42,22 +42,22 @@ static const u8 sec_map_2xx[3] = { PK11_SECTION_WB, PK11_SECTION_LD, PK11_SECTIO
|
||||
static const u8 sec_map_4xx[3] = { PK11_SECTION_LD, PK11_SECTION_SM, PK11_SECTION_WB };
|
||||
|
||||
static const pkg1_id_t _pkg1_ids[] = {
|
||||
{ "20161121183008", 0, 0x1900, 0x3FE0, 0x40014020, 0x8000D000 }, // 1.0.0.
|
||||
{ "20170210155124", 0, 0x1900, 0x3FE0, 0x4002D000, 0x8000D000 }, // 2.0.0 - 2.3.0.
|
||||
{ "20170519101410", 1, 0x1A00, 0x3FE0, 0x4002D000, 0x8000D000 }, // 3.0.0.
|
||||
{ "20170710161758", 2, 0x1A00, 0x3FE0, 0x4002D000, 0x8000D000 }, // 3.0.1 - 3.0.2.
|
||||
{ "20170921172629", 3, 0x1800, 0x3FE0, 0x4002B000, 0x4003B000 }, // 4.0.0 - 4.1.0.
|
||||
{ "20180220163747", 4, 0x1900, 0x3FE0, 0x4002B000, 0x4003B000 }, // 5.0.0 - 5.1.0.
|
||||
{ "20180802162753", 5, 0x1900, 0x3FE0, 0x4002B000, 0x4003D800 }, // 6.0.0 - 6.1.0.
|
||||
{ "20181107105733", 6, 0x0E00, 0x6FE0, 0x4002B000, 0x4003D800 }, // 6.2.0.
|
||||
{ "20181218175730", 7, 0x0F00, 0x6FE0, 0x40030000, 0x4003E000 }, // 7.0.0.
|
||||
{ "20190208150037", 7, 0x0F00, 0x6FE0, 0x40030000, 0x4003E000 }, // 7.0.1.
|
||||
{ "20190314172056", 7, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 8.0.0 - 8.0.1.
|
||||
{ "20190531152432", 8, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 8.1.0.
|
||||
{ "20190809135709", 9, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 9.0.0 - 9.0.1.
|
||||
{ "20191021113848", 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 9.1.0.
|
||||
{ "20200303104606", 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 10.0.0.
|
||||
{ "20201030110855", 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 11.0.0.
|
||||
{ "20161121183008", 0, 0x1900, 0x3FE0, 0x40014020, 0x8000D000 }, // 1.0.0.
|
||||
{ "20170210155124", 0, 0x1900, 0x3FE0, 0x4002D000, 0x8000D000 }, // 2.0.0 - 2.3.0.
|
||||
{ "20170519101410", 1, 0x1A00, 0x3FE0, 0x4002D000, 0x8000D000 }, // 3.0.0.
|
||||
{ "20170710161758", 2, 0x1A00, 0x3FE0, 0x4002D000, 0x8000D000 }, // 3.0.1 - 3.0.2.
|
||||
{ "20170921172629", 3, 0x1800, 0x3FE0, 0x4002B000, 0x4003B000 }, // 4.0.0 - 4.1.0.
|
||||
{ "20180220163747", 4, 0x1900, 0x3FE0, 0x4002B000, 0x4003B000 }, // 5.0.0 - 5.1.0.
|
||||
{ "20180802162753", 5, 0x1900, 0x3FE0, 0x4002B000, 0x4003D800 }, // 6.0.0 - 6.1.0.
|
||||
{ "20181107105733", 6, 0x0E00, 0x6FE0, 0x4002B000, 0x4003D800 }, // 6.2.0.
|
||||
{ "20181218175730", 7, 0x0F00, 0x6FE0, 0x40030000, 0x4003E000 }, // 7.0.0.
|
||||
{ "20190208150037", 7, 0x0F00, 0x6FE0, 0x40030000, 0x4003E000 }, // 7.0.1.
|
||||
{ "20190314172056", 7, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 8.0.0 - 8.0.1.
|
||||
{ "20190531152432", 8, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 8.1.0 - 8.1.1.
|
||||
{ "20190809135709", 9, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 9.0.0 - 9.0.1.
|
||||
{ "20191021113848", 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 9.1.0 - 9.2.0.
|
||||
{ "20200303104606", 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 10.0.0 - 10.2.0.
|
||||
{ "20201030110855", 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 11.0.0+
|
||||
{ NULL } //End.
|
||||
};
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include "hos.h"
|
||||
#include "sept.h"
|
||||
#include "../config.h"
|
||||
#include <gfx/di.h>
|
||||
#include <display/di.h>
|
||||
#include <ianos/ianos.h>
|
||||
#include <libs/fatfs/ff.h>
|
||||
#include <mem/heap.h>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <memory_map.h>
|
||||
|
||||
#include "config.h"
|
||||
#include <gfx/di.h>
|
||||
#include <display/di.h>
|
||||
#include <gfx_utils.h>
|
||||
#include "hos/hos.h"
|
||||
#include <ianos/ianos.h>
|
||||
@@ -32,11 +32,13 @@
|
||||
#include <mem/minerva.h>
|
||||
#include <mem/sdram.h>
|
||||
#include <power/max77620.h>
|
||||
#include <soc/clock.h>
|
||||
#include <soc/bpmp.h>
|
||||
#include <soc/fuse.h>
|
||||
#include <soc/gpio.h>
|
||||
#include <soc/hw_init.h>
|
||||
#include <soc/i2c.h>
|
||||
#include <soc/pinmux.h>
|
||||
#include <soc/pmc.h>
|
||||
#include <soc/t210.h>
|
||||
#include <soc/uart.h>
|
||||
@@ -67,43 +69,55 @@ const volatile ipl_ver_meta_t __attribute__((section ("._ipl_version"))) ipl_ver
|
||||
volatile nyx_storage_t *nyx_str = (nyx_storage_t *)NYX_STORAGE_ADDR;
|
||||
volatile boot_cfg_t *b_cfg;
|
||||
|
||||
void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage)
|
||||
char *emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage)
|
||||
{
|
||||
sdmmc_storage_t storage2;
|
||||
sdmmc_t sdmmc;
|
||||
char emmcSN[9];
|
||||
bool init_done = false;
|
||||
static char emmc_sn[9] = {0};
|
||||
|
||||
memcpy(path, "backup", 7);
|
||||
f_mkdir(path);
|
||||
// Check if eMMC S/N storage has valid data and skip parsing in that case.
|
||||
if (emmc_sn[0] && strcmp(emmc_sn, "00000000"))
|
||||
goto create_dir;
|
||||
|
||||
// Get actual eMMC S/N.
|
||||
if (!storage)
|
||||
{
|
||||
sdmmc_t sdmmc;
|
||||
sdmmc_storage_t storage2;
|
||||
|
||||
if (!sdmmc_storage_init_mmc(&storage2, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
memcpy(emmcSN, "00000000", 9);
|
||||
strcpy(emmc_sn, "00000000");
|
||||
else
|
||||
{
|
||||
init_done = true;
|
||||
itoa(storage2.cid.serial, emmcSN, 16);
|
||||
itoa(storage2.cid.serial, emmc_sn, 16);
|
||||
sdmmc_storage_end(&storage2);
|
||||
}
|
||||
}
|
||||
else
|
||||
itoa(storage->cid.serial, emmcSN, 16);
|
||||
itoa(storage->cid.serial, emmc_sn, 16);
|
||||
|
||||
u32 sub_dir_len = strlen(sub_dir); // Can be a null-terminator.
|
||||
u32 filename_len = strlen(filename); // Can be a null-terminator.
|
||||
create_dir:
|
||||
// Check if only eMMC S/N was requested.
|
||||
if (!path)
|
||||
return emmc_sn;
|
||||
|
||||
memcpy(path + strlen(path), "/", 2);
|
||||
memcpy(path + strlen(path), emmcSN, 9);
|
||||
// Create main folder.
|
||||
strcpy(path, "backup");
|
||||
f_mkdir(path);
|
||||
memcpy(path + strlen(path), sub_dir, sub_dir_len + 1);
|
||||
if (sub_dir_len)
|
||||
f_mkdir(path);
|
||||
memcpy(path + strlen(path), "/", 2);
|
||||
memcpy(path + strlen(path), filename, filename_len + 1);
|
||||
|
||||
if (init_done)
|
||||
sdmmc_storage_end(&storage2);
|
||||
// Create eMMC S/N folder.
|
||||
strcat(path, "/");
|
||||
strcat(path, emmc_sn);
|
||||
f_mkdir(path);
|
||||
|
||||
// Create sub folder if defined. Dir slash must be included.
|
||||
strcat(path, sub_dir); // Can be a null-terminator.
|
||||
if (strlen(sub_dir))
|
||||
f_mkdir(path);
|
||||
|
||||
// Add filename.
|
||||
strcat(path, "/");
|
||||
strcat(path, filename); // Can be a null-terminator.
|
||||
|
||||
return emmc_sn;
|
||||
}
|
||||
|
||||
// This is a safe and unused DRAM region for our payloads.
|
||||
@@ -173,7 +187,7 @@ lv_res_t launch_payload(lv_obj_t *list)
|
||||
{
|
||||
f_close(&fp);
|
||||
|
||||
EPRINTF("T210B01: Coreboot not allowed!");
|
||||
EPRINTF("Coreboot not allowed on Mariko!");
|
||||
|
||||
goto out;
|
||||
}
|
||||
@@ -355,6 +369,21 @@ void nyx_init_load_res()
|
||||
set_default_configuration();
|
||||
set_nyx_default_configuration();
|
||||
|
||||
// Reset new info if magic not correct.
|
||||
if (nyx_str->info.magic != NYX_NEW_INFO)
|
||||
{
|
||||
nyx_str->info.sd_init = 0;
|
||||
for (u32 i = 0; i < 3; i++)
|
||||
nyx_str->info.sd_errors[i] = 0;
|
||||
}
|
||||
|
||||
// Clear info magic.
|
||||
nyx_str->info.magic = 0;
|
||||
|
||||
// Set display id from previous initialization.
|
||||
display_set_decoded_panel_id(nyx_str->info.disp_id);
|
||||
|
||||
// Initialize gfx console.
|
||||
gfx_init_ctxt((u32 *)LOG_FB_ADDRESS, 1280, 656, 656);
|
||||
gfx_con_init();
|
||||
|
||||
@@ -421,7 +450,8 @@ void ipl_main()
|
||||
#endif
|
||||
pinmux_config_uart(DEBUG_UART_PORT);
|
||||
clock_enable_uart(DEBUG_UART_PORT);
|
||||
uart_init(DEBUG_UART_PORT, 115200);
|
||||
uart_init(DEBUG_UART_PORT, DEBUG_UART_BAUDRATE);
|
||||
uart_invert(DEBUG_UART_PORT, DEBUG_UART_INVERT, UART_INVERT_TXD);
|
||||
|
||||
uart_send(DEBUG_UART_PORT, (u8 *)"hekate-NYX: Hello!\r\n", 20);
|
||||
uart_wait_idle(DEBUG_UART_PORT, UART_TX_IDLE);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2019-2020 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -16,9 +17,10 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <storage/mbr_gpt.h>
|
||||
#include "nx_emmc.h"
|
||||
#include <mem/heap.h>
|
||||
#include <soc/fuse.h>
|
||||
#include <storage/mbr_gpt.h>
|
||||
#include <utils/list.h>
|
||||
|
||||
sdmmc_t emmc_sdmmc;
|
||||
@@ -83,3 +85,17 @@ int nx_emmc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_o
|
||||
return 0;
|
||||
return sdmmc_storage_write(storage, part->lba_start + sector_off, num_sectors, buf);
|
||||
}
|
||||
|
||||
void nx_emmc_get_autorcm_masks(u8 *mod0, u8 *mod1)
|
||||
{
|
||||
if (fuse_read_hw_state() == FUSE_NX_HW_STATE_PROD)
|
||||
{
|
||||
*mod0 = 0xF7;
|
||||
*mod1 = 0x86;
|
||||
}
|
||||
else
|
||||
{
|
||||
*mod0 = 0x37;
|
||||
*mod1 = 0x84;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2019-2020 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -43,7 +44,9 @@ extern FATFS emmc_fs;
|
||||
void nx_emmc_gpt_parse(link_t *gpt, sdmmc_storage_t *storage);
|
||||
void nx_emmc_gpt_free(link_t *gpt);
|
||||
emmc_part_t *nx_emmc_part_find(link_t *gpt, const char *name);
|
||||
int nx_emmc_part_read(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf);
|
||||
int nx_emmc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf);
|
||||
int nx_emmc_part_read(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf);
|
||||
int nx_emmc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf);
|
||||
|
||||
void nx_emmc_get_autorcm_masks(u8 *mod0, u8 *mod1);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
NATIVE_CC ?= gcc
|
||||
|
||||
ifeq (, $(shell which $(NATIVE_CC) 2>/dev/null))
|
||||
$(error "Native GCC is missing. Please install it first. If it's path is custom, set it with export NATIVE_CC=<path to native gcc toolchain>")
|
||||
endif
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: bin2c
|
||||
@echo > /dev/null
|
||||
|
||||
clean:
|
||||
rm -f bin2c
|
||||
@rm -f bin2c
|
||||
|
||||
bin2c: bin2c.c
|
||||
@$(NATIVE_CC) -o $@ bin2c.c
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
NATIVE_CC ?= gcc
|
||||
|
||||
ifeq (, $(shell which $(NATIVE_CC) 2>/dev/null))
|
||||
$(error "Native GCC is missing. Please install it first. If it's path is custom, set it with export NATIVE_CC=<path to native gcc toolchain>")
|
||||
endif
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: lz77
|
||||
@echo > /dev/null
|
||||
|
||||
clean:
|
||||
rm -f lz77
|
||||
@rm -f lz77
|
||||
|
||||
lz77: lz.c lz77.c
|
||||
@$(NATIVE_CC) -o $@ lz.c lz77.c
|
||||
|
||||
@@ -33,7 +33,7 @@ int main(int argc, char *argv[])
|
||||
if(stat(argv[1], &statbuf))
|
||||
goto error;
|
||||
|
||||
if((in_file=fopen(argv[1], "r")) == NULL)
|
||||
if((in_file=fopen(argv[1], "rb")) == NULL)
|
||||
goto error;
|
||||
|
||||
strcpy(filename, argv[1]);
|
||||
@@ -76,7 +76,7 @@ int main(int argc, char *argv[])
|
||||
if (nbytes > out_size)
|
||||
goto error;
|
||||
|
||||
if((out_file = fopen(filename,"w")) == NULL)
|
||||
if((out_file = fopen(filename,"wb")) == NULL)
|
||||
goto error;
|
||||
|
||||
if (fwrite(out_buf, 1, nbytes, out_file) != nbytes)
|
||||
|
||||
Reference in New Issue
Block a user