Compare commits

..

65 Commits

Author SHA1 Message Date
CTCaer
13e5216a4e Bump hekate to v5.5.2 and Nyx to v0.9.8 2021-01-05 17:13:39 +02:00
CTCaer
147ccd3070 nyx: Add Main/CPU/GPU pmic info. 2021-01-05 17:12:03 +02:00
CTCaer
dc5c26e7c6 nyx: Change fuse dumping names for T210B01 again
Use offsets in names for making it easier to parse.
2021-01-05 15:52:34 +02:00
CTCaer
4914af1200 nyx: Allow selection of emuMMC migration type 2021-01-05 15:44:35 +02:00
CTCaer
b57d26e99a nyx: Add nyx options save reminder 2021-01-05 15:41:27 +02:00
CTCaer
f196b8bb0e eks: Add compatibility support for v1.1 2021-01-05 15:37:36 +02:00
CTCaer
7b460f7e56 gfx: Do not try to print if console is not initialized 2021-01-05 15:36:43 +02:00
CTCaer
9daa14abec ums: Dim backlight and change the maintenance order 2021-01-04 20:12:26 +02:00
CTCaer
bf8fd9a33b hos: Replace fuse count if current fw is higher 2021-01-04 19:05:04 +02:00
CTCaer
1f37b96359 coreboot mitigation: Reinstate SD controller power 2021-01-04 19:03:50 +02:00
CTCaer
46921aca22 Disable battery management on dev units 2021-01-04 02:58:07 +02:00
CTCaer
41f96d4305 hos: Utilize burnt fuse info instead of keyblob
Streamline identification of HOS version quirks
2021-01-04 02:57:07 +02:00
CTCaer
0959dc3a2d nyx: Add touch panel info
This can probably also show if the panel is paired to the firmware.
In case it's not, an error will show up.
2021-01-04 02:49:07 +02:00
CTCaer
31baf3d19a nyx: Rearrange hw info a bit 2021-01-04 02:47:08 +02:00
CTCaer
f4696da0ef sdram: Update names for Aula 2021-01-04 02:45:32 +02:00
CTCaer
83ab79c51e fuse: Return the proper dram id when raw is requested 2021-01-04 02:41:55 +02:00
CTCaer
745ac609d2 max7762x: Update everything to use the improved pmic management 2021-01-04 02:41:15 +02:00
CTCaer
0f9aa51afe max7762x: Refactor pmic
- Add Erista CPU/GPU pmics and Mariko CPU/GPU/DRAM pmics together with system pmic.
- Every type of pmic can be configured via the relevant functions.
- Better and easier configation of the regulators
2021-01-04 02:34:58 +02:00
CTCaer
9fbb28e887 max7762x: Update registers for all pmic types 2021-01-04 02:29:36 +02:00
CTCaer
adf2045896 joycon: Do not send CRC if nxpad + some refactoring 2021-01-03 15:37:44 +02:00
CTCaer
1a797bf93a Merge pull request #545 from krnlyng/hori_support
joycon: add support for the hori split pad pro
2021-01-03 14:59:02 +02:00
CTCaer
1a9372b4ce nyx: Add MSC partition for L4T Android 2021-01-03 14:52:13 +02:00
CTCaer
87b91174ec nyx: Disable Flash Linux/Android buttons if partitions not found 2021-01-03 14:51:48 +02:00
CTCaer
26fff275ce nyx: Remove L4T joycon driver mitigation
Seems that this was fixed long ago
2021-01-03 14:46:42 +02:00
CTCaer
53b44a525d Refactor emmcsn_path_impl and return serial number if needed
The refactoring also makes consecutive requests instantaneous.
2021-01-03 14:45:06 +02:00
CTCaer
8ce5d55eb8 mtc: Confine RAM OC completely inside minerva
Enabling OVERCLOCK_FREQ takes care of everything without the need of changing minerva caller.
2021-01-03 14:37:39 +02:00
CTCaer
afb749560a mtc: Fix temperature deltas for clk tree delays when negative 2021-01-03 14:35:21 +02:00
CTCaer
7a66e0298a mtc: Refactor various types 2021-01-03 14:33:56 +02:00
Franz-Josef Haider
e491a4cf57 joycon: add support for the hori split pad pro 2020-12-31 13:54:00 +02:00
CTCaer
b7789f1edb xusb: Increase performance up to 96%
The default interrupt moderation on XUSB controller was causing 4.62ms latency, hurting performance tremendously, especially in smaller usb packets (which are the norm).
This change brings it to parity with USB2 controller.
2020-12-30 13:40:16 +02:00
CTCaer
4949331f4c usb: Rework timeouts
- Rework all timeouts to be more relaxed when doing big data transfers.
- Fix a bug where async transfer would timeout sooner instead of infinite tries.

Both showed up in Arch Linux, because of it's huge latency USB stack latency that can reach 1-2s.

The rework will let every OS work without adding additional wait time in the gadget loops.
2020-12-30 13:37:36 +02:00
CTCaer
2c695e9a96 ums: Refactor errors 2020-12-30 13:29:29 +02:00
CTCaer
faaf801534 nyx: Add metadata copy in partitioning and extra warns 2020-12-28 05:34:01 +02:00
CTCaer
3fa775e3ad nyx: Add burnt fuses - HOS pair info
Additionally add raw value info for ODM fuses 4, 6 and 7.
2020-12-28 05:32:23 +02:00
CTCaer
6663330de3 nyx: Split T210B01 fuse dumping for better readability 2020-12-28 05:30:34 +02:00
CTCaer
ed916360eb display: Add new panel revision 2020-12-28 05:24:42 +02:00
CTCaer
e4bc5c41ce display: Add fifo draining before requesting info
In case we got loaded from bad chainloader.
Fixes issues with incorrect display ID when fifo has left overs.
2020-12-28 05:23:33 +02:00
CTCaer
d0d943c9c3 display: Make dsi write buffer bigger 2020-12-28 05:21:21 +02:00
CTCaer
60b629e57f Move display related objects to display parrent 2020-12-28 05:19:23 +02:00
CTCaer
df80339060 mc: Simplify clock enable/reset
Additionally utilize the redirect flag.
2020-12-27 12:50:20 +02:00
CTCaer
cbbd427d3a Change coreboot error from T210B01 to Mariko
Change T210B01 name in order for users to understand that it's about Mariko.
2020-12-26 17:30:49 +02:00
CTCaer
dfcdb2e1e6 mtc: Update minerva to simplify some logic 2020-12-26 17:28:49 +02:00
CTCaer
11ca6caf5f clock: Add more defines and simplify some logic 2020-12-26 17:28:08 +02:00
CTCaer
15afdf53e4 clock: Add module actual frequency getter 2020-12-26 17:25:23 +02:00
CTCaer
d15f958b48 irq: Disable irq if not handled. 2020-12-26 17:22:56 +02:00
CTCaer
5fd3bdede7 pmc: Add defines for power rails 2020-12-26 17:20:26 +02:00
CTCaer
e2dd218f33 pmc: Add latest pmc secure scratch lock 2020-12-26 16:48:00 +02:00
CTCaer
a85891ae00 Refactor AutoRCM tools 2020-12-26 16:38:21 +02:00
CTCaer
2628044ba8 fuse: Move more parsing into its specific object 2020-12-26 16:34:12 +02:00
CTCaer
e620783a89 Add tools cleanup with parrent clean 2020-12-26 16:17:03 +02:00
CTCaer
2fba9848ae In case native GCC is missing, inform user 2020-12-20 21:34:43 +02:00
CTCaer
52c65661d8 Improve Power off by resetting all regulators 2020-12-15 19:37:52 +02:00
CTCaer
601c85c23e util: Refactor power management (reboot/power off) 2020-12-15 19:33:46 +02:00
CTCaer
9d79f39897 Bump hekate to v5.5.1 and Nyx to v0.9.7 2020-12-11 18:34:52 +02:00
CTCaer
2a7a3452ba hos: Add HOS 11.0.1 support 2020-12-11 18:24:10 +02:00
CTCaer
f1386c60af hos: Fix sleep on modchiped Erista 2020-12-11 18:22:33 +02:00
CTCaer
b6ec217484 exo: Support uart logging
This can be enabled via compile time flags or exosphere.ini.
Compile time flags override exosphere.ini
2020-12-11 18:14:00 +02:00
CTCaer
ad560b650e nyx: di: Set display id we got from bootloader 2020-12-11 17:49:06 +02:00
CTCaer
14a048a496 nyx: Add SD init info from bootloader
This shows info about the sd initialization process that happened on hekate main
2020-12-11 17:46:44 +02:00
CTCaer
ba984d02eb sdmmc: Mitigate some Phison SDs which think they are SDSC 2020-12-11 17:43:01 +02:00
CTCaer
fce59fba43 nyx: Add SD card AU info 2020-12-11 17:41:09 +02:00
CTCaer
685663dcf6 nyx: Add bis key print in console 2020-12-11 17:39:30 +02:00
CTCaer
cb61e856ad hos: Fix bis keygen for keygen rev 11 (HOS 9.1.0+) 2020-12-11 17:39:05 +02:00
CTCaer
5b8fb9fb6b Various refactoring and addition of comments 2020-12-11 17:25:59 +02:00
CTCaer
8249d9e1a2 se: Ensure aligned key/iv/ctr/hash copy 2020-12-05 20:39:17 +02:00
83 changed files with 2744 additions and 1448 deletions

View File

@@ -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)

View File

@@ -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

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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*/

View File

@@ -63,7 +63,7 @@ void lv_log_add(lv_log_level_t level, const char * file, int line, const char *
if(level >= LV_LOG_LEVEL) {
#if 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);

View File

@@ -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
}

View File

@@ -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)
{

View File

@@ -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();

View File

@@ -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();

View File

@@ -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

View File

@@ -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.

View File

@@ -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_ */

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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.

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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();

View File

@@ -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.

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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:
*

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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.

View File

@@ -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!");

View File

@@ -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)

View File

@@ -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)

View File

@@ -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;

View File

@@ -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)();

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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)));

View File

@@ -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);

View File

@@ -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;

View File

@@ -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>

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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>

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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];

View File

@@ -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;

View File

@@ -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)

View File

@@ -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)
{

View File

@@ -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)

View File

@@ -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;

View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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.
};

View File

@@ -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>

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)