mirror of
https://github.com/CTCaer/hekate.git
synced 2025-04-20 03:25:01 +00:00
Compare commits
152 commits
Author | SHA1 | Date | |
---|---|---|---|
|
3250b2e32a | ||
|
e3eee73318 | ||
|
81fb318f6b | ||
|
84f3f7d92a | ||
|
788ecb60a3 | ||
|
14413ae6bd | ||
|
1849ac6667 | ||
|
1bec721baf | ||
|
6fa844b031 | ||
|
d2fc6379c6 | ||
|
f15af01727 | ||
|
69acef4db3 | ||
|
cdc1012f50 | ||
|
63c4bdd7d9 | ||
|
0e23d0e0fd | ||
|
9463f8aa7d | ||
|
34f8692f5c | ||
|
9da5149394 | ||
|
75676a78ff | ||
|
66454b934c | ||
|
7b60c3d162 | ||
|
c422d63b64 | ||
|
0acdefb32a | ||
|
edf00d8e51 | ||
|
1a98e3a702 | ||
|
8bf3bee08b | ||
|
f2be59888b | ||
|
5c77601f7a | ||
|
9e239df39e | ||
|
b1bc6ebdd8 | ||
|
5c39d04ca2 | ||
|
85cd26e305 | ||
|
6c601ccaa5 | ||
|
0aea402632 | ||
|
280ebcc1e6 | ||
|
106a08f19c | ||
|
aacae78420 | ||
|
716cfbfbaf | ||
|
e47b6ec19b | ||
|
acb3997a7d | ||
|
4c5cc6d567 | ||
|
c321d3508c | ||
|
66303d0d47 | ||
|
80b3651d0a | ||
|
242debfe3e | ||
|
68408bbb79 | ||
|
cf954b451c | ||
|
75a4a8ba1d | ||
|
a37b5c7841 | ||
|
48334779a5 | ||
|
054c68f251 | ||
|
655209bedc | ||
|
85eb5489fe | ||
|
11262c2112 | ||
|
8b4f776c9d | ||
|
a34206df5b | ||
|
4a24fe0b35 | ||
|
14c482ddce | ||
|
8d49bc3c33 | ||
|
39c614a3ab | ||
|
7652d9cdb1 | ||
|
21d782587f | ||
|
48ef1826e9 | ||
|
4fef1890aa | ||
|
320b91a767 | ||
|
c5f6837c35 | ||
|
72f980d0f4 | ||
|
b3be7e7a41 | ||
|
26c6c6372d | ||
|
28eb3f4bcd | ||
|
bd55a3e756 | ||
|
146ff53a31 | ||
|
a96cac5964 | ||
|
b01cc2432f | ||
|
05db43a97c | ||
|
859811a154 | ||
|
0a6521ec26 | ||
|
6b54c4a477 | ||
|
e46f54d4e6 | ||
|
9d79af231e | ||
|
d933aa80f7 | ||
|
84c5439c70 | ||
|
ddd19661bd | ||
|
78cdb5575d | ||
|
8c44969afb | ||
|
7a74761da9 | ||
|
14706cef4e | ||
|
93296c2c38 | ||
|
b744f82942 | ||
|
c4567ab2b5 | ||
|
0544f9143f | ||
|
a070d2e394 | ||
|
927489d2da | ||
|
5453c593a3 | ||
|
ae29f359ee | ||
|
7af343dd6c | ||
|
547a3542ee | ||
|
4bc0a0591c | ||
|
1214ab0e02 | ||
|
985c513770 | ||
|
16eb6a3c44 | ||
|
ef1e328e11 | ||
|
856994e4f4 | ||
|
77782b974c | ||
|
38f4902e1d | ||
|
90b9f9f589 | ||
|
ec2e62236a | ||
|
2648a2655c | ||
|
62153fdfbb | ||
|
28960728f9 | ||
|
902ccede9a | ||
|
96efa7a002 | ||
|
d92906db5e | ||
|
e8d6516f43 | ||
|
a6727f6e32 | ||
|
35ea35f6ad | ||
|
9e1b2ee573 | ||
|
9cfe1d2162 | ||
|
cfbbafe72f | ||
|
5607fd18ea | ||
|
d71903abf2 | ||
|
547cfca0c9 | ||
|
dca350bfe9 | ||
|
06b7a38d47 | ||
|
9567ba19c8 | ||
|
c9ff5179f9 | ||
|
f764bf04b1 | ||
|
8b1486c74b | ||
|
471b99366d | ||
|
368ca21316 | ||
|
c021aef9b0 | ||
|
622f7124ac | ||
|
e846f4576e | ||
|
42c02e97e8 | ||
|
4b3014bc18 | ||
|
4effaab241 | ||
|
d687b53249 | ||
|
9e41aa7759 | ||
|
0100c11757 | ||
|
9ba7c44b89 | ||
|
cdf0f30b17 | ||
|
9a520d63a6 | ||
|
20e661fc01 | ||
|
e341cf39f2 | ||
|
3a4fa12f42 | ||
|
fb31cb2926 | ||
|
82925845e3 | ||
|
f126486266 | ||
|
25b7ffecd1 | ||
|
7d1600b85c | ||
|
b1e6661a7a | ||
|
83ac40c4b9 |
119 changed files with 2840 additions and 2343 deletions
4
Makefile
4
Makefile
|
@ -64,8 +64,8 @@ FFCFG_INC := '"../$(SOURCEDIR)/libs/fatfs/ffconf.h"'
|
|||
################################################################################
|
||||
|
||||
CUSTOMDEFINES := -DIPL_LOAD_ADDR=$(IPL_LOAD_ADDR) -DBL_MAGIC=$(IPL_MAGIC)
|
||||
CUSTOMDEFINES += -DBL_VER_MJ=$(BLVERSION_MAJOR) -DBL_VER_MN=$(BLVERSION_MINOR) -DBL_VER_HF=$(BLVERSION_HOTFX) -DBL_RESERVED=$(BLVERSION_RSVD)
|
||||
CUSTOMDEFINES += -DNYX_VER_MJ=$(NYXVERSION_MAJOR) -DNYX_VER_MN=$(NYXVERSION_MINOR) -DNYX_VER_HF=$(NYXVERSION_HOTFX) -DNYX_RESERVED=$(NYXVERSION_RSVD)
|
||||
CUSTOMDEFINES += -DBL_VER_MJ=$(BLVERSION_MAJOR) -DBL_VER_MN=$(BLVERSION_MINOR) -DBL_VER_HF=$(BLVERSION_HOTFX) -DBL_VER_RL=$(BLVERSION_REL)
|
||||
CUSTOMDEFINES += -DNYX_VER_MJ=$(NYXVERSION_MAJOR) -DNYX_VER_MN=$(NYXVERSION_MINOR) -DNYX_VER_HF=$(NYXVERSION_HOTFX) -DNYX_VER_RL=$(NYXVERSION_REL)
|
||||
|
||||
# BDK defines.
|
||||
CUSTOMDEFINES += -DBDK_MALLOC_NO_DEFRAG -DBDK_MC_ENABLE_AHB_REDIRECT -DBDK_EMUMMC_ENABLE
|
||||
|
|
24
README.md
24
README.md
|
@ -106,7 +106,7 @@ There are four possible type of entries. "**[ ]**": Boot entry, "**{ }**": Capti
|
|||
| emupath={FOLDER path} | Forces emuMMC to use the selected one. (=emuMMC/RAW1, =emuMMC/SD00, etc). emuMMC must be created by hekate because it uses the raw_based/file_based files. |
|
||||
| emummcforce=1 | Forces the use of emuMMC. If emummc.ini is disabled or not found, then it causes an error. |
|
||||
| emummc_force_disable=1 | Disables emuMMC, if it's enabled. |
|
||||
| stock=1 | Disables unneeded kernel patching and CFW kips when running stock or semi-stock. `If emuMMC is enabled, emummc_force_disable=1` is required. emuMMC is not supported on stock. If additional KIPs are needed other than OFW's, you can define them with `kip1` key. No kip should be used that relies on Atmosphère patching, because it will hang. If `NOGC` is needed, use `kip1patch=nogc`. |
|
||||
| stock=1 | OFW via hekate bootloader. Disables unneeded kernel patching and CFW kips when running stock. `If emuMMC is enabled, emummc_force_disable=1` is required. emuMMC is not supported on stock. If additional KIPs are needed other than OFW's, you can define them with `kip1` key. No kip should be used that relies on Atmosphère patching, because it will hang. If `NOGC` is needed, use `kip1patch=nogc`. |
|
||||
| fullsvcperm=1 | Disables SVC verification (full services permission). Doesn't work with Mesosphere as kernel. |
|
||||
| debugmode=1 | Enables Debug mode. Obsolete when used with exosphere as secmon. |
|
||||
| atmosphere=1 | Enables Atmosphère patching. Not needed when `fss0` is used. |
|
||||
|
@ -188,20 +188,26 @@ hekate has a boot storage in the binary that helps it configure it outside of BP
|
|||
|
||||
```
|
||||
hekate (c) 2018, naehrwert, st4rk.
|
||||
(c) 2018-2023, CTCaer.
|
||||
(c) 2018-2024, CTCaer.
|
||||
|
||||
Nyx GUI (c) 2019-2023, CTCaer.
|
||||
Nyx GUI (c) 2019-2024, CTCaer.
|
||||
|
||||
Thanks to: derrek, nedwill, plutoo, shuffle2, smea, thexyz, yellows8.
|
||||
Greetings to: fincs, hexkyz, SciresM, Shiny Quagsire, WinterMute.
|
||||
|
||||
Open source and free packages used:
|
||||
- FatFs R0.13a, Copyright (c) 2017, ChaN
|
||||
- bcl-1.2.0, Copyright (c) 2003-2006, Marcus Geelnard
|
||||
- Atmosphère (Exosphere types/panic, prc id kernel patches),
|
||||
Copyright (c) 2018-2019, Atmosphère-NX
|
||||
- elfload, Copyright (c) 2014 Owen Shepherd, Copyright (c) 2018 M4xw
|
||||
- Littlev Graphics Library, Copyright (c) 2016 Gabor Kiss-Vamosi
|
||||
- Littlev Graphics Library,
|
||||
Copyright (c) 2016-2018 Gabor Kiss-Vamosi
|
||||
- FatFs R0.13c,
|
||||
Copyright (c) 2006-2018, ChaN
|
||||
Copyright (c) 2018-2022, CTCaer
|
||||
- bcl-1.2.0,
|
||||
Copyright (c) 2003-2006, Marcus Geelnard
|
||||
- blz,
|
||||
Copyright (c) 2018, SciresM
|
||||
- elfload,
|
||||
Copyright (c) 2014 Owen Shepherd,
|
||||
Copyright (c) 2018 M4xw
|
||||
|
||||
___
|
||||
.-' `'.
|
||||
|
|
10
Versions.inc
10
Versions.inc
|
@ -1,11 +1,11 @@
|
|||
# IPL Version.
|
||||
BLVERSION_MAJOR := 6
|
||||
BLVERSION_MINOR := 1
|
||||
BLVERSION_HOTFX := 0
|
||||
BLVERSION_RSVD := 0
|
||||
BLVERSION_MINOR := 2
|
||||
BLVERSION_HOTFX := 2
|
||||
BLVERSION_REL := 0
|
||||
|
||||
# Nyx Version.
|
||||
NYXVERSION_MAJOR := 1
|
||||
NYXVERSION_MINOR := 6
|
||||
NYXVERSION_HOTFX := 0
|
||||
NYXVERSION_RSVD := 0
|
||||
NYXVERSION_HOTFX := 4
|
||||
NYXVERSION_REL := 0
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include <soc/gpio.h>
|
||||
#include <soc/hw_init.h>
|
||||
#include <soc/i2c.h>
|
||||
#include <soc/irq.h>
|
||||
#include <soc/kfuse.h>
|
||||
#include <soc/pinmux.h>
|
||||
#include <soc/pmc.h>
|
||||
|
@ -76,4 +77,4 @@
|
|||
|
||||
#include <gfx_utils.h>
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
227
bdk/display/di.c
227
bdk/display/di.c
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2023 CTCaer
|
||||
* Copyright (c) 2018-2024 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,
|
||||
|
@ -59,7 +59,7 @@ void display_wait_interrupt(u32 intr)
|
|||
|
||||
// Interrupts are masked. Poll status register for checking if fired.
|
||||
while (!(DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) & intr))
|
||||
;
|
||||
;
|
||||
}
|
||||
|
||||
static void _display_dsi_wait(u32 timeout, u32 off, u32 mask)
|
||||
|
@ -373,24 +373,10 @@ void display_init()
|
|||
// Get Chip ID.
|
||||
bool tegra_t210 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210;
|
||||
|
||||
// T210B01: Power on SD2 regulator for supplying LDO0.
|
||||
if (!tegra_t210)
|
||||
{
|
||||
// Set SD2 regulator voltage.
|
||||
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);
|
||||
max7762x_regulator_enable(REGULATOR_SD2, true);
|
||||
}
|
||||
|
||||
// Enable LCD DVDD.
|
||||
// Enable DSI AVDD.
|
||||
max7762x_regulator_set_voltage(REGULATOR_LDO0, 1200000);
|
||||
max7762x_regulator_enable(REGULATOR_LDO0, true);
|
||||
|
||||
if (tegra_t210)
|
||||
max77620_config_gpio(7, MAX77620_GPIO_OUTPUT_ENABLE); // T210: LD0 -> GPIO7 -> LCD.
|
||||
|
||||
// Enable Display Interface specific clocks.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_MIPI_CAL) | BIT(CLK_H_DSI);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_MIPI_CAL) | BIT(CLK_H_DSI);
|
||||
|
@ -398,10 +384,10 @@ void display_init()
|
|||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_DISP1);
|
||||
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = BIT(CLK_X_UART_FST_MIPI_CAL);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIPI_CAL) = 10; // Set PLLP_OUT3 and div 6 (17MHz).
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIPI_CAL) = CLK_SRC_DIV(6); // Set PLLP_OUT3 and div 6 (68MHz).
|
||||
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_SET) = BIT(CLK_W_DSIA_LP);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP) = 10; // Set PLLP_OUT and div 6 (68MHz).
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP) = CLK_SRC_DIV(6); // Set PLLP_OUT and div 6 (68MHz).
|
||||
|
||||
// Bring every IO rail out of deep power down.
|
||||
PMC(APBDEV_PMC_IO_DPD_REQ) = PMC_IO_DPD_REQ_DPD_OFF;
|
||||
|
@ -448,26 +434,19 @@ void display_init()
|
|||
clock_enable_plld(3, 20, true, tegra_t210);
|
||||
|
||||
// Setup Display Interface initial window configuration.
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, _di_dc_setup_win_config, CFG_SIZE(_di_dc_setup_win_config));
|
||||
reg_write_array((u32 *)DISPLAY_A_BASE, _di_dc_setup_win_config, ARRAY_SIZE(_di_dc_setup_win_config));
|
||||
|
||||
// Setup dsi init sequence packets.
|
||||
exec_cfg((u32 *)DSI_BASE, _di_dsi_init_irq_pkt_config0, CFG_SIZE(_di_dsi_init_irq_pkt_config0));
|
||||
if (tegra_t210)
|
||||
DSI(_DSIREG(DSI_INIT_SEQ_DATA_15)) = 0;
|
||||
else
|
||||
DSI(_DSIREG(DSI_INIT_SEQ_DATA_15_B01)) = 0;
|
||||
exec_cfg((u32 *)DSI_BASE, _di_dsi_init_irq_pkt_config1, CFG_SIZE(_di_dsi_init_irq_pkt_config1));
|
||||
reg_write_array((u32 *)DSI_BASE, _di_dsi_seq_pkt_reset_config0, ARRAY_SIZE(_di_dsi_seq_pkt_reset_config0));
|
||||
DSI(_DSIREG(tegra_t210 ? DSI_INIT_SEQ_DATA_15 : DSI_INIT_SEQ_DATA_15_B01)) = 0;
|
||||
reg_write_array((u32 *)DSI_BASE, _di_dsi_seq_pkt_reset_config1, ARRAY_SIZE(_di_dsi_seq_pkt_reset_config1));
|
||||
|
||||
// Reset pad trimmers for T210B01.
|
||||
if (!tegra_t210)
|
||||
exec_cfg((u32 *)DSI_BASE, _di_dsi_init_pads_t210b01, CFG_SIZE(_di_dsi_init_pads_t210b01));
|
||||
reg_write_array((u32 *)DSI_BASE, _di_dsi_init_pads_t210b01, ARRAY_SIZE(_di_dsi_init_pads_t210b01));
|
||||
|
||||
// Setup init sequence packets and timings.
|
||||
exec_cfg((u32 *)DSI_BASE, _di_dsi_init_timing_pkt_config2, CFG_SIZE(_di_dsi_init_timing_pkt_config2));
|
||||
DSI(_DSIREG(DSI_PHY_TIMING_0)) = tegra_t210 ? 0x6070601 : 0x6070603; // DSI_THSPREPR: 1 : 3.
|
||||
exec_cfg((u32 *)DSI_BASE, _di_dsi_init_timing_pwrctrl_config, CFG_SIZE(_di_dsi_init_timing_pwrctrl_config));
|
||||
DSI(_DSIREG(DSI_PHY_TIMING_0)) = tegra_t210 ? 0x6070601 : 0x6070603; // DSI_THSPREPR: 1 : 3.
|
||||
exec_cfg((u32 *)DSI_BASE, _di_dsi_init_timing_pkt_config3, CFG_SIZE(_di_dsi_init_timing_pkt_config3));
|
||||
// Setup init seq packet lengths, timings and power on DSI.
|
||||
reg_write_array((u32 *)DSI_BASE, _di_dsi_init_config, ARRAY_SIZE(_di_dsi_init_config));
|
||||
usleep(10000);
|
||||
|
||||
// Enable LCD Reset.
|
||||
|
@ -505,9 +484,9 @@ void display_init()
|
|||
{
|
||||
case PANEL_SAM_AMS699VC01:
|
||||
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 180000);
|
||||
// Set color mode to natural. Stock is Saturated (0x00). (Reset value is 0x20).
|
||||
// Set color mode to basic (natural). Stock is Saturated (0x00). (Reset value is 0x20).
|
||||
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE_PARAM,
|
||||
MIPI_DCS_PRIV_SM_SET_COLOR_MODE | (DCS_SM_COLOR_MODE_NATURAL << 8), 0);
|
||||
MIPI_DCS_PRIV_SM_SET_COLOR_MODE | (DCS_SM_COLOR_MODE_BASIC << 8), 0);
|
||||
// Enable backlight and smooth PWM.
|
||||
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE_PARAM,
|
||||
MIPI_DCS_SET_CONTROL_DISPLAY | ((DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL | DCS_CONTROL_DISPLAY_DIMMING_CTRL) << 8), 0);
|
||||
|
@ -537,7 +516,7 @@ void display_init()
|
|||
break;
|
||||
|
||||
case PANEL_JDI_XXX062M:
|
||||
exec_cfg((u32 *)DSI_BASE, _di_dsi_panel_init_config_jdi, CFG_SIZE(_di_dsi_panel_init_config_jdi));
|
||||
reg_write_array((u32 *)DSI_BASE, _di_dsi_panel_init_config_jdi, ARRAY_SIZE(_di_dsi_panel_init_config_jdi));
|
||||
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 180000);
|
||||
break;
|
||||
|
||||
|
@ -578,21 +557,24 @@ void display_init()
|
|||
clock_enable_plld(1, 24, false, tegra_t210);
|
||||
|
||||
// Finalize DSI init packet sequence configuration.
|
||||
DSI(_DSIREG(DSI_PAD_CONTROL_1)) = 0;
|
||||
DSI(_DSIREG(DSI_PHY_TIMING_0)) = tegra_t210 ? 0x6070601 : 0x6070603;
|
||||
exec_cfg((u32 *)DSI_BASE, _di_dsi_init_seq_pkt_final_config, CFG_SIZE(_di_dsi_init_seq_pkt_final_config));
|
||||
reg_write_array((u32 *)DSI_BASE, _di_dsi_seq_pkt_video_non_burst_no_eot_config, ARRAY_SIZE(_di_dsi_seq_pkt_video_non_burst_no_eot_config));
|
||||
|
||||
// Set 1-by-1 pixel/clock and pixel clock to 234 / 3 = 78 MHz. For 60 Hz refresh rate.
|
||||
DISPLAY_A(_DIREG(DC_DISP_DISP_CLOCK_CONTROL)) = PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(4); // 4: div3.
|
||||
|
||||
// Set DSI mode.
|
||||
exec_cfg((u32 *)DSI_BASE, _di_dsi_mode_config, CFG_SIZE(_di_dsi_mode_config));
|
||||
// Set DSI mode to HOST.
|
||||
reg_write_array((u32 *)DSI_BASE, _di_dsi_host_mode_config, ARRAY_SIZE(_di_dsi_host_mode_config));
|
||||
usleep(10000);
|
||||
|
||||
// Calibrate display communication pads.
|
||||
u32 loops = tegra_t210 ? 1 : 2; // Calibrate pads 2 times on T210B01.
|
||||
exec_cfg((u32 *)MIPI_CAL_BASE, _di_mipi_pad_cal_config, CFG_SIZE(_di_mipi_pad_cal_config));
|
||||
for (u32 i = 0; i < loops; i++)
|
||||
/*
|
||||
* Calibrate display communication pads.
|
||||
* When switching to the 16ff pad brick, the clock lane termination control
|
||||
* is separated from data lane termination. This change of the mipi cal
|
||||
* brings in a bug that the DSI pad clock termination code can't be loaded
|
||||
* in one time calibration. Trigger calibration twice.
|
||||
*/
|
||||
reg_write_array((u32 *)MIPI_CAL_BASE, _di_mipi_pad_cal_config, ARRAY_SIZE(_di_mipi_pad_cal_config));
|
||||
for (u32 i = 0; i < 2; i++)
|
||||
{
|
||||
// Set MIPI bias pad config.
|
||||
MIPI_CAL(_DSIREG(MIPI_CAL_MIPI_BIAS_PAD_CFG2)) = 0x10010;
|
||||
|
@ -601,22 +583,25 @@ void display_init()
|
|||
// Set pad trimmers and set MIPI DSI cal offsets.
|
||||
if (tegra_t210)
|
||||
{
|
||||
exec_cfg((u32 *)DSI_BASE, _di_dsi_pad_cal_config_t210, CFG_SIZE(_di_dsi_pad_cal_config_t210));
|
||||
exec_cfg((u32 *)MIPI_CAL_BASE, _di_mipi_dsi_cal_offsets_config_t210, CFG_SIZE(_di_mipi_dsi_cal_offsets_config_t210));
|
||||
reg_write_array((u32 *)DSI_BASE, _di_dsi_pad_cal_config_t210, ARRAY_SIZE(_di_dsi_pad_cal_config_t210));
|
||||
reg_write_array((u32 *)MIPI_CAL_BASE, _di_mipi_dsi_cal_prod_config_t210, ARRAY_SIZE(_di_mipi_dsi_cal_prod_config_t210));
|
||||
}
|
||||
else
|
||||
{
|
||||
exec_cfg((u32 *)DSI_BASE, _di_dsi_pad_cal_config_t210b01, CFG_SIZE(_di_dsi_pad_cal_config_t210b01));
|
||||
exec_cfg((u32 *)MIPI_CAL_BASE, _di_mipi_dsi_cal_offsets_config_t210b01, CFG_SIZE(_di_mipi_dsi_cal_offsets_config_t210b01));
|
||||
reg_write_array((u32 *)DSI_BASE, _di_dsi_pad_cal_config_t210b01, ARRAY_SIZE(_di_dsi_pad_cal_config_t210b01));
|
||||
reg_write_array((u32 *)MIPI_CAL_BASE, _di_mipi_dsi_cal_prod_config_t210b01, ARRAY_SIZE(_di_mipi_dsi_cal_prod_config_t210b01));
|
||||
}
|
||||
|
||||
// Reset all MIPI cal offsets and start calibration.
|
||||
exec_cfg((u32 *)MIPI_CAL_BASE, _di_mipi_start_dsi_cal_config, CFG_SIZE(_di_mipi_start_dsi_cal_config));
|
||||
// Reset all unused MIPI cal offsets.
|
||||
reg_write_array((u32 *)MIPI_CAL_BASE, _di_mipi_dsi_cal_unused_config, ARRAY_SIZE(_di_mipi_dsi_cal_unused_config));
|
||||
|
||||
// Set Prescale/filter and start calibration.
|
||||
MIPI_CAL(_DSIREG(MIPI_CAL_MIPI_CAL_CTRL)) = 0x2A000001;
|
||||
}
|
||||
usleep(10000);
|
||||
|
||||
// Enable video display controller.
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, _di_dc_video_enable_config, CFG_SIZE(_di_dc_video_enable_config));
|
||||
reg_write_array((u32 *)DISPLAY_A_BASE, _di_dc_video_enable_config, ARRAY_SIZE(_di_dc_video_enable_config));
|
||||
}
|
||||
|
||||
void display_backlight_pwm_init()
|
||||
|
@ -624,12 +609,15 @@ void display_backlight_pwm_init()
|
|||
if (_display_id == PANEL_SAM_AMS699VC01)
|
||||
return;
|
||||
|
||||
// Enable PWM clock.
|
||||
clock_enable_pwm();
|
||||
|
||||
// Enable PWM and set it to 25KHz PFM. 29.5KHz is stock.
|
||||
PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN;
|
||||
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & ~PINMUX_FUNC_MASK) | 1; // Set PWM0 mode.
|
||||
usleep(2);
|
||||
|
||||
gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight power mode.
|
||||
}
|
||||
|
||||
|
@ -650,9 +638,9 @@ static void _display_dsi_backlight_brightness(u32 duty)
|
|||
u16 bl_ctrl = byte_swap_16((u16)candela);
|
||||
display_dsi_vblank_write(MIPI_DCS_SET_BRIGHTNESS, 2, &bl_ctrl);
|
||||
|
||||
// Wait for backlight to completely turn off. 6+1 frames.
|
||||
// Wait for backlight to completely turn off. 6 frames.
|
||||
if (!duty)
|
||||
usleep(120000);
|
||||
usleep(100000);
|
||||
|
||||
_dsi_bl = duty;
|
||||
}
|
||||
|
@ -696,7 +684,10 @@ void display_backlight_brightness(u32 brightness, u32 step_delay)
|
|||
|
||||
u32 display_get_backlight_brightness()
|
||||
{
|
||||
return ((PWM(PWM_CONTROLLER_PWM_CSR_0) >> 16) & 0xFF);
|
||||
if (_display_id != PANEL_SAM_AMS699VC01)
|
||||
return ((PWM(PWM_CONTROLLER_PWM_CSR_0) >> 16) & 0xFF);
|
||||
else
|
||||
return _dsi_bl;
|
||||
}
|
||||
|
||||
static void _display_panel_and_hw_end(bool no_panel_deinit)
|
||||
|
@ -713,14 +704,15 @@ static void _display_panel_and_hw_end(bool no_panel_deinit)
|
|||
DSI(_DSIREG(DSI_WR_DATA)) = (MIPI_DCS_SET_DISPLAY_OFF << 8) | MIPI_DSI_DCS_SHORT_WRITE;
|
||||
|
||||
// Wait for 5 frames (HOST1X_CH0_SYNC_SYNCPT_9).
|
||||
// Not here.
|
||||
// Not here. Wait for 1 frame manually.
|
||||
usleep(20000);
|
||||
|
||||
// Propagate changes to all register buffers and disable host cmd packets during video.
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_ACCESS)) = READ_MUX | WRITE_MUX;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_ACCESS)) = READ_MUX_ACTIVE | WRITE_MUX_ACTIVE;
|
||||
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 0;
|
||||
|
||||
// De-initialize video controller.
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, _di_dc_video_disable_config, CFG_SIZE(_di_dc_video_disable_config));
|
||||
reg_write_array((u32 *)DISPLAY_A_BASE, _di_dc_video_disable_config, ARRAY_SIZE(_di_dc_video_disable_config));
|
||||
|
||||
// Set DISP1 clock source, parent clock and DSI/PCLK to low power mode.
|
||||
// T210: DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 100.0 MHz, PLLD_OUT0 (DSI-PCLK): 50.0 MHz. (PCLK: 16.66 MHz)
|
||||
|
@ -728,7 +720,7 @@ static void _display_panel_and_hw_end(bool no_panel_deinit)
|
|||
clock_enable_plld(3, 20, true, hw_get_chip_id() == GP_HIDREV_MAJOR_T210);
|
||||
|
||||
// Set timings for lowpower clocks.
|
||||
exec_cfg((u32 *)DSI_BASE, _di_dsi_timing_deinit_config, CFG_SIZE(_di_dsi_timing_deinit_config));
|
||||
reg_write_array((u32 *)DSI_BASE, _di_dsi_timing_deinit_config, ARRAY_SIZE(_di_dsi_timing_deinit_config));
|
||||
|
||||
if (_display_id != PANEL_SAM_AMS699VC01)
|
||||
usleep(10000);
|
||||
|
@ -737,11 +729,12 @@ static void _display_panel_and_hw_end(bool no_panel_deinit)
|
|||
switch (_display_id)
|
||||
{
|
||||
case PANEL_JDI_XXX062M:
|
||||
exec_cfg((u32 *)DSI_BASE, _di_dsi_panel_deinit_config_jdi, CFG_SIZE(_di_dsi_panel_deinit_config_jdi));
|
||||
reg_write_array((u32 *)DSI_BASE, _di_dsi_panel_deinit_config_jdi, ARRAY_SIZE(_di_dsi_panel_deinit_config_jdi));
|
||||
break;
|
||||
|
||||
case PANEL_AUO_A062TAN01:
|
||||
exec_cfg((u32 *)DSI_BASE, _di_dsi_panel_deinit_config_auo, CFG_SIZE(_di_dsi_panel_deinit_config_auo));
|
||||
reg_write_array((u32 *)DSI_BASE, _di_dsi_panel_deinit_config_auo, ARRAY_SIZE(_di_dsi_panel_deinit_config_auo));
|
||||
usleep(5000);
|
||||
break;
|
||||
|
||||
case PANEL_INL_2J055IA_27A:
|
||||
|
@ -796,6 +789,10 @@ skip_panel_deinit:
|
|||
{
|
||||
gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_LOW); // LCD AVDD -5.4V disable.
|
||||
gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_LOW); // LCD AVDD +5.4V disable.
|
||||
|
||||
// Make sure LCD PWM backlight pin is in PWM0 mode.
|
||||
gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight PWM.
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = PINMUX_TRISTATE | PINMUX_PULL_DOWN | 1; // Set PWM0 mode.
|
||||
}
|
||||
usleep(10000);
|
||||
|
||||
|
@ -810,14 +807,7 @@ skip_panel_deinit:
|
|||
DSI_PAD_CONTROL_VS1_PDIO_CLK | DSI_PAD_CONTROL_VS1_PDIO(0xF);
|
||||
DSI(_DSIREG(DSI_POWER_CONTROL)) = 0;
|
||||
|
||||
// Switch LCD PWM backlight pin to special function mode and enable PWM0 mode.
|
||||
if (!_nx_aula)
|
||||
{
|
||||
gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight PWM.
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = PINMUX_TRISTATE | PINMUX_PULL_DOWN | 1; // Set PWM0 mode.
|
||||
}
|
||||
|
||||
// Disable LCD DVDD.
|
||||
// Disable DSI AVDD.
|
||||
max7762x_regulator_enable(REGULATOR_LDO0, false);
|
||||
}
|
||||
|
||||
|
@ -846,14 +836,15 @@ void display_set_decoded_panel_id(u32 id)
|
|||
|
||||
void display_color_screen(u32 color)
|
||||
{
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, _di_win_one_color, CFG_SIZE(_di_win_one_color));
|
||||
// Disable all windows.
|
||||
reg_write_array((u32 *)DISPLAY_A_BASE, _di_win_one_color, ARRAY_SIZE(_di_win_one_color));
|
||||
|
||||
// Configure display to show single color.
|
||||
DISPLAY_A(_DIREG(DC_WIN_AD_WIN_OPTIONS)) = 0;
|
||||
DISPLAY_A(_DIREG(DC_WIN_BD_WIN_OPTIONS)) = 0;
|
||||
DISPLAY_A(_DIREG(DC_WIN_CD_WIN_OPTIONS)) = 0;
|
||||
DISPLAY_A(_DIREG(DC_DISP_BLEND_BACKGROUND_COLOR)) = color;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = (DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) & 0xFFFFFFFE) | GENERAL_ACT_REQ;
|
||||
|
||||
// Arm and activate changes.
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE | WIN_D_UPDATE;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ | WIN_D_ACT_REQ;
|
||||
usleep(35000); // Wait 2 frames. No need on Aula.
|
||||
|
||||
if (_display_id != PANEL_SAM_AMS699VC01)
|
||||
|
@ -862,58 +853,108 @@ void display_color_screen(u32 color)
|
|||
display_backlight_brightness(150, 0);
|
||||
}
|
||||
|
||||
u32 *display_init_framebuffer_pitch()
|
||||
u32 *display_init_window_a_pitch()
|
||||
{
|
||||
// Sanitize framebuffer area.
|
||||
memset((u32 *)IPL_FB_ADDRESS, 0, IPL_FB_SZ);
|
||||
|
||||
// This configures the framebuffer @ IPL_FB_ADDRESS with a resolution of 720x1280 (line stride 720).
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, _di_win_framebuffer_pitch, CFG_SIZE(_di_win_framebuffer_pitch));
|
||||
reg_write_array((u32 *)DISPLAY_A_BASE, _di_winA_pitch, ARRAY_SIZE(_di_winA_pitch));
|
||||
//usleep(35000); // Wait 2 frames. No need on Aula.
|
||||
|
||||
return (u32 *)DISPLAY_A(_DIREG(DC_WINBUF_START_ADDR));
|
||||
}
|
||||
|
||||
u32 *display_init_framebuffer_pitch_vic()
|
||||
u32 *display_init_window_a_pitch_vic()
|
||||
{
|
||||
// This configures the framebuffer @ NYX_FB_ADDRESS with a resolution of 720x1280 (line stride 720).
|
||||
if (_display_id != PANEL_SAM_AMS699VC01)
|
||||
usleep(8000); // Wait half frame for PWM to apply.
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, _di_win_framebuffer_pitch_vic, CFG_SIZE(_di_win_framebuffer_pitch_vic));
|
||||
reg_write_array((u32 *)DISPLAY_A_BASE, _di_winA_pitch_vic, ARRAY_SIZE(_di_winA_pitch_vic));
|
||||
if (_display_id != PANEL_SAM_AMS699VC01)
|
||||
usleep(35000); // Wait 2 frames.
|
||||
|
||||
return (u32 *)DISPLAY_A(_DIREG(DC_WINBUF_START_ADDR));
|
||||
}
|
||||
|
||||
u32 *display_init_framebuffer_pitch_inv()
|
||||
u32 *display_init_window_a_pitch_inv()
|
||||
{
|
||||
// This configures the framebuffer @ NYX_FB_ADDRESS with a resolution of 720x1280 (line stride 720).
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, _di_win_framebuffer_pitch_inv, CFG_SIZE(_di_win_framebuffer_pitch_inv));
|
||||
reg_write_array((u32 *)DISPLAY_A_BASE, _di_winA_pitch_inv, ARRAY_SIZE(_di_winA_pitch_inv));
|
||||
usleep(35000); // Wait 2 frames. No need on Aula.
|
||||
|
||||
return (u32 *)DISPLAY_A(_DIREG(DC_WINBUF_START_ADDR));
|
||||
}
|
||||
|
||||
u32 *display_init_framebuffer_block()
|
||||
u32 *display_init_window_a_block()
|
||||
{
|
||||
// This configures the framebuffer @ NYX_FB_ADDRESS with a resolution of 720x1280.
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, _di_win_framebuffer_block, CFG_SIZE(_di_win_framebuffer_block));
|
||||
reg_write_array((u32 *)DISPLAY_A_BASE, _di_winA_block, ARRAY_SIZE(_di_winA_block));
|
||||
usleep(35000); // Wait 2 frames. No need on Aula.
|
||||
|
||||
return (u32 *)DISPLAY_A(_DIREG(DC_WINBUF_START_ADDR));
|
||||
}
|
||||
|
||||
u32 *display_init_framebuffer_log()
|
||||
u32 *display_init_window_d_console()
|
||||
{
|
||||
// This configures the framebuffer @ LOG_FB_ADDRESS with a resolution of 1280x720 (line stride 720).
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, _di_win_framebuffer_log, CFG_SIZE(_di_win_framebuffer_log));
|
||||
reg_write_array((u32 *)DISPLAY_A_BASE, _di_winD_log, ARRAY_SIZE(_di_winD_log));
|
||||
|
||||
return (u32 *)DISPLAY_A(_DIREG(DC_WINBUF_START_ADDR));
|
||||
}
|
||||
|
||||
void display_activate_console()
|
||||
void display_window_disable(u32 window)
|
||||
{
|
||||
// Select window C.
|
||||
DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = BIT(WINDOW_SELECT + window);
|
||||
|
||||
// Disable window C.
|
||||
DISPLAY_A(_DIREG(DC_WIN_WIN_OPTIONS)) = 0;
|
||||
|
||||
// Arm and activate changes.
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | BIT(WIN_UPDATE + window);
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | BIT(WIN_ACT_REQ + window);
|
||||
}
|
||||
|
||||
void display_set_framebuffer(u32 window, void *fb)
|
||||
{
|
||||
// Select window.
|
||||
DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = BIT(WINDOW_SELECT + window);
|
||||
|
||||
// Set new fb address.
|
||||
DISPLAY_A(_DIREG(DC_WINBUF_START_ADDR)) = (u32)fb;
|
||||
|
||||
// Arm and activate changes.
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | BIT(WIN_UPDATE + window);
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | BIT(WIN_ACT_REQ + window);
|
||||
}
|
||||
|
||||
void display_move_framebuffer(u32 window, void *fb)
|
||||
{
|
||||
// Select window.
|
||||
DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = BIT(WINDOW_SELECT + window);
|
||||
|
||||
// Get current framebuffer address.
|
||||
const void *fb_curr = (void *)DISPLAY_A(_DIREG(DC_WINBUF_START_ADDR));
|
||||
u32 win_size = DISPLAY_A(_DIREG(DC_WIN_PRESCALED_SIZE));
|
||||
win_size = (win_size & 0x7FFF) * ((win_size >> 16) & 0x1FFF);
|
||||
|
||||
// Copy fb over.
|
||||
memcpy(fb, fb_curr, win_size);
|
||||
|
||||
// Set new fb address.
|
||||
DISPLAY_A(_DIREG(DC_WINBUF_START_ADDR)) = (u32)fb;
|
||||
|
||||
// Arm and activate changes.
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | BIT(WIN_UPDATE + window);
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | BIT(WIN_ACT_REQ + window);
|
||||
}
|
||||
|
||||
void display_window_d_console_enable()
|
||||
{
|
||||
// Only update active registers on vsync.
|
||||
DISPLAY_A(_DIREG(DC_CMD_REG_ACT_CONTROL)) = DISPLAY_A(_DIREG(DC_CMD_REG_ACT_CONTROL)) & ~WIN_D_ACT_HCNTR_SEL;
|
||||
|
||||
// Select window D.
|
||||
DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = WINDOW_D_SELECT;
|
||||
|
||||
|
@ -942,12 +983,9 @@ void display_activate_console()
|
|||
// Arm and activate changes.
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_D_ACT_REQ;
|
||||
|
||||
// Re-select window A.
|
||||
DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = WINDOW_A_SELECT;
|
||||
}
|
||||
|
||||
void display_deactivate_console()
|
||||
void display_window_d_console_disable()
|
||||
{
|
||||
// Select window D.
|
||||
DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = WINDOW_D_SELECT;
|
||||
|
@ -965,18 +1003,15 @@ void display_deactivate_console()
|
|||
}
|
||||
|
||||
// Disable window D.
|
||||
DISPLAY_A(_DIREG(DC_WIN_POSITION)) = 0;
|
||||
DISPLAY_A(_DIREG(DC_WIN_POSITION)) = 0;
|
||||
DISPLAY_A(_DIREG(DC_WIN_WIN_OPTIONS)) = 0;
|
||||
|
||||
// Arm and activate changes.
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_D_ACT_REQ;
|
||||
|
||||
// Re-select window A.
|
||||
DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = WINDOW_A_SELECT;
|
||||
}
|
||||
|
||||
void display_init_cursor(void *crs_fb, u32 size)
|
||||
void display_cursor_init(void *crs_fb, u32 size)
|
||||
{
|
||||
// Setup cursor.
|
||||
DISPLAY_A(_DIREG(DC_DISP_CURSOR_START_ADDR)) = CURSOR_CLIPPING(CURSOR_CLIP_WIN_A) | size | ((u32)crs_fb >> 10);
|
||||
|
@ -992,7 +1027,7 @@ void display_init_cursor(void *crs_fb, u32 size)
|
|||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | CURSOR_ACT_REQ;
|
||||
}
|
||||
|
||||
void display_set_pos_cursor(u32 x, u32 y)
|
||||
void display_cursor_set_pos(u32 x, u32 y)
|
||||
{
|
||||
// Set cursor position.
|
||||
DISPLAY_A(_DIREG(DC_DISP_CURSOR_POSITION)) = x | (y << 16);
|
||||
|
@ -1002,7 +1037,7 @@ void display_set_pos_cursor(u32 x, u32 y)
|
|||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | CURSOR_ACT_REQ;
|
||||
}
|
||||
|
||||
void display_deinit_cursor()
|
||||
void display_cursor_deinit()
|
||||
{
|
||||
DISPLAY_A(_DIREG(DC_DISP_BLEND_CURSOR_CONTROL)) = 0;
|
||||
DISPLAY_A(_DIREG(DC_DISP_DISP_WIN_OPTIONS)) &= ~CURSOR_ENABLE;
|
||||
|
|
213
bdk/display/di.h
213
bdk/display/di.h
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2023 CTCaer
|
||||
* Copyright (c) 2018-2024 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
|
@ -24,6 +24,11 @@
|
|||
#define DSI_VIDEO_DISABLED 0
|
||||
#define DSI_VIDEO_ENABLED 1
|
||||
|
||||
#define WINDOW_A 0
|
||||
#define WINDOW_B 1
|
||||
#define WINDOW_C 2
|
||||
#define WINDOW_D 3
|
||||
|
||||
/*! Display registers. */
|
||||
#define _DIREG(reg) ((reg) * 4)
|
||||
|
||||
|
@ -43,8 +48,8 @@
|
|||
|
||||
// DC_CMD non-shadowed command/sync registers.
|
||||
#define DC_CMD_GENERAL_INCR_SYNCPT 0x00
|
||||
#define SYNCPT_GENERAL_INDX(x) (((x) & 0xff) << 0)
|
||||
#define SYNCPT_GENERAL_COND(x) (((x) & 0xff) << 8)
|
||||
#define SYNCPT_GENERAL_INDX(x) (((x) & 0xFF) << 0)
|
||||
#define SYNCPT_GENERAL_COND(x) (((x) & 0xFF) << 8)
|
||||
#define COND_REG_WR_SAFE 3
|
||||
|
||||
#define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL 0x01
|
||||
|
@ -52,7 +57,7 @@
|
|||
#define SYNCPT_CNTRL_NO_STALL BIT(8)
|
||||
|
||||
#define DC_CMD_CONT_SYNCPT_VSYNC 0x28
|
||||
#define SYNCPT_VSYNC_INDX(x) (((x) & 0xff) << 0)
|
||||
#define SYNCPT_VSYNC_INDX(x) (((x) & 0xFF) << 0)
|
||||
#define SYNCPT_VSYNC_ENABLE BIT(8)
|
||||
|
||||
#define DC_CMD_DISPLAY_COMMAND_OPTION0 0x031
|
||||
|
@ -77,19 +82,24 @@
|
|||
#define DC_CMD_INT_ENABLE 0x39
|
||||
#define DC_CMD_INT_FRAME_END_INT BIT(1)
|
||||
#define DC_CMD_INT_V_BLANK_INT BIT(2)
|
||||
#define DC_CMD_INT_POLARITY 0x3B
|
||||
|
||||
#define DC_CMD_STATE_ACCESS 0x40
|
||||
#define READ_MUX BIT(0)
|
||||
#define WRITE_MUX BIT(2)
|
||||
#define READ_MUX_ASSEMBLY 0x0
|
||||
#define WRITE_MUX_ASSEMBLY 0x0
|
||||
#define READ_MUX_ACTIVE BIT(0)
|
||||
#define WRITE_MUX_ACTIVE BIT(2)
|
||||
|
||||
#define DC_CMD_STATE_CONTROL 0x41
|
||||
#define GENERAL_ACT_REQ BIT(0)
|
||||
#define WIN_ACT_REQ 1
|
||||
#define WIN_A_ACT_REQ BIT(1)
|
||||
#define WIN_B_ACT_REQ BIT(2)
|
||||
#define WIN_C_ACT_REQ BIT(3)
|
||||
#define WIN_D_ACT_REQ BIT(4)
|
||||
#define CURSOR_ACT_REQ BIT(7)
|
||||
#define GENERAL_UPDATE BIT(8)
|
||||
#define WIN_UPDATE 9
|
||||
#define WIN_A_UPDATE BIT(9)
|
||||
#define WIN_B_UPDATE BIT(10)
|
||||
#define WIN_C_UPDATE BIT(11)
|
||||
|
@ -98,6 +108,7 @@
|
|||
#define NC_HOST_TRIG BIT(24)
|
||||
|
||||
#define DC_CMD_DISPLAY_WINDOW_HEADER 0x42
|
||||
#define WINDOW_SELECT 4
|
||||
#define WINDOW_A_SELECT BIT(4)
|
||||
#define WINDOW_B_SELECT BIT(5)
|
||||
#define WINDOW_C_SELECT BIT(6)
|
||||
|
@ -137,6 +148,31 @@
|
|||
#define DC_COM_PIN_OUTPUT_POLARITY(x) (0x306 + (x))
|
||||
#define LSC0_OUTPUT_POLARITY_LOW BIT(24)
|
||||
|
||||
// CMU registers.
|
||||
#define DC_COM_CMU_CSC_KRR 0x32A
|
||||
#define DC_COM_CMU_CSC_KGR 0x32B
|
||||
#define DC_COM_CMU_CSC_KBR 0x32C
|
||||
#define DC_COM_CMU_CSC_KRG 0x32D
|
||||
#define DC_COM_CMU_CSC_KGG 0x32E
|
||||
#define DC_COM_CMU_CSC_KBG 0x32F
|
||||
#define DC_COM_CMU_CSC_KRB 0x330
|
||||
#define DC_COM_CMU_CSC_KGB 0x331
|
||||
#define DC_COM_CMU_CSC_KBB 0x332
|
||||
#define DC_COM_CMU_LUT1 0x336
|
||||
#define LUT1_ADDR(x) ((x) & 0xFF)
|
||||
#define LUT1_DATA(x) (((x) & 0xFFF) << 16)
|
||||
#define LUT1_READ_DATA(x) (((x) >> 16) & 0xFFF)
|
||||
#define DC_COM_CMU_LUT2 0x337
|
||||
#define LUT2_ADDR(x) ((x) & 0x3FF)
|
||||
#define LUT2_DATA(x) (((x) & 0xFF) << 16)
|
||||
#define LUT2_READ_DATA(x) (((x) >> 16) & 0xFF)
|
||||
#define DC_COM_CMU_LUT1_READ 0x338
|
||||
#define LUT1_READ_ADDR(x) (((x) & 0xFF) << 8)
|
||||
#define LUT1_READ_EN BIT(0)
|
||||
#define DC_COM_CMU_LUT2_READ 0x339
|
||||
#define LUT2_READ_ADDR(x) (((x) & 0x3FF) << 8)
|
||||
#define LUT2_READ_EN BIT(0)
|
||||
|
||||
#define DC_COM_DSC_TOP_CTL 0x33E
|
||||
|
||||
// DC_DISP shadowed registers.
|
||||
|
@ -153,30 +189,30 @@
|
|||
#define DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER 0x404
|
||||
|
||||
#define DC_DISP_DISP_TIMING_OPTIONS 0x405
|
||||
#define VSYNC_H_POSITION(x) (((x) & 0x1fff) << 0)
|
||||
#define VSYNC_H_POSITION(x) (((x) & 0x1FFF) << 0)
|
||||
|
||||
#define DC_DISP_REF_TO_SYNC 0x406
|
||||
#define H_REF_TO_SYNC(x) (((x) & 0x1fff) << 0) // Min 0 pixel clock.
|
||||
#define V_REF_TO_SYNC(x) (((x) & 0x1fff) << 16) // Min 1 line clock.
|
||||
#define H_REF_TO_SYNC(x) (((x) & 0x1FFF) << 0) // Min 0 pixel clock.
|
||||
#define V_REF_TO_SYNC(x) (((x) & 0x1FFF) << 16) // Min 1 line clock.
|
||||
|
||||
#define DC_DISP_SYNC_WIDTH 0x407
|
||||
#define H_SYNC_WIDTH(x) (((x) & 0x1fff) << 0) // Min 1 pixel clock.
|
||||
#define V_SYNC_WIDTH(x) (((x) & 0x1fff) << 16) // Min 1 line clock.
|
||||
#define H_SYNC_WIDTH(x) (((x) & 0x1FFF) << 0) // Min 1 pixel clock.
|
||||
#define V_SYNC_WIDTH(x) (((x) & 0x1FFF) << 16) // Min 1 line clock.
|
||||
|
||||
#define DC_DISP_BACK_PORCH 0x408
|
||||
#define H_BACK_PORCH(x) (((x) & 0x1fff) << 0)
|
||||
#define V_BACK_PORCH(x) (((x) & 0x1fff) << 16)
|
||||
#define H_BACK_PORCH(x) (((x) & 0x1FFF) << 0)
|
||||
#define V_BACK_PORCH(x) (((x) & 0x1FFF) << 16)
|
||||
|
||||
#define DC_DISP_ACTIVE 0x409
|
||||
#define H_DISP_ACTIVE(x) (((x) & 0x1fff) << 0) // Min 16 pixel clock.
|
||||
#define V_DISP_ACTIVE(x) (((x) & 0x1fff) << 16) // Min 16 line clock.
|
||||
#define H_DISP_ACTIVE(x) (((x) & 0x1FFF) << 0) // Min 16 pixel clock.
|
||||
#define V_DISP_ACTIVE(x) (((x) & 0x1FFF) << 16) // Min 16 line clock.
|
||||
|
||||
#define DC_DISP_FRONT_PORCH 0x40A
|
||||
#define H_FRONT_PORCH(x) (((x) & 0x1fff) << 0) // Min -=PS_=-H_REF_TO_SYNC + 1
|
||||
#define V_FRONT_PORCH(x) (((x) & 0x1fff) << 16) // Min -=PS_=-V_REF_TO_SYNC + 1
|
||||
#define H_FRONT_PORCH(x) (((x) & 0x1FFF) << 0) // Min -=PS_=-H_REF_TO_SYNC + 1
|
||||
#define V_FRONT_PORCH(x) (((x) & 0x1FFF) << 16) // Min -=PS_=-V_REF_TO_SYNC + 1
|
||||
|
||||
#define DC_DISP_DISP_CLOCK_CONTROL 0x42E
|
||||
#define SHIFT_CLK_DIVIDER(x) ((x) & 0xff)
|
||||
#define SHIFT_CLK_DIVIDER(x) ((x) & 0xFF)
|
||||
#define PIXEL_CLK_DIVIDER_PCD1 (0 << 8)
|
||||
#define PIXEL_CLK_DIVIDER_PCD1H (1 << 8)
|
||||
#define PIXEL_CLK_DIVIDER_PCD2 (2 << 8)
|
||||
|
@ -207,11 +243,7 @@
|
|||
#define DISP_ORDER_BLUE_RED (1 << 9)
|
||||
|
||||
#define DC_DISP_DISP_COLOR_CONTROL 0x430
|
||||
#define DITHER_CONTROL_MASK (3 << 8)
|
||||
#define DITHER_CONTROL_DISABLE (0 << 8)
|
||||
#define DITHER_CONTROL_ORDERED (2 << 8)
|
||||
#define DITHER_CONTROL_ERRDIFF (3 << 8)
|
||||
#define BASE_COLOR_SIZE_MASK (0xf << 0)
|
||||
#define BASE_COLOR_SIZE_MASK (0xF << 0)
|
||||
#define BASE_COLOR_SIZE_666 (0 << 0)
|
||||
#define BASE_COLOR_SIZE_111 (1 << 0)
|
||||
#define BASE_COLOR_SIZE_222 (2 << 0)
|
||||
|
@ -221,6 +253,13 @@
|
|||
#define BASE_COLOR_SIZE_565 (6 << 0)
|
||||
#define BASE_COLOR_SIZE_332 (7 << 0)
|
||||
#define BASE_COLOR_SIZE_888 (8 << 0)
|
||||
#define DITHER_CONTROL_MASK (3 << 8)
|
||||
#define DITHER_CONTROL_DISABLE (0 << 8)
|
||||
#define DITHER_CONTROL_ORDERED (2 << 8)
|
||||
#define DITHER_CONTROL_ERRDIFF (3 << 8)
|
||||
#define DISP_COLOR_SWAP BIT(16)
|
||||
#define BLANK_COLOR_WHITE BIT(17)
|
||||
#define CMU_ENABLE BIT(20)
|
||||
|
||||
#define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431
|
||||
#define SC0_H_QUALIFIER_NONE BIT(0)
|
||||
|
@ -242,6 +281,7 @@
|
|||
#define CURSOR_COLOR(r,g,b) (((r) & 0xFF) | (((g) & 0xFF) << 8) | (((b) & 0xFF) << 16))
|
||||
|
||||
#define DC_DISP_CURSOR_START_ADDR 0x43E
|
||||
#define DC_DISP_CURSOR_START_ADDR_NS 0x43F
|
||||
#define CURSOR_CLIPPING(w) ((w) << 28)
|
||||
#define CURSOR_CLIP_WIN_A 1
|
||||
#define CURSOR_CLIP_WIN_B 2
|
||||
|
@ -253,6 +293,7 @@
|
|||
#define DC_DISP_CURSOR_POSITION 0x440
|
||||
#define DC_DISP_BLEND_BACKGROUND_COLOR 0x4E4
|
||||
#define DC_DISP_CURSOR_START_ADDR_HI 0x4EC
|
||||
#define DC_DISP_CURSOR_START_ADDR_HI_NS 0x4ED
|
||||
#define DC_DISP_BLEND_CURSOR_CONTROL 0x4F1
|
||||
#define CURSOR_BLEND_2BIT (0 << 24)
|
||||
#define CURSOR_BLEND_R8G8B8A8 (1 << 24)
|
||||
|
@ -269,17 +310,22 @@
|
|||
#define DC_DISP_BLEND_BACKGROUND_COLOR 0x4E4
|
||||
|
||||
#define DC_WINC_COLOR_PALETTE 0x500
|
||||
#define DC_WINC_COLOR_PALETTE_IDX(off) (DC_WINC_COLOR_PALETTE + (off))
|
||||
#define COLOR_PALETTE_IDX(off) (DC_WINC_COLOR_PALETTE + (off))
|
||||
#define COLOR_PALETTE_RGB(rgb) (byte_swap_32(rgb) >> 8)
|
||||
#define DC_WINC_PALETTE_COLOR_EXT 0x600
|
||||
|
||||
#define DC_WIN_CSC_YOF 0x611
|
||||
#define DC_WIN_CSC_KYRGB 0x612
|
||||
#define DC_WIN_CSC_KUR 0x613
|
||||
#define DC_WIN_CSC_KVR 0x614
|
||||
#define DC_WIN_CSC_KUG 0x615
|
||||
#define DC_WIN_CSC_KVG 0x616
|
||||
#define DC_WIN_CSC_KUB 0x617
|
||||
#define DC_WIN_CSC_KVB 0x618
|
||||
#define DC_WINC_H_FILTER_P(p) (0x601 + (p))
|
||||
#define DC_WINC_V_FILTER_P(p) (0x619 + (p))
|
||||
#define DC_WINC_H_FILTER_HI_P(p) (0x629 + (p))
|
||||
|
||||
#define DC_WINC_CSC_YOF 0x611
|
||||
#define DC_WINC_CSC_KYRGB 0x612
|
||||
#define DC_WINC_CSC_KUR 0x613
|
||||
#define DC_WINC_CSC_KVR 0x614
|
||||
#define DC_WINC_CSC_KUG 0x615
|
||||
#define DC_WINC_CSC_KVG 0x616
|
||||
#define DC_WINC_CSC_KUB 0x617
|
||||
#define DC_WINC_CSC_KVB 0x618
|
||||
#define DC_WIN_AD_WIN_OPTIONS 0xB80
|
||||
#define DC_WIN_BD_WIN_OPTIONS 0xD80
|
||||
#define DC_WIN_CD_WIN_OPTIONS 0xF80
|
||||
|
@ -290,15 +336,17 @@
|
|||
#define V_DIRECTION BIT(2)
|
||||
#define SCAN_COLUMN BIT(4)
|
||||
#define COLOR_EXPAND BIT(6)
|
||||
#define H_FILTER_ENABLE BIT(8)
|
||||
#define V_FILTER_ENABLE BIT(10)
|
||||
#define COLOR_PALETTE_ENABLE BIT(16)
|
||||
#define CSC_ENABLE BIT(18)
|
||||
#define DV_ENABLE BIT(20)
|
||||
#define WIN_ENABLE BIT(30)
|
||||
#define H_FILTER_EXPAND BIT(31)
|
||||
|
||||
#define DC_WIN_BUFFER_CONTROL 0x702
|
||||
#define BUFFER_CONTROL_HOST 0
|
||||
#define BUFFER_CONTROL_VI 1
|
||||
#define BUFFER_CONTROL_EPP 2
|
||||
#define BUFFER_CONTROL_MPEGE 3
|
||||
#define BUFFER_CONTROL_SB2D 4
|
||||
|
||||
#define DC_WIN_COLOR_DEPTH 0x703
|
||||
|
@ -324,6 +372,10 @@
|
|||
#define WIN_COLOR_DEPTH_YUV422R 0x17
|
||||
#define WIN_COLOR_DEPTH_YCbCr422RA 0x18
|
||||
#define WIN_COLOR_DEPTH_YUV422RA 0x19
|
||||
#define WIN_COLOR_DEPTH_X1R5G5B5 0x1E
|
||||
#define WIN_COLOR_DEPTH_R5G5B5X1 0x1F
|
||||
#define WIN_COLOR_DEPTH_X1B5G5R5 0x20
|
||||
#define WIN_COLOR_DEPTH_B5G5R5X1 0x21
|
||||
#define WIN_COLOR_DEPTH_YCbCr444P 0x29
|
||||
#define WIN_COLOR_DEPTH_YCrCb420SP 0x2A
|
||||
#define WIN_COLOR_DEPTH_YCbCr420SP 0x2B
|
||||
|
@ -338,33 +390,37 @@
|
|||
#define WIN_COLOR_DEPTH_YUV444SP 0x3C
|
||||
|
||||
#define DC_WIN_POSITION 0x704
|
||||
#define H_POSITION(x) (((x) & 0xffff) << 0) // Support negative.
|
||||
#define V_POSITION(x) (((x) & 0xffff) << 16) // Support negative.
|
||||
#define H_POSITION(x) (((x) & 0xFFFF) << 0) // Support negative.
|
||||
#define V_POSITION(x) (((x) & 0xFFFF) << 16) // Support negative.
|
||||
|
||||
#define DC_WIN_SIZE 0x705
|
||||
#define H_SIZE(x) (((x) & 0x1fff) << 0)
|
||||
#define V_SIZE(x) (((x) & 0x1fff) << 16)
|
||||
#define H_SIZE(x) (((x) & 0x1FFF) << 0)
|
||||
#define V_SIZE(x) (((x) & 0x1FFF) << 16)
|
||||
|
||||
#define DC_WIN_PRESCALED_SIZE 0x706
|
||||
#define H_PRESCALED_SIZE(x) (((x) & 0x7fff) << 0)
|
||||
#define V_PRESCALED_SIZE(x) (((x) & 0x1fff) << 16)
|
||||
#define H_PRESCALED_SIZE(x) (((x) & 0x7FFF) << 0)
|
||||
#define V_PRESCALED_SIZE(x) (((x) & 0x1FFF) << 16)
|
||||
|
||||
#define DC_WIN_H_INITIAL_DDA 0x707
|
||||
#define DC_WIN_V_INITIAL_DDA 0x708
|
||||
|
||||
#define DC_WIN_DDA_INC 0x709
|
||||
#define H_DDA_INC(x) (((x) & 0xffff) << 0)
|
||||
#define V_DDA_INC(x) (((x) & 0xffff) << 16)
|
||||
#define H_DDA_INC(x) (((x) & 0xFFFF) << 0)
|
||||
#define V_DDA_INC(x) (((x) & 0xFFFF) << 16)
|
||||
|
||||
#define DC_WIN_LINE_STRIDE 0x70A
|
||||
#define LINE_STRIDE(x) (x)
|
||||
#define UV_LINE_STRIDE(x) (((x) & 0xffff) << 16)
|
||||
#define UV_LINE_STRIDE(x) (((x) & 0xFFFF) << 16)
|
||||
|
||||
#define DC_WIN_DV_CONTROL 0x70E
|
||||
#define DV_CTRL_R(r) (((r) & 7) << 16)
|
||||
#define DV_CTRL_G(g) (((g) & 7) << 8)
|
||||
#define DV_CTRL_B(b) (((b) & 7) << 0)
|
||||
|
||||
#define DC_WINBUF_BLEND_LAYER_CONTROL 0x716
|
||||
#define WIN_BLEND_DEPTH(x) (((x) & 0xff) << 0)
|
||||
#define WIN_K1(x) (((x) & 0xff) << 8)
|
||||
#define WIN_K2(x) (((x) & 0xff) << 16)
|
||||
#define WIN_BLEND_DEPTH(x) (((x) & 0xFF) << 0)
|
||||
#define WIN_K1(x) (((x) & 0xFF) << 8)
|
||||
#define WIN_K2(x) (((x) & 0xFF) << 16)
|
||||
#define WIN_BLEND_ENABLE (0 << 24)
|
||||
#define WIN_BLEND_BYPASS (1 << 24)
|
||||
|
||||
|
@ -395,8 +451,8 @@
|
|||
#define WIN_BLEND_FACT_DST_ALPHA_MATCH_SEL_K2 (3 << 12)
|
||||
|
||||
#define DC_WINBUF_BLEND_ALPHA_1BIT 0x719
|
||||
#define WIN_ALPHA_1BIT_WEIGHT0(x) (((x) & 0xff) << 0)
|
||||
#define WIN_ALPHA_1BIT_WEIGHT1(x) (((x) & 0xff) << 8)
|
||||
#define WIN_ALPHA_1BIT_WEIGHT0(x) (((x) & 0xFF) << 0)
|
||||
#define WIN_ALPHA_1BIT_WEIGHT1(x) (((x) & 0xFF) << 8)
|
||||
|
||||
/*! The following registers are A/B/C shadows of the 0xBC0/0xDC0/0xFC0 registers (see DISPLAY_WINDOW_HEADER). */
|
||||
#define DC_WINBUF_START_ADDR 0x800
|
||||
|
@ -408,6 +464,8 @@
|
|||
#define BLOCK (2 << 0)
|
||||
#define BLOCK_HEIGHT(x) (((x) & 0x7) << 4)
|
||||
|
||||
#define DC_WINBUF_MEMFETCH_CONTROL 0x82B
|
||||
|
||||
/*! Display serial interface registers. */
|
||||
#define _DSIREG(reg) ((reg) * 4)
|
||||
|
||||
|
@ -486,8 +544,8 @@
|
|||
#define DSI_PKT_LEN_2_3 0x35
|
||||
#define DSI_PKT_LEN_4_5 0x36
|
||||
#define DSI_PKT_LEN_6_7 0x37
|
||||
#define PKT0_LEN(x) (((x) & 0xffff) << 0)
|
||||
#define PKT1_LEN(x) (((x) & 0xffff) << 16)
|
||||
#define PKT0_LEN(x) (((x) & 0xFFFF) << 0)
|
||||
#define PKT1_LEN(x) (((x) & 0xFFFF) << 16)
|
||||
|
||||
#define DSI_PHY_TIMING_0 0x3C
|
||||
#define DSI_PHY_TIMING_1 0x3D
|
||||
|
@ -495,20 +553,20 @@
|
|||
#define DSI_BTA_TIMING 0x3F
|
||||
|
||||
#define DSI_TIMEOUT_0 0x44
|
||||
#define DSI_TIMEOUT_HTX(x) (((x) & 0xffff) << 0)
|
||||
#define DSI_TIMEOUT_LRX(x) (((x) & 0xffff) << 16)
|
||||
#define DSI_TIMEOUT_HTX(x) (((x) & 0xFFFF) << 0)
|
||||
#define DSI_TIMEOUT_LRX(x) (((x) & 0xFFFF) << 16)
|
||||
|
||||
#define DSI_TIMEOUT_1 0x45
|
||||
#define DSI_TIMEOUT_TA(x) (((x) & 0xffff) << 0)
|
||||
#define DSI_TIMEOUT_PR(x) (((x) & 0xffff) << 16)
|
||||
#define DSI_TIMEOUT_TA(x) (((x) & 0xFFFF) << 0)
|
||||
#define DSI_TIMEOUT_PR(x) (((x) & 0xFFFF) << 16)
|
||||
|
||||
#define DSI_TO_TALLY 0x46
|
||||
|
||||
#define DSI_PAD_CONTROL_0 0x4B
|
||||
#define DSI_PAD_CONTROL_VS1_PDIO_CLK BIT(8)
|
||||
#define DSI_PAD_CONTROL_VS1_PDIO(x) (((x) & 0xf) << 0)
|
||||
#define DSI_PAD_CONTROL_VS1_PDIO(x) (((x) & 0xF) << 0)
|
||||
#define DSI_PAD_CONTROL_VS1_PULLDN_CLK BIT(24)
|
||||
#define DSI_PAD_CONTROL_VS1_PULLDN(x) (((x) & 0xf) << 16)
|
||||
#define DSI_PAD_CONTROL_VS1_PULLDN(x) (((x) & 0xF) << 16)
|
||||
|
||||
#define DSI_PAD_CONTROL_CD 0x4C
|
||||
#define DSI_VIDEO_MODE_CONTROL 0x4E
|
||||
|
@ -789,10 +847,12 @@ enum
|
|||
PANEL_SHP_LQ055T1SW10 = 0x1040,
|
||||
PANEL_SAM_AMS699VC01 = 0x2050,
|
||||
|
||||
// Found on 6/2" clones. Unknown markings. Quality seems JDI like. Has bad low backlight scaling. ID: [83] 94 [0F].
|
||||
PANEL_OEM_CLONE_6_2 = 0x0F83,
|
||||
// Found on 5.5" clones with AUO A055TAN02 (59.05A30.001) fake markings.
|
||||
PANEL_OEM_CLONE_5_5 = 0xB3,
|
||||
PANEL_OEM_CLONE_5_5 = 0x00B3,
|
||||
// Found on 5.5" clones with AUO A055TAN02 (59.05A30.001) fake markings.
|
||||
PANEL_OEM_CLONE = 0
|
||||
PANEL_OEM_CLONE = 0x0000
|
||||
};
|
||||
|
||||
void display_init();
|
||||
|
@ -808,6 +868,12 @@ void display_wait_interrupt(u32 intr);
|
|||
u16 display_get_decoded_panel_id();
|
||||
void display_set_decoded_panel_id(u32 id);
|
||||
|
||||
/*! MIPI DCS register management */
|
||||
int display_dsi_read(u8 cmd, u32 len, void *data);
|
||||
int display_dsi_vblank_read(u8 cmd, u32 len, void *data);
|
||||
void display_dsi_write(u8 cmd, u32 len, void *data);
|
||||
void display_dsi_vblank_write(u8 cmd, u32 len, void *data);
|
||||
|
||||
/*! Show one single color on the display. */
|
||||
void display_color_screen(u32 color);
|
||||
|
||||
|
@ -816,21 +882,22 @@ void display_backlight(bool enable);
|
|||
void display_backlight_brightness(u32 brightness, u32 step_delay);
|
||||
u32 display_get_backlight_brightness();
|
||||
|
||||
/*! Init display in full 720x1280 resolution (B8G8R8A8, line stride 720, framebuffer size = 720*1280*4 bytes). */
|
||||
u32 *display_init_framebuffer_pitch();
|
||||
u32 *display_init_framebuffer_pitch_vic();
|
||||
u32 *display_init_framebuffer_pitch_inv();
|
||||
u32 *display_init_framebuffer_block();
|
||||
u32 *display_init_framebuffer_log();
|
||||
void display_activate_console();
|
||||
void display_deactivate_console();
|
||||
void display_init_cursor(void *crs_fb, u32 size);
|
||||
void display_set_pos_cursor(u32 x, u32 y);
|
||||
void display_deinit_cursor();
|
||||
u32 *display_init_window_a_pitch();
|
||||
u32 *display_init_window_a_pitch_vic();
|
||||
u32 *display_init_window_a_pitch_inv();
|
||||
u32 *display_init_window_a_block();
|
||||
u32 *display_init_window_d_console();
|
||||
|
||||
int display_dsi_read(u8 cmd, u32 len, void *data);
|
||||
int display_dsi_vblank_read(u8 cmd, u32 len, void *data);
|
||||
void display_dsi_write(u8 cmd, u32 len, void *data);
|
||||
void display_dsi_vblank_write(u8 cmd, u32 len, void *data);
|
||||
void display_window_disable(u32 window);
|
||||
|
||||
void display_set_framebuffer(u32 window, void *fb);
|
||||
void display_move_framebuffer(u32 window, void *fb);
|
||||
|
||||
void display_window_d_console_enable();
|
||||
void display_window_d_console_disable();
|
||||
|
||||
void display_cursor_init(void *crs_fb, u32 size);
|
||||
void display_cursor_set_pos(u32 x, u32 y);
|
||||
void display_cursor_deinit();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2022 CTCaer
|
||||
* Copyright (c) 2018-2024 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,37 +16,35 @@
|
|||
*/
|
||||
|
||||
// Display A config.
|
||||
static const cfg_op_t _di_dc_setup_win_config[] = {
|
||||
{DC_CMD_STATE_ACCESS, 0},
|
||||
static const reg_cfg_t _di_dc_setup_win_config[] = {
|
||||
{DC_CMD_STATE_ACCESS, READ_MUX_ASSEMBLY | WRITE_MUX_ASSEMBLY},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
|
||||
{DC_CMD_REG_ACT_CONTROL, WIN_A_ACT_HCNTR_SEL | WIN_B_ACT_HCNTR_SEL | WIN_C_ACT_HCNTR_SEL},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT},
|
||||
{DC_DISP_DC_MCCIF_FIFOCTRL, 0},
|
||||
{DC_DISP_DISP_MEM_HIGH_PRIORITY, 0},
|
||||
{DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER, 0},
|
||||
{DC_CMD_DISPLAY_POWER_CONTROL, PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE | PW4_ENABLE | PM0_ENABLE | PM1_ENABLE},
|
||||
{DC_CMD_GENERAL_INCR_SYNCPT_CNTRL, SYNCPT_CNTRL_NO_STALL},
|
||||
{DC_CMD_CONT_SYNCPT_VSYNC, SYNCPT_VSYNC_ENABLE | SYNCPT_VSYNC_INDX(9)},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ},
|
||||
{DC_CMD_STATE_ACCESS, 0},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE | WIN_D_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ | WIN_D_ACT_REQ},
|
||||
|
||||
/* Setup Windows A/B/C */
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT},
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT | WINDOW_D_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_WIN_DV_CONTROL, 0},
|
||||
/* Setup default YUV colorspace conversion coefficients */
|
||||
{DC_WIN_CSC_YOF, 0xF0},
|
||||
{DC_WIN_CSC_KYRGB, 0x12A},
|
||||
{DC_WIN_CSC_KUR, 0},
|
||||
{DC_WIN_CSC_KVR, 0x198},
|
||||
{DC_WIN_CSC_KUG, 0x39B},
|
||||
{DC_WIN_CSC_KVG, 0x32F},
|
||||
{DC_WIN_CSC_KUB, 0x204},
|
||||
{DC_WIN_CSC_KVB, 0},
|
||||
{DC_WINC_CSC_YOF, 0xF0},
|
||||
{DC_WINC_CSC_KYRGB, 0x12A},
|
||||
{DC_WINC_CSC_KUR, 0},
|
||||
{DC_WINC_CSC_KVR, 0x198},
|
||||
{DC_WINC_CSC_KUG, 0x39B},
|
||||
{DC_WINC_CSC_KVG, 0x32F},
|
||||
{DC_WINC_CSC_KUB, 0x204},
|
||||
{DC_WINC_CSC_KVB, 0},
|
||||
/* End of color coefficients */
|
||||
|
||||
{DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888},
|
||||
|
@ -55,21 +53,18 @@ static const cfg_op_t _di_dc_setup_win_config[] = {
|
|||
{DC_COM_PIN_OUTPUT_POLARITY(3), 0},
|
||||
{DC_DISP_BLEND_BACKGROUND_COLOR, 0},
|
||||
{DC_COM_CRC_CONTROL, 0},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ},
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE | WIN_D_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ | WIN_D_ACT_REQ},
|
||||
{DC_WINBUF_BLEND_LAYER_CONTROL, WIN_BLEND_BYPASS | WIN_BLEND_DEPTH(255)},
|
||||
{DC_CMD_DISPLAY_COMMAND_OPTION0, 0},
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, 0},
|
||||
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_STOP},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ}
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE | WIN_D_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ | WIN_D_ACT_REQ}
|
||||
};
|
||||
|
||||
// DSI Init config.
|
||||
static const cfg_op_t _di_dsi_init_irq_pkt_config0[] = {
|
||||
static const reg_cfg_t _di_dsi_seq_pkt_reset_config0[] = {
|
||||
{DSI_WR_DATA, 0},
|
||||
{DSI_INT_ENABLE, 0},
|
||||
{DSI_INT_STATUS, 0},
|
||||
|
@ -79,7 +74,7 @@ static const cfg_op_t _di_dsi_init_irq_pkt_config0[] = {
|
|||
{DSI_INIT_SEQ_DATA_2, 0},
|
||||
{DSI_INIT_SEQ_DATA_3, 0}
|
||||
};
|
||||
static const cfg_op_t _di_dsi_init_irq_pkt_config1[] = {
|
||||
static const reg_cfg_t _di_dsi_seq_pkt_reset_config1[] = {
|
||||
{DSI_DCS_CMDS, 0},
|
||||
{DSI_PKT_SEQ_0_LO, 0},
|
||||
{DSI_PKT_SEQ_1_LO, 0},
|
||||
|
@ -95,7 +90,7 @@ static const cfg_op_t _di_dsi_init_irq_pkt_config1[] = {
|
|||
{DSI_PKT_SEQ_5_HI, 0},
|
||||
{DSI_CONTROL, 0}
|
||||
};
|
||||
static const cfg_op_t _di_dsi_init_pads_t210b01[] = {
|
||||
static const reg_cfg_t _di_dsi_init_pads_t210b01[] = {
|
||||
{DSI_PAD_CONTROL_1, 0},
|
||||
{DSI_PAD_CONTROL_2, 0},
|
||||
{DSI_PAD_CONTROL_3, 0},
|
||||
|
@ -104,39 +99,47 @@ static const cfg_op_t _di_dsi_init_pads_t210b01[] = {
|
|||
{DSI_PAD_CONTROL_6_B01, 0},
|
||||
{DSI_PAD_CONTROL_7_B01, 0}
|
||||
};
|
||||
static const cfg_op_t _di_dsi_init_timing_pkt_config2[] = {
|
||||
static const reg_cfg_t _di_dsi_init_config[] = {
|
||||
{DSI_PAD_CONTROL_CD, 0},
|
||||
{DSI_SOL_DELAY, 24},
|
||||
{DSI_MAX_THRESHOLD, 480},
|
||||
{DSI_TRIGGER, 0},
|
||||
{DSI_INIT_SEQ_CONTROL, 0},
|
||||
|
||||
{DSI_PKT_LEN_0_1, 0},
|
||||
{DSI_PKT_LEN_2_3, 0},
|
||||
{DSI_PKT_LEN_4_5, 0},
|
||||
{DSI_PKT_LEN_6_7, 0},
|
||||
{DSI_PAD_CONTROL_1, 0}
|
||||
};
|
||||
static const cfg_op_t _di_dsi_init_timing_pwrctrl_config[] = {
|
||||
|
||||
{DSI_PAD_CONTROL_1, 0},
|
||||
|
||||
/* DSI PHY timings */
|
||||
{DSI_PHY_TIMING_0, 0x6070603},
|
||||
{DSI_PHY_TIMING_1, 0x40A0E05},
|
||||
{DSI_PHY_TIMING_2, 0x30109},
|
||||
{DSI_BTA_TIMING, 0x190A14},
|
||||
/* DSI timeout */
|
||||
{DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF)},
|
||||
{DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x765) | DSI_TIMEOUT_TA(0x2000)},
|
||||
{DSI_TO_TALLY, 0},
|
||||
{DSI_PAD_CONTROL_0, DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0)}, // Enable
|
||||
|
||||
{DSI_PAD_CONTROL_0, DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0)}, // Power up.
|
||||
{DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
|
||||
{DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
|
||||
{DSI_POWER_CONTROL, 0},
|
||||
{DSI_POWER_CONTROL, 0},
|
||||
{DSI_PAD_CONTROL_1, 0}
|
||||
};
|
||||
static const cfg_op_t _di_dsi_init_timing_pkt_config3[] = {
|
||||
{DSI_PAD_CONTROL_1, 0},
|
||||
|
||||
/* DSI PHY timings */
|
||||
{DSI_PHY_TIMING_0, 0x6070603},
|
||||
{DSI_PHY_TIMING_1, 0x40A0E05},
|
||||
{DSI_PHY_TIMING_2, 0x30118},
|
||||
{DSI_BTA_TIMING, 0x190A14},
|
||||
/* DSI timeout */
|
||||
{DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF)},
|
||||
{DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x1343) | DSI_TIMEOUT_TA(0x2000)},
|
||||
{DSI_TO_TALLY, 0},
|
||||
|
||||
{DSI_HOST_CONTROL, DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC},
|
||||
{DSI_CONTROL, DSI_CONTROL_LANES(3) | DSI_CONTROL_HOST_ENABLE},
|
||||
{DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
|
||||
|
@ -148,7 +151,7 @@ static const cfg_op_t _di_dsi_init_timing_pkt_config3[] = {
|
|||
};
|
||||
|
||||
// DSI panel JDI config.
|
||||
static const cfg_op_t _di_dsi_panel_init_config_jdi[] = {
|
||||
static const reg_cfg_t _di_dsi_panel_init_config_jdi[] = {
|
||||
{DSI_WR_DATA, 0x0439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
|
||||
{DSI_WR_DATA, 0x9483FFB9}, // MIPI_DCS_PRIV_SET_EXTC. (Pass: FF 83 94).
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
|
@ -195,13 +198,19 @@ static const cfg_op_t _di_dsi_panel_init_config_jdi[] = {
|
|||
};
|
||||
|
||||
// DSI packet config.
|
||||
static const cfg_op_t _di_dsi_init_seq_pkt_final_config[] = {
|
||||
static const reg_cfg_t _di_dsi_seq_pkt_video_non_burst_no_eot_config[] = {
|
||||
{DSI_PAD_CONTROL_1, 0},
|
||||
|
||||
/* DSI PHY timings */
|
||||
{DSI_PHY_TIMING_0, 0x6070603},
|
||||
{DSI_PHY_TIMING_1, 0x40A0E05},
|
||||
{DSI_PHY_TIMING_2, 0x30172},
|
||||
{DSI_BTA_TIMING, 0x190A14},
|
||||
/* DSI timeout */
|
||||
{DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xA40)},
|
||||
{DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x5A2F) | DSI_TIMEOUT_TA(0x2000)},
|
||||
{DSI_TO_TALLY, 0},
|
||||
|
||||
{DSI_PKT_SEQ_0_LO, 0x40000208},
|
||||
{DSI_PKT_SEQ_2_LO, 0x40000308},
|
||||
{DSI_PKT_SEQ_4_LO, 0x40000308},
|
||||
|
@ -218,7 +227,7 @@ static const cfg_op_t _di_dsi_init_seq_pkt_final_config[] = {
|
|||
};
|
||||
|
||||
// DSI mode config.
|
||||
static const cfg_op_t _di_dsi_mode_config[] = {
|
||||
static const reg_cfg_t _di_dsi_host_mode_config[] = {
|
||||
{DSI_TRIGGER, 0},
|
||||
{DSI_CONTROL, 0},
|
||||
{DSI_SOL_DELAY, 6},
|
||||
|
@ -232,7 +241,7 @@ static const cfg_op_t _di_dsi_mode_config[] = {
|
|||
};
|
||||
|
||||
// MIPI CAL config.
|
||||
static const cfg_op_t _di_mipi_pad_cal_config[] = {
|
||||
static const reg_cfg_t _di_mipi_pad_cal_config[] = {
|
||||
{MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0},
|
||||
{MIPI_CAL_CIL_MIPI_CAL_STATUS, 0xF3F10000},
|
||||
{MIPI_CAL_MIPI_BIAS_PAD_CFG0, 0},
|
||||
|
@ -240,13 +249,13 @@ static const cfg_op_t _di_mipi_pad_cal_config[] = {
|
|||
};
|
||||
|
||||
// DSI pad config.
|
||||
static const cfg_op_t _di_dsi_pad_cal_config_t210[] = {
|
||||
static const reg_cfg_t _di_dsi_pad_cal_config_t210[] = {
|
||||
{DSI_PAD_CONTROL_1, 0},
|
||||
{DSI_PAD_CONTROL_2, 0},
|
||||
{DSI_PAD_CONTROL_3, DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) | DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3)},
|
||||
{DSI_PAD_CONTROL_4, 0}
|
||||
};
|
||||
static const cfg_op_t _di_dsi_pad_cal_config_t210b01[] = {
|
||||
static const reg_cfg_t _di_dsi_pad_cal_config_t210b01[] = {
|
||||
{DSI_PAD_CONTROL_1, 0},
|
||||
{DSI_PAD_CONTROL_2, 0},
|
||||
{DSI_PAD_CONTROL_3, 0},
|
||||
|
@ -257,19 +266,19 @@ static const cfg_op_t _di_dsi_pad_cal_config_t210b01[] = {
|
|||
};
|
||||
|
||||
// MIPI CAL config.
|
||||
static const cfg_op_t _di_mipi_dsi_cal_offsets_config_t210[] = {
|
||||
static const reg_cfg_t _di_mipi_dsi_cal_prod_config_t210[] = {
|
||||
{MIPI_CAL_DSIA_MIPI_CAL_CONFIG, 0x200200},
|
||||
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG, 0x200200},
|
||||
{MIPI_CAL_DSIA_MIPI_CAL_CONFIG_2, 0x200002},
|
||||
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0x200002}
|
||||
};
|
||||
static const cfg_op_t _di_mipi_dsi_cal_offsets_config_t210b01[] = {
|
||||
static const reg_cfg_t _di_mipi_dsi_cal_prod_config_t210b01[] = {
|
||||
{MIPI_CAL_DSIA_MIPI_CAL_CONFIG, 0x200006},
|
||||
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG, 0x200006},
|
||||
{MIPI_CAL_DSIA_MIPI_CAL_CONFIG_2, 0x260000},
|
||||
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0x260000}
|
||||
};
|
||||
static const cfg_op_t _di_mipi_start_dsi_cal_config[] = {
|
||||
static const reg_cfg_t _di_mipi_dsi_cal_unused_config[] = {
|
||||
{MIPI_CAL_CILA_MIPI_CAL_CONFIG, 0},
|
||||
{MIPI_CAL_CILB_MIPI_CAL_CONFIG, 0},
|
||||
{MIPI_CAL_CILC_MIPI_CAL_CONFIG, 0},
|
||||
|
@ -280,48 +289,11 @@ static const cfg_op_t _di_mipi_start_dsi_cal_config[] = {
|
|||
{MIPI_CAL_DSID_MIPI_CAL_CONFIG, 0},
|
||||
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0},
|
||||
{MIPI_CAL_DSIC_MIPI_CAL_CONFIG_2, 0},
|
||||
{MIPI_CAL_DSID_MIPI_CAL_CONFIG_2, 0},
|
||||
{MIPI_CAL_MIPI_CAL_CTRL, 0x2A000001} // Set Prescale and filter and start calibration.
|
||||
{MIPI_CAL_DSID_MIPI_CAL_CONFIG_2, 0}
|
||||
};
|
||||
|
||||
// Display A enable config.
|
||||
static const cfg_op_t _di_dc_video_enable_config[] = {
|
||||
{DC_CMD_STATE_ACCESS, 0},
|
||||
|
||||
/* Setup Windows A/B/C */
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_WIN_DV_CONTROL, 0},
|
||||
/* Setup default YUV colorspace conversion coefficients */
|
||||
{DC_WIN_CSC_YOF, 0xF0},
|
||||
{DC_WIN_CSC_KYRGB, 0x12A},
|
||||
{DC_WIN_CSC_KUR, 0},
|
||||
{DC_WIN_CSC_KVR, 0x198},
|
||||
{DC_WIN_CSC_KUG, 0x39B},
|
||||
{DC_WIN_CSC_KVG, 0x32F},
|
||||
{DC_WIN_CSC_KUB, 0x204},
|
||||
{DC_WIN_CSC_KVB, 0},
|
||||
/* End of color coefficients */
|
||||
|
||||
{DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888},
|
||||
{DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C},
|
||||
{DC_COM_PIN_OUTPUT_POLARITY(1), LSC0_OUTPUT_POLARITY_LOW},
|
||||
{DC_COM_PIN_OUTPUT_POLARITY(3), 0},
|
||||
{DC_DISP_BLEND_BACKGROUND_COLOR, 0},
|
||||
{DC_COM_CRC_CONTROL, 0},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ},
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT},
|
||||
{DC_WINBUF_BLEND_LAYER_CONTROL, WIN_BLEND_BYPASS | WIN_BLEND_DEPTH(255)},
|
||||
{DC_CMD_DISPLAY_COMMAND_OPTION0, 0},
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, 0},
|
||||
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_STOP},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ},
|
||||
{DC_CMD_STATE_ACCESS, 0},
|
||||
|
||||
static const reg_cfg_t _di_dc_video_enable_config[] = {
|
||||
/* Set panel timings */
|
||||
{DC_DISP_DISP_TIMING_OPTIONS, VSYNC_H_POSITION(0)},
|
||||
{DC_DISP_REF_TO_SYNC, V_REF_TO_SYNC(1) | H_REF_TO_SYNC(0)},
|
||||
|
@ -334,59 +306,60 @@ static const cfg_op_t _di_dc_video_enable_config[] = {
|
|||
{DC_DISP_SHIFT_CLOCK_OPTIONS, SC1_H_QUALIFIER_NONE | SC0_H_QUALIFIER_NONE},
|
||||
{DC_COM_PIN_OUTPUT_ENABLE(1), 0},
|
||||
{DC_DISP_DATA_ENABLE_OPTIONS, DE_SELECT_ACTIVE | DE_CONTROL_NORMAL},
|
||||
{DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C},
|
||||
{DC_DISP_DISP_CLOCK_CONTROL, 0},
|
||||
{DC_CMD_DISPLAY_COMMAND_OPTION0, 0},
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, 0},
|
||||
|
||||
/* Start continuous display. */
|
||||
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
|
||||
{DC_CMD_STATE_ACCESS, READ_MUX | WRITE_MUX},
|
||||
{DC_DISP_FRONT_PORCH, V_FRONT_PORCH(10) | H_FRONT_PORCH(136)},
|
||||
{DC_CMD_STATE_ACCESS, 0},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
|
||||
{DC_CMD_GENERAL_INCR_SYNCPT, SYNCPT_GENERAL_COND(COND_REG_WR_SAFE) | SYNCPT_GENERAL_INDX(1)},
|
||||
{DC_CMD_GENERAL_INCR_SYNCPT, SYNCPT_GENERAL_COND(COND_REG_WR_SAFE) | SYNCPT_GENERAL_INDX(1)},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
|
||||
{DC_CMD_STATE_ACCESS, 0},
|
||||
{DC_DISP_DISP_CLOCK_CONTROL, PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(4)},
|
||||
{DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888},
|
||||
{DC_CMD_DISPLAY_COMMAND_OPTION0, 0}
|
||||
|
||||
{DC_DISP_DISP_CLOCK_CONTROL, PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(4)}, // 4: div3.
|
||||
};
|
||||
|
||||
// Display A disable config.
|
||||
static const cfg_op_t _di_dc_video_disable_config[] = {
|
||||
{DC_DISP_FRONT_PORCH, V_FRONT_PORCH(10) | H_FRONT_PORCH(136)},
|
||||
static const reg_cfg_t _di_dc_video_disable_config[] = {
|
||||
{DC_CMD_INT_MASK, 0},
|
||||
{DC_CMD_STATE_ACCESS, 0},
|
||||
{DC_CMD_STATE_ACCESS, READ_MUX_ASSEMBLY | WRITE_MUX_ASSEMBLY},
|
||||
{DC_CMD_INT_ENABLE, 0},
|
||||
{DC_CMD_CONT_SYNCPT_VSYNC, 0},
|
||||
|
||||
/* Stop display. */
|
||||
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_STOP},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
|
||||
{DC_CMD_GENERAL_INCR_SYNCPT, SYNCPT_GENERAL_COND(COND_REG_WR_SAFE) | SYNCPT_GENERAL_INDX(1)},
|
||||
{DC_CMD_GENERAL_INCR_SYNCPT, SYNCPT_GENERAL_COND(COND_REG_WR_SAFE) | SYNCPT_GENERAL_INDX(1)},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
|
||||
// LCD panels should sleep for 40ms here.
|
||||
// TODO: LCD panels should sleep for 40ms here.
|
||||
{DC_CMD_DISPLAY_POWER_CONTROL, 0},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
|
||||
};
|
||||
|
||||
// DSI deinit config.
|
||||
static const cfg_op_t _di_dsi_timing_deinit_config[] = {
|
||||
static const reg_cfg_t _di_dsi_timing_deinit_config[] = {
|
||||
{DSI_POWER_CONTROL, 0},
|
||||
{DSI_PAD_CONTROL_1, 0},
|
||||
{DSI_PHY_TIMING_0, 0x6070601}, //mariko changes
|
||||
|
||||
/* DSI PHY timings */
|
||||
{DSI_PHY_TIMING_0, 0x6070603},
|
||||
{DSI_PHY_TIMING_1, 0x40A0E05},
|
||||
{DSI_PHY_TIMING_2, 0x30118},
|
||||
{DSI_BTA_TIMING, 0x190A14},
|
||||
{DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF) },
|
||||
/* DSI timeout */
|
||||
{DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF)},
|
||||
{DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x1343) | DSI_TIMEOUT_TA(0x2000)},
|
||||
{DSI_TO_TALLY, 0},
|
||||
|
||||
{DSI_HOST_CONTROL, DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC},
|
||||
{DSI_CONTROL, DSI_CONTROL_LANES(3) | DSI_CONTROL_HOST_ENABLE},
|
||||
{DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
|
||||
|
@ -397,7 +370,7 @@ static const cfg_op_t _di_dsi_timing_deinit_config[] = {
|
|||
};
|
||||
|
||||
// DSI panel JDI deinit config.
|
||||
static const cfg_op_t _di_dsi_panel_deinit_config_jdi[] = {
|
||||
static const reg_cfg_t _di_dsi_panel_deinit_config_jdi[] = {
|
||||
{DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
|
||||
{DSI_WR_DATA, 0x9483FFB9}, // MIPI_DCS_PRIV_SET_EXTC. (Pass: FF 83 94).
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
|
@ -423,7 +396,7 @@ static const cfg_op_t _di_dsi_panel_deinit_config_jdi[] = {
|
|||
};
|
||||
|
||||
// DSI panel AUO deinit config.
|
||||
static const cfg_op_t _di_dsi_panel_deinit_config_auo[] = {
|
||||
static const reg_cfg_t _di_dsi_panel_deinit_config_auo[] = {
|
||||
{DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
|
||||
{DSI_WR_DATA, 0x9483FFB9}, // MIPI_DCS_PRIV_SET_EXTC. (Pass: FF 83 94).
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
|
@ -464,24 +437,24 @@ static const cfg_op_t _di_dsi_panel_deinit_config_auo[] = {
|
|||
{DSI_TRIGGER, DSI_TRIGGER_HOST}
|
||||
};
|
||||
|
||||
static const cfg_op_t _di_init_config_invert[] = {
|
||||
/*
|
||||
static const reg_cfg_t _di_init_config_invert[] = {
|
||||
{DSI_WR_DATA, 0x239},
|
||||
{DSI_WR_DATA, 0x02C1}, // INV_EN.
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
};
|
||||
*/
|
||||
|
||||
// Display A Window A one color config.
|
||||
static const cfg_op_t _di_win_one_color[] = {
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT},
|
||||
static const reg_cfg_t _di_win_one_color[] = {
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT | WINDOW_D_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
|
||||
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY} // Continuous display.
|
||||
};
|
||||
|
||||
// Display A Window A linear pitch config.
|
||||
static const cfg_op_t _di_win_framebuffer_pitch[] = {
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT | WINDOW_B_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
static const reg_cfg_t _di_winA_pitch[] = {
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
|
||||
|
@ -500,14 +473,12 @@ static const cfg_op_t _di_win_framebuffer_pitch[] = {
|
|||
{DC_WINBUF_ADDR_V_OFFSET, 0},
|
||||
{DC_WIN_WIN_OPTIONS, WIN_ENABLE}, // Enable window AD.
|
||||
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, // Continuous display.
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ}
|
||||
};
|
||||
|
||||
// Display A Window A linear pitch + Win D support config.
|
||||
static const cfg_op_t _di_win_framebuffer_pitch_vic[] = {
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT | WINDOW_C_SELECT | WINDOW_B_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
static const reg_cfg_t _di_winA_pitch_vic[] = {
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
|
||||
|
@ -526,14 +497,12 @@ static const cfg_op_t _di_win_framebuffer_pitch_vic[] = {
|
|||
{DC_WINBUF_ADDR_V_OFFSET, 0},
|
||||
{DC_WIN_WIN_OPTIONS, WIN_ENABLE}, // Enable window AD.
|
||||
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, // Continuous display.
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ}
|
||||
};
|
||||
|
||||
// Display A Window A linear pitch inverse + Win D support config.
|
||||
static const cfg_op_t _di_win_framebuffer_pitch_inv[] = {
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT | WINDOW_C_SELECT | WINDOW_B_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
static const reg_cfg_t _di_winA_pitch_inv[] = {
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
|
||||
|
@ -552,14 +521,12 @@ static const cfg_op_t _di_win_framebuffer_pitch_inv[] = {
|
|||
{DC_WINBUF_ADDR_V_OFFSET, 1279}, // Linear: 1279, Block: 0.
|
||||
{DC_WIN_WIN_OPTIONS, WIN_ENABLE | V_DIRECTION}, // Enable window AD.
|
||||
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, // Continuous display.
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ}
|
||||
};
|
||||
|
||||
// Display A Window A block linear config.
|
||||
static const cfg_op_t _di_win_framebuffer_block[] = {
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT | WINDOW_C_SELECT | WINDOW_B_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
static const reg_cfg_t _di_winA_block[] = {
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
|
||||
|
@ -578,12 +545,12 @@ static const cfg_op_t _di_win_framebuffer_block[] = {
|
|||
{DC_WINBUF_ADDR_V_OFFSET, 0}, // Linear: 1279, Block: 0.
|
||||
{DC_WIN_WIN_OPTIONS, WIN_ENABLE | SCAN_COLUMN | H_DIRECTION}, // Enable window AD. | SCAN_COLUMN | H_DIRECTION.
|
||||
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, // Continuous display.
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ}
|
||||
};
|
||||
|
||||
// Display A Window D config.
|
||||
static const cfg_op_t _di_win_framebuffer_log[] = {
|
||||
static const reg_cfg_t _di_winD_log[] = {
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8},
|
||||
|
@ -601,6 +568,6 @@ static const cfg_op_t _di_win_framebuffer_log[] = {
|
|||
{DC_WINBUF_ADDR_V_OFFSET, 0},
|
||||
{DC_WINBUF_BLEND_LAYER_CONTROL, WIN_BLEND_ENABLE | WIN_K1(200) | WIN_BLEND_DEPTH(0)},
|
||||
{DC_WINBUF_BLEND_MATCH_SELECT, WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_K1 | WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_NEG_K1},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_D_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_D_ACT_REQ}
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_D_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_D_ACT_REQ},
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* VIC driver for Tegra X1
|
||||
*
|
||||
* Copyright (c) 2018-2023 CTCaer
|
||||
* Copyright (c) 2018-2024 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,
|
||||
|
@ -390,7 +390,7 @@ static int _vic_wait_idle()
|
|||
return 0;
|
||||
}
|
||||
|
||||
void vic_set_surface(vic_surface_t *sfc)
|
||||
void vic_set_surface(const vic_surface_t *sfc)
|
||||
{
|
||||
u32 flip_x = 0;
|
||||
u32 flip_y = 0;
|
||||
|
@ -406,6 +406,9 @@ void vic_set_surface(vic_surface_t *sfc)
|
|||
// Get format alpha type.
|
||||
switch (sfc->pix_fmt)
|
||||
{
|
||||
case VIC_PIX_FORMAT_L8:
|
||||
case VIC_PIX_FORMAT_X1B5G5R5:
|
||||
case VIC_PIX_FORMAT_B5G5R5X1:
|
||||
case VIC_PIX_FORMAT_X8B8G8R8:
|
||||
case VIC_PIX_FORMAT_X8R8G8B8:
|
||||
case VIC_PIX_FORMAT_B8G8R8X8:
|
||||
|
@ -536,14 +539,8 @@ int vic_compose()
|
|||
|
||||
int vic_init()
|
||||
{
|
||||
// Ease the stress to APB.
|
||||
bpmp_freq_t prev_fid = bpmp_clk_rate_set(BPMP_CLK_NORMAL);
|
||||
|
||||
clock_enable_vic();
|
||||
|
||||
// Restore sys clock.
|
||||
bpmp_clk_rate_set(prev_fid);
|
||||
|
||||
// Load Fetch Control Engine microcode.
|
||||
for (u32 i = 0; i < sizeof(vic_fce_ucode) / sizeof(u32); i++)
|
||||
{
|
||||
|
|
|
@ -33,6 +33,10 @@ typedef enum _vic_rotation_t
|
|||
|
||||
typedef enum _vic_pix_format_t
|
||||
{
|
||||
VIC_PIX_FORMAT_L8 = 1, // 8-bit LUT.
|
||||
VIC_PIX_FORMAT_X1B5G5R5 = 21, // 16-bit XBGR.
|
||||
VIC_PIX_FORMAT_B5G5R5X1 = 23, // 16-bit BGRX.
|
||||
|
||||
VIC_PIX_FORMAT_A8B8G8R8 = 31, // 32-bit ABGR.
|
||||
VIC_PIX_FORMAT_A8R8G8B8 = 32, // 32-bit ARGB.
|
||||
VIC_PIX_FORMAT_B8G8R8A8 = 33, // 32-bit BGRA.
|
||||
|
@ -42,7 +46,6 @@ typedef enum _vic_pix_format_t
|
|||
VIC_PIX_FORMAT_X8R8G8B8 = 36, // 32-bit XRGB.
|
||||
VIC_PIX_FORMAT_B8G8R8X8 = 37, // 32-bit BGRX.
|
||||
VIC_PIX_FORMAT_R8G8B8X8 = 38, // 32-bit RGBX.
|
||||
|
||||
} vic_pix_format_t;
|
||||
|
||||
typedef struct _vic_surface_t
|
||||
|
@ -55,7 +58,7 @@ typedef struct _vic_surface_t
|
|||
u32 rotation;
|
||||
} vic_surface_t;
|
||||
|
||||
void vic_set_surface(vic_surface_t *sfc);
|
||||
void vic_set_surface(const vic_surface_t *sfc);
|
||||
int vic_compose();
|
||||
int vic_init();
|
||||
void vic_end();
|
||||
|
|
|
@ -45,7 +45,7 @@ typedef struct _opt_win_cal_t
|
|||
} opt_win_cal_t;
|
||||
|
||||
// Nintendo Switch Icosa/Iowa Optical Window calibration.
|
||||
const opt_win_cal_t opt_win_cal_default[] = {
|
||||
static const opt_win_cal_t opt_win_cal_default[] = {
|
||||
{ 500, 5002, 7502 },
|
||||
{ 754, 2250, 2000 },
|
||||
{ 1029, 1999, 1667 },
|
||||
|
@ -54,14 +54,14 @@ const opt_win_cal_t opt_win_cal_default[] = {
|
|||
};
|
||||
|
||||
// Nintendo Switch Aula Optical Window calibration.
|
||||
const opt_win_cal_t opt_win_cal_aula[] = {
|
||||
static const opt_win_cal_t opt_win_cal_aula[] = {
|
||||
{ 231, 9697, 30300 },
|
||||
{ 993, 3333, 2778 },
|
||||
{ 1478, 1621, 1053 },
|
||||
{ 7500, 81, 10 }
|
||||
};
|
||||
|
||||
const u32 als_gain_idx_tbl[4] = { 1, 2, 64, 128 };
|
||||
static const u32 als_gain_idx_tbl[4] = { 1, 2, 64, 128 };
|
||||
|
||||
void set_als_cfg(als_ctxt_t *als_ctxt, u8 gain, u8 cycle)
|
||||
{
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Joy-Con UART driver for Nintendo Switch
|
||||
*
|
||||
* Copyright (c) 2019-2023 CTCaer
|
||||
* Copyright (c) 2019-2024 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
|
@ -22,7 +22,6 @@
|
|||
#include <gfx_utils.h>
|
||||
#include <power/max17050.h>
|
||||
#include <power/regulator_5v.h>
|
||||
#include <soc/bpmp.h>
|
||||
#include <soc/clock.h>
|
||||
#include <soc/fuse.h>
|
||||
#include <soc/gpio.h>
|
||||
|
@ -104,10 +103,10 @@ enum
|
|||
enum
|
||||
{
|
||||
JC_BATT_EMTPY = 0,
|
||||
JC_BATT_CRIT = 2,
|
||||
JC_BATT_LOW = 4,
|
||||
JC_BATT_MID = 6,
|
||||
JC_BATT_FULL = 8
|
||||
JC_BATT_CRIT = 1,
|
||||
JC_BATT_LOW = 2,
|
||||
JC_BATT_MID = 3,
|
||||
JC_BATT_FULL = 4
|
||||
};
|
||||
|
||||
static const u8 sio_init[] = {
|
||||
|
@ -223,8 +222,8 @@ typedef struct _jc_hid_in_rpt_t
|
|||
{
|
||||
u8 cmd;
|
||||
u8 pkt_id;
|
||||
u8 conn_info:4;
|
||||
u8 batt_info:4;
|
||||
u8 conn_info:4; // Connection detect.
|
||||
u8 batt_info:4; // Power info.
|
||||
u8 btn_right;
|
||||
u8 btn_shared;
|
||||
u8 btn_left;
|
||||
|
@ -234,7 +233,7 @@ typedef struct _jc_hid_in_rpt_t
|
|||
u8 stick_h_right;
|
||||
u8 stick_m_right;
|
||||
u8 stick_v_right;
|
||||
u8 vib_decider; // right:8, left:8. (bit3 en, bit2-0 buffer avail).
|
||||
u8 vib_decider; // right:4, left:4 (bit3 en, bit2-0 buffer avail).
|
||||
u8 submcd_ack;
|
||||
u8 subcmd;
|
||||
u8 subcmd_data[];
|
||||
|
@ -317,9 +316,10 @@ typedef struct _joycon_ctxt_t
|
|||
u8 uart;
|
||||
u8 type;
|
||||
u8 state;
|
||||
u8 mac[6];
|
||||
u32 last_received_time;
|
||||
u32 last_status_req_time;
|
||||
u8 mac[6];
|
||||
u8 pkt_id;
|
||||
u8 rumble_sent;
|
||||
u8 connected;
|
||||
u8 detected;
|
||||
|
@ -330,11 +330,10 @@ 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;
|
||||
|
||||
static jc_gamepad_rpt_t jc_gamepad;
|
||||
|
||||
static u8 _jc_crc(u8 *data, u16 len, u8 init)
|
||||
static u8 _jc_crc(const u8 *data, u16 len, u8 init)
|
||||
{
|
||||
u8 crc = init;
|
||||
for (u16 i = 0; i < len; i++)
|
||||
|
@ -407,12 +406,16 @@ static void _jc_detect()
|
|||
if (!jc_gamepad.sio_mode)
|
||||
{
|
||||
// Turn on Joy-Con detect. (UARTB/C TX). UART CTS also if HW flow control and irq is enabled.
|
||||
PINMUX_AUX(PINMUX_AUX_UART2_TX) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE;
|
||||
PINMUX_AUX(PINMUX_AUX_UART3_TX) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE;
|
||||
PINMUX_AUX(PINMUX_AUX_UART2_TX) = PINMUX_INPUT_ENABLE;
|
||||
PINMUX_AUX(PINMUX_AUX_UART3_TX) = PINMUX_INPUT_ENABLE;
|
||||
gpio_direction_input(GPIO_PORT_G, GPIO_PIN_0);
|
||||
gpio_direction_input(GPIO_PORT_D, GPIO_PIN_1);
|
||||
usleep(20);
|
||||
|
||||
//! HW BUG: Unlatch gpio buffer.
|
||||
(void)gpio_read(GPIO_PORT_H, GPIO_PIN_6);
|
||||
(void)gpio_read(GPIO_PORT_E, GPIO_PIN_6);
|
||||
|
||||
// Read H6/E6 which are shared with UART TX pins.
|
||||
jc_r.detected = !gpio_read(GPIO_PORT_H, GPIO_PIN_6);
|
||||
jc_l.detected = !gpio_read(GPIO_PORT_E, GPIO_PIN_6);
|
||||
|
@ -444,7 +447,7 @@ static void _jc_conn_check()
|
|||
if (jc_l.connected)
|
||||
_jc_power_supply(UART_C, false);
|
||||
|
||||
hid_pkt_inc = 0;
|
||||
jc_l.pkt_id = 0;
|
||||
|
||||
jc_l.connected = false;
|
||||
jc_l.rumble_sent = false;
|
||||
|
@ -461,7 +464,7 @@ static void _jc_conn_check()
|
|||
if (jc_r.connected)
|
||||
_jc_power_supply(UART_B, false);
|
||||
|
||||
hid_pkt_inc = 0;
|
||||
jc_r.pkt_id = 0;
|
||||
|
||||
jc_r.connected = false;
|
||||
jc_r.rumble_sent = false;
|
||||
|
@ -480,7 +483,7 @@ static void _joycon_send_raw(u8 uart_port, const u8 *buf, u16 size)
|
|||
uart_wait_xfer(uart_port, UART_TX_IDLE);
|
||||
}
|
||||
|
||||
static u16 _jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, u8 *data, u16 size, bool crc)
|
||||
static u16 _jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, const u8 *data, u16 size, bool crc)
|
||||
{
|
||||
out->uart_hdr.magic[0] = 0x19;
|
||||
out->uart_hdr.magic[1] = 0x01;
|
||||
|
@ -500,7 +503,7 @@ static u16 _jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, u8 *data,
|
|||
return sizeof(jc_wired_hdr_t);
|
||||
}
|
||||
|
||||
static u16 _jc_hid_output_rpt_craft(jc_wired_hdr_t *rpt, u8 *payload, u16 size, bool crc)
|
||||
static u16 _jc_hid_output_rpt_craft(jc_wired_hdr_t *rpt, const u8 *payload, u16 size, bool crc)
|
||||
{
|
||||
u16 pkt_size = _jc_packet_add_uart_hdr(rpt, JC_WIRED_HID, NULL, 0, crc);
|
||||
pkt_size += size;
|
||||
|
@ -515,25 +518,21 @@ static u16 _jc_hid_output_rpt_craft(jc_wired_hdr_t *rpt, u8 *payload, u16 size,
|
|||
return pkt_size;
|
||||
}
|
||||
|
||||
static void _jc_send_hid_output_rpt(u8 uart, u8 *payload, u16 size, bool crc)
|
||||
static void _jc_send_hid_output_rpt(joycon_ctxt_t *jc, jc_hid_out_rpt_t *hid_pkt, 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, crc);
|
||||
hid_pkt->pkt_id = (jc->pkt_id++ & 0xF);
|
||||
u32 rpt_size = _jc_hid_output_rpt_craft((jc_wired_hdr_t *)rpt, (u8 *)hid_pkt, size, crc);
|
||||
|
||||
_joycon_send_raw(uart, rpt, rpt_size);
|
||||
_joycon_send_raw(jc->uart, rpt, rpt_size);
|
||||
}
|
||||
|
||||
static u8 _jc_hid_pkt_id_incr()
|
||||
static void _jc_send_hid_cmd(joycon_ctxt_t *jc, u8 subcmd, const u8 *data, u16 size)
|
||||
{
|
||||
return (hid_pkt_inc++ & 0xF);
|
||||
}
|
||||
|
||||
static void _jc_send_hid_cmd(u8 uart, u8 subcmd, u8 *data, u16 size)
|
||||
{
|
||||
const u8 rumble_neutral[8] = { 0x00, 0x01, 0x40, 0x40, 0x00, 0x01, 0x40, 0x40 };
|
||||
const u8 rumble_init[8] = { 0xc2, 0xc8, 0x03, 0x72, 0xc2, 0xc8, 0x03, 0x72 };
|
||||
static const u8 rumble_neutral[8] = { 0x00, 0x01, 0x40, 0x40, 0x00, 0x01, 0x40, 0x40 };
|
||||
static const u8 rumble_init[8] = { 0xc2, 0xc8, 0x03, 0x72, 0xc2, 0xc8, 0x03, 0x72 };
|
||||
|
||||
u8 temp[0x30] = {0};
|
||||
|
||||
|
@ -547,47 +546,43 @@ static void _jc_send_hid_cmd(u8 uart, u8 subcmd, u8 *data, u16 size)
|
|||
|
||||
// Enable rumble.
|
||||
hid_pkt->cmd = JC_HID_OUTPUT_RPT;
|
||||
hid_pkt->pkt_id = _jc_hid_pkt_id_incr();
|
||||
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, false);
|
||||
_jc_send_hid_output_rpt(&jc_r, hid_pkt, 0x10, false);
|
||||
if (send_l_rumble)
|
||||
_jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 0x10, false);
|
||||
_jc_send_hid_output_rpt(&jc_l, hid_pkt, 0x10, false);
|
||||
|
||||
// Send rumble.
|
||||
hid_pkt->cmd = JC_HID_RUMBLE_RPT;
|
||||
hid_pkt->pkt_id = _jc_hid_pkt_id_incr();
|
||||
hid_pkt->cmd = JC_HID_RUMBLE_RPT;
|
||||
memcpy(hid_pkt->rumble, rumble_init, sizeof(rumble_init));
|
||||
if (send_r_rumble)
|
||||
_jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 10, false);
|
||||
_jc_send_hid_output_rpt(&jc_r, hid_pkt, 10, false);
|
||||
if (send_l_rumble)
|
||||
_jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 10, false);
|
||||
_jc_send_hid_output_rpt(&jc_l, hid_pkt, 10, false);
|
||||
|
||||
msleep(15);
|
||||
|
||||
// Disable rumble.
|
||||
hid_pkt->cmd = JC_HID_OUTPUT_RPT;
|
||||
hid_pkt->pkt_id = _jc_hid_pkt_id_incr();
|
||||
hid_pkt->subcmd = JC_HID_SUBCMD_RUMBLE_CTL;
|
||||
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, false);
|
||||
_jc_send_hid_output_rpt(&jc_r, hid_pkt, 0x10, false);
|
||||
if (send_l_rumble)
|
||||
_jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 0x10, false);
|
||||
_jc_send_hid_output_rpt(&jc_l, hid_pkt, 0x10, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool crc_needed = (jc_l.uart == uart) ? (jc_l.type & JC_ID_HORI) : (jc_r.type & JC_ID_HORI);
|
||||
bool crc_needed = jc->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);
|
||||
|
||||
_jc_send_hid_output_rpt(uart, (u8 *)hid_pkt, sizeof(jc_hid_out_rpt_t) + size, crc_needed);
|
||||
_jc_send_hid_output_rpt(jc, hid_pkt, sizeof(jc_hid_out_rpt_t) + size, crc_needed);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -596,13 +591,13 @@ static void _jc_charging_decider(u8 batt, u8 uart)
|
|||
u32 system_batt_enough = max17050_get_cached_batt_volt() > 4000;
|
||||
|
||||
// Power supply control based on battery levels and charging.
|
||||
if ((batt >> 1 << 1) < JC_BATT_LOW) // Level without checking charging.
|
||||
if ((batt >> 1) < JC_BATT_LOW) // Level without checking charging.
|
||||
_jc_power_supply(uart, true);
|
||||
else if (batt > (system_batt_enough ? JC_BATT_FULL : JC_BATT_MID)) // Addresses the charging bit.
|
||||
else if (batt > (system_batt_enough ? JC_BATT_FULL : JC_BATT_MID) << 1) // Addresses the charging bit.
|
||||
_jc_power_supply(uart, false);
|
||||
}
|
||||
|
||||
static void _jc_parse_wired_hid(joycon_ctxt_t *jc, const u8* packet, u32 size)
|
||||
static void _jc_parse_wired_hid(joycon_ctxt_t *jc, const u8 *packet, int size)
|
||||
{
|
||||
u32 btn_tmp;
|
||||
jc_hid_in_rpt_t *hid_pkt = (jc_hid_in_rpt_t *)packet;
|
||||
|
@ -610,7 +605,14 @@ static void _jc_parse_wired_hid(joycon_ctxt_t *jc, const u8* packet, u32 size)
|
|||
switch (hid_pkt->cmd)
|
||||
{
|
||||
case JC_HORI_INPUT_RPT:
|
||||
if (!(jc->type & JC_ID_HORI))
|
||||
return;
|
||||
|
||||
case JC_HID_INPUT_RPT:
|
||||
// Discard incomplete hid packets.
|
||||
if (size < 12)
|
||||
break;
|
||||
|
||||
btn_tmp = hid_pkt->btn_right | hid_pkt->btn_shared << 8 | hid_pkt->btn_left << 16;
|
||||
|
||||
if (jc->type & JC_ID_L)
|
||||
|
@ -670,8 +672,12 @@ static void _jc_parse_wired_hid(joycon_ctxt_t *jc, const u8* packet, u32 size)
|
|||
}
|
||||
}
|
||||
|
||||
static void _jc_parse_wired_init(joycon_ctxt_t *jc, const u8* data, u32 size)
|
||||
static void _jc_parse_wired_init(joycon_ctxt_t *jc, const u8 *data, int size)
|
||||
{
|
||||
// Discard empty packets.
|
||||
if (size <= 0)
|
||||
return;
|
||||
|
||||
switch (data[0])
|
||||
{
|
||||
case JC_WIRED_CMD_GET_INFO:
|
||||
|
@ -694,13 +700,13 @@ static void _jc_parse_wired_init(joycon_ctxt_t *jc, const u8* data, u32 size)
|
|||
}
|
||||
}
|
||||
|
||||
static void _jc_uart_pkt_parse(joycon_ctxt_t *jc, const jc_wired_hdr_t *pkt, size_t size)
|
||||
static void _jc_uart_pkt_parse(joycon_ctxt_t *jc, const jc_wired_hdr_t *pkt, int size)
|
||||
{
|
||||
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]);
|
||||
_jc_parse_wired_hid(jc, pkt->payload, size - sizeof(jc_wired_hdr_t));
|
||||
break;
|
||||
case JC_WIRED_INIT_REPLY:
|
||||
_jc_parse_wired_init(jc, pkt->data, size - sizeof(jc_uart_hdr_t) - 1);
|
||||
|
@ -715,11 +721,15 @@ static void _jc_uart_pkt_parse(joycon_ctxt_t *jc, const jc_wired_hdr_t *pkt, siz
|
|||
jc->last_received_time = get_tmr_ms();
|
||||
}
|
||||
|
||||
static void _jc_sio_parse_payload(joycon_ctxt_t *jc, u8 cmd, const u8* payload, u32 size)
|
||||
static void _jc_sio_parse_payload(joycon_ctxt_t *jc, u8 cmd, const u8 *payload, int size)
|
||||
{
|
||||
switch (cmd)
|
||||
{
|
||||
case JC_SIO_CMD_STATUS:
|
||||
// Discard incomplete packets.
|
||||
if (size < 12)
|
||||
break;
|
||||
|
||||
jc_sio_hid_in_rpt_t *hid_pkt = (jc_sio_hid_in_rpt_t *)payload;
|
||||
jc_gamepad.buttons = hid_pkt->btn_right | hid_pkt->btn_shared << 8 | hid_pkt->btn_left << 16;
|
||||
jc_gamepad.home = !gpio_read(GPIO_PORT_V, GPIO_PIN_3);
|
||||
|
@ -740,7 +750,7 @@ static void _jc_sio_parse_payload(joycon_ctxt_t *jc, u8 cmd, const u8* payload,
|
|||
}
|
||||
}
|
||||
|
||||
static void _jc_sio_uart_pkt_parse(joycon_ctxt_t *jc, const jc_sio_in_rpt_t *pkt, u32 size)
|
||||
static void _jc_sio_uart_pkt_parse(joycon_ctxt_t *jc, const jc_sio_in_rpt_t *pkt, int size)
|
||||
{
|
||||
if (pkt->crc_hdr != _jc_crc((u8 *)pkt, sizeof(jc_sio_in_rpt_t) - 1, 0))
|
||||
return;
|
||||
|
@ -757,7 +767,7 @@ static void _jc_sio_uart_pkt_parse(joycon_ctxt_t *jc, const jc_sio_in_rpt_t *pkt
|
|||
break;
|
||||
case JC_SIO_CMD_IAP_VER:
|
||||
case JC_SIO_CMD_STATUS:
|
||||
_jc_sio_parse_payload(jc, cmd, pkt->payload, pkt->payload_size);
|
||||
_jc_sio_parse_payload(jc, cmd, pkt->payload, size - sizeof(jc_sio_in_rpt_t));
|
||||
break;
|
||||
case JC_SIO_CMD_UNK02:
|
||||
case JC_SIO_CMD_UNK20:
|
||||
|
@ -784,7 +794,7 @@ static void _jc_rcv_pkt(joycon_ctxt_t *jc)
|
|||
jc_wired_hdr_t *jc_pkt = (jc_wired_hdr_t *)jc->buf;
|
||||
if (!jc->sio_mode && !memcmp(jc_pkt->uart_hdr.magic, "\x19\x81\x03", 3))
|
||||
{
|
||||
_jc_uart_pkt_parse(jc, jc_pkt, jc_pkt->uart_hdr.total_size_lsb + sizeof(jc_uart_hdr_t));
|
||||
_jc_uart_pkt_parse(jc, jc_pkt, len);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -793,7 +803,7 @@ static void _jc_rcv_pkt(joycon_ctxt_t *jc)
|
|||
jc_sio_in_rpt_t *sio_pkt = (jc_sio_in_rpt_t *)(jc->buf);
|
||||
if (jc->sio_mode && sio_pkt->cmd == JC_SIO_INPUT_RPT && (sio_pkt->ack & JC_SIO_CMD_ACK) == JC_SIO_CMD_ACK)
|
||||
{
|
||||
_jc_sio_uart_pkt_parse(jc, sio_pkt, sio_pkt->payload_size + sizeof(jc_sio_in_rpt_t));
|
||||
_jc_sio_uart_pkt_parse(jc, sio_pkt, len);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -804,7 +814,7 @@ static bool _jc_send_init_rumble(joycon_ctxt_t *jc)
|
|||
// Send init rumble or request nx pad status report.
|
||||
if ((jc_r.connected && !jc_r.rumble_sent) || (jc_l.connected && !jc_l.rumble_sent))
|
||||
{
|
||||
_jc_send_hid_cmd(jc->uart, JC_HID_SUBCMD_SND_RUMBLE, NULL, 0);
|
||||
_jc_send_hid_cmd(jc, JC_HID_SUBCMD_SND_RUMBLE, NULL, 0);
|
||||
|
||||
if (jc_l.connected)
|
||||
jc_l.rumble_sent = true;
|
||||
|
@ -842,10 +852,10 @@ static void _jc_req_nx_pad_status(joycon_ctxt_t *jc)
|
|||
else
|
||||
_joycon_send_raw(jc->uart, hori_pad_status, sizeof(hori_pad_status));
|
||||
|
||||
jc->last_status_req_time = get_tmr_ms() + 15;
|
||||
jc->last_status_req_time = get_tmr_ms() + (!jc->sio_mode ? 15 : 7);
|
||||
}
|
||||
|
||||
static bool _jc_validate_pairing_info(u8 *buf, bool *is_hos)
|
||||
static bool _jc_validate_pairing_info(const u8 *buf, bool *is_hos)
|
||||
{
|
||||
u8 crc = 0;
|
||||
for (u32 i = 0; i < 0x22; i++)
|
||||
|
@ -914,13 +924,13 @@ retry:
|
|||
{
|
||||
if (!jc_l_found)
|
||||
{
|
||||
_jc_send_hid_cmd(jc_l.uart, JC_HID_SUBCMD_SPI_READ, (u8 *)&subcmd_data_l, 5);
|
||||
_jc_send_hid_cmd(&jc_l, JC_HID_SUBCMD_SPI_READ, (u8 *)&subcmd_data_l, 5);
|
||||
jc_l.last_status_req_time = get_tmr_ms() + 15;
|
||||
}
|
||||
|
||||
if (!jc_r_found)
|
||||
{
|
||||
_jc_send_hid_cmd(jc_r.uart, JC_HID_SUBCMD_SPI_READ, (u8 *)&subcmd_data_r, 5);
|
||||
_jc_send_hid_cmd(&jc_r, JC_HID_SUBCMD_SPI_READ, (u8 *)&subcmd_data_r, 5);
|
||||
jc_r.last_status_req_time = get_tmr_ms() + 15;
|
||||
}
|
||||
|
||||
|
@ -1111,7 +1121,7 @@ static void _jc_init_conn(joycon_ctxt_t *jc)
|
|||
|
||||
// Initialize the controller.
|
||||
u32 retries = 10;
|
||||
while (!jc->connected)
|
||||
while (!jc->connected && retries)
|
||||
{
|
||||
_joycon_send_raw(jc->uart, sio_init, sizeof(sio_init));
|
||||
msleep(5);
|
||||
|
@ -1196,17 +1206,11 @@ void jc_init_hw()
|
|||
pinmux_config_uart(UART_B);
|
||||
pinmux_config_uart(UART_C);
|
||||
|
||||
// Ease the stress to APB.
|
||||
bpmp_freq_t prev_fid = bpmp_clk_rate_set(BPMP_CLK_NORMAL);
|
||||
|
||||
// Enable UART B and C clocks.
|
||||
if (!jc_gamepad.sio_mode)
|
||||
clock_enable_uart(UART_B);
|
||||
clock_enable_uart(UART_C);
|
||||
|
||||
// Restore OC.
|
||||
bpmp_clk_rate_set(prev_fid);
|
||||
|
||||
jc_init_done = true;
|
||||
#endif
|
||||
}
|
||||
|
@ -1226,12 +1230,12 @@ void jc_deinit()
|
|||
u8 data = HCI_STATE_SLEEP;
|
||||
if (jc_r.connected && !(jc_r.type & JC_ID_HORI))
|
||||
{
|
||||
_jc_send_hid_cmd(UART_B, JC_HID_SUBCMD_HCI_STATE, &data, 1);
|
||||
_jc_send_hid_cmd(&jc_r, JC_HID_SUBCMD_HCI_STATE, &data, 1);
|
||||
_jc_rcv_pkt(&jc_r);
|
||||
}
|
||||
if (jc_l.connected && !(jc_l.type & JC_ID_HORI))
|
||||
{
|
||||
_jc_send_hid_cmd(UART_C, JC_HID_SUBCMD_HCI_STATE, &data, 1);
|
||||
_jc_send_hid_cmd(&jc_l, JC_HID_SUBCMD_HCI_STATE, &data, 1);
|
||||
_jc_rcv_pkt(&jc_l);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,34 +43,34 @@ typedef struct _jc_gamepad_rpt_t
|
|||
struct
|
||||
{
|
||||
// Joy-Con (R).
|
||||
u32 y:1;
|
||||
u32 x:1;
|
||||
u32 b:1;
|
||||
u32 a:1;
|
||||
u32 sr_r:1;
|
||||
u32 sl_r:1;
|
||||
u32 r:1;
|
||||
u32 zr:1;
|
||||
/*00*/ u32 y:1;
|
||||
/*01*/ u32 x:1;
|
||||
/*02*/ u32 b:1;
|
||||
/*03*/ u32 a:1;
|
||||
/*04*/ u32 sr_r:1;
|
||||
/*05*/ u32 sl_r:1;
|
||||
/*06*/ u32 r:1;
|
||||
/*07*/ u32 zr:1;
|
||||
|
||||
// Shared
|
||||
u32 minus:1;
|
||||
u32 plus:1;
|
||||
u32 r3:1;
|
||||
u32 l3:1;
|
||||
u32 home:1;
|
||||
u32 cap:1;
|
||||
u32 pad:1;
|
||||
u32 wired:1;
|
||||
/*08*/ u32 minus:1;
|
||||
/*09*/ u32 plus:1;
|
||||
/*10*/ u32 r3:1;
|
||||
/*11*/ u32 l3:1;
|
||||
/*12*/ u32 home:1;
|
||||
/*13*/ u32 cap:1;
|
||||
/*14*/ u32 pad:1;
|
||||
/*15*/ u32 wired:1;
|
||||
|
||||
// Joy-Con (L).
|
||||
u32 down:1;
|
||||
u32 up:1;
|
||||
u32 right:1;
|
||||
u32 left:1;
|
||||
u32 sr_l:1;
|
||||
u32 sl_l:1;
|
||||
u32 l:1;
|
||||
u32 zl:1;
|
||||
/*16*/ u32 down:1;
|
||||
/*17*/ u32 up:1;
|
||||
/*18*/ u32 right:1;
|
||||
/*19*/ u32 left:1;
|
||||
/*20*/ u32 sr_l:1;
|
||||
/*21*/ u32 sl_l:1;
|
||||
/*22*/ u32 l:1;
|
||||
/*23*/ u32 zl:1;
|
||||
};
|
||||
u32 buttons;
|
||||
};
|
||||
|
@ -105,4 +105,4 @@ void jc_deinit();
|
|||
jc_gamepad_rpt_t *joycon_poll();
|
||||
jc_gamepad_rpt_t *jc_get_bt_pairing_info(bool *is_l_hos, bool *is_r_hos);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -20,33 +20,33 @@
|
|||
|
||||
#include "blz.h"
|
||||
|
||||
const blz_footer *blz_get_footer(const unsigned char *compData, unsigned int compDataLen, blz_footer *outFooter)
|
||||
const blz_footer *blz_get_footer(const u8 *comp_data, u32 comp_data_size, blz_footer *out_footer)
|
||||
{
|
||||
if (compDataLen < sizeof(blz_footer))
|
||||
if (comp_data_size < sizeof(blz_footer))
|
||||
return NULL;
|
||||
|
||||
const blz_footer *srcFooter = (const blz_footer*)&compData[compDataLen - sizeof(blz_footer)];
|
||||
if (outFooter != NULL)
|
||||
memcpy(outFooter, srcFooter, sizeof(blz_footer)); // Must be a memcpy because no umaligned accesses on ARMv4.
|
||||
const blz_footer *src_footer = (const blz_footer *)&comp_data[comp_data_size - sizeof(blz_footer)];
|
||||
if (out_footer)
|
||||
memcpy(out_footer, src_footer, sizeof(blz_footer)); // Must be a memcpy because no unaligned accesses on ARMv4.
|
||||
|
||||
return srcFooter;
|
||||
return src_footer;
|
||||
}
|
||||
|
||||
// From https://github.com/SciresM/hactool/blob/master/kip.c which is exactly how kernel does it, thanks SciresM!
|
||||
int blz_uncompress_inplace(unsigned char *dataBuf, unsigned int compSize, const blz_footer *footer)
|
||||
int blz_uncompress_inplace(u8 *data, u32 comp_size, const blz_footer *footer)
|
||||
{
|
||||
u32 addl_size = footer->addl_size;
|
||||
u32 header_size = footer->header_size;
|
||||
u32 cmp_and_hdr_size = footer->cmp_and_hdr_size;
|
||||
|
||||
unsigned char* cmp_start = &dataBuf[compSize] - cmp_and_hdr_size;
|
||||
u8 *cmp_start = &data[comp_size] - cmp_and_hdr_size;
|
||||
u32 cmp_ofs = cmp_and_hdr_size - header_size;
|
||||
u32 out_ofs = cmp_and_hdr_size + addl_size;
|
||||
|
||||
while (out_ofs)
|
||||
{
|
||||
unsigned char control = cmp_start[--cmp_ofs];
|
||||
for (unsigned int i=0; i<8; i++)
|
||||
u8 control = cmp_start[--cmp_ofs];
|
||||
for (u32 i = 0; i < 8; i++)
|
||||
{
|
||||
if (control & 0x80)
|
||||
{
|
||||
|
@ -54,45 +54,48 @@ int blz_uncompress_inplace(unsigned char *dataBuf, unsigned int compSize, const
|
|||
return 0; // Out of bounds.
|
||||
|
||||
cmp_ofs -= 2;
|
||||
u16 seg_val = ((unsigned int)(cmp_start[cmp_ofs + 1]) << 8) | cmp_start[cmp_ofs];
|
||||
u16 seg_val = ((u32)(cmp_start[cmp_ofs + 1]) << 8) | cmp_start[cmp_ofs];
|
||||
u32 seg_size = ((seg_val >> 12) & 0xF) + 3;
|
||||
u32 seg_ofs = (seg_val & 0x0FFF) + 3;
|
||||
if (out_ofs < seg_size) // Kernel restricts segment copy to stay in bounds.
|
||||
|
||||
// Kernel restricts segment copy to stay in bounds.
|
||||
if (out_ofs < seg_size)
|
||||
seg_size = out_ofs;
|
||||
|
||||
out_ofs -= seg_size;
|
||||
|
||||
for (unsigned int j = 0; j < seg_size; j++)
|
||||
for (u32 j = 0; j < seg_size; j++)
|
||||
cmp_start[out_ofs + j] = cmp_start[out_ofs + j + seg_ofs];
|
||||
}
|
||||
else
|
||||
else // Copy directly.
|
||||
{
|
||||
// Copy directly.
|
||||
if (cmp_ofs < 1)
|
||||
return 0; //out of bounds
|
||||
return 0; // Out of bounds.
|
||||
|
||||
cmp_start[--out_ofs] = cmp_start[--cmp_ofs];
|
||||
}
|
||||
|
||||
control <<= 1;
|
||||
if (out_ofs == 0) // Blz works backwards, so if it reaches byte 0, it's done.
|
||||
|
||||
if (!out_ofs) // Blz works backwards, so if it reaches byte 0, it's done.
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int blz_uncompress_srcdest(const unsigned char *compData, unsigned int compDataLen, unsigned char *dstData, unsigned int dstSize)
|
||||
int blz_uncompress_srcdest(const u8 *comp_data, u32 comp_data_size, u8 *dst_data, u32 dst_size)
|
||||
{
|
||||
blz_footer footer;
|
||||
const blz_footer *compFooterPtr = blz_get_footer(compData, compDataLen, &footer);
|
||||
if (compFooterPtr == NULL)
|
||||
const blz_footer *comp_footer = blz_get_footer(comp_data, comp_data_size, &footer);
|
||||
if (!comp_footer)
|
||||
return 0;
|
||||
|
||||
// Decompression must be done in-place, so need to copy the relevant compressed data first.
|
||||
unsigned int numCompBytes = (const unsigned char*)(compFooterPtr)-compData;
|
||||
memcpy(dstData, compData, numCompBytes);
|
||||
memset(&dstData[numCompBytes], 0, dstSize - numCompBytes);
|
||||
// Decompression happens in-place, so need to copy the relevant compressed data first.
|
||||
u32 comp_bytes = (const u8 *)comp_footer - comp_data;
|
||||
memcpy(dst_data, comp_data, comp_bytes);
|
||||
memset(&dst_data[comp_bytes], 0, dst_size - comp_bytes);
|
||||
|
||||
return blz_uncompress_inplace(dstData, compDataLen, &footer);
|
||||
return blz_uncompress_inplace(dst_data, comp_data_size, &footer);
|
||||
}
|
||||
|
|
|
@ -26,11 +26,11 @@ typedef struct _blz_footer
|
|||
u32 addl_size;
|
||||
} blz_footer;
|
||||
|
||||
// Returns pointer to footer in compData if present, additionally copies it to outFooter if not NULL.
|
||||
const blz_footer *blz_get_footer(const unsigned char *compData, unsigned int compDataLen, blz_footer *outFooter);
|
||||
// Returns pointer to footer in comp_data if present, additionally copies it to out_footer if not NULL.
|
||||
const blz_footer *blz_get_footer(const u8 *comp_data, u32 comp_data_size, blz_footer *out_footer);
|
||||
// Returns 0 on failure.
|
||||
int blz_uncompress_inplace(unsigned char *dataBuf, unsigned int compSize, const blz_footer *footer);
|
||||
int blz_uncompress_inplace(u8 *data, u32 comp_size, const blz_footer *footer);
|
||||
// Returns 0 on failure.
|
||||
int blz_uncompress_srcdest(const unsigned char *compData, unsigned int compDataLen, unsigned char *dstData, unsigned int dstSize);
|
||||
int blz_uncompress_srcdest(const u8 *comp_data, u32 comp_data_size, u8 *dst_data, u32 dst_size);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -92,22 +92,12 @@
|
|||
# define LZ4_FORCE_O2_INLINE_GCC_PPC64LE static
|
||||
#endif
|
||||
|
||||
#if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__)
|
||||
# define expect(expr,value) (__builtin_expect ((expr),(value)) )
|
||||
#else
|
||||
# define expect(expr,value) (expr)
|
||||
#endif
|
||||
|
||||
#define likely(expr) expect((expr) != 0, 1)
|
||||
#define unlikely(expr) expect((expr) != 0, 0)
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Memory routines
|
||||
**************************************/
|
||||
#include <mem/heap.h> /* malloc, calloc, free */
|
||||
#define ALLOC(s) malloc(s)
|
||||
#define ALLOC_AND_ZERO(s) calloc(1,s)
|
||||
#define ALLOC_AND_ZERO(s) zalloc(s)
|
||||
#define FREEMEM free
|
||||
#include <string.h> /* memset, memcpy */
|
||||
#define MEM_INIT memset
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
* Copyright (c) 2018-2022 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,
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
/*------------------------------------------------------------------------*/
|
||||
/* Sample Code of OS Dependent Functions for FatFs */
|
||||
/* (C) ChaN, 2018 */
|
||||
/* (C) CTCaer, 2018 */
|
||||
/* (C) ChaN, 2018 */
|
||||
/* (C) CTCaer, 2018-2024 */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
#include <bdk.h>
|
||||
|
||||
#include <libs/fatfs/ff.h>
|
||||
#include "../../config.h"
|
||||
|
||||
extern nyx_config n_cfg;
|
||||
|
||||
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
|
||||
|
||||
|
@ -21,7 +18,8 @@ void* ff_memalloc ( /* Returns pointer to the allocated memory block (null if no
|
|||
UINT msize /* Number of bytes to allocate */
|
||||
)
|
||||
{
|
||||
return malloc(msize); /* Allocate a new memory block with POSIX API */
|
||||
// Ensure size is aligned to SDMMC block size.
|
||||
return malloc(ALIGN(msize, SDMMC_DAT_BLOCKSIZE)); /* Allocate a new memory block with POSIX API */
|
||||
}
|
||||
|
||||
|
||||
|
@ -50,12 +48,7 @@ DWORD get_fattime (
|
|||
{
|
||||
rtc_time_t time;
|
||||
|
||||
max77620_rtc_get_time(&time);
|
||||
if (n_cfg.timeoff)
|
||||
{
|
||||
u32 epoch = (u32)((s32)max77620_rtc_date_to_epoch(&time) + (s32)n_cfg.timeoff);
|
||||
max77620_rtc_epoch_to_date(epoch, &time);
|
||||
}
|
||||
max77620_rtc_get_time_adjusted(&time);
|
||||
|
||||
return (((DWORD)(time.year - 1980) << 25) | ((DWORD)time.month << 21) | ((DWORD)time.day << 16) |
|
||||
((DWORD)time.hour << 11) | ((DWORD)time.min << 5) | (time.sec >> 1));
|
|
@ -2,7 +2,7 @@
|
|||
* arch/arm/mach-tegra/tegra21_emc.h
|
||||
*
|
||||
* Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2019-2020, CTCaer.
|
||||
* Copyright (c) 2019-2024, CTCaer.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -23,6 +23,7 @@
|
|||
#ifndef _EMC_H_
|
||||
#define _EMC_H_
|
||||
|
||||
#define EMC_INTSTATUS 0x0
|
||||
#define EMC_DBG 0x8
|
||||
#define EMC_CFG 0xC
|
||||
#define EMC_CONFIG_SAMPLE_DELAY 0x5f0
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2024 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,
|
||||
|
@ -159,6 +159,13 @@ void *calloc(u32 num, u32 size)
|
|||
return res;
|
||||
}
|
||||
|
||||
void *zalloc(u32 size)
|
||||
{
|
||||
void *res = (void *)_heap_alloc(size);
|
||||
memset(res, 0, ALIGN(size, sizeof(hnode_t))); // Clear the aligned size.
|
||||
return res;
|
||||
}
|
||||
|
||||
void free(void *buf)
|
||||
{
|
||||
if (buf >= _heap.start)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2024 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
|
@ -48,6 +48,7 @@ void heap_init(void *base);
|
|||
void heap_set(heap_t *heap);
|
||||
void *malloc(u32 size);
|
||||
void *calloc(u32 num, u32 size);
|
||||
void *zalloc(u32 size);
|
||||
void free(void *buf);
|
||||
void heap_monitor(heap_monitor_t *mon, bool print_node_stats);
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2014, NVIDIA Corporation. All rights reserved.
|
||||
* Copyright (c) 2014, NVIDIA Corporation.
|
||||
* Copyright (c) 2018-2023, CTCaer
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
|
@ -14,6 +15,22 @@
|
|||
#ifndef _MC_T210_H_
|
||||
#define _MC_T210_H_
|
||||
|
||||
/*! MC SMMU registers */
|
||||
#define MC_SMMU_CONFIG 0x10
|
||||
#define MC_SMMU_TLB_CONFIG 0x14
|
||||
#define MC_SMMU_PTC_CONFIG 0x18
|
||||
#define MC_SMMU_PTB_ASID 0x1c
|
||||
#define MC_SMMU_PTB_DATA 0x20
|
||||
#define MC_SMMU_TLB_FLUSH 0x30
|
||||
#define MC_SMMU_PTC_FLUSH 0x34
|
||||
#define MC_SMMU_ASID_SECURITY 0x38
|
||||
#define MC_SMMU_TRANSLATION_ENABLE_0 0x228
|
||||
#define MC_SMMU_TRANSLATION_ENABLE_1 0x22c
|
||||
#define MC_SMMU_TRANSLATION_ENABLE_2 0x230
|
||||
#define MC_SMMU_TRANSLATION_ENABLE_3 0x234
|
||||
#define MC_SMMU_TRANSLATION_ENABLE_4 0xb98
|
||||
|
||||
/*! MC General registers */
|
||||
#define MC_INTSTATUS 0x0
|
||||
#define MC_INTMASK 0x4
|
||||
#define MC_ERR_STATUS 0x8
|
||||
|
@ -464,7 +481,7 @@
|
|||
#define MC_UNTRANSLATED_REGION_CHECK 0x948
|
||||
#define MC_DA_CONFIG0 0x9dc
|
||||
|
||||
/* MC_SECURITY_CARVEOUTX_CLIENT_FORCE_INTERNAL_ACCESS0 */
|
||||
/*! MC_SECURITY_CARVEOUTX_CLIENT_FORCE_INTERNAL_ACCESS0 */
|
||||
#define SEC_CARVEOUT_CA0_R_PTCR BIT(0)
|
||||
#define SEC_CARVEOUT_CA0_R_DISPLAY0A BIT(1)
|
||||
#define SEC_CARVEOUT_CA0_R_DISPLAY0AB BIT(2)
|
||||
|
@ -484,7 +501,7 @@
|
|||
#define SEC_CARVEOUT_CA0_R_PPCSAHBSLV BIT(30)
|
||||
#define SEC_CARVEOUT_CA0_R_SATAR BIT(31)
|
||||
|
||||
/* MC_SECURITY_CARVEOUTX_CLIENT_FORCE_INTERNAL_ACCESS1 */
|
||||
/*! MC_SECURITY_CARVEOUTX_CLIENT_FORCE_INTERNAL_ACCESS1 */
|
||||
#define SEC_CARVEOUT_CA1_R_VDEBSEV BIT(2)
|
||||
#define SEC_CARVEOUT_CA1_R_VDEMBE BIT(3)
|
||||
#define SEC_CARVEOUT_CA1_R_VDEMCE BIT(4)
|
||||
|
@ -504,7 +521,7 @@
|
|||
#define SEC_CARVEOUT_CA1_W_VDEBSEV BIT(30)
|
||||
#define SEC_CARVEOUT_CA1_W_VDEDBG BIT(31)
|
||||
|
||||
/* MC_SECURITY_CARVEOUTX_CLIENT_FORCE_INTERNAL_ACCESS2 */
|
||||
/*! MC_SECURITY_CARVEOUTX_CLIENT_FORCE_INTERNAL_ACCESS2 */
|
||||
#define SEC_CARVEOUT_CA2_W_VDEMBE BIT(0)
|
||||
#define SEC_CARVEOUT_CA2_W_VDETPM BIT(1)
|
||||
#define SEC_CARVEOUT_CA2_R_ISPRA BIT(4)
|
||||
|
@ -524,7 +541,7 @@
|
|||
#define SEC_CARVEOUT_CA2_W_GPU BIT(25)
|
||||
#define SEC_CARVEOUT_CA2_R_DISPLAYT BIT(26)
|
||||
|
||||
/* MC_SECURITY_CARVEOUTX_CLIENT_FORCE_INTERNAL_ACCESS3 */
|
||||
/*! MC_SECURITY_CARVEOUTX_CLIENT_FORCE_INTERNAL_ACCESS3 */
|
||||
#define SEC_CARVEOUT_CA3_R_SDMMCA BIT(0)
|
||||
#define SEC_CARVEOUT_CA3_R_SDMMCAA BIT(1)
|
||||
#define SEC_CARVEOUT_CA3_R_SDMMC BIT(2)
|
||||
|
@ -544,7 +561,7 @@
|
|||
#define SEC_CARVEOUT_CA3_R_NVJPG BIT(30)
|
||||
#define SEC_CARVEOUT_CA3_W_NVJPG BIT(31)
|
||||
|
||||
/* MC_SECURITY_CARVEOUTX_CLIENT_FORCE_INTERNAL_ACCESS4 */
|
||||
/*! MC_SECURITY_CARVEOUTX_CLIENT_FORCE_INTERNAL_ACCESS4 */
|
||||
#define SEC_CARVEOUT_CA4_R_SE BIT(0)
|
||||
#define SEC_CARVEOUT_CA4_W_SE BIT(1)
|
||||
#define SEC_CARVEOUT_CA4_R_AXIAP BIT(2)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2022 CTCaer
|
||||
* Copyright (c) 2019-2024 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,
|
||||
|
@ -155,13 +155,13 @@ void minerva_sdmmc_la_program(void *table, bool t210b01)
|
|||
switch (freq)
|
||||
{
|
||||
case 204000:
|
||||
la_scale_regs[LA_SDMMC1_INDEX] = (la_scale_regs[LA_SDMMC1_INDEX] & 0xFF0000) | 75;
|
||||
la_scale_regs[LA_SDMMC1_INDEX] = (la_scale_regs[LA_SDMMC1_INDEX] & 0xFF0000) | 50;
|
||||
break;
|
||||
case 408000:
|
||||
la_scale_regs[LA_SDMMC1_INDEX] = (la_scale_regs[LA_SDMMC1_INDEX] & 0xFF0000) | 37;
|
||||
la_scale_regs[LA_SDMMC1_INDEX] = (la_scale_regs[LA_SDMMC1_INDEX] & 0xFF0000) | 25;
|
||||
break;
|
||||
default:
|
||||
la_scale_regs[LA_SDMMC1_INDEX] = (la_scale_regs[LA_SDMMC1_INDEX] & 0xFF0000) | 30;
|
||||
la_scale_regs[LA_SDMMC1_INDEX] = (la_scale_regs[LA_SDMMC1_INDEX] & 0xFF0000) | 20;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -206,6 +206,23 @@ void minerva_prep_boot_l4t(u32 oc_freq, u32 opt_custom)
|
|||
mtc_cfg->table_entries++;
|
||||
}
|
||||
|
||||
// Trim table.
|
||||
int entries = 0;
|
||||
for (u32 i = 0; i < mtc_cfg->table_entries; i++)
|
||||
{
|
||||
// Copy frequencies from 204/408/800 MHz and 1333+ MHz.
|
||||
int rate = mtc_cfg->mtc_table[i].rate_khz;
|
||||
if (rate == FREQ_204 ||
|
||||
rate == FREQ_408 ||
|
||||
rate == FREQ_800 ||
|
||||
rate >= FREQ_1333)
|
||||
{
|
||||
memcpy(&mtc_cfg->mtc_table[entries], &mtc_cfg->mtc_table[i], sizeof(emc_table_t));
|
||||
entries++;
|
||||
}
|
||||
}
|
||||
mtc_cfg->table_entries = entries;
|
||||
|
||||
// Set init frequency.
|
||||
minerva_change_freq(FREQ_204);
|
||||
|
||||
|
@ -213,38 +230,21 @@ void minerva_prep_boot_l4t(u32 oc_freq, u32 opt_custom)
|
|||
mtc_cfg->train_mode = OP_TRAIN;
|
||||
for (u32 i = 0; i < mtc_cfg->table_entries; i++)
|
||||
{
|
||||
mtc_cfg->rate_to = mtc_cfg->mtc_table[i].rate_khz;
|
||||
// Skip already trained frequencies.
|
||||
if (mtc_cfg->rate_to == FREQ_204 ||
|
||||
mtc_cfg->rate_to == FREQ_800 ||
|
||||
mtc_cfg->rate_to == FREQ_1600 ||
|
||||
mtc_cfg->rate_to == oc_freq) // Skip OC freq since Arachne handles it.
|
||||
// Skip already trained frequencies and OC freq (Arachne handles it).
|
||||
if (mtc_cfg->mtc_table[i].trained || mtc_cfg->rate_to == oc_freq)
|
||||
continue;
|
||||
|
||||
// Train frequency.
|
||||
mtc_cfg->rate_to = mtc_cfg->mtc_table[i].rate_khz;
|
||||
minerva_cfg(mtc_cfg, NULL);
|
||||
}
|
||||
|
||||
// Do FSP WAR and scale to 800 MHz as boot freq.
|
||||
bool fsp_opwr_disabled = !(EMC(EMC_MRW3) & 0xC0);
|
||||
if (fsp_opwr_disabled)
|
||||
minerva_change_freq(FREQ_666);
|
||||
minerva_change_freq(FREQ_1333);
|
||||
minerva_change_freq(FREQ_800);
|
||||
|
||||
// Trim table.
|
||||
int entries = 0;
|
||||
for (u32 i = 0; i < mtc_cfg->table_entries; i++)
|
||||
{
|
||||
// Copy freqs from 204 MHz to 800 MHz and 1600 MHz and above.
|
||||
int rate = mtc_cfg->mtc_table[i].rate_khz;
|
||||
if ((rate >= FREQ_204 && rate <= FREQ_800) || rate >= FREQ_1600)
|
||||
{
|
||||
memcpy(&mtc_cfg->mtc_table[entries], &mtc_cfg->mtc_table[i], sizeof(emc_table_t));
|
||||
entries++;
|
||||
}
|
||||
}
|
||||
mtc_cfg->table_entries = entries;
|
||||
|
||||
// Do not let other mtc ops.
|
||||
mtc_cfg->init_done = 0;
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ typedef struct
|
|||
bool emc_2X_clk_src_is_pllmb;
|
||||
bool fsp_for_src_freq;
|
||||
bool train_ram_patterns;
|
||||
bool init_done;
|
||||
u32 init_done;
|
||||
} mtc_config_t;
|
||||
|
||||
enum train_mode_t
|
||||
|
@ -53,8 +53,9 @@ enum train_mode_t
|
|||
typedef enum
|
||||
{
|
||||
FREQ_204 = 204000,
|
||||
FREQ_666 = 665600,
|
||||
FREQ_408 = 408000,
|
||||
FREQ_800 = 800000,
|
||||
FREQ_1333 = 1331200,
|
||||
FREQ_1600 = 1600000
|
||||
} minerva_freq_t;
|
||||
|
||||
|
|
254
bdk/mem/sdram.c
254
bdk/mem/sdram.c
|
@ -34,8 +34,6 @@
|
|||
#include <soc/timer.h>
|
||||
#include <soc/t210.h>
|
||||
|
||||
#define CONFIG_SDRAM_KEEP_ALIVE
|
||||
|
||||
#define DRAM_ID(x) BIT(x)
|
||||
#define DRAM_CC(x) BIT(x)
|
||||
|
||||
|
@ -184,16 +182,68 @@ emc_mr_data_t sdram_read_mrx(emc_mr_t mrx)
|
|||
return data;
|
||||
}
|
||||
|
||||
void sdram_src_pllc(bool enable)
|
||||
{
|
||||
static bool enabled = false;
|
||||
|
||||
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210 || enable == enabled)
|
||||
return;
|
||||
|
||||
enabled = enable;
|
||||
|
||||
// Clear CC interrupt.
|
||||
EMC(EMC_INTSTATUS) = BIT(4);
|
||||
(void)EMC(EMC_INTSTATUS);
|
||||
|
||||
u32 clk_src_emc = _dram_cfg_08_10_12_14_samsung_hynix_4gb.emc_clock_source;
|
||||
|
||||
if (enable)
|
||||
{
|
||||
// Check if clock source is not the expected one.
|
||||
if (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) != clk_src_emc)
|
||||
return;
|
||||
|
||||
// Set source as PLLC_OUT0.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = 0x20188004;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Restore MC/EMC clock.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = clk_src_emc;
|
||||
}
|
||||
|
||||
// Wait for CC interrupt.
|
||||
while (!(EMC(EMC_INTSTATUS) & BIT(4)))
|
||||
usleep(1);
|
||||
}
|
||||
|
||||
static void _sdram_config_t210(const sdram_params_t210_t *params)
|
||||
{
|
||||
// VDDP Select.
|
||||
PMC(APBDEV_PMC_VDDP_SEL) = params->pmc_vddp_sel;
|
||||
usleep(params->pmc_vddp_sel_wait);
|
||||
|
||||
// Set DDR pad voltage.
|
||||
PMC(APBDEV_PMC_DDR_PWR) = PMC(APBDEV_PMC_DDR_PWR); // Normally params->pmc_ddr_pwr.
|
||||
|
||||
// Turn on MEM IO Power.
|
||||
PMC(APBDEV_PMC_NO_IOPOWER) &= PMC_NO_IOPOWER_SDMMC1; // Only keep SDMMC1 state. (Was params->pmc_no_io_power).
|
||||
PMC(APBDEV_PMC_REG_SHORT) = params->pmc_reg_short;
|
||||
|
||||
PMC(APBDEV_PMC_DDR_CNTRL) = params->pmc_ddr_ctrl;
|
||||
|
||||
// Patch 1 using BCT spare variables
|
||||
if (params->emc_bct_spare0)
|
||||
*(vu32 *)params->emc_bct_spare0 = params->emc_bct_spare1;
|
||||
|
||||
// Program DPD3/DPD4 regs (coldboot path).
|
||||
// Enable sel_dpd on unused pins.
|
||||
u32 dpd_req = (params->emc_pmc_scratch1 & 0x3FFFFFFF) | (2 << 30u);
|
||||
u32 dpd_req = (params->emc_pmc_scratch1 & 0x3FFFFFFF) | PMC_IO_DPD_REQ_DPD_ON;
|
||||
PMC(APBDEV_PMC_IO_DPD3_REQ) = (dpd_req ^ 0xFFFF) & 0xC000FFFF;
|
||||
usleep(params->pmc_io_dpd3_req_wait);
|
||||
|
||||
// Disable e_dpd_vttgen.
|
||||
dpd_req = (params->emc_pmc_scratch2 & 0x3FFFFFFF) | (2 << 30u);
|
||||
dpd_req = (params->emc_pmc_scratch2 & 0x3FFFFFFF) | PMC_IO_DPD_REQ_DPD_ON;
|
||||
PMC(APBDEV_PMC_IO_DPD4_REQ) = (dpd_req & 0xFFFF0000) ^ 0x3FFF0000;
|
||||
usleep(params->pmc_io_dpd4_req_wait);
|
||||
|
||||
|
@ -204,28 +254,24 @@ static void _sdram_config_t210(const sdram_params_t210_t *params)
|
|||
PMC(APBDEV_PMC_WEAK_BIAS) = 0;
|
||||
usleep(1);
|
||||
|
||||
// Start clocks.
|
||||
// Start PLLM.
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLM_MISC1) = params->pllm_setup_control;
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLM_MISC2) = 0;
|
||||
|
||||
#ifdef CONFIG_SDRAM_KEEP_ALIVE
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLM_BASE) =
|
||||
(params->pllm_feedback_divider << 8) | params->pllm_input_divider | ((params->pllm_post_divider & 0xFFFF) << 20) | PLLCX_BASE_ENABLE;
|
||||
#else
|
||||
u32 pllm_div = (params->pllm_feedback_divider << 8) | params->pllm_input_divider | ((params->pllm_post_divider & 0xFFFF) << 20);
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLM_BASE) = pllm_div;
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLM_BASE) = pllm_div | PLLCX_BASE_ENABLE;
|
||||
#endif
|
||||
|
||||
u32 wait_end = get_tmr_us() + 300;
|
||||
while (!(CLOCK(CLK_RST_CONTROLLER_PLLM_BASE) & 0x8000000))
|
||||
while (!(CLOCK(CLK_RST_CONTROLLER_PLLM_BASE) & BIT(27)))
|
||||
{
|
||||
if (get_tmr_us() >= wait_end)
|
||||
goto break_nosleep;
|
||||
goto lock_timeout;
|
||||
}
|
||||
usleep(10);
|
||||
|
||||
break_nosleep:
|
||||
lock_timeout:
|
||||
// Set clock sources.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = ((params->mc_emem_arb_misc0 >> 11) & 0x10000) | (params->emc_clock_source & 0xFFFEFFFF);
|
||||
if (params->emc_clock_source_dll)
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC_DLL) = params->emc_clock_source_dll;
|
||||
|
@ -237,12 +283,13 @@ break_nosleep:
|
|||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = BIT(CLK_X_EMC_DLL);
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_EMC) | BIT(CLK_H_MEM);
|
||||
|
||||
// Set pad macros.
|
||||
// Set pad vtt levels.
|
||||
EMC(EMC_PMACRO_VTTGEN_CTRL_0) = params->emc_pmacro_vttgen_ctrl0;
|
||||
EMC(EMC_PMACRO_VTTGEN_CTRL_1) = params->emc_pmacro_vttgen_ctrl1;
|
||||
EMC(EMC_PMACRO_VTTGEN_CTRL_2) = params->emc_pmacro_vttgen_ctrl2;
|
||||
|
||||
EMC(EMC_TIMING_CONTROL) = 1; // Trigger timing update so above writes take place.
|
||||
// Trigger timing update so above writes take place.
|
||||
EMC(EMC_TIMING_CONTROL) = 1;
|
||||
usleep(10); // Ensure the regulators settle.
|
||||
|
||||
// Select EMC write mux.
|
||||
|
@ -279,6 +326,7 @@ break_nosleep:
|
|||
// This is required to do any reads from the pad macros.
|
||||
EMC(EMC_CONFIG_SAMPLE_DELAY) = params->emc_config_sample_delay;
|
||||
|
||||
// Set data pipes mode.
|
||||
EMC(EMC_FBIO_CFG8) = params->emc_fbio_cfg8;
|
||||
|
||||
// Set swizzle for Rank 0.
|
||||
|
@ -296,12 +344,12 @@ break_nosleep:
|
|||
if (params->emc_bct_spare6)
|
||||
*(vu32 *)params->emc_bct_spare6 = params->emc_bct_spare7;
|
||||
|
||||
// Set pad controls.
|
||||
// Program calibration impedance.
|
||||
EMC(EMC_XM2COMPPADCTRL) = params->emc_xm2_comp_pad_ctrl;
|
||||
EMC(EMC_XM2COMPPADCTRL2) = params->emc_xm2_comp_pad_ctrl2;
|
||||
EMC(EMC_XM2COMPPADCTRL3) = params->emc_xm2_comp_pad_ctrl3;
|
||||
|
||||
// Program Autocal controls with shadowed register fields.
|
||||
// Program Autocal controls.
|
||||
EMC(EMC_AUTO_CAL_CONFIG2) = params->emc_auto_cal_config2;
|
||||
EMC(EMC_AUTO_CAL_CONFIG3) = params->emc_auto_cal_config3;
|
||||
EMC(EMC_AUTO_CAL_CONFIG4) = params->emc_auto_cal_config4;
|
||||
|
@ -310,6 +358,7 @@ break_nosleep:
|
|||
EMC(EMC_AUTO_CAL_CONFIG7) = params->emc_auto_cal_config7;
|
||||
EMC(EMC_AUTO_CAL_CONFIG8) = params->emc_auto_cal_config8;
|
||||
|
||||
// Program termination and drive strength
|
||||
EMC(EMC_PMACRO_RX_TERM) = params->emc_pmacro_rx_term;
|
||||
EMC(EMC_PMACRO_DQ_TX_DRV) = params->emc_pmacro_dq_tx_drive;
|
||||
EMC(EMC_PMACRO_CA_TX_DRV) = params->emc_pmacro_ca_tx_drive;
|
||||
|
@ -318,10 +367,12 @@ break_nosleep:
|
|||
EMC(EMC_AUTO_CAL_CHANNEL) = params->emc_auto_cal_channel;
|
||||
EMC(EMC_PMACRO_ZCTRL) = params->emc_pmacro_zcrtl;
|
||||
|
||||
// Program dll config.
|
||||
EMC(EMC_DLL_CFG_0) = params->emc_dll_cfg0;
|
||||
EMC(EMC_DLL_CFG_1) = params->emc_dll_cfg1;
|
||||
EMC(EMC_CFG_DIG_DLL_1) = params->emc_cfg_dig_dll_1;
|
||||
|
||||
// Program barrelshift.
|
||||
EMC(EMC_DATA_BRLSHFT_0) = params->emc_data_brlshft0;
|
||||
EMC(EMC_DATA_BRLSHFT_1) = params->emc_data_brlshft1;
|
||||
EMC(EMC_DQS_BRLSHFT_0) = params->emc_dqs_brlshft0;
|
||||
|
@ -335,6 +386,7 @@ break_nosleep:
|
|||
EMC(EMC_QUSE_BRLSHFT_2) = params->emc_quse_brlshft2;
|
||||
EMC(EMC_QUSE_BRLSHFT_3) = params->emc_quse_brlshft3;
|
||||
|
||||
// Program pad macros controls and termination.
|
||||
EMC(EMC_PMACRO_BRICK_CTRL_RFU1) = (params->emc_pmacro_brick_ctrl_rfu1 & 0x1BF01BF) | 0x1E401E40;
|
||||
EMC(EMC_PMACRO_PAD_CFG_CTRL) = params->emc_pmacro_pad_cfg_ctrl;
|
||||
|
||||
|
@ -349,6 +401,7 @@ break_nosleep:
|
|||
EMC(EMC_PMACRO_CMD_RX_TERM_MODE) = params->emc_pmacro_cmd_rx_term_mode;
|
||||
EMC(EMC_PMACRO_CMD_PAD_TX_CTRL) = params->emc_pmacro_cmd_pad_tx_ctrl;
|
||||
|
||||
// Program pad macro pins/bytes.
|
||||
EMC(EMC_CFG_3) = params->emc_cfg3;
|
||||
EMC(EMC_PMACRO_TX_PWRD_0) = params->emc_pmacro_tx_pwrd0;
|
||||
EMC(EMC_PMACRO_TX_PWRD_1) = params->emc_pmacro_tx_pwrd1;
|
||||
|
@ -369,12 +422,15 @@ break_nosleep:
|
|||
EMC(EMC_PMACRO_CMD_CTRL_0) = params->emc_pmacro_cmd_ctrl0;
|
||||
EMC(EMC_PMACRO_CMD_CTRL_1) = params->emc_pmacro_cmd_ctrl1;
|
||||
EMC(EMC_PMACRO_CMD_CTRL_2) = params->emc_pmacro_cmd_ctrl2;
|
||||
|
||||
// Program inbound vref setting.
|
||||
EMC(EMC_PMACRO_IB_VREF_DQ_0) = params->emc_pmacro_ib_vref_dq_0;
|
||||
EMC(EMC_PMACRO_IB_VREF_DQ_1) = params->emc_pmacro_ib_vref_dq_1;
|
||||
EMC(EMC_PMACRO_IB_VREF_DQS_0) = params->emc_pmacro_ib_vref_dqs_0;
|
||||
EMC(EMC_PMACRO_IB_VREF_DQS_1) = params->emc_pmacro_ib_vref_dqs_1;
|
||||
EMC(EMC_PMACRO_IB_RXRT) = params->emc_pmacro_ib_rxrt;
|
||||
|
||||
// Program quse trimmers.
|
||||
EMC(EMC_PMACRO_QUSE_DDLL_RANK0_0) = params->emc_pmacro_quse_ddll_rank0_0;
|
||||
EMC(EMC_PMACRO_QUSE_DDLL_RANK0_1) = params->emc_pmacro_quse_ddll_rank0_1;
|
||||
EMC(EMC_PMACRO_QUSE_DDLL_RANK0_2) = params->emc_pmacro_quse_ddll_rank0_2;
|
||||
|
@ -389,6 +445,7 @@ break_nosleep:
|
|||
EMC(EMC_PMACRO_QUSE_DDLL_RANK1_5) = params->emc_pmacro_quse_ddll_rank1_5;
|
||||
EMC(EMC_PMACRO_BRICK_CTRL_RFU1) = params->emc_pmacro_brick_ctrl_rfu1;
|
||||
|
||||
// Program outbound trimmers.
|
||||
EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0) = params->emc_pmacro_ob_ddll_long_dq_rank0_0;
|
||||
EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1) = params->emc_pmacro_ob_ddll_long_dq_rank0_1;
|
||||
EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2) = params->emc_pmacro_ob_ddll_long_dq_rank0_2;
|
||||
|
@ -423,6 +480,7 @@ break_nosleep:
|
|||
EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_2) = params->emc_pmacro_ib_ddll_long_dqs_rank1_2;
|
||||
EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_3) = params->emc_pmacro_ib_ddll_long_dqs_rank1_3;
|
||||
|
||||
// Program clock trimmers.
|
||||
EMC(EMC_PMACRO_DDLL_LONG_CMD_0) = params->emc_pmacro_ddll_long_cmd_0;
|
||||
EMC(EMC_PMACRO_DDLL_LONG_CMD_1) = params->emc_pmacro_ddll_long_cmd_1;
|
||||
EMC(EMC_PMACRO_DDLL_LONG_CMD_2) = params->emc_pmacro_ddll_long_cmd_2;
|
||||
|
@ -439,7 +497,8 @@ break_nosleep:
|
|||
if (params->emc_bct_spare4)
|
||||
*(vu32 *)params->emc_bct_spare4 = params->emc_bct_spare5;
|
||||
|
||||
EMC(EMC_TIMING_CONTROL) = 1; // Trigger timing update so above writes take place.
|
||||
// Trigger timing update so above writes take place.
|
||||
EMC(EMC_TIMING_CONTROL) = 1;
|
||||
|
||||
// Initialize MC VPR settings.
|
||||
MC(MC_VIDEO_PROTECT_BOM) = params->mc_video_protect_bom;
|
||||
|
@ -504,7 +563,8 @@ break_nosleep:
|
|||
MC(MC_EMEM_ARB_RSV) = params->mc_emem_arb_rsv;
|
||||
MC(MC_DA_CONFIG0) = params->mc_da_cfg0;
|
||||
|
||||
MC(MC_TIMING_CONTROL) = 1; // Trigger MC timing update.
|
||||
// Trigger MC timing update.
|
||||
MC(MC_TIMING_CONTROL) = 1;
|
||||
|
||||
// Program second-level clock enable overrides.
|
||||
MC(MC_CLKEN_OVERRIDE) = params->mc_clken_override;
|
||||
|
@ -526,6 +586,7 @@ break_nosleep:
|
|||
EMC(EMC_AUTO_CAL_VREF_SEL_0) = params->emc_auto_cal_vref_sel0;
|
||||
EMC(EMC_AUTO_CAL_VREF_SEL_1) = params->emc_auto_cal_vref_sel1;
|
||||
|
||||
// Program/Start auto calibration.
|
||||
EMC(EMC_AUTO_CAL_INTERVAL) = params->emc_auto_cal_interval;
|
||||
EMC(EMC_AUTO_CAL_CONFIG) = params->emc_auto_cal_config;
|
||||
usleep(params->emc_auto_cal_wait);
|
||||
|
@ -583,10 +644,12 @@ break_nosleep:
|
|||
EMC(EMC_PMACRO_COMMON_PAD_TX_CTRL) = params->emc_pmacro_common_pad_tx_ctrl;
|
||||
EMC(EMC_DBG) = params->emc_dbg;
|
||||
|
||||
// Clear read fifo.
|
||||
EMC(EMC_QRST) = params->emc_qrst;
|
||||
EMC(EMC_ISSUE_QRST) = 1;
|
||||
EMC(EMC_ISSUE_QRST) = 0;
|
||||
|
||||
// Program the rest of EMC timing configuration.
|
||||
EMC(EMC_QSAFE) = params->emc_qsafe;
|
||||
EMC(EMC_RDV) = params->emc_rdv;
|
||||
EMC(EMC_RDV_MASK) = params->emc_rdv_mask;
|
||||
|
@ -635,14 +698,16 @@ break_nosleep:
|
|||
if (params->boot_rom_patch_control & BIT(31))
|
||||
{
|
||||
*(vu32 *)(APB_MISC_BASE + params->boot_rom_patch_control * 4) = params->boot_rom_patch_data;
|
||||
MC(MC_TIMING_CONTROL) = 1; // Trigger MC timing update.
|
||||
|
||||
// Trigger MC timing update.
|
||||
MC(MC_TIMING_CONTROL) = 1;
|
||||
}
|
||||
|
||||
// Release SEL_DPD_CMD.
|
||||
PMC(APBDEV_PMC_IO_DPD3_REQ) = (params->emc_pmc_scratch1 & 0xFFF0000) | (1 << 30u);
|
||||
PMC(APBDEV_PMC_IO_DPD3_REQ) = (params->emc_pmc_scratch1 & 0xFFF0000) | PMC_IO_DPD_REQ_DPD_OFF;
|
||||
usleep(params->pmc_io_dpd3_req_wait);
|
||||
|
||||
// Set autocal interval if not configured.
|
||||
// Stall auto call measurements if periodic calibration is disabled.
|
||||
if (!params->emc_auto_cal_interval)
|
||||
EMC(EMC_AUTO_CAL_CONFIG) = params->emc_auto_cal_config | 0x200;
|
||||
|
||||
|
@ -655,7 +720,8 @@ break_nosleep:
|
|||
EMC(EMC_ZCAL_MRW_CMD) = params->emc_zcal_mrw_cmd;
|
||||
}
|
||||
|
||||
EMC(EMC_TIMING_CONTROL) = 1; // Trigger timing update so above writes take place.
|
||||
// Trigger timing update so above writes take place.
|
||||
EMC(EMC_TIMING_CONTROL) = 1;
|
||||
usleep(params->emc_timing_control_wait);
|
||||
|
||||
// Deassert HOLD_CKE_LOW.
|
||||
|
@ -724,7 +790,8 @@ break_nosleep:
|
|||
if (params->emc_bct_spare12)
|
||||
*(vu32 *)params->emc_bct_spare12 = params->emc_bct_spare13;
|
||||
|
||||
EMC(EMC_TIMING_CONTROL) = 1; // Trigger timing update so above writes take place.
|
||||
// Trigger timing update so above writes take place.
|
||||
EMC(EMC_TIMING_CONTROL) = 1;
|
||||
|
||||
if (params->emc_extra_refresh_num)
|
||||
EMC(EMC_REF) = (((1 << params->emc_extra_refresh_num) - 1) << 8) | (params->emc_dev_select << 30) | 3;
|
||||
|
@ -742,7 +809,8 @@ break_nosleep:
|
|||
// Write addr swizzle lock bit.
|
||||
EMC(EMC_FBIO_SPARE) = params->emc_fbio_spare | BIT(1);
|
||||
|
||||
EMC(EMC_TIMING_CONTROL) = 1; // Re-trigger timing to latch power saving functions.
|
||||
// Re-trigger timing to latch power saving functions.
|
||||
EMC(EMC_TIMING_CONTROL) = 1;
|
||||
|
||||
// Enable EMC pipe clock gating.
|
||||
EMC(EMC_CFG_PIPE_CLK) = params->emc_cfg_pipe_clk;
|
||||
|
@ -764,8 +832,19 @@ break_nosleep:
|
|||
|
||||
static void _sdram_config_t210b01(const sdram_params_t210b01_t *params)
|
||||
{
|
||||
u32 pmc_scratch1 = ~params->emc_pmc_scratch1;
|
||||
u32 pmc_scratch2 = ~params->emc_pmc_scratch2;
|
||||
// VDDP Select.
|
||||
PMC(APBDEV_PMC_VDDP_SEL) = params->pmc_vddp_sel;
|
||||
usleep(params->pmc_vddp_sel_wait);
|
||||
|
||||
// Turn on MEM IO Power.
|
||||
PMC(APBDEV_PMC_NO_IOPOWER) &= PMC_NO_IOPOWER_SDMMC1; // Only keep SDMMC1 state. (Was params->pmc_no_io_power).
|
||||
PMC(APBDEV_PMC_REG_SHORT) = params->pmc_reg_short;
|
||||
|
||||
PMC(APBDEV_PMC_DDR_CNTRL) = params->pmc_ddr_ctrl;
|
||||
|
||||
// Patch 1 using BCT spare variables
|
||||
if (params->emc_bct_spare0)
|
||||
*(vu32 *)params->emc_bct_spare0 = params->emc_bct_spare1;
|
||||
|
||||
// Override HW FSM if needed.
|
||||
if (params->clk_rst_pllm_misc20_override_enable)
|
||||
|
@ -773,16 +852,18 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params)
|
|||
|
||||
// Program DPD3/DPD4 regs (coldboot path).
|
||||
// Enable sel_dpd on unused pins.
|
||||
u32 pmc_scratch1 = ~params->emc_pmc_scratch1;
|
||||
PMC(APBDEV_PMC_WEAK_BIAS) = (pmc_scratch1 & 0x1000) << 19 | (pmc_scratch1 & 0xFFF) << 18 | (pmc_scratch1 & 0x8000) << 15;
|
||||
PMC(APBDEV_PMC_IO_DPD3_REQ) = (pmc_scratch1 & 0x9FFF) | (2 << 30u);
|
||||
PMC(APBDEV_PMC_IO_DPD3_REQ) = (pmc_scratch1 & 0x9FFF) | PMC_IO_DPD_REQ_DPD_ON;
|
||||
usleep(params->pmc_io_dpd3_req_wait);
|
||||
|
||||
// Disable e_dpd_vttgen.
|
||||
PMC(APBDEV_PMC_IO_DPD4_REQ) = (pmc_scratch2 & 0x3FFF0000) | (2 << 30u);
|
||||
u32 pmc_scratch2 = ~params->emc_pmc_scratch2;
|
||||
PMC(APBDEV_PMC_IO_DPD4_REQ) = (pmc_scratch2 & 0x3FFF0000) | PMC_IO_DPD_REQ_DPD_ON;
|
||||
usleep(params->pmc_io_dpd4_req_wait);
|
||||
|
||||
// Disable e_dpd_bg.
|
||||
PMC(APBDEV_PMC_IO_DPD4_REQ) = (pmc_scratch2 & 0x1FFF) | (2 << 30u);
|
||||
PMC(APBDEV_PMC_IO_DPD4_REQ) = (pmc_scratch2 & 0x1FFF) | PMC_IO_DPD_REQ_DPD_ON;
|
||||
usleep(1);
|
||||
|
||||
// Program CMD mapping. Required before brick mapping, else
|
||||
|
@ -823,7 +904,8 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params)
|
|||
if (params->emc_bct_spare_secure4)
|
||||
*(vu32 *)params->emc_bct_spare_secure4 = params->emc_bct_spare_secure5;
|
||||
|
||||
EMC(EMC_TIMING_CONTROL) = 1; // Trigger timing update so above writes take place.
|
||||
// Trigger timing update so above writes take place.
|
||||
EMC(EMC_TIMING_CONTROL) = 1;
|
||||
usleep(params->pmc_vddp_sel_wait + 2); // Ensure the regulators settle.
|
||||
|
||||
// Set clock sources.
|
||||
|
@ -840,6 +922,7 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params)
|
|||
// This is required to do any reads from the pad macros.
|
||||
EMC(EMC_CONFIG_SAMPLE_DELAY) = params->emc_config_sample_delay;
|
||||
|
||||
// Set data pipes mode.
|
||||
EMC(EMC_FBIO_CFG8) = params->emc_fbio_cfg8;
|
||||
|
||||
// Set swizzle for Rank 0.
|
||||
|
@ -857,12 +940,12 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params)
|
|||
if (params->emc_bct_spare6)
|
||||
*(vu32 *)params->emc_bct_spare6 = params->emc_bct_spare7;
|
||||
|
||||
// Set pad controls.
|
||||
// Program calibration impedance.
|
||||
EMC(EMC_XM2COMPPADCTRL) = params->emc_xm2_comp_pad_ctrl;
|
||||
EMC(EMC_XM2COMPPADCTRL2) = params->emc_xm2_comp_pad_ctrl2;
|
||||
EMC(EMC_XM2COMPPADCTRL3) = params->emc_xm2_comp_pad_ctrl3;
|
||||
|
||||
// Program Autocal controls with shadowed register fields.
|
||||
// Program Autocal controls.
|
||||
EMC(EMC_AUTO_CAL_CONFIG2) = params->emc_auto_cal_config2;
|
||||
EMC(EMC_AUTO_CAL_CONFIG3) = params->emc_auto_cal_config3;
|
||||
EMC(EMC_AUTO_CAL_CONFIG4) = params->emc_auto_cal_config4;
|
||||
|
@ -871,6 +954,7 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params)
|
|||
EMC(EMC_AUTO_CAL_CONFIG7) = params->emc_auto_cal_config7;
|
||||
EMC(EMC_AUTO_CAL_CONFIG8) = params->emc_auto_cal_config8;
|
||||
|
||||
// Program termination and drive strength
|
||||
EMC(EMC_PMACRO_RX_TERM) = params->emc_pmacro_rx_term;
|
||||
EMC(EMC_PMACRO_DQ_TX_DRV) = params->emc_pmacro_dq_tx_drive;
|
||||
EMC(EMC_PMACRO_CA_TX_DRV) = params->emc_pmacro_ca_tx_drive;
|
||||
|
@ -879,10 +963,12 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params)
|
|||
EMC(EMC_AUTO_CAL_CHANNEL) = params->emc_auto_cal_channel;
|
||||
EMC(EMC_PMACRO_ZCTRL) = params->emc_pmacro_zcrtl;
|
||||
|
||||
// Program dll config.
|
||||
EMC(EMC_DLL_CFG_0) = params->emc_dll_cfg0;
|
||||
EMC(EMC_DLL_CFG_1) = params->emc_dll_cfg1;
|
||||
EMC(EMC_CFG_DIG_DLL_1) = params->emc_cfg_dig_dll_1;
|
||||
|
||||
// Program barrelshift.
|
||||
EMC(EMC_DATA_BRLSHFT_0) = params->emc_data_brlshft0;
|
||||
EMC(EMC_DATA_BRLSHFT_1) = params->emc_data_brlshft1;
|
||||
EMC(EMC_DQS_BRLSHFT_0) = params->emc_dqs_brlshft0;
|
||||
|
@ -896,6 +982,7 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params)
|
|||
EMC(EMC_QUSE_BRLSHFT_2) = params->emc_quse_brlshft2;
|
||||
EMC(EMC_QUSE_BRLSHFT_3) = params->emc_quse_brlshft3;
|
||||
|
||||
// Program pad macros controls and termination.
|
||||
EMC(EMC_PMACRO_BRICK_CTRL_RFU1) = params->emc_pmacro_brick_ctrl_rfu1;
|
||||
EMC(EMC_PMACRO_PAD_CFG_CTRL) = params->emc_pmacro_pad_cfg_ctrl;
|
||||
|
||||
|
@ -909,6 +996,7 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params)
|
|||
EMC(EMC_PMACRO_CMD_RX_TERM_MODE) = params->emc_pmacro_cmd_rx_term_mode;
|
||||
EMC(EMC_PMACRO_CMD_PAD_TX_CTRL) = params->emc_pmacro_cmd_pad_tx_ctrl & 0xEFFFFFFF;
|
||||
|
||||
// Program pad macro pins/bytes.
|
||||
EMC(EMC_CFG_3) = params->emc_cfg3;
|
||||
EMC(EMC_PMACRO_TX_PWRD_0) = params->emc_pmacro_tx_pwrd0;
|
||||
EMC(EMC_PMACRO_TX_PWRD_1) = params->emc_pmacro_tx_pwrd1;
|
||||
|
@ -952,12 +1040,15 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params)
|
|||
EMC(EMC_PMACRO_CMD_CTRL_0) = params->emc_pmacro_cmd_ctrl0;
|
||||
EMC(EMC_PMACRO_CMD_CTRL_1) = params->emc_pmacro_cmd_ctrl1;
|
||||
EMC(EMC_PMACRO_CMD_CTRL_2) = params->emc_pmacro_cmd_ctrl2;
|
||||
|
||||
// Program inbound vref setting.
|
||||
EMC(EMC_PMACRO_IB_VREF_DQ_0) = params->emc_pmacro_ib_vref_dq_0;
|
||||
EMC(EMC_PMACRO_IB_VREF_DQ_1) = params->emc_pmacro_ib_vref_dq_1;
|
||||
EMC(EMC_PMACRO_IB_VREF_DQS_0) = params->emc_pmacro_ib_vref_dqs_0;
|
||||
EMC(EMC_PMACRO_IB_VREF_DQS_1) = params->emc_pmacro_ib_vref_dqs_1;
|
||||
EMC(EMC_PMACRO_IB_RXRT) = params->emc_pmacro_ib_rxrt;
|
||||
|
||||
// Program quse trimmers.
|
||||
EMC(EMC_PMACRO_QUSE_DDLL_RANK0_0) = params->emc_pmacro_quse_ddll_rank0_0;
|
||||
EMC(EMC_PMACRO_QUSE_DDLL_RANK0_1) = params->emc_pmacro_quse_ddll_rank0_1;
|
||||
EMC(EMC_PMACRO_QUSE_DDLL_RANK0_2) = params->emc_pmacro_quse_ddll_rank0_2;
|
||||
|
@ -971,6 +1062,7 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params)
|
|||
EMC(EMC_PMACRO_QUSE_DDLL_RANK1_4) = params->emc_pmacro_quse_ddll_rank1_4;
|
||||
EMC(EMC_PMACRO_QUSE_DDLL_RANK1_5) = params->emc_pmacro_quse_ddll_rank1_5;
|
||||
|
||||
// Program outbound trimmers.
|
||||
EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0) = params->emc_pmacro_ob_ddll_long_dq_rank0_0;
|
||||
EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1) = params->emc_pmacro_ob_ddll_long_dq_rank0_1;
|
||||
EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2) = params->emc_pmacro_ob_ddll_long_dq_rank0_2;
|
||||
|
@ -1005,6 +1097,7 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params)
|
|||
EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_2) = params->emc_pmacro_ib_ddll_long_dqs_rank1_2;
|
||||
EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_3) = params->emc_pmacro_ib_ddll_long_dqs_rank1_3;
|
||||
|
||||
// Program clock trimmers.
|
||||
EMC(EMC_PMACRO_DDLL_LONG_CMD_0) = params->emc_pmacro_ddll_long_cmd_0;
|
||||
EMC(EMC_PMACRO_DDLL_LONG_CMD_1) = params->emc_pmacro_ddll_long_cmd_1;
|
||||
EMC(EMC_PMACRO_DDLL_LONG_CMD_2) = params->emc_pmacro_ddll_long_cmd_2;
|
||||
|
@ -1029,7 +1122,8 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params)
|
|||
if (params->emc_bct_spare_secure10)
|
||||
*(vu32 *)params->emc_bct_spare_secure10 = params->emc_bct_spare_secure11;
|
||||
|
||||
EMC(EMC_TIMING_CONTROL) = 1; // Trigger timing update so above writes take place.
|
||||
// Trigger timing update so above writes take place.
|
||||
EMC(EMC_TIMING_CONTROL) = 1;
|
||||
|
||||
// Initialize MC VPR settings.
|
||||
MC(MC_VIDEO_PROTECT_BOM) = params->mc_video_protect_bom;
|
||||
|
@ -1094,7 +1188,8 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params)
|
|||
MC(MC_EMEM_ARB_RSV) = params->mc_emem_arb_rsv;
|
||||
MC(MC_DA_CONFIG0) = params->mc_da_cfg0;
|
||||
|
||||
MC(MC_TIMING_CONTROL) = 1; // Trigger MC timing update.
|
||||
// Trigger MC timing update.
|
||||
MC(MC_TIMING_CONTROL) = 1;
|
||||
|
||||
// Program second-level clock enable overrides.
|
||||
MC(MC_CLKEN_OVERRIDE) = params->mc_clken_override;
|
||||
|
@ -1116,6 +1211,7 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params)
|
|||
EMC(EMC_AUTO_CAL_VREF_SEL_0) = params->emc_auto_cal_vref_sel0;
|
||||
EMC(EMC_AUTO_CAL_VREF_SEL_1) = params->emc_auto_cal_vref_sel1;
|
||||
|
||||
// Program/Start auto calibration.
|
||||
EMC(EMC_AUTO_CAL_INTERVAL) = params->emc_auto_cal_interval;
|
||||
EMC(EMC_AUTO_CAL_CONFIG) = params->emc_auto_cal_config;
|
||||
usleep(params->emc_auto_cal_wait);
|
||||
|
@ -1179,10 +1275,12 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params)
|
|||
|
||||
EMC(EMC_DBG) = params->emc_dbg;
|
||||
|
||||
// Clear read fifo.
|
||||
EMC(EMC_QRST) = params->emc_qrst;
|
||||
EMC(EMC_ISSUE_QRST) = 1;
|
||||
EMC(EMC_ISSUE_QRST) = 0;
|
||||
|
||||
// Program the rest of EMC timing configuration.
|
||||
EMC(EMC_QSAFE) = params->emc_qsafe;
|
||||
EMC(EMC_RDV) = params->emc_rdv;
|
||||
EMC(EMC_RDV_MASK) = params->emc_rdv_mask;
|
||||
|
@ -1232,7 +1330,9 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params)
|
|||
if (params->boot_rom_patch_control)
|
||||
{
|
||||
*(vu32 *)params->boot_rom_patch_control = params->boot_rom_patch_data;
|
||||
MC(MC_TIMING_CONTROL) = 1; // Trigger MC timing update.
|
||||
|
||||
// Trigger MC timing update.
|
||||
MC(MC_TIMING_CONTROL) = 1;
|
||||
}
|
||||
|
||||
// Patch 7 to 9 using BCT spare secure variables.
|
||||
|
@ -1244,7 +1344,7 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params)
|
|||
*(vu32 *)params->emc_bct_spare_secure16 = params->emc_bct_spare_secure17;
|
||||
|
||||
// Release SEL_DPD_CMD.
|
||||
PMC(APBDEV_PMC_IO_DPD3_REQ) = (params->emc_pmc_scratch1 & 0xFFF0000) | (1 << 30u);
|
||||
PMC(APBDEV_PMC_IO_DPD3_REQ) = (params->emc_pmc_scratch1 & 0xFFF0000) | PMC_IO_DPD_REQ_DPD_OFF;
|
||||
usleep(params->pmc_io_dpd3_req_wait);
|
||||
|
||||
// Set transmission pad control parameters.
|
||||
|
@ -1257,7 +1357,8 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params)
|
|||
EMC(EMC_ZCAL_MRW_CMD) = params->emc_zcal_mrw_cmd;
|
||||
}
|
||||
|
||||
EMC(EMC_TIMING_CONTROL) = 1; // Trigger timing update so above writes take place.
|
||||
// Trigger timing update so above writes take place.
|
||||
EMC(EMC_TIMING_CONTROL) = 1;
|
||||
usleep(params->emc_timing_control_wait);
|
||||
|
||||
// Deassert HOLD_CKE_LOW.
|
||||
|
@ -1334,7 +1435,8 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params)
|
|||
if (params->emc_bct_spare12)
|
||||
*(vu32 *)params->emc_bct_spare12 = params->emc_bct_spare13;
|
||||
|
||||
EMC(EMC_TIMING_CONTROL) = 1; // Trigger timing update so above writes take place.
|
||||
// Trigger timing update so above writes take place.
|
||||
EMC(EMC_TIMING_CONTROL) = 1;
|
||||
|
||||
if (params->emc_extra_refresh_num)
|
||||
EMC(EMC_REF) = ((1 << params->emc_extra_refresh_num << 8) - 253) | (params->emc_dev_select << 30);
|
||||
|
@ -1351,7 +1453,8 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params)
|
|||
// Write addr swizzle lock bit.
|
||||
EMC(EMC_FBIO_SPARE) = params->emc_fbio_spare | BIT(1);
|
||||
|
||||
EMC(EMC_TIMING_CONTROL) = 1; // Re-trigger timing to latch power saving functions.
|
||||
// Re-trigger timing to latch power saving functions.
|
||||
EMC(EMC_TIMING_CONTROL) = 1;
|
||||
|
||||
EMC(EMC_CFG_UPDATE) = params->emc_cfg_update;
|
||||
|
||||
|
@ -1452,65 +1555,28 @@ void *sdram_get_params_patched()
|
|||
return (void *)sdram_params;
|
||||
}
|
||||
|
||||
static void _sdram_init_t210()
|
||||
{
|
||||
const sdram_params_t210_t *params = (const sdram_params_t210_t *)_sdram_get_params_t210();
|
||||
if (params->memory_type != MEMORY_TYPE_LPDDR4)
|
||||
return;
|
||||
|
||||
// Set DRAM voltage.
|
||||
max7762x_regulator_set_voltage(REGULATOR_SD1, 1125000); // HOS: 1.125V. Bootloader: 1.1V.
|
||||
|
||||
// VDDP Select.
|
||||
PMC(APBDEV_PMC_VDDP_SEL) = params->pmc_vddp_sel;
|
||||
usleep(params->pmc_vddp_sel_wait);
|
||||
|
||||
// Set DDR pad voltage.
|
||||
PMC(APBDEV_PMC_DDR_PWR) = PMC(APBDEV_PMC_DDR_PWR); // Normally params->pmc_ddr_pwr.
|
||||
|
||||
// Turn on MEM IO Power.
|
||||
PMC(APBDEV_PMC_NO_IOPOWER) = params->pmc_no_io_power;
|
||||
PMC(APBDEV_PMC_REG_SHORT) = params->pmc_reg_short;
|
||||
|
||||
PMC(APBDEV_PMC_DDR_CNTRL) = params->pmc_ddr_ctrl;
|
||||
|
||||
// Patch 1 using BCT spare variables
|
||||
if (params->emc_bct_spare0)
|
||||
*(vu32 *)params->emc_bct_spare0 = params->emc_bct_spare1;
|
||||
|
||||
_sdram_config_t210(params);
|
||||
}
|
||||
|
||||
static void _sdram_init_t210b01()
|
||||
{
|
||||
const sdram_params_t210b01_t *params = (const sdram_params_t210b01_t *)sdram_get_params_t210b01();
|
||||
if (params->memory_type != MEMORY_TYPE_LPDDR4)
|
||||
return;
|
||||
|
||||
// VDDP Select.
|
||||
PMC(APBDEV_PMC_VDDP_SEL) = params->pmc_vddp_sel;
|
||||
usleep(params->pmc_vddp_sel_wait);
|
||||
|
||||
// Turn on MEM IO Power.
|
||||
PMC(APBDEV_PMC_NO_IOPOWER) = params->pmc_no_io_power;
|
||||
PMC(APBDEV_PMC_REG_SHORT) = params->pmc_reg_short;
|
||||
|
||||
PMC(APBDEV_PMC_DDR_CNTRL) = params->pmc_ddr_ctrl;
|
||||
|
||||
// Patch 1 using BCT spare variables
|
||||
if (params->emc_bct_spare0)
|
||||
*(vu32 *)params->emc_bct_spare0 = params->emc_bct_spare1;
|
||||
|
||||
_sdram_config_t210b01(params);
|
||||
}
|
||||
|
||||
void sdram_init()
|
||||
{
|
||||
// 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();
|
||||
{
|
||||
const sdram_params_t210_t *params = (const sdram_params_t210_t *)_sdram_get_params_t210();
|
||||
if (params->memory_type != MEMORY_TYPE_LPDDR4)
|
||||
return;
|
||||
|
||||
// Set DRAM voltage.
|
||||
max7762x_regulator_set_voltage(REGULATOR_SD1, 1125000); // HOS: 1.125V. Bootloader: 1.1V.
|
||||
|
||||
_sdram_config_t210(params);
|
||||
}
|
||||
else
|
||||
_sdram_init_t210b01();
|
||||
{
|
||||
const sdram_params_t210b01_t *params = (const sdram_params_t210b01_t *)sdram_get_params_t210b01();
|
||||
if (params->memory_type != MEMORY_TYPE_LPDDR4)
|
||||
return;
|
||||
|
||||
_sdram_config_t210b01(params);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,14 @@ enum sdram_ids_erista
|
|||
|
||||
LPDDR4_ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH = 4, // Die-C. (2y-01).
|
||||
|
||||
// Custom hekate/L4T supported 8GB. 7 dram id can be easily applied in fuses.
|
||||
/*
|
||||
* Custom hekate/L4T supported 8GB. 7 dram id can be easily applied in fuses.
|
||||
*
|
||||
* 4GB modules:
|
||||
* Samsung K4FBE3D4HM-MGCH/CJ/CL. MG/TF/GF/TH/GH: Package + Temperature.
|
||||
* Hynix H9HCNNNCPUMLXR-NME/NEE/NEI. E/I: Temperature.
|
||||
* Hynix H54G56BYYVX046/QX046/PX046. V/Q/P: Package + Temperature.
|
||||
*/
|
||||
LPDDR4_ICOSA_8GB_SAMSUNG_K4FBE3D4HM_MGXX = 7, // XX: CH/CJ/CL.
|
||||
};
|
||||
|
||||
|
@ -128,6 +135,7 @@ void sdram_init();
|
|||
void *sdram_get_params_patched();
|
||||
void *sdram_get_params_t210b01();
|
||||
void sdram_lp0_save_params(const void *params);
|
||||
void sdram_src_pllc(bool enable);
|
||||
emc_mr_data_t sdram_read_mrx(emc_mr_t mrx);
|
||||
|
||||
#endif
|
||||
|
|
230
bdk/mem/smmu.c
230
bdk/mem/smmu.c
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 balika011
|
||||
* Copyright (c) 2018-2022 CTCaer
|
||||
* Copyright (c) 2018-2024 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
|
@ -18,156 +18,228 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
#include <soc/bpmp.h>
|
||||
#include <soc/ccplex.h>
|
||||
#include <soc/timer.h>
|
||||
#include <soc/t210.h>
|
||||
#include <mem/mc_t210.h>
|
||||
#include <mem/smmu.h>
|
||||
#include <utils/aarch64_util.h>
|
||||
#include <memory_map.h>
|
||||
|
||||
bool smmu_used = false;
|
||||
u8 *_pageheap = (u8 *)SMMU_HEAP_ADDR;
|
||||
/*! SMMU register defines */
|
||||
#define SMMU_ASID(asid) (((asid) << 24u) | ((asid) << 16u) | ((asid) << 8u) | (asid))
|
||||
#define SMMU_ENABLE BIT(31)
|
||||
#define SMMU_TLB_ACTIVE_LINES(l) ((l) << 0u)
|
||||
#define SMMU_TLB_RR_ARBITRATION BIT(28)
|
||||
#define SMMU_TLB_HIT_UNDER_MISS BIT(29)
|
||||
#define SMMU_TLB_STATS_ENABLE BIT(31)
|
||||
#define SMUU_PTC_INDEX_MAP(m) ((m) << 0u)
|
||||
#define SMUU_PTC_LINE_MASK(m) ((m) << 8u)
|
||||
#define SMUU_PTC_REQ_LIMIT(l) ((l) << 24u)
|
||||
#define SMUU_PTC_CACHE_ENABLE BIT(29)
|
||||
#define SMUU_PTC_STATS_ENABLE BIT(31)
|
||||
|
||||
//Enabling SMMU requires a TZ secure write: MC(MC_SMMU_CONFIG) = 1;
|
||||
u8 smmu_payload[] __attribute__((aligned(16))) = {
|
||||
0x41, 0x01, 0x00, 0x58, // 0x00: LDR X1, =0x70019010
|
||||
/*! Page table defines */
|
||||
#define SMMU_4MB_REGION 0
|
||||
#define SMMU_PAGE_TABLE 1
|
||||
#define SMMU_PDIR_COUNT 1024
|
||||
#define SMMU_PTBL_COUNT 1024
|
||||
#define SMMU_PAGE_SHIFT 12u
|
||||
#define SMMU_PTN_SHIFT SMMU_PAGE_SHIFT
|
||||
#define SMMU_PDN_SHIFT 22u
|
||||
#define SMMU_ADDR_TO_PFN(addr) ((addr) >> SMMU_PAGE_SHIFT)
|
||||
#define SMMU_ADDR_TO_PTN(addr) ((addr) >> SMMU_PTN_SHIFT)
|
||||
#define SMMU_ADDR_TO_PDN(addr) ((addr) >> SMMU_PDN_SHIFT)
|
||||
#define SMMU_PTN_TO_ADDR(ptn) ((ptn) << SMMU_PTN_SHIFT)
|
||||
#define SMMU_PDN_TO_ADDR(pdn) ((pdn) << SMMU_PDN_SHIFT)
|
||||
#define SMMU_PTB(page, attr) (((attr) << 29u) | ((page) >> SMMU_PAGE_SHIFT))
|
||||
|
||||
static void *smmu_heap = (void *)SMMU_HEAP_ADDR;
|
||||
|
||||
// Enabling SMMU requires a TZ (EL3) secure write. MC(MC_SMMU_CONFIG) = 1;
|
||||
static const u8 smmu_enable_payload[] = {
|
||||
0xC1, 0x00, 0x00, 0x18, // 0x00: LDR W1, =0x70019010
|
||||
0x20, 0x00, 0x80, 0xD2, // 0x04: MOV X0, #0x1
|
||||
0x20, 0x00, 0x00, 0xB9, // 0x08: STR W0, [X1]
|
||||
0x1F, 0x71, 0x08, 0xD5, // 0x0C: IC IALLUIS
|
||||
0x9F, 0x3B, 0x03, 0xD5, // 0x10: DSB ISH
|
||||
0xFE, 0xFF, 0xFF, 0x17, // 0x14: B loop
|
||||
0x00, 0x00, 0x80, 0xD2, // 0x18: MOV X0, #0x0
|
||||
0x20, 0x00, 0x00, 0xB9, // 0x1C: STR W0, [X1]
|
||||
0x80, 0x00, 0x00, 0x58, // 0x20: LDR X0, =0x4002B000
|
||||
0x00, 0x00, 0x1F, 0xD6, // 0x28: BR X0
|
||||
0x10, 0x90, 0x01, 0x70, // 0x28: MC_SMMU_CONFIG
|
||||
0x00, 0x00, 0x00, 0x00, // 0x2C:
|
||||
0x00, 0x00, 0x00, 0x00, // 0x30: secmon address
|
||||
0x00, 0x00, 0x00, 0x00 // 0x34:
|
||||
0x10, 0x90, 0x01, 0x70, // 0x18: MC_SMMU_CONFIG
|
||||
};
|
||||
|
||||
void *page_alloc(u32 num)
|
||||
void *smmu_page_zalloc(u32 num)
|
||||
{
|
||||
u8 *res = _pageheap;
|
||||
_pageheap += SZ_PAGE * num;
|
||||
memset(res, 0, SZ_PAGE * num);
|
||||
return res;
|
||||
void *page = smmu_heap;
|
||||
memset(page, 0, SZ_PAGE * num);
|
||||
|
||||
smmu_heap += SZ_PAGE * num;
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
u32 *smmu_alloc_pdir()
|
||||
static pde_t *_smmu_pdir_alloc()
|
||||
{
|
||||
u32 *pdir = (u32 *)page_alloc(1);
|
||||
for (int pdn = 0; pdn < SMMU_PDIR_COUNT; pdn++)
|
||||
pdir[pdn] = _PDE_VACANT(pdn);
|
||||
pde_t *pdir = (pde_t *)smmu_page_zalloc(1);
|
||||
|
||||
// Initialize pdes with no permissions.
|
||||
for (u32 pdn = 0; pdn < SMMU_PDIR_COUNT; pdn++)
|
||||
pdir[pdn].huge.page = pdn;
|
||||
|
||||
return pdir;
|
||||
}
|
||||
|
||||
void smmu_flush_regs()
|
||||
static void _smmu_flush_regs()
|
||||
{
|
||||
(void)MC(MC_SMMU_PTB_DATA);
|
||||
}
|
||||
|
||||
void smmu_flush_all()
|
||||
{
|
||||
MC(MC_SMMU_PTC_FLUSH) = 0;
|
||||
smmu_flush_regs();
|
||||
|
||||
// Flush the entire page table cache.
|
||||
MC(MC_SMMU_PTC_FLUSH) = 0;
|
||||
_smmu_flush_regs();
|
||||
|
||||
// Flush the entire table.
|
||||
MC(MC_SMMU_TLB_FLUSH) = 0;
|
||||
smmu_flush_regs();
|
||||
_smmu_flush_regs();
|
||||
}
|
||||
|
||||
void smmu_init(u32 secmon_base)
|
||||
void smmu_init()
|
||||
{
|
||||
MC(MC_SMMU_PTB_ASID) = 0;
|
||||
MC(MC_SMMU_PTB_DATA) = 0;
|
||||
MC(MC_SMMU_TLB_CONFIG) = 0x30000030;
|
||||
MC(MC_SMMU_PTC_CONFIG) = 0x28000F3F;
|
||||
MC(MC_SMMU_TLB_CONFIG) = SMMU_TLB_HIT_UNDER_MISS | SMMU_TLB_RR_ARBITRATION | SMMU_TLB_ACTIVE_LINES(48);
|
||||
MC(MC_SMMU_PTC_CONFIG) = SMUU_PTC_CACHE_ENABLE | SMUU_PTC_REQ_LIMIT(8) | SMUU_PTC_LINE_MASK(0xF) | SMUU_PTC_INDEX_MAP(0x3F);
|
||||
MC(MC_SMMU_PTC_FLUSH) = 0;
|
||||
MC(MC_SMMU_TLB_FLUSH) = 0;
|
||||
|
||||
// Set the secmon address
|
||||
*(u32 *)(smmu_payload + 0x30) = secmon_base;
|
||||
}
|
||||
|
||||
void smmu_enable()
|
||||
{
|
||||
if (smmu_used)
|
||||
static bool enabled = false;
|
||||
|
||||
if (enabled)
|
||||
return;
|
||||
|
||||
ccplex_boot_cpu0((u32)smmu_payload);
|
||||
smmu_used = true;
|
||||
msleep(150);
|
||||
// Launch payload on CCPLEX in order to set SMMU enable bit.
|
||||
ccplex_boot_cpu0((u32)smmu_enable_payload, false);
|
||||
msleep(100);
|
||||
ccplex_powergate_cpu0();
|
||||
|
||||
smmu_flush_all();
|
||||
|
||||
enabled = true;
|
||||
}
|
||||
|
||||
bool smmu_is_used()
|
||||
void smmu_reset_heap()
|
||||
{
|
||||
return smmu_used;
|
||||
smmu_heap = (void *)SMMU_HEAP_ADDR;
|
||||
}
|
||||
|
||||
void smmu_exit()
|
||||
void *smmu_init_domain(u32 dev_base, u32 asid)
|
||||
{
|
||||
*(u32 *)(smmu_payload + 0x14) = _NOP();
|
||||
}
|
||||
|
||||
u32 *smmu_init_domain4(u32 dev_base, u32 asid)
|
||||
{
|
||||
u32 *pdir = smmu_alloc_pdir();
|
||||
void *ptb = _smmu_pdir_alloc();
|
||||
|
||||
MC(MC_SMMU_PTB_ASID) = asid;
|
||||
MC(MC_SMMU_PTB_DATA) = SMMU_MK_PDIR((u32)pdir, _PDIR_ATTR);
|
||||
smmu_flush_regs();
|
||||
MC(MC_SMMU_PTB_DATA) = SMMU_PTB((u32)ptb, SMMU_ATTR_ALL);
|
||||
_smmu_flush_regs();
|
||||
|
||||
MC(dev_base) = 0x80000000 | (asid << 24) | (asid << 16) | (asid << 8) | (asid);
|
||||
smmu_flush_regs();
|
||||
// Use the same macro for both quad and single domains. Reserved bits are not set anyway.
|
||||
MC(dev_base) = SMMU_ENABLE | SMMU_ASID(asid);
|
||||
_smmu_flush_regs();
|
||||
|
||||
return pdir;
|
||||
return ptb;
|
||||
}
|
||||
|
||||
u32 *smmu_get_pte(u32 *pdir, u32 iova)
|
||||
void smmu_deinit_domain(u32 dev_base, u32 asid)
|
||||
{
|
||||
u32 ptn = SMMU_ADDR_TO_PFN(iova);
|
||||
u32 pdn = SMMU_ADDR_TO_PDN(iova);
|
||||
u32 *ptbl;
|
||||
MC(MC_SMMU_PTB_ASID) = asid;
|
||||
MC(MC_SMMU_PTB_DATA) = 0;
|
||||
MC(dev_base) = 0;
|
||||
_smmu_flush_regs();
|
||||
}
|
||||
|
||||
if (pdir[pdn] != _PDE_VACANT(pdn))
|
||||
ptbl = (u32 *)((pdir[pdn] & SMMU_PFN_MASK) << SMMU_PDIR_SHIFT);
|
||||
void smmu_domain_bypass(u32 dev_base, bool bypass)
|
||||
{
|
||||
if (bypass)
|
||||
{
|
||||
smmu_flush_all();
|
||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
|
||||
MC(dev_base) &= ~SMMU_ENABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptbl = (u32 *)page_alloc(1);
|
||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
|
||||
MC(dev_base) |= SMMU_ENABLE;
|
||||
smmu_flush_all();
|
||||
}
|
||||
_smmu_flush_regs();
|
||||
}
|
||||
|
||||
static pte_t *_smmu_get_pte(pde_t *pdir, u32 iova)
|
||||
{
|
||||
u32 pdn = SMMU_ADDR_TO_PDN(iova);
|
||||
pte_t *ptbl;
|
||||
|
||||
// Get 4MB page table or initialize one.
|
||||
if (pdir[pdn].tbl.attr)
|
||||
ptbl = (pte_t *)(SMMU_PTN_TO_ADDR(pdir[pdn].tbl.table));
|
||||
else
|
||||
{
|
||||
// Allocate page table.
|
||||
ptbl = (pte_t *)smmu_page_zalloc(1);
|
||||
|
||||
// Get address.
|
||||
u32 addr = SMMU_PDN_TO_ADDR(pdn);
|
||||
for (int pn = 0; pn < SMMU_PTBL_COUNT; pn++, addr += SMMU_PAGE_SIZE)
|
||||
ptbl[pn] = _PTE_VACANT(addr);
|
||||
pdir[pdn] = SMMU_MK_PDE((u32)ptbl, _PDE_ATTR | _PDE_NEXT);
|
||||
|
||||
// Initialize page table with no permissions.
|
||||
for (u32 pn = 0; pn < SMMU_PTBL_COUNT; pn++, addr += SZ_PAGE)
|
||||
ptbl[pn].page = SMMU_ADDR_TO_PFN(addr);
|
||||
|
||||
// Set page table to the page directory.
|
||||
pdir[pdn].tbl.table = SMMU_ADDR_TO_PTN((u32)ptbl);
|
||||
pdir[pdn].tbl.next = SMMU_PAGE_TABLE;
|
||||
pdir[pdn].tbl.attr = SMMU_ATTR_ALL;
|
||||
|
||||
smmu_flush_all();
|
||||
}
|
||||
|
||||
return &ptbl[ptn % SMMU_PTBL_COUNT];
|
||||
return &ptbl[SMMU_ADDR_TO_PTN(iova) % SMMU_PTBL_COUNT];
|
||||
}
|
||||
|
||||
void smmu_map(u32 *pdir, u32 addr, u32 page, int cnt, u32 attr)
|
||||
void smmu_map(void *ptb, u32 iova, u64 iopa, u32 pages, u32 attr)
|
||||
{
|
||||
for (int i = 0; i < cnt; i++)
|
||||
// Map pages to page table entries. VA/PA should be aligned to 4KB.
|
||||
for (u32 i = 0; i < pages; i++)
|
||||
{
|
||||
u32 *pte = smmu_get_pte(pdir, addr);
|
||||
*pte = SMMU_ADDR_TO_PFN(page) | attr;
|
||||
addr += SZ_PAGE;
|
||||
page += SZ_PAGE;
|
||||
pte_t *pte = _smmu_get_pte((pde_t *)ptb, iova);
|
||||
|
||||
pte->page = SMMU_ADDR_TO_PFN(iopa);
|
||||
pte->attr = attr;
|
||||
|
||||
iova += SZ_PAGE;
|
||||
iopa += SZ_PAGE;
|
||||
}
|
||||
|
||||
smmu_flush_all();
|
||||
}
|
||||
|
||||
u32 *smmu_init_for_tsec()
|
||||
void smmu_map_huge(void *ptb, u32 iova, u64 iopa, u32 regions, u32 attr)
|
||||
{
|
||||
return smmu_init_domain4(MC_SMMU_TSEC_ASID, 1);
|
||||
}
|
||||
pde_t *pdir = (pde_t *)ptb;
|
||||
|
||||
void smmu_deinit_for_tsec()
|
||||
{
|
||||
MC(MC_SMMU_PTB_ASID) = 1;
|
||||
MC(MC_SMMU_PTB_DATA) = 0;
|
||||
MC(MC_SMMU_TSEC_ASID) = 0;
|
||||
smmu_flush_regs();
|
||||
}
|
||||
// Map 4MB regions to page directory entries. VA/PA should be aligned to 4MB.
|
||||
for (u32 i = 0; i < regions; i++)
|
||||
{
|
||||
u32 pdn = SMMU_ADDR_TO_PDN(iova);
|
||||
pdir[pdn].huge.page = SMMU_ADDR_TO_PDN(iopa);
|
||||
pdir[pdn].huge.next = SMMU_4MB_REGION;
|
||||
pdir[pdn].huge.attr = attr;
|
||||
|
||||
iova += SZ_4M;
|
||||
iopa += SZ_4M;
|
||||
}
|
||||
|
||||
smmu_flush_all();
|
||||
}
|
||||
|
|
110
bdk/mem/smmu.h
110
bdk/mem/smmu.h
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2024 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,
|
||||
|
@ -14,70 +15,57 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <utils/types.h>
|
||||
|
||||
#define SMMU_HEAP_ADDR 0xA0000000
|
||||
|
||||
#define MC_INTSTATUS 0x0
|
||||
#define MC_INTMASK 0x4
|
||||
#define MC_ERR_STATUS 0x8
|
||||
#define MC_ERR_ADR 0xc
|
||||
#define MC_SMMU_CONFIG 0x10
|
||||
#define MC_SMMU_TLB_CONFIG 0x14
|
||||
#define MC_SMMU_PTC_CONFIG 0x18
|
||||
#define MC_SMMU_PTB_ASID 0x1c
|
||||
#define MC_SMMU_PTB_DATA 0x20
|
||||
#define MC_SMMU_TLB_FLUSH 0x30
|
||||
#define MC_SMMU_PTC_FLUSH 0x34
|
||||
#define MC_SMMU_ASID_SECURITY 0x38
|
||||
#define MC_SMMU_AVPC_ASID 0x23C
|
||||
#define MC_SMMU_TSEC_ASID 0x294
|
||||
#define MC_SMMU_TRANSLATION_ENABLE_0 0x228
|
||||
#define MC_SMMU_TRANSLATION_ENABLE_1 0x22c
|
||||
#define MC_SMMU_TRANSLATION_ENABLE_2 0x230
|
||||
#define MC_SMMU_TRANSLATION_ENABLE_3 0x234
|
||||
#define MC_SMMU_TRANSLATION_ENABLE_4 0xb98
|
||||
|
||||
#define SMMU_PDE_NEXT_SHIFT 28
|
||||
#define MC_SMMU_PTB_DATA_0_ASID_NONSECURE_SHIFT 29
|
||||
#define MC_SMMU_PTB_DATA_0_ASID_WRITABLE_SHIFT 30
|
||||
#define MC_SMMU_PTB_DATA_0_ASID_READABLE_SHIFT 31
|
||||
#define SMMU_PAGE_SHIFT 12
|
||||
#define SMMU_PAGE_SIZE (1 << SMMU_PAGE_SHIFT)
|
||||
#define SMMU_PDIR_COUNT 1024
|
||||
#define SMMU_PDIR_SIZE (sizeof(u32) * SMMU_PDIR_COUNT)
|
||||
#define SMMU_PTBL_COUNT 1024
|
||||
#define SMMU_PTBL_SIZE (sizeof(u32) * SMMU_PTBL_COUNT)
|
||||
#define SMMU_PDIR_SHIFT 12
|
||||
#define SMMU_PDE_SHIFT 12
|
||||
#define SMMU_PTE_SHIFT 12
|
||||
#define SMMU_PFN_MASK 0x000FFFFF
|
||||
#define SMMU_ADDR_TO_PFN(addr) ((addr) >> 12)
|
||||
#define SMMU_ADDR_TO_PDN(addr) ((addr) >> 22)
|
||||
#define SMMU_PDN_TO_ADDR(addr) ((pdn) << 22)
|
||||
#define _READABLE (1 << MC_SMMU_PTB_DATA_0_ASID_READABLE_SHIFT)
|
||||
#define _WRITABLE (1 << MC_SMMU_PTB_DATA_0_ASID_WRITABLE_SHIFT)
|
||||
#define _NONSECURE (1 << MC_SMMU_PTB_DATA_0_ASID_NONSECURE_SHIFT)
|
||||
#define _PDE_NEXT (1 << SMMU_PDE_NEXT_SHIFT)
|
||||
#define _MASK_ATTR (_READABLE | _WRITABLE | _NONSECURE)
|
||||
#define _PDIR_ATTR (_READABLE | _WRITABLE | _NONSECURE)
|
||||
#define _PDE_ATTR (_READABLE | _WRITABLE | _NONSECURE)
|
||||
#define _PDE_VACANT(pdn) (((pdn) << 10) | _PDE_ATTR)
|
||||
#define _PTE_ATTR (_READABLE | _WRITABLE | _NONSECURE)
|
||||
#define _PTE_VACANT(addr) (((addr) >> SMMU_PAGE_SHIFT) | _PTE_ATTR)
|
||||
#define SMMU_MK_PDIR(page, attr) (((page) >> SMMU_PDIR_SHIFT) | (attr))
|
||||
#define SMMU_MK_PDE(page, attr) (((page) >> SMMU_PDE_SHIFT) | (attr))
|
||||
#define SMMU_NS BIT(0)
|
||||
#define SMMU_WRITE BIT(1)
|
||||
#define SMMU_READ BIT(2)
|
||||
#define SMMU_ATTR_ALL (SMMU_READ | SMMU_WRITE | SMMU_NS)
|
||||
|
||||
void *page_alloc(u32 num);
|
||||
u32 *smmu_alloc_pdir();
|
||||
void smmu_flush_regs();
|
||||
void smmu_flush_all();
|
||||
void smmu_init(u32 secmon_base);
|
||||
void smmu_enable();
|
||||
bool smmu_is_used();
|
||||
void smmu_exit();
|
||||
u32 *smmu_init_domain4(u32 dev_base, u32 asid);
|
||||
u32 *smmu_get_pte(u32 *pdir, u32 iova);
|
||||
void smmu_map(u32 *pdir, u32 addr, u32 page, int cnt, u32 attr);
|
||||
u32 *smmu_init_for_tsec();
|
||||
void smmu_deinit_for_tsec();
|
||||
typedef struct _pde_t {
|
||||
union {
|
||||
union {
|
||||
struct {
|
||||
u32 table:22;
|
||||
u32 rsvd:6;
|
||||
u32 next:1;
|
||||
u32 attr:3;
|
||||
} tbl;
|
||||
|
||||
struct {
|
||||
u32 rsvd_:10;
|
||||
u32 page:12;
|
||||
u32 rsvd:6;
|
||||
u32 next:1;
|
||||
u32 attr:3;
|
||||
} huge;
|
||||
};
|
||||
|
||||
u32 pde;
|
||||
};
|
||||
} pde_t;
|
||||
|
||||
typedef struct _pte_t {
|
||||
u32 page:22;
|
||||
u32 rsvd:7;
|
||||
u32 attr:3;
|
||||
} pte_t;
|
||||
|
||||
static_assert(sizeof(pde_t) == sizeof(u32), "pde_t size is wrong!");
|
||||
static_assert(sizeof(pte_t) == sizeof(u32), "pte_t size is wrong!");
|
||||
|
||||
void *smmu_page_zalloc(u32 num);
|
||||
void smmu_flush_all();
|
||||
void smmu_init();
|
||||
void smmu_enable();
|
||||
void smmu_reset_heap();
|
||||
void *smmu_init_domain(u32 dev_base, u32 asid);
|
||||
void smmu_deinit_domain(u32 dev_base, u32 asid);
|
||||
void smmu_domain_bypass(u32 dev_base, bool bypass);
|
||||
void smmu_map(void *ptb, u32 iova, u64 iopa, u32 pages, u32 attr);
|
||||
void smmu_map_huge(void *ptb, u32 iova, u64 iopa, u32 regions, u32 attr);
|
||||
|
|
|
@ -50,7 +50,9 @@
|
|||
/* Stack theoretical max: 33MB */
|
||||
#define IPL_STACK_TOP 0x83100000
|
||||
#define IPL_HEAP_START 0x84000000
|
||||
#define IPL_HEAP_SZ SZ_512M
|
||||
#define IPL_HEAP_SZ (SZ_512M - SZ_64M)
|
||||
|
||||
#define SMMU_HEAP_ADDR 0xA0000000
|
||||
/* --- Gap: 1040MB 0xA4000000 - 0xE4FFFFFF --- */
|
||||
|
||||
// Virtual disk / Chainloader buffers.
|
||||
|
|
|
@ -75,7 +75,7 @@ void bm92t36_get_sink_info(bool *inserted, usb_pd_objects_t *usb_pd)
|
|||
{
|
||||
memset(buf, 0, sizeof(buf));
|
||||
_bm92t36_read_reg(buf, 2, STATUS1_REG);
|
||||
*inserted = buf[0] & STATUS1_INSERT ? true : false;
|
||||
*inserted = (buf[0] & STATUS1_INSERT) ? true : false;
|
||||
}
|
||||
|
||||
if (usb_pd)
|
||||
|
|
|
@ -32,24 +32,24 @@ void regulator_5v_enable(u8 dev)
|
|||
// The power supply selection from battery or USB is automatic.
|
||||
if (!reg_5v_dev)
|
||||
{
|
||||
// Fan and Rail power from battery 5V regulator.
|
||||
// Fan and Rail power from battery 5V regulator EN.
|
||||
PINMUX_AUX(PINMUX_AUX_SATA_LED_ACTIVE) = 1;
|
||||
gpio_direction_output(GPIO_PORT_A, GPIO_PIN_5, GPIO_HIGH);
|
||||
|
||||
// Only Icosa has USB 5V VBUS rails.
|
||||
if (tegra_t210)
|
||||
{
|
||||
// Fan and Rail power from USB 5V VBUS.
|
||||
// Fan and Rail power from USB 5V VBUS EN.
|
||||
PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN0) = PINMUX_LPDR | 1;
|
||||
gpio_direction_output(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW);
|
||||
}
|
||||
|
||||
// Make sure GPIO IO power is enabled.
|
||||
PMC(APBDEV_PMC_NO_IOPOWER) &= ~PMC_NO_IOPOWER_GPIO_IO_EN;
|
||||
PMC(APBDEV_PMC_NO_IOPOWER) &= ~PMC_NO_IOPOWER_GPIO;
|
||||
(void)PMC(APBDEV_PMC_NO_IOPOWER); // Commit write.
|
||||
|
||||
// Override power detect for GPIO AO IO rails.
|
||||
PMC(APBDEV_PMC_PWR_DET_VAL) &= ~PMC_PWR_DET_GPIO_IO_EN;
|
||||
// Inform GPIO IO pads that we switched to 1.8V.
|
||||
PMC(APBDEV_PMC_PWR_DET_VAL) &= ~PMC_PWR_DET_33V_GPIO;
|
||||
(void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write.
|
||||
|
||||
usb_src = false;
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include <soc/timer.h>
|
||||
#include <soc/t210.h>
|
||||
|
||||
int epoch_offset = 0;
|
||||
|
||||
void max77620_rtc_prep_read()
|
||||
{
|
||||
i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_UPDATE0_REG, MAX77620_RTC_READ_UPDATE);
|
||||
|
@ -154,6 +156,21 @@ u32 max77620_rtc_date_to_epoch(const rtc_time_t *time)
|
|||
return epoch;
|
||||
}
|
||||
|
||||
void max77620_rtc_get_time_adjusted(rtc_time_t *time)
|
||||
{
|
||||
max77620_rtc_get_time(time);
|
||||
if (epoch_offset)
|
||||
{
|
||||
u32 epoch = (u32)((s64)max77620_rtc_date_to_epoch(time) + epoch_offset);
|
||||
max77620_rtc_epoch_to_date(epoch, time);
|
||||
}
|
||||
}
|
||||
|
||||
void max77620_rtc_set_epoch_offset(int offset)
|
||||
{
|
||||
epoch_offset = offset;
|
||||
}
|
||||
|
||||
void max77620_rtc_set_reboot_reason(rtc_reboot_reason_t *rr)
|
||||
{
|
||||
max77620_rtc_stop_alarm();
|
||||
|
|
|
@ -109,6 +109,8 @@ typedef struct _rtc_reboot_reason_t
|
|||
|
||||
void max77620_rtc_prep_read();
|
||||
void max77620_rtc_get_time(rtc_time_t *time);
|
||||
void max77620_rtc_get_time_adjusted(rtc_time_t *time);
|
||||
void max77620_rtc_set_epoch_offset(int offset);
|
||||
void max77620_rtc_stop_alarm();
|
||||
void max77620_rtc_epoch_to_date(u32 epoch, rtc_time_t *time);
|
||||
u32 max77620_rtc_date_to_epoch(const rtc_time_t *time);
|
||||
|
|
14
bdk/sec/se.c
14
bdk/sec/se.c
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2022 CTCaer
|
||||
* Copyright (c) 2018-2024 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,
|
||||
|
@ -182,7 +182,7 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr
|
|||
if (!src || !dst)
|
||||
return 0;
|
||||
|
||||
u8 *block = (u8 *)calloc(1, SE_AES_BLOCK_SIZE);
|
||||
u8 *block = (u8 *)zalloc(SE_AES_BLOCK_SIZE);
|
||||
|
||||
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
|
||||
|
||||
|
@ -194,7 +194,7 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr
|
|||
return res;
|
||||
}
|
||||
|
||||
static void _se_aes_ctr_set(void *ctr)
|
||||
static void _se_aes_ctr_set(const void *ctr)
|
||||
{
|
||||
u32 data[SE_AES_IV_SIZE / 4];
|
||||
memcpy(data, ctr, SE_AES_IV_SIZE);
|
||||
|
@ -226,7 +226,7 @@ u32 se_key_acc_ctrl_get(u32 ks)
|
|||
return SE(SE_CRYPTO_KEYTABLE_ACCESS_REG + 4 * ks);
|
||||
}
|
||||
|
||||
void se_aes_key_set(u32 ks, void *key, u32 size)
|
||||
void se_aes_key_set(u32 ks, const void *key, u32 size)
|
||||
{
|
||||
u32 data[SE_AES_MAX_KEY_SIZE / 4];
|
||||
memcpy(data, key, size);
|
||||
|
@ -238,7 +238,7 @@ void se_aes_key_set(u32 ks, void *key, u32 size)
|
|||
}
|
||||
}
|
||||
|
||||
void se_aes_iv_set(u32 ks, void *iv)
|
||||
void se_aes_iv_set(u32 ks, const void *iv)
|
||||
{
|
||||
u32 data[SE_AES_IV_SIZE / 4];
|
||||
memcpy(data, iv, SE_AES_IV_SIZE);
|
||||
|
@ -657,8 +657,8 @@ void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize)
|
|||
int se_aes_cmac_128(u32 ks, void *dst, const void *src, u32 src_size)
|
||||
{
|
||||
int res = 0;
|
||||
u8 *key = (u8 *)calloc(1, SE_KEY_128_SIZE);
|
||||
u8 *last_block = (u8 *)calloc(1, SE_AES_BLOCK_SIZE);
|
||||
u8 *key = (u8 *)zalloc(SE_KEY_128_SIZE);
|
||||
u8 *last_block = (u8 *)zalloc(SE_AES_BLOCK_SIZE);
|
||||
|
||||
se_aes_iv_clear(ks);
|
||||
se_aes_iv_updated_clear(ks);
|
||||
|
|
|
@ -25,8 +25,8 @@ void se_rsa_acc_ctrl(u32 rs, u32 flags);
|
|||
void se_key_acc_ctrl(u32 ks, u32 flags);
|
||||
u32 se_key_acc_ctrl_get(u32 ks);
|
||||
void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize);
|
||||
void se_aes_key_set(u32 ks, void *key, u32 size);
|
||||
void se_aes_iv_set(u32 ks, void *iv);
|
||||
void se_aes_key_set(u32 ks, const void *key, u32 size);
|
||||
void se_aes_iv_set(u32 ks, const void *iv);
|
||||
void se_aes_key_get(u32 ks, void *key, u32 size);
|
||||
void se_aes_key_clear(u32 ks);
|
||||
void se_aes_iv_clear(u32 ks);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2023 CTCaer
|
||||
* Copyright (c) 2018-2024 CTCaer
|
||||
* Copyright (c) 2018 balika011
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
@ -70,11 +70,12 @@ int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt)
|
|||
int res = 0;
|
||||
u8 *fwbuf = NULL;
|
||||
u32 type = tsec_ctxt->type;
|
||||
u32 *pdir, *car, *fuse, *pmc, *flowctrl, *se, *mc, *iram, *evec;
|
||||
u32 *car, *fuse, *pmc, *flowctrl, *se, *mc, *iram, *evec;
|
||||
u32 *pkg11_magic_off;
|
||||
void *ptb;
|
||||
|
||||
bpmp_mmu_disable();
|
||||
bpmp_freq_t prev_fid = bpmp_clk_rate_set(BPMP_CLK_NORMAL);
|
||||
bpmp_clk_rate_relaxed(true);
|
||||
|
||||
// Enable clocks.
|
||||
clock_enable_tsec();
|
||||
|
@ -145,56 +146,56 @@ int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt)
|
|||
if (type == TSEC_FW_TYPE_EMU)
|
||||
{
|
||||
// Init SMMU translation for TSEC.
|
||||
pdir = smmu_init_for_tsec();
|
||||
smmu_init(tsec_ctxt->secmon_base);
|
||||
// Enable SMMU
|
||||
if (!smmu_is_used())
|
||||
smmu_enable();
|
||||
ptb = smmu_init_domain(MC_SMMU_TSEC_ASID, 1);
|
||||
smmu_init();
|
||||
|
||||
// Enable SMMU.
|
||||
smmu_enable();
|
||||
|
||||
// Clock reset controller.
|
||||
car = page_alloc(1);
|
||||
car = smmu_page_zalloc(1);
|
||||
memcpy(car, (void *)CLOCK_BASE, SZ_PAGE);
|
||||
car[CLK_RST_CONTROLLER_CLK_SOURCE_TSEC / 4] = 2;
|
||||
smmu_map(pdir, CLOCK_BASE, (u32)car, 1, _WRITABLE | _READABLE | _NONSECURE);
|
||||
car[CLK_RST_CONTROLLER_CLK_SOURCE_TSEC / 4] = CLK_SRC_DIV(2);
|
||||
smmu_map(ptb, CLOCK_BASE, (u32)car, 1, SMMU_WRITE | SMMU_READ | SMMU_NS);
|
||||
|
||||
// Fuse driver.
|
||||
fuse = page_alloc(1);
|
||||
fuse = smmu_page_zalloc(1);
|
||||
memcpy((void *)&fuse[0x800/4], (void *)FUSE_BASE, SZ_1K);
|
||||
fuse[0x82C / 4] = 0;
|
||||
fuse[0x9E0 / 4] = (1 << (TSEC_HOS_KB_620 + 2)) - 1;
|
||||
fuse[0x9E4 / 4] = (1 << (TSEC_HOS_KB_620 + 2)) - 1;
|
||||
smmu_map(pdir, (FUSE_BASE - 0x800), (u32)fuse, 1, _READABLE | _NONSECURE);
|
||||
smmu_map(ptb, (FUSE_BASE - 0x800), (u32)fuse, 1, SMMU_READ | SMMU_NS);
|
||||
|
||||
// Power management controller.
|
||||
pmc = page_alloc(1);
|
||||
smmu_map(pdir, RTC_BASE, (u32)pmc, 1, _READABLE | _NONSECURE);
|
||||
pmc = smmu_page_zalloc(1);
|
||||
smmu_map(ptb, RTC_BASE, (u32)pmc, 1, SMMU_READ | SMMU_NS);
|
||||
|
||||
// Flow control.
|
||||
flowctrl = page_alloc(1);
|
||||
smmu_map(pdir, FLOW_CTLR_BASE, (u32)flowctrl, 1, _WRITABLE | _NONSECURE);
|
||||
flowctrl = smmu_page_zalloc(1);
|
||||
smmu_map(ptb, FLOW_CTLR_BASE, (u32)flowctrl, 1, SMMU_WRITE | SMMU_NS);
|
||||
|
||||
// Security engine.
|
||||
se = page_alloc(1);
|
||||
se = smmu_page_zalloc(1);
|
||||
memcpy(se, (void *)SE_BASE, SZ_PAGE);
|
||||
smmu_map(pdir, SE_BASE, (u32)se, 1, _READABLE | _WRITABLE | _NONSECURE);
|
||||
smmu_map(ptb, SE_BASE, (u32)se, 1, SMMU_READ | SMMU_WRITE | SMMU_NS);
|
||||
|
||||
// Memory controller.
|
||||
mc = page_alloc(1);
|
||||
mc = smmu_page_zalloc(1);
|
||||
memcpy(mc, (void *)MC_BASE, SZ_PAGE);
|
||||
mc[MC_IRAM_BOM / 4] = 0;
|
||||
mc[MC_IRAM_TOM / 4] = DRAM_START;
|
||||
smmu_map(pdir, MC_BASE, (u32)mc, 1, _READABLE | _NONSECURE);
|
||||
smmu_map(ptb, MC_BASE, (u32)mc, 1, SMMU_READ | SMMU_NS);
|
||||
|
||||
// IRAM
|
||||
iram = page_alloc(0x30);
|
||||
iram = smmu_page_zalloc(0x30);
|
||||
memcpy(iram, tsec_ctxt->pkg1, 0x30000);
|
||||
// PKG1.1 magic offset.
|
||||
pkg11_magic_off = (u32 *)(iram + ((tsec_ctxt->pkg11_off + 0x20) / 4));
|
||||
smmu_map(pdir, 0x40010000, (u32)iram, 0x30, _READABLE | _WRITABLE | _NONSECURE);
|
||||
pkg11_magic_off = (u32 *)(iram + ((tsec_ctxt->pkg11_off + 0x20) / sizeof(u32)));
|
||||
smmu_map(ptb, 0x40010000, (u32)iram, 0x30, SMMU_READ | SMMU_WRITE | SMMU_NS);
|
||||
|
||||
// Exception vectors
|
||||
evec = page_alloc(1);
|
||||
smmu_map(pdir, EXCP_VEC_BASE, (u32)evec, 1, _READABLE | _WRITABLE | _NONSECURE);
|
||||
evec = smmu_page_zalloc(1);
|
||||
smmu_map(ptb, EXCP_VEC_BASE, (u32)evec, 1, SMMU_READ | SMMU_WRITE | SMMU_NS);
|
||||
}
|
||||
|
||||
// Execute firmware.
|
||||
|
@ -229,7 +230,7 @@ int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt)
|
|||
if (kidx != 8)
|
||||
{
|
||||
res = -6;
|
||||
smmu_deinit_for_tsec();
|
||||
smmu_deinit_domain(MC_SMMU_TSEC_ASID, 1);
|
||||
|
||||
goto out_free;
|
||||
}
|
||||
|
@ -240,7 +241,7 @@ int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt)
|
|||
memcpy(tsec_keys, &key, 0x20);
|
||||
memcpy(tsec_ctxt->pkg1, iram, 0x30000);
|
||||
|
||||
smmu_deinit_for_tsec();
|
||||
smmu_deinit_domain(MC_SMMU_TSEC_ASID, 1);
|
||||
|
||||
// for (int i = 0; i < kidx; i++)
|
||||
// gfx_printf("key %08X\n", key[i]);
|
||||
|
@ -304,7 +305,7 @@ out:
|
|||
clock_disable_sor_safe();
|
||||
clock_disable_tsec();
|
||||
bpmp_mmu_enable();
|
||||
bpmp_clk_rate_set(prev_fid);
|
||||
bpmp_clk_rate_relaxed(false);
|
||||
|
||||
#ifdef BDK_MC_ENABLE_AHB_REDIRECT
|
||||
// Re-enable AHB aperture.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
* Copyright (c) 2018-2024 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,
|
||||
|
@ -35,7 +35,6 @@ typedef struct _tsec_ctxt_t
|
|||
u32 type;
|
||||
void *pkg1;
|
||||
u32 pkg11_off;
|
||||
u32 secmon_base;
|
||||
} tsec_ctxt_t;
|
||||
|
||||
int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* BPMP-Lite Cache/MMU and Frequency driver for Tegra X1
|
||||
*
|
||||
* Copyright (c) 2019-2023 CTCaer
|
||||
* Copyright (c) 2019-2024 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,
|
||||
|
@ -118,7 +118,7 @@
|
|||
#define MMU_EN_READ BIT(2)
|
||||
#define MMU_EN_WRITE BIT(3)
|
||||
|
||||
bpmp_mmu_entry_t mmu_entries[] =
|
||||
static const bpmp_mmu_entry_t mmu_entries[] =
|
||||
{
|
||||
{ DRAM_START, 0xFFFFFFFF, MMU_EN_READ | MMU_EN_WRITE | MMU_EN_EXEC | MMU_EN_CACHED, true },
|
||||
{ IRAM_BASE, 0x4003FFFF, MMU_EN_READ | MMU_EN_WRITE | MMU_EN_EXEC | MMU_EN_CACHED, true }
|
||||
|
@ -140,7 +140,7 @@ void bpmp_mmu_maintenance(u32 op, bool force)
|
|||
BPMP_CACHE_CTRL(BPMP_CACHE_INT_CLEAR) = BPMP_CACHE_CTRL(BPMP_CACHE_INT_RAW_EVENT);
|
||||
}
|
||||
|
||||
void bpmp_mmu_set_entry(int idx, bpmp_mmu_entry_t *entry, bool apply)
|
||||
void bpmp_mmu_set_entry(int idx, const bpmp_mmu_entry_t *entry, bool apply)
|
||||
{
|
||||
if (idx > 31)
|
||||
return;
|
||||
|
@ -200,10 +200,45 @@ void bpmp_mmu_disable()
|
|||
BPMP_CACHE_CTRL(BPMP_CACHE_CONFIG) = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* CLK_RST_CONTROLLER_SCLK_BURST_POLICY:
|
||||
* 0 = CLKM
|
||||
* 1 = PLLC_OUT1
|
||||
* 2 = PLLC4_OUT3
|
||||
* 3 = PLLP_OUT0
|
||||
* 4 = PLLP_OUT2
|
||||
* 5 = PLLC4_OUT1
|
||||
* 6 = CLK_S
|
||||
* 7 = PLLC4_OUT2
|
||||
*/
|
||||
|
||||
bpmp_freq_t bpmp_fid_current = BPMP_CLK_NORMAL;
|
||||
|
||||
void bpmp_clk_rate_relaxed(bool enable)
|
||||
{
|
||||
// This is a glitch-free way to reduce the SCLK timings.
|
||||
if (enable)
|
||||
{
|
||||
// Restore to PLLP source during PLLC configuration.
|
||||
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003330; // PLLP_OUT.
|
||||
usleep(100); // Wait a bit for clock source change.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // PCLK = HCLK / (2 + 1). HCLK == SCLK.
|
||||
}
|
||||
else if (bpmp_fid_current)
|
||||
{
|
||||
// Restore to PLLC_OUT1.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 3; // PCLK = HCLK / (3 + 1). HCLK == SCLK.
|
||||
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003310; // PLLC_OUT1 and CLKM for idle.
|
||||
usleep(100); // Wait a bit for clock source change.
|
||||
}
|
||||
}
|
||||
|
||||
// APB clock affects RTC, PWM, MEMFETCH, APE, USB, SOR PWM,
|
||||
// I2C host, DC/DSI/DISP. UART gives extra stress.
|
||||
// 92: 100% success ratio. 93-94: 595-602MHz has 99% success ratio. 95: 608MHz less.
|
||||
const u8 pll_divn[] = {
|
||||
// APB clock max is supposed to be 204 MHz though.
|
||||
static const u8 pll_divn[] = {
|
||||
0, // BPMP_CLK_NORMAL: 408MHz 0% - 136MHz APB.
|
||||
85, // BPMP_CLK_HIGH_BOOST: 544MHz 33% - 136MHz APB.
|
||||
88, // BPMP_CLK_HIGH2_BOOST: 563MHz 38% - 141MHz APB.
|
||||
|
@ -213,8 +248,6 @@ const u8 pll_divn[] = {
|
|||
//95 // BPMP_CLK_DEV_BOOST: 608MHz 49% - 152MHz APB.
|
||||
};
|
||||
|
||||
bpmp_freq_t bpmp_fid_current = BPMP_CLK_NORMAL;
|
||||
|
||||
void bpmp_clk_rate_get()
|
||||
{
|
||||
bool clk_src_is_pllp = ((CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) >> 4) & 7) == 3;
|
||||
|
@ -237,45 +270,42 @@ void bpmp_clk_rate_get()
|
|||
}
|
||||
}
|
||||
|
||||
bpmp_freq_t bpmp_clk_rate_set(bpmp_freq_t fid)
|
||||
void bpmp_clk_rate_set(bpmp_freq_t fid)
|
||||
{
|
||||
bpmp_freq_t prev_fid = bpmp_fid_current;
|
||||
|
||||
if (fid > (BPMP_CLK_MAX - 1))
|
||||
fid = BPMP_CLK_MAX - 1;
|
||||
|
||||
if (prev_fid == fid)
|
||||
return prev_fid;
|
||||
if (bpmp_fid_current == fid)
|
||||
return;
|
||||
|
||||
bpmp_fid_current = fid;
|
||||
|
||||
if (fid)
|
||||
{
|
||||
if (prev_fid)
|
||||
{
|
||||
// Restore to PLLP source during PLLC configuration.
|
||||
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003333; // PLLP_OUT.
|
||||
msleep(1); // Wait a bit for clock source change.
|
||||
}
|
||||
// Use default SCLK / HCLK / PCLK clocks.
|
||||
bpmp_clk_rate_relaxed(true);
|
||||
|
||||
// Configure and enable PLLC.
|
||||
clock_enable_pllc(pll_divn[fid]);
|
||||
|
||||
// Set SCLK / HCLK / PCLK.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 3; // PCLK = HCLK / (3 + 1). HCLK == SCLK.
|
||||
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003310; // PLLC_OUT1 for active and CLKM for idle.
|
||||
// Set new source and SCLK / HCLK / PCLK dividers.
|
||||
bpmp_clk_rate_relaxed(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003330; // PLLP_OUT for active and CLKM for idle.
|
||||
msleep(1); // Wait a bit for clock source change.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // PCLK = HCLK / (2 + 1). HCLK == SCLK.
|
||||
// Use default SCLK / HCLK / PCLK clocks.
|
||||
bpmp_clk_rate_relaxed(true);
|
||||
|
||||
// Disable PLLC to save power.
|
||||
clock_disable_pllc();
|
||||
}
|
||||
bpmp_fid_current = fid;
|
||||
}
|
||||
|
||||
// Return old fid in case of temporary swap.
|
||||
return prev_fid;
|
||||
// State is reset to RUN on any clock or source set via SW.
|
||||
void bpmp_state_set(bpmp_state_t state)
|
||||
{
|
||||
u32 cfg = CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) & ~0xF0000000u;
|
||||
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = cfg | (state << 28u);
|
||||
}
|
||||
|
||||
// The following functions halt BPMP to reduce power while sleeping.
|
||||
|
@ -287,10 +317,10 @@ void bpmp_usleep(u32 us)
|
|||
// Each iteration takes 1us.
|
||||
while (us)
|
||||
{
|
||||
delay = (us > HALT_COP_MAX_CNT) ? HALT_COP_MAX_CNT : us;
|
||||
delay = (us > HALT_MAX_CNT) ? HALT_MAX_CNT : us;
|
||||
us -= delay;
|
||||
|
||||
FLOW_CTLR(FLOW_CTLR_HALT_COP_EVENTS) = HALT_COP_WAIT_EVENT | HALT_COP_USEC | delay;
|
||||
FLOW_CTLR(FLOW_CTLR_HALT_COP_EVENTS) = HALT_MODE_WAITEVENT | HALT_USEC | delay;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -301,14 +331,14 @@ void bpmp_msleep(u32 ms)
|
|||
// Iteration time is variable. ~200 - 1000us.
|
||||
while (ms)
|
||||
{
|
||||
delay = (ms > HALT_COP_MAX_CNT) ? HALT_COP_MAX_CNT : ms;
|
||||
delay = (ms > HALT_MAX_CNT) ? HALT_MAX_CNT : ms;
|
||||
ms -= delay;
|
||||
|
||||
FLOW_CTLR(FLOW_CTLR_HALT_COP_EVENTS) = HALT_COP_WAIT_EVENT | HALT_COP_MSEC | delay;
|
||||
FLOW_CTLR(FLOW_CTLR_HALT_COP_EVENTS) = HALT_MODE_WAITEVENT | HALT_MSEC | delay;
|
||||
}
|
||||
}
|
||||
|
||||
void bpmp_halt()
|
||||
{
|
||||
FLOW_CTLR(FLOW_CTLR_HALT_COP_EVENTS) = HALT_COP_WAIT_EVENT | HALT_COP_JTAG;
|
||||
FLOW_CTLR(FLOW_CTLR_HALT_COP_EVENTS) = HALT_MODE_WAITEVENT | HALT_JTAG;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* BPMP-Lite Cache/MMU and Frequency driver for Tegra X1
|
||||
*
|
||||
* Copyright (c) 2019-2023 CTCaer
|
||||
* Copyright (c) 2019-2024 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,
|
||||
|
@ -54,16 +54,28 @@ typedef enum
|
|||
BPMP_CLK_MAX
|
||||
} bpmp_freq_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BPMP_STATE_STANDBY = 0, // 32KHz.
|
||||
BPMP_STATE_IDLE = 1,
|
||||
BPMP_STATE_RUN = 2,
|
||||
|
||||
BPMP_STATE_IRQ = BIT(2),
|
||||
BPMP_STATE_FIQ = BIT(3),
|
||||
} bpmp_state_t;
|
||||
|
||||
#define BPMP_CLK_LOWEST_BOOST BPMP_CLK_HIGH2_BOOST
|
||||
#define BPMP_CLK_LOWER_BOOST BPMP_CLK_SUPER_BOOST
|
||||
#define BPMP_CLK_DEFAULT_BOOST BPMP_CLK_HYPER_BOOST
|
||||
|
||||
void bpmp_mmu_maintenance(u32 op, bool force);
|
||||
void bpmp_mmu_set_entry(int idx, bpmp_mmu_entry_t *entry, bool apply);
|
||||
void bpmp_mmu_set_entry(int idx, const bpmp_mmu_entry_t *entry, bool apply);
|
||||
void bpmp_mmu_enable();
|
||||
void bpmp_mmu_disable();
|
||||
void bpmp_clk_rate_relaxed(bool enable);
|
||||
void bpmp_clk_rate_get();
|
||||
bpmp_freq_t bpmp_clk_rate_set(bpmp_freq_t fid);
|
||||
void bpmp_clk_rate_set(bpmp_freq_t fid);
|
||||
void bpmp_state_set(bpmp_state_t state);
|
||||
void bpmp_usleep(u32 us);
|
||||
void bpmp_msleep(u32 ms);
|
||||
void bpmp_halt();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2022 CTCaer
|
||||
* Copyright (c) 2018-2024 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,
|
||||
|
@ -27,7 +27,9 @@
|
|||
#include <power/max77812.h>
|
||||
#include <utils/util.h>
|
||||
|
||||
void _ccplex_enable_power_t210()
|
||||
#define CCPLEX_FLOWCTRL_POWERGATING 0
|
||||
|
||||
static void _ccplex_enable_power_t210()
|
||||
{
|
||||
// Configure GPIO5 and enable output in order to power CPU pmic.
|
||||
max77620_config_gpio(5, MAX77620_GPIO_OUTPUT_ENABLE);
|
||||
|
@ -37,19 +39,31 @@ void _ccplex_enable_power_t210()
|
|||
// 1.0.0-3.x: MAX77621_T_JUNCTION_120 | MAX77621_CKKADV_TRIP_DISABLE | MAX77621_INDUCTOR_NOMINAL.
|
||||
max77621_config_default(REGULATOR_CPU0, MAX77621_CTRL_HOS_CFG);
|
||||
|
||||
// Set voltage and enable cores power.
|
||||
// Set voltage and enable cluster power.
|
||||
max7762x_regulator_set_voltage(REGULATOR_CPU0, 950000);
|
||||
max7762x_regulator_enable(REGULATOR_CPU0, true);
|
||||
}
|
||||
|
||||
void _ccplex_enable_power_t210b01()
|
||||
static void _ccplex_enable_power_t210b01()
|
||||
{
|
||||
// Set voltage and enable cores power.
|
||||
// Set voltage and enable cluster power.
|
||||
max7762x_regulator_set_voltage(REGULATOR_CPU1, 800000);
|
||||
max7762x_regulator_enable(REGULATOR_CPU1, true);
|
||||
}
|
||||
|
||||
void ccplex_boot_cpu0(u32 entry)
|
||||
static void _ccplex_disable_power()
|
||||
{
|
||||
// Disable cluster power.
|
||||
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210)
|
||||
{
|
||||
max7762x_regulator_enable(REGULATOR_CPU0, false);
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO5, 0);
|
||||
}
|
||||
else
|
||||
max7762x_regulator_enable(REGULATOR_CPU1, false);
|
||||
}
|
||||
|
||||
void ccplex_boot_cpu0(u32 entry, bool lock)
|
||||
{
|
||||
// Set ACTIVE_CLUSER to FAST.
|
||||
FLOW_CTLR(FLOW_CTLR_BPMP_CLUSTER_CONTROL) &= ~CLUSTER_CTRL_ACTIVE_SLOW;
|
||||
|
@ -62,12 +76,12 @@ void ccplex_boot_cpu0(u32 entry)
|
|||
clock_enable_pllx();
|
||||
|
||||
// Configure MSELECT source and enable clock to 102MHz.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) & 0x1FFFFF00) | 6;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) = (0 << 29) | CLK_SRC_DIV(4);
|
||||
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; // PLLX_OUT0_LJ.
|
||||
CLOCK(CLK_RST_CONTROLLER_SUPER_CCLK_DIVIDER) = 0x80000000;
|
||||
CLOCK(CLK_RST_CONTROLLER_SUPER_CCLK_DIVIDER) = BIT(31); // SUPER_CDIV_ENB.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = BIT(CLK_V_CPUG);
|
||||
|
||||
clock_enable_coresight();
|
||||
|
@ -90,12 +104,15 @@ void ccplex_boot_cpu0(u32 entry)
|
|||
EXCP_VEC(EVP_CPU_RESET_VECTOR) = 0;
|
||||
|
||||
// Set reset vector.
|
||||
SB(SB_AA64_RESET_LOW) = entry | SB_AA64_RST_AARCH64_MODE_EN;
|
||||
SB(SB_AA64_RESET_LOW) = entry | SB_AA64_RST_AARCH64_MODE_EN;
|
||||
SB(SB_AA64_RESET_HIGH) = 0;
|
||||
|
||||
// Non-secure reset vector write disable.
|
||||
SB(SB_CSR) = SB_CSR_NS_RST_VEC_WR_DIS;
|
||||
(void)SB(SB_CSR);
|
||||
if (lock)
|
||||
{
|
||||
SB(SB_CSR) = SB_CSR_NS_RST_VEC_WR_DIS;
|
||||
(void)SB(SB_CSR);
|
||||
}
|
||||
|
||||
// Tighten up the security aperture.
|
||||
// MC(MC_TZ_SECURITY_CTRL) = 1;
|
||||
|
@ -103,8 +120,46 @@ void ccplex_boot_cpu0(u32 entry)
|
|||
// Clear MSELECT reset.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_V_CLR) = BIT(CLK_V_MSELECT);
|
||||
// Clear NONCPU reset.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR) = 0x20000000;
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR) = BIT(29); // CLR_NONCPURESET.
|
||||
// Clear CPU0 reset.
|
||||
// < 5.x: 0x411F000F, Clear CPU{0,1,2,3} POR and CORE, CX0, L2, and DBG reset.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR) = 0x41010001;
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR) = BIT(30) | BIT(24) | BIT(16) | BIT(0);
|
||||
}
|
||||
|
||||
void ccplex_powergate_cpu0()
|
||||
{
|
||||
#if CCPLEX_FLOWCTRL_POWERGATING
|
||||
// Halt CPU0.
|
||||
FLOW_CTLR(FLOW_CTLR_HALT_CPU0_EVENTS) = HALT_MODE_STOP_UNTIL_IRQ;
|
||||
|
||||
// Powergate cluster via flow control without waiting for WFI.
|
||||
FLOW_CTLR(FLOW_CTLR_CPU0_CSR) = CSR_INTR_FLAG | CSR_EVENT_FLAG | CSR_ENABLE_EXT_CPU_RAIL | CSR_WAIT_WFI_NONE | CSR_ENABLE;
|
||||
|
||||
// Wait for the rail power off to finish.
|
||||
while((FLOW_CTLR(FLOW_CTLR_CPU_PWR_CSR) & CPU_PWR_RAIL_STS_MASK) != CPU_PWR_RAIL_OFF);
|
||||
|
||||
// Set CPU0 to waitevent.
|
||||
FLOW_CTLR(FLOW_CTLR_HALT_CPU0_EVENTS) = HALT_MODE_WAITEVENT;
|
||||
#endif
|
||||
|
||||
// Set CPU0 POR and CORE, CX0, L2, and DBG reset.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_CPUG_CMPLX_SET) = BIT(30) | BIT(24) | BIT(16) | BIT(0);
|
||||
// Set NONCPU reset.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_CPUG_CMPLX_SET) = BIT(29);
|
||||
// Set MSELECT reset.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_V_SET) = BIT(CLK_V_MSELECT);
|
||||
|
||||
// Disable CE0.
|
||||
pmc_enable_partition(POWER_RAIL_CE0, DISABLE);
|
||||
// Disable cluster 0 non-CPU.
|
||||
pmc_enable_partition(POWER_RAIL_C0NC, DISABLE);
|
||||
// Disable CPU rail.
|
||||
pmc_enable_partition(POWER_RAIL_CRAIL, DISABLE);
|
||||
|
||||
clock_disable_coresight();
|
||||
|
||||
// Clear out MSELECT and CPU clocks.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_CLR) = BIT(CLK_V_MSELECT) | BIT(CLK_V_CPUG);
|
||||
|
||||
_ccplex_disable_power();
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include <utils/types.h>
|
||||
|
||||
void ccplex_boot_cpu0(u32 entry);
|
||||
void ccplex_boot_cpu0(u32 entry, bool lock);
|
||||
void ccplex_powergate_cpu0();
|
||||
|
||||
#endif
|
||||
|
|
123
bdk/soc/clock.c
123
bdk/soc/clock.c
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2023 CTCaer
|
||||
* Copyright (c) 2018-2024 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
|
@ -15,6 +15,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <soc/bpmp.h>
|
||||
#include <soc/clock.h>
|
||||
#include <soc/hw_init.h>
|
||||
#include <soc/pmc.h>
|
||||
|
@ -42,82 +43,82 @@ static const clock_osc_t _clock_osc_cnt[] = {
|
|||
/* clk_rst_t: reset, enable, source, index, clk_src, clk_div */
|
||||
|
||||
static const clk_rst_t _clock_uart[] = {
|
||||
{ CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTA, CLK_L_UARTA, 0, 2 },
|
||||
{ CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTB, CLK_L_UARTB, 0, 2 },
|
||||
{ CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_UARTC, CLK_H_UARTC, 0, 2 },
|
||||
{ CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_UARTD, CLK_U_UARTD, 0, 2 },
|
||||
{ CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_UARTAPE, CLK_Y_UARTAPE, 0, 2 }
|
||||
{ CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTA, CLK_L_UARTA, 0, CLK_SRC_DIV(2) },
|
||||
{ CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTB, CLK_L_UARTB, 0, CLK_SRC_DIV(2) },
|
||||
{ CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_UARTC, CLK_H_UARTC, 0, CLK_SRC_DIV(2) },
|
||||
{ CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_UARTD, CLK_U_UARTD, 0, CLK_SRC_DIV(2) },
|
||||
{ CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_UARTAPE, CLK_Y_UARTAPE, 0, CLK_SRC_DIV(2) }
|
||||
};
|
||||
|
||||
//I2C default parameters - TLOW: 4, THIGH: 2, DEBOUNCE: 0, FM_DIV: 26.
|
||||
static const clk_rst_t _clock_i2c[] = {
|
||||
{ CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_I2C1, CLK_L_I2C1, 0, 19 }, //20.4MHz -> 100KHz
|
||||
{ CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_I2C2, CLK_H_I2C2, 0, 4 }, //81.6MHz -> 400KHz
|
||||
{ CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_I2C3, CLK_U_I2C3, 0, 4 }, //81.6MHz -> 400KHz
|
||||
{ CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_I2C4, CLK_V_I2C4, 0, 19 }, //20.4MHz -> 100KHz
|
||||
{ CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_I2C5, CLK_H_I2C5, 0, 4 }, //81.6MHz -> 400KHz
|
||||
{ CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_I2C6, CLK_X_I2C6, 0, 19 } //20.4MHz -> 100KHz
|
||||
{ CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_I2C1, CLK_L_I2C1, 0, CLK_SRC_DIV(10.5) }, //20.4MHz -> 100KHz
|
||||
{ CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_I2C2, CLK_H_I2C2, 0, CLK_SRC_DIV(3) }, //81.6MHz -> 400KHz
|
||||
{ CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_I2C3, CLK_U_I2C3, 0, CLK_SRC_DIV(3) }, //81.6MHz -> 400KHz
|
||||
{ CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_I2C4, CLK_V_I2C4, 0, CLK_SRC_DIV(10.5) }, //20.4MHz -> 100KHz
|
||||
{ CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_I2C5, CLK_H_I2C5, 0, CLK_SRC_DIV(3) }, //81.6MHz -> 400KHz
|
||||
{ CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_I2C6, CLK_X_I2C6, 0, CLK_SRC_DIV(10.5) } //20.4MHz -> 100KHz
|
||||
};
|
||||
|
||||
static clk_rst_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 // 408MHz. Default: 408MHz. Max: 627.2 MHz.
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_SE, CLK_V_SE, 0, CLK_SRC_DIV(1) // 408MHz. Default: 408MHz. Max: 627.2 MHz.
|
||||
};
|
||||
static clk_rst_t _clock_tzram = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_NO_SOURCE, CLK_V_TZRAM, 0, 0
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_NO_SOURCE, CLK_V_TZRAM, 0, CLK_SRC_DIV(1)
|
||||
};
|
||||
static clk_rst_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 // 163.2MHz. Max: 408MHz.
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X, CLK_L_HOST1X, 4, CLK_SRC_DIV(2.5) // 163.2MHz. Max: 408MHz.
|
||||
};
|
||||
static clk_rst_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 // 204MHz. Max: 408MHz.
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_TSEC, CLK_U_TSEC, 0, CLK_SRC_DIV(2) // 204MHz. Max: 408MHz.
|
||||
};
|
||||
static clk_rst_t _clock_nvdec = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_NVDEC, CLK_Y_NVDEC, 4, 0 // 408 MHz. Max: 716.8/979.2MHz.
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_NVDEC, CLK_Y_NVDEC, 4, CLK_SRC_DIV(1) // 408 MHz. Max: 716.8/979.2MHz.
|
||||
};
|
||||
static clk_rst_t _clock_nvjpg = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_NVJPG, CLK_Y_NVJPG, 4, 0 // 408 MHz. Max: 627.2/652.8MHz.
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_NVJPG, CLK_Y_NVJPG, 4, CLK_SRC_DIV(1) // 408 MHz. Max: 627.2/652.8MHz.
|
||||
};
|
||||
static clk_rst_t _clock_vic = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_VIC, CLK_X_VIC, 2, 0 // 408 MHz. Max: 627.2/652.8MHz.
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_VIC, CLK_X_VIC, 2, CLK_SRC_DIV(1) // 408 MHz. Max: 627.2/652.8MHz.
|
||||
};
|
||||
static clk_rst_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
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_NO_SOURCE, CLK_Y_SOR_SAFE, 0, CLK_SRC_DIV(1)
|
||||
};
|
||||
static clk_rst_t _clock_sor0 = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_NOT_USED, 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, CLK_SRC_DIV(1)
|
||||
};
|
||||
static clk_rst_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 // 204MHz.
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_SOR1, CLK_X_SOR1, 0, CLK_SRC_DIV(2) // 204MHz.
|
||||
};
|
||||
static clk_rst_t _clock_kfuse = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_KFUSE, 0, 0
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_KFUSE, 0, CLK_SRC_DIV(1)
|
||||
};
|
||||
static clk_rst_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
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_W, CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_NO_SOURCE, CLK_W_DVFS, 0, CLK_SRC_DIV(1)
|
||||
};
|
||||
static clk_rst_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 // 136MHz.
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_CSITE, CLK_U_CSITE, 0, CLK_SRC_DIV(3) // 136MHz.
|
||||
};
|
||||
static clk_rst_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. HOS: 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, CLK_SRC_DIV(3) // Fref: 6.4MHz. HOS: PLLP / 54 = 7.55MHz.
|
||||
};
|
||||
static clk_rst_t _clock_sdmmc_legacy_tm = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM, CLK_Y_SDMMC_LEGACY_TM, 4, 66
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM, CLK_Y_SDMMC_LEGACY_TM, 4, CLK_SRC_DIV(34) // 12MHz.
|
||||
};
|
||||
static clk_rst_t _clock_apbdma = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_APBDMA, 0, 0 // Max: 204MHz.
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_APBDMA, 0, CLK_SRC_DIV(1) // Max: 204MHz.
|
||||
};
|
||||
static clk_rst_t _clock_ahbdma = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_AHBDMA, 0, 0
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_AHBDMA, 0, CLK_SRC_DIV(1)
|
||||
};
|
||||
static clk_rst_t _clock_actmon = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_ACTMON, CLK_V_ACTMON, 6, 0 // 19.2MHz.
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_ACTMON, CLK_V_ACTMON, 6, CLK_SRC_DIV(1) // 19.2MHz.
|
||||
};
|
||||
static clk_rst_t _clock_extperiph1 = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH1, CLK_V_EXTPERIPH1, 0, 0
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH1, CLK_V_EXTPERIPH1, 0, CLK_SRC_DIV(1)
|
||||
};
|
||||
static clk_rst_t _clock_extperiph2 = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH2, CLK_V_EXTPERIPH2, 2, 202 // 4.0MHz
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH2, CLK_V_EXTPERIPH2, 2, CLK_SRC_DIV(102) // 4.0MHz
|
||||
};
|
||||
|
||||
void clock_enable(const clk_rst_t *clk)
|
||||
|
@ -128,7 +129,7 @@ void clock_enable(const clk_rst_t *clk)
|
|||
CLOCK(clk->enable) &= ~BIT(clk->index);
|
||||
// Configure clock source if required.
|
||||
if (clk->source)
|
||||
CLOCK(clk->source) = clk->clk_div | (clk->clk_src << 29);
|
||||
CLOCK(clk->source) = clk->clk_div | (clk->clk_src << 29u);
|
||||
// Enable.
|
||||
CLOCK(clk->enable) = (CLOCK(clk->enable) & ~BIT(clk->index)) | BIT(clk->index);
|
||||
usleep(2);
|
||||
|
@ -153,7 +154,13 @@ void clock_enable_fuse(bool enable)
|
|||
|
||||
void clock_enable_uart(u32 idx)
|
||||
{
|
||||
// Ease the stress to APB.
|
||||
bpmp_clk_rate_relaxed(true);
|
||||
|
||||
clock_enable(&_clock_uart[idx]);
|
||||
|
||||
// Restore OC.
|
||||
bpmp_clk_rate_relaxed(false);
|
||||
}
|
||||
|
||||
void clock_disable_uart(u32 idx)
|
||||
|
@ -168,12 +175,12 @@ int clock_uart_use_src_div(u32 idx, u32 baud)
|
|||
u32 clk_src_div = CLOCK(_clock_uart[idx].source) & 0xE0000000;
|
||||
|
||||
if (baud == 3000000)
|
||||
CLOCK(_clock_uart[idx].source) = clk_src_div | UART_SRC_CLK_DIV_EN | 15;
|
||||
CLOCK(_clock_uart[idx].source) = clk_src_div | UART_SRC_CLK_DIV_EN | CLK_SRC_DIV(8.5);
|
||||
else if (baud == 1000000)
|
||||
CLOCK(_clock_uart[idx].source) = clk_src_div | UART_SRC_CLK_DIV_EN | 49;
|
||||
CLOCK(_clock_uart[idx].source) = clk_src_div | UART_SRC_CLK_DIV_EN | CLK_SRC_DIV(25.5);
|
||||
else
|
||||
{
|
||||
CLOCK(_clock_uart[idx].source) = clk_src_div | 2;
|
||||
CLOCK(_clock_uart[idx].source) = clk_src_div | CLK_SRC_DIV(2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -247,7 +254,13 @@ void clock_disable_nvjpg()
|
|||
|
||||
void clock_enable_vic()
|
||||
{
|
||||
// Ease the stress to APB.
|
||||
bpmp_clk_rate_relaxed(true);
|
||||
|
||||
clock_enable(&_clock_vic);
|
||||
|
||||
// Restore sys clock.
|
||||
bpmp_clk_rate_relaxed(false);
|
||||
}
|
||||
|
||||
void clock_disable_vic()
|
||||
|
@ -323,7 +336,13 @@ void clock_disable_coresight()
|
|||
|
||||
void clock_enable_pwm()
|
||||
{
|
||||
// Ease the stress to APB.
|
||||
bpmp_clk_rate_relaxed(true);
|
||||
|
||||
clock_enable(&_clock_pwm);
|
||||
|
||||
// Restore OC.
|
||||
bpmp_clk_rate_relaxed(false);
|
||||
}
|
||||
|
||||
void clock_disable_pwm()
|
||||
|
@ -398,10 +417,8 @@ void clock_enable_plld(u32 divp, u32 divn, bool lowpower, bool tegra_t210)
|
|||
if (lowpower && tegra_t210)
|
||||
misc = 0x2D0000 | 0x0AAA; // Clock enable and PLLD_SDM_DIN: 2730 -> DIVN + 0.833.
|
||||
|
||||
|
||||
// Set DISP1 clock source and parent clock.
|
||||
if (lowpower)
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DISP1) = 0x40000000; // PLLD_OUT0.
|
||||
// Set DISP1 clock source.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DISP1) = 2 << 29u; // PLLD_OUT0.
|
||||
|
||||
// Set dividers and enable PLLD.
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div;
|
||||
|
@ -464,10 +481,10 @@ void clock_enable_pllc(u32 divn)
|
|||
;
|
||||
|
||||
// Disable PLLC_OUT1, enable reset and set div to 1.5.
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) = BIT(8);
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) = 1 << 8;
|
||||
|
||||
// Enable PLLC_OUT1 and bring it out of reset.
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) |= (PLLC_OUT1_CLKEN | PLLC_OUT1_RSTN_CLR);
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) |= PLLC_OUT1_CLKEN | PLLC_OUT1_RSTN_CLR;
|
||||
msleep(1); // Wait a bit for PLL to stabilize.
|
||||
}
|
||||
|
||||
|
@ -684,7 +701,7 @@ static void _clock_sdmmc_clear_enable(u32 id)
|
|||
|
||||
static void _clock_sdmmc_config_legacy_tm()
|
||||
{
|
||||
clk_rst_t *clk = &_clock_sdmmc_legacy_tm;
|
||||
const clk_rst_t *clk = &_clock_sdmmc_legacy_tm;
|
||||
if (!(CLOCK(clk->enable) & BIT(clk->index)))
|
||||
clock_enable(clk);
|
||||
}
|
||||
|
@ -715,38 +732,38 @@ static int _clock_sdmmc_config_clock_host(u32 *pclock, u32 id, u32 val)
|
|||
{
|
||||
case 25000:
|
||||
*pclock = 24728;
|
||||
divisor = 31; // 16.5 div.
|
||||
divisor = CLK_SRC_DIV(16.5);
|
||||
break;
|
||||
|
||||
case 26000:
|
||||
*pclock = 25500;
|
||||
divisor = 30; // 16 div.
|
||||
divisor = CLK_SRC_DIV(16);
|
||||
break;
|
||||
|
||||
case 50000:
|
||||
*pclock = 48000;
|
||||
divisor = 15; // 8.5 div.
|
||||
divisor = CLK_SRC_DIV(8.5);
|
||||
break;
|
||||
|
||||
case 52000:
|
||||
*pclock = 51000;
|
||||
divisor = 14; // 8 div.
|
||||
divisor = CLK_SRC_DIV(8);
|
||||
break;
|
||||
|
||||
case 82000:
|
||||
*pclock = 81600;
|
||||
divisor = 8; // 5 div.
|
||||
divisor = CLK_SRC_DIV(5);
|
||||
break;
|
||||
|
||||
case 100000:
|
||||
source = SDMMC_CLOCK_SRC_PLLC4_OUT2;
|
||||
*pclock = 99840;
|
||||
divisor = 2; // 2 div.
|
||||
divisor = CLK_SRC_DIV(2);
|
||||
break;
|
||||
|
||||
case 164000:
|
||||
*pclock = 163200;
|
||||
divisor = 3; // 2.5 div.
|
||||
divisor = CLK_SRC_DIV(2.5);
|
||||
break;
|
||||
|
||||
case 200000:
|
||||
|
@ -762,14 +779,14 @@ static int _clock_sdmmc_config_clock_host(u32 *pclock, u32 id, u32 val)
|
|||
break;
|
||||
}
|
||||
*pclock = 199680;
|
||||
divisor = 0; // 1 div.
|
||||
divisor = CLK_SRC_DIV(1);
|
||||
break;
|
||||
|
||||
#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT
|
||||
case 400000:
|
||||
source = SDMMC_CLOCK_SRC_PLLC4_OUT0;
|
||||
*pclock = 399360;
|
||||
divisor = 3; // 2.5 div
|
||||
divisor = CLK_SRC_DIV(2.5);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
@ -785,7 +802,7 @@ static int _clock_sdmmc_config_clock_host(u32 *pclock, u32 id, u32 val)
|
|||
_clock_sdmmc_config_legacy_tm();
|
||||
|
||||
// Set SDMMC clock.
|
||||
u32 src_div = (source << 29) | divisor;
|
||||
u32 src_div = (source << 29u) | divisor;
|
||||
switch (id)
|
||||
{
|
||||
case SDMMC_1:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2022 CTCaer
|
||||
* Copyright (c) 2018-2024 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,
|
||||
|
@ -47,6 +47,7 @@
|
|||
#define CLK_RST_CONTROLLER_PLLM_MISC1 0x98
|
||||
#define CLK_RST_CONTROLLER_PLLM_MISC2 0x9C
|
||||
#define CLK_RST_CONTROLLER_PLLP_BASE 0xA0
|
||||
#define CLK_RST_CONTROLLER_PLLP_OUTB 0xA8
|
||||
#define CLK_RST_CONTROLLER_PLLA_BASE 0xB0
|
||||
#define CLK_RST_CONTROLLER_PLLA_OUT 0xB4
|
||||
#define CLK_RST_CONTROLLER_PLLA_MISC1 0xB8
|
||||
|
@ -149,6 +150,7 @@
|
|||
#define CLK_RST_CONTROLLER_PLLC_MISC_2 0x5D0
|
||||
#define CLK_RST_CONTROLLER_PLLC4_OUT 0x5E4
|
||||
#define CLK_RST_CONTROLLER_PLLMB_BASE 0x5E8
|
||||
#define CLK_RST_CONTROLLER_PLLMB_MISC1 0x5EC
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_XUSB_FS 0x608
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_XUSB_CORE_DEV 0x60C
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_XUSB_SS 0x610
|
||||
|
@ -198,6 +200,9 @@
|
|||
|
||||
#define UTMIPLL_LOCK BIT(31)
|
||||
|
||||
/*! Clock source */
|
||||
#define CLK_SRC_DIV(d) ((d) ? ((u32)(((d) - 1) * 2)) : 0)
|
||||
|
||||
/*! PTO_CLK_CNT */
|
||||
#define PTO_REF_CLK_WIN_CFG_MASK 0xF
|
||||
#define PTO_REF_CLK_WIN_CFG_16P 0xF
|
||||
|
|
|
@ -189,7 +189,7 @@ void fuse_read_array(u32 *words)
|
|||
words[i] = fuse_read(i);
|
||||
}
|
||||
|
||||
static u32 _parity32_even(u32 *words, u32 count)
|
||||
static u32 _parity32_even(const u32 *words, u32 count)
|
||||
{
|
||||
u32 acc = words[0];
|
||||
for (u32 i = 1; i < count; i++)
|
||||
|
@ -303,7 +303,7 @@ int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value))
|
|||
u32 words[80];
|
||||
u32 word_count;
|
||||
u32 word_addr;
|
||||
u32 word0 = 0;
|
||||
u32 word0;
|
||||
u32 total_read = 0;
|
||||
|
||||
word_count = FUSE(FUSE_FIRST_BOOTROM_PATCH_SIZE);
|
||||
|
@ -363,7 +363,7 @@ int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len)
|
|||
u32 words[80];
|
||||
u32 word_count;
|
||||
u32 word_addr;
|
||||
u32 word0 = 0;
|
||||
u32 word0;
|
||||
u32 total_read = 0;
|
||||
int evp_thunk_written = 0;
|
||||
void *evp_thunk_dst_addr = 0;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2023 CTCaer
|
||||
* Copyright (c) 2018-2024 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,
|
||||
|
@ -93,6 +93,24 @@ static void _config_oscillators()
|
|||
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // Set HCLK div to 1 and PCLK div to 3.
|
||||
}
|
||||
|
||||
void hw_config_arbiter(bool reset)
|
||||
{
|
||||
if (reset)
|
||||
{
|
||||
ARB_PRI(ARB_PRIO_CPU_PRIORITY) = 0x0040090;
|
||||
ARB_PRI(ARB_PRIO_COP_PRIORITY) = 0x12024C2;
|
||||
ARB_PRI(ARB_PRIO_VCP_PRIORITY) = 0x2201209;
|
||||
ARB_PRI(ARB_PRIO_DMA_PRIORITY) = 0x320365B;
|
||||
}
|
||||
else
|
||||
{
|
||||
ARB_PRI(ARB_PRIO_CPU_PRIORITY) = 0x12412D1;
|
||||
ARB_PRI(ARB_PRIO_COP_PRIORITY) = 0x0000000;
|
||||
ARB_PRI(ARB_PRIO_VCP_PRIORITY) = 0x220244A;
|
||||
ARB_PRI(ARB_PRIO_DMA_PRIORITY) = 0x320369B;
|
||||
}
|
||||
}
|
||||
|
||||
// The uart is skipped for Copper, Hoag and Calcio. Used in Icosa, Iowa and Aula.
|
||||
static void _config_gpios(bool nx_hoag)
|
||||
{
|
||||
|
@ -268,7 +286,7 @@ static void _config_se_brom()
|
|||
APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) = (APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) & 0xF0) | (7 << 10);
|
||||
}
|
||||
|
||||
static void _config_regulators(bool tegra_t210)
|
||||
static void _config_regulators(bool tegra_t210, bool nx_hoag)
|
||||
{
|
||||
// Set RTC/AO domain to POR voltage.
|
||||
if (tegra_t210)
|
||||
|
@ -277,22 +295,26 @@ static void _config_regulators(bool tegra_t210)
|
|||
// Disable low battery shutdown monitor.
|
||||
max77620_low_battery_monitor_config(false);
|
||||
|
||||
// Disable SDMMC1 IO/Core power.
|
||||
// Power on all relevant rails in case we came out of warmboot. Only keep MEM/MEM_COMP and SDMMC1 states.
|
||||
PMC(APBDEV_PMC_NO_IOPOWER) &= PMC_NO_IOPOWER_MEM_COMP | PMC_NO_IOPOWER_SDMMC1 | PMC_NO_IOPOWER_MEM;
|
||||
|
||||
// Make sure SDMMC1 IO/Core are powered off.
|
||||
max7762x_regulator_enable(REGULATOR_LDO2, false);
|
||||
gpio_write(GPIO_PORT_E, GPIO_PIN_4, GPIO_LOW);
|
||||
PMC(APBDEV_PMC_NO_IOPOWER) |= PMC_NO_IOPOWER_SDMMC1;
|
||||
(void)PMC(APBDEV_PMC_NO_IOPOWER);
|
||||
sd_power_cycle_time_start = get_tmr_ms();
|
||||
|
||||
// Disable LCD DVDD to make sure it's in a reset state.
|
||||
max7762x_regulator_enable(REGULATOR_LDO0, false);
|
||||
|
||||
// Disable backup battery charger.
|
||||
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,
|
||||
MAX77620_ONOFFCNFG1_RSVD | (3 << MAX77620_ONOFFCNFG1_MRT_SHIFT)); // PWR delay for forced shutdown off.
|
||||
|
||||
// Set PWR delay for forced shutdown off to 6s.
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_RSVD | (3 << MAX77620_ONOFFCNFG1_MRT_SHIFT));
|
||||
|
||||
if (tegra_t210)
|
||||
{
|
||||
// Configure all Flexible Power Sequencers for MAX77620.
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_CFG0, (7 << MAX77620_FPS_TIME_PERIOD_SHIFT));
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_CFG0, (7 << MAX77620_FPS_TIME_PERIOD_SHIFT) | (0 << MAX77620_FPS_EN_SRC_SHIFT));
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_CFG1, (7 << MAX77620_FPS_TIME_PERIOD_SHIFT) | (1 << MAX77620_FPS_EN_SRC_SHIFT));
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_CFG2, (7 << MAX77620_FPS_TIME_PERIOD_SHIFT));
|
||||
max77620_regulator_config_fps(REGULATOR_LDO4);
|
||||
|
@ -301,13 +323,13 @@ static void _config_regulators(bool tegra_t210)
|
|||
max77620_regulator_config_fps(REGULATOR_SD1);
|
||||
max77620_regulator_config_fps(REGULATOR_SD3);
|
||||
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_GPIO3,
|
||||
(4 << MAX77620_FPS_TIME_PERIOD_SHIFT) | (2 << MAX77620_FPS_PD_PERIOD_SHIFT)); // 3.x+
|
||||
// Set GPIO3 to FPS0 for SYS 3V3 EN. Enabled when FPS0 is enabled.
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_GPIO3, (4 << MAX77620_FPS_PU_PERIOD_SHIFT) | (2 << MAX77620_FPS_PD_PERIOD_SHIFT));
|
||||
|
||||
// Set vdd_core voltage to 1.125V.
|
||||
max7762x_regulator_set_voltage(REGULATOR_SD0, 1125000);
|
||||
|
||||
// Fix CPU/GPU after L4T warmboot.
|
||||
// Power down CPU/GPU regulators after L4T warmboot.
|
||||
max77620_config_gpio(5, MAX77620_GPIO_OUTPUT_DISABLE);
|
||||
max77620_config_gpio(6, MAX77620_GPIO_OUTPUT_DISABLE);
|
||||
|
||||
|
@ -315,8 +337,26 @@ static void _config_regulators(bool tegra_t210)
|
|||
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.
|
||||
else
|
||||
{
|
||||
// Tegra X1+ set vdd_core voltage to 1.05V.
|
||||
max7762x_regulator_set_voltage(REGULATOR_SD0, 1050000);
|
||||
|
||||
// Power on SD2 regulator for supplying LDO0/1/8.
|
||||
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_POWER_MODE_NORMAL << MAX77620_SD_POWER_MODE_SHIFT) |
|
||||
MAX77620_SD_CFG1_FSRADE_SD_ENABLE);
|
||||
|
||||
// Enable LDO8 on HOAG as it also powers I2C1 IO pads.
|
||||
if (nx_hoag)
|
||||
{
|
||||
max7762x_regulator_set_voltage(REGULATOR_LDO8, 2800000);
|
||||
max7762x_regulator_enable(REGULATOR_LDO8, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hw_init()
|
||||
|
@ -337,6 +377,9 @@ void hw_init()
|
|||
if (tegra_t210)
|
||||
_mbist_workaround();
|
||||
|
||||
// Make sure PLLP_OUT3/4 is set to 408 MHz and enabled.
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLP_OUTB) = 0x30003;
|
||||
|
||||
// Enable Security Engine clock.
|
||||
clock_enable_se();
|
||||
|
||||
|
@ -355,18 +398,6 @@ void hw_init()
|
|||
// Initialize pin configuration.
|
||||
_config_gpios(nx_hoag);
|
||||
|
||||
#ifdef DEBUG_UART_PORT
|
||||
#if (DEBUG_UART_PORT == UART_B)
|
||||
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO);
|
||||
#elif (DEBUG_UART_PORT == UART_C)
|
||||
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO);
|
||||
#endif
|
||||
pinmux_config_uart(DEBUG_UART_PORT);
|
||||
clock_enable_uart(DEBUG_UART_PORT);
|
||||
uart_init(DEBUG_UART_PORT, DEBUG_UART_BAUDRATE, UART_AO_TX_AO_RX);
|
||||
uart_invert(DEBUG_UART_PORT, DEBUG_UART_INVERT, UART_INVERT_TXD);
|
||||
#endif
|
||||
|
||||
// Enable CL-DVFS clock unconditionally to avoid issues with I2C5 sharing.
|
||||
clock_enable_cl_dvfs();
|
||||
|
||||
|
@ -380,19 +411,12 @@ void hw_init()
|
|||
// Initialize I2C5, mandatory for PMIC.
|
||||
i2c_init(I2C_5);
|
||||
|
||||
// Enable LDO8 on HOAG as it also powers I2C1 IO pads.
|
||||
if (nx_hoag)
|
||||
{
|
||||
max7762x_regulator_set_voltage(REGULATOR_LDO8, 2800000);
|
||||
max7762x_regulator_enable(REGULATOR_LDO8, true);
|
||||
}
|
||||
// Initialize various regulators based on Erista/Mariko platform.
|
||||
_config_regulators(tegra_t210, nx_hoag);
|
||||
|
||||
// Initialize I2C1 for various power related devices.
|
||||
i2c_init(I2C_1);
|
||||
|
||||
// Initialize various regulators based on Erista/Mariko platform.
|
||||
_config_regulators(tegra_t210);
|
||||
|
||||
_config_pmc_scratch(); // Missing from 4.x+
|
||||
|
||||
// Set BPMP/SCLK to PLLP_OUT (408MHz).
|
||||
|
@ -406,6 +430,9 @@ void hw_init()
|
|||
PMC(APBDEV_PMC_TZRAM_SEC_DISABLE) = PMC_TZRAM_DISABLE_REG_WRITE | PMC_TZRAM_DISABLE_REG_READ;
|
||||
}
|
||||
|
||||
// Set arbiter.
|
||||
hw_config_arbiter(false);
|
||||
|
||||
// Initialize External memory controller and configure DRAM parameters.
|
||||
sdram_init();
|
||||
|
||||
|
@ -413,9 +440,22 @@ void hw_init()
|
|||
|
||||
// Enable HOST1X used by every display module (DC, VIC, NVDEC, NVENC, TSEC, etc).
|
||||
clock_enable_host1x();
|
||||
|
||||
#ifdef DEBUG_UART_PORT
|
||||
// Setup debug uart port.
|
||||
#if (DEBUG_UART_PORT == UART_B)
|
||||
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO);
|
||||
#elif (DEBUG_UART_PORT == UART_C)
|
||||
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO);
|
||||
#endif
|
||||
pinmux_config_uart(DEBUG_UART_PORT);
|
||||
clock_enable_uart(DEBUG_UART_PORT);
|
||||
uart_init(DEBUG_UART_PORT, DEBUG_UART_BAUDRATE, UART_AO_TX_AO_RX);
|
||||
uart_invert(DEBUG_UART_PORT, DEBUG_UART_INVERT, UART_INVERT_TXD);
|
||||
#endif
|
||||
}
|
||||
|
||||
void hw_reinit_workaround(bool coreboot, u32 bl_magic)
|
||||
void hw_deinit(bool coreboot, u32 bl_magic)
|
||||
{
|
||||
bool tegra_t210 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210;
|
||||
|
||||
|
@ -426,7 +466,7 @@ void hw_reinit_workaround(bool coreboot, u32 bl_magic)
|
|||
// Disable temperature sensor, touchscreen, 5V regulators, Joy-Con and VIC.
|
||||
vic_end();
|
||||
tmp451_end();
|
||||
set_fan_duty(0);
|
||||
fan_set_duty(0);
|
||||
touch_power_off();
|
||||
jc_deinit();
|
||||
regulator_5v_disable(REGULATOR_5V_ALL);
|
||||
|
@ -439,6 +479,9 @@ void hw_reinit_workaround(bool coreboot, u32 bl_magic)
|
|||
// Flush/disable MMU cache.
|
||||
bpmp_mmu_disable();
|
||||
|
||||
// Reset arbiter.
|
||||
hw_config_arbiter(true);
|
||||
|
||||
// Re-enable clocks to Audio Processing Engine as a workaround to hanging.
|
||||
if (tegra_t210)
|
||||
{
|
||||
|
@ -458,7 +501,7 @@ void hw_reinit_workaround(bool coreboot, u32 bl_magic)
|
|||
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO);
|
||||
|
||||
// Reinstate SD controller power.
|
||||
PMC(APBDEV_PMC_NO_IOPOWER) &= ~(PMC_NO_IOPOWER_SDMMC1_IO_EN);
|
||||
PMC(APBDEV_PMC_NO_IOPOWER) &= ~PMC_NO_IOPOWER_SDMMC1;
|
||||
}
|
||||
|
||||
// Seamless display or display power off.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
* Copyright (c) 2018-2024 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,
|
||||
|
@ -27,7 +27,8 @@ extern u32 hw_rst_status;
|
|||
extern u32 hw_rst_reason;
|
||||
|
||||
void hw_init();
|
||||
void hw_reinit_workaround(bool coreboot, u32 magic);
|
||||
void hw_deinit(bool coreboot, u32 magic);
|
||||
void hw_config_arbiter(bool reset);
|
||||
u32 hw_get_chip_id();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -96,7 +96,7 @@ static void _i2c_load_cfg_wait(vu32 *base)
|
|||
}
|
||||
}
|
||||
|
||||
static int _i2c_send_single(u32 i2c_idx, u32 dev_addr, u8 *buf, u32 size)
|
||||
static int _i2c_send_single(u32 i2c_idx, u32 dev_addr, const u8 *buf, u32 size)
|
||||
{
|
||||
if (size > 8)
|
||||
return 0;
|
||||
|
@ -384,7 +384,7 @@ int i2c_recv_buf_big(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr, u32 reg)
|
|||
return _i2c_recv_pkt(i2c_idx, buf, size, dev_addr, reg);
|
||||
}
|
||||
|
||||
int i2c_send_buf_small(u32 i2c_idx, u32 dev_addr, u32 reg, u8 *buf, u32 size)
|
||||
int i2c_send_buf_small(u32 i2c_idx, u32 dev_addr, u32 reg, const u8 *buf, u32 size)
|
||||
{
|
||||
u8 tmp[8];
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ void i2c_init(u32 i2c_idx);
|
|||
int i2c_recv_buf(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr);
|
||||
int i2c_send_buf_big(u32 i2c_idx, u32 dev_addr, u8 *buf, u32 size);
|
||||
int i2c_recv_buf_big(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr, u32 reg);
|
||||
int i2c_send_buf_small(u32 i2c_idx, u32 dev_addr, u32 reg, u8 *buf, u32 size);
|
||||
int i2c_send_buf_small(u32 i2c_idx, u32 dev_addr, u32 reg, const u8 *buf, u32 size);
|
||||
int i2c_recv_buf_small(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr, u32 reg);
|
||||
int i2c_send_byte(u32 i2c_idx, u32 dev_addr, u32 reg, u8 val);
|
||||
u8 i2c_recv_byte(u32 i2c_idx, u32 dev_addr, u32 reg);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* BPMP-Lite IRQ driver for Tegra X1
|
||||
*
|
||||
* Copyright (c) 2019 CTCaer
|
||||
* Copyright (c) 2019-2024 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,
|
||||
|
@ -71,19 +71,9 @@ static void _irq_disable_and_ack_all()
|
|||
{
|
||||
u32 enabled_irqs = ICTLR(ctrl_idx, PRI_ICTLR_COP_IER);
|
||||
ICTLR(ctrl_idx, PRI_ICTLR_COP_IER_CLR) = enabled_irqs;
|
||||
ICTLR(ctrl_idx, PRI_ICTLR_FIR_CLR) = enabled_irqs;
|
||||
}
|
||||
}
|
||||
|
||||
static void _irq_ack_source(u32 irq)
|
||||
{
|
||||
u32 ctrl_idx = irq >> 5;
|
||||
u32 bit = irq % 32;
|
||||
|
||||
// Force stop the interrupt as it's serviced here.
|
||||
ICTLR(ctrl_idx, PRI_ICTLR_FIR_CLR) = BIT(bit);
|
||||
}
|
||||
|
||||
void irq_free(u32 irq)
|
||||
{
|
||||
for (u32 idx = 0; idx < IRQ_MAX_HANDLERS; idx++)
|
||||
|
@ -121,7 +111,6 @@ static irq_status_t _irq_handle_source(u32 irq)
|
|||
int status = IRQ_NONE;
|
||||
|
||||
_irq_disable_source(irq);
|
||||
_irq_ack_source(irq);
|
||||
|
||||
u32 idx;
|
||||
for (idx = 0; idx < IRQ_MAX_HANDLERS; idx++)
|
||||
|
@ -135,8 +124,8 @@ static irq_status_t _irq_handle_source(u32 irq)
|
|||
}
|
||||
}
|
||||
|
||||
// Do not re-enable if not handled.
|
||||
if (status == IRQ_NONE)
|
||||
// Do not re-enable if not handled or error.
|
||||
if (status != IRQ_HANDLED)
|
||||
return status;
|
||||
|
||||
if (irqs[idx].flags & IRQ_FLAG_ONE_OFF)
|
||||
|
@ -155,7 +144,6 @@ void irq_handler()
|
|||
if (!irq_init_done)
|
||||
{
|
||||
_irq_disable_source(irq);
|
||||
_irq_ack_source(irq);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -194,10 +182,9 @@ void irq_wait_event(u32 irq)
|
|||
_irq_enable_source(irq);
|
||||
|
||||
// Halt BPMP and wait for the IRQ. No need to use WAIT_EVENT + LIC_IRQ when BPMP serves the IRQ.
|
||||
FLOW_CTLR(FLOW_CTLR_HALT_COP_EVENTS) = HALT_COP_STOP_UNTIL_IRQ;
|
||||
FLOW_CTLR(FLOW_CTLR_HALT_COP_EVENTS) = HALT_MODE_STOP_UNTIL_IRQ;
|
||||
|
||||
_irq_disable_source(irq);
|
||||
_irq_ack_source(irq);
|
||||
|
||||
irq_enable_cpu_irq_exceptions();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2024 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,3 +31,11 @@ void pinmux_config_i2c(u32 idx)
|
|||
PINMUX_AUX(PINMUX_AUX_X_I2C_SCL(idx)) = PINMUX_INPUT_ENABLE;
|
||||
PINMUX_AUX(PINMUX_AUX_X_I2C_SDA(idx)) = PINMUX_INPUT_ENABLE;
|
||||
}
|
||||
|
||||
void pinmux_config_i2s(u32 idx)
|
||||
{
|
||||
PINMUX_AUX(PINMUX_AUX_X_I2S_LRCK(idx)) = PINMUX_DRIVE_4X | PINMUX_PULL_DOWN;
|
||||
PINMUX_AUX(PINMUX_AUX_X_I2C_DIN(idx)) = PINMUX_DRIVE_4X | PINMUX_INPUT_ENABLE | PINMUX_TRISTATE | PINMUX_PULL_DOWN;
|
||||
PINMUX_AUX(PINMUX_AUX_X_I2C_DOUT(idx)) = PINMUX_DRIVE_4X | PINMUX_PULL_DOWN;
|
||||
PINMUX_AUX(PINMUX_AUX_X_I2C_BCLK(idx)) = PINMUX_DRIVE_4X | PINMUX_PULL_DOWN;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2024 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,
|
||||
|
@ -50,6 +51,7 @@
|
|||
#define PINMUX_AUX_DAP4_DOUT 0x14C
|
||||
#define PINMUX_AUX_DAP4_SCLK 0x150
|
||||
#define PINMUX_AUX_CLK_32K_OUT 0x164
|
||||
#define PINMUX_AUX_AUD_MCLK 0x180
|
||||
#define PINMUX_AUX_GPIO_X1_AUD 0x18C
|
||||
#define PINMUX_AUX_GPIO_X3_AUD 0x190
|
||||
#define PINMUX_AUX_SPDIF_IN 0x1A4
|
||||
|
@ -69,6 +71,7 @@
|
|||
#define PINMUX_AUX_LCD_RST 0x204
|
||||
#define PINMUX_AUX_LCD_GPIO1 0x208
|
||||
#define PINMUX_AUX_LCD_GPIO2 0x20C
|
||||
#define PINMUX_AUX_TOUCH_RST 0x214
|
||||
#define PINMUX_AUX_TOUCH_CLK 0x218
|
||||
#define PINMUX_AUX_TOUCH_INT 0x220
|
||||
#define PINMUX_AUX_MOTION_INT 0x224
|
||||
|
@ -81,6 +84,7 @@
|
|||
#define PINMUX_AUX_GPIO_PK3 0x260
|
||||
#define PINMUX_AUX_GPIO_PK7 0x270
|
||||
#define PINMUX_AUX_GPIO_PZ1 0x280
|
||||
#define PINMUX_AUX_GPIO_PZ4 0x28C
|
||||
/* Only in T210B01 */
|
||||
#define PINMUX_AUX_SDMMC2_DAT0 0x294
|
||||
#define PINMUX_AUX_SDMMC2_DAT1 0x298
|
||||
|
@ -101,6 +105,11 @@
|
|||
/*! 0:GEN1, 1:GEN2, 2:GEN3, 3:CAM, 4:PWR */
|
||||
#define PINMUX_AUX_X_I2C_SCL(x) (0xBC + 8 * (x))
|
||||
#define PINMUX_AUX_X_I2C_SDA(x) (0xC0 + 8 * (x))
|
||||
/*! 0:I2S1, 1:I2S2 */
|
||||
#define PINMUX_AUX_X_I2S_LRCK(x) (0x124 + 0x10 * (x))
|
||||
#define PINMUX_AUX_X_I2C_DIN(x) (0x128 + 0x10 * (x))
|
||||
#define PINMUX_AUX_X_I2C_DOUT(x) (0x12c + 0x10 * (x))
|
||||
#define PINMUX_AUX_X_I2C_BCLK(x) (0x130 + 0x10 * (x))
|
||||
|
||||
#define PINMUX_FUNC_MASK (3 << 0)
|
||||
|
||||
|
@ -130,5 +139,6 @@
|
|||
|
||||
void pinmux_config_uart(u32 idx);
|
||||
void pinmux_config_i2c(u32 idx);
|
||||
void pinmux_config_i2s(u32 idx);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 st4rk
|
||||
* Copyright (c) 2018-2022 CTCaer
|
||||
* Copyright (c) 2018-2024 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,
|
||||
|
@ -39,10 +39,12 @@
|
|||
#define APBDEV_PMC_PWRGATE_TOGGLE 0x30
|
||||
#define APBDEV_PMC_PWRGATE_STATUS 0x38
|
||||
#define APBDEV_PMC_NO_IOPOWER 0x44
|
||||
#define PMC_NO_IOPOWER_SDMMC1_IO_EN BIT(12)
|
||||
#define PMC_NO_IOPOWER_SDMMC4_IO_EN BIT(14)
|
||||
#define PMC_NO_IOPOWER_MEM BIT(7)
|
||||
#define PMC_NO_IOPOWER_SDMMC1 BIT(12)
|
||||
#define PMC_NO_IOPOWER_SDMMC4 BIT(14)
|
||||
#define PMC_NO_IOPOWER_MEM_COMP BIT(16)
|
||||
#define PMC_NO_IOPOWER_AUDIO_HV BIT(18)
|
||||
#define PMC_NO_IOPOWER_GPIO_IO_EN BIT(21)
|
||||
#define PMC_NO_IOPOWER_GPIO BIT(21)
|
||||
#define APBDEV_PMC_SCRATCH0 0x50
|
||||
#define PMC_SCRATCH0_MODE_WARMBOOT BIT(0)
|
||||
#define PMC_SCRATCH0_MODE_RCM BIT(1)
|
||||
|
@ -61,9 +63,9 @@
|
|||
#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)
|
||||
#define PMC_PWR_DET_GPIO_IO_EN BIT(21)
|
||||
#define PMC_PWR_DET_33V_SDMMC1 BIT(12)
|
||||
#define PMC_PWR_DET_33V_AUDIO_HV BIT(18)
|
||||
#define PMC_PWR_DET_33V_GPIO BIT(21)
|
||||
#define APBDEV_PMC_DDR_PWR 0xE8
|
||||
#define APBDEV_PMC_USB_AO 0xF0
|
||||
#define APBDEV_PMC_CRYPTO_OP 0xF4
|
||||
|
@ -99,7 +101,9 @@
|
|||
#define PMC_RST_STATUS_LP0 4
|
||||
#define PMC_RST_STATUS_AOTAG 5
|
||||
#define APBDEV_PMC_IO_DPD_REQ 0x1B8
|
||||
#define PMC_IO_DPD_REQ_DPD_OFF BIT(30)
|
||||
#define PMC_IO_DPD_REQ_DPD_IDLE (0 << 30u)
|
||||
#define PMC_IO_DPD_REQ_DPD_OFF (1 << 30u)
|
||||
#define PMC_IO_DPD_REQ_DPD_ON (2 << 30u)
|
||||
#define APBDEV_PMC_IO_DPD2_REQ 0x1C0
|
||||
#define APBDEV_PMC_VDDP_SEL 0x1CC
|
||||
#define APBDEV_PMC_DDR_CFG 0x1D0
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
#define GPU_USER_BASE 0x58000000
|
||||
#define RES_SEMAPH_BASE 0x60001000
|
||||
#define ARB_SEMAPH_BASE 0x60002000
|
||||
#define ARBPRI_BASE 0x60003000
|
||||
#define ARB_PRI_BASE 0x60003000
|
||||
#define ICTLR_BASE 0x60004000
|
||||
#define TMR_BASE 0x60005000
|
||||
#define CLOCK_BASE 0x60006000
|
||||
|
@ -81,6 +81,7 @@
|
|||
#define CL_DVFS_BASE 0x70110000
|
||||
#define APE_BASE 0x702C0000
|
||||
#define AHUB_BASE 0x702D0000
|
||||
#define ADMAIF_BASE 0x702D0000
|
||||
#define AXBAR_BASE 0x702D0800
|
||||
#define I2S_BASE 0x702D1000
|
||||
#define ADMA_BASE 0x702E2000
|
||||
|
@ -112,6 +113,7 @@
|
|||
#define SOR1(off) MMIO_REG32(SOR1_BASE, off)
|
||||
#define GPU(off) MMIO_REG32(GPU_BASE, off)
|
||||
#define GPU_USER(off) MMIO_REG32(GPU_USER_BASE, off)
|
||||
#define ARB_PRI(off) MMIO_REG32(ARB_PRI_BASE, off)
|
||||
#define ICTLR(cidx, off) MMIO_REG32(ICTLR_BASE + (0x100 * (cidx)), off)
|
||||
#define TMR(off) MMIO_REG32(TMR_BASE, off)
|
||||
#define CLOCK(off) MMIO_REG32(CLOCK_BASE, off)
|
||||
|
@ -174,6 +176,7 @@
|
|||
#define EVP_COP_IRQ_STS 0x220
|
||||
|
||||
/*! Primary Interrupt Controller registers. */
|
||||
#define PRI_ICTLR_ISR 0x10
|
||||
#define PRI_ICTLR_FIR 0x14
|
||||
#define PRI_ICTLR_FIR_SET 0x18
|
||||
#define PRI_ICTLR_FIR_CLR 0x1C
|
||||
|
@ -186,6 +189,13 @@
|
|||
#define PRI_ICTLR_COP_IER_CLR 0x38
|
||||
#define PRI_ICTLR_COP_IEP_CLASS 0x3C
|
||||
|
||||
/* Arbiter registers */
|
||||
#define ARB_PRIO_CPU_PRIORITY 0x0
|
||||
#define ARB_PRIO_COP_PRIORITY 0x4
|
||||
#define ARB_PRIO_VCP_PRIORITY 0x8
|
||||
#define ARB_PRIO_DMA_PRIORITY 0xC
|
||||
#define ARB_PRIO_UCQ_PRIORITY 0x10
|
||||
|
||||
/*! AHB Gizmo registers. */
|
||||
#define AHB_ARBITRATION_PRIORITY_CTRL 0x8
|
||||
#define PRIORITY_CTRL_WEIGHT(x) (((x) & 7) << 29)
|
||||
|
@ -308,29 +318,47 @@
|
|||
#define EMC_HEKA_UPD BIT(30)
|
||||
|
||||
/*! Flow controller registers. */
|
||||
#define FLOW_CTLR_HALT_COP_EVENTS 0x4
|
||||
#define HALT_COP_GIC_IRQ BIT(9)
|
||||
#define HALT_COP_LIC_IRQ BIT(11)
|
||||
#define HALT_COP_SEC BIT(23)
|
||||
#define HALT_COP_MSEC BIT(24)
|
||||
#define HALT_COP_USEC BIT(25)
|
||||
#define HALT_COP_JTAG BIT(28)
|
||||
#define HALT_COP_WAIT_EVENT BIT(30)
|
||||
#define HALT_COP_STOP_UNTIL_IRQ BIT(31)
|
||||
#define HALT_COP_MAX_CNT 0xFF
|
||||
#define FLOW_CTLR_HALT_CPU0_EVENTS 0x0
|
||||
#define FLOW_CTLR_HALT_CPU1_EVENTS 0x14
|
||||
#define FLOW_CTLR_HALT_CPU2_EVENTS 0x1C
|
||||
#define FLOW_CTLR_HALT_CPU3_EVENTS 0x24
|
||||
#define FLOW_CTLR_CPU0_CSR 0x8
|
||||
#define FLOW_CTLR_CPU1_CSR 0x18
|
||||
#define FLOW_CTLR_CPU2_CSR 0x20
|
||||
#define FLOW_CTLR_CPU3_CSR 0x28
|
||||
#define FLOW_CTLR_RAM_REPAIR 0x40
|
||||
#define RAM_REPAIR_REQ BIT(0)
|
||||
#define RAM_REPAIR_STS BIT(1)
|
||||
#define FLOW_CTLR_BPMP_CLUSTER_CONTROL 0x98
|
||||
#define CLUSTER_CTRL_ACTIVE_SLOW BIT(0)
|
||||
#define FLOW_CTLR_HALT_COP_EVENTS 0x4
|
||||
#define FLOW_CTLR_HALT_CPU0_EVENTS 0x0
|
||||
#define FLOW_CTLR_HALT_CPU1_EVENTS 0x14
|
||||
#define FLOW_CTLR_HALT_CPU2_EVENTS 0x1C
|
||||
#define FLOW_CTLR_HALT_CPU3_EVENTS 0x24
|
||||
#define HALT_GIC_IRQ BIT(9)
|
||||
#define HALT_LIC_IRQ BIT(11)
|
||||
#define HALT_SEC BIT(23)
|
||||
#define HALT_MSEC BIT(24)
|
||||
#define HALT_USEC BIT(25)
|
||||
#define HALT_JTAG BIT(28)
|
||||
#define HALT_MODE_NONE (0 << 29u)
|
||||
#define HALT_MODE_RUN_AND_INT (1 << 29u)
|
||||
#define HALT_MODE_WAITEVENT (2 << 29u)
|
||||
#define HALT_MODE_WAITEVENT_AND_INT (3 << 29u)
|
||||
#define HALT_MODE_STOP_UNTIL_IRQ (4 << 29u)
|
||||
#define HALT_MODE_STOP_UNTIL_IRQ_AND_INT (5 << 29u)
|
||||
#define HALT_MODE_STOP_UNTIL_EVENT_AND_IRQ (6 << 29u)
|
||||
#define HALT_MAX_CNT 0xFF
|
||||
#define FLOW_CTLR_COP_CSR 0xC
|
||||
#define FLOW_CTLR_CPU0_CSR 0x8
|
||||
#define FLOW_CTLR_CPU1_CSR 0x18
|
||||
#define FLOW_CTLR_CPU2_CSR 0x20
|
||||
#define FLOW_CTLR_CPU3_CSR 0x28
|
||||
#define CSR_ENABLE BIT(0)
|
||||
#define CSR_WAIT_WFI_NONE (0 << 8u)
|
||||
#define CSR_WAIT_WFI_CPU0 (BIT(0) << 8u)
|
||||
#define CSR_ENABLE_EXT_CPU_ONLY (0 << 12u)
|
||||
#define CSR_ENABLE_EXT_CPU_NCPU (1 << 12u)
|
||||
#define CSR_ENABLE_EXT_CPU_RAIL (2 << 12u)
|
||||
#define CSR_EVENT_FLAG BIT(14)
|
||||
#define CSR_INTR_FLAG BIT(15)
|
||||
#define CSR_HALT BIT(22)
|
||||
#define FLOW_CTLR_CPU_PWR_CSR 0x38
|
||||
#define CPU_PWR_RAIL_STS_MASK (3 << 1u)
|
||||
#define CPU_PWR_RAIL_OFF 0
|
||||
#define FLOW_CTLR_RAM_REPAIR 0x40
|
||||
#define RAM_REPAIR_REQ BIT(0)
|
||||
#define RAM_REPAIR_STS BIT(1)
|
||||
#define FLOW_CTLR_BPMP_CLUSTER_CONTROL 0x98
|
||||
#define CLUSTER_CTRL_ACTIVE_SLOW BIT(0)
|
||||
|
||||
/* MSelect registers */
|
||||
#define MSELECT_CONFIG 0x00
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#define EXCP_TYPE_ADDR 0x4003FFF8
|
||||
#define EXCP_TYPE_WDT 0x544457 // "WDT".
|
||||
|
||||
#define USE_RTC_TIMER
|
||||
|
||||
u32 get_tmr_s()
|
||||
{
|
||||
(void)RTC(APBDEV_RTC_MILLI_SECONDS);
|
||||
|
@ -118,4 +120,4 @@ bool watchdog_fired()
|
|||
{
|
||||
// Return if watchdog got fired. User handles clearing.
|
||||
return (*(u32 *)EXCP_TYPE_ADDR == EXCP_TYPE_WDT);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -174,14 +174,14 @@ void uart_empty_fifo(u32 idx, u32 which)
|
|||
(void)uart->UART_SPR;
|
||||
usleep(96);
|
||||
|
||||
uart->UART_IIR_FCR = UART_IIR_FCR_EN_FIFO | UART_IIR_FCR_TX_CLR | UART_IIR_FCR_RX_CLR;
|
||||
uart->UART_IIR_FCR = UART_IIR_FCR_EN_FIFO | which;
|
||||
(void)uart->UART_SPR;
|
||||
usleep(18);
|
||||
u32 tries = 0;
|
||||
|
||||
if (UART_IIR_FCR_TX_CLR & which)
|
||||
{
|
||||
while (tries < 10 && uart->UART_LSR & UART_LSR_TMTY)
|
||||
while (tries < 10 && !(uart->UART_LSR & UART_LSR_TMTY))
|
||||
{
|
||||
tries++;
|
||||
usleep(100);
|
||||
|
@ -191,7 +191,7 @@ void uart_empty_fifo(u32 idx, u32 which)
|
|||
|
||||
if (UART_IIR_FCR_RX_CLR & which)
|
||||
{
|
||||
while (tries < 10 && !uart->UART_LSR & UART_LSR_RDR)
|
||||
while (tries < 10 && (uart->UART_LSR & UART_LSR_RDR))
|
||||
{
|
||||
tries++;
|
||||
usleep(100);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2019-2022 CTCaer
|
||||
* Copyright (c) 2019-2024 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,
|
||||
|
@ -135,7 +135,7 @@ int emmc_set_partition(u32 partition) { return sdmmc_storage_set_mmc_partition(&
|
|||
|
||||
void emmc_gpt_parse(link_t *gpt)
|
||||
{
|
||||
gpt_t *gpt_buf = (gpt_t *)calloc(GPT_NUM_BLOCKS, EMMC_BLOCKSIZE);
|
||||
gpt_t *gpt_buf = (gpt_t *)zalloc(GPT_NUM_BLOCKS * EMMC_BLOCKSIZE);
|
||||
|
||||
#ifdef BDK_EMUMMC_ENABLE
|
||||
emummc_storage_read(GPT_FIRST_LBA, GPT_NUM_BLOCKS, gpt_buf);
|
||||
|
@ -149,7 +149,7 @@ void emmc_gpt_parse(link_t *gpt)
|
|||
|
||||
for (u32 i = 0; i < gpt_buf->header.num_part_ents; i++)
|
||||
{
|
||||
emmc_part_t *part = (emmc_part_t *)calloc(sizeof(emmc_part_t), 1);
|
||||
emmc_part_t *part = (emmc_part_t *)zalloc(sizeof(emmc_part_t));
|
||||
|
||||
if (gpt_buf->entries[i].lba_start < gpt_buf->header.first_use_lba)
|
||||
continue;
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
#define GPT_FIRST_LBA 1
|
||||
#define GPT_NUM_BLOCKS 33
|
||||
#define EMMC_BLOCKSIZE 512
|
||||
#define EMMC_BLOCKSIZE SDMMC_DAT_BLOCKSIZE
|
||||
|
||||
enum
|
||||
{
|
||||
|
|
|
@ -274,7 +274,7 @@ void *sd_file_read(const char *path, u32 *fsize)
|
|||
return buf;
|
||||
}
|
||||
|
||||
int sd_save_to_file(void *buf, u32 size, const char *filename)
|
||||
int sd_save_to_file(const void *buf, u32 size, const char *filename)
|
||||
{
|
||||
FIL fp;
|
||||
u32 res = 0;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include <storage/sdmmc_driver.h>
|
||||
#include <libs/fatfs/ff.h>
|
||||
|
||||
#define SD_BLOCKSIZE 512
|
||||
#define SD_BLOCKSIZE SDMMC_DAT_BLOCKSIZE
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -61,6 +61,6 @@ void sd_unmount();
|
|||
void sd_end();
|
||||
bool sd_is_gpt();
|
||||
void *sd_file_read(const char *path, u32 *fsize);
|
||||
int sd_save_to_file(void *buf, u32 size, const char *filename);
|
||||
int sd_save_to_file(const void *buf, u32 size, const char *filename);
|
||||
|
||||
#endif
|
|
@ -46,7 +46,7 @@
|
|||
|
||||
/* OCR bit definitions */
|
||||
#define SD_OCR_VDD_18 (1U << 7) /* VDD voltage 1.8 */
|
||||
#define SD_VHD_27_36 (1U << 8) /* VDD voltage 2.7 ~ 3.6 */
|
||||
#define SD_VHS_27_36 (1U << 8) /* VDD voltage 2.7 ~ 3.6 */
|
||||
#define SD_OCR_VDD_32_33 (1U << 20) /* VDD voltage 3.2 ~ 3.3 */
|
||||
#define SD_OCR_S18R (1U << 24) /* 1.8V switching request */
|
||||
#define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
|
||||
u32 sd_power_cycle_time_start;
|
||||
|
||||
static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size)
|
||||
static inline u32 unstuff_bits(const u32 *resp, u32 start, u32 size)
|
||||
{
|
||||
const u32 mask = (size < 32 ? 1 << size : 0) - 1;
|
||||
const u32 off = 3 - ((start) / 32);
|
||||
|
@ -184,7 +184,7 @@ int sdmmc_storage_vendor_sandisk_report(sdmmc_storage_t *storage, void *buf)
|
|||
|
||||
reqbuf.buf = buf;
|
||||
reqbuf.num_sectors = 1;
|
||||
reqbuf.blksize = 512;
|
||||
reqbuf.blksize = SDMMC_DAT_BLOCKSIZE;
|
||||
reqbuf.is_write = 0;
|
||||
reqbuf.is_multi_block = 0;
|
||||
reqbuf.is_auto_stop_trn = 0;
|
||||
|
@ -215,7 +215,7 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out
|
|||
|
||||
reqbuf.buf = buf;
|
||||
reqbuf.num_sectors = num_sectors;
|
||||
reqbuf.blksize = 512;
|
||||
reqbuf.blksize = SDMMC_DAT_BLOCKSIZE;
|
||||
reqbuf.is_write = is_write;
|
||||
reqbuf.is_multi_block = 1;
|
||||
reqbuf.is_auto_stop_trn = 1;
|
||||
|
@ -233,6 +233,8 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out
|
|||
|
||||
int sdmmc_storage_end(sdmmc_storage_t *storage)
|
||||
{
|
||||
DPRINTF("[SDMMC%d] end\n", storage->sdmmc->id);
|
||||
|
||||
if (!_sdmmc_storage_go_idle_state(storage))
|
||||
return 0;
|
||||
|
||||
|
@ -275,7 +277,7 @@ reinit_try:
|
|||
// Disk IO failure! Reinit SD/EMMC to a lower speed.
|
||||
if (storage->sdmmc->id == SDMMC_1 || storage->sdmmc->id == SDMMC_4)
|
||||
{
|
||||
int res;
|
||||
int res = 0;
|
||||
|
||||
if (storage->sdmmc->id == SDMMC_1)
|
||||
{
|
||||
|
@ -326,7 +328,7 @@ reinit_try:
|
|||
out:
|
||||
sct_off += blkcnt;
|
||||
sct_total -= blkcnt;
|
||||
bbuf += 512 * blkcnt;
|
||||
bbuf += SDMMC_DAT_BLOCKSIZE * blkcnt;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -338,13 +340,13 @@ int sdmmc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, vo
|
|||
if (mc_client_has_access(buf) && !((u32)buf % 8))
|
||||
return _sdmmc_storage_readwrite(storage, sector, num_sectors, buf, 0);
|
||||
|
||||
if (num_sectors > (SDMMC_UP_BUF_SZ / 512))
|
||||
if (num_sectors > (SDMMC_UP_BUF_SZ / SDMMC_DAT_BLOCKSIZE))
|
||||
return 0;
|
||||
|
||||
u8 *tmp_buf = (u8 *)SDMMC_UPPER_BUFFER;
|
||||
if (_sdmmc_storage_readwrite(storage, sector, num_sectors, tmp_buf, 0))
|
||||
{
|
||||
memcpy(buf, tmp_buf, 512 * num_sectors);
|
||||
memcpy(buf, tmp_buf, SDMMC_DAT_BLOCKSIZE * num_sectors);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -356,11 +358,11 @@ int sdmmc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, v
|
|||
if (mc_client_has_access(buf) && !((u32)buf % 8))
|
||||
return _sdmmc_storage_readwrite(storage, sector, num_sectors, buf, 1);
|
||||
|
||||
if (num_sectors > (SDMMC_UP_BUF_SZ / 512))
|
||||
if (num_sectors > (SDMMC_UP_BUF_SZ / SDMMC_DAT_BLOCKSIZE))
|
||||
return 0;
|
||||
|
||||
u8 *tmp_buf = (u8 *)SDMMC_UPPER_BUFFER;
|
||||
memcpy(tmp_buf, buf, 512 * num_sectors);
|
||||
memcpy(tmp_buf, buf, SDMMC_DAT_BLOCKSIZE * num_sectors);
|
||||
return _sdmmc_storage_readwrite(storage, sector, num_sectors, tmp_buf, 1);
|
||||
}
|
||||
|
||||
|
@ -519,7 +521,7 @@ int mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf)
|
|||
|
||||
sdmmc_req_t reqbuf;
|
||||
reqbuf.buf = buf;
|
||||
reqbuf.blksize = 512;
|
||||
reqbuf.blksize = SDMMC_DAT_BLOCKSIZE;
|
||||
reqbuf.num_sectors = 1;
|
||||
reqbuf.is_write = 0;
|
||||
reqbuf.is_multi_block = 0;
|
||||
|
@ -708,9 +710,9 @@ int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_wid
|
|||
return 0;
|
||||
DPRINTF("[MMC] card selected\n");
|
||||
|
||||
if (!_sdmmc_storage_set_blocklen(storage, 512))
|
||||
if (!_sdmmc_storage_set_blocklen(storage, EMMC_BLOCKSIZE))
|
||||
return 0;
|
||||
DPRINTF("[MMC] set blocklen to 512\n");
|
||||
DPRINTF("[MMC] set blocklen to EMMC_BLOCKSIZE\n");
|
||||
|
||||
// Check system specification version, only version 4.0 and later support below features.
|
||||
if (storage->csd.mmca_vsn < CSD_SPEC_VER_4)
|
||||
|
@ -781,7 +783,7 @@ static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp
|
|||
}
|
||||
|
||||
#ifdef SDMMC_DEBUG_PRINT_SD_REGS
|
||||
void _sd_storage_debug_print_cid(u32 *raw_cid)
|
||||
void _sd_storage_debug_print_cid(const u32 *raw_cid)
|
||||
{
|
||||
gfx_printf("Card Identification\n");
|
||||
|
||||
|
@ -797,7 +799,7 @@ void _sd_storage_debug_print_cid(u32 *raw_cid)
|
|||
gfx_printf("--RSVD-- %X\n", unstuff_bits(raw_cid, 20, 4));
|
||||
}
|
||||
|
||||
void _sd_storage_debug_print_csd(u32 *raw_csd)
|
||||
void _sd_storage_debug_print_csd(const u32 *raw_csd)
|
||||
{
|
||||
gfx_printf("\n");
|
||||
|
||||
|
@ -834,7 +836,7 @@ void _sd_storage_debug_print_csd(u32 *raw_csd)
|
|||
unstuff_bits(raw_csd, 16, 5), unstuff_bits(raw_csd, 8, 2));
|
||||
}
|
||||
|
||||
void _sd_storage_debug_print_scr(u32 *raw_scr)
|
||||
void _sd_storage_debug_print_scr(const u32 *raw_scr)
|
||||
{
|
||||
u32 resp[4];
|
||||
memcpy(&resp[2], raw_scr, 8);
|
||||
|
@ -855,7 +857,7 @@ void _sd_storage_debug_print_scr(u32 *raw_scr)
|
|||
gfx_printf("--RSVD-- %X\n", unstuff_bits(resp, 36, 2));
|
||||
}
|
||||
|
||||
void _sd_storage_debug_print_ssr(u8 *raw_ssr)
|
||||
void _sd_storage_debug_print_ssr(const u8 *raw_ssr)
|
||||
{
|
||||
u32 raw_ssr0[4]; // 511:384.
|
||||
u32 raw_ssr1[4]; // 383:256.
|
||||
|
@ -910,7 +912,7 @@ void _sd_storage_debug_print_ssr(u8 *raw_ssr)
|
|||
static int _sd_storage_send_if_cond(sdmmc_storage_t *storage, bool *is_sdsc)
|
||||
{
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
u16 vhd_pattern = SD_VHD_27_36 | 0xAA;
|
||||
u16 vhd_pattern = SD_VHS_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))
|
||||
{
|
||||
|
@ -1089,7 +1091,7 @@ static int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf)
|
|||
|
||||
sdmmc_req_t reqbuf;
|
||||
reqbuf.buf = buf;
|
||||
reqbuf.blksize = 64;
|
||||
reqbuf.blksize = SDMMC_CMD_BLOCKSIZE;
|
||||
reqbuf.num_sectors = 1;
|
||||
reqbuf.is_write = 0;
|
||||
reqbuf.is_multi_block = 0;
|
||||
|
@ -1113,7 +1115,7 @@ static int _sd_storage_switch(sdmmc_storage_t *storage, void *buf, int mode, int
|
|||
|
||||
sdmmc_req_t reqbuf;
|
||||
reqbuf.buf = buf;
|
||||
reqbuf.blksize = 64;
|
||||
reqbuf.blksize = SDMMC_CMD_BLOCKSIZE;
|
||||
reqbuf.num_sectors = 1;
|
||||
reqbuf.is_write = 0;
|
||||
reqbuf.is_multi_block = 0;
|
||||
|
@ -1132,17 +1134,20 @@ static void _sd_storage_set_power_limit(sdmmc_storage_t *storage, u16 power_limi
|
|||
u32 pwr = SD_SET_POWER_LIMIT_0_72;
|
||||
|
||||
// If UHS-I only, anything above 1.44W defaults to 1.44W.
|
||||
/*
|
||||
if (power_limit & SD_MAX_POWER_2_88)
|
||||
pwr = SD_SET_POWER_LIMIT_2_88;
|
||||
else if (power_limit & SD_MAX_POWER_2_16)
|
||||
pwr = SD_SET_POWER_LIMIT_2_16;
|
||||
else if (power_limit & SD_MAX_POWER_1_44)
|
||||
*/
|
||||
if (power_limit & SD_MAX_POWER_1_44)
|
||||
pwr = SD_SET_POWER_LIMIT_1_44;
|
||||
|
||||
_sd_storage_switch(storage, buf, SD_SWITCH_SET, SD_SWITCH_GRP_PWRLIM, pwr);
|
||||
|
||||
switch ((buf[15] >> 4) & 0x0F)
|
||||
{
|
||||
/*
|
||||
case SD_SET_POWER_LIMIT_2_88:
|
||||
DPRINTF("[SD] power limit raised to 2880 mW\n");
|
||||
break;
|
||||
|
@ -1150,7 +1155,7 @@ static void _sd_storage_set_power_limit(sdmmc_storage_t *storage, u16 power_limi
|
|||
case SD_SET_POWER_LIMIT_2_16:
|
||||
DPRINTF("[SD] power limit raised to 2160 mW\n");
|
||||
break;
|
||||
|
||||
*/
|
||||
case SD_SET_POWER_LIMIT_1_44:
|
||||
DPRINTF("[SD] power limit raised to 1440 mW\n");
|
||||
break;
|
||||
|
@ -1396,7 +1401,7 @@ static int _sd_storage_enable_uhs_low_volt(sdmmc_storage_t *storage, u32 type, u
|
|||
}
|
||||
|
||||
// Try to raise the power limit to let the card perform better.
|
||||
if (hs_type != UHS_SDR25_BUS_SPEED)
|
||||
if (hs_type != UHS_SDR25_BUS_SPEED) // Not applicable for SDR12/SDR25.
|
||||
_sd_storage_set_power_limit(storage, fmodes.power_limit, buf);
|
||||
|
||||
// Setup and set selected card and bus speed.
|
||||
|
@ -1424,9 +1429,6 @@ static int _sd_storage_enable_hs_high_volt(sdmmc_storage_t *storage, u8 *buf)
|
|||
|
||||
DPRINTF("[SD] access: %02X, power: %02X\n", fmodes.access_mode, fmodes.power_limit);
|
||||
|
||||
// Try to raise the power limit to let the card perform better.
|
||||
_sd_storage_set_power_limit(storage, fmodes.power_limit, buf);
|
||||
|
||||
if (!(fmodes.access_mode & SD_MODE_HIGH_SPEED))
|
||||
return 1;
|
||||
|
||||
|
@ -1526,7 +1528,7 @@ int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
|
|||
|
||||
sdmmc_req_t reqbuf;
|
||||
reqbuf.buf = buf;
|
||||
reqbuf.blksize = 64;
|
||||
reqbuf.blksize = SDMMC_CMD_BLOCKSIZE;
|
||||
reqbuf.num_sectors = 1;
|
||||
reqbuf.is_write = 0;
|
||||
reqbuf.is_multi_block = 0;
|
||||
|
@ -1545,7 +1547,7 @@ int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
|
|||
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
|
||||
|
||||
// Convert buffer to LE.
|
||||
for (int i = 0; i < 64; i += 4)
|
||||
for (int i = 0; i < SDMMC_CMD_BLOCKSIZE; i += 4)
|
||||
{
|
||||
storage->raw_ssr[i + 3] = buf[i];
|
||||
storage->raw_ssr[i + 2] = buf[i + 1];
|
||||
|
@ -1596,7 +1598,7 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
|
|||
{
|
||||
case 0:
|
||||
storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2);
|
||||
storage->csd.capacity <<= unstuff_bits(raw_csd, 80, 4) - 9; // Convert native block size to LBA 512B.
|
||||
storage->csd.capacity <<= unstuff_bits(raw_csd, 80, 4) - 9; // Convert native block size to LBA SDMMC_DAT_BLOCKSIZE.
|
||||
break;
|
||||
|
||||
case 1:
|
||||
|
@ -1698,9 +1700,9 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_widt
|
|||
return 0;
|
||||
DPRINTF("[SD] card selected\n");
|
||||
|
||||
if (!_sdmmc_storage_set_blocklen(storage, 512))
|
||||
if (!_sdmmc_storage_set_blocklen(storage, SD_BLOCKSIZE))
|
||||
return 0;
|
||||
DPRINTF("[SD] set blocklen to 512\n");
|
||||
DPRINTF("[SD] set blocklen to SD_BLOCKSIZE\n");
|
||||
|
||||
// Disconnect Card Detect resistor from DAT3.
|
||||
if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_CLR_CARD_DETECT, 0, 0, R1_STATE_TRAN))
|
||||
|
@ -1775,7 +1777,7 @@ int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf)
|
|||
|
||||
sdmmc_req_t reqbuf;
|
||||
reqbuf.buf = buf;
|
||||
reqbuf.blksize = 64;
|
||||
reqbuf.blksize = SDMMC_CMD_BLOCKSIZE;
|
||||
reqbuf.num_sectors = 1;
|
||||
reqbuf.is_write = 1;
|
||||
reqbuf.is_multi_block = 0;
|
||||
|
|
|
@ -22,6 +22,9 @@
|
|||
#include <storage/sd_def.h>
|
||||
#include <storage/sdmmc_driver.h>
|
||||
|
||||
#define SDMMC_CMD_BLOCKSIZE 64
|
||||
#define SDMMC_DAT_BLOCKSIZE 512
|
||||
|
||||
extern u32 sd_power_cycle_time_start;
|
||||
|
||||
typedef enum _sdmmc_type
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2023 CTCaer
|
||||
* Copyright (c) 2018-2024 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,
|
||||
|
@ -109,8 +109,8 @@ void sdmmc_save_tap_value(sdmmc_t *sdmmc)
|
|||
|
||||
static int _sdmmc_config_tap_val(sdmmc_t *sdmmc, u32 type)
|
||||
{
|
||||
const u32 dqs_trim_val = 40; // 24 if HS533/HS667.
|
||||
const u8 tap_values_t210[4] = { 4, 0, 3, 0 };
|
||||
static const u32 dqs_trim_val = 40; // 24 if HS533/HS667.
|
||||
static const u8 tap_values_t210[4] = { 4, 0, 3, 0 };
|
||||
|
||||
u32 tap_val = 0;
|
||||
|
||||
|
@ -222,6 +222,9 @@ static void _sdmmc_autocal_execute(sdmmc_t *sdmmc, u32 power)
|
|||
{
|
||||
sdmmc->regs->autocalcfg &= ~SDHCI_TEGRA_AUTOCAL_ENABLE;
|
||||
_sdmmc_pad_config_fallback(sdmmc, power);
|
||||
#ifdef ERROR_EXTRA_PRINTING
|
||||
EPRINTFARGS("SDMMC%d: Comp Pad cal timeout!", sdmmc->id + 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Disable E_INPUT (SD) or enable E_PWRD (eMMC) to conserve power.
|
||||
|
@ -403,7 +406,7 @@ static void _sdmmc_card_clock_enable(sdmmc_t *sdmmc)
|
|||
sdmmc->card_clock_enabled = 1;
|
||||
}
|
||||
|
||||
static void _sdmmc_sd_clock_disable(sdmmc_t *sdmmc)
|
||||
static void _sdmmc_card_clock_disable(sdmmc_t *sdmmc)
|
||||
{
|
||||
sdmmc->card_clock_enabled = 0;
|
||||
sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN;
|
||||
|
@ -572,7 +575,7 @@ static int _sdmmc_setup_read_small_block(sdmmc_t *sdmmc)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int _sdmmc_send_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, bool is_data_present)
|
||||
static int _sdmmc_send_cmd(sdmmc_t *sdmmc, const sdmmc_cmd_t *cmd, bool is_data_present)
|
||||
{
|
||||
u16 cmdflags = 0;
|
||||
|
||||
|
@ -934,7 +937,7 @@ static u32 _sdmmc_check_mask_interrupt(sdmmc_t *sdmmc, u16 *pout, u16 mask)
|
|||
if (norintsts & SDHCI_INT_ERROR)
|
||||
{
|
||||
#ifdef ERROR_EXTRA_PRINTING
|
||||
EPRINTFARGS("SDMMC%d: norintsts %08X, errintsts %08X\n", sdmmc->id + 1, norintsts, errintsts);
|
||||
EPRINTFARGS("SDMMC%d: norintsts %08X, errintsts %08X", sdmmc->id + 1, norintsts, errintsts);
|
||||
#endif
|
||||
sdmmc->regs->errintsts = errintsts;
|
||||
return SDMMC_MASKINT_ERROR;
|
||||
|
@ -1022,7 +1025,7 @@ int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp)
|
|||
return result;
|
||||
}
|
||||
|
||||
static int _sdmmc_config_sdma(sdmmc_t *sdmmc, u32 *blkcnt_out, sdmmc_req_t *req)
|
||||
static int _sdmmc_config_sdma(sdmmc_t *sdmmc, u32 *blkcnt_out, const sdmmc_req_t *req)
|
||||
{
|
||||
if (!req->blksize || !req->num_sectors)
|
||||
return 0;
|
||||
|
@ -1152,7 +1155,7 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
|
|||
int result = _sdmmc_wait_response(sdmmc);
|
||||
#ifdef ERROR_EXTRA_PRINTING
|
||||
if (!result)
|
||||
EPRINTFARGS("SDMMC%d: Transfer timeout!", sdmmc->id + 1);
|
||||
EPRINTFARGS("SDMMC%d: Transfer error!", sdmmc->id + 1);
|
||||
#endif
|
||||
DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result,
|
||||
sdmmc->regs->rspreg0, sdmmc->regs->rspreg1, sdmmc->regs->rspreg2, sdmmc->regs->rspreg3);
|
||||
|
@ -1273,16 +1276,7 @@ static int _sdmmc_config_sdmmc1(bool t210b01)
|
|||
if (!sdmmc_get_sd_inserted())
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Pinmux config:
|
||||
* DRV_TYPE = DRIVE_2X (for 33 Ohm driver)
|
||||
* E_SCHMT = ENABLE (for 1.8V), DISABLE (for 3.3V)
|
||||
* E_INPUT = ENABLE
|
||||
* TRISTATE = PASSTHROUGH
|
||||
* APB_MISC_GP_SDMMCx_CLK_LPBK_CONTROL = SDMMCx_CLK_PAD_E_LPBK for CLK
|
||||
*/
|
||||
|
||||
// Enable deep loopback for SDMMC1 CLK pad.
|
||||
// Enable deep loopback for SDMMC1 CLK pad so reads work.
|
||||
APB_MISC(APB_MISC_GP_SDMMC1_CLK_LPBK_CONTROL) = 1;
|
||||
|
||||
// Configure SDMMC1 CLK pinmux, based on state and SoC type.
|
||||
|
@ -1302,18 +1296,18 @@ static int _sdmmc_config_sdmmc1(bool t210b01)
|
|||
_sdmmc_config_sdmmc1_schmitt();
|
||||
|
||||
// Make sure the SDMMC1 controller is powered.
|
||||
PMC(APBDEV_PMC_NO_IOPOWER) |= PMC_NO_IOPOWER_SDMMC1_IO_EN;
|
||||
PMC(APBDEV_PMC_NO_IOPOWER) |= PMC_NO_IOPOWER_SDMMC1;
|
||||
usleep(1000);
|
||||
PMC(APBDEV_PMC_NO_IOPOWER) &= ~(PMC_NO_IOPOWER_SDMMC1_IO_EN);
|
||||
PMC(APBDEV_PMC_NO_IOPOWER) &= ~PMC_NO_IOPOWER_SDMMC1;
|
||||
(void)PMC(APBDEV_PMC_NO_IOPOWER); // Commit write.
|
||||
|
||||
// Set enable SD card power.
|
||||
// Enable SD card power. Powers LDO2 also.
|
||||
PINMUX_AUX(PINMUX_AUX_DMIC3_CLK) = PINMUX_PULL_DOWN | 2;
|
||||
gpio_direction_output(GPIO_PORT_E, GPIO_PIN_4, GPIO_HIGH);
|
||||
usleep(10000);
|
||||
|
||||
// Inform IO pads that voltage is gonna be 3.3V.
|
||||
PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_SDMMC1_IO_EN;
|
||||
PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_33V_SDMMC1;
|
||||
(void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write.
|
||||
|
||||
// Enable SD card IO power.
|
||||
|
@ -1366,8 +1360,8 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type)
|
|||
u16 divisor;
|
||||
u8 vref_sel = 7;
|
||||
|
||||
const u8 trim_values_t210[4] = { 2, 8, 3, 8 };
|
||||
const u8 trim_values_t210b01[4] = { 14, 13, 15, 13 };
|
||||
static const u8 trim_values_t210[4] = { 2, 8, 3, 8 };
|
||||
static const u8 trim_values_t210b01[4] = { 14, 13, 15, 13 };
|
||||
const u8 *trim_values;
|
||||
|
||||
if (id > SDMMC_4 || id == SDMMC_3)
|
||||
|
@ -1403,19 +1397,18 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type)
|
|||
// Disable clock if enabled.
|
||||
if (clock_sdmmc_is_not_reset_and_enabled(id))
|
||||
{
|
||||
_sdmmc_sd_clock_disable(sdmmc);
|
||||
_sdmmc_card_clock_disable(sdmmc);
|
||||
_sdmmc_commit_changes(sdmmc);
|
||||
}
|
||||
|
||||
// Configure and enable selected clock.
|
||||
clock_sdmmc_get_card_clock_div(&clock, &divisor, type);
|
||||
clock_sdmmc_enable(id, clock);
|
||||
sdmmc->clock_stopped = 0;
|
||||
|
||||
// Make sure all sdmmc registers are reset.
|
||||
_sdmmc_reset_all(sdmmc);
|
||||
|
||||
sdmmc->clock_stopped = 0;
|
||||
|
||||
// Set default pad IO trimming configuration.
|
||||
sdmmc->regs->iospare |= BIT(19); // Enable 1 cycle delayed cmd_oen.
|
||||
sdmmc->regs->veniotrimctl &= ~BIT(2); // Set Band Gap VREG to supply DLL.
|
||||
|
@ -1456,23 +1449,23 @@ void sdmmc1_disable_power()
|
|||
// T210B01 WAR: Set pads to discharge state.
|
||||
_sdmmc_config_sdmmc1_pads(true);
|
||||
|
||||
// Disable SD card IO power regulator.
|
||||
// Disable SD card IO power.
|
||||
max7762x_regulator_enable(REGULATOR_LDO2, false);
|
||||
usleep(4000);
|
||||
|
||||
// Disable SD card IO power pin.
|
||||
// Disable SD card power.
|
||||
gpio_write(GPIO_PORT_E, GPIO_PIN_4, GPIO_LOW);
|
||||
|
||||
// T210/T210B01 WAR: Set start timer for IO and Controller power discharge.
|
||||
sd_power_cycle_time_start = get_tmr_ms();
|
||||
usleep(1000); // To power cycle, min 1ms without power is needed.
|
||||
usleep(10000); // To power cycle, min 1ms without power is needed.
|
||||
|
||||
// Disable SDMMC1 controller power.
|
||||
PMC(APBDEV_PMC_NO_IOPOWER) |= PMC_NO_IOPOWER_SDMMC1_IO_EN;
|
||||
PMC(APBDEV_PMC_NO_IOPOWER) |= PMC_NO_IOPOWER_SDMMC1;
|
||||
(void)PMC(APBDEV_PMC_NO_IOPOWER); // Commit write.
|
||||
|
||||
// Inform IO pads that next voltage might be 3.3V.
|
||||
PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_SDMMC1_IO_EN;
|
||||
PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_33V_SDMMC1;
|
||||
(void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write.
|
||||
|
||||
// T210B01 WAR: Restore pads to reset state.
|
||||
|
@ -1486,7 +1479,7 @@ void sdmmc_end(sdmmc_t *sdmmc)
|
|||
{
|
||||
if (!sdmmc->clock_stopped)
|
||||
{
|
||||
_sdmmc_sd_clock_disable(sdmmc);
|
||||
_sdmmc_card_clock_disable(sdmmc);
|
||||
// Disable SDMMC power.
|
||||
_sdmmc_set_io_power(sdmmc, SDMMC_POWER_OFF);
|
||||
_sdmmc_commit_changes(sdmmc);
|
||||
|
@ -1547,7 +1540,7 @@ int sdmmc_enable_low_voltage(sdmmc_t *sdmmc)
|
|||
usleep(150);
|
||||
|
||||
// Inform IO pads that we switched to 1.8V.
|
||||
PMC(APBDEV_PMC_PWR_DET_VAL) &= ~(PMC_PWR_DET_SDMMC1_IO_EN);
|
||||
PMC(APBDEV_PMC_PWR_DET_VAL) &= ~PMC_PWR_DET_33V_SDMMC1;
|
||||
(void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write.
|
||||
|
||||
// Enable schmitt trigger for better duty cycle and low jitter clock.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Fan driver for Nintendo Switch
|
||||
*
|
||||
* Copyright (c) 2018-2023 CTCaer
|
||||
* Copyright (c) 2018-2024 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,
|
||||
|
@ -27,7 +27,7 @@
|
|||
#include <soc/timer.h>
|
||||
#include <soc/t210.h>
|
||||
|
||||
void set_fan_duty(u32 duty)
|
||||
void fan_set_duty(u32 duty)
|
||||
{
|
||||
static bool fan_init = false;
|
||||
static u16 curr_duty = -1;
|
||||
|
@ -49,16 +49,8 @@ void set_fan_duty(u32 duty)
|
|||
|
||||
// Enable PWM if disabled.
|
||||
if (fuse_read_hw_type() == FUSE_NX_HW_TYPE_AULA)
|
||||
{
|
||||
// Ease the stress to APB.
|
||||
bpmp_freq_t prev_fid = bpmp_clk_rate_set(BPMP_CLK_NORMAL);
|
||||
|
||||
clock_enable_pwm();
|
||||
|
||||
// Restore OC.
|
||||
bpmp_clk_rate_set(prev_fid);
|
||||
}
|
||||
|
||||
PWM(PWM_CONTROLLER_PWM_CSR_1) = PWM_CSR_EN | (0x100 << 16); // Max PWM to disable fan.
|
||||
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_GPIO2) = 1; // Set source to PWM1.
|
||||
|
@ -91,7 +83,7 @@ void set_fan_duty(u32 duty)
|
|||
}
|
||||
}
|
||||
|
||||
void get_fan_speed(u32 *duty, u32 *rpm)
|
||||
void fan_get_speed(u32 *duty, u32 *rpm)
|
||||
{
|
||||
if (rpm)
|
||||
{
|
||||
|
@ -122,3 +114,15 @@ void get_fan_speed(u32 *duty, u32 *rpm)
|
|||
if (duty)
|
||||
*duty = 236 - ((PWM(PWM_CONTROLLER_PWM_CSR_1) >> 16) & 0xFF);
|
||||
}
|
||||
|
||||
void fan_set_from_temp(u32 temp)
|
||||
{
|
||||
if (temp >= 52)
|
||||
fan_set_duty(102);
|
||||
else if (temp >= 47)
|
||||
fan_set_duty(76);
|
||||
else if (temp >= 42)
|
||||
fan_set_duty(51);
|
||||
else if (temp <= 39)
|
||||
fan_set_duty(0);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Fan driver for Nintendo Switch
|
||||
*
|
||||
* Copyright (c) 2018 CTCaer
|
||||
* Copyright (c) 2018-2024 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
|
@ -22,8 +22,10 @@
|
|||
#include <utils/types.h>
|
||||
|
||||
// Disable: 0 (0 RPM), min duty: 1 (960 RPM), max duty 235 (11000 RPM).
|
||||
void set_fan_duty(u32 duty);
|
||||
// Passing NULL ptr on either of the two, disables parsing of it.
|
||||
void get_fan_speed(u32 *duty, u32 *rpm);
|
||||
void fan_set_duty(u32 duty);
|
||||
// Passing NULL ptr on either of the two, disables results.
|
||||
void fan_get_speed(u32 *duty, u32 *rpm);
|
||||
|
||||
void fan_set_from_temp(u32 temp);
|
||||
|
||||
#endif /* __FAN_H_ */
|
||||
|
|
|
@ -71,10 +71,16 @@ typedef struct _jc_cal_t
|
|||
u16 cry_min;
|
||||
} jc_cal_t;
|
||||
|
||||
enum {
|
||||
INPUT_POLL_HAS_PACKET,
|
||||
INPUT_POLL_NO_PACKET,
|
||||
INPUT_POLL_EXIT,
|
||||
};
|
||||
|
||||
static jc_cal_t jc_cal_ctx;
|
||||
static usb_ops_t usb_ops;
|
||||
|
||||
static bool _jc_calibration(jc_gamepad_rpt_t *jc_pad)
|
||||
static bool _jc_calibration(const jc_gamepad_rpt_t *jc_pad)
|
||||
{
|
||||
// Calibrate left stick.
|
||||
if (jc_cal_ctx.cl_step != JC_CAL_MAX_STEPS)
|
||||
|
@ -119,22 +125,24 @@ static bool _jc_calibration(jc_gamepad_rpt_t *jc_pad)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool _jc_poll(gamepad_report_t *rpt)
|
||||
static int _jc_poll(gamepad_report_t *rpt)
|
||||
{
|
||||
static gamepad_report_t prev_rpt = {0};
|
||||
|
||||
// Poll Joy-Con.
|
||||
jc_gamepad_rpt_t *jc_pad = joycon_poll();
|
||||
|
||||
if (!jc_pad)
|
||||
return false;
|
||||
return INPUT_POLL_NO_PACKET;
|
||||
|
||||
// Exit emulation if Left stick and Home are pressed.
|
||||
if (jc_pad->l3 && jc_pad->home)
|
||||
return true;
|
||||
return INPUT_POLL_EXIT;
|
||||
|
||||
if (jc_cal_ctx.cl_step != JC_CAL_MAX_STEPS || jc_cal_ctx.cr_step != JC_CAL_MAX_STEPS)
|
||||
{
|
||||
if (!_jc_calibration(jc_pad))
|
||||
return false;
|
||||
return INPUT_POLL_NO_PACKET;
|
||||
}
|
||||
|
||||
// Re-calibrate on disconnection.
|
||||
|
@ -282,7 +290,12 @@ static bool _jc_poll(gamepad_report_t *rpt)
|
|||
//rpt->btn13 = jc_pad->cap;
|
||||
//rpt->btn14 = jc_pad->home;
|
||||
|
||||
return false;
|
||||
if (!memcmp(rpt, &prev_rpt, sizeof(gamepad_report_t)))
|
||||
return INPUT_POLL_NO_PACKET;
|
||||
|
||||
memcpy(&prev_rpt, rpt, sizeof(gamepad_report_t));
|
||||
|
||||
return INPUT_POLL_HAS_PACKET;
|
||||
}
|
||||
|
||||
typedef struct _touchpad_report_t
|
||||
|
@ -351,12 +364,14 @@ static u8 _hid_transfer_start(usb_ctxt_t *usbs, u32 len)
|
|||
|
||||
static bool _hid_poll_jc(usb_ctxt_t *usbs)
|
||||
{
|
||||
if (_jc_poll((gamepad_report_t *)USB_EP_BULK_IN_BUF_ADDR))
|
||||
int res = _jc_poll((gamepad_report_t *)USB_EP_BULK_IN_BUF_ADDR);
|
||||
if (res == INPUT_POLL_EXIT)
|
||||
return true;
|
||||
|
||||
// Send HID report.
|
||||
if (_hid_transfer_start(usbs, sizeof(gamepad_report_t)))
|
||||
return true; // EP Error.
|
||||
if (res == INPUT_POLL_HAS_PACKET)
|
||||
if (_hid_transfer_start(usbs, sizeof(gamepad_report_t)))
|
||||
return true; // EP Error.
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* Copyright (c) 2003-2008 Alan Stern
|
||||
* Copyright (c) 2009 Samsung Electronics
|
||||
* Author: Michal Nazarewicz <m.nazarewicz@samsung.com>
|
||||
* Copyright (c) 2019-2023 CTCaer
|
||||
* Copyright (c) 2019-2024 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,
|
||||
|
@ -1842,10 +1842,11 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
|
|||
ums.bulk_ctxt.bulk_out_buf = (u8 *)USB_EP_BULK_OUT_BUF_ADDR;
|
||||
|
||||
// Set LUN parameters.
|
||||
ums.lun.ro = usbs->ro;
|
||||
ums.lun.type = usbs->type;
|
||||
ums.lun.partition = usbs->partition;
|
||||
ums.lun.offset = usbs->offset;
|
||||
ums.lun.ro = usbs->ro;
|
||||
ums.lun.type = usbs->type;
|
||||
ums.lun.partition = usbs->partition;
|
||||
ums.lun.num_sectors = usbs->sectors;
|
||||
ums.lun.offset = usbs->offset;
|
||||
ums.lun.removable = 1; // Always removable to force OSes to use prevent media removal.
|
||||
ums.lun.unit_attention_data = SS_RESET_OCCURRED;
|
||||
|
||||
|
@ -1898,10 +1899,14 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
|
|||
|
||||
ums.set_text(ums.label, "#C7EA46 Status:# Started UMS");
|
||||
|
||||
if (usbs->sectors)
|
||||
ums.lun.num_sectors = usbs->sectors;
|
||||
else
|
||||
ums.lun.num_sectors = ums.lun.storage->sec_cnt;
|
||||
// If partition sectors are not set get them from hardware.
|
||||
if (!ums.lun.num_sectors)
|
||||
{
|
||||
if (usbs->type == MMC_EMMC && (ums.lun.partition - 1)) // eMMC BOOT0/1.
|
||||
ums.lun.num_sectors = emmc_storage.ext_csd.boot_mult << 8;
|
||||
else
|
||||
ums.lun.num_sectors = ums.lun.storage->sec_cnt; // eMMC GPP or SD.
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
|
@ -1931,7 +1936,9 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
|
|||
|
||||
_handle_ep0_ctrl(&ums);
|
||||
|
||||
if (_parse_scsi_cmd(&ums, &ums.bulk_ctxt) || (ums.state > UMS_STATE_NORMAL))
|
||||
_parse_scsi_cmd(&ums, &ums.bulk_ctxt);
|
||||
|
||||
if (ums.state > UMS_STATE_NORMAL)
|
||||
continue;
|
||||
|
||||
_handle_ep0_ctrl(&ums);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Enhanced USB Device (EDCI) driver for Tegra X1
|
||||
*
|
||||
* Copyright (c) 2019-2023 CTCaer
|
||||
* Copyright (c) 2019-2024 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,
|
||||
|
@ -355,9 +355,15 @@ int usb_device_init()
|
|||
if (usb_init_done)
|
||||
return USB_RES_OK;
|
||||
|
||||
// Ease the stress to APB.
|
||||
bpmp_clk_rate_relaxed(true);
|
||||
|
||||
// Initialize USB2 controller PHY.
|
||||
_usb_init_phy();
|
||||
|
||||
// Restore OC.
|
||||
bpmp_clk_rate_relaxed(false);
|
||||
|
||||
// AHB USB performance cfg.
|
||||
AHB_GIZMO(AHB_GIZMO_AHB_MEM) |= AHB_MEM_DONT_SPLIT_AHB_WR | AHB_MEM_ENB_FAST_REARBITRATE;
|
||||
AHB_GIZMO(AHB_GIZMO_USB) |= AHB_GIZMO_IMMEDIATE;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* eXtensible USB Device driver (XDCI) for Tegra X1
|
||||
*
|
||||
* Copyright (c) 2020-2022 CTCaer
|
||||
* Copyright (c) 2020-2024 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,
|
||||
|
@ -883,6 +883,9 @@ static void _xusbd_init_device_clocks()
|
|||
|
||||
int xusb_device_init()
|
||||
{
|
||||
// Ease the stress to APB.
|
||||
bpmp_clk_rate_relaxed(true);
|
||||
|
||||
// Disable USB2 device controller clocks.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_USBD);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = BIT(CLK_L_USBD);
|
||||
|
@ -920,6 +923,9 @@ int xusb_device_init()
|
|||
// Initialize device clocks.
|
||||
_xusbd_init_device_clocks();
|
||||
|
||||
// Restore OC.
|
||||
bpmp_clk_rate_relaxed(false);
|
||||
|
||||
// Enable AHB redirect for access to IRAM for Event/EP ring buffers.
|
||||
mc_enable_ahb_redirect();
|
||||
|
||||
|
@ -1005,7 +1011,7 @@ static void _xusb_device_power_down()
|
|||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_CLR) = BIT(CLK_W_XUSB);
|
||||
}
|
||||
|
||||
static int _xusb_queue_trb(u32 ep_idx, void *trb, bool ring_doorbell)
|
||||
static int _xusb_queue_trb(u32 ep_idx, const void *trb, bool ring_doorbell)
|
||||
{
|
||||
int res = USB_RES_OK;
|
||||
data_trb_t *next_trb;
|
||||
|
@ -1220,7 +1226,7 @@ static int _xusb_wait_ep_stopped(u32 endpoint)
|
|||
return USB_RES_OK;
|
||||
}
|
||||
|
||||
static int _xusb_handle_transfer_event(transfer_event_trb_t *trb)
|
||||
static int _xusb_handle_transfer_event(const transfer_event_trb_t *trb)
|
||||
{
|
||||
// Advance dequeue list.
|
||||
data_trb_t *next_trb;
|
||||
|
@ -1455,7 +1461,7 @@ static int _xusb_handle_get_ep_status(u32 ep_idx)
|
|||
return _xusb_issue_data_trb(xusb_ep_status_descriptor, 2, USB_DIR_IN);
|
||||
}
|
||||
|
||||
static int _xusb_handle_get_class_request(usb_ctrl_setup_t *ctrl_setup)
|
||||
static int _xusb_handle_get_class_request(const usb_ctrl_setup_t *ctrl_setup)
|
||||
{
|
||||
u8 _bRequest = ctrl_setup->bRequest;
|
||||
u16 _wIndex = ctrl_setup->wIndex;
|
||||
|
@ -1486,7 +1492,7 @@ stall:
|
|||
return USB_RES_OK;
|
||||
}
|
||||
|
||||
static int _xusb_handle_get_descriptor(usb_ctrl_setup_t *ctrl_setup)
|
||||
static int _xusb_handle_get_descriptor(const usb_ctrl_setup_t *ctrl_setup)
|
||||
{
|
||||
u32 size;
|
||||
void *descriptor;
|
||||
|
@ -1615,7 +1621,7 @@ static int _xusb_handle_get_descriptor(usb_ctrl_setup_t *ctrl_setup)
|
|||
return _xusb_issue_data_trb(descriptor, size, USB_DIR_IN);
|
||||
}
|
||||
|
||||
static void _xusb_handle_set_request_dev_address(usb_ctrl_setup_t *ctrl_setup)
|
||||
static void _xusb_handle_set_request_dev_address(const usb_ctrl_setup_t *ctrl_setup)
|
||||
{
|
||||
u32 addr = ctrl_setup->wValue & 0xFF;
|
||||
|
||||
|
@ -1627,7 +1633,7 @@ static void _xusb_handle_set_request_dev_address(usb_ctrl_setup_t *ctrl_setup)
|
|||
usbd_xotg->device_state = XUSB_ADDRESSED_STS_WAIT;
|
||||
}
|
||||
|
||||
static void _xusb_handle_set_request_configuration(usb_ctrl_setup_t *ctrl_setup)
|
||||
static void _xusb_handle_set_request_configuration(const usb_ctrl_setup_t *ctrl_setup)
|
||||
{
|
||||
usbd_xotg->config_num = ctrl_setup->wValue;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2018 CTCaer
|
||||
* Copyright (c) 2018-2024 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,21 +17,23 @@
|
|||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dirlist.h"
|
||||
#include <libs/fatfs/ff.h>
|
||||
#include <mem/heap.h>
|
||||
#include <utils/types.h>
|
||||
|
||||
#define MAX_ENTRIES 64
|
||||
|
||||
char *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles, bool parse_dirs)
|
||||
dirlist_t *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles, bool parse_dirs)
|
||||
{
|
||||
int res = 0;
|
||||
u32 i = 0, j = 0, k = 0;
|
||||
u32 k = 0;
|
||||
DIR dir;
|
||||
FILINFO fno;
|
||||
|
||||
char *dir_entries = (char *)calloc(MAX_ENTRIES, 256);
|
||||
char *temp = (char *)calloc(1, 256);
|
||||
dirlist_t *dir_entries = (dirlist_t *)malloc(sizeof(dirlist_t));
|
||||
|
||||
// Setup pointer tree.
|
||||
for (u32 i = 0; i < DIR_MAX_ENTRIES; i++)
|
||||
dir_entries->name[i] = &dir_entries->data[i * 256];
|
||||
|
||||
if (!pattern && !f_opendir(&dir, directory))
|
||||
{
|
||||
|
@ -47,9 +49,8 @@ char *dirlist(const char *directory, const char *pattern, bool includeHiddenFile
|
|||
{
|
||||
if ((fno.fname[0] != '.') && (includeHiddenFiles || !(fno.fattrib & AM_HID)))
|
||||
{
|
||||
strcpy(dir_entries + (k * 256), fno.fname);
|
||||
k++;
|
||||
if (k > (MAX_ENTRIES - 1))
|
||||
strcpy(&dir_entries->data[k * 256], fno.fname);
|
||||
if (++k >= DIR_MAX_ENTRIES)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -62,9 +63,8 @@ char *dirlist(const char *directory, const char *pattern, bool includeHiddenFile
|
|||
{
|
||||
if (!(fno.fattrib & AM_DIR) && (fno.fname[0] != '.') && (includeHiddenFiles || !(fno.fattrib & AM_HID)))
|
||||
{
|
||||
strcpy(dir_entries + (k * 256), fno.fname);
|
||||
k++;
|
||||
if (k > (MAX_ENTRIES - 1))
|
||||
strcpy(&dir_entries->data[k * 256], fno.fname);
|
||||
if (++k >= DIR_MAX_ENTRIES)
|
||||
break;
|
||||
}
|
||||
res = f_findnext(&dir, &fno);
|
||||
|
@ -74,27 +74,27 @@ char *dirlist(const char *directory, const char *pattern, bool includeHiddenFile
|
|||
|
||||
if (!k)
|
||||
{
|
||||
free(temp);
|
||||
free(dir_entries);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Terminate name list.
|
||||
dir_entries->name[k] = NULL;
|
||||
|
||||
// Reorder ini files by ASCII ordering.
|
||||
for (i = 0; i < k - 1 ; i++)
|
||||
for (u32 i = 0; i < k - 1 ; i++)
|
||||
{
|
||||
for (j = i + 1; j < k; j++)
|
||||
for (u32 j = i + 1; j < k; j++)
|
||||
{
|
||||
if (strcmp(&dir_entries[i * 256], &dir_entries[j * 256]) > 0)
|
||||
if (strcmp(dir_entries->name[i], dir_entries->name[j]) > 0)
|
||||
{
|
||||
strcpy(temp, &dir_entries[i * 256]);
|
||||
strcpy(&dir_entries[i * 256], &dir_entries[j * 256]);
|
||||
strcpy(&dir_entries[j * 256], temp);
|
||||
char *tmp = dir_entries->name[i];
|
||||
dir_entries->name[i] = dir_entries->name[j];
|
||||
dir_entries->name[j] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(temp);
|
||||
|
||||
return dir_entries;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2018 CTCaer
|
||||
* Copyright (c) 2018-2024 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,4 +16,12 @@
|
|||
|
||||
#include <utils/types.h>
|
||||
|
||||
char *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles, bool parse_dirs);
|
||||
#define DIR_MAX_ENTRIES 64
|
||||
|
||||
typedef struct _dirlist_t
|
||||
{
|
||||
char *name[DIR_MAX_ENTRIES];
|
||||
char data[DIR_MAX_ENTRIES * 256];
|
||||
} dirlist_t;
|
||||
|
||||
dirlist_t *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles, bool parse_dirs);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2022 CTCaer
|
||||
* Copyright (c) 2018-2024 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,
|
||||
|
@ -41,7 +41,7 @@ ini_sec_t *_ini_create_section(link_t *dst, ini_sec_t *csec, char *name, u8 type
|
|||
|
||||
// Calculate total allocation size.
|
||||
u32 len = name ? strlen(name) + 1 : 0;
|
||||
char *buf = calloc(sizeof(ini_sec_t) + len, 1);
|
||||
char *buf = zalloc(sizeof(ini_sec_t) + len);
|
||||
|
||||
csec = (ini_sec_t *)buf;
|
||||
csec->name = strcpy_ns(buf + sizeof(ini_sec_t), name);
|
||||
|
@ -53,7 +53,7 @@ ini_sec_t *_ini_create_section(link_t *dst, ini_sec_t *csec, char *name, u8 type
|
|||
return csec;
|
||||
}
|
||||
|
||||
int ini_parse(link_t *dst, char *ini_path, bool is_dir)
|
||||
int ini_parse(link_t *dst, const char *ini_path, bool is_dir)
|
||||
{
|
||||
FIL fp;
|
||||
u32 lblen;
|
||||
|
@ -62,7 +62,7 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir)
|
|||
ini_sec_t *csec = NULL;
|
||||
|
||||
char *lbuf = NULL;
|
||||
char *filelist = NULL;
|
||||
dirlist_t *filelist = NULL;
|
||||
char *filename = (char *)malloc(256);
|
||||
|
||||
strcpy(filename, ini_path);
|
||||
|
@ -85,9 +85,9 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir)
|
|||
// Copy ini filename in path string.
|
||||
if (is_dir)
|
||||
{
|
||||
if (filelist[k * 256])
|
||||
if (filelist->name[k])
|
||||
{
|
||||
strcpy(filename + pathlen, &filelist[k * 256]);
|
||||
strcpy(filename + pathlen, filelist->name[k]);
|
||||
k++;
|
||||
}
|
||||
else
|
||||
|
@ -144,7 +144,7 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir)
|
|||
// Calculate total allocation size.
|
||||
u32 klen = strlen(&lbuf[0]) + 1;
|
||||
u32 vlen = strlen(&lbuf[i + 1]) + 1;
|
||||
char *buf = calloc(sizeof(ini_kv_t) + klen + vlen, 1);
|
||||
char *buf = zalloc(sizeof(ini_kv_t) + klen + vlen);
|
||||
|
||||
ini_kv_t *kv = (ini_kv_t *)buf;
|
||||
buf += sizeof(ini_kv_t);
|
||||
|
|
|
@ -43,7 +43,7 @@ typedef struct _ini_sec_t
|
|||
u32 color;
|
||||
} ini_sec_t;
|
||||
|
||||
int ini_parse(link_t *dst, char *ini_path, bool is_dir);
|
||||
int ini_parse(link_t *dst, const char *ini_path, bool is_dir);
|
||||
char *ini_check_special_section(ini_sec_t *cfg);
|
||||
void ini_free(link_t *src);
|
||||
|
||||
|
|
|
@ -28,10 +28,32 @@ static void _s_putc(char c)
|
|||
*sout_buf += 1;
|
||||
}
|
||||
|
||||
static void _s_puts(char *s)
|
||||
static void _s_putspace(int fcnt)
|
||||
{
|
||||
if (fcnt <= 0)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < fcnt; i++)
|
||||
_s_putc(' ');
|
||||
}
|
||||
|
||||
static void _s_puts(char *s, char fill, int fcnt)
|
||||
{
|
||||
if (fcnt)
|
||||
{
|
||||
fcnt = fcnt - strlen(s);
|
||||
|
||||
// Left padding. Check if padding is not space based (dot counts as such).
|
||||
if (fill != '.')
|
||||
_s_putspace(fcnt);
|
||||
}
|
||||
|
||||
for (; *s; s++)
|
||||
_s_putc(*s);
|
||||
|
||||
// Right padding. Check if padding is space based (dot counts as such).
|
||||
if (fill == '.')
|
||||
_s_putspace(fcnt);
|
||||
}
|
||||
|
||||
static void _s_putn(u32 v, int base, char fill, int fcnt)
|
||||
|
@ -75,9 +97,28 @@ static void _s_putn(u32 v, int base, char fill, int fcnt)
|
|||
}
|
||||
}
|
||||
|
||||
_s_puts(p);
|
||||
_s_puts(p, 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Padding:
|
||||
* Numbers:
|
||||
* %3d: Fill: ' ', Count: 3.
|
||||
* % 3d: Fill: ' ', Count: 3.
|
||||
* %.3d: Fill: '.', Count: 3.
|
||||
* %23d: Fill: '2', Count: 3.
|
||||
* % 23d: Fill: ' ', Count: 23.
|
||||
* %223d: Fill: '2', Count: 23.
|
||||
*
|
||||
* Strings, Fill: ' ':
|
||||
* %3s: Count: 5, Left.
|
||||
* %23s: Count: 5, Left.
|
||||
* %223s: Count: 25, Left.
|
||||
* %.3s: Count: 5, Right.
|
||||
* %.23s: Count: 25, Right.
|
||||
* %.223s: Count: 225, Right.
|
||||
*/
|
||||
|
||||
void s_printf(char *out_buf, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
@ -94,8 +135,8 @@ void s_printf(char *out_buf, const char *fmt, ...)
|
|||
fill = 0;
|
||||
fcnt = 0;
|
||||
|
||||
// Check for padding. Number or space based.
|
||||
if ((*fmt >= '0' && *fmt <= '9') || *fmt == ' ')
|
||||
// Check for padding. Number or space based (dot count as space for string).
|
||||
if ((*fmt >= '0' && *fmt <= '9') || *fmt == ' ' || *fmt == '.')
|
||||
{
|
||||
fcnt = *fmt; // Padding size or padding type.
|
||||
fmt++;
|
||||
|
@ -132,7 +173,7 @@ parse_padding_dec:
|
|||
break;
|
||||
|
||||
case 's':
|
||||
_s_puts(va_arg(ap, char *));
|
||||
_s_puts(va_arg(ap, char *), fill, fcnt);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
|
@ -221,7 +262,7 @@ parse_padding_dec:
|
|||
break;
|
||||
|
||||
case 's':
|
||||
_s_puts(va_arg(ap, char *));
|
||||
_s_puts(va_arg(ap, char *), fill, fcnt);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
|
|
|
@ -21,7 +21,25 @@
|
|||
|
||||
#include <utils/types.h>
|
||||
|
||||
/*
|
||||
* Padding:
|
||||
* Numbers:
|
||||
* %3d: Fill: ' ', Count: 3.
|
||||
* % 3d: Fill: ' ', Count: 3.
|
||||
* %23d: Fill: '2', Count: 3.
|
||||
* % 23d: Fill: ' ', Count: 23.
|
||||
* %223d: Fill: '2', Count: 23.
|
||||
*
|
||||
* Strings, Fill: ' ':
|
||||
* %3s: Count: 5, Left.
|
||||
* %23s: Count: 5, Left.
|
||||
* %223s: Count: 25, Left.
|
||||
* %.3s: Count: 5, Right.
|
||||
* %.23s: Count: 25, Right.
|
||||
* %.223s: Count: 225, Right.
|
||||
*/
|
||||
|
||||
void s_printf(char *out_buf, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
|
||||
void s_vprintf(char *out_buf, const char *fmt, va_list ap);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -98,10 +98,12 @@ typedef unsigned long uptr;
|
|||
#define OFFSET_OF(t, m) ((uptr)&((t *)NULL)->m)
|
||||
#define CONTAINER_OF(mp, t, mn) ((t *)((uptr)mp - OFFSET_OF(t, mn)))
|
||||
|
||||
#define byte_swap_16(num) ((((num) >> 8) & 0xff) | (((num) << 8) & 0xff00))
|
||||
#define byte_swap_32(num) ((((num) >> 24) & 0xff) | (((num) << 8) & 0xff0000) | \
|
||||
(((num) >> 8 ) & 0xff00) | (((num) << 24) & 0xff000000))
|
||||
#define byte_swap_16(num) ((((num) >> 8) & 0xFF) | (((num) & 0xFF) << 8))
|
||||
#define byte_swap_32(num) ((((num) >> 24) & 0xFF) | (((num) & 0xFF00) << 8 ) | \
|
||||
(((num) >> 8 ) & 0xFF00) | (((num) & 0xFF) << 24))
|
||||
|
||||
#define likely(x) (__builtin_expect((x) != 0, 1))
|
||||
#define unlikely(x) (__builtin_expect((x) != 0, 0))
|
||||
|
||||
/* Bootloader/Nyx */
|
||||
#define BOOT_CFG_AUTOBOOT_EN BIT(0)
|
||||
|
|
|
@ -29,8 +29,6 @@
|
|||
#include <storage/sd.h>
|
||||
#include <utils/util.h>
|
||||
|
||||
#define USE_RTC_TIMER
|
||||
|
||||
u8 bit_count(u32 val)
|
||||
{
|
||||
u8 cnt = 0;
|
||||
|
@ -197,10 +195,11 @@ int atoi(const char *nptr)
|
|||
return (int)strtol(nptr, (char **)NULL, 10);
|
||||
}
|
||||
|
||||
void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops)
|
||||
void reg_write_array(u32 *base, const reg_cfg_t *cfg, u32 num_cfg)
|
||||
{
|
||||
for (u32 i = 0; i < num_ops; i++)
|
||||
base[ops[i].off] = ops[i].val;
|
||||
// Expected register offset is a u32 array index.
|
||||
for (u32 i = 0; i < num_cfg; i++)
|
||||
base[cfg[i].idx] = cfg[i].val;
|
||||
}
|
||||
|
||||
u32 crc32_calc(u32 crc, const u8 *buf, u32 len)
|
||||
|
@ -211,7 +210,7 @@ u32 crc32_calc(u32 crc, const u8 *buf, u32 len)
|
|||
// Calculate CRC table.
|
||||
if (!table)
|
||||
{
|
||||
table = calloc(256, sizeof(u32));
|
||||
table = zalloc(256 * sizeof(u32));
|
||||
for (u32 i = 0; i < 256; i++)
|
||||
{
|
||||
u32 rem = i;
|
||||
|
@ -262,7 +261,7 @@ void power_set_state(power_state_t state)
|
|||
sd_end();
|
||||
|
||||
// De-initialize and power down various hardware.
|
||||
hw_reinit_workaround(false, 0);
|
||||
hw_deinit(false, 0);
|
||||
|
||||
// Set power state.
|
||||
switch (state)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2022 CTCaer
|
||||
* Copyright (c) 2018-2024 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,8 +21,6 @@
|
|||
#include <utils/types.h>
|
||||
#include <mem/minerva.h>
|
||||
|
||||
#define CFG_SIZE(array) (sizeof(array) / sizeof(cfg_op_t))
|
||||
|
||||
#define NYX_NEW_INFO 0x3058594E
|
||||
|
||||
typedef enum
|
||||
|
@ -53,11 +51,11 @@ typedef enum
|
|||
ERR_EXCEPTION = BIT(31),
|
||||
} hekate_errors_t;
|
||||
|
||||
typedef struct _cfg_op_t
|
||||
typedef struct _reg_cfg_t
|
||||
{
|
||||
u32 off;
|
||||
u32 idx;
|
||||
u32 val;
|
||||
} cfg_op_t;
|
||||
} reg_cfg_t;
|
||||
|
||||
typedef struct _nyx_info_t
|
||||
{
|
||||
|
@ -88,7 +86,7 @@ u64 sqrt64(u64 num);
|
|||
long strtol(const char *nptr, char **endptr, register int base);
|
||||
int atoi(const char *nptr);
|
||||
|
||||
void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops);
|
||||
void reg_write_array(u32 *base, const reg_cfg_t *cfg, u32 num_cfg);
|
||||
u32 crc32_calc(u32 crc, const u8 *buf, u32 len);
|
||||
|
||||
void panic(u32 val);
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include <libs/fatfs/ff.h>
|
||||
|
||||
extern hekate_config h_cfg;
|
||||
extern void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage);
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("Os")
|
||||
|
@ -145,7 +144,7 @@ void print_mmc_info()
|
|||
" Current Rate: %d MB/s\n"
|
||||
" Type Support: ",
|
||||
emmc_storage.csd.mmca_vsn, emmc_storage.ext_csd.rev, emmc_storage.ext_csd.dev_version, emmc_storage.csd.cmdclass,
|
||||
emmc_storage.csd.capacity == (4096 * 512) ? "High" : "Low", speed & 0xFFFF, (speed >> 16) & 0xFFFF,
|
||||
emmc_storage.csd.capacity == (4096 * EMMC_BLOCKSIZE) ? "High" : "Low", speed & 0xFFFF, (speed >> 16) & 0xFFFF,
|
||||
emmc_storage.csd.busspeed);
|
||||
gfx_con.fntsz = 8;
|
||||
gfx_printf("%s", card_type_support);
|
||||
|
@ -156,13 +155,13 @@ void print_mmc_info()
|
|||
u32 rpmb_size = emmc_storage.ext_csd.rpmb_mult << 17;
|
||||
gfx_printf("%keMMC Partitions:%k\n", TXT_CLR_CYAN_L, TXT_CLR_DEFAULT);
|
||||
gfx_printf(" 1: %kBOOT0 %k\n Size: %5d KiB (LBA Sectors: 0x%07X)\n", TXT_CLR_GREENISH, TXT_CLR_DEFAULT,
|
||||
boot_size / 1024, boot_size / 512);
|
||||
boot_size / 1024, boot_size / EMMC_BLOCKSIZE);
|
||||
gfx_put_small_sep();
|
||||
gfx_printf(" 2: %kBOOT1 %k\n Size: %5d KiB (LBA Sectors: 0x%07X)\n", TXT_CLR_GREENISH, TXT_CLR_DEFAULT,
|
||||
boot_size / 1024, boot_size / 512);
|
||||
boot_size / 1024, boot_size / EMMC_BLOCKSIZE);
|
||||
gfx_put_small_sep();
|
||||
gfx_printf(" 3: %kRPMB %k\n Size: %5d KiB (LBA Sectors: 0x%07X)\n", TXT_CLR_GREENISH, TXT_CLR_DEFAULT,
|
||||
rpmb_size / 1024, rpmb_size / 512);
|
||||
rpmb_size / 1024, rpmb_size / EMMC_BLOCKSIZE);
|
||||
gfx_put_small_sep();
|
||||
gfx_printf(" 0: %kGPP (USER) %k\n Size: %5d MiB (LBA Sectors: 0x%07X)\n\n", TXT_CLR_GREENISH, TXT_CLR_DEFAULT,
|
||||
emmc_storage.sec_cnt >> SECTORS_TO_MIB_COEFF, emmc_storage.sec_cnt);
|
||||
|
@ -314,23 +313,20 @@ void print_battery_charger_info()
|
|||
|
||||
gfx_printf("%k\n\nBattery Charger Info:\n%k", TXT_CLR_CYAN_L, TXT_CLR_DEFAULT);
|
||||
|
||||
bq24193_get_property(BQ24193_InputVoltageLimit, &value);
|
||||
gfx_printf("Input voltage limit: %4d mV\n", value);
|
||||
|
||||
bq24193_get_property(BQ24193_InputCurrentLimit, &value);
|
||||
gfx_printf("Input current limit: %4d mA\n", value);
|
||||
gfx_printf("Input current limit: %4d mA\n", value);
|
||||
|
||||
bq24193_get_property(BQ24193_SystemMinimumVoltage, &value);
|
||||
gfx_printf("Min voltage limit: %4d mV\n", value);
|
||||
gfx_printf("System voltage limit: %4d mV\n", value);
|
||||
|
||||
bq24193_get_property(BQ24193_FastChargeCurrentLimit, &value);
|
||||
gfx_printf("Fast charge current limit: %4d mA\n", value);
|
||||
gfx_printf("Charge current limit: %4d mA\n", value);
|
||||
|
||||
bq24193_get_property(BQ24193_ChargeVoltageLimit, &value);
|
||||
gfx_printf("Charge voltage limit: %4d mV\n", value);
|
||||
gfx_printf("Charge voltage limit: %4d mV\n", value);
|
||||
|
||||
bq24193_get_property(BQ24193_ChargeStatus, &value);
|
||||
gfx_printf("Charge status: ");
|
||||
gfx_printf("Charge status: ");
|
||||
switch (value)
|
||||
{
|
||||
case 0:
|
||||
|
@ -350,7 +346,7 @@ void print_battery_charger_info()
|
|||
break;
|
||||
}
|
||||
bq24193_get_property(BQ24193_TempStatus, &value);
|
||||
gfx_printf("Temperature status: ");
|
||||
gfx_printf("Temperature status: ");
|
||||
switch (value)
|
||||
{
|
||||
case 0:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2022 CTCaer
|
||||
* Copyright (c) 2018-2024 CTCaer
|
||||
* Copyright (c) 2018 Reisyukaku
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
@ -32,22 +32,14 @@ extern hekate_config h_cfg;
|
|||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("Os")
|
||||
|
||||
void _toggle_autorcm(bool enable)
|
||||
static void _toggle_autorcm(bool enable)
|
||||
{
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
if (!emmc_initialize(false))
|
||||
{
|
||||
EPRINTF("Failed to init eMMC.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
u8 *tempbuf = (u8 *)malloc(0x200);
|
||||
emmc_set_partition(EMMC_BOOT0);
|
||||
|
||||
int i, sect = 0;
|
||||
u8 corr_mod0, mod1;
|
||||
u8 *tempbuf = (u8 *)malloc(0x200);
|
||||
|
||||
// Get the correct RSA modulus byte masks.
|
||||
nx_emmc_get_autorcm_masks(&corr_mod0, &mod1);
|
||||
|
@ -70,7 +62,6 @@ void _toggle_autorcm(bool enable)
|
|||
}
|
||||
|
||||
free(tempbuf);
|
||||
emmc_end();
|
||||
|
||||
if (enable)
|
||||
gfx_printf("%kAutoRCM mode enabled!%k", TXT_CLR_ORANGE, TXT_CLR_DEFAULT);
|
||||
|
@ -78,12 +69,34 @@ void _toggle_autorcm(bool enable)
|
|||
gfx_printf("%kAutoRCM mode disabled!%k", TXT_CLR_GREENISH, TXT_CLR_DEFAULT);
|
||||
gfx_printf("\n\nPress any key...\n");
|
||||
|
||||
out:
|
||||
btn_wait();
|
||||
}
|
||||
|
||||
void _enable_autorcm() { _toggle_autorcm(true); }
|
||||
void _disable_autorcm() { _toggle_autorcm(false); }
|
||||
static void _enable_autorcm() { _toggle_autorcm(true); }
|
||||
static void _disable_autorcm() { _toggle_autorcm(false); }
|
||||
|
||||
bool tools_autorcm_enabled()
|
||||
{
|
||||
u8 mod0, mod1;
|
||||
u8 *tempbuf = (u8 *)malloc(0x200);
|
||||
|
||||
// Get the correct RSA modulus byte masks.
|
||||
nx_emmc_get_autorcm_masks(&mod0, &mod1);
|
||||
|
||||
// Get 1st RSA modulus.
|
||||
emmc_set_partition(EMMC_BOOT0);
|
||||
sdmmc_storage_read(&emmc_storage, 0x200 / EMMC_BLOCKSIZE, 1, tempbuf);
|
||||
|
||||
// Check if 2nd byte of modulus is correct.
|
||||
bool enabled = false;
|
||||
if (tempbuf[0x11] == mod1)
|
||||
if (tempbuf[0x10] != mod0)
|
||||
enabled = true;
|
||||
|
||||
free(tempbuf);
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
void menu_autorcm()
|
||||
{
|
||||
|
@ -98,9 +111,6 @@ void menu_autorcm()
|
|||
return;
|
||||
}
|
||||
|
||||
// Do a simple check on the main BCT.
|
||||
bool disabled = true;
|
||||
|
||||
if (!emmc_initialize(false))
|
||||
{
|
||||
EPRINTF("Failed to init eMMC.");
|
||||
|
@ -109,21 +119,8 @@ 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);
|
||||
emmc_set_partition(EMMC_BOOT0);
|
||||
sdmmc_storage_read(&emmc_storage, 0x200 / EMMC_BLOCKSIZE, 1, tempbuf);
|
||||
|
||||
// Check if 2nd byte of modulus is correct.
|
||||
if (tempbuf[0x11] == mod1)
|
||||
if (tempbuf[0x10] != mod0)
|
||||
disabled = false;
|
||||
|
||||
free(tempbuf);
|
||||
emmc_end();
|
||||
// Do a simple check on the main BCT.
|
||||
bool enabled = tools_autorcm_enabled();
|
||||
|
||||
// Create AutoRCM menu.
|
||||
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * 6);
|
||||
|
@ -135,7 +132,7 @@ void menu_autorcm()
|
|||
|
||||
ments[2].type = MENT_CAPTION;
|
||||
ments[3].type = MENT_CHGLINE;
|
||||
if (disabled)
|
||||
if (!enabled)
|
||||
{
|
||||
ments[2].caption = "Status: Disabled!";
|
||||
ments[2].color = TXT_CLR_GREENISH;
|
||||
|
@ -156,6 +153,10 @@ void menu_autorcm()
|
|||
menu_t menu = {ments, "This corrupts BOOT0!", 0, 0};
|
||||
|
||||
tui_do_menu(&menu);
|
||||
|
||||
emmc_end();
|
||||
|
||||
free(ments);
|
||||
}
|
||||
|
||||
#pragma GCC pop_options
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2022 CTCaer
|
||||
* Copyright (c) 2018-2024 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,5 +19,6 @@
|
|||
#define _FE_TOOLS_H_
|
||||
|
||||
void menu_autorcm();
|
||||
bool tools_autorcm_enabled();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Atmosphère Fusée Secondary Storage (Package3) parser.
|
||||
*
|
||||
* Copyright (c) 2019-2023 CTCaer
|
||||
* Copyright (c) 2019-2024 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,
|
||||
|
@ -31,7 +31,7 @@
|
|||
|
||||
extern hekate_config h_cfg;
|
||||
|
||||
extern bool is_ipl_updated(void *buf, char *path, bool force);
|
||||
extern bool is_ipl_updated(void *buf, const char *path, bool force);
|
||||
|
||||
// FSS0 Magic and Meta header offset.
|
||||
#define FSS0_MAGIC 0x30535346
|
||||
|
@ -82,34 +82,13 @@ typedef struct _fss_content_t
|
|||
char name[0x10];
|
||||
} fss_content_t;
|
||||
|
||||
static void _set_fss_path_and_update_r2p(launch_ctxt_t *ctxt, const char *path)
|
||||
static void _fss_update_r2p()
|
||||
{
|
||||
char *r2p_path = malloc(256);
|
||||
u32 path_len = strlen(path);
|
||||
u8 *r2p_payload = sd_file_read("atmosphere/reboot_payload.bin", NULL);
|
||||
|
||||
strcpy(r2p_path, path);
|
||||
is_ipl_updated(r2p_payload, "atmosphere/reboot_payload.bin", h_cfg.updater2p ? true : false);
|
||||
|
||||
while (path_len)
|
||||
{
|
||||
if ((r2p_path[path_len - 1] == '/') || (r2p_path[path_len - 1] == '\\'))
|
||||
{
|
||||
r2p_path[path_len] = 0;
|
||||
strcat(r2p_path, "reboot_payload.bin");
|
||||
u8 *r2p_payload = sd_file_read(r2p_path, NULL);
|
||||
|
||||
is_ipl_updated(r2p_payload, r2p_path, h_cfg.updater2p ? true : false);
|
||||
|
||||
free(r2p_payload);
|
||||
|
||||
// Save FSS0 parent path.
|
||||
r2p_path[path_len] = 0;
|
||||
ctxt->fss0_main_path = r2p_path;
|
||||
return;
|
||||
}
|
||||
path_len--;
|
||||
}
|
||||
|
||||
free(r2p_path);
|
||||
free(r2p_payload);
|
||||
}
|
||||
|
||||
int parse_fss(launch_ctxt_t *ctxt, const char *path)
|
||||
|
@ -230,8 +209,10 @@ int parse_fss(launch_ctxt_t *ctxt, const char *path)
|
|||
gfx_printf("Done!\n");
|
||||
f_close(&fp);
|
||||
|
||||
// Set FSS0 path and update r2p if needed.
|
||||
_set_fss_path_and_update_r2p(ctxt, path);
|
||||
ctxt->fss0 = fss;
|
||||
|
||||
// Update r2p if needed.
|
||||
_fss_update_r2p();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 st4rk
|
||||
* Copyright (c) 2018 Ced2911
|
||||
* Copyright (c) 2018-2023 CTCaer
|
||||
* Copyright (c) 2018-2024 CTCaer
|
||||
* Copyright (c) 2018 balika011
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
@ -25,6 +25,7 @@
|
|||
#include "hos.h"
|
||||
#include "hos_config.h"
|
||||
#include "secmon_exo.h"
|
||||
#include "../frontend/fe_tools.h"
|
||||
#include "../config.h"
|
||||
#include "../storage/emummc.h"
|
||||
|
||||
|
@ -121,6 +122,8 @@ static const u8 master_kekseed_t210_tsec_v4[HOS_KB_VERSION_MAX - HOS_KB_VERSION_
|
|||
{ 0x6E, 0x77, 0x86, 0xAC, 0x83, 0x0A, 0x8D, 0x3E, 0x7D, 0xB7, 0x66, 0xA0, 0x22, 0xB7, 0x6E, 0x67 }, // 15.0.0.
|
||||
{ 0x99, 0x22, 0x09, 0x57, 0xA7, 0xF9, 0x5E, 0x94, 0xFE, 0x78, 0x7F, 0x41, 0xD6, 0xE7, 0x56, 0xE6 }, // 16.0.0.
|
||||
{ 0x71, 0xB9, 0xA6, 0xC0, 0xFF, 0x97, 0x6B, 0x0C, 0xB4, 0x40, 0xB9, 0xD5, 0x81, 0x5D, 0x81, 0x90 }, // 17.0.0.
|
||||
{ 0x00, 0x04, 0x5D, 0xF0, 0x4D, 0xCD, 0x14, 0xA3, 0x1C, 0xBF, 0xDE, 0x48, 0x55, 0xBA, 0x35, 0xC1 }, // 18.0.0.
|
||||
{ 0xD7, 0x63, 0x74, 0x46, 0x4E, 0xBA, 0x78, 0x0A, 0x7C, 0x9D, 0xB3, 0xE8, 0x7A, 0x3D, 0x71, 0xE3 }, // 19.0.0.
|
||||
};
|
||||
|
||||
//!TODO: Update on mkey changes.
|
||||
|
@ -137,6 +140,8 @@ static const u8 master_kekseed_t210b01[HOS_KB_VERSION_MAX - HOS_KB_VERSION_600 +
|
|||
{ 0xEC, 0x61, 0xBC, 0x82, 0x1E, 0x0F, 0x5A, 0xC3, 0x2B, 0x64, 0x3F, 0x9D, 0xD6, 0x19, 0x22, 0x2D }, // 15.0.0.
|
||||
{ 0xA5, 0xEC, 0x16, 0x39, 0x1A, 0x30, 0x16, 0x08, 0x2E, 0xCF, 0x09, 0x6F, 0x5E, 0x7C, 0xEE, 0xA9 }, // 16.0.0.
|
||||
{ 0x8D, 0xEE, 0x9E, 0x11, 0x36, 0x3A, 0x9B, 0x0A, 0x6A, 0xC7, 0xBB, 0xE9, 0xD1, 0x03, 0xF7, 0x80 }, // 17.0.0.
|
||||
{ 0x4F, 0x41, 0x3C, 0x3B, 0xFB, 0x6A, 0x01, 0x2A, 0x68, 0x9F, 0x83, 0xE9, 0x53, 0xBD, 0x16, 0xD2 }, // 18.0.0.
|
||||
{ 0x31, 0xBE, 0x25, 0xFB, 0xDB, 0xB4, 0xEE, 0x49, 0x5C, 0x77, 0x05, 0xC2, 0x36, 0x9F, 0x34, 0x80 }, // 19.0.0.
|
||||
};
|
||||
|
||||
static const u8 console_keyseed[SE_KEY_128_SIZE] =
|
||||
|
@ -218,7 +223,7 @@ static void _hos_eks_get()
|
|||
if (!h_cfg.eks)
|
||||
{
|
||||
// Read EKS blob.
|
||||
u8 *mbr = calloc(512 , 1);
|
||||
u8 *mbr = zalloc(SD_BLOCKSIZE);
|
||||
if (!hos_eks_rw_try(mbr, false))
|
||||
goto out;
|
||||
|
||||
|
@ -248,7 +253,7 @@ static void _hos_eks_save()
|
|||
bool new_eks = false;
|
||||
if (!h_cfg.eks)
|
||||
{
|
||||
h_cfg.eks = calloc(512 , 1);
|
||||
h_cfg.eks = zalloc(SD_BLOCKSIZE);
|
||||
new_eks = true;
|
||||
}
|
||||
|
||||
|
@ -256,7 +261,7 @@ static void _hos_eks_save()
|
|||
if (h_cfg.eks->enabled != HOS_EKS_TSEC_VER)
|
||||
{
|
||||
// Read EKS blob.
|
||||
u8 *mbr = calloc(512 , 1);
|
||||
u8 *mbr = zalloc(SD_BLOCKSIZE);
|
||||
if (!hos_eks_rw_try(mbr, false))
|
||||
{
|
||||
if (new_eks)
|
||||
|
@ -269,7 +274,7 @@ static void _hos_eks_save()
|
|||
}
|
||||
|
||||
// Get keys.
|
||||
u8 *keys = (u8 *)calloc(SZ_4K, 2);
|
||||
u8 *keys = (u8 *)zalloc(SZ_8K);
|
||||
se_get_aes_keys(keys + SZ_4K, keys, SE_KEY_128_SIZE);
|
||||
|
||||
// Set magic and personalized info.
|
||||
|
@ -283,7 +288,7 @@ static void _hos_eks_save()
|
|||
memcpy(h_cfg.eks->troot_dev, keys + 11 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
|
||||
|
||||
// Encrypt EKS blob.
|
||||
u8 *eks = calloc(512 , 1);
|
||||
u8 *eks = zalloc(SD_BLOCKSIZE);
|
||||
memcpy(eks, h_cfg.eks, sizeof(hos_eks_mbr_t));
|
||||
se_aes_crypt_ecb(14, ENCRYPT, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
|
||||
|
||||
|
@ -310,7 +315,7 @@ void hos_eks_clear(u32 kb)
|
|||
if (h_cfg.eks->enabled)
|
||||
{
|
||||
// Read EKS blob.
|
||||
u8 *mbr = calloc(512 , 1);
|
||||
u8 *mbr = zalloc(SD_BLOCKSIZE);
|
||||
if (!hos_eks_rw_try(mbr, false))
|
||||
goto out;
|
||||
|
||||
|
@ -318,7 +323,7 @@ void hos_eks_clear(u32 kb)
|
|||
h_cfg.eks->enabled = 0;
|
||||
|
||||
// Encrypt EKS blob.
|
||||
u8 *eks = calloc(512 , 1);
|
||||
u8 *eks = zalloc(SD_BLOCKSIZE);
|
||||
memcpy(eks, h_cfg.eks, sizeof(hos_eks_mbr_t));
|
||||
se_aes_crypt_ecb(14, ENCRYPT, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
|
||||
|
||||
|
@ -378,7 +383,7 @@ int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock, bool i
|
|||
_hos_eks_get();
|
||||
|
||||
// Use tsec keygen for old firmware or if EKS keys does not exist for newer.
|
||||
if (kb <= HOS_KB_VERSION_620 || !h_cfg.eks || (h_cfg.eks && h_cfg.eks->enabled != HOS_EKS_TSEC_VER))
|
||||
if (kb <= HOS_KB_VERSION_620 || !h_cfg.eks || (h_cfg.eks->enabled != HOS_EKS_TSEC_VER))
|
||||
use_tsec = true;
|
||||
|
||||
if (kb <= HOS_KB_VERSION_600)
|
||||
|
@ -392,7 +397,7 @@ int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock, bool i
|
|||
tsec_ctxt->type = TSEC_FW_TYPE_EMU;
|
||||
|
||||
// Prepare smmu tsec page for 6.2.0.
|
||||
u8 *tsec_paged = (u8 *)page_alloc(3);
|
||||
u8 *tsec_paged = (u8 *)smmu_page_zalloc(3);
|
||||
memcpy(tsec_paged, (void *)tsec_ctxt->fw, tsec_ctxt->size);
|
||||
tsec_ctxt->fw = tsec_paged;
|
||||
}
|
||||
|
@ -646,7 +651,7 @@ try_load:
|
|||
// Read the correct keyblob for older HOS versions.
|
||||
if (ctxt->pkg1_id->kb <= HOS_KB_VERSION_600)
|
||||
{
|
||||
ctxt->keyblob = (u8 *)calloc(EMMC_BLOCKSIZE, 1);
|
||||
ctxt->keyblob = (u8 *)zalloc(EMMC_BLOCKSIZE);
|
||||
emummc_storage_read(PKG1_HOS_KEYBLOBS_OFFSET / EMMC_BLOCKSIZE + ctxt->pkg1_id->kb, 1, ctxt->keyblob);
|
||||
}
|
||||
|
||||
|
@ -669,7 +674,7 @@ DPRINTF("Parsed GPT\n");
|
|||
goto out;
|
||||
|
||||
// Read in package2 header and get package2 real size.
|
||||
const u32 BCT_SIZE = SZ_16K;
|
||||
static const u32 BCT_SIZE = SZ_16K;
|
||||
bctBuf = (u8 *)malloc(BCT_SIZE);
|
||||
emmc_part_read(pkg2_part, BCT_SIZE / EMMC_BLOCKSIZE, 1, bctBuf);
|
||||
u32 *hdr = (u32 *)(bctBuf + 0x100);
|
||||
|
@ -694,12 +699,12 @@ out:
|
|||
|
||||
static void _free_launch_components(launch_ctxt_t *ctxt)
|
||||
{
|
||||
// Free the malloc'ed guaranteed addresses.
|
||||
free(ctxt->fss0);
|
||||
free(ctxt->keyblob);
|
||||
free(ctxt->pkg1);
|
||||
free(ctxt->pkg2);
|
||||
free(ctxt->warmboot);
|
||||
free(ctxt->secmon);
|
||||
free(ctxt->kernel);
|
||||
free(ctxt->kip1_patches);
|
||||
}
|
||||
|
||||
|
@ -711,7 +716,7 @@ static bool _get_fs_exfat_compatible(link_t *info, u32 *hos_revision)
|
|||
|
||||
LIST_FOREACH_ENTRY(pkg2_kip1_info_t, ki, info, link)
|
||||
{
|
||||
if (strncmp((const char*)ki->kip1->name, "FS", sizeof(ki->kip1->name)))
|
||||
if (strcmp((char *)ki->kip1->name, "FS"))
|
||||
continue;
|
||||
|
||||
if (!se_calc_sha256_oneshot(sha_buf, ki->kip1, ki->size))
|
||||
|
@ -756,6 +761,7 @@ int hos_launch(ini_sec_t *cfg)
|
|||
volatile secmon_mailbox_t *secmon_mailbox;
|
||||
|
||||
minerva_change_freq(FREQ_1600);
|
||||
sdram_src_pllc(true);
|
||||
list_init(&ctxt.kip1_list);
|
||||
|
||||
ctxt.cfg = cfg;
|
||||
|
@ -785,12 +791,6 @@ int hos_launch(ini_sec_t *cfg)
|
|||
goto error;
|
||||
}
|
||||
|
||||
// Read package1 and the correct keyblob.
|
||||
if (!_read_emmc_pkg1(&ctxt))
|
||||
goto error;
|
||||
|
||||
kb = ctxt.pkg1_id->kb;
|
||||
|
||||
// Try to parse config if present.
|
||||
if (ctxt.cfg && !parse_boot_config(&ctxt))
|
||||
{
|
||||
|
@ -798,6 +798,25 @@ int hos_launch(ini_sec_t *cfg)
|
|||
goto error;
|
||||
}
|
||||
|
||||
// Read package1 and the correct keyblob.
|
||||
if (!_read_emmc_pkg1(&ctxt))
|
||||
{
|
||||
// Check if stock is enabled and device can boot in OFW.
|
||||
if (ctxt.stock && (h_cfg.t210b01 || !tools_autorcm_enabled()))
|
||||
{
|
||||
sdram_src_pllc(false);
|
||||
emmc_end();
|
||||
|
||||
WPRINTF("\nRebooting to OFW in 5s...");
|
||||
msleep(5000);
|
||||
|
||||
power_set_state(REBOOT_BYPASS_FUSES);
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
|
||||
kb = ctxt.pkg1_id->kb;
|
||||
|
||||
bool emummc_enabled = emu_cfg.enabled && !h_cfg.emummc_force_disable;
|
||||
|
||||
// Enable emummc patching.
|
||||
|
@ -824,7 +843,7 @@ int hos_launch(ini_sec_t *cfg)
|
|||
if (!ctxt.stock)
|
||||
{
|
||||
u32 fuses = fuse_read_odm(7);
|
||||
if ((h_cfg.autonogc &&
|
||||
if ((h_cfg.autonogc && // Prevent GC fuse burning (sysMMC and emuMMC).
|
||||
(
|
||||
(!(fuses & ~0xF) && (ctxt.pkg1_id->fuses >= 5)) || // LAFW v2, 4.0.0+
|
||||
(!(fuses & ~0x3FF) && (ctxt.pkg1_id->fuses >= 11)) || // LAFW v3, 9.0.0+
|
||||
|
@ -833,12 +852,12 @@ int hos_launch(ini_sec_t *cfg)
|
|||
(!(fuses & ~0x3FFF) && (ctxt.pkg1_id->fuses >= 15)) // LAFW v5, 12.0.2+
|
||||
)
|
||||
)
|
||||
|| ((emummc_enabled) &&
|
||||
|| ((emummc_enabled) && // Force NOGC if already burnt (only emuMMC).
|
||||
(
|
||||
((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.
|
||||
// Detection broken! Use kip1patch=nogc // HOS 12.0.0+
|
||||
((fuses & 0x4000) && (ctxt.pkg1_id->fuses <= 14)) // HOS 12.0.2+ fuses burnt.
|
||||
((fuses & BIT(10)) && (ctxt.pkg1_id->fuses <= 10)) || // HOS 9.0.0+ fuses burnt.
|
||||
((fuses & BIT(13)) && (ctxt.pkg1_id->fuses <= 13)) || // HOS 11.0.0+ fuses burnt.
|
||||
// Detection broken! Use kip1patch=nogc // HOS 12.0.0+
|
||||
((fuses & BIT(14)) && (ctxt.pkg1_id->fuses <= 14)) // HOS 12.0.2+ fuses burnt.
|
||||
)
|
||||
))
|
||||
config_kip1patch(&ctxt, "nogc");
|
||||
|
@ -849,16 +868,18 @@ int hos_launch(ini_sec_t *cfg)
|
|||
// Check if secmon is exosphere.
|
||||
if (ctxt.secmon)
|
||||
is_exo = !memcmp((void *)((u8 *)ctxt.secmon + ctxt.secmon_size - 4), "LENY", 4);
|
||||
|
||||
// Get secmon and warmboot bases.
|
||||
const pkg1_id_t *pk1_latest = pkg1_get_latest();
|
||||
secmon_base = is_exo ? pk1_latest->secmon_base : ctxt.pkg1_id->secmon_base;
|
||||
secmon_base = is_exo ? pk1_latest->secmon_base : ctxt.pkg1_id->secmon_base;
|
||||
warmboot_base = is_exo ? pk1_latest->warmboot_base : ctxt.pkg1_id->warmboot_base;
|
||||
|
||||
// Generate keys.
|
||||
tsec_ctxt.fw = (u8 *)ctxt.pkg1 + ctxt.pkg1_id->tsec_off;
|
||||
tsec_ctxt.pkg1 = ctxt.pkg1;
|
||||
// Set package1 and tsec fw offsets.
|
||||
tsec_ctxt.fw = (u8 *)ctxt.pkg1 + ctxt.pkg1_id->tsec_off;
|
||||
tsec_ctxt.pkg1 = ctxt.pkg1;
|
||||
tsec_ctxt.pkg11_off = ctxt.pkg1_id->pkg11_off;
|
||||
tsec_ctxt.secmon_base = secmon_base;
|
||||
|
||||
// Generate keys.
|
||||
if (!hos_keygen(ctxt.keyblob, kb, &tsec_ctxt, ctxt.stock, is_exo))
|
||||
goto error;
|
||||
gfx_puts("Generated keys\n");
|
||||
|
@ -903,7 +924,7 @@ int hos_launch(ini_sec_t *cfg)
|
|||
}
|
||||
else
|
||||
{
|
||||
_hos_crit_error("No mandatory secmon or warmboot provided!");
|
||||
_hos_crit_error("No mandatory pkg1 files provided!");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
@ -999,7 +1020,7 @@ int hos_launch(ini_sec_t *cfg)
|
|||
}
|
||||
|
||||
// In case a kernel patch option is set; allows to disable SVC verification or/and enable debug mode.
|
||||
kernel_patch_t *kernel_patchset = ctxt.pkg2_kernel_id->kernel_patchset;
|
||||
const kernel_patch_t *kernel_patchset = ctxt.pkg2_kernel_id->kernel_patchset;
|
||||
if (kernel_patchset != NULL)
|
||||
{
|
||||
gfx_printf("%kPatching kernel%k\n", TXT_CLR_ORANGE, TXT_CLR_DEFAULT);
|
||||
|
@ -1036,20 +1057,17 @@ int hos_launch(ini_sec_t *cfg)
|
|||
{
|
||||
_hos_crit_error("SD Card is exFAT but installed HOS driver\nonly supports FAT32!");
|
||||
|
||||
_free_launch_components(&ctxt);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
// Patch kip1s in memory if needed.
|
||||
if (ctxt.kip1_patches)
|
||||
gfx_printf("%kPatching kips%k\n", TXT_CLR_ORANGE, TXT_CLR_DEFAULT);
|
||||
const char* unappliedPatch = pkg2_patch_kips(&kip1_info, ctxt.kip1_patches);
|
||||
if (unappliedPatch != NULL)
|
||||
const char *failed_patch = pkg2_patch_kips(&kip1_info, ctxt.kip1_patches);
|
||||
if (failed_patch != NULL)
|
||||
{
|
||||
EHPRINTFARGS("Failed to apply '%s'!", unappliedPatch);
|
||||
EHPRINTFARGS("Failed to apply '%s'!", failed_patch);
|
||||
|
||||
bool emmc_patch_failed = !strcmp(unappliedPatch, "emummc");
|
||||
bool emmc_patch_failed = !strcmp(failed_patch, "emummc");
|
||||
if (!emmc_patch_failed)
|
||||
{
|
||||
gfx_puts("\nPress POWER to continue.\nPress VOL to go to the menu.\n");
|
||||
|
@ -1057,10 +1075,7 @@ int hos_launch(ini_sec_t *cfg)
|
|||
}
|
||||
|
||||
if (emmc_patch_failed || !(btn_wait() & BTN_POWER))
|
||||
{
|
||||
_free_launch_components(&ctxt);
|
||||
goto error; // MUST stop here, because if user requests 'nogc' but it's not applied, their GC controller gets updated!
|
||||
}
|
||||
}
|
||||
|
||||
// Rebuild and encrypt package2.
|
||||
|
@ -1128,12 +1143,9 @@ int hos_launch(ini_sec_t *cfg)
|
|||
// Lock SE before starting 'SecureMonitor' if < 6.2.0, otherwise lock bootrom and ipatches.
|
||||
_se_lock(kb <= HOS_KB_VERSION_600 && !is_exo);
|
||||
|
||||
// Reset sysctr0 counters.
|
||||
if (kb >= HOS_KB_VERSION_620)
|
||||
{
|
||||
for (u32 i = 0; i < SYSCTR0_COUNTERS; i += sizeof(u32))
|
||||
SYSCTR0(SYSCTR0_COUNTERS_BASE + i) = 0;
|
||||
}
|
||||
// Reset sysctr0 counters. Mandatory for 6.2.0 and up.
|
||||
for (u32 i = 0; i < SYSCTR0_COUNTERS; i++)
|
||||
SYSCTR0(SYSCTR0_COUNTERS_BASE + i * sizeof(u32)) = 0;
|
||||
|
||||
// NX Bootloader locks LP0 Carveout secure scratch registers.
|
||||
//pmc_scratch_lock(PMC_SEC_LOCK_LP0_PARAMS);
|
||||
|
@ -1152,11 +1164,12 @@ int hos_launch(ini_sec_t *cfg)
|
|||
}
|
||||
|
||||
// Start directly from PKG2 ready signal and reset outgoing value.
|
||||
secmon_mailbox->in = pkg1_state_pkg2_ready;
|
||||
secmon_mailbox->in = pkg1_state_pkg2_ready;
|
||||
secmon_mailbox->out = SECMON_STATE_NOT_READY;
|
||||
|
||||
// Disable display. This must be executed before secmon to provide support for all fw versions.
|
||||
display_end();
|
||||
clock_disable_host1x();
|
||||
|
||||
// Override uCID if set.
|
||||
EMC(EMC_SCRATCH0) = ctxt.ucid;
|
||||
|
@ -1165,7 +1178,11 @@ int hos_launch(ini_sec_t *cfg)
|
|||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_USBD);
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = BIT(CLK_H_AHBDMA) | BIT(CLK_H_APBDMA) | BIT(CLK_H_USB2);
|
||||
|
||||
// Reset arbiter.
|
||||
hw_config_arbiter(true);
|
||||
|
||||
// Scale down RAM OC if enabled.
|
||||
sdram_src_pllc(false);
|
||||
minerva_prep_boot_freq();
|
||||
|
||||
// Flush cache and disable MMU.
|
||||
|
@ -1173,16 +1190,15 @@ int hos_launch(ini_sec_t *cfg)
|
|||
bpmp_clk_rate_set(BPMP_CLK_NORMAL);
|
||||
|
||||
// Launch secmon.
|
||||
if (smmu_is_used())
|
||||
smmu_exit();
|
||||
else
|
||||
ccplex_boot_cpu0(secmon_base);
|
||||
ccplex_boot_cpu0(secmon_base, true);
|
||||
|
||||
// Halt ourselves in wait-event state.
|
||||
while (true)
|
||||
bpmp_halt();
|
||||
|
||||
error:
|
||||
_free_launch_components(&ctxt);
|
||||
sdram_src_pllc(false);
|
||||
emmc_end();
|
||||
|
||||
EPRINTF("\nFailed to launch HOS!");
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2023 CTCaer
|
||||
* Copyright (c) 2018-2024 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,9 @@ enum {
|
|||
HOS_KB_VERSION_1500 = 14,
|
||||
HOS_KB_VERSION_1600 = 15,
|
||||
HOS_KB_VERSION_1700 = 16,
|
||||
HOS_KB_VERSION_MAX = HOS_KB_VERSION_1700
|
||||
HOS_KB_VERSION_1800 = 17,
|
||||
HOS_KB_VERSION_1900 = 18,
|
||||
HOS_KB_VERSION_MAX = HOS_KB_VERSION_1900
|
||||
};
|
||||
|
||||
#define HOS_TSEC_VERSION 4 //! TODO: Update on TSEC Root Key changes.
|
||||
|
@ -109,7 +111,7 @@ typedef struct _launch_ctxt_t
|
|||
bool stock;
|
||||
bool emummc_forced;
|
||||
|
||||
char *fss0_main_path;
|
||||
void *fss0;
|
||||
u32 fss0_hosver;
|
||||
bool atmosphere;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
* Copyright (c) 2018-2024 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
|
@ -65,7 +65,7 @@ static int _config_kip1(launch_ctxt_t *ctxt, const char *value)
|
|||
|
||||
u32 dirlen = 0;
|
||||
dir[strlen(dir) - 2] = 0;
|
||||
char *filelist = dirlist(dir, "*.kip*", false, false);
|
||||
dirlist_t *filelist = dirlist(dir, "*.kip*", false, false);
|
||||
|
||||
strcat(dir, "/");
|
||||
dirlen = strlen(dir);
|
||||
|
@ -75,10 +75,10 @@ static int _config_kip1(launch_ctxt_t *ctxt, const char *value)
|
|||
{
|
||||
while (true)
|
||||
{
|
||||
if (!filelist[i * 256])
|
||||
if (!filelist->name[i])
|
||||
break;
|
||||
|
||||
strcpy(dir + dirlen, &filelist[i * 256]);
|
||||
strcpy(dir + dirlen, filelist->name[i]);
|
||||
|
||||
merge_kip_t *mkip1 = (merge_kip_t *)malloc(sizeof(merge_kip_t));
|
||||
mkip1->kip1 = sd_file_read(dir, &size);
|
||||
|
@ -122,27 +122,28 @@ int config_kip1patch(launch_ctxt_t *ctxt, const char *value)
|
|||
if (value == NULL)
|
||||
return 0;
|
||||
|
||||
int valueLen = strlen(value);
|
||||
if (!valueLen)
|
||||
int len = strlen(value);
|
||||
if (!len)
|
||||
return 0;
|
||||
|
||||
if (ctxt->kip1_patches == NULL)
|
||||
{
|
||||
ctxt->kip1_patches = malloc(valueLen + 1);
|
||||
memcpy(ctxt->kip1_patches, value, valueLen);
|
||||
ctxt->kip1_patches[valueLen] = 0;
|
||||
ctxt->kip1_patches = malloc(len + 1);
|
||||
memcpy(ctxt->kip1_patches, value, len);
|
||||
ctxt->kip1_patches[len] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *oldAlloc = ctxt->kip1_patches;
|
||||
int oldSize = strlen(oldAlloc);
|
||||
ctxt->kip1_patches = malloc(oldSize + 1 + valueLen + 1);
|
||||
memcpy(ctxt->kip1_patches, oldAlloc, oldSize);
|
||||
free(oldAlloc);
|
||||
oldAlloc = NULL;
|
||||
ctxt->kip1_patches[oldSize++] = ',';
|
||||
memcpy(&ctxt->kip1_patches[oldSize], value, valueLen);
|
||||
ctxt->kip1_patches[oldSize + valueLen] = 0;
|
||||
char *old_addr = ctxt->kip1_patches;
|
||||
int old_len = strlen(old_addr);
|
||||
|
||||
ctxt->kip1_patches = malloc(old_len + 1 + len + 1);
|
||||
memcpy(ctxt->kip1_patches, old_addr, old_len);
|
||||
free(old_addr);
|
||||
|
||||
ctxt->kip1_patches[old_len++] = ',';
|
||||
memcpy(&ctxt->kip1_patches[old_len], value, len);
|
||||
ctxt->kip1_patches[old_len + len] = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -220,7 +221,7 @@ static int _config_exo_user_pmu_access(launch_ctxt_t *ctxt, const char *value)
|
|||
static int _config_exo_usb3_force(launch_ctxt_t *ctxt, const char *value)
|
||||
{
|
||||
// Override key found.
|
||||
ctxt->exo_ctx.usb3_force = calloc(sizeof(bool), 1);
|
||||
ctxt->exo_ctx.usb3_force = zalloc(sizeof(bool));
|
||||
|
||||
if (*value == '1')
|
||||
{
|
||||
|
@ -233,7 +234,7 @@ static int _config_exo_usb3_force(launch_ctxt_t *ctxt, const char *value)
|
|||
static int _config_exo_cal0_blanking(launch_ctxt_t *ctxt, const char *value)
|
||||
{
|
||||
// Override key found.
|
||||
ctxt->exo_ctx.cal0_blank = calloc(sizeof(bool), 1);
|
||||
ctxt->exo_ctx.cal0_blank = zalloc(sizeof(bool));
|
||||
|
||||
if (*value == '1')
|
||||
{
|
||||
|
@ -246,7 +247,7 @@ static int _config_exo_cal0_blanking(launch_ctxt_t *ctxt, const char *value)
|
|||
static int _config_exo_cal0_writes_enable(launch_ctxt_t *ctxt, const char *value)
|
||||
{
|
||||
// Override key found.
|
||||
ctxt->exo_ctx.cal0_allow_writes_sys = calloc(sizeof(bool), 1);
|
||||
ctxt->exo_ctx.cal0_allow_writes_sys = zalloc(sizeof(bool));
|
||||
|
||||
if (*value == '1')
|
||||
{
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 st4rk
|
||||
* Copyright (c) 2018-2023 CTCaer
|
||||
* Copyright (c) 2018-2024 CTCaer
|
||||
* Copyright (c) 2018 balika011
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
@ -169,7 +169,9 @@ static const pkg1_id_t _pkg1_ids[] = {
|
|||
{ "20220209", 13, 16, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 14.0.0 - 14.1.2.
|
||||
{ "20220801", 14, 17, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 15.0.0 - 15.0.1.
|
||||
{ "20230111", 15, 18, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 16.0.0 - 16.1.0.
|
||||
{ "20230906", 16, 19, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 17.0.0+
|
||||
{ "20230906", 16, 19, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 17.0.0 - 17.0.1.
|
||||
{ "20240207", 17, 19, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 18.0.0 - 18.1.0.
|
||||
{ "20240808", 18, 20, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 19.0.0+
|
||||
};
|
||||
|
||||
const pkg1_id_t *pkg1_get_latest()
|
||||
|
@ -266,7 +268,7 @@ const u8 *pkg1_unpack(void *wm_dst, u32 *wb_sz, void *sm_dst, void *ldr_dst, con
|
|||
|
||||
void pkg1_secmon_patch(void *hos_ctxt, u32 secmon_base, bool t210b01)
|
||||
{
|
||||
patch_t *secmon_patchset;
|
||||
const patch_t *secmon_patchset;
|
||||
launch_ctxt_t *ctxt = (launch_ctxt_t *)hos_ctxt;
|
||||
|
||||
// Patch Secmon to allow for an unsigned package2 and patched kernel.
|
||||
|
@ -319,7 +321,7 @@ void pkg1_secmon_patch(void *hos_ctxt, u32 secmon_base, bool t210b01)
|
|||
void pkg1_warmboot_patch(void *hos_ctxt)
|
||||
{
|
||||
launch_ctxt_t *ctxt = (launch_ctxt_t *)hos_ctxt;
|
||||
patch_t *warmboot_patchset;
|
||||
const patch_t *warmboot_patchset;
|
||||
|
||||
// Patch warmboot on T210 to allow downgrading.
|
||||
switch (ctxt->pkg1_id->kb)
|
||||
|
@ -436,7 +438,7 @@ int pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base, u32 fuses_fw, u8 kb)
|
|||
void pkg1_warmboot_rsa_mod(u32 warmboot_base)
|
||||
{
|
||||
// Set warmboot binary rsa modulus.
|
||||
u8 *rsa_mod = (u8 *)malloc(512);
|
||||
u8 *rsa_mod = (u8 *)malloc(EMMC_BLOCKSIZE);
|
||||
|
||||
emmc_set_partition(EMMC_BOOT0);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2022-2023 CTCaer
|
||||
* Copyright (c) 2022-2024 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,
|
||||
|
@ -41,7 +41,7 @@ typedef struct _patch_t
|
|||
} patch_t;
|
||||
|
||||
#define PATCHSET_DEF(name, ...) \
|
||||
patch_t name[] = { \
|
||||
const patch_t name[] = { \
|
||||
__VA_ARGS__, \
|
||||
{ 0xFFFFFFFF, 0xFFFFFFFF } \
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ typedef struct _pkg1_id_t
|
|||
u16 pkg11_off;
|
||||
u32 secmon_base;
|
||||
u32 warmboot_base;
|
||||
patch_t *secmon_patchset;
|
||||
const patch_t *secmon_patchset;
|
||||
} pkg1_id_t;
|
||||
|
||||
typedef struct _pk11_hdr_t
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2023 CTCaer
|
||||
* Copyright (c) 2018-2024 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,
|
||||
|
@ -57,7 +57,7 @@ enum kip_offset_section
|
|||
|
||||
#include "pkg2_patches.inl"
|
||||
|
||||
static kip1_id_t *_kip_id_sets = _kip_ids;
|
||||
static kip1_id_t *_kip_id_sets = (kip1_id_t *)_kip_ids;
|
||||
static u32 _kip_id_sets_cnt = ARRAY_SIZE(_kip_ids);
|
||||
|
||||
void pkg2_get_ids(kip1_id_t **ids, u32 *entries)
|
||||
|
@ -77,100 +77,100 @@ static void parse_external_kip_patches()
|
|||
if (ini_patch_parse(&ini_kip_sections, "bootloader/patches.ini"))
|
||||
{
|
||||
// Copy ids into a new patchset.
|
||||
_kip_id_sets = calloc(sizeof(kip1_id_t), 256); // Max 256 kip ids.
|
||||
_kip_id_sets = zalloc(sizeof(kip1_id_t) * 256); // Max 256 kip ids.
|
||||
memcpy(_kip_id_sets, _kip_ids, sizeof(_kip_ids));
|
||||
|
||||
// Parse patchsets and glue them together.
|
||||
LIST_FOREACH_ENTRY(ini_kip_sec_t, ini_psec, &ini_kip_sections, link)
|
||||
{
|
||||
kip1_id_t* curr_kip = NULL;
|
||||
kip1_id_t *kip = NULL;
|
||||
bool found = false;
|
||||
for (u32 curr_kip_idx = 0; curr_kip_idx < _kip_id_sets_cnt + 1; curr_kip_idx++)
|
||||
for (u32 kip_idx = 0; kip_idx < _kip_id_sets_cnt + 1; kip_idx++)
|
||||
{
|
||||
curr_kip = &_kip_id_sets[curr_kip_idx];
|
||||
kip = &_kip_id_sets[kip_idx];
|
||||
|
||||
// Check if reached the end of predefined list.
|
||||
if (!curr_kip->name)
|
||||
if (!kip->name)
|
||||
break;
|
||||
|
||||
// Check if name and hash match.
|
||||
if (!strcmp(curr_kip->name, ini_psec->name) && !memcmp(curr_kip->hash, ini_psec->hash, 8))
|
||||
if (!strcmp(kip->name, ini_psec->name) && !memcmp(kip->hash, ini_psec->hash, 8))
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!curr_kip)
|
||||
if (!kip)
|
||||
continue;
|
||||
|
||||
// If not found, create a new empty entry.
|
||||
if (!found)
|
||||
{
|
||||
curr_kip->name = ini_psec->name;
|
||||
memcpy(curr_kip->hash, ini_psec->hash, 8);
|
||||
curr_kip->patchset = calloc(sizeof(kip1_patchset_t), 1);
|
||||
kip->name = ini_psec->name;
|
||||
memcpy(kip->hash, ini_psec->hash, 8);
|
||||
kip->patchset = zalloc(sizeof(kip1_patchset_t));
|
||||
|
||||
_kip_id_sets_cnt++;
|
||||
}
|
||||
|
||||
kip1_patchset_t *patchsets = (kip1_patchset_t *)calloc(sizeof(kip1_patchset_t), 16); // Max 16 patchsets per kip.
|
||||
kip1_patchset_t *patchsets = (kip1_patchset_t *)zalloc(sizeof(kip1_patchset_t) * 16); // Max 16 patchsets per kip.
|
||||
|
||||
u32 curr_patchset_idx;
|
||||
for (curr_patchset_idx = 0; curr_kip->patchset[curr_patchset_idx].name != NULL; curr_patchset_idx++)
|
||||
u32 patchset_idx;
|
||||
for (patchset_idx = 0; kip->patchset[patchset_idx].name != NULL; patchset_idx++)
|
||||
{
|
||||
patchsets[curr_patchset_idx].name = curr_kip->patchset[curr_patchset_idx].name;
|
||||
patchsets[curr_patchset_idx].patches = curr_kip->patchset[curr_patchset_idx].patches;
|
||||
patchsets[patchset_idx].name = kip->patchset[patchset_idx].name;
|
||||
patchsets[patchset_idx].patches = kip->patchset[patchset_idx].patches;
|
||||
}
|
||||
|
||||
curr_kip->patchset = patchsets;
|
||||
kip->patchset = patchsets;
|
||||
bool first_ext_patch = true;
|
||||
u32 curr_patch_idx = 0;
|
||||
u32 patch_idx = 0;
|
||||
|
||||
// Parse patches and glue them together to a patchset.
|
||||
kip1_patch_t *patches = calloc(sizeof(kip1_patch_t), 32); // Max 32 patches per set.
|
||||
kip1_patch_t *patches = zalloc(sizeof(kip1_patch_t) * 32); // Max 32 patches per set.
|
||||
LIST_FOREACH_ENTRY(ini_patchset_t, pt, &ini_psec->pts, link)
|
||||
{
|
||||
if (first_ext_patch)
|
||||
{
|
||||
first_ext_patch = false;
|
||||
patchsets[curr_patchset_idx].name = pt->name;
|
||||
patchsets[curr_patchset_idx].patches = patches;
|
||||
patchsets[patchset_idx].name = pt->name;
|
||||
patchsets[patchset_idx].patches = patches;
|
||||
}
|
||||
else if (strcmp(pt->name, patchsets[curr_patchset_idx].name))
|
||||
else if (strcmp(pt->name, patchsets[patchset_idx].name))
|
||||
{
|
||||
// New patchset name found, create a new set.
|
||||
curr_patchset_idx++;
|
||||
curr_patch_idx = 0;
|
||||
patches = calloc(sizeof(kip1_patch_t), 32); // Max 32 patches per set.
|
||||
patchset_idx++;
|
||||
patch_idx = 0;
|
||||
patches = zalloc(sizeof(kip1_patch_t) * 32); // Max 32 patches per set.
|
||||
|
||||
patchsets[curr_patchset_idx].name = pt->name;
|
||||
patchsets[curr_patchset_idx].patches = patches;
|
||||
patchsets[patchset_idx].name = pt->name;
|
||||
patchsets[patchset_idx].patches = patches;
|
||||
}
|
||||
|
||||
if (pt->length)
|
||||
{
|
||||
patches[curr_patch_idx].offset = pt->offset;
|
||||
patches[curr_patch_idx].length = pt->length;
|
||||
patches[patch_idx].offset = pt->offset;
|
||||
patches[patch_idx].length = pt->length;
|
||||
|
||||
patches[curr_patch_idx].srcData = (char *)pt->srcData;
|
||||
patches[curr_patch_idx].dstData = (char *)pt->dstData;
|
||||
patches[patch_idx].src_data = (char *)pt->src_data;
|
||||
patches[patch_idx].dst_data = (char *)pt->dst_data;
|
||||
}
|
||||
else
|
||||
patches[curr_patch_idx].srcData = malloc(1); // Empty patches check. Keep everything else as 0.
|
||||
patches[patch_idx].src_data = malloc(1); // Empty patches check. Keep everything else as 0.
|
||||
|
||||
curr_patch_idx++;
|
||||
patch_idx++;
|
||||
}
|
||||
curr_patchset_idx++;
|
||||
patchsets[curr_patchset_idx].name = NULL;
|
||||
patchsets[curr_patchset_idx].patches = NULL;
|
||||
patchset_idx++;
|
||||
patchsets[patchset_idx].name = NULL;
|
||||
patchsets[patchset_idx].patches = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ext_patches_parsed = true;
|
||||
}
|
||||
|
||||
const pkg2_kernel_id_t *pkg2_identify(u8 *hash)
|
||||
const pkg2_kernel_id_t *pkg2_identify(const u8 *hash)
|
||||
{
|
||||
for (u32 i = 0; i < ARRAY_SIZE(_pkg2_kernel_ids); i++)
|
||||
{
|
||||
|
@ -307,7 +307,7 @@ void pkg2_merge_kip(link_t *info, pkg2_kip1_t *kip1)
|
|||
pkg2_add_kip(info, kip1);
|
||||
}
|
||||
|
||||
int pkg2_decompress_kip(pkg2_kip1_info_t* ki, u32 sectsToDecomp)
|
||||
static int _decompress_kip(pkg2_kip1_info_t *ki, u32 sectsToDecomp)
|
||||
{
|
||||
u32 compClearMask = ~sectsToDecomp;
|
||||
if ((ki->kip1->flags & compClearMask) == ki->kip1->flags)
|
||||
|
@ -316,70 +316,70 @@ int pkg2_decompress_kip(pkg2_kip1_info_t* ki, u32 sectsToDecomp)
|
|||
pkg2_kip1_t hdr;
|
||||
memcpy(&hdr, ki->kip1, sizeof(hdr));
|
||||
|
||||
unsigned int newKipSize = sizeof(hdr);
|
||||
for (u32 sectIdx = 0; sectIdx < KIP1_NUM_SECTIONS; sectIdx++)
|
||||
u32 new_kip_size = sizeof(hdr);
|
||||
for (u32 sect_idx = 0; sect_idx < KIP1_NUM_SECTIONS; sect_idx++)
|
||||
{
|
||||
u32 sectCompBit = BIT(sectIdx);
|
||||
u32 comp_bit_mask = BIT(sect_idx);
|
||||
// For compressed, cant get actual decompressed size without doing it, so use safe "output size".
|
||||
if (sectIdx < 3 && (sectsToDecomp & sectCompBit) && (hdr.flags & sectCompBit))
|
||||
newKipSize += hdr.sections[sectIdx].size_decomp;
|
||||
if (sect_idx < 3 && (sectsToDecomp & comp_bit_mask) && (hdr.flags & comp_bit_mask))
|
||||
new_kip_size += hdr.sections[sect_idx].size_decomp;
|
||||
else
|
||||
newKipSize += hdr.sections[sectIdx].size_comp;
|
||||
new_kip_size += hdr.sections[sect_idx].size_comp;
|
||||
}
|
||||
|
||||
pkg2_kip1_t* newKip = malloc(newKipSize);
|
||||
unsigned char* dstDataPtr = newKip->data;
|
||||
const unsigned char* srcDataPtr = ki->kip1->data;
|
||||
for (u32 sectIdx = 0; sectIdx < KIP1_NUM_SECTIONS; sectIdx++)
|
||||
pkg2_kip1_t *new_kip = malloc(new_kip_size);
|
||||
u8 *dst_data = new_kip->data;
|
||||
const u8 *src_data = ki->kip1->data;
|
||||
for (u32 sect_idx = 0; sect_idx < KIP1_NUM_SECTIONS; sect_idx++)
|
||||
{
|
||||
u32 sectCompBit = BIT(sectIdx);
|
||||
u32 comp_bit_mask = BIT(sect_idx);
|
||||
// Easy copy path for uncompressed or ones we dont want to uncompress.
|
||||
if (sectIdx >= 3 || !(sectsToDecomp & sectCompBit) || !(hdr.flags & sectCompBit))
|
||||
if (sect_idx >= 3 || !(sectsToDecomp & comp_bit_mask) || !(hdr.flags & comp_bit_mask))
|
||||
{
|
||||
unsigned int dataSize = hdr.sections[sectIdx].size_comp;
|
||||
u32 dataSize = hdr.sections[sect_idx].size_comp;
|
||||
if (dataSize == 0)
|
||||
continue;
|
||||
|
||||
memcpy(dstDataPtr, srcDataPtr, dataSize);
|
||||
srcDataPtr += dataSize;
|
||||
dstDataPtr += dataSize;
|
||||
memcpy(dst_data, src_data, dataSize);
|
||||
src_data += dataSize;
|
||||
dst_data += dataSize;
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned int compSize = hdr.sections[sectIdx].size_comp;
|
||||
unsigned int outputSize = hdr.sections[sectIdx].size_decomp;
|
||||
gfx_printf("Decomping '%s', sect %d, size %d..\n", (const char*)hdr.name, sectIdx, compSize);
|
||||
if (blz_uncompress_srcdest(srcDataPtr, compSize, dstDataPtr, outputSize) == 0)
|
||||
u32 comp_size = hdr.sections[sect_idx].size_comp;
|
||||
u32 output_size = hdr.sections[sect_idx].size_decomp;
|
||||
gfx_printf("Decomping '%s', sect %d, size %d..\n", (char *)hdr.name, sect_idx, comp_size);
|
||||
if (blz_uncompress_srcdest(src_data, comp_size, dst_data, output_size) == 0)
|
||||
{
|
||||
gfx_con.mute = false;
|
||||
gfx_printf("%kERROR decomping sect %d of '%s'!%k\n", TXT_CLR_ERROR, sectIdx, (char*)hdr.name, TXT_CLR_DEFAULT);
|
||||
free(newKip);
|
||||
gfx_printf("%kERROR decomping sect %d of '%s'!%k\n", TXT_CLR_ERROR, sect_idx, (char *)hdr.name, TXT_CLR_DEFAULT);
|
||||
free(new_kip);
|
||||
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINTF("Done! Decompressed size is %d!\n", outputSize);
|
||||
DPRINTF("Done! Decompressed size is %d!\n", output_size);
|
||||
}
|
||||
hdr.sections[sectIdx].size_comp = outputSize;
|
||||
srcDataPtr += compSize;
|
||||
dstDataPtr += outputSize;
|
||||
hdr.sections[sect_idx].size_comp = output_size;
|
||||
src_data += comp_size;
|
||||
dst_data += output_size;
|
||||
}
|
||||
|
||||
hdr.flags &= compClearMask;
|
||||
memcpy(newKip, &hdr, sizeof(hdr));
|
||||
newKipSize = dstDataPtr-(unsigned char*)(newKip);
|
||||
memcpy(new_kip, &hdr, sizeof(hdr));
|
||||
new_kip_size = dst_data - (u8 *)(new_kip);
|
||||
|
||||
free(ki->kip1);
|
||||
ki->kip1 = newKip;
|
||||
ki->size = newKipSize;
|
||||
ki->kip1 = new_kip;
|
||||
ki->size = new_kip_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _kipm_inject(const char *kipm_path, char *target_name, pkg2_kip1_info_t* ki)
|
||||
static int _kipm_inject(const char *kipm_path, char *target_name, pkg2_kip1_info_t *ki)
|
||||
{
|
||||
if (!strncmp((const char *)ki->kip1->name, target_name, sizeof(ki->kip1->name)))
|
||||
if (!strcmp((char *)ki->kip1->name, target_name))
|
||||
{
|
||||
u32 size = 0;
|
||||
u8 *kipm_data = (u8 *)sd_file_read(kipm_path, &size);
|
||||
|
@ -403,9 +403,9 @@ static int _kipm_inject(const char *kipm_path, char *target_name, pkg2_kip1_info
|
|||
|
||||
u32 new_offset = 0;
|
||||
|
||||
for (u32 currSectIdx = 0; currSectIdx < KIP1_NUM_SECTIONS - 2; currSectIdx++)
|
||||
for (u32 section_idx = 0; section_idx < KIP1_NUM_SECTIONS - 2; section_idx++)
|
||||
{
|
||||
if (!currSectIdx) // .text.
|
||||
if (!section_idx) // .text.
|
||||
{
|
||||
memcpy(ki->kip1->data + inject_size, fs_kip->data, fs_kip->sections[0].size_comp);
|
||||
ki->kip1->sections[0].size_decomp += inject_size;
|
||||
|
@ -413,11 +413,11 @@ static int _kipm_inject(const char *kipm_path, char *target_name, pkg2_kip1_info
|
|||
}
|
||||
else // Others.
|
||||
{
|
||||
if (currSectIdx < 3)
|
||||
memcpy(ki->kip1->data + new_offset + inject_size, fs_kip->data + new_offset, fs_kip->sections[currSectIdx].size_comp);
|
||||
ki->kip1->sections[currSectIdx].offset += inject_size;
|
||||
if (section_idx < 3)
|
||||
memcpy(ki->kip1->data + new_offset + inject_size, fs_kip->data + new_offset, fs_kip->sections[section_idx].size_comp);
|
||||
ki->kip1->sections[section_idx].offset += inject_size;
|
||||
}
|
||||
new_offset += fs_kip->sections[currSectIdx].size_comp;
|
||||
new_offset += fs_kip->sections[section_idx].size_comp;
|
||||
}
|
||||
|
||||
// Patch PMC capabilities for 1.0.0.
|
||||
|
@ -440,24 +440,28 @@ static int _kipm_inject(const char *kipm_path, char *target_name, pkg2_kip1_info
|
|||
return 1;
|
||||
}
|
||||
|
||||
const char* pkg2_patch_kips(link_t *info, char* patchNames)
|
||||
const char *pkg2_patch_kips(link_t *info, char *patch_names)
|
||||
{
|
||||
if (patchNames == NULL || patchNames[0] == 0)
|
||||
bool emummc_patch_selected = false;
|
||||
|
||||
if (patch_names == NULL || patch_names[0] == 0)
|
||||
return NULL;
|
||||
|
||||
static const u32 MAX_NUM_PATCHES_REQUESTED = sizeof(u32) * 8;
|
||||
char* patches[MAX_NUM_PATCHES_REQUESTED];
|
||||
gfx_printf("%kPatching kips%k\n", TXT_CLR_ORANGE, TXT_CLR_DEFAULT);
|
||||
|
||||
u32 numPatches = 1;
|
||||
patches[0] = patchNames;
|
||||
static const u32 MAX_NUM_PATCHES_REQUESTED = sizeof(u32) * 8;
|
||||
char *patches[MAX_NUM_PATCHES_REQUESTED];
|
||||
|
||||
u32 patches_num = 1;
|
||||
patches[0] = patch_names;
|
||||
{
|
||||
for (char* p = patchNames; *p != 0; p++)
|
||||
for (char *p = patch_names; *p != 0; p++)
|
||||
{
|
||||
if (*p == ',')
|
||||
{
|
||||
*p = 0;
|
||||
patches[numPatches++] = p + 1;
|
||||
if (numPatches >= MAX_NUM_PATCHES_REQUESTED)
|
||||
patches[patches_num++] = p + 1;
|
||||
if (patches_num >= MAX_NUM_PATCHES_REQUESTED)
|
||||
return "too_many_patches";
|
||||
}
|
||||
else if (*p >= 'A' && *p <= 'Z') // Convert to lowercase.
|
||||
|
@ -465,198 +469,217 @@ const char* pkg2_patch_kips(link_t *info, char* patchNames)
|
|||
}
|
||||
}
|
||||
|
||||
u32 patchesApplied = 0; // Bitset over patches.
|
||||
for (u32 i = 0; i < numPatches; i++)
|
||||
u32 patches_applied = 0; // Bitset over patches.
|
||||
for (u32 i = 0; i < patches_num; i++)
|
||||
{
|
||||
// Eliminate leading spaces.
|
||||
for (const char* p = patches[i]; *p != 0; p++)
|
||||
for (const char *p = patches[i]; *p != 0; p++)
|
||||
{
|
||||
if (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')
|
||||
patches[i]++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
int valueLen = strlen(patches[i]);
|
||||
if (valueLen == 0)
|
||||
|
||||
int patch_len = strlen(patches[i]);
|
||||
if (patch_len == 0)
|
||||
continue;
|
||||
|
||||
// Eliminate trailing spaces.
|
||||
for (int chIdx = valueLen - 1; chIdx >= 0; chIdx--)
|
||||
for (int chIdx = patch_len - 1; chIdx >= 0; chIdx--)
|
||||
{
|
||||
const char* p = patches[i] + chIdx;
|
||||
const char *p = patches[i] + chIdx;
|
||||
if (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')
|
||||
valueLen = chIdx;
|
||||
patch_len = chIdx;
|
||||
else
|
||||
break;
|
||||
}
|
||||
patches[i][valueLen] = 0;
|
||||
patches[i][patch_len] = 0;
|
||||
|
||||
DPRINTF("Requested patch: '%s'\n", patches[i]);
|
||||
}
|
||||
|
||||
// Parse external patches if needed.
|
||||
for (u32 i = 0; i < numPatches; i++)
|
||||
for (u32 i = 0; i < patches_num; i++)
|
||||
{
|
||||
if (strcmp(patches[i], "emummc") && strcmp(patches[i], "nogc"))
|
||||
if (!strcmp(patches[i], "emummc"))
|
||||
{
|
||||
parse_external_kip_patches();
|
||||
break;
|
||||
// emuMMC patch is managed on its own.
|
||||
emummc_patch_selected = true;
|
||||
patches_applied |= BIT(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(patches[i], "nogc"))
|
||||
parse_external_kip_patches();
|
||||
}
|
||||
|
||||
u32 shaBuf[SE_SHA_256_SIZE / sizeof(u32)];
|
||||
u32 kip_hash[SE_SHA_256_SIZE / sizeof(u32)];
|
||||
LIST_FOREACH_ENTRY(pkg2_kip1_info_t, ki, info, link)
|
||||
{
|
||||
shaBuf[0] = 0; // sha256 for this kip not yet calculated.
|
||||
for (u32 currKipIdx = 0; currKipIdx < _kip_id_sets_cnt; currKipIdx++)
|
||||
// Reset hash so it can be calculated for the new kip.
|
||||
kip_hash[0] = 0;
|
||||
|
||||
bool emummc_patch_apply = emummc_patch_selected && !strcmp((char *)ki->kip1->name, "FS");
|
||||
|
||||
// Check all SHA256 ID sets. (IDs are grouped per KIP. IDs are still unique.)
|
||||
for (u32 kip_id_idx = 0; kip_id_idx < _kip_id_sets_cnt; kip_id_idx++)
|
||||
{
|
||||
if (strncmp((const char*)ki->kip1->name, _kip_id_sets[currKipIdx].name, sizeof(ki->kip1->name)) != 0)
|
||||
// Check if KIP name macthes ID's KIP name.
|
||||
if (strcmp((char *)ki->kip1->name, _kip_id_sets[kip_id_idx].name) != 0)
|
||||
continue;
|
||||
|
||||
u32 bitsAffected = 0;
|
||||
kip1_patchset_t* currPatchset = _kip_id_sets[currKipIdx].patchset;
|
||||
while (currPatchset != NULL && currPatchset->name != NULL)
|
||||
// Check if there are patches to apply.
|
||||
bool patches_found = false;
|
||||
const kip1_patchset_t *patchset = _kip_id_sets[kip_id_idx].patchset;
|
||||
while (patchset != NULL && patchset->name != NULL && !patches_found)
|
||||
{
|
||||
for (u32 i = 0; i < numPatches; i++)
|
||||
for (u32 i = 0; i < patches_num; i++)
|
||||
{
|
||||
// Continue if patch name does not match.
|
||||
if (strcmp(currPatchset->name, patches[i]) != 0)
|
||||
if (strcmp(patchset->name, patches[i]) != 0)
|
||||
continue;
|
||||
|
||||
bitsAffected = i + 1;
|
||||
patches_found = true;
|
||||
break;
|
||||
}
|
||||
currPatchset++;
|
||||
patchset++;
|
||||
}
|
||||
|
||||
// Dont bother even hashing this KIP if we dont have any patches enabled for it.
|
||||
if (bitsAffected == 0)
|
||||
// Don't bother hashing this KIP if no patches are enabled for it.
|
||||
if (!patches_found && !emummc_patch_apply)
|
||||
continue;
|
||||
|
||||
if (shaBuf[0] == 0)
|
||||
{
|
||||
if (!se_calc_sha256_oneshot(shaBuf, ki->kip1, ki->size))
|
||||
memset(shaBuf, 0, sizeof(shaBuf));
|
||||
}
|
||||
// Check if current KIP not hashed and hash it.
|
||||
if (kip_hash[0] == 0)
|
||||
if (!se_calc_sha256_oneshot(kip_hash, ki->kip1, ki->size))
|
||||
memset(kip_hash, 0, sizeof(kip_hash));
|
||||
|
||||
if (memcmp(shaBuf, _kip_id_sets[currKipIdx].hash, sizeof(_kip_id_sets[0].hash)) != 0)
|
||||
// Check if kip is the expected version.
|
||||
if (memcmp(kip_hash, _kip_id_sets[kip_id_idx].hash, sizeof(_kip_id_sets[0].hash)) != 0)
|
||||
continue;
|
||||
|
||||
// Find out which sections are affected by the enabled patches, to know which to decompress.
|
||||
bitsAffected = 0;
|
||||
currPatchset = _kip_id_sets[currKipIdx].patchset;
|
||||
while (currPatchset != NULL && currPatchset->name != NULL)
|
||||
// Find out which sections are affected by the enabled patches, in order to decompress them.
|
||||
u32 sections_affected = 0;
|
||||
patchset = _kip_id_sets[kip_id_idx].patchset;
|
||||
while (patchset != NULL && patchset->name != NULL)
|
||||
{
|
||||
if (currPatchset->patches != NULL)
|
||||
if (patchset->patches != NULL)
|
||||
{
|
||||
for (u32 currEnabIdx = 0; currEnabIdx < numPatches; currEnabIdx++)
|
||||
for (u32 patch_idx = 0; patch_idx < patches_num; patch_idx++)
|
||||
{
|
||||
if (strcmp(currPatchset->name, patches[currEnabIdx]))
|
||||
if (strcmp(patchset->name, patches[patch_idx]))
|
||||
continue;
|
||||
|
||||
if (!strcmp(currPatchset->name, "emummc"))
|
||||
bitsAffected |= BIT(GET_KIP_PATCH_SECTION(currPatchset->patches->offset));
|
||||
|
||||
for (const kip1_patch_t* currPatch=currPatchset->patches; currPatch != NULL && (currPatch->length != 0); currPatch++)
|
||||
bitsAffected |= BIT(GET_KIP_PATCH_SECTION(currPatch->offset));
|
||||
for (const kip1_patch_t *patch = patchset->patches; patch != NULL && (patch->length != 0); patch++)
|
||||
sections_affected |= BIT(GET_KIP_PATCH_SECTION(patch->offset));
|
||||
}
|
||||
}
|
||||
currPatchset++;
|
||||
patchset++;
|
||||
}
|
||||
|
||||
// Got patches to apply to this kip, have to decompress it.
|
||||
if (pkg2_decompress_kip(ki, bitsAffected))
|
||||
return (const char*)ki->kip1->name; // Failed to decompress.
|
||||
// If emuMMC is enabled, set its affected section.
|
||||
if (emummc_patch_apply)
|
||||
sections_affected |= BIT(KIP_TEXT);
|
||||
|
||||
currPatchset = _kip_id_sets[currKipIdx].patchset;
|
||||
bool emummc_patch_selected = false;
|
||||
while (currPatchset != NULL && currPatchset->name != NULL)
|
||||
// Got patches to apply to this kip, have to decompress it.
|
||||
if (_decompress_kip(ki, sections_affected))
|
||||
return (char *)ki->kip1->name; // Failed to decompress.
|
||||
|
||||
// Apply all patches for matched ID.
|
||||
patchset = _kip_id_sets[kip_id_idx].patchset;
|
||||
while (patchset != NULL && patchset->name != NULL)
|
||||
{
|
||||
for (u32 currEnabIdx = 0; currEnabIdx < numPatches; currEnabIdx++)
|
||||
for (u32 patch_idx = 0; patch_idx < patches_num; patch_idx++)
|
||||
{
|
||||
if (strcmp(currPatchset->name, patches[currEnabIdx]))
|
||||
// Check if patchset name matches requested patch.
|
||||
if (strcmp(patchset->name, patches[patch_idx]))
|
||||
continue;
|
||||
|
||||
u32 appliedMask = BIT(currEnabIdx);
|
||||
u32 applied_mask = BIT(patch_idx);
|
||||
|
||||
if (!strcmp(currPatchset->name, "emummc"))
|
||||
// Check if patchset is empty.
|
||||
if (patchset->patches == NULL)
|
||||
{
|
||||
emummc_patch_selected = true;
|
||||
patchesApplied |= appliedMask;
|
||||
|
||||
continue; // Patching is done later.
|
||||
}
|
||||
|
||||
if (currPatchset->patches == NULL)
|
||||
{
|
||||
DPRINTF("Patch '%s' not necessary for %s\n", currPatchset->name, (const char*)ki->kip1->name);
|
||||
patchesApplied |= appliedMask;
|
||||
DPRINTF("Patch '%s' not necessary for %s\n", patchset->name, (char *)ki->kip1->name);
|
||||
patches_applied |= applied_mask;
|
||||
|
||||
continue; // Continue in case it's double defined.
|
||||
}
|
||||
|
||||
unsigned char* kipSectData = ki->kip1->data;
|
||||
for (u32 currSectIdx = 0; currSectIdx < KIP1_NUM_SECTIONS; currSectIdx++)
|
||||
// Apply patches per section.
|
||||
u8 *kip_sect_data = ki->kip1->data;
|
||||
for (u32 section_idx = 0; section_idx < KIP1_NUM_SECTIONS; section_idx++)
|
||||
{
|
||||
if (bitsAffected & BIT(currSectIdx))
|
||||
if (sections_affected & BIT(section_idx))
|
||||
{
|
||||
gfx_printf("Applying '%s' on %s, sect %d\n", currPatchset->name, (const char*)ki->kip1->name, currSectIdx);
|
||||
for (const kip1_patch_t* currPatch = currPatchset->patches; currPatch != NULL && currPatch->srcData != NULL; currPatch++)
|
||||
gfx_printf("Applying '%s' on %s, sect %d\n", patchset->name, (char *)ki->kip1->name, section_idx);
|
||||
for (const kip1_patch_t *patch = patchset->patches; patch != NULL && patch->src_data != NULL; patch++)
|
||||
{
|
||||
if (GET_KIP_PATCH_SECTION(currPatch->offset) != currSectIdx)
|
||||
// Check if patch is in current section.
|
||||
if (GET_KIP_PATCH_SECTION(patch->offset) != section_idx)
|
||||
continue;
|
||||
|
||||
if (!currPatch->length)
|
||||
// Check if patch is empty.
|
||||
if (!patch->length)
|
||||
{
|
||||
gfx_con.mute = false;
|
||||
gfx_printf("%kPatch empty!%k\n", TXT_CLR_ERROR, TXT_CLR_DEFAULT);
|
||||
return currPatchset->name; // MUST stop here as it's not probably intended.
|
||||
return patchset->name; // MUST stop here as it's not probably intended.
|
||||
}
|
||||
|
||||
u32 currOffset = GET_KIP_PATCH_OFFSET(currPatch->offset);
|
||||
// If source does not match and is not already patched, throw an error.
|
||||
if ((memcmp(&kipSectData[currOffset], currPatch->srcData, currPatch->length) != 0) &&
|
||||
(memcmp(&kipSectData[currOffset], currPatch->dstData, currPatch->length) != 0))
|
||||
u32 patch_offset = GET_KIP_PATCH_OFFSET(patch->offset);
|
||||
if (patch->src_data != KIP1_PATCH_SRC_NO_CHECK &&
|
||||
(memcmp(&kip_sect_data[patch_offset], patch->src_data, patch->length) != 0) &&
|
||||
(memcmp(&kip_sect_data[patch_offset], patch->dst_data, patch->length) != 0))
|
||||
{
|
||||
gfx_con.mute = false;
|
||||
gfx_printf("%kPatch mismatch at 0x%x!%k\n", TXT_CLR_ERROR, currOffset, TXT_CLR_DEFAULT);
|
||||
return currPatchset->name; // MUST stop here as kip is likely corrupt.
|
||||
gfx_printf("%kPatch mismatch at 0x%x!%k\n", TXT_CLR_ERROR, patch_offset, TXT_CLR_DEFAULT);
|
||||
return patchset->name; // MUST stop here as kip is likely corrupt.
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINTF("Patching %d bytes at offset 0x%x\n", currPatch->length, currOffset);
|
||||
memcpy(&kipSectData[currOffset], currPatch->dstData, currPatch->length);
|
||||
DPRINTF("Patching %d bytes at offset 0x%x\n", patch->length, patch_offset);
|
||||
memcpy(&kip_sect_data[patch_offset], patch->dst_data, patch->length);
|
||||
}
|
||||
}
|
||||
}
|
||||
kipSectData += ki->kip1->sections[currSectIdx].size_comp;
|
||||
kip_sect_data += ki->kip1->sections[section_idx].size_comp;
|
||||
}
|
||||
|
||||
patchesApplied |= appliedMask;
|
||||
continue; // Continue in case it's double defined.
|
||||
patches_applied |= applied_mask;
|
||||
}
|
||||
currPatchset++;
|
||||
|
||||
patchset++;
|
||||
}
|
||||
|
||||
if (emummc_patch_selected && !strncmp(_kip_id_sets[currKipIdx].name, "FS", sizeof(ki->kip1->name)))
|
||||
// emuMMC must be applied after all other patches, since it affects TEXT offset.
|
||||
if (emummc_patch_apply)
|
||||
{
|
||||
emummc_patch_selected = false;
|
||||
emu_cfg.fs_ver = currKipIdx;
|
||||
if (currKipIdx)
|
||||
// Encode ID.
|
||||
emu_cfg.fs_ver = kip_id_idx;
|
||||
if (kip_id_idx)
|
||||
emu_cfg.fs_ver--;
|
||||
if (currKipIdx > 17)
|
||||
if (kip_id_idx > 17)
|
||||
emu_cfg.fs_ver -= 2;
|
||||
|
||||
// Inject emuMMC code.
|
||||
gfx_printf("Injecting emuMMC. FS ID: %d\n", emu_cfg.fs_ver);
|
||||
if (_kipm_inject("/bootloader/sys/emummc.kipm", "FS", ki))
|
||||
if (_kipm_inject("bootloader/sys/emummc.kipm", "FS", ki))
|
||||
return "emummc";
|
||||
|
||||
// Skip checking again.
|
||||
emummc_patch_selected = false;
|
||||
emummc_patch_apply = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < numPatches; i++)
|
||||
// Check if all patches were applied.
|
||||
for (u32 i = 0; i < patches_num; i++)
|
||||
{
|
||||
if ((patchesApplied & BIT(i)) == 0)
|
||||
if ((patches_applied & BIT(i)) == 0)
|
||||
return patches[i];
|
||||
}
|
||||
|
||||
|
@ -746,7 +769,7 @@ static u32 _pkg2_ini1_build(u8 *pdst, u8 *psec, pkg2_hdr_t *hdr, link_t *kips_in
|
|||
// Merge KIPs into INI1.
|
||||
LIST_FOREACH_ENTRY(pkg2_kip1_info_t, ki, kips_info, link)
|
||||
{
|
||||
DPRINTF("adding kip1 '%s' @ %08X (%08X)\n", ki->kip1->name, (u32)ki->kip1, ki->size);
|
||||
DPRINTF("adding kip1 '%s' @ %08X (%08X)\n", (char *)ki->kip1->name, (u32)ki->kip1, ki->size);
|
||||
memcpy(pdst, ki->kip1, ki->size);
|
||||
pdst += ki->size;
|
||||
ini1->num_procs++;
|
||||
|
@ -770,7 +793,7 @@ DPRINTF("adding kip1 '%s' @ %08X (%08X)\n", ki->kip1->name, (u32)ki->kip1, ki->s
|
|||
|
||||
void pkg2_build_encrypt(void *dst, void *hos_ctxt, link_t *kips_info, bool is_exo)
|
||||
{
|
||||
launch_ctxt_t * ctxt = (launch_ctxt_t *)hos_ctxt;
|
||||
launch_ctxt_t *ctxt = (launch_ctxt_t *)hos_ctxt;
|
||||
u32 meso_magic = *(u32 *)(ctxt->kernel + 4);
|
||||
u32 kernel_size = ctxt->kernel_size;
|
||||
u8 kb = ctxt->pkg1_id->kb;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2023 CTCaer
|
||||
* Copyright (c) 2018-2024 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,
|
||||
|
@ -40,14 +40,14 @@ extern u32 pkg2_newkern_ini1_end;
|
|||
|
||||
typedef struct _kernel_patch_t
|
||||
{
|
||||
u32 id;
|
||||
u32 off;
|
||||
u32 val;
|
||||
u32 *ptr;
|
||||
u32 id;
|
||||
u32 off;
|
||||
u32 val;
|
||||
const u32 *ptr;
|
||||
} kernel_patch_t;
|
||||
|
||||
#define KERNEL_PATCHSET_DEF(name, ...) \
|
||||
kernel_patch_t name[] = { \
|
||||
static const kernel_patch_t name[] = { \
|
||||
__VA_ARGS__, \
|
||||
{0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, (u32 *)0xFFFFFFFF} \
|
||||
}
|
||||
|
@ -67,8 +67,8 @@ enum
|
|||
|
||||
typedef struct _pkg2_hdr_t
|
||||
{
|
||||
u8 ctr[0x10];
|
||||
u8 sec_ctr[0x40];
|
||||
u8 ctr[0x10];
|
||||
u8 sec_ctr[0x40];
|
||||
u32 magic;
|
||||
u32 base;
|
||||
u32 pad0;
|
||||
|
@ -77,8 +77,8 @@ typedef struct _pkg2_hdr_t
|
|||
u16 pad1;
|
||||
u32 sec_size[4];
|
||||
u32 sec_off[4];
|
||||
u8 sec_sha256[0x80];
|
||||
u8 data[];
|
||||
u8 sec_sha256[0x80];
|
||||
u8 data[];
|
||||
} pkg2_hdr_t;
|
||||
|
||||
typedef struct _pkg2_ini1_t
|
||||
|
@ -102,7 +102,7 @@ typedef struct _pkg2_kip1_sec_t
|
|||
typedef struct _pkg2_kip1_t
|
||||
{
|
||||
/* 0x000 */ u32 magic;
|
||||
/* 0x004*/ u8 name[12];
|
||||
/* 0x004*/ u8 name[12];
|
||||
/* 0x010 */ u64 tid;
|
||||
/* 0x018 */ u32 proc_cat;
|
||||
/* 0x01C */ u8 main_thrd_prio;
|
||||
|
@ -124,28 +124,30 @@ typedef struct _pkg2_kip1_info_t
|
|||
typedef struct _pkg2_kernel_id_t
|
||||
{
|
||||
u8 hash[8];
|
||||
kernel_patch_t *kernel_patchset;
|
||||
const kernel_patch_t *kernel_patchset;
|
||||
} pkg2_kernel_id_t;
|
||||
|
||||
#define KIP1_PATCH_SRC_NO_CHECK (char *)(-1)
|
||||
|
||||
typedef struct _kip1_patch_t
|
||||
{
|
||||
u32 offset; // section+offset of patch to apply.
|
||||
u32 length; // In bytes, 0 means last patch.
|
||||
char* srcData; // That must match.
|
||||
char* dstData; // That it gets replaced by.
|
||||
u32 offset; // section+offset of patch to apply.
|
||||
u32 length; // In bytes, 0 means last patch.
|
||||
char *src_data; // That must match.
|
||||
char *dst_data; // That it gets replaced by.
|
||||
} kip1_patch_t;
|
||||
|
||||
typedef struct _kip1_patchset_t
|
||||
{
|
||||
char* name; // NULL means end.
|
||||
kip1_patch_t* patches; // NULL means not necessary.
|
||||
char *name; // NULL means end.
|
||||
const kip1_patch_t *patches; // NULL means not necessary.
|
||||
} kip1_patchset_t;
|
||||
|
||||
typedef struct _kip1_id_t
|
||||
{
|
||||
const char* name;
|
||||
const char *name;
|
||||
u8 hash[8];
|
||||
kip1_patchset_t* patchset;
|
||||
const kip1_patchset_t *patchset;
|
||||
} kip1_id_t;
|
||||
|
||||
void pkg2_get_newkern_info(u8 *kern_data);
|
||||
|
@ -155,9 +157,9 @@ void pkg2_replace_kip(link_t *info, u64 tid, pkg2_kip1_t *kip1);
|
|||
void pkg2_add_kip(link_t *info, pkg2_kip1_t *kip1);
|
||||
void pkg2_merge_kip(link_t *info, pkg2_kip1_t *kip1);
|
||||
void pkg2_get_ids(kip1_id_t **ids, u32 *entries);
|
||||
const char* pkg2_patch_kips(link_t *info, char* patchNames);
|
||||
const char *pkg2_patch_kips(link_t *info, char *patch_names);
|
||||
|
||||
const pkg2_kernel_id_t *pkg2_identify(u8 *hash);
|
||||
const pkg2_kernel_id_t *pkg2_identify(const u8 *hash);
|
||||
pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb, bool is_exo);
|
||||
void pkg2_build_encrypt(void *dst, void *hos_ctxt, link_t *kips_info, bool is_exo);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2022 CTCaer
|
||||
* Copyright (c) 2019-2024 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,
|
||||
|
@ -80,7 +80,7 @@ static ini_kip_sec_t *_ini_create_kip_section(link_t *dst, ini_kip_sec_t *ksec,
|
|||
|
||||
// Calculate total allocation size.
|
||||
u32 len = strlen(name);
|
||||
char *buf = calloc(sizeof(ini_kip_sec_t) + len + 1, 1);
|
||||
char *buf = zalloc(sizeof(ini_kip_sec_t) + len + 1);
|
||||
|
||||
ksec = (ini_kip_sec_t *)buf;
|
||||
u32 i = _find_patch_section_name(name, len, ':') + 1;
|
||||
|
@ -95,7 +95,7 @@ static ini_kip_sec_t *_ini_create_kip_section(link_t *dst, ini_kip_sec_t *ksec,
|
|||
return ksec;
|
||||
}
|
||||
|
||||
int ini_patch_parse(link_t *dst, char *ini_path)
|
||||
int ini_patch_parse(link_t *dst, const char *ini_path)
|
||||
{
|
||||
FIL fp;
|
||||
u32 lblen;
|
||||
|
@ -132,7 +132,7 @@ int ini_patch_parse(link_t *dst, char *ini_path)
|
|||
u32 pos = _find_patch_section_name(lbuf, lblen, '=');
|
||||
|
||||
// Calculate total allocation size.
|
||||
char *buf = calloc(sizeof(ini_patchset_t) + strlen(&lbuf[1]) + 1, 1);
|
||||
char *buf = zalloc(sizeof(ini_patchset_t) + strlen(&lbuf[1]) + 1);
|
||||
ini_patchset_t *pt = (ini_patchset_t *)buf;
|
||||
|
||||
// Set patch name.
|
||||
|
@ -154,15 +154,15 @@ int ini_patch_parse(link_t *dst, char *ini_path)
|
|||
pt->length = strtol(&lbuf[pos], NULL, 16);
|
||||
pos += str_start + 1;
|
||||
|
||||
u8 *buf = malloc(pt->length * 2);
|
||||
u8 *data = malloc(pt->length * 2);
|
||||
|
||||
// Set patch source data.
|
||||
str_start = _find_patch_section_name(&lbuf[pos], lblen - pos, ',');
|
||||
pt->srcData = _htoa(NULL, &lbuf[pos], pt->length, buf);
|
||||
pt->src_data = _htoa(NULL, &lbuf[pos], pt->length, data);
|
||||
pos += str_start + 1;
|
||||
|
||||
// Set patch destination data.
|
||||
pt->dstData = _htoa(NULL, &lbuf[pos], pt->length, buf + pt->length);
|
||||
pt->dst_data = _htoa(NULL, &lbuf[pos], pt->length, data + pt->length);
|
||||
}
|
||||
|
||||
list_append(&ksec->pts, &pt->link);
|
||||
|
|
|
@ -22,10 +22,10 @@
|
|||
typedef struct _ini_patchset_t
|
||||
{
|
||||
char *name;
|
||||
u32 offset; // section + offset of patch to apply.
|
||||
u32 length; // In bytes, 0 means last patch.
|
||||
u8 *srcData; // That must match.
|
||||
u8 *dstData; // Gets replaced with.
|
||||
u32 offset; // section + offset of patch to apply.
|
||||
u32 length; // In bytes, 0 means last patch.
|
||||
u8 *src_data; // That must match.
|
||||
u8 *dst_data; // Gets replaced with.
|
||||
link_t link;
|
||||
} ini_patchset_t;
|
||||
|
||||
|
@ -37,6 +37,6 @@ typedef struct _ini_kip_sec_t
|
|||
link_t link;
|
||||
} ini_kip_sec_t;
|
||||
|
||||
int ini_patch_parse(link_t *dst, char *ini_path);
|
||||
int ini_patch_parse(link_t *dst, const char *ini_path);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2023 CTCaer
|
||||
* Copyright (c) 2018-2024 CTCaer
|
||||
* Copyright (c) 2018 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
@ -63,37 +63,37 @@
|
|||
#define ID_RCV_OFF_1101 0x22B28
|
||||
#define ID_RCV_OFF_1200 0x23424
|
||||
|
||||
static u32 PRC_ID_SND_100[] =
|
||||
static const u32 PRC_ID_SND_100[] =
|
||||
{
|
||||
0xA9BF2FEA, 0x2A0E03EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B,
|
||||
0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9412948, 0xA8C12FEA
|
||||
};
|
||||
#define CODE_OFF_2ND_100 (CODE_OFF_1ST_100 + sizeof(PRC_ID_SND_100) + sizeof(u32))
|
||||
static u32 PRC_ID_RCV_100[] =
|
||||
static const u32 PRC_ID_RCV_100[] =
|
||||
{
|
||||
0xA9BF2FEA, 0x2A1C03EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A,
|
||||
0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9412968, 0xA8C12FEA
|
||||
};
|
||||
|
||||
static u32 PRC_ID_SND_200[] =
|
||||
static const u32 PRC_ID_SND_200[] =
|
||||
{
|
||||
0xA9BF2FEA, 0x2A1803EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B,
|
||||
0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9413148, 0xA8C12FEA
|
||||
};
|
||||
#define CODE_OFF_2ND_200 (CODE_OFF_1ST_200 + sizeof(PRC_ID_SND_200) + sizeof(u32))
|
||||
static u32 PRC_ID_RCV_200[] =
|
||||
static const u32 PRC_ID_RCV_200[] =
|
||||
{
|
||||
0xA9BF2FEA, 0x2A0F03EA, 0xD37EF54A, 0xF9405FEB, 0xF86A696A, 0xF9407BEB, 0x92FFFFE9, 0x8A090148,
|
||||
0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9413168, 0xA8C12FEA
|
||||
};
|
||||
|
||||
static u32 PRC_ID_SND_300[] =
|
||||
static const u32 PRC_ID_SND_300[] =
|
||||
{
|
||||
0xA9BF2FEA, 0x2A1803EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B,
|
||||
0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9415548, 0xA8C12FEA
|
||||
};
|
||||
#define CODE_OFF_2ND_300 (CODE_OFF_1ST_300 + sizeof(PRC_ID_SND_300) + sizeof(u32))
|
||||
static u32 PRC_ID_RCV_300[] =
|
||||
static const u32 PRC_ID_RCV_300[] =
|
||||
{
|
||||
0xA9BF2FEA, 0x2A0F03EA, 0xD37EF54A, 0xF9405FEB, 0xF86A696A, 0xF9407BEB, 0x92FFFFE9, 0x8A090148,
|
||||
0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415568, 0xA8C12FEA
|
||||
|
@ -101,52 +101,52 @@ static u32 PRC_ID_RCV_300[] =
|
|||
|
||||
#define CODE_OFF_2ND_302 (CODE_OFF_1ST_302 + sizeof(PRC_ID_SND_300) + sizeof(u32))
|
||||
|
||||
static u32 PRC_ID_SND_400[] =
|
||||
static const u32 PRC_ID_SND_400[] =
|
||||
{
|
||||
0x2A1703EA, 0xD37EF54A, 0xF86A6B8A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9,
|
||||
0xEB09015F, 0x54000060, 0xF94053EA, 0xF9415948, 0xF94053EA
|
||||
};
|
||||
#define CODE_OFF_2ND_400 (CODE_OFF_1ST_400 + sizeof(PRC_ID_SND_400) + sizeof(u32))
|
||||
static u32 PRC_ID_RCV_400[] =
|
||||
static const u32 PRC_ID_RCV_400[] =
|
||||
{
|
||||
0xF9403BED, 0x2A0E03EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A,
|
||||
0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415B28, 0xD503201F
|
||||
};
|
||||
|
||||
static u32 PRC_ID_SND_500[] =
|
||||
static const u32 PRC_ID_SND_500[] =
|
||||
{
|
||||
0x2A1703EA, 0xD37EF54A, 0xF86A6B6A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9,
|
||||
0xEB09015F, 0x54000060, 0xF94043EA, 0xF9415948, 0xF94043EA
|
||||
};
|
||||
#define CODE_OFF_2ND_500 (CODE_OFF_1ST_500 + sizeof(PRC_ID_SND_500) + sizeof(u32))
|
||||
static u32 PRC_ID_RCV_500[] =
|
||||
static const u32 PRC_ID_RCV_500[] =
|
||||
{
|
||||
0xF9403BED, 0x2A1503EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A,
|
||||
0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415B08, 0xF9406FEA
|
||||
};
|
||||
|
||||
static u32 PRC_ID_SND_600[] =
|
||||
static const u32 PRC_ID_SND_600[] =
|
||||
{
|
||||
0xA9BF2FEA, 0xF94037EB, 0x2A1503EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9,
|
||||
0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400308, 0xF9401D08, 0xAA1803E0,
|
||||
0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0
|
||||
};
|
||||
#define CODE_OFF_2ND_600 (CODE_OFF_1ST_600 + sizeof(PRC_ID_SND_600) + sizeof(u32))
|
||||
static u32 PRC_ID_RCV_600[] =
|
||||
static const u32 PRC_ID_RCV_600[] =
|
||||
{
|
||||
0xA9BF2FEA, 0xF94043EB, 0x2A1503EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9,
|
||||
0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400308, 0xF9401D08, 0xAA1803E0,
|
||||
0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0
|
||||
};
|
||||
|
||||
static u32 PRC_ID_SND_700[] =
|
||||
static const u32 PRC_ID_SND_700[] =
|
||||
{
|
||||
0xA9BF2FEA, 0xF9403BEB, 0x2A1903EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9,
|
||||
0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF94002A8, 0xF9401D08, 0xAA1503E0,
|
||||
0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0
|
||||
};
|
||||
#define CODE_OFF_2ND_700 (CODE_OFF_1ST_700 + sizeof(PRC_ID_SND_700) + sizeof(u32))
|
||||
static u32 PRC_ID_RCV_700[] =
|
||||
static const u32 PRC_ID_RCV_700[] =
|
||||
{
|
||||
0xA9BF2FEA, 0xF9404FEB, 0x2A1603EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9,
|
||||
0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400368, 0xF9401D08, 0xAA1B03E0,
|
||||
|
@ -155,56 +155,56 @@ static u32 PRC_ID_RCV_700[] =
|
|||
|
||||
#define CODE_OFF_2ND_800 (CODE_OFF_1ST_800 + sizeof(PRC_ID_SND_700) + sizeof(u32))
|
||||
|
||||
static u32 PRC_ID_SND_900[] =
|
||||
static const u32 PRC_ID_SND_900[] =
|
||||
{
|
||||
0xA9BF2FEA, 0xF94037EB, 0x2A1603EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9,
|
||||
0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF94002E8, 0xF9401D08, 0xAA1703E0,
|
||||
0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0
|
||||
};
|
||||
#define CODE_OFF_2ND_900 (CODE_OFF_1ST_900 + sizeof(PRC_ID_SND_900) + sizeof(u32))
|
||||
static u32 PRC_ID_RCV_900[] =
|
||||
static const u32 PRC_ID_RCV_900[] =
|
||||
{
|
||||
0xA9BF2FEA, 0xF9404BEB, 0x2A1703EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9,
|
||||
0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400368, 0xF9401D08, 0xAA1B03E0,
|
||||
0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0
|
||||
};
|
||||
|
||||
static u32 PRC_ID_SND_1000[] =
|
||||
static const u32 PRC_ID_SND_1000[] =
|
||||
{
|
||||
0xA9BF2FEA, 0xF94063EB, 0x2A1603EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9,
|
||||
0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF94002E8, 0xF9401D08, 0xAA1703E0,
|
||||
0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0
|
||||
};
|
||||
#define CODE_OFF_2ND_1000 (CODE_OFF_1ST_1000 + sizeof(PRC_ID_SND_1000) + sizeof(u32))
|
||||
static u32 PRC_ID_RCV_1000[] =
|
||||
static const u32 PRC_ID_RCV_1000[] =
|
||||
{
|
||||
0xA9BF2FEA, 0xF94067EB, 0x2A1A03EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9,
|
||||
0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400388, 0xF9401D08, 0xAA1C03E0,
|
||||
0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0
|
||||
};
|
||||
|
||||
static u32 PRC_ID_SND_1100[] =
|
||||
static const u32 PRC_ID_SND_1100[] =
|
||||
{
|
||||
0xA9BF2FEA, 0xF94043EB, 0x5280006A, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9,
|
||||
0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF94002A8, 0xF9401D08, 0xAA1503E0,
|
||||
0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0
|
||||
};
|
||||
#define CODE_OFF_2ND_1100 (CODE_OFF_1ST_1100 + sizeof(PRC_ID_SND_1100) + sizeof(u32))
|
||||
static u32 PRC_ID_RCV_1100[] =
|
||||
static const u32 PRC_ID_RCV_1100[] =
|
||||
{
|
||||
0xA9BF2FEA, 0xF94073EB, 0x5280006A, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9,
|
||||
0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400308, 0xF9401D08, 0xAA1803E0,
|
||||
0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0
|
||||
};
|
||||
|
||||
static u32 PRC_ID_SND_1200[] =
|
||||
static const u32 PRC_ID_SND_1200[] =
|
||||
{
|
||||
0xA9BF2FEA, 0xF9404FEB, 0x5280006A, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9,
|
||||
0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF94002C8, 0xF9401D08, 0xAA1603E0,
|
||||
0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0
|
||||
};
|
||||
#define CODE_OFF_2ND_1200 (CODE_OFF_1ST_1200 + sizeof(PRC_ID_SND_1200) + sizeof(u32))
|
||||
static u32 PRC_ID_RCV_1200[] =
|
||||
static const u32 PRC_ID_RCV_1200[] =
|
||||
{
|
||||
0xA9BF2FEA, 0xF94073EB, 0x5280006A, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9,
|
||||
0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400388, 0xF9401D08, 0xAA1C03E0,
|
||||
|
@ -448,367 +448,378 @@ static const pkg2_kernel_id_t _pkg2_kernel_ids[] =
|
|||
};
|
||||
|
||||
// All kip patch offsets are without the 0x100-sized header.
|
||||
static kip1_patch_t _fs_emummc[] = {
|
||||
{ KPS(KIP_TEXT) | 1, 0, "", "" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_100[] = {
|
||||
static const kip1_patchset_t _fs_patches_100[] = {
|
||||
{ "nogc", NULL },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_40x[] = {
|
||||
{ KPS(KIP_TEXT) | 0xA3458, 4, "\x14\x40\x80\x72", "\x14\x80\x80\x72" },
|
||||
{ KPS(KIP_TEXT) | 0xAAB44, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
static const kip1_patch_t _fs_nogc_40x[] = {
|
||||
{ KPS(KIP_TEXT) | 0xA3458, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x72" },
|
||||
{ KPS(KIP_TEXT) | 0xAAB44, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_40x[] = {
|
||||
static const kip1_patchset_t _fs_patches_40x[] = {
|
||||
{ "nogc", _fs_nogc_40x },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_410[] = {
|
||||
{ KPS(KIP_TEXT) | 0xA34BC, 4, "\x14\x40\x80\x72", "\x14\x80\x80\x72" },
|
||||
{ KPS(KIP_TEXT) | 0xAABA8, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
static const kip1_patch_t _fs_nogc_410[] = {
|
||||
{ KPS(KIP_TEXT) | 0xA34BC, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x72" },
|
||||
{ KPS(KIP_TEXT) | 0xAABA8, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_410[] = {
|
||||
static const kip1_patchset_t _fs_patches_410[] = {
|
||||
{ "nogc", _fs_nogc_410 },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_50x[] = {
|
||||
{ KPS(KIP_TEXT) | 0xCF3C4, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
{ KPS(KIP_TEXT) | 0xD73A0, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
static const kip1_patch_t _fs_nogc_50x[] = {
|
||||
{ KPS(KIP_TEXT) | 0xCF3C4, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ KPS(KIP_TEXT) | 0xD73A0, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_50x[] = {
|
||||
static const kip1_patchset_t _fs_patches_50x[] = {
|
||||
{ "nogc", _fs_nogc_50x },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_510[] = {
|
||||
{ KPS(KIP_TEXT) | 0xCF794, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
{ KPS(KIP_TEXT) | 0xD7770, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
static const kip1_patch_t _fs_nogc_510[] = {
|
||||
{ KPS(KIP_TEXT) | 0xCF794, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ KPS(KIP_TEXT) | 0xD7770, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_510[] = {
|
||||
static const kip1_patchset_t _fs_patches_510[] = {
|
||||
{ "nogc", _fs_nogc_510 },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_600[] = {
|
||||
{ KPS(KIP_TEXT) | 0x12CC20, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x1538F4, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
static const kip1_patch_t _fs_nogc_600[] = {
|
||||
{ KPS(KIP_TEXT) | 0x12CC20, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x1538F4, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_600_exfat[] = {
|
||||
{ KPS(KIP_TEXT) | 0x138320, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x15EFF4, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
static const kip1_patch_t _fs_nogc_600_exfat[] = {
|
||||
{ KPS(KIP_TEXT) | 0x138320, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x15EFF4, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_600[] = {
|
||||
static const kip1_patchset_t _fs_patches_600[] = {
|
||||
{ "nogc", _fs_nogc_600 },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_600_exfat[] = {
|
||||
static const kip1_patchset_t _fs_patches_600_exfat[] = {
|
||||
{ "nogc", _fs_nogc_600_exfat },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_700[] = {
|
||||
{ KPS(KIP_TEXT) | 0x134160, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x15BF04, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
static const kip1_patch_t _fs_nogc_700[] = {
|
||||
{ KPS(KIP_TEXT) | 0x134160, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x15BF04, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_700_exfat[] = {
|
||||
{ KPS(KIP_TEXT) | 0x13F710, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x1674B4, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
static const kip1_patch_t _fs_nogc_700_exfat[] = {
|
||||
{ KPS(KIP_TEXT) | 0x13F710, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x1674B4, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_700[] = {
|
||||
static const kip1_patchset_t _fs_patches_700[] = {
|
||||
{ "nogc", _fs_nogc_700 },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_700_exfat[] = {
|
||||
static const kip1_patchset_t _fs_patches_700_exfat[] = {
|
||||
{ "nogc", _fs_nogc_700_exfat },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_800[] = {
|
||||
{ KPS(KIP_TEXT) | 0x136800, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x15EB94, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
static const kip1_patch_t _fs_nogc_800[] = {
|
||||
{ KPS(KIP_TEXT) | 0x136800, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x15EB94, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_800_exfat[] = {
|
||||
{ KPS(KIP_TEXT) | 0x141DB0, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x16A144, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
static const kip1_patch_t _fs_nogc_800_exfat[] = {
|
||||
{ KPS(KIP_TEXT) | 0x141DB0, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x16A144, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_800[] = {
|
||||
static const kip1_patchset_t _fs_patches_800[] = {
|
||||
{ "nogc", _fs_nogc_800 },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_800_exfat[] = {
|
||||
static const kip1_patchset_t _fs_patches_800_exfat[] = {
|
||||
{ "nogc", _fs_nogc_800_exfat },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_900[] = {
|
||||
{ KPS(KIP_TEXT) | 0x129420, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x143268, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
static const kip1_patch_t _fs_nogc_900[] = {
|
||||
{ KPS(KIP_TEXT) | 0x129420, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x143268, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_900[] = {
|
||||
static const kip1_patchset_t _fs_patches_900[] = {
|
||||
{ "nogc", _fs_nogc_900 },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_910[] = {
|
||||
{ KPS(KIP_TEXT) | 0x129430, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x143278, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
static const kip1_patch_t _fs_nogc_910[] = {
|
||||
{ KPS(KIP_TEXT) | 0x129430, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x143278, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_910[] = {
|
||||
static const kip1_patchset_t _fs_patches_910[] = {
|
||||
{ "nogc", _fs_nogc_910 },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_1000[] = {
|
||||
{ KPS(KIP_TEXT) | 0x13BE90, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x14DE08, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
static const kip1_patch_t _fs_nogc_1000[] = {
|
||||
{ KPS(KIP_TEXT) | 0x13BE90, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x14DE08, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_1000[] = {
|
||||
static const kip1_patchset_t _fs_patches_1000[] = {
|
||||
{ "nogc", _fs_nogc_1000 },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_1020[] = {
|
||||
{ KPS(KIP_TEXT) | 0x13C2F0, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x14E268, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
static const kip1_patch_t _fs_nogc_1020[] = {
|
||||
{ KPS(KIP_TEXT) | 0x13C2F0, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x14E268, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_1020[] = {
|
||||
static const kip1_patchset_t _fs_patches_1020[] = {
|
||||
{ "nogc", _fs_nogc_1020 },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_1100[] = {
|
||||
{ KPS(KIP_TEXT) | 0x1398B4, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x156EB8, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
static const kip1_patch_t _fs_nogc_1100[] = {
|
||||
{ KPS(KIP_TEXT) | 0x1398B4, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x156EB8, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_1100[] = {
|
||||
static const kip1_patchset_t _fs_patches_1100[] = {
|
||||
{ "nogc", _fs_nogc_1100 },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_1200[] = {
|
||||
{ KPS(KIP_TEXT) | 0x13EA24, 8, "\xFD\x7B\xBE\xA9\xF4\x4F\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x155368, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
static const kip1_patch_t _fs_nogc_1200[] = {
|
||||
{ KPS(KIP_TEXT) | 0x13EA24, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x155368, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_1200[] = {
|
||||
static const kip1_patchset_t _fs_patches_1200[] = {
|
||||
{ "nogc", _fs_nogc_1200 },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_1203[] = {
|
||||
{ KPS(KIP_TEXT) | 0x13EB34, 8, "\xFD\x7B\xBE\xA9\xF4\x4F\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x155478, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
static const kip1_patch_t _fs_nogc_1203[] = {
|
||||
{ KPS(KIP_TEXT) | 0x13EB34, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x155478, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_1203[] = {
|
||||
static const kip1_patchset_t _fs_patches_1203[] = {
|
||||
{ "nogc", _fs_nogc_1203 },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_1300[] = {
|
||||
{ KPS(KIP_TEXT) | 0x1425D0, 8, "\xFD\x7B\xBE\xA9\xF4\x4F\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x159018, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
static const kip1_patch_t _fs_nogc_1300[] = {
|
||||
{ KPS(KIP_TEXT) | 0x1425D0, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x159018, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_1300[] = {
|
||||
static const kip1_patchset_t _fs_patches_1300[] = {
|
||||
{ "nogc", _fs_nogc_1300 },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_1310[] = {
|
||||
{ KPS(KIP_TEXT) | 0x142570, 8, "\xFD\x7B\xBE\xA9\xF4\x4F\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x158FB8, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
static const kip1_patch_t _fs_nogc_1310[] = {
|
||||
{ KPS(KIP_TEXT) | 0x142570, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x158FB8, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_1310[] = {
|
||||
static const kip1_patchset_t _fs_patches_1310[] = {
|
||||
{ "nogc", _fs_nogc_1310 },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_1400[] = {
|
||||
{ KPS(KIP_TEXT) | 0x164230, 8, "\xFD\x7B\xBE\xA9\xF4\x4F\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x18A2E8, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
static const kip1_patch_t _fs_nogc_1400[] = {
|
||||
{ KPS(KIP_TEXT) | 0x164230, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x18A2E8, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_1400[] = {
|
||||
static const kip1_patchset_t _fs_patches_1400[] = {
|
||||
{ "nogc", _fs_nogc_1400 },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_1400_exfat[] = {
|
||||
{ KPS(KIP_TEXT) | 0x16F5B0, 8, "\xFD\x7B\xBE\xA9\xF4\x4F\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x195668, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
static const kip1_patch_t _fs_nogc_1400_exfat[] = {
|
||||
{ KPS(KIP_TEXT) | 0x16F5B0, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x195668, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_1400_exfat[] = {
|
||||
static const kip1_patchset_t _fs_patches_1400_exfat[] = {
|
||||
{ "nogc", _fs_nogc_1400_exfat },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_1500[] = {
|
||||
{ KPS(KIP_TEXT) | 0x15ECE4, 8, "\xFD\x7B\xBE\xA9\xF4\x4F\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x184158, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
static const kip1_patch_t _fs_nogc_1500[] = {
|
||||
{ KPS(KIP_TEXT) | 0x15ECE4, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x184158, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_1500[] = {
|
||||
static const kip1_patchset_t _fs_patches_1500[] = {
|
||||
{ "nogc", _fs_nogc_1500 },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_1500_exfat[] = {
|
||||
{ KPS(KIP_TEXT) | 0x169C74, 8, "\xFD\x7B\xBE\xA9\xF4\x4F\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x18F0E8, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
static const kip1_patch_t _fs_nogc_1500_exfat[] = {
|
||||
{ KPS(KIP_TEXT) | 0x169C74, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x18F0E8, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_1500_exfat[] = {
|
||||
static const kip1_patchset_t _fs_patches_1500_exfat[] = {
|
||||
{ "nogc", _fs_nogc_1500_exfat },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_1600[] = {
|
||||
{ KPS(KIP_TEXT) | 0x160B70, 8, "\xFD\x7B\xBE\xA9\xF4\x4F\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x1865D8, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
static const kip1_patch_t _fs_nogc_1600[] = {
|
||||
{ KPS(KIP_TEXT) | 0x160B70, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x1865D8, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_1600[] = {
|
||||
static const kip1_patchset_t _fs_patches_1600[] = {
|
||||
{ "nogc", _fs_nogc_1600 },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_1600_exfat[] = {
|
||||
{ KPS(KIP_TEXT) | 0x16B850, 8, "\xFD\x7B\xBE\xA9\xF4\x4F\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x1912B8, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
static const kip1_patch_t _fs_nogc_1600_exfat[] = {
|
||||
{ KPS(KIP_TEXT) | 0x16B850, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x1912B8, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_1600_exfat[] = {
|
||||
static const kip1_patchset_t _fs_patches_1600_exfat[] = {
|
||||
{ "nogc", _fs_nogc_1600_exfat },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_1603[] = {
|
||||
{ KPS(KIP_TEXT) | 0x160BC0, 8, "\xFD\x7B\xBE\xA9\xF4\x4F\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x186628, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
static const kip1_patch_t _fs_nogc_1603[] = {
|
||||
{ KPS(KIP_TEXT) | 0x160BC0, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x186628, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_1603[] = {
|
||||
static const kip1_patchset_t _fs_patches_1603[] = {
|
||||
{ "nogc", _fs_nogc_1603 },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_1603_exfat[] = {
|
||||
{ KPS(KIP_TEXT) | 0x16B8A0, 8, "\xFD\x7B\xBE\xA9\xF4\x4F\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x191308, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
static const kip1_patch_t _fs_nogc_1603_exfat[] = {
|
||||
{ KPS(KIP_TEXT) | 0x16B8A0, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x191308, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_1603_exfat[] = {
|
||||
static const kip1_patchset_t _fs_patches_1603_exfat[] = {
|
||||
{ "nogc", _fs_nogc_1603_exfat },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_1700[] = {
|
||||
{ KPS(KIP_TEXT) | 0x165100, 8, "\xFD\x7B\xBD\xA9\xF5\x0B\x00\xF9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x18B048, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
static const kip1_patch_t _fs_nogc_1700[] = {
|
||||
{ KPS(KIP_TEXT) | 0x165100, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x18B048, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_1700[] = {
|
||||
static const kip1_patchset_t _fs_patches_1700[] = {
|
||||
{ "nogc", _fs_nogc_1700 },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patch_t _fs_nogc_1700_exfat[] = {
|
||||
{ KPS(KIP_TEXT) | 0x16FF60, 8, "\xFD\x7B\xBD\xA9\xF5\x0B\x00\xF9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x195EA8, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
|
||||
static const kip1_patch_t _fs_nogc_1700_exfat[] = {
|
||||
{ KPS(KIP_TEXT) | 0x16FF60, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x195EA8, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static kip1_patchset_t _fs_patches_1700_exfat[] = {
|
||||
static const kip1_patchset_t _fs_patches_1700_exfat[] = {
|
||||
{ "nogc", _fs_nogc_1700_exfat },
|
||||
{ "emummc", _fs_emummc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static const kip1_patch_t _fs_nogc_1800[] = {
|
||||
{ KPS(KIP_TEXT) | 0x164A50, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x18AE48, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static const kip1_patchset_t _fs_patches_1800[] = {
|
||||
{ "nogc", _fs_nogc_1800 },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static const kip1_patch_t _fs_nogc_1800_exfat[] = {
|
||||
{ KPS(KIP_TEXT) | 0x16FAE0, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x195ED8, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static const kip1_patchset_t _fs_patches_1800_exfat[] = {
|
||||
{ "nogc", _fs_nogc_1800_exfat },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static const kip1_patch_t _fs_nogc_1900[] = {
|
||||
{ KPS(KIP_TEXT) | 0x16F070, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x195B74, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ KPS(KIP_TEXT) | 0x195D74, 4, KIP1_PATCH_SRC_NO_CHECK, "\x16\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static const kip1_patchset_t _fs_patches_1900[] = {
|
||||
{ "nogc", _fs_nogc_1900 },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static const kip1_patch_t _fs_nogc_1900_exfat[] = {
|
||||
{ KPS(KIP_TEXT) | 0x17A8A0, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||
{ KPS(KIP_TEXT) | 0x1A13A4, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||
{ KPS(KIP_TEXT) | 0x1A15A4, 4, KIP1_PATCH_SRC_NO_CHECK, "\x16\x80\x80\x52" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static const kip1_patchset_t _fs_patches_1900_exfat[] = {
|
||||
{ "nogc", _fs_nogc_1900_exfat },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
// SHA256 hashes.
|
||||
static kip1_id_t _kip_ids[] =
|
||||
static const kip1_id_t _kip_ids[] =
|
||||
{
|
||||
{ "FS", "\xde\x9f\xdd\xa4\x08\x5d\xd5\xfe", _fs_patches_100 }, // FS 1.0.0
|
||||
{ "FS", "\xfc\x3e\x80\x99\x1d\xca\x17\x96", _fs_patches_100 }, // FS 1.0.0 exFAT
|
||||
|
@ -866,4 +877,10 @@ static kip1_id_t _kip_ids[] =
|
|||
{ "FS", "\x62\xC6\x5E\xFD\x9A\xBF\x7C\x43", _fs_patches_1603_exfat }, // FS 16.0.3 exFAT
|
||||
{ "FS", "\x27\x07\x3B\xF0\xA1\xB8\xCE\x61", _fs_patches_1700 }, // FS 17.0.0
|
||||
{ "FS", "\xEE\x0F\x4B\xAC\x6D\x1F\xFC\x4B", _fs_patches_1700_exfat }, // FS 17.0.0 exFAT
|
||||
{ "FS", "\x79\x5F\x5A\x5E\xB0\xC6\x77\x9E", _fs_patches_1800 }, // FS 18.0.0
|
||||
{ "FS", "\x1E\x2C\x64\xB1\xCC\xE2\x78\x24", _fs_patches_1800_exfat }, // FS 18.0.0 exFAT
|
||||
{ "FS", "\xA3\x39\xF0\x1C\x95\xBF\xA7\x68", _fs_patches_1800 }, // FS 18.1.0
|
||||
{ "FS", "\x20\x4C\xBA\x86\xDE\x08\x44\x6A", _fs_patches_1800_exfat }, // FS 18.1.0 exFAT
|
||||
{ "FS", "\xD9\x4C\x68\x15\xF8\xF5\x0A\x20", _fs_patches_1900 }, // FS 19.0.0
|
||||
{ "FS", "\xED\xA8\x78\x68\xA4\x49\x07\x50", _fs_patches_1900_exfat }, // FS 19.0.0 exFAT
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2023 CTCaer
|
||||
* Copyright (c) 2018-2024 CTCaer
|
||||
* Copyright (c) 2019 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
@ -156,28 +156,24 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base)
|
|||
|
||||
//! TODO: Replace current HOS version decoding (as it's bound to break in the future).
|
||||
|
||||
// Old exosphere target versioning. Use fuses for a simpler decoding.
|
||||
if (ctxt->pkg1_id->fuses <= 3 || ctxt->pkg1_id->fuses >= 10) // 1.0.0 - 3.0.0, 8.1.0+.
|
||||
// Old exosphere target versioning.
|
||||
if (ctxt->pkg1_id->kb >= HOS_KB_VERSION_1210) // 12.1.0+
|
||||
exo_fw_no = ctxt->pkg1_id->kb + 4;
|
||||
else if (ctxt->pkg1_id->fuses <= 3 || ctxt->pkg1_id->fuses >= 10) // 1.0.0 - 3.0.0, 8.1.0 - 12.0.3.
|
||||
exo_fw_no = ctxt->pkg1_id->fuses;
|
||||
else
|
||||
exo_fw_no = ctxt->pkg1_id->fuses - 1; // 3.0.1 - 7.0.1, 8.0.x.
|
||||
exo_fw_no = ctxt->pkg1_id->fuses - 1; // 3.0.1 - 7.0.1, 8.0.x.
|
||||
|
||||
// Handle versions that change API and do not burn new fuse.
|
||||
if (!memcmp(ctxt->pkg1_id->id, "20190314", 8) || // 8.0.x, same fuses with 7.0.1.
|
||||
!memcmp(ctxt->pkg1_id->id, "20210129", 8) // 12.0.0, same fuses with 11.0.0.
|
||||
)
|
||||
exo_fw_no++;
|
||||
|
||||
// Set 12.1.0 specific revision.
|
||||
if (ctxt->pkg1_id->kb == HOS_KB_VERSION_1210)
|
||||
ctxt->exo_ctx.hos_revision = 1;
|
||||
|
||||
// Handle 15.0.0+.
|
||||
if (ctxt->pkg1_id->fuses >= 17)
|
||||
exo_fw_no++;
|
||||
|
||||
// Handle versions that change API and do not burn new fuse.
|
||||
if (!memcmp(ctxt->pkg1_id->id, "20190314", 8) || // 8.0.x, same fuses with 7.0.1.
|
||||
!memcmp(ctxt->pkg1_id->id, "20210129", 8) || // 12.0.0, same fuses with 11.0.0.
|
||||
!memcmp(ctxt->pkg1_id->id, "20210805", 8) || // 13.0.0, same fuses with 12.1.0.
|
||||
!memcmp(ctxt->pkg1_id->id, "20220209", 8) // 14.0.0, same fuses with 13.2.1.
|
||||
)
|
||||
exo_fw_no++;
|
||||
|
||||
// Feed old exosphere target versioning to new.
|
||||
switch (exo_fw_no)
|
||||
{
|
||||
|
@ -203,7 +199,7 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base)
|
|||
case 12:
|
||||
exo_fw_no = EXO_FW_VER(9, 1);
|
||||
break;
|
||||
case 13 ... 20: //!TODO: Update on API changes. 20: 17.0.0.
|
||||
case 13 ... 22: //!TODO: Update on API changes. 22: 19.0.0.
|
||||
exo_fw_no = EXO_FW_VER(exo_fw_no - 3, ctxt->exo_ctx.hos_revision);
|
||||
break;
|
||||
}
|
||||
|
@ -211,10 +207,10 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base)
|
|||
// Parse exosphere.ini.
|
||||
if (!ctxt->stock)
|
||||
{
|
||||
LIST_INIT(ini_sections);
|
||||
if (ini_parse(&ini_sections, "exosphere.ini", false))
|
||||
LIST_INIT(ini_exo_sections);
|
||||
if (ini_parse(&ini_exo_sections, "exosphere.ini", false))
|
||||
{
|
||||
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
|
||||
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_exo_sections, link)
|
||||
{
|
||||
// Only parse exosphere section.
|
||||
if (!(ini_sec->type == INI_CHOICE) || strcmp(ini_sec->name, "exosphere"))
|
||||
|
@ -245,32 +241,29 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base)
|
|||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse usb mtim settings. Avoid parsing if it's overridden.
|
||||
if (ctxt->fss0_main_path && !ctxt->exo_ctx.usb3_force)
|
||||
{
|
||||
char settings_path[256];
|
||||
strcpy(settings_path, ctxt->fss0_main_path);
|
||||
strcat(settings_path, "config/system_settings.ini");
|
||||
LIST_INIT(sys_settings);
|
||||
if (ini_parse(&ini_sections, settings_path, false))
|
||||
// Parse usb mtim settings. Avoid parsing if it's overridden.
|
||||
if (!ctxt->exo_ctx.usb3_force)
|
||||
{
|
||||
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
|
||||
LIST_INIT(ini_sys_sections);
|
||||
if (ini_parse(&ini_sys_sections, "atmosphere/config/system_settings.ini", false))
|
||||
{
|
||||
// Only parse usb section.
|
||||
if (!(ini_sec->type == INI_CHOICE) || strcmp(ini_sec->name, "usb"))
|
||||
continue;
|
||||
|
||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
|
||||
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sys_sections, link)
|
||||
{
|
||||
if (!strcmp("usb30_force_enabled", kv->key))
|
||||
// Only parse usb section.
|
||||
if (!(ini_sec->type == INI_CHOICE) || strcmp(ini_sec->name, "usb"))
|
||||
continue;
|
||||
|
||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
|
||||
{
|
||||
usb3_force = !strcmp("u8!0x1", kv->val);
|
||||
break; // Only parse usb30_force_enabled key.
|
||||
if (!strcmp("usb30_force_enabled", kv->key))
|
||||
{
|
||||
usb3_force = !strcmp("u8!0x1", kv->val);
|
||||
break; // Only parse usb30_force_enabled key.
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -416,7 +409,7 @@ void secmon_exo_check_panic()
|
|||
// Save context to the SD card.
|
||||
char filepath[0x40];
|
||||
f_mkdir("atmosphere/fatal_errors");
|
||||
strcpy(filepath, "/atmosphere/fatal_errors/report_");
|
||||
strcpy(filepath, "atmosphere/fatal_errors/report_");
|
||||
itoa((u32)((u64)rpt->report_identifier >> 32), filepath + strlen(filepath), 16);
|
||||
itoa((u32)(rpt->report_identifier), filepath + strlen(filepath), 16);
|
||||
strcat(filepath, ".bin");
|
||||
|
|
|
@ -33,9 +33,14 @@
|
|||
* 1: SDMMC1 LA programming for SDMMC1 UHS DDR200.
|
||||
* 2: Arachne Register Cell v1.
|
||||
* 3: Arachne Register Cell v2. PTSA Rework support.
|
||||
* 4: Arachne Register Cell v3. DRAM OPT and DDR200 changes.
|
||||
* 5: Arachne Register Cell v4. DRAM FREQ and DDR200 changes.
|
||||
* 6: Arachne Register Cell v5. Signal quality and performance changes. TZ param changes.
|
||||
* 7: Arachne Register Cell v6. Decouple of rd/wr latencies.
|
||||
*/
|
||||
#define L4T_LOADER_API_REV 4
|
||||
#define L4T_FIRMWARE_REV 0x34524556 // REV4.
|
||||
|
||||
#define L4T_LOADER_API_REV 7
|
||||
#define L4T_FIRMWARE_REV 0x37524556 // REV7.
|
||||
|
||||
#ifdef DEBUG_UART_PORT
|
||||
#include <soc/uart.h>
|
||||
|
@ -49,16 +54,18 @@
|
|||
#endif
|
||||
|
||||
#if CARVEOUT_NVDEC_TSEC_ENABLE
|
||||
#define TZ_SIZE SZ_8M
|
||||
#define TZDRAM_SIZE_CFG SZ_8M
|
||||
#else
|
||||
#define TZ_SIZE SZ_1M
|
||||
#define TZDRAM_SIZE_CFG SZ_1M
|
||||
#endif
|
||||
|
||||
// TZDRAM addresses and sizes.
|
||||
#define TZDRAM_SIZE TZ_SIZE // Secure Element.
|
||||
#define TZDRAM_BASE (0xFFFFFFFF - TZDRAM_SIZE + 1) // 0xFFF00000 or 0xFF800000.
|
||||
#define TZDRAM_SIZE TZDRAM_SIZE_CFG // Secure Element.
|
||||
#define TZDRAM_BASE (0xFFFFFFFF - TZDRAM_SIZE + 1) // 0xFFF00000 or 0xFF800000.
|
||||
#define TZDRAM_COLD_ENTRY (TZDRAM_BASE)
|
||||
#define TZDRAM_WARM_ENTRY (TZDRAM_BASE + 0x200)
|
||||
#define TZ_PARAM_SIZE SZ_4K
|
||||
#define TZ_PARAM_BASE (0xFFFFFFFF - TZ_PARAM_SIZE + 1) // 0xFFFFF000.
|
||||
|
||||
// Carveout sizes.
|
||||
#define CARVEOUT_NVDEC_SIZE SZ_1M
|
||||
|
@ -73,8 +80,14 @@
|
|||
|
||||
#define SC7ENTRY_HDR_SIZE 0x400
|
||||
|
||||
// Always start 1MB below TZDRAM for Secure Firmware or NVDEC.
|
||||
#define GEN_CARVEOUT_TOP (TZDRAM_BASE - SZ_1M)
|
||||
|
||||
// NVDEC and SECFW bases.
|
||||
#define NVDFW_BASE GEN_CARVEOUT_TOP // 0xFF700000.
|
||||
#define SECFW_BASE GEN_CARVEOUT_TOP // 0xFFE00000.
|
||||
|
||||
// Secure Elements addresses for T210.
|
||||
#define SECFW_BASE (TZDRAM_BASE - SZ_1M) // 0xFFE00000 or 0xFF700000.
|
||||
#define SC7ENTRY_HDR_BASE (SECFW_BASE + 0)
|
||||
#define SC7ENTRY_BASE (SECFW_BASE + SC7ENTRY_HDR_SIZE) // After header.
|
||||
#define SC7EXIT_BASE (SECFW_BASE + SZ_64K) // 64KB after SECFW_BASE.
|
||||
|
@ -211,7 +224,7 @@ typedef struct _bl_v1_params {
|
|||
u64 bl32_image_info;
|
||||
u64 bl33_ep_info;
|
||||
u64 bl33_image_info;
|
||||
} bl_v1_params_t;
|
||||
} bl31_v1_params_t;
|
||||
|
||||
typedef struct _plat_params_from_bl2 {
|
||||
// TZDRAM.
|
||||
|
@ -240,7 +253,7 @@ typedef struct _plat_params_from_bl2 {
|
|||
u64 r2p_payload_base;
|
||||
|
||||
u64 flags; // Platform flags.
|
||||
} plat_params_from_bl2_t;
|
||||
} bl31_plat_params_from_bl2_t;
|
||||
|
||||
typedef struct _l4t_fw_t
|
||||
{
|
||||
|
@ -262,6 +275,10 @@ typedef struct _l4t_ctxt_t
|
|||
u32 sc7entry_size;
|
||||
|
||||
emc_table_t *mtc_table;
|
||||
|
||||
bl31_v1_params_t bl31_v1_params;
|
||||
bl31_plat_params_from_bl2_t bl31_plat_params;
|
||||
entry_point_info_t bl33_ep_info;
|
||||
} l4t_ctxt_t;
|
||||
|
||||
#define DRAM_VDD2_OC_MIN_VOLTAGE 1050
|
||||
|
@ -480,7 +497,7 @@ static void _l4t_mc_config_carveout(bool t210b01)
|
|||
UPRINTF("TZD: TZDRAM Carveout: %08X - %08X\n", TZDRAM_BASE, TZDRAM_BASE - 1 + TZDRAM_SIZE);
|
||||
|
||||
// Configure generalized security carveouts.
|
||||
u32 carveout_base = TZDRAM_BASE - SZ_1M; // Always leave space for Secure Firmware.
|
||||
u32 carveout_base = GEN_CARVEOUT_TOP;
|
||||
|
||||
#if CARVEOUT_NVDEC_TSEC_ENABLE
|
||||
|
||||
|
@ -546,8 +563,10 @@ static void _l4t_mc_config_carveout(bool t210b01)
|
|||
MC(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS2) = 0;
|
||||
MC(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS3) = 0;
|
||||
MC(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS4) = 0;
|
||||
MC(MC_SECURITY_CARVEOUT1_CFG0) = SEC_CARVEOUT_CFG_RD_NS |
|
||||
SEC_CARVEOUT_CFG_WR_NS |
|
||||
MC(MC_SECURITY_CARVEOUT1_CFG0) = SEC_CARVEOUT_CFG_RD_NS |
|
||||
SEC_CARVEOUT_CFG_RD_SEC |
|
||||
SEC_CARVEOUT_CFG_WR_NS |
|
||||
SEC_CARVEOUT_CFG_WR_SEC |
|
||||
SEC_CARVEOUT_CFG_LOCKED;
|
||||
UPRINTF("GSC1: SECFW Carveout: %08X - %08X\n",
|
||||
MC(MC_SECURITY_CARVEOUT1_BOM), MC(MC_SECURITY_CARVEOUT1_BOM) + MC(MC_SECURITY_CARVEOUT1_SIZE_128KB) * SZ_128K);
|
||||
|
@ -833,7 +852,7 @@ static int _l4t_sc7_exit_config(bool t210b01)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void _l4t_bl33_cfg_set_key(char *env, char *key, char *val)
|
||||
static void _l4t_bl33_cfg_set_key(char *env, const char *key, const char *val)
|
||||
{
|
||||
strcat(env, key);
|
||||
strcat(env, "=");
|
||||
|
@ -907,7 +926,7 @@ static void _l4t_set_config(l4t_ctxt_t *ctxt, const ini_sec_t *ini_sec, int entr
|
|||
_l4t_bl33_cfg_set_key(bl33_env, "autoboot_list", val);
|
||||
|
||||
val[0] = '0' + L4T_LOADER_API_REV;
|
||||
_l4t_bl33_cfg_set_key(bl33_env, "loader_rev", val);
|
||||
_l4t_bl33_cfg_set_key(bl33_env, "loader_rev", val);
|
||||
|
||||
// Enable BL33 memory env import.
|
||||
*(u32 *)(BL33_ENV_MAGIC_OFFSET) = BL33_ENV_MAGIC;
|
||||
|
@ -920,25 +939,23 @@ static void _l4t_set_config(l4t_ctxt_t *ctxt, const ini_sec_t *ini_sec, int entr
|
|||
|
||||
void launch_l4t(const ini_sec_t *ini_sec, int entry_idx, int is_list, bool t210b01)
|
||||
{
|
||||
l4t_ctxt_t ctxt = {0};
|
||||
bl_v1_params_t bl_v1_params = {0};
|
||||
plat_params_from_bl2_t plat_params = {0};
|
||||
entry_point_info_t bl33_ep_info = {0};
|
||||
l4t_ctxt_t *ctxt = (l4t_ctxt_t *)TZ_PARAM_BASE;
|
||||
memset(ctxt, 0, TZ_PARAM_SIZE);
|
||||
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
// Parse config.
|
||||
_l4t_set_config(&ctxt, ini_sec, entry_idx, is_list, t210b01);
|
||||
_l4t_set_config(ctxt, ini_sec, entry_idx, is_list, t210b01);
|
||||
|
||||
if (!ctxt.path)
|
||||
if (!ctxt->path)
|
||||
{
|
||||
_l4t_crit_error("Path missing", false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get MTC table.
|
||||
ctxt.mtc_table = minerva_get_mtc_table();
|
||||
if (!t210b01 && !ctxt.mtc_table)
|
||||
ctxt->mtc_table = minerva_get_mtc_table();
|
||||
if (!t210b01 && !ctxt->mtc_table)
|
||||
{
|
||||
_l4t_crit_error("Minerva missing", true);
|
||||
return;
|
||||
|
@ -965,8 +982,8 @@ void launch_l4t(const ini_sec_t *ini_sec, int entry_idx, int is_list, bool t210b
|
|||
if (!t210b01)
|
||||
{
|
||||
// Load SC7-Entry firmware.
|
||||
ctxt.sc7entry_size = _l4t_sd_load(SC7ENTRY_FW);
|
||||
if (!ctxt.sc7entry_size)
|
||||
ctxt->sc7entry_size = _l4t_sd_load(SC7ENTRY_FW);
|
||||
if (!ctxt->sc7entry_size)
|
||||
{
|
||||
_l4t_crit_error("loading SC7-Entry", true);
|
||||
return;
|
||||
|
@ -1014,10 +1031,10 @@ void launch_l4t(const ini_sec_t *ini_sec, int entry_idx, int is_list, bool t210b
|
|||
mc_disable_ahb_redirect();
|
||||
|
||||
// Enable debug port.
|
||||
if (ctxt.serial_port)
|
||||
if (ctxt->serial_port)
|
||||
{
|
||||
pinmux_config_uart(ctxt.serial_port - 1);
|
||||
clock_enable_uart(ctxt.serial_port - 1);
|
||||
pinmux_config_uart(ctxt->serial_port - 1);
|
||||
clock_enable_uart(ctxt->serial_port - 1);
|
||||
}
|
||||
|
||||
// Restore UARTB/C TX pins to SPIO.
|
||||
|
@ -1029,7 +1046,7 @@ void launch_l4t(const ini_sec_t *ini_sec, int entry_idx, int is_list, bool t210b
|
|||
{
|
||||
// Defaults are for UARTA.
|
||||
char *bl33_serial_port = NULL;
|
||||
switch (ctxt.serial_port)
|
||||
switch (ctxt->serial_port)
|
||||
{
|
||||
case 0: // Disable.
|
||||
break;
|
||||
|
@ -1048,41 +1065,41 @@ void launch_l4t(const ini_sec_t *ini_sec, int entry_idx, int is_list, bool t210b
|
|||
{
|
||||
BL33_DTB_SET_STDOUT_PATH(bl33_serial_port);
|
||||
BL33_DTB_SET_STDERR_PATH(bl33_serial_port);
|
||||
BL33_DTB_SET_UART_STATUS(ctxt.serial_port);
|
||||
BL33_DTB_SET_UART_STATUS(ctxt->serial_port);
|
||||
}
|
||||
}
|
||||
|
||||
// Set BL31 params.
|
||||
bl_v1_params.hdr.type = PARAM_BL31;
|
||||
bl_v1_params.hdr.version = VERSION_1;
|
||||
bl_v1_params.hdr.size = sizeof(bl_v1_params_t);
|
||||
bl_v1_params.hdr.attr = PARAM_EP_SECURE;
|
||||
bl_v1_params.bl33_ep_info = (u64)(u32)&bl33_ep_info;
|
||||
ctxt->bl31_v1_params.hdr.type = PARAM_BL31;
|
||||
ctxt->bl31_v1_params.hdr.version = VERSION_1;
|
||||
ctxt->bl31_v1_params.hdr.size = sizeof(bl31_v1_params_t);
|
||||
ctxt->bl31_v1_params.hdr.attr = PARAM_EP_SECURE;
|
||||
ctxt->bl31_v1_params.bl33_ep_info = (u64)(u32)&ctxt->bl33_ep_info;
|
||||
|
||||
// Set BL33 params.
|
||||
bl33_ep_info.hdr.type = PARAM_EP;
|
||||
bl33_ep_info.hdr.version = VERSION_1;
|
||||
bl33_ep_info.hdr.size = sizeof(entry_point_info_t);
|
||||
bl33_ep_info.hdr.attr = PARAM_EP_NON_SECURE;
|
||||
bl33_ep_info.pc = BL33_LOAD_BASE;
|
||||
bl33_ep_info.spsr = SPSR_EL2T;
|
||||
ctxt->bl33_ep_info.hdr.type = PARAM_EP;
|
||||
ctxt->bl33_ep_info.hdr.version = VERSION_1;
|
||||
ctxt->bl33_ep_info.hdr.size = sizeof(entry_point_info_t);
|
||||
ctxt->bl33_ep_info.hdr.attr = PARAM_EP_NON_SECURE;
|
||||
ctxt->bl33_ep_info.pc = BL33_LOAD_BASE;
|
||||
ctxt->bl33_ep_info.spsr = SPSR_EL2T;
|
||||
|
||||
// Set Platform parameters.
|
||||
plat_params.tzdram_base = TZDRAM_BASE;
|
||||
plat_params.tzdram_size = TZDRAM_SIZE;
|
||||
ctxt->bl31_plat_params.tzdram_base = TZDRAM_BASE;
|
||||
ctxt->bl31_plat_params.tzdram_size = TZDRAM_SIZE;
|
||||
#if DEBUG_LOG_ATF
|
||||
plat_params.uart_id = ctxt.serial_port;
|
||||
ctxt->bl31_plat_params.uart_id = ctxt->serial_port;
|
||||
#endif
|
||||
|
||||
if (!t210b01)
|
||||
{
|
||||
// Set SC7-Entry fw parameters. For now BPMP-FW is not used on T210.
|
||||
plat_params.sc7entry_fw_base = SC7ENTRY_HDR_BASE;
|
||||
plat_params.sc7entry_fw_size = ALIGN(ctxt.sc7entry_size + SC7ENTRY_HDR_SIZE, SZ_PAGE);
|
||||
ctxt->bl31_plat_params.sc7entry_fw_base = SC7ENTRY_HDR_BASE;
|
||||
ctxt->bl31_plat_params.sc7entry_fw_size = ALIGN(ctxt->sc7entry_size + SC7ENTRY_HDR_SIZE, SZ_PAGE);
|
||||
}
|
||||
|
||||
// Enable below features.
|
||||
plat_params.enable_extra_features = BL31_EXTRA_FEATURES_ENABLE;
|
||||
ctxt->bl31_plat_params.enable_extra_features = BL31_EXTRA_FEATURES_ENABLE;
|
||||
|
||||
if (!t210b01)
|
||||
{
|
||||
|
@ -1092,37 +1109,37 @@ void launch_l4t(const ini_sec_t *ini_sec, int entry_idx, int is_list, bool t210b
|
|||
memset((u8 *)R2P_PAYLOAD_BASE + 0x94, 0, sizeof(boot_cfg_t)); // Clear Boot Config Storage.
|
||||
|
||||
// Set R2P payload fw parameters.
|
||||
plat_params.r2p_payload_base = R2P_PAYLOAD_BASE;
|
||||
plat_params.r2p_payload_size = ALIGN(reloc->end - reloc->start, SZ_PAGE);
|
||||
ctxt->bl31_plat_params.r2p_payload_base = R2P_PAYLOAD_BASE;
|
||||
ctxt->bl31_plat_params.r2p_payload_size = ALIGN(reloc->end - reloc->start, SZ_PAGE);
|
||||
}
|
||||
|
||||
// Set PMC access security. NS is mandatory for T210B01.
|
||||
plat_params.flags = FLAGS_PMC_NON_SECURE; // Unsecure it unconditionally to reduce SMC calls to a minimum.
|
||||
ctxt->bl31_plat_params.flags = FLAGS_PMC_NON_SECURE; // Unsecure it unconditionally to reduce SMC calls to a minimum.
|
||||
// Lift SC7 placement restrictions. Disables TZDRAM increased carveout too.
|
||||
plat_params.flags |= FLAGS_SC7_NO_BASE_RESTRICTION;
|
||||
ctxt->bl31_plat_params.flags |= FLAGS_SC7_NO_BASE_RESTRICTION;
|
||||
|
||||
// Prepare EMC table.
|
||||
if (ctxt.mtc_table)
|
||||
if (ctxt->mtc_table)
|
||||
{
|
||||
// Set DRAM voltage.
|
||||
if (ctxt.ram_oc_vdd2)
|
||||
max7762x_regulator_set_voltage(REGULATOR_SD1, ctxt.ram_oc_vdd2 * 1000);
|
||||
if (ctxt->ram_oc_vdd2)
|
||||
max7762x_regulator_set_voltage(REGULATOR_SD1, ctxt->ram_oc_vdd2 * 1000);
|
||||
|
||||
// Train the rest of the table, apply FSP WAR, set RAM to 800 MHz.
|
||||
minerva_prep_boot_l4t(ctxt.ram_oc_freq, ctxt.ram_oc_opt);
|
||||
minerva_prep_boot_l4t(ctxt->ram_oc_freq, ctxt->ram_oc_opt);
|
||||
|
||||
// Set emc table parameters and copy it.
|
||||
int table_entries = minerva_get_mtc_table_entries();
|
||||
plat_params.emc_table_base = MTCTABLE_BASE;
|
||||
plat_params.emc_table_size = sizeof(emc_table_t) * table_entries;
|
||||
memcpy((u32 *)MTCTABLE_BASE, ctxt.mtc_table, sizeof(emc_table_t) * table_entries);
|
||||
ctxt->bl31_plat_params.emc_table_base = MTCTABLE_BASE;
|
||||
ctxt->bl31_plat_params.emc_table_size = sizeof(emc_table_t) * table_entries;
|
||||
memcpy((u32 *)MTCTABLE_BASE, ctxt->mtc_table, sizeof(emc_table_t) * table_entries);
|
||||
}
|
||||
|
||||
// Set and enable IRAM based BL31 config.
|
||||
PMC(APBDEV_PMC_SECURE_SCRATCH112) = PMC(APBDEV_PMC_SECURE_SCRATCH108);
|
||||
PMC(APBDEV_PMC_SECURE_SCRATCH114) = PMC(APBDEV_PMC_SECURE_SCRATCH109);
|
||||
PMC(APBDEV_PMC_SECURE_SCRATCH108) = (u32)&bl_v1_params;
|
||||
PMC(APBDEV_PMC_SECURE_SCRATCH109) = (u32)&plat_params;
|
||||
PMC(APBDEV_PMC_SECURE_SCRATCH108) = (u32)&ctxt->bl31_v1_params;
|
||||
PMC(APBDEV_PMC_SECURE_SCRATCH109) = (u32)&ctxt->bl31_plat_params;
|
||||
PMC(APBDEV_PMC_SECURE_SCRATCH110) = BL31_IRAM_PARAMS;
|
||||
|
||||
// Set panel model.
|
||||
|
@ -1142,13 +1159,13 @@ void launch_l4t(const ini_sec_t *ini_sec, int entry_idx, int is_list, bool t210b
|
|||
|
||||
// Set BPMP-FW parameters.
|
||||
if (t210b01)
|
||||
_l4t_bpmpfw_b01_config(&ctxt);
|
||||
_l4t_bpmpfw_b01_config(ctxt);
|
||||
|
||||
// Set carveouts and save them to PMC for SC7 Exit.
|
||||
_l4t_mc_config_carveout(t210b01);
|
||||
|
||||
// Deinit any unneeded HW.
|
||||
hw_reinit_workaround(false, BL_MAGIC_L4TLDR_SLD);
|
||||
hw_deinit(false, BL_MAGIC_L4TLDR_SLD);
|
||||
|
||||
// Do late hardware config.
|
||||
_l4t_late_hw_config(t210b01);
|
||||
|
@ -1156,7 +1173,7 @@ void launch_l4t(const ini_sec_t *ini_sec, int entry_idx, int is_list, bool t210b
|
|||
if (t210b01)
|
||||
{
|
||||
// Launch BL31.
|
||||
ccplex_boot_cpu0(TZDRAM_COLD_ENTRY);
|
||||
ccplex_boot_cpu0(TZDRAM_COLD_ENTRY, true);
|
||||
|
||||
// Enable Wrap burst for BPMP, GPU and PCIE.
|
||||
MSELECT(MSELECT_CONFIG) = (MSELECT(MSELECT_CONFIG) & (~(MSELECT_CFG_ERR_RESP_EN_GPU | MSELECT_CFG_ERR_RESP_EN_PCIE))) |
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
/*------------------------------------------------------------------------*/
|
||||
/* Sample Code of OS Dependent Functions for FatFs */
|
||||
/* (C) ChaN, 2018 */
|
||||
/* (C) CTCaer, 2018 */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
#include <bdk.h>
|
||||
|
||||
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Allocate a memory block */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
void* ff_memalloc ( /* Returns pointer to the allocated memory block (null if not enough core) */
|
||||
UINT msize /* Number of bytes to allocate */
|
||||
)
|
||||
{
|
||||
return malloc(msize); /* Allocate a new memory block with POSIX API */
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Free a memory block */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
void ff_memfree (
|
||||
void* mblock /* Pointer to the memory block to free (nothing to do if null) */
|
||||
)
|
||||
{
|
||||
free(mblock); /* Free the memory block with POSIX API */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
*
|
||||
* Copyright (c) 2018-2023 CTCaer
|
||||
* Copyright (c) 2018-2024 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,
|
||||
|
@ -39,51 +39,14 @@ hekate_config h_cfg;
|
|||
boot_cfg_t __attribute__((section ("._boot_cfg"))) b_cfg;
|
||||
const volatile ipl_ver_meta_t __attribute__((section ("._ipl_version"))) ipl_ver = {
|
||||
.magic = BL_MAGIC,
|
||||
.version = (BL_VER_MJ + '0') | ((BL_VER_MN + '0') << 8) | ((BL_VER_HF + '0') << 16),
|
||||
.version = (BL_VER_MJ + '0') | ((BL_VER_MN + '0') << 8) | ((BL_VER_HF + '0') << 16) | ((BL_VER_RL) << 24),
|
||||
.rsvd0 = 0,
|
||||
.rsvd1 = 0
|
||||
};
|
||||
|
||||
volatile nyx_storage_t *nyx_str = (nyx_storage_t *)NYX_STORAGE_ADDR;
|
||||
|
||||
void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage)
|
||||
{
|
||||
static char emmc_sn[9] = {0};
|
||||
|
||||
// Check if not valid S/N and get actual eMMC S/N.
|
||||
if (!storage && !emmc_sn[0])
|
||||
{
|
||||
if (!emmc_initialize(false))
|
||||
strcpy(emmc_sn, "00000000");
|
||||
else
|
||||
{
|
||||
itoa(emmc_storage.cid.serial, emmc_sn, 16);
|
||||
emmc_end();
|
||||
}
|
||||
}
|
||||
else
|
||||
itoa(storage->cid.serial, emmc_sn, 16);
|
||||
|
||||
// Create main folder.
|
||||
strcpy(path, "backup");
|
||||
f_mkdir(path);
|
||||
|
||||
// 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.
|
||||
}
|
||||
|
||||
void check_power_off_from_hos()
|
||||
static void _check_power_off_from_hos()
|
||||
{
|
||||
// Power off on alarm wakeup from HOS shutdown. For modchips/dongles.
|
||||
u8 hos_wakeup = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_IRQTOP);
|
||||
|
@ -157,7 +120,7 @@ static void _reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size)
|
|||
}
|
||||
}
|
||||
|
||||
bool is_ipl_updated(void *buf, char *path, bool force)
|
||||
bool is_ipl_updated(void *buf, const char *path, bool force)
|
||||
{
|
||||
ipl_ver_meta_t *update_ft = (ipl_ver_meta_t *)(buf + PATCHED_RELOC_SZ + sizeof(boot_cfg_t));
|
||||
|
||||
|
@ -175,8 +138,7 @@ bool is_ipl_updated(void *buf, char *path, bool force)
|
|||
{
|
||||
FIL fp;
|
||||
reloc_meta_t *reloc = (reloc_meta_t *)(IPL_LOAD_ADDR + RELOC_META_OFF);
|
||||
boot_cfg_t *tmp_cfg = malloc(sizeof(boot_cfg_t));
|
||||
memset(tmp_cfg, 0, sizeof(boot_cfg_t));
|
||||
boot_cfg_t *tmp_cfg = zalloc(sizeof(boot_cfg_t));
|
||||
|
||||
f_open(&fp, path, FA_WRITE | FA_CREATE_ALWAYS);
|
||||
f_write(&fp, (u8 *)reloc->start, reloc->end - reloc->start, NULL);
|
||||
|
@ -252,7 +214,7 @@ static void _launch_payload(char *path, bool update, bool clear_screen)
|
|||
else
|
||||
_reloc_patcher(PATCHED_RELOC_ENTRY, EXT_PAYLOAD_ADDR, ALIGN(size, 0x10));
|
||||
|
||||
hw_reinit_workaround(false, byte_swap_32(*(u32 *)(buf + size - sizeof(u32))));
|
||||
hw_deinit(false, byte_swap_32(*(u32 *)(buf + size - sizeof(u32))));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -262,18 +224,20 @@ static void _launch_payload(char *path, bool update, bool clear_screen)
|
|||
u32 magic = 0;
|
||||
char *magic_ptr = buf + COREBOOT_VER_OFF;
|
||||
memcpy(&magic, magic_ptr + strlen(magic_ptr) - 4, 4);
|
||||
hw_reinit_workaround(true, magic);
|
||||
hw_deinit(true, magic);
|
||||
}
|
||||
|
||||
// Some cards (Sandisk U1), do not like a fast power cycle. Wait min 100ms.
|
||||
sdmmc_storage_init_wait_sd();
|
||||
|
||||
void (*update_ptr)() = (void *)RCM_PAYLOAD_ADDR;
|
||||
void (*ext_payload_ptr)() = (void *)EXT_PAYLOAD_ADDR;
|
||||
|
||||
// Launch our payload.
|
||||
if (!update)
|
||||
{
|
||||
// Some cards (Sandisk U1), do not like a fast power cycle. Wait min 100ms.
|
||||
sdmmc_storage_init_wait_sd();
|
||||
|
||||
(*ext_payload_ptr)();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set updated flag to skip check on launch.
|
||||
|
@ -292,20 +256,18 @@ out:
|
|||
static void _launch_payloads()
|
||||
{
|
||||
u8 max_entries = 61;
|
||||
char *filelist = NULL;
|
||||
ment_t *ments = NULL;
|
||||
char *file_sec = NULL;
|
||||
char *dir = NULL;
|
||||
|
||||
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (max_entries + 3));
|
||||
dirlist_t *filelist = NULL;
|
||||
|
||||
gfx_clear_grey(0x1B);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
if (!sd_mount())
|
||||
{
|
||||
free(ments);
|
||||
goto failed_sd_mount;
|
||||
}
|
||||
|
||||
ments = (ment_t *)malloc(sizeof(ment_t) * (max_entries + 3));
|
||||
|
||||
dir = (char *)malloc(256);
|
||||
memcpy(dir, "bootloader/payloads", 20);
|
||||
|
@ -324,11 +286,11 @@ static void _launch_payloads()
|
|||
|
||||
while (true)
|
||||
{
|
||||
if (i > max_entries || !filelist[i * 256])
|
||||
if (i > max_entries || !filelist->name[i])
|
||||
break;
|
||||
ments[i + 2].type = INI_CHOICE;
|
||||
ments[i + 2].caption = &filelist[i * 256];
|
||||
ments[i + 2].data = &filelist[i * 256];
|
||||
ments[i + 2].caption = filelist->name[i];
|
||||
ments[i + 2].data = filelist->name[i];
|
||||
|
||||
i++;
|
||||
}
|
||||
|
@ -354,9 +316,6 @@ static void _launch_payloads()
|
|||
else
|
||||
EPRINTF("No payloads found.");
|
||||
|
||||
free(ments);
|
||||
free(filelist);
|
||||
|
||||
if (file_sec)
|
||||
{
|
||||
memcpy(dir + strlen(dir), "/", 2);
|
||||
|
@ -366,8 +325,10 @@ static void _launch_payloads()
|
|||
}
|
||||
|
||||
failed_sd_mount:
|
||||
sd_end();
|
||||
free(dir);
|
||||
free(ments);
|
||||
free(filelist);
|
||||
sd_end();
|
||||
|
||||
btn_wait();
|
||||
}
|
||||
|
@ -377,6 +338,7 @@ static void _launch_ini_list()
|
|||
u8 max_entries = 61;
|
||||
char *special_path = NULL;
|
||||
char *emummc_path = NULL;
|
||||
ment_t *ments = NULL;
|
||||
ini_sec_t *cfg_sec = NULL;
|
||||
|
||||
LIST_INIT(ini_list_sections);
|
||||
|
@ -395,7 +357,7 @@ static void _launch_ini_list()
|
|||
}
|
||||
|
||||
// Build configuration menu.
|
||||
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (max_entries + 3));
|
||||
ments = (ment_t *)malloc(sizeof(ment_t) * (max_entries + 3));
|
||||
ments[0].type = MENT_BACK;
|
||||
ments[0].caption = "Back";
|
||||
|
||||
|
@ -458,7 +420,6 @@ static void _launch_ini_list()
|
|||
}
|
||||
else
|
||||
EPRINTF("No extra configs found.");
|
||||
free(ments);
|
||||
|
||||
parse_failed:
|
||||
if (!cfg_sec)
|
||||
|
@ -494,6 +455,7 @@ wrong_emupath:
|
|||
}
|
||||
|
||||
out:
|
||||
free(ments);
|
||||
|
||||
btn_wait();
|
||||
}
|
||||
|
@ -502,9 +464,11 @@ static void _launch_config()
|
|||
{
|
||||
u8 max_entries = 61;
|
||||
char *special_path = NULL;
|
||||
char *emummc_path = NULL;
|
||||
char *emummc_path = NULL;
|
||||
|
||||
ment_t *ments = NULL;
|
||||
ini_sec_t *cfg_sec = NULL;
|
||||
|
||||
LIST_INIT(ini_sections);
|
||||
|
||||
gfx_clear_grey(0x1B);
|
||||
|
@ -520,7 +484,7 @@ static void _launch_config()
|
|||
ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false);
|
||||
|
||||
// Build configuration menu.
|
||||
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * (max_entries + 6));
|
||||
ments = (ment_t *)malloc(sizeof(ment_t) * (max_entries + 6));
|
||||
ments[0].type = MENT_BACK;
|
||||
ments[0].caption = "Back";
|
||||
|
||||
|
@ -597,8 +561,6 @@ static void _launch_config()
|
|||
return;
|
||||
}
|
||||
|
||||
free(ments);
|
||||
|
||||
parse_failed:
|
||||
if (!cfg_sec)
|
||||
{
|
||||
|
@ -638,6 +600,8 @@ wrong_emupath:
|
|||
out:
|
||||
sd_end();
|
||||
|
||||
free(ments);
|
||||
|
||||
h_cfg.emummc_force_disable = false;
|
||||
|
||||
btn_wait();
|
||||
|
@ -658,7 +622,7 @@ static void _nyx_load_run()
|
|||
|
||||
// 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));
|
||||
u32 nyx_ver = byte_swap_32(*(u32 *)(nyx + NYX_VER_OFF)) & 0xFFFFFF00;
|
||||
if (nyx_ver < expected_nyx_ver)
|
||||
{
|
||||
h_cfg.errors |= ERR_SYSOLD_NYX;
|
||||
|
@ -767,7 +731,7 @@ static void _check_for_updated_bootloader()
|
|||
_launch_payload("bootloader/update.bin", true, false);
|
||||
else
|
||||
{
|
||||
u8 *buf = calloc(0x200, 1);
|
||||
u8 *buf = zalloc(0x200);
|
||||
is_ipl_updated(buf, "bootloader/update.bin", true);
|
||||
free(buf);
|
||||
}
|
||||
|
@ -885,7 +849,7 @@ static void _auto_launch()
|
|||
}
|
||||
|
||||
if (h_cfg.autohosoff && !(b_cfg.boot_cfg & BOOT_CFG_AUTOBOOT_EN))
|
||||
check_power_off_from_hos();
|
||||
_check_power_off_from_hos();
|
||||
|
||||
if (h_cfg.autoboot_list || (boot_from_id && !cfg_sec))
|
||||
{
|
||||
|
@ -1174,7 +1138,7 @@ static void _show_errors()
|
|||
|
||||
if (h_cfg.errors & ERR_L4T_KERNEL)
|
||||
{
|
||||
WPRINTF("Kernel panic occurred!\n");
|
||||
WPRINTF("L4T Kernel panic occurred!\n");
|
||||
if (!(h_cfg.errors & ERR_SD_BOOT_EN))
|
||||
{
|
||||
if (!sd_save_to_file((void *)PSTORE_ADDR, PSTORE_SZ, "L4T_panic.bin"))
|
||||
|
@ -1221,6 +1185,9 @@ static void _check_low_battery()
|
|||
int batt_volt = 0;
|
||||
int charge_status = 0;
|
||||
|
||||
// Enable charger in case it's disabled.
|
||||
bq24193_enable_charger();
|
||||
|
||||
bq24193_get_property(BQ24193_ChargeStatus, &charge_status);
|
||||
max17050_get_property(MAX17050_AvgVCELL, &batt_volt);
|
||||
|
||||
|
@ -1236,7 +1203,7 @@ static void _check_low_battery()
|
|||
|
||||
u8 *battery_icon = malloc(0x95A); // 21x38x3
|
||||
u8 *charging_icon = malloc(0x2F4); // 21x12x3
|
||||
u8 *no_charging_icon = calloc(0x2F4, 1);
|
||||
u8 *no_charging_icon = zalloc(0x2F4);
|
||||
|
||||
memcpy(charging_icon, battery_res, 0x2F4);
|
||||
memcpy(battery_icon, battery_res + 0x2F4, 0x95A);
|
||||
|
@ -1295,7 +1262,7 @@ static void _check_low_battery()
|
|||
if (!screen_on)
|
||||
{
|
||||
display_init();
|
||||
u32 *fb = display_init_framebuffer_pitch();
|
||||
u32 *fb = display_init_window_a_pitch();
|
||||
gfx_init_ctxt(fb, 720, 1280, 720);
|
||||
|
||||
gfx_set_rect_rgb(battery_icon, BATTERY_EMPTY_WIDTH, BATTERY_EMPTY_BATT_HEIGHT, 16, battery_icon_y_pos);
|
||||
|
@ -1332,7 +1299,7 @@ out:
|
|||
max77620_low_battery_monitor_config(true);
|
||||
}
|
||||
|
||||
static void _r2p_get_config_t210b01()
|
||||
static void _r2c_get_config_t210b01()
|
||||
{
|
||||
rtc_reboot_reason_t rr;
|
||||
if (!max77620_rtc_get_reboot_reason(&rr))
|
||||
|
@ -1372,7 +1339,7 @@ static void _r2p_get_config_t210b01()
|
|||
|
||||
static void _ipl_reload()
|
||||
{
|
||||
hw_reinit_workaround(false, 0);
|
||||
hw_deinit(false, 0);
|
||||
|
||||
// Reload hekate.
|
||||
void (*ipl_ptr)() = (void *)IPL_LOAD_ADDR;
|
||||
|
@ -1383,7 +1350,7 @@ static void _about()
|
|||
{
|
||||
static const char credits[] =
|
||||
"\nhekate (c) 2018, naehrwert, st4rk\n\n"
|
||||
" (c) 2018-2023, CTCaer\n\n"
|
||||
" (c) 2018-2024, CTCaer\n\n"
|
||||
" ___________________________________________\n\n"
|
||||
"Thanks to: %kderrek, nedwill, plutoo,\n"
|
||||
" shuffle2, smea, thexyz, yellows8%k\n"
|
||||
|
@ -1393,11 +1360,12 @@ static void _about()
|
|||
" ___________________________________________\n\n"
|
||||
"Open source and free packages used:\n\n"
|
||||
" - FatFs R0.13c\n"
|
||||
" (c) 2018, ChaN\n\n"
|
||||
" (c) 2006-2018, ChaN\n"
|
||||
" (c) 2018-2022, CTCaer\n\n"
|
||||
" - bcl-1.2.0\n"
|
||||
" (c) 2003-2006, Marcus Geelnard\n\n"
|
||||
" - Atmosphere (Exo st/types, prc id patches)\n"
|
||||
" (c) 2018-2019, Atmosphere-NX\n\n"
|
||||
" - blz\n"
|
||||
" (c) 2018, SciresM\n\n"
|
||||
" - elfload\n"
|
||||
" (c) 2014, Owen Shepherd\n"
|
||||
" (c) 2018, M4xw\n"
|
||||
|
@ -1478,7 +1446,7 @@ ment_t ment_top[] = {
|
|||
MDEF_END()
|
||||
};
|
||||
|
||||
menu_t menu_top = { ment_top, "hekate v6.1.0", 0, 0 };
|
||||
menu_t menu_top = { ment_top, "hekate v6.2.2", 0, 0 };
|
||||
|
||||
extern void pivot_stack(u32 stack_top);
|
||||
|
||||
|
@ -1487,10 +1455,10 @@ void ipl_main()
|
|||
// Do initial HW configuration. This is compatible with consecutive reruns without a reset.
|
||||
hw_init();
|
||||
|
||||
// Pivot the stack so we have enough space.
|
||||
pivot_stack(IPL_STACK_TOP);
|
||||
// Pivot the stack under IPL. (Only max 4KB is needed).
|
||||
pivot_stack(IPL_LOAD_ADDR);
|
||||
|
||||
// Tegra/Horizon configuration goes to 0x80000000+, package2 goes to 0xA9800000, we place our heap in between.
|
||||
// Place heap at a place outside of L4T/HOS configuration and binaries.
|
||||
heap_init((void *)IPL_HEAP_START);
|
||||
|
||||
#ifdef DEBUG_UART_PORT
|
||||
|
@ -1504,12 +1472,15 @@ void ipl_main()
|
|||
// Set bootloader's default configuration.
|
||||
set_default_configuration();
|
||||
|
||||
// Prep RTC regs for read. Needed for T210B01 R2P.
|
||||
// Prep RTC regs for read. Needed for T210B01 R2C.
|
||||
max77620_rtc_prep_read();
|
||||
|
||||
// Initialize display.
|
||||
display_init();
|
||||
|
||||
// Overclock BPMP.
|
||||
bpmp_clk_rate_set(h_cfg.t210b01 ? BPMP_CLK_DEFAULT_BOOST : BPMP_CLK_LOWER_BOOST);
|
||||
|
||||
// Mount SD Card.
|
||||
h_cfg.errors |= !sd_mount() ? ERR_SD_BOOT_EN : 0;
|
||||
|
||||
|
@ -1534,19 +1505,17 @@ void ipl_main()
|
|||
|
||||
skip_lp0_minerva_config:
|
||||
// Initialize display window, backlight and gfx console.
|
||||
u32 *fb = display_init_framebuffer_pitch();
|
||||
u32 *fb = display_init_window_a_pitch();
|
||||
gfx_init_ctxt(fb, 720, 1280, 720);
|
||||
gfx_con_init();
|
||||
|
||||
// Initialize backlight PWM.
|
||||
display_backlight_pwm_init();
|
||||
//display_backlight_brightness(h_cfg.backlight, 1000);
|
||||
|
||||
// Overclock BPMP.
|
||||
bpmp_clk_rate_set(h_cfg.t210b01 ? BPMP_CLK_DEFAULT_BOOST : BPMP_CLK_LOWER_BOOST);
|
||||
|
||||
// Get R2P config from RTC.
|
||||
// Get R2C config from RTC.
|
||||
if (h_cfg.t210b01)
|
||||
_r2p_get_config_t210b01();
|
||||
_r2c_get_config_t210b01();
|
||||
|
||||
// Show exceptions, HOS errors, library errors and L4T kernel panics.
|
||||
_show_errors();
|
||||
|
|
|
@ -60,7 +60,8 @@ _reloc_ipl:
|
|||
BX R3
|
||||
|
||||
_real_start:
|
||||
/* Initially, we place our stack in IRAM but will move it to SDRAM later. */
|
||||
/* Initially, we place our stack under relocator but will move it to under the payload. */
|
||||
/* This depends on application scope. */
|
||||
LDR SP, =0x4003FF00
|
||||
LDR R0, =__bss_start
|
||||
EOR R1, R1, R1
|
||||
|
|
|
@ -27,7 +27,7 @@ OBJS = $(addprefix $(BUILDDIR)/$(TARGET)/, \
|
|||
################################################################################
|
||||
|
||||
CUSTOMDEFINES := -DBL_MAGIC=$(IPL_MAGIC)
|
||||
CUSTOMDEFINES += -DBL_VER_MJ=$(BLVERSION_MAJOR) -DBL_VER_MN=$(BLVERSION_MINOR) -DBL_VER_HF=$(BLVERSION_HOTFX) -DBL_RESERVED=$(BLVERSION_RSVD)
|
||||
CUSTOMDEFINES += -DBL_VER_MJ=$(BLVERSION_MAJOR) -DBL_VER_MN=$(BLVERSION_MINOR) -DBL_VER_HF=$(BLVERSION_HOTFX) -DBL_VER_RL=$(BLVERSION_REL)
|
||||
|
||||
#TODO: Considering reinstating some of these when pointer warnings have been fixed.
|
||||
WARNINGS := -Wall -Wsign-compare -Wno-array-bounds -Wno-stringop-overflow
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019 CTCaer
|
||||
* Copyright (c) 2019-2024 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,
|
||||
|
@ -32,12 +32,12 @@
|
|||
boot_cfg_t __attribute__((section ("._boot_cfg"))) b_cfg;
|
||||
const volatile ipl_ver_meta_t __attribute__((section ("._ipl_version"))) ipl_ver = {
|
||||
.magic = BL_MAGIC,
|
||||
.version = (BL_VER_MJ + '0') | ((BL_VER_MN + '0') << 8) | ((BL_VER_HF + '0') << 16),
|
||||
.version = (BL_VER_MJ + '0') | ((BL_VER_MN + '0') << 8) | ((BL_VER_HF + '0') << 16) | ((BL_VER_RL) << 24),
|
||||
.rsvd0 = 0,
|
||||
.rsvd1 = 0
|
||||
};
|
||||
|
||||
const volatile char __attribute__((section ("._octopus"))) octopus[] =
|
||||
const char __attribute__((section ("._octopus"))) octopus[] =
|
||||
"\n"
|
||||
" ___\n"
|
||||
" .-' `'.\n"
|
||||
|
@ -67,6 +67,12 @@ void loader_main()
|
|||
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // Set HCLK div to 1 and PCLK div to 3.
|
||||
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003333; // Set SCLK to PLLP_OUT (408MHz).
|
||||
|
||||
// Set arbiter.
|
||||
ARB_PRI(ARB_PRIO_CPU_PRIORITY) = 0x12412D1;
|
||||
ARB_PRI(ARB_PRIO_COP_PRIORITY) = 0x0000000;
|
||||
ARB_PRI(ARB_PRIO_VCP_PRIORITY) = 0x220244A;
|
||||
ARB_PRI(ARB_PRIO_DMA_PRIORITY) = 0x320369B;
|
||||
|
||||
// Get Payload size.
|
||||
u32 payload_size = sizeof(payload_00) + sizeof(payload_01); // Actual payload size.
|
||||
payload_size += (u32)payload_01 - (u32)payload_00 - sizeof(payload_00); // Add compiler alignment.
|
||||
|
|
|
@ -28,7 +28,7 @@ $(BUILD)/%.o: ./%.c
|
|||
$(TARGET).bso: $(OBJS)
|
||||
@$(CC) $(LDFLAGS) -e _modInit $^ -o $(OUTPUT)/$(TARGET).bso
|
||||
@$(STRIP) -g $(OUTPUT)/$(TARGET).bso
|
||||
@echo "-------------\nBuilt module: "$(TARGET)".bso\n-------------"
|
||||
@echo -e "-------------\nBuilt module: "$(TARGET)".bso\n-------------"
|
||||
|
||||
clean:
|
||||
@rm -rf $(OUTPUT)/$(TARGET).bso
|
||||
|
|
|
@ -981,6 +981,7 @@ struct sdram_params_t210b01
|
|||
/* Specifies the value for MC_MTS_CARVEOUT_REG_CTRL */
|
||||
u32 mc_mts_carveout_reg_ctrl;
|
||||
|
||||
/* Specifies the clients that are allowed to access untranslated memory */
|
||||
u32 mc_untranslated_region_check;
|
||||
|
||||
/* Just a place holder for special usage when there is no BCT for certain registers */
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue