Compare commits

..

7 Commits

Author SHA1 Message Date
suchmememanyskill
83b49299b4 Make stuff work maybe 2023-07-22 17:59:29 +02:00
suchmememanyskill
ee6ea3e64c Update BDK to Hekate 6.0.5 2023-07-20 16:45:07 +02:00
suchmememanyskill
09fc492610 Step 5: Scare the init bugs away
Seriously though why the fuck was this the issue
2022-01-23 00:40:08 +01:00
suchmememanyskill
5c59d42a30 Step 4: Fix the ini parser
also why am i using steps
2022-01-22 16:05:08 +01:00
suchmememanyskill
c8468a6d73 Step 3: Fix up crypto 2022-01-22 15:56:31 +01:00
suchmememanyskill
626cae4e00 Step 2: Stop using pkg1 versions 2022-01-22 02:19:00 +01:00
suchmememanyskill
72c58c93b8 Step 1: Compile 2022-01-22 01:59:17 +01:00
153 changed files with 8557 additions and 12679 deletions

View File

@@ -10,8 +10,8 @@ include $(DEVKITARM)/base_rules
IPL_LOAD_ADDR := 0x40008000 IPL_LOAD_ADDR := 0x40008000
LPVERSION_MAJOR := 4 LPVERSION_MAJOR := 4
LPVERSION_MINOR := 1 LPVERSION_MINOR := 0
LPVERSION_BUGFX := 0 LPVERSION_BUGFX := 1
LPVERSION := \"$(LPVERSION_MAJOR).$(LPVERSION_MINOR).$(LPVERSION_BUGFX)\" LPVERSION := \"$(LPVERSION_MAJOR).$(LPVERSION_MINOR).$(LPVERSION_BUGFX)\"
################################################################################ ################################################################################
@@ -41,9 +41,13 @@ FFCFG_INC := '"../$(SOURCEDIR)/libs/fatfs/ffconf.h"'
################################################################################ ################################################################################
CUSTOMDEFINES := -DIPL_LOAD_ADDR=$(IPL_LOAD_ADDR) CUSTOMDEFINES := -DIPL_LOAD_ADDR=$(IPL_LOAD_ADDR)
CUSTOMDEFINES += -DLP_VER_MJ=$(LPVERSION_MAJOR) -DLP_VER_MN=$(LPVERSION_MINOR) -DLP_VER_BF=$(LPVERSION_BUGFX) -DLP_VER=$(LPVERSION) CUSTOMDEFINES += -DLP_VER_MJ=$(LPVERSION_MAJOR) -DLP_VER_MN=$(LPVERSION_MINOR) -DLP_VER_BF=$(LPVERSION_BUGFX) -DLP_VER=$(LPVERSION) -DBDK_EMUMMC_ENABLE
CUSTOMDEFINES += -DGFX_INC=$(GFX_INC) -DFFCFG_INC=$(FFCFG_INC) CUSTOMDEFINES += -DGFX_INC=$(GFX_INC) -DFFCFG_INC=$(FFCFG_INC)
CUSTOMDEFINES += -DBDK_MALLOC_NO_DEFRAG -DBDK_MC_ENABLE_AHB_REDIRECT -DBDK_EMUMMC_ENABLE
FFCFG_INC := '"../$(PROJECT_DIR)/libs/fatfs/ffconf.h"'
# 0: UART_A, 1: UART_B. # 0: UART_A, 1: UART_B.
#CUSTOMDEFINES += -DDEBUG_UART_PORT=0 #CUSTOMDEFINES += -DDEBUG_UART_PORT=0

28
Modified BDK files.md Normal file
View File

@@ -0,0 +1,28 @@
For future reference if updating the BDK
// TODO: memory map(?)
## /bdk/sec/SE.c&h
- Added se_aes_cmac
- Added se_calc_hmac_sha256
## /bdk/usb
- Removed entirely
## /bdk/storage/sd.c
- in sd_file_read(), extend read buffer by 1 and place a NULL byte at the end
## /bdk/libs/fatfs/ff.c&h
- Added f_fdisk_mod
- Stubbed exfat partition creation
## /bdk/utils/ini.c
- Added initial 'unknown' section to parse prod.keys
## /bdk/utils/types.h
- Added colors from lockpick-rcm
- Add ALWAYS_INLINE, LOG2, DIV_ROUND_UP defs
- Add 'open_mode_t' and 'validity_t' enums
## /bdk/libs
- Added nx-savedata from [Lockpick_RCM](https://github.com/shchmue/Lockpick_RCM)

View File

@@ -61,7 +61,6 @@ Other awesome people:
- Bleck9999 - Bleck9999
- Exelix - Exelix
- Emmo - Emmo
- JeffV
## Screenshots ## Screenshots

78
bdk/bdk.h Normal file
View File

@@ -0,0 +1,78 @@
/*
* Copyright (c) 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,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef BDK_H
#define BDK_H
#include <memory_map.h>
#include <display/di.h>
#include <display/vic.h>
#include <input/als.h>
#include <input/joycon.h>
#include <input/touch.h>
#include <mem/emc.h>
#include <mem/heap.h>
#include <mem/mc.h>
#include <mem/minerva.h>
#include <mem/sdram.h>
#include <mem/smmu.h>
#include <module.h>
#include <power/bm92t36.h>
#include <power/bq24193.h>
#include <power/max17050.h>
#include <power/max77620.h>
#include <power/max7762x.h>
#include <power/max77812.h>
#include <power/regulator_5v.h>
#include <rtc/max77620-rtc.h>
#include <sec/se.h>
#include <sec/tsec.h>
#include <soc/actmon.h>
#include <soc/bpmp.h>
#include <soc/ccplex.h>
#include <soc/clock.h>
#include <soc/fuse.h>
#include <soc/gpio.h>
#include <soc/hw_init.h>
#include <soc/i2c.h>
#include <soc/kfuse.h>
#include <soc/pinmux.h>
#include <soc/pmc.h>
#include <soc/timer.h>
#include <soc/t210.h>
#include <soc/uart.h>
#include <storage/emmc.h>
#include <storage/mbr_gpt.h>
#include <storage/mmc.h>
#include <storage/nx_emmc_bis.h>
#include <storage/ramdisk.h>
#include <storage/sd.h>
#include <storage/sdmmc.h>
#include <thermal/fan.h>
#include <thermal/tmp451.h>
#include <utils/aarch64_util.h>
#include <utils/btn.h>
#include <utils/dirlist.h>
#include <utils/ini.h>
#include <utils/list.h>
#include <utils/sprintf.h>
#include <utils/types.h>
#include <utils/util.h>
#include <gfx_utils.h>
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2021 CTCaer * Copyright (c) 2018-2023 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -43,13 +43,17 @@
// DC_CMD non-shadowed command/sync registers. // DC_CMD non-shadowed command/sync registers.
#define DC_CMD_GENERAL_INCR_SYNCPT 0x00 #define DC_CMD_GENERAL_INCR_SYNCPT 0x00
#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 #define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL 0x01
#define SYNCPT_CNTRL_SOFT_RESET BIT(0) #define SYNCPT_CNTRL_SOFT_RESET BIT(0)
#define SYNCPT_CNTRL_NO_STALL BIT(8) #define SYNCPT_CNTRL_NO_STALL BIT(8)
#define DC_CMD_CONT_SYNCPT_VSYNC 0x28 #define DC_CMD_CONT_SYNCPT_VSYNC 0x28
#define SYNCPT_VSYNC_ENABLE BIT(8) #define SYNCPT_VSYNC_INDX(x) (((x) & 0xff) << 0)
#define SYNCPT_VSYNC_ENABLE BIT(8)
#define DC_CMD_DISPLAY_COMMAND_OPTION0 0x031 #define DC_CMD_DISPLAY_COMMAND_OPTION0 0x031
@@ -72,6 +76,7 @@
#define DC_CMD_INT_MASK 0x38 #define DC_CMD_INT_MASK 0x38
#define DC_CMD_INT_ENABLE 0x39 #define DC_CMD_INT_ENABLE 0x39
#define DC_CMD_INT_FRAME_END_INT BIT(1) #define DC_CMD_INT_FRAME_END_INT BIT(1)
#define DC_CMD_INT_V_BLANK_INT BIT(2)
#define DC_CMD_STATE_ACCESS 0x40 #define DC_CMD_STATE_ACCESS 0x40
#define READ_MUX BIT(0) #define READ_MUX BIT(0)
@@ -98,7 +103,13 @@
#define WINDOW_C_SELECT BIT(6) #define WINDOW_C_SELECT BIT(6)
#define WINDOW_D_SELECT BIT(7) #define WINDOW_D_SELECT BIT(7)
#define DC_CMD_REG_ACT_CONTROL 0x043 #define DC_CMD_REG_ACT_CONTROL 0x43
#define GENERAL_ACT_HCNTR_SEL BIT(0)
#define WIN_A_ACT_HCNTR_SEL BIT(2)
#define WIN_B_ACT_HCNTR_SEL BIT(4)
#define WIN_C_ACT_HCNTR_SEL BIT(6)
#define CURSOR_ACT_HCNTR_SEL BIT(7)
#define WIN_D_ACT_HCNTR_SEL BIT(10)
// DC_D_WIN_DD window D instance of DC_WIN // DC_D_WIN_DD window D instance of DC_WIN
#define DC_D_WIN_DD_WIN_OPTIONS 0x80 #define DC_D_WIN_DD_WIN_OPTIONS 0x80
@@ -124,6 +135,7 @@
#define DC_COM_CRC_CONTROL 0x300 #define DC_COM_CRC_CONTROL 0x300
#define DC_COM_PIN_OUTPUT_ENABLE(x) (0x302 + (x)) #define DC_COM_PIN_OUTPUT_ENABLE(x) (0x302 + (x))
#define DC_COM_PIN_OUTPUT_POLARITY(x) (0x306 + (x)) #define DC_COM_PIN_OUTPUT_POLARITY(x) (0x306 + (x))
#define LSC0_OUTPUT_POLARITY_LOW BIT(24)
#define DC_COM_DSC_TOP_CTL 0x33E #define DC_COM_DSC_TOP_CTL 0x33E
@@ -139,12 +151,29 @@
#define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403 #define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403
#define DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER 0x404 #define DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER 0x404
#define DC_DISP_DISP_TIMING_OPTIONS 0x405 #define DC_DISP_DISP_TIMING_OPTIONS 0x405
#define VSYNC_H_POSITION(x) (((x) & 0x1fff) << 0)
#define DC_DISP_REF_TO_SYNC 0x406 #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 DC_DISP_SYNC_WIDTH 0x407 #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 DC_DISP_BACK_PORCH 0x408 #define DC_DISP_BACK_PORCH 0x408
#define H_BACK_PORCH(x) (((x) & 0x1fff) << 0)
#define V_BACK_PORCH(x) (((x) & 0x1fff) << 16)
#define DC_DISP_ACTIVE 0x409 #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 DC_DISP_FRONT_PORCH 0x40A #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 DC_DISP_DISP_CLOCK_CONTROL 0x42E #define DC_DISP_DISP_CLOCK_CONTROL 0x42E
#define SHIFT_CLK_DIVIDER(x) ((x) & 0xff) #define SHIFT_CLK_DIVIDER(x) ((x) & 0xff)
@@ -239,6 +268,10 @@
#define DC_DISP_SD_BL_CONTROL 0x4DC #define DC_DISP_SD_BL_CONTROL 0x4DC
#define DC_DISP_BLEND_BACKGROUND_COLOR 0x4E4 #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 DC_WINC_PALETTE_COLOR_EXT 0x600
#define DC_WIN_CSC_YOF 0x611 #define DC_WIN_CSC_YOF 0x611
#define DC_WIN_CSC_KYRGB 0x612 #define DC_WIN_CSC_KYRGB 0x612
#define DC_WIN_CSC_KUR 0x613 #define DC_WIN_CSC_KUR 0x613
@@ -253,12 +286,13 @@
// The following registers are A/B/C shadows of the 0xB80/0xD80/0xF80 registers (see DISPLAY_WINDOW_HEADER). // The following registers are A/B/C shadows of the 0xB80/0xD80/0xF80 registers (see DISPLAY_WINDOW_HEADER).
#define DC_WIN_WIN_OPTIONS 0x700 #define DC_WIN_WIN_OPTIONS 0x700
#define H_DIRECTION BIT(0) #define H_DIRECTION BIT(0)
#define V_DIRECTION BIT(2) #define V_DIRECTION BIT(2)
#define SCAN_COLUMN BIT(4) #define SCAN_COLUMN BIT(4)
#define COLOR_EXPAND BIT(6) #define COLOR_EXPAND BIT(6)
#define CSC_ENABLE BIT(18) #define COLOR_PALETTE_ENABLE BIT(16)
#define WIN_ENABLE BIT(30) #define CSC_ENABLE BIT(18)
#define WIN_ENABLE BIT(30)
#define DC_WIN_BUFFER_CONTROL 0x702 #define DC_WIN_BUFFER_CONTROL 0x702
#define BUFFER_CONTROL_HOST 0 #define BUFFER_CONTROL_HOST 0
@@ -290,10 +324,22 @@
#define WIN_COLOR_DEPTH_YUV422R 0x17 #define WIN_COLOR_DEPTH_YUV422R 0x17
#define WIN_COLOR_DEPTH_YCbCr422RA 0x18 #define WIN_COLOR_DEPTH_YCbCr422RA 0x18
#define WIN_COLOR_DEPTH_YUV422RA 0x19 #define WIN_COLOR_DEPTH_YUV422RA 0x19
#define WIN_COLOR_DEPTH_YCbCr444P 0x29
#define WIN_COLOR_DEPTH_YCrCb420SP 0x2A
#define WIN_COLOR_DEPTH_YCbCr420SP 0x2B
#define WIN_COLOR_DEPTH_YCrCb422SP 0x2C
#define WIN_COLOR_DEPTH_YCbCr422SP 0x2D
#define WIN_COLOR_DEPTH_YUV444P 0x34
#define WIN_COLOR_DEPTH_YVU420SP 0x35
#define WIN_COLOR_DEPTH_YUV420SP 0x36
#define WIN_COLOR_DEPTH_YVU422SP 0x37
#define WIN_COLOR_DEPTH_YUV422SP 0x38
#define WIN_COLOR_DEPTH_YVU444SP 0x3B
#define WIN_COLOR_DEPTH_YUV444SP 0x3C
#define DC_WIN_POSITION 0x704 #define DC_WIN_POSITION 0x704
#define H_POSITION(x) (((x) & 0xFfff) << 0) #define H_POSITION(x) (((x) & 0xffff) << 0) // Support negative.
#define V_POSITION(x) (((x) & 0x1fff) << 16) #define V_POSITION(x) (((x) & 0xffff) << 16) // Support negative.
#define DC_WIN_SIZE 0x705 #define DC_WIN_SIZE 0x705
#define H_SIZE(x) (((x) & 0x1fff) << 0) #define H_SIZE(x) (((x) & 0x1fff) << 0)
@@ -316,6 +362,7 @@
#define DC_WIN_DV_CONTROL 0x70E #define DC_WIN_DV_CONTROL 0x70E
#define DC_WINBUF_BLEND_LAYER_CONTROL 0x716 #define DC_WINBUF_BLEND_LAYER_CONTROL 0x716
#define WIN_BLEND_DEPTH(x) (((x) & 0xff) << 0)
#define WIN_K1(x) (((x) & 0xff) << 8) #define WIN_K1(x) (((x) & 0xff) << 8)
#define WIN_K2(x) (((x) & 0xff) << 16) #define WIN_K2(x) (((x) & 0xff) << 16)
#define WIN_BLEND_ENABLE (0 << 24) #define WIN_BLEND_ENABLE (0 << 24)
@@ -386,6 +433,7 @@
#define DSI_HOST_CONTROL_FIFO_SEL BIT(4) #define DSI_HOST_CONTROL_FIFO_SEL BIT(4)
#define DSI_HOST_CONTROL_HS BIT(5) #define DSI_HOST_CONTROL_HS BIT(5)
#define DSI_HOST_CONTROL_RAW BIT(6) #define DSI_HOST_CONTROL_RAW BIT(6)
#define DSI_HOST_CONTROL_TX_TRIG_MASK (3 << 12)
#define DSI_HOST_CONTROL_TX_TRIG_SOL (0 << 12) #define DSI_HOST_CONTROL_TX_TRIG_SOL (0 << 12)
#define DSI_HOST_CONTROL_TX_TRIG_FIFO (1 << 12) #define DSI_HOST_CONTROL_TX_TRIG_FIFO (1 << 12)
#define DSI_HOST_CONTROL_TX_TRIG_HOST (2 << 12) #define DSI_HOST_CONTROL_TX_TRIG_HOST (2 << 12)
@@ -433,10 +481,14 @@
#define DSI_PKT_SEQ_5_LO 0x2D #define DSI_PKT_SEQ_5_LO 0x2D
#define DSI_PKT_SEQ_5_HI 0x2E #define DSI_PKT_SEQ_5_HI 0x2E
#define DSI_DCS_CMDS 0x33 #define DSI_DCS_CMDS 0x33
#define DSI_PKT_LEN_0_1 0x34 #define DSI_PKT_LEN_0_1 0x34
#define DSI_PKT_LEN_2_3 0x35 #define DSI_PKT_LEN_2_3 0x35
#define DSI_PKT_LEN_4_5 0x36 #define DSI_PKT_LEN_4_5 0x36
#define DSI_PKT_LEN_6_7 0x37 #define DSI_PKT_LEN_6_7 0x37
#define PKT0_LEN(x) (((x) & 0xffff) << 0)
#define PKT1_LEN(x) (((x) & 0xffff) << 16)
#define DSI_PHY_TIMING_0 0x3C #define DSI_PHY_TIMING_0 0x3C
#define DSI_PHY_TIMING_1 0x3D #define DSI_PHY_TIMING_1 0x3D
#define DSI_PHY_TIMING_2 0x3E #define DSI_PHY_TIMING_2 0x3E
@@ -593,6 +645,7 @@
#define MIPI_DCS_GET_SCANLINE 0x45 #define MIPI_DCS_GET_SCANLINE 0x45
#define MIPI_DCS_SET_TEAR_SCANLINE_WIDTH 0x46 #define MIPI_DCS_SET_TEAR_SCANLINE_WIDTH 0x46
#define MIPI_DCS_GET_SCANLINE_WIDTH 0x47 #define MIPI_DCS_GET_SCANLINE_WIDTH 0x47
#define MIPI_DSI_AREA_COLOR_MODE 0x4C
#define MIPI_DCS_SET_BRIGHTNESS 0x51 // DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL. 1 byte. 0-7: DBV. #define MIPI_DCS_SET_BRIGHTNESS 0x51 // DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL. 1 byte. 0-7: DBV.
#define MIPI_DCS_GET_BRIGHTNESS 0x52 // 1 byte. 0-7: DBV. #define MIPI_DCS_GET_BRIGHTNESS 0x52 // 1 byte. 0-7: DBV.
#define MIPI_DCS_SET_CONTROL_DISPLAY 0x53 // 1 byte. 2: BL, 3: DD, 5: BCTRL. #define MIPI_DCS_SET_CONTROL_DISPLAY 0x53 // 1 byte. 2: BL, 3: DD, 5: BCTRL.
@@ -606,7 +659,9 @@
#define MIPI_DCS_READ_DDB_CONTINUE 0xA8 // 0x100 size. #define MIPI_DCS_READ_DDB_CONTINUE 0xA8 // 0x100 size.
/*! MIPI DCS Panel Private CMDs. */ /*! MIPI DCS Panel Private CMDs. */
#define MIPI_DCS_PRIV_UNK_A0 0xA0 #define MIPI_DCS_PRIV_SM_SET_COLOR_MODE 0xA0
#define MIPI_DCS_PRIV_SM_SET_REG_OFFSET 0xB0
#define MIPI_DCS_PRIV_SM_SET_ELVSS 0xB1 // OLED backlight tuning. Byte7: PWM transition time in frames.
#define MIPI_DCS_PRIV_SET_POWER_CONTROL 0xB1 #define MIPI_DCS_PRIV_SET_POWER_CONTROL 0xB1
#define MIPI_DCS_PRIV_SET_EXTC 0xB9 // Enable extended commands. #define MIPI_DCS_PRIV_SET_EXTC 0xB9 // Enable extended commands.
#define MIPI_DCS_PRIV_UNK_BD 0xBD #define MIPI_DCS_PRIV_UNK_BD 0xBD
@@ -614,6 +669,8 @@
#define MIPI_DCS_PRIV_UNK_D6 0xD6 #define MIPI_DCS_PRIV_UNK_D6 0xD6
#define MIPI_DCS_PRIV_UNK_D8 0xD8 #define MIPI_DCS_PRIV_UNK_D8 0xD8
#define MIPI_DCS_PRIV_UNK_D9 0xD9 #define MIPI_DCS_PRIV_UNK_D9 0xD9
// LVL1 LVL2 LVL3 UNK0 UNK1
#define MIPI_DCS_PRIV_SM_SET_REGS_LOCK 0xE2 // Samsung: Lock (default): 5A5A A5A5 A5A5 A500 A500. Unlock: A5A5 5A5A 5A5A UNK UNK.
#define MIPI_DCS_PRIV_READ_EXTC_CMD_SPI 0xFE // Read EXTC Command In SPI. 1 byte. 0-6: EXT_SPI_CNT, 7:EXT_SP. #define MIPI_DCS_PRIV_READ_EXTC_CMD_SPI 0xFE // Read EXTC Command In SPI. 1 byte. 0-6: EXT_SPI_CNT, 7:EXT_SP.
#define MIPI_DCS_PRIV_SET_EXTC_CMD_REG 0xFF // EXTC Command Set enable register. 5 bytes. Pass: FF 98 06 04, PAGE. #define MIPI_DCS_PRIV_SET_EXTC_CMD_REG 0xFF // EXTC Command Set enable register. 5 bytes. Pass: FF 98 06 04, PAGE.
@@ -648,32 +705,55 @@
#define DCS_GAMMA_CURVE_GC2_1_0 BIT(2) #define DCS_GAMMA_CURVE_GC2_1_0 BIT(2)
#define DCS_GAMMA_CURVE_GC3_1_0 BIT(3) // Are there more? #define DCS_GAMMA_CURVE_GC3_1_0 BIT(3) // Are there more?
#define DCS_CONTROL_DISPLAY_SM_FLASHLIGHT BIT(2)
#define DCS_CONTROL_DISPLAY_BACKLIGHT_CTRL BIT(2) #define DCS_CONTROL_DISPLAY_BACKLIGHT_CTRL BIT(2)
#define DCS_CONTROL_DISPLAY_DIMMING_CTRL BIT(3) #define DCS_CONTROL_DISPLAY_DIMMING_CTRL BIT(3)
#define DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL BIT(5) #define DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL BIT(5)
#define PANEL_OLED_BL_COEFF 82 // 82%. #define DCS_SM_COLOR_MODE_SATURATED 0x00 // Disabled. Similar to vivid but over-saturated. Wide gamut?
#define PANEL_OLED_BL_OFFSET 45 // Least legible backlight duty. #define DCS_SM_COLOR_MODE_WASHED 0x45
#define DCS_SM_COLOR_MODE_BASIC 0x03
#define DCS_SM_COLOR_MODE_POR_RESET 0x20 // Reset value on power on.
#define DCS_SM_COLOR_MODE_NATURAL 0x23 // Not actually natural..
#define DCS_SM_COLOR_MODE_VIVID 0x65
#define DCS_SM_COLOR_MODE_NIGHT0 0x43 // Based on washed out.
#define DCS_SM_COLOR_MODE_NIGHT1 0x15 // Based on basic.
#define DCS_SM_COLOR_MODE_NIGHT2 0x35 // Based on natural.
#define DCS_SM_COLOR_MODE_NIGHT3 0x75 // Based on vivid.
#define DCS_SM_COLOR_MODE_ENABLE BIT(0)
#define PANEL_SM_BL_CANDELA_MAX 2047
/* Switch Panels: /* Switch Panels:
* *
* 6.2" panels for Icosa and Iowa skus: * 6.2" panels for Icosa and Iowa SKUs:
* [10] 81 [26]: JDI LPM062M326A * [10] 81 [26]: JDI LPM062M326A
* [10] 96 [09]: JDI LAM062M109A * [10] 96 [09]: JDI LAM062M109A
* [20] 93 [0F]: InnoLux P062CCA-AZ1 (Rev A1) * [20] 93 [0F]: InnoLux P062CCA-AZ1 (Rev A1)
* [20] 95 [0F]: InnoLux P062CCA-AZ2 (Rev B1) * [20] 95 [0F]: InnoLux P062CCA-AZ2 (Rev B1)
* [20] 96 [0F]: InnoLux P062CCA-AZ3 [UNCONFIRMED MODEL REV] * [20] 96 [0F]: InnoLux P062CCA-AZ3 (Rev XX) [UNCONFIRMED MODEL+REV]
* [20] 98 [0F]: InnoLux P062CCA-??? [UNCONFIRMED MODEL REV] * [20] 97 [0F]: InnoLux P062CCA-??? (Rev XX) [UNCONFIRMED MODEL+REV]
* [20] 98 [0F]: InnoLux P062CCA-??? (Rev XX) [UNCONFIRMED MODEL+REV]
* [30] 93 [0F]: AUO A062TAN00 (59.06A33.000)
* [30] 94 [0F]: AUO A062TAN01 (59.06A33.001) * [30] 94 [0F]: AUO A062TAN01 (59.06A33.001)
* [30] 95 [0F]: AUO A062TAN02 (59.06A33.002) * [30] 95 [0F]: AUO A062TAN02 (59.06A33.002)
* [30] 97 [0F]: AUO A062TAN02 (59.06A33.002) [From photo of assumed same panel]
* [30] 98 [0F]: AUO A062TAN0? [UNCONFIRMED MODEL]
* [30] XX [0F]: AUO A062TAN03 (59.06A33.003) [UNCONFIRMED ID] * [30] XX [0F]: AUO A062TAN03 (59.06A33.003) [UNCONFIRMED ID]
* *
* 5.5" panels for Hoag skus:
* [20] 94 [10]: InnoLux 2J055IA-27A (Rev B1)
* [30] 93 [10]: AUO A055TAN01 (59.05A30.001)
* [40] XX [10]: Vendor 40 [UNCONFIRMED ID]
* *
* 7.0" OLED panels for Aula skus: * 5.5" panels for Hoag SKU:
* [20] 94 [10]: InnoLux 2J055IA-27A (Rev B1) (6203B001P4000)
* [20] 95 [10]: InnoLux 2J055IA-27A (Rev XX) [UNCONFIRMED MODEL+REV]
* [20] 96 [10]: InnoLux 2J055IA-27A (Rev XX) [UNCONFIRMED MODEL+REV]
* [30] 93 [10]: AUO A055TAN01 (59.05A30.001)
* [30] 94 [10]: AUO A055TAN02 (59.05A30.002)
* [30] 95 [10]: AUO A055TAN03 (59.05A30.003)
* [40] 94 [10]: Sharp LQ055T1SW10 (Rev P)
*
*
* 7.0" OLED panels for Aula SKU:
* [50] 9B [20]: Samsung AMS699VC01-0 (Rev 2.5) * [50] 9B [20]: Samsung AMS699VC01-0 (Rev 2.5)
*/ */
@@ -687,7 +767,7 @@
* 10h: Japan Display Inc. * 10h: Japan Display Inc.
* 20h: InnoLux Corporation * 20h: InnoLux Corporation
* 30h: AU Optronics * 30h: AU Optronics
* 40h: Unknown0 * 40h: Sharp
* 50h: Samsung * 50h: Samsung
* *
* Boards, Panel Size: * Boards, Panel Size:
@@ -705,7 +785,7 @@ enum
PANEL_AUO_A062TAN01 = 0x0F30, PANEL_AUO_A062TAN01 = 0x0F30,
PANEL_INL_2J055IA_27A = 0x1020, PANEL_INL_2J055IA_27A = 0x1020,
PANEL_AUO_A055TAN01 = 0x1030, PANEL_AUO_A055TAN01 = 0x1030,
PANEL_V40_55_UNK = 0x1040, PANEL_SHP_LQ055T1SW10 = 0x1040,
PANEL_SAM_AMS699VC01 = 0x2050 PANEL_SAM_AMS699VC01 = 0x2050
}; };
@@ -725,8 +805,9 @@ void display_backlight(bool enable);
void display_backlight_brightness(u32 brightness, u32 step_delay); void display_backlight_brightness(u32 brightness, u32 step_delay);
u32 display_get_backlight_brightness(); u32 display_get_backlight_brightness();
/*! Init display in full 1280x720 resolution (B8G8R8A8, line stride 768, framebuffer size = 1280*768*4 bytes). */ /*! Init display in full 720x1280 resolution (B8G8R8A8, line stride 720, framebuffer size = 720*1280*4 bytes). */
u32 *display_init_framebuffer_pitch(); u32 *display_init_framebuffer_pitch();
u32 *display_init_framebuffer_pitch_vic();
u32 *display_init_framebuffer_pitch_inv(); u32 *display_init_framebuffer_pitch_inv();
u32 *display_init_framebuffer_block(); u32 *display_init_framebuffer_block();
u32 *display_init_framebuffer_log(); u32 *display_init_framebuffer_log();
@@ -736,7 +817,9 @@ void display_init_cursor(void *crs_fb, u32 size);
void display_set_pos_cursor(u32 x, u32 y); void display_set_pos_cursor(u32 x, u32 y);
void display_deinit_cursor(); void display_deinit_cursor();
void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled); int display_dsi_read(u8 cmd, u32 len, void *data);
int display_dsi_read(u8 cmd, u32 len, void *data, bool video_enabled); 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);
#endif #endif

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer * Copyright (c) 2018-2022 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -15,33 +15,29 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
//Display A config. // Display A config.
static const cfg_op_t _display_dc_setup_win_config[94] = { static const cfg_op_t _di_dc_setup_win_config[] = {
{DC_CMD_STATE_ACCESS, 0}, {DC_CMD_STATE_ACCESS, 0},
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, {DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{DC_CMD_REG_ACT_CONTROL, 0x54}, // Select H counter for win A/B/C. {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_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_DISP_DC_MCCIF_FIFOCTRL, 0}, {DC_DISP_DC_MCCIF_FIFOCTRL, 0},
{DC_DISP_DISP_MEM_HIGH_PRIORITY, 0}, {DC_DISP_DISP_MEM_HIGH_PRIORITY, 0},
{DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER, 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_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_GENERAL_INCR_SYNCPT_CNTRL, SYNCPT_CNTRL_NO_STALL},
{DC_CMD_CONT_SYNCPT_VSYNC, SYNCPT_VSYNC_ENABLE | 0x9}, // 9: SYNCPT {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_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_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ},
{DC_CMD_STATE_ACCESS, 0}, {DC_CMD_STATE_ACCESS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
/* 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_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, {DC_WIN_DV_CONTROL, 0},
{DC_WIN_DV_CONTROL, 0},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
/* Setup default YUV colorspace conversion coefficients */ /* Setup default YUV colorspace conversion coefficients */
{DC_WIN_CSC_YOF, 0xF0}, {DC_WIN_CSC_YOF, 0xF0},
{DC_WIN_CSC_KYRGB, 0x12A}, {DC_WIN_CSC_KYRGB, 0x12A},
@@ -52,66 +48,19 @@ static const cfg_op_t _display_dc_setup_win_config[94] = {
{DC_WIN_CSC_KUB, 0x204}, {DC_WIN_CSC_KUB, 0x204},
{DC_WIN_CSC_KVB, 0}, {DC_WIN_CSC_KVB, 0},
/* End of color coefficients */ /* End of color coefficients */
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_WIN_DV_CONTROL, 0},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
/* 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_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_WIN_DV_CONTROL, 0},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
/* 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_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888}, {DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888},
{DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C}, {DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C},
{DC_COM_PIN_OUTPUT_POLARITY(1), 0x1000000}, {DC_COM_PIN_OUTPUT_POLARITY(1), LSC0_OUTPUT_POLARITY_LOW},
{DC_COM_PIN_OUTPUT_POLARITY(3), 0}, {DC_COM_PIN_OUTPUT_POLARITY(3), 0},
{DC_DISP_BLEND_BACKGROUND_COLOR, 0}, {DC_DISP_BLEND_BACKGROUND_COLOR, 0},
{DC_COM_CRC_CONTROL, 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_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_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT},
{DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF}, {DC_WINBUF_BLEND_LAYER_CONTROL, WIN_BLEND_BYPASS | WIN_BLEND_DEPTH(255)},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF},
{DC_CMD_DISPLAY_COMMAND_OPTION0, 0}, {DC_CMD_DISPLAY_COMMAND_OPTION0, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_WIN_WIN_OPTIONS, 0}, {DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, 0}, {DC_DISP_DISP_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_STOP}, {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_STOP},
@@ -119,18 +68,18 @@ static const cfg_op_t _display_dc_setup_win_config[94] = {
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ} {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ}
}; };
//DSI Init config. // DSI Init config.
static const cfg_op_t _display_dsi_init_config_part1[8] = { static const cfg_op_t _di_dsi_init_irq_pkt_config0[] = {
{DSI_WR_DATA, 0}, {DSI_WR_DATA, 0},
{DSI_INT_ENABLE, 0}, {DSI_INT_ENABLE, 0},
{DSI_INT_STATUS, 0}, {DSI_INT_STATUS, 0},
{DSI_INT_MASK, 0}, {DSI_INT_MASK, 0},
{DSI_INIT_SEQ_DATA_0, 0}, {DSI_INIT_SEQ_DATA_0, 0},
{DSI_INIT_SEQ_DATA_1, 0}, {DSI_INIT_SEQ_DATA_1, 0},
{DSI_INIT_SEQ_DATA_2, 0}, {DSI_INIT_SEQ_DATA_2, 0},
{DSI_INIT_SEQ_DATA_3, 0} {DSI_INIT_SEQ_DATA_3, 0}
}; };
static const cfg_op_t _display_dsi_init_config_part2[14] = { static const cfg_op_t _di_dsi_init_irq_pkt_config1[] = {
{DSI_DCS_CMDS, 0}, {DSI_DCS_CMDS, 0},
{DSI_PKT_SEQ_0_LO, 0}, {DSI_PKT_SEQ_0_LO, 0},
{DSI_PKT_SEQ_1_LO, 0}, {DSI_PKT_SEQ_1_LO, 0},
@@ -146,7 +95,7 @@ static const cfg_op_t _display_dsi_init_config_part2[14] = {
{DSI_PKT_SEQ_5_HI, 0}, {DSI_PKT_SEQ_5_HI, 0},
{DSI_CONTROL, 0} {DSI_CONTROL, 0}
}; };
static const cfg_op_t _display_dsi_init_config_part3_t210b01[7] = { static const cfg_op_t _di_dsi_init_pads_t210b01[] = {
{DSI_PAD_CONTROL_1, 0}, {DSI_PAD_CONTROL_1, 0},
{DSI_PAD_CONTROL_2, 0}, {DSI_PAD_CONTROL_2, 0},
{DSI_PAD_CONTROL_3, 0}, {DSI_PAD_CONTROL_3, 0},
@@ -155,10 +104,10 @@ static const cfg_op_t _display_dsi_init_config_part3_t210b01[7] = {
{DSI_PAD_CONTROL_6_B01, 0}, {DSI_PAD_CONTROL_6_B01, 0},
{DSI_PAD_CONTROL_7_B01, 0} {DSI_PAD_CONTROL_7_B01, 0}
}; };
static const cfg_op_t _display_dsi_init_config_part4[10] = { static const cfg_op_t _di_dsi_init_timing_pkt_config2[] = {
{DSI_PAD_CONTROL_CD, 0}, {DSI_PAD_CONTROL_CD, 0},
{DSI_SOL_DELAY, 0x18}, {DSI_SOL_DELAY, 24},
{DSI_MAX_THRESHOLD, 0x1E0}, {DSI_MAX_THRESHOLD, 480},
{DSI_TRIGGER, 0}, {DSI_TRIGGER, 0},
{DSI_INIT_SEQ_CONTROL, 0}, {DSI_INIT_SEQ_CONTROL, 0},
{DSI_PKT_LEN_0_1, 0}, {DSI_PKT_LEN_0_1, 0},
@@ -167,12 +116,12 @@ static const cfg_op_t _display_dsi_init_config_part4[10] = {
{DSI_PKT_LEN_6_7, 0}, {DSI_PKT_LEN_6_7, 0},
{DSI_PAD_CONTROL_1, 0} {DSI_PAD_CONTROL_1, 0}
}; };
static const cfg_op_t _display_dsi_init_config_part5[12] = { static const cfg_op_t _di_dsi_init_timing_pwrctrl_config[] = {
{DSI_PHY_TIMING_1, 0x40A0E05}, {DSI_PHY_TIMING_1, 0x40A0E05},
{DSI_PHY_TIMING_2, 0x30109}, {DSI_PHY_TIMING_2, 0x30109},
{DSI_BTA_TIMING, 0x190A14}, {DSI_BTA_TIMING, 0x190A14},
{DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF)}, {DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF)},
{DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x765) | DSI_TIMEOUT_TA(0x2000)}, {DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x765) | DSI_TIMEOUT_TA(0x2000)},
{DSI_TO_TALLY, 0}, {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)}, // Enable
{DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, {DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
@@ -181,25 +130,25 @@ static const cfg_op_t _display_dsi_init_config_part5[12] = {
{DSI_POWER_CONTROL, 0}, {DSI_POWER_CONTROL, 0},
{DSI_PAD_CONTROL_1, 0} {DSI_PAD_CONTROL_1, 0}
}; };
static const cfg_op_t _display_dsi_init_config_part6[14] = { static const cfg_op_t _di_dsi_init_timing_pkt_config3[] = {
{DSI_PHY_TIMING_1, 0x40A0E05}, {DSI_PHY_TIMING_1, 0x40A0E05},
{DSI_PHY_TIMING_2, 0x30118}, {DSI_PHY_TIMING_2, 0x30118},
{DSI_BTA_TIMING, 0x190A14}, {DSI_BTA_TIMING, 0x190A14},
{DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF)}, {DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF)},
{DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x1343) | DSI_TIMEOUT_TA(0x2000)}, {DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x1343) | DSI_TIMEOUT_TA(0x2000)},
{DSI_TO_TALLY, 0}, {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_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_CONTROL, DSI_CONTROL_LANES(3) | DSI_CONTROL_HOST_ENABLE},
{DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, {DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, {DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{DSI_MAX_THRESHOLD, 0x40}, {DSI_MAX_THRESHOLD, 64},
{DSI_TRIGGER, 0}, {DSI_TRIGGER, 0},
{DSI_TX_CRC, 0}, {DSI_TX_CRC, 0},
{DSI_INIT_SEQ_CONTROL, 0} {DSI_INIT_SEQ_CONTROL, 0}
}; };
//DSI panel config. // DSI panel JDI config.
static const cfg_op_t _display_init_config_jdi[43] = { static const cfg_op_t _di_dsi_panel_init_config_jdi[] = {
{DSI_WR_DATA, 0x0439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes. {DSI_WR_DATA, 0x0439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
{DSI_WR_DATA, 0x9483FFB9}, // MIPI_DCS_PRIV_SET_EXTC. (Pass: FF 83 94). {DSI_WR_DATA, 0x9483FFB9}, // MIPI_DCS_PRIV_SET_EXTC. (Pass: FF 83 94).
{DSI_TRIGGER, DSI_TRIGGER_HOST}, {DSI_TRIGGER, DSI_TRIGGER_HOST},
@@ -245,13 +194,13 @@ static const cfg_op_t _display_init_config_jdi[43] = {
{DSI_TRIGGER, DSI_TRIGGER_HOST} {DSI_TRIGGER, DSI_TRIGGER_HOST}
}; };
//DSI packet config. // DSI packet config.
static const cfg_op_t _display_dsi_packet_config[19] = { static const cfg_op_t _di_dsi_init_seq_pkt_final_config[] = {
{DSI_PHY_TIMING_1, 0x40A0E05}, {DSI_PHY_TIMING_1, 0x40A0E05},
{DSI_PHY_TIMING_2, 0x30172}, {DSI_PHY_TIMING_2, 0x30172},
{DSI_BTA_TIMING, 0x190A14}, {DSI_BTA_TIMING, 0x190A14},
{DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xA40)}, {DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xA40)},
{DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x5A2F) | DSI_TIMEOUT_TA(0x2000)}, {DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x5A2F) | DSI_TIMEOUT_TA(0x2000)},
{DSI_TO_TALLY, 0}, {DSI_TO_TALLY, 0},
{DSI_PKT_SEQ_0_LO, 0x40000208}, {DSI_PKT_SEQ_0_LO, 0x40000208},
{DSI_PKT_SEQ_2_LO, 0x40000308}, {DSI_PKT_SEQ_2_LO, 0x40000308},
@@ -261,66 +210,66 @@ static const cfg_op_t _display_dsi_packet_config[19] = {
{DSI_PKT_SEQ_3_HI, 0x2CC}, {DSI_PKT_SEQ_3_HI, 0x2CC},
{DSI_PKT_SEQ_5_LO, 0x3F3B2B08}, {DSI_PKT_SEQ_5_LO, 0x3F3B2B08},
{DSI_PKT_SEQ_5_HI, 0x2CC}, {DSI_PKT_SEQ_5_HI, 0x2CC},
{DSI_PKT_LEN_0_1, 0xCE0000}, {DSI_PKT_LEN_0_1, PKT1_LEN(206) | PKT0_LEN(0)},
{DSI_PKT_LEN_2_3, 0x87001A2}, {DSI_PKT_LEN_2_3, PKT1_LEN(2160) | PKT0_LEN(418)},
{DSI_PKT_LEN_4_5, 0x190}, {DSI_PKT_LEN_4_5, PKT1_LEN(0) | PKT0_LEN(400)},
{DSI_PKT_LEN_6_7, 0x190}, {DSI_PKT_LEN_6_7, PKT1_LEN(0) | PKT0_LEN(400)},
{DSI_HOST_CONTROL, 0} {DSI_HOST_CONTROL, 0}
}; };
//DSI mode config. // DSI mode config.
static const cfg_op_t _display_dsi_mode_config[10] = { static const cfg_op_t _di_dsi_mode_config[] = {
{DSI_TRIGGER, 0}, {DSI_TRIGGER, 0},
{DSI_CONTROL, 0}, {DSI_CONTROL, 0},
{DSI_SOL_DELAY, 6}, {DSI_SOL_DELAY, 6},
{DSI_MAX_THRESHOLD, 0x1E0}, {DSI_MAX_THRESHOLD, 480},
{DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, {DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{DSI_CONTROL, DSI_CONTROL_HS_CLK_CTRL | DSI_CONTROL_FORMAT(3) | DSI_CONTROL_LANES(3) | DSI_CONTROL_VIDEO_ENABLE}, {DSI_CONTROL, DSI_CONTROL_HS_CLK_CTRL | DSI_CONTROL_FORMAT(3) | DSI_CONTROL_LANES(3) | DSI_CONTROL_VIDEO_ENABLE},
{DSI_HOST_CONTROL, DSI_HOST_CONTROL_HS | DSI_HOST_CONTROL_FIFO_SEL| DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC}, {DSI_HOST_CONTROL, DSI_HOST_CONTROL_HS | DSI_HOST_CONTROL_FIFO_SEL | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC},
{DSI_CONTROL, DSI_CONTROL_HS_CLK_CTRL | DSI_CONTROL_FORMAT(3) | DSI_CONTROL_LANES(3) | DSI_CONTROL_VIDEO_ENABLE}, {DSI_CONTROL, DSI_CONTROL_HS_CLK_CTRL | DSI_CONTROL_FORMAT(3) | DSI_CONTROL_LANES(3) | DSI_CONTROL_VIDEO_ENABLE},
{DSI_HOST_CONTROL, DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC}, {DSI_HOST_CONTROL, DSI_HOST_CONTROL_TX_TRIG_SOL | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC},
{DSI_HOST_CONTROL, DSI_HOST_CONTROL_HS | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC} {DSI_HOST_CONTROL, DSI_HOST_CONTROL_HS | DSI_HOST_CONTROL_TX_TRIG_SOL | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC}
}; };
//MIPI CAL config. // MIPI CAL config.
static const cfg_op_t _display_mipi_pad_cal_config[4] = { static const cfg_op_t _di_mipi_pad_cal_config[] = {
{MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0}, {MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0},
{MIPI_CAL_CIL_MIPI_CAL_STATUS, 0xF3F10000}, {MIPI_CAL_CIL_MIPI_CAL_STATUS, 0xF3F10000},
{MIPI_CAL_MIPI_BIAS_PAD_CFG0, 0}, {MIPI_CAL_MIPI_BIAS_PAD_CFG0, 0},
{MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0} {MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0}
}; };
//DSI config. // DSI pad config.
static const cfg_op_t _display_dsi_pad_cal_config_t210[4] = { static const cfg_op_t _di_dsi_pad_cal_config_t210[] = {
{DSI_PAD_CONTROL_1, 0}, {DSI_PAD_CONTROL_1, 0},
{DSI_PAD_CONTROL_2, 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_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} {DSI_PAD_CONTROL_4, 0}
}; };
static const cfg_op_t _display_dsi_pad_cal_config_t210b01[7] = { static const cfg_op_t _di_dsi_pad_cal_config_t210b01[] = {
{DSI_PAD_CONTROL_1, 0}, {DSI_PAD_CONTROL_1, 0},
{DSI_PAD_CONTROL_2, 0}, {DSI_PAD_CONTROL_2, 0},
{DSI_PAD_CONTROL_3, 0}, {DSI_PAD_CONTROL_3, 0},
{DSI_PAD_CONTROL_4, 0x77777}, {DSI_PAD_CONTROL_4, 0x77777},
{DSI_PAD_CONTROL_5_B01, 0x77777}, {DSI_PAD_CONTROL_5_B01, 0x77777},
{DSI_PAD_CONTROL_6_B01, 0x1111}, {DSI_PAD_CONTROL_6_B01, DSI_PAD_PREEMP_PD_CLK(0x1) | DSI_PAD_PREEMP_PU_CLK(0x1) | DSI_PAD_PREEMP_PD(0x01) | DSI_PAD_PREEMP_PU(0x1)},
{DSI_PAD_CONTROL_7_B01, 0} {DSI_PAD_CONTROL_7_B01, 0}
}; };
//MIPI CAL config. // MIPI CAL config.
static const cfg_op_t _display_mipi_dsi_cal_offsets_config_t210[4] = { static const cfg_op_t _di_mipi_dsi_cal_offsets_config_t210[] = {
{MIPI_CAL_DSIA_MIPI_CAL_CONFIG, 0x200200}, {MIPI_CAL_DSIA_MIPI_CAL_CONFIG, 0x200200},
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG, 0x200200}, {MIPI_CAL_DSIB_MIPI_CAL_CONFIG, 0x200200},
{MIPI_CAL_DSIA_MIPI_CAL_CONFIG_2, 0x200002}, {MIPI_CAL_DSIA_MIPI_CAL_CONFIG_2, 0x200002},
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0x200002} {MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0x200002}
}; };
static const cfg_op_t _display_mipi_dsi_cal_offsets_config_t210b01[4] = { static const cfg_op_t _di_mipi_dsi_cal_offsets_config_t210b01[] = {
{MIPI_CAL_DSIA_MIPI_CAL_CONFIG, 0x200006}, {MIPI_CAL_DSIA_MIPI_CAL_CONFIG, 0x200006},
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG, 0x200006}, {MIPI_CAL_DSIB_MIPI_CAL_CONFIG, 0x200006},
{MIPI_CAL_DSIA_MIPI_CAL_CONFIG_2, 0x260000}, {MIPI_CAL_DSIA_MIPI_CAL_CONFIG_2, 0x260000},
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0x260000} {MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0x260000}
}; };
static const cfg_op_t _display_mipi_apply_dsi_cal_config[12] = { static const cfg_op_t _di_mipi_start_dsi_cal_config[] = {
{MIPI_CAL_CILA_MIPI_CAL_CONFIG, 0}, {MIPI_CAL_CILA_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_CILB_MIPI_CAL_CONFIG, 0}, {MIPI_CAL_CILB_MIPI_CAL_CONFIG, 0},
{MIPI_CAL_CILC_MIPI_CAL_CONFIG, 0}, {MIPI_CAL_CILC_MIPI_CAL_CONFIG, 0},
@@ -332,19 +281,17 @@ static const cfg_op_t _display_mipi_apply_dsi_cal_config[12] = {
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0}, {MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0},
{MIPI_CAL_DSIC_MIPI_CAL_CONFIG_2, 0}, {MIPI_CAL_DSIC_MIPI_CAL_CONFIG_2, 0},
{MIPI_CAL_DSID_MIPI_CAL_CONFIG_2, 0}, {MIPI_CAL_DSID_MIPI_CAL_CONFIG_2, 0},
{MIPI_CAL_MIPI_CAL_CTRL, 0x2A000001} {MIPI_CAL_MIPI_CAL_CTRL, 0x2A000001} // Set Prescale and filter and start calibration.
}; };
//Display A config. // Display A enable config.
static const cfg_op_t _display_video_disp_controller_enable_config[113] = { static const cfg_op_t _di_dc_video_enable_config[] = {
{DC_CMD_STATE_ACCESS, 0}, {DC_CMD_STATE_ACCESS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
/* 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_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, {DC_WIN_DV_CONTROL, 0},
{DC_WIN_DV_CONTROL, 0},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
/* Setup default YUV colorspace conversion coefficients */ /* Setup default YUV colorspace conversion coefficients */
{DC_WIN_CSC_YOF, 0xF0}, {DC_WIN_CSC_YOF, 0xF0},
{DC_WIN_CSC_KYRGB, 0x12A}, {DC_WIN_CSC_KYRGB, 0x12A},
@@ -355,66 +302,19 @@ static const cfg_op_t _display_video_disp_controller_enable_config[113] = {
{DC_WIN_CSC_KUB, 0x204}, {DC_WIN_CSC_KUB, 0x204},
{DC_WIN_CSC_KVB, 0}, {DC_WIN_CSC_KVB, 0},
/* End of color coefficients */ /* End of color coefficients */
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_WIN_DV_CONTROL, 0},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
/* 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_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_WIN_DV_CONTROL, 0},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
/* 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_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888}, {DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888},
{DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C}, {DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C},
{DC_COM_PIN_OUTPUT_POLARITY(1), 0x1000000}, {DC_COM_PIN_OUTPUT_POLARITY(1), LSC0_OUTPUT_POLARITY_LOW},
{DC_COM_PIN_OUTPUT_POLARITY(3), 0}, {DC_COM_PIN_OUTPUT_POLARITY(3), 0},
{DC_DISP_BLEND_BACKGROUND_COLOR, 0}, {DC_DISP_BLEND_BACKGROUND_COLOR, 0},
{DC_COM_CRC_CONTROL, 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_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_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT},
{DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF}, {DC_WINBUF_BLEND_LAYER_CONTROL, WIN_BLEND_BYPASS | WIN_BLEND_DEPTH(255)},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF},
{DC_CMD_DISPLAY_COMMAND_OPTION0, 0}, {DC_CMD_DISPLAY_COMMAND_OPTION0, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_WIN_WIN_OPTIONS, 0}, {DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, 0}, {DC_DISP_DISP_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_STOP}, {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_STOP},
@@ -422,34 +322,13 @@ static const cfg_op_t _display_video_disp_controller_enable_config[113] = {
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ}, {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_ACCESS, 0},
/* Set Display timings /* Set panel timings */
* {DC_DISP_DISP_TIMING_OPTIONS, VSYNC_H_POSITION(0)},
* DC_DISP_REF_TO_SYNC: {DC_DISP_REF_TO_SYNC, V_REF_TO_SYNC(1) | H_REF_TO_SYNC(0)},
* V_REF_TO_SYNC - 1 {DC_DISP_SYNC_WIDTH, V_SYNC_WIDTH(1) | H_SYNC_WIDTH(72)},
* H_REF_TO_SYNC - 0 {DC_DISP_BACK_PORCH, V_BACK_PORCH(9) | H_BACK_PORCH(72)},
* {DC_DISP_FRONT_PORCH, V_FRONT_PORCH(10) | H_FRONT_PORCH(136)},
* DC_DISP_SYNC_WIDTH: {DC_DISP_ACTIVE, V_DISP_ACTIVE(1280) | H_DISP_ACTIVE(720)},
* V_SYNC_WIDTH - 1
* H_SYNC_WIDTH - 72
*
* DC_DISP_BACK_PORCH:
* V_BACK_PORCH - 9
* H_BACK_PORCH - 72
*
* DC_DISP_ACTIVE:
* V_DISP_ACTIVE - 1280
* H_DISP_ACTIVE - 720
*
* DC_DISP_FRONT_PORCH:
* V_FRONT_PORCH - 10
* H_FRONT_PORCH - 136
*/
{DC_DISP_DISP_TIMING_OPTIONS, 0},
{DC_DISP_REF_TO_SYNC, 0x10000},
{DC_DISP_SYNC_WIDTH, 0x10048},
{DC_DISP_BACK_PORCH, 0x90048},
{DC_DISP_ACTIVE, 0x50002D0},
{DC_DISP_FRONT_PORCH, 0xA0088}, // Sources say that this should happen before DC_DISP_ACTIVE cmd.
/* End of Display timings */ /* End of Display timings */
{DC_DISP_SHIFT_CLOCK_OPTIONS, SC1_H_QUALIFIER_NONE | SC0_H_QUALIFIER_NONE}, {DC_DISP_SHIFT_CLOCK_OPTIONS, SC1_H_QUALIFIER_NONE | SC0_H_QUALIFIER_NONE},
@@ -458,23 +337,18 @@ static const cfg_op_t _display_video_disp_controller_enable_config[113] = {
{DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C}, {DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C},
{DC_DISP_DISP_CLOCK_CONTROL, 0}, {DC_DISP_DISP_CLOCK_CONTROL, 0},
{DC_CMD_DISPLAY_COMMAND_OPTION0, 0}, {DC_CMD_DISPLAY_COMMAND_OPTION0, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_WIN_WIN_OPTIONS, 0}, {DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, 0}, {DC_DISP_DISP_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY},
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, {DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{DC_CMD_STATE_ACCESS, READ_MUX | WRITE_MUX}, {DC_CMD_STATE_ACCESS, READ_MUX | WRITE_MUX},
{DC_DISP_FRONT_PORCH, 0xA0088}, {DC_DISP_FRONT_PORCH, V_FRONT_PORCH(10) | H_FRONT_PORCH(136)},
{DC_CMD_STATE_ACCESS, 0}, {DC_CMD_STATE_ACCESS, 0},
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, {DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{DC_CMD_GENERAL_INCR_SYNCPT, 0x301}, {DC_CMD_GENERAL_INCR_SYNCPT, SYNCPT_GENERAL_COND(COND_REG_WR_SAFE) | SYNCPT_GENERAL_INDX(1)},
{DC_CMD_GENERAL_INCR_SYNCPT, 0x301},
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, {DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{DC_CMD_STATE_ACCESS, 0}, {DC_CMD_STATE_ACCESS, 0},
@@ -483,9 +357,9 @@ static const cfg_op_t _display_video_disp_controller_enable_config[113] = {
{DC_CMD_DISPLAY_COMMAND_OPTION0, 0} {DC_CMD_DISPLAY_COMMAND_OPTION0, 0}
}; };
////Display A config. // Display A disable config.
static const cfg_op_t _display_video_disp_controller_disable_config[17] = { static const cfg_op_t _di_dc_video_disable_config[] = {
{DC_DISP_FRONT_PORCH, 0xA0088}, {DC_DISP_FRONT_PORCH, V_FRONT_PORCH(10) | H_FRONT_PORCH(136)},
{DC_CMD_INT_MASK, 0}, {DC_CMD_INT_MASK, 0},
{DC_CMD_STATE_ACCESS, 0}, {DC_CMD_STATE_ACCESS, 0},
{DC_CMD_INT_ENABLE, 0}, {DC_CMD_INT_ENABLE, 0},
@@ -493,39 +367,37 @@ static const cfg_op_t _display_video_disp_controller_disable_config[17] = {
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_STOP}, {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_STOP},
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, {DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, {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_STATE_CONTROL, GENERAL_UPDATE}, {DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{DC_CMD_GENERAL_INCR_SYNCPT, 0x301}, // LCD panels should sleep for 40ms here.
{DC_CMD_GENERAL_INCR_SYNCPT, 0x301},
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
{DC_CMD_DISPLAY_POWER_CONTROL, 0}, {DC_CMD_DISPLAY_POWER_CONTROL, 0},
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, {DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
}; };
//DSI config. // DSI deinit config.
static const cfg_op_t _display_dsi_timing_deinit_config[16] = { static const cfg_op_t _di_dsi_timing_deinit_config[] = {
{DSI_POWER_CONTROL, 0}, {DSI_POWER_CONTROL, 0},
{DSI_PAD_CONTROL_1, 0}, {DSI_PAD_CONTROL_1, 0},
{DSI_PHY_TIMING_0, 0x6070601}, {DSI_PHY_TIMING_0, 0x6070601}, //mariko changes
{DSI_PHY_TIMING_1, 0x40A0E05}, {DSI_PHY_TIMING_1, 0x40A0E05},
{DSI_PHY_TIMING_2, 0x30118}, {DSI_PHY_TIMING_2, 0x30118},
{DSI_BTA_TIMING, 0x190A14}, {DSI_BTA_TIMING, 0x190A14},
{DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF) }, {DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF) },
{DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x1343) | DSI_TIMEOUT_TA(0x2000)}, {DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x1343) | DSI_TIMEOUT_TA(0x2000)},
{DSI_TO_TALLY, 0}, {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_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_CONTROL, DSI_CONTROL_LANES(3) | DSI_CONTROL_HOST_ENABLE},
{DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, {DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE},
{DSI_MAX_THRESHOLD, 0x40}, {DSI_MAX_THRESHOLD, 64},
{DSI_TRIGGER, 0}, {DSI_TRIGGER, 0},
{DSI_TX_CRC, 0}, {DSI_TX_CRC, 0},
{DSI_INIT_SEQ_CONTROL, 0} {DSI_INIT_SEQ_CONTROL, 0}
}; };
//DSI config (if ver == 0x10). // DSI panel JDI deinit config.
static const cfg_op_t _display_deinit_config_jdi[22] = { static const cfg_op_t _di_dsi_panel_deinit_config_jdi[] = {
{DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes. {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_WR_DATA, 0x9483FFB9}, // MIPI_DCS_PRIV_SET_EXTC. (Pass: FF 83 94).
{DSI_TRIGGER, DSI_TRIGGER_HOST}, {DSI_TRIGGER, DSI_TRIGGER_HOST},
@@ -550,7 +422,8 @@ static const cfg_op_t _display_deinit_config_jdi[22] = {
{DSI_TRIGGER, DSI_TRIGGER_HOST} {DSI_TRIGGER, DSI_TRIGGER_HOST}
}; };
static const cfg_op_t _display_deinit_config_auo[37] = { // DSI panel AUO deinit config.
static const cfg_op_t _di_dsi_panel_deinit_config_auo[] = {
{DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes. {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_WR_DATA, 0x9483FFB9}, // MIPI_DCS_PRIV_SET_EXTC. (Pass: FF 83 94).
{DSI_TRIGGER, DSI_TRIGGER_HOST}, {DSI_TRIGGER, DSI_TRIGGER_HOST},
@@ -591,156 +464,143 @@ static const cfg_op_t _display_deinit_config_auo[37] = {
{DSI_TRIGGER, DSI_TRIGGER_HOST} {DSI_TRIGGER, DSI_TRIGGER_HOST}
}; };
static const cfg_op_t _display_init_config_invert[3] = { static const cfg_op_t _di_init_config_invert[] = {
{DSI_WR_DATA, 0x239}, {DSI_WR_DATA, 0x239},
{DSI_WR_DATA, 0x02C1}, // INV_EN. {DSI_WR_DATA, 0x02C1}, // INV_EN.
{DSI_TRIGGER, DSI_TRIGGER_HOST}, {DSI_TRIGGER, DSI_TRIGGER_HOST},
}; };
//Display A config. // Display A Window A one color config.
static const cfg_op_t cfg_display_one_color[8] = { static const cfg_op_t _di_win_one_color[] = {
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_WIN_WIN_OPTIONS, 0}, {DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY} // Continuous display. {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY} // Continuous display.
}; };
//Display A config linear pitch. // Display A Window A linear pitch config.
static const cfg_op_t cfg_display_framebuffer_pitch[32] = { static const cfg_op_t _di_win_framebuffer_pitch[] = {
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT | WINDOW_B_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_WIN_WIN_OPTIONS, 0}, {DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{DC_WIN_WIN_OPTIONS, 0}, {DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, // NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8. {DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, // NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8.
{DC_WIN_WIN_OPTIONS, 0},
{DC_WIN_WIN_OPTIONS, 0},
{DC_WIN_POSITION, 0}, //(0,0) {DC_WIN_POSITION, 0}, //(0,0)
{DC_WIN_H_INITIAL_DDA, 0}, {DC_WIN_H_INITIAL_DDA, 0},
{DC_WIN_V_INITIAL_DDA, 0}, {DC_WIN_V_INITIAL_DDA, 0},
{DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(720 * 4)}, {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(720 * 4)},
{DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x. {DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x.
{DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)}, {DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)},
{DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(720 * 2) | LINE_STRIDE(720 * 4)}, // 720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements. {DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(720 * 2) | LINE_STRIDE(720 * 4)}, // 720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
{DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST}, {DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST},
{DC_WINBUF_SURFACE_KIND, PITCH}, {DC_WINBUF_SURFACE_KIND, PITCH},
{DC_WINBUF_START_ADDR, IPL_FB_ADDRESS}, // Framebuffer address. {DC_WINBUF_START_ADDR, IPL_FB_ADDRESS}, // Framebuffer address.
{DC_WINBUF_ADDR_H_OFFSET, 0}, {DC_WINBUF_ADDR_H_OFFSET, 0},
{DC_WINBUF_ADDR_V_OFFSET, 0}, {DC_WINBUF_ADDR_V_OFFSET, 0},
{DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{DC_WIN_WIN_OPTIONS, WIN_ENABLE}, // Enable window AD. {DC_WIN_WIN_OPTIONS, WIN_ENABLE}, // Enable window AD.
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, // Continuous display. {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} {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ}
}; };
//Display A config linear pitch inverse + Win D support. // Display A Window A linear pitch + Win D support config.
static const cfg_op_t cfg_display_framebuffer_pitch_inv[34] = { static const cfg_op_t _di_win_framebuffer_pitch_vic[] = {
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT}, {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT | WINDOW_C_SELECT | WINDOW_B_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_WIN_WIN_OPTIONS, 0}, {DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{DC_WIN_WIN_OPTIONS, 0}, {DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, // NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8. {DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, // NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8.
{DC_WIN_WIN_OPTIONS, 0},
{DC_WIN_WIN_OPTIONS, 0},
{DC_WIN_POSITION, 0}, //(0,0) {DC_WIN_POSITION, 0}, //(0,0)
{DC_WIN_H_INITIAL_DDA, 0}, {DC_WIN_H_INITIAL_DDA, 0},
{DC_WIN_V_INITIAL_DDA, 0}, {DC_WIN_V_INITIAL_DDA, 0},
{DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(720 * 4)}, {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(720 * 4)},
{DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x. {DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x.
{DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)}, {DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)},
{DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(720 * 2) | LINE_STRIDE(720 * 4)}, // 720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements. {DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(720 * 2) | LINE_STRIDE(720 * 4)}, // 720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
{DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST},
{DC_WINBUF_SURFACE_KIND, PITCH},
{DC_WINBUF_START_ADDR, NYX_FB_ADDRESS}, // Framebuffer address.
{DC_WINBUF_ADDR_H_OFFSET, 0},
{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_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},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, // NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8.
{DC_WIN_POSITION, 0}, //(0,0)
{DC_WIN_H_INITIAL_DDA, 0},
{DC_WIN_V_INITIAL_DDA, 0},
{DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(720 * 4)},
{DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x.
{DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)},
{DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(720 * 2) | LINE_STRIDE(720 * 4)}, // 720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
{DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST}, {DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST},
{DC_WINBUF_SURFACE_KIND, PITCH}, {DC_WINBUF_SURFACE_KIND, PITCH},
{DC_WINBUF_START_ADDR, NYX_FB_ADDRESS}, // Framebuffer address. {DC_WINBUF_START_ADDR, NYX_FB_ADDRESS}, // Framebuffer address.
{DC_WINBUF_ADDR_H_OFFSET, 0}, // Linear: 0x383FFC, Block: 0x3813FC. {DC_WINBUF_ADDR_H_OFFSET, 0}, // Linear: 0x383FFC, Block: 0x3813FC.
{DC_WINBUF_ADDR_V_OFFSET, 1279}, // Linear: 1279, Block: 0. {DC_WINBUF_ADDR_V_OFFSET, 1279}, // Linear: 1279, Block: 0.
{DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{DC_WIN_WIN_OPTIONS, WIN_ENABLE | V_DIRECTION}, // Enable window AD. {DC_WIN_WIN_OPTIONS, WIN_ENABLE | V_DIRECTION}, // Enable window AD.
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, // Continuous display. {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} {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ}
}; };
//Display A config block linear. // Display A Window A block linear config.
static const cfg_op_t cfg_display_framebuffer_block[34] = { static const cfg_op_t _di_win_framebuffer_block[] = {
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT}, {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT | WINDOW_C_SELECT | WINDOW_B_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{DC_WIN_WIN_OPTIONS, 0}, {DC_WIN_WIN_OPTIONS, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{DC_WIN_WIN_OPTIONS, 0}, {DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, // NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8. {DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, // NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8.
{DC_WIN_WIN_OPTIONS, 0},
{DC_WIN_WIN_OPTIONS, 0},
{DC_WIN_POSITION, 0}, //(0,0) {DC_WIN_POSITION, 0}, //(0,0)
{DC_WIN_H_INITIAL_DDA, 0}, {DC_WIN_H_INITIAL_DDA, 0},
{DC_WIN_V_INITIAL_DDA, 0}, {DC_WIN_V_INITIAL_DDA, 0},
{DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(720 * 4)}, {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(720 * 4)},
{DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x. {DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x.
{DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)}, {DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)},
{DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(1280 * 2) | LINE_STRIDE(1280 * 4)}, //720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements. {DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(1280 * 2) | LINE_STRIDE(1280 * 4)}, //720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
{DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST}, {DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST},
{DC_WINBUF_SURFACE_KIND, BLOCK_HEIGHT(4) | BLOCK}, {DC_WINBUF_SURFACE_KIND, BLOCK_HEIGHT(4) | BLOCK},
{DC_WINBUF_START_ADDR, NYX_FB_ADDRESS}, // Framebuffer address. {DC_WINBUF_START_ADDR, NYX_FB_ADDRESS}, // Framebuffer address.
{DC_WINBUF_ADDR_H_OFFSET, 0x3813FC}, // Linear: 0x383FFC, Block: 0x3813FC. {DC_WINBUF_ADDR_H_OFFSET, 0x3813FC}, // Linear: 0x383FFC, Block: 0x3813FC. Block in HOS: 0x13FF.
{DC_WINBUF_ADDR_V_OFFSET, 0}, // Linear: 1279, Block: 0. {DC_WINBUF_ADDR_V_OFFSET, 0}, // Linear: 1279, Block: 0.
{DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
{DC_WIN_WIN_OPTIONS, WIN_ENABLE | SCAN_COLUMN | H_DIRECTION}, // Enable window AD. | SCAN_COLUMN | H_DIRECTION. {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_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} {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ}
}; };
//Display D config. // Display A Window D config.
static const cfg_op_t cfg_display_framebuffer_log[20] = { static const cfg_op_t _di_win_framebuffer_log[] = {
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT}, {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT},
{DC_WIN_WIN_OPTIONS, 0}, {DC_WIN_WIN_OPTIONS, 0},
{DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, {DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8},
{DC_WIN_POSITION, 0}, //(0,0) {DC_WIN_POSITION, 0}, //(0,0)
{DC_WIN_H_INITIAL_DDA, 0}, {DC_WIN_H_INITIAL_DDA, 0},
{DC_WIN_V_INITIAL_DDA, 0}, {DC_WIN_V_INITIAL_DDA, 0},
{DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(656 * 4)}, {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(656 * 4)},
{DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x. {DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x.
{DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(656)}, {DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(656)},
{DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(656 * 2) | LINE_STRIDE(656 * 4)}, //656*2x656*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements. {DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(656 * 2) | LINE_STRIDE(656 * 4)}, //656*2x656*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
{DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST}, {DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST},
{DC_WINBUF_SURFACE_KIND, PITCH}, {DC_WINBUF_SURFACE_KIND, PITCH},
{DC_WINBUF_START_ADDR, LOG_FB_ADDRESS}, // Framebuffer address. {DC_WINBUF_START_ADDR, LOG_FB_ADDRESS}, // Framebuffer address.
{DC_WINBUF_ADDR_H_OFFSET, 0}, {DC_WINBUF_ADDR_H_OFFSET, 0},
{DC_WINBUF_ADDR_V_OFFSET, 0}, {DC_WINBUF_ADDR_V_OFFSET, 0},
{DC_WINBUF_BLEND_LAYER_CONTROL, WIN_BLEND_ENABLE | WIN_K1(200)}, {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_WINBUF_BLEND_MATCH_SELECT, WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_K1 | WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_NEG_K1},
{DC_WIN_WIN_OPTIONS, 0}, // Enable window DD.
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_D_UPDATE}, {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_ACT_REQ | WIN_D_ACT_REQ}
}; };

563
bdk/display/vic.c Normal file
View File

@@ -0,0 +1,563 @@
/*
* VIC driver for Tegra X1
*
* Copyright (c) 2018-2023 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "vic.h"
#include <mem/heap.h>
#include <soc/bpmp.h>
#include <soc/clock.h>
#include <soc/timer.h>
#include <soc/t210.h>
#include <utils/types.h>
/* VIC Private registers */
#define PVIC_FALCON_PA_OFFSET 0x1000
#define PVIC_FALCON_ADDR 0x10AC
#define PVIC_FALCON_IDLESTATE 0x104C
/* VIC Control and Status registers. */
/* Fetch Control registers. */
#define VIC_FC_COMPOSE 0x10000
#define COMPOSE_START BIT(0)
#define VIC_FC_CFG_STRUCT_SLOT_INDEX 0x10B00
#define VIC_FC_CFG_STRUCT_SLOT_CFG0 0x10B04
#define SLOT_ENABLE BIT(0)
#define FIELD_CURRENT_ENABLE BIT(8)
#define VIC_FC_CFG_STRUCT_SLOT_CFG2 0x10B0C
#define CACHE_WIDTH(n) ((n) << 16)
#define CACHE_WIDTH_16BX16 0 // Block Linear.
#define CACHE_WIDTH_32BX8 1 // Block Linear. Recommended for Block Linear.
#define CACHE_WIDTH_64BX4 2 // Block Linear, Pitch. Recommended for Pitch.
#define CACHE_WIDTH_128BX2 3 // Block Linear, Pitch.
#define OUTPUT_FLIP_X BIT(20)
#define OUTPUT_FLIP_Y BIT(21)
#define OUTPUT_TRANSPOSE BIT(22)
#define VIC_FC_CFG_STRUCT_SLOT_SFC_SIZE 0x10B10
#define VIC_FC_CFG_STRUCT_SLOT_LUMA_SIZE 0x10B14
#define VIC_FC_CFG_STRUCT_SLOT_CHROMA_SIZE 0x10B18
#define VIC_FC_CFG_STRUCT_SLOT_SRC_RECT_LR 0x10B1C
#define VIC_FC_CFG_STRUCT_SLOT_SRC_RECT_TB 0x10B20
#define VIC_FC_CFG_STRUCT_SLOT_DST_RECT_LR 0x10B30
#define VIC_FC_CFG_STRUCT_SLOT_DST_RECT_TB 0x10B34
#define VIC_FC_CFG_STRUCT_TGT_RECT_LR 0x10B38
#define VIC_FC_CFG_STRUCT_TGT_RECT_TB 0x10B3C
#define VIC_FC_SLOT_MAP 0x10C00
#define VIC_FC_FCE_CTRL 0x11000
#define START_TRIGGER BIT(0)
#define HALT_TRIGGER BIT(1)
#define CLEAR_ERROR BIT(8)
#define VIC_FC_FCE_UCODE_ADDR 0x11200
#define VIC_FC_FCE_UCODE_INST 0x11300
/* Surface List registers. */
#define VIC_SL_CFG_STRUCT_SLOT_INDEX 0x12100
#define VIC_SL_CFG_STRUCT_SLOT_DST_RECT_LR 0x12200
#define VIC_SL_CFG_STRUCT_SLOT_DST_RECT_TB 0x12300
#define VIC_SL_CFG_STRUCT_TGT_RECT_LR 0x12400
#define VIC_SL_CFG_STRUCT_TGT_RECT_TB 0x12500
#define VIC_SL_CFG_STRUCT_SLOT_CFG0 0x12600
/* Surface Cache registers. */
#define VIC_SC_PRAMBASE 0x14000
#define VIC_SC_PRAMSIZE 0x14100
#define VIC_SC_SFC0_BASE_LUMA(n) (0x14300 + (n) * 0x100)
/* Blending Output registers. */
#define VIC_BL_TARGET_BASADR 0x22000
#define VIC_BL_CONFIG 0x22800
#define SUBPARTITION_MODE BIT(0)
#define PROCESS_CFG_STRUCT_TRIGGER BIT(2)
#define SLOTMASK(n) ((n) << 8)
#define VIC_BL_CFG_STRUCT_CFG0 0x22C00
#define VIC_BL_CFG_STRUCT_SFC_SIZE 0x22C04
#define VIC_BL_CFG_STRUCT_LUMA_SIZE 0x22C08
#define VIC_BL_CFG_STRUCT_CHROMA_SIZE 0x22C0C
#define VIC_BL_CFG_STRUCT_TGT_RECT_LR 0x22C10
#define VIC_BL_CFG_STRUCT_TGT_RECT_TB 0x22C14
// VIC_FC_CFG_STRUCT_SLOT_CFG2 & VIC_BL_CFG_STRUCT_CFG0.
#define BLK_KIND(n) ((n) << 8)
#define BLK_KIND_PITCH 0
#define BLK_KIND_GENERIC_16BX2 1
#define BLK_HEIGHT(n) ((n) << 12)
#define BLK_HEIGHT_ONE_GOB 0
#define BLK_HEIGHT_SIXTEEN_GOBS 4
// Generic size macros.
#define SIZE_WIDTH(n) (((n) - 1) << 0)
#define SIZE_HEIGHT(n) (((n) - 1) << 16)
#define RECT_LEFT(n) ((n) << 0)
#define RECT_RIGHT(n) (((n) - 1) << 16)
#define RECT_TOP(n) ((n) << 0)
#define RECT_BOTTOM(n) (((n) - 1) << 16)
#define FORMAT_PROGRESSIVE 0
#define SOFT_CLAMP_MIN 0
#define SOFT_CLAMP_MAX 0x3FFu
#define ALPHA_1_0 0x3FFu
typedef struct _OutputConfig {
u64 AlphaFillMode:3;
u64 AlphaFillSlot:3;
u64 BackgroundAlpha:10;
u64 BackgroundR:10;
u64 BackgroundG:10;
u64 BackgroundB:10;
u64 RegammaMode:2;
u64 OutputFlipX:1;
u64 OutputFlipY:1;
u64 OutputTranspose:1;
u64 rsvd1:1;
u64 rsvd2:12;
u64 TargetRectLeft:14;
u64 rsvd3:2;
u64 TargetRectRight:14;
u64 rsvd4:2;
u64 TargetRectTop:14;
u64 rsvd5:2;
u64 TargetRectBottom:14;
u64 rsvd6:2;
} OutputConfig;
typedef struct _OutputSurfaceConfig {
u64 OutPixelFormat:7;
u64 OutChromaLocHoriz:2;
u64 OutChromaLocVert:2;
u64 OutBlkKind:4;
u64 OutBlkHeight:4;
u64 rsvd0:3;
u64 rsvd1:10;
u64 OutSurfaceWidth:14;
u64 OutSurfaceHeight:14;
u64 rsvd2:4;
u64 OutLumaWidth:14;
u64 OutLumaHeight:14;
u64 rsvd3:4;
u64 OutChromaWidth:14;
u64 OutChromaHeight:14;
u64 rsvd4:4;
} OutputSurfaceConfig;
typedef struct _SlotConfig {
u64 SlotEnable:1;
u64 DeNoise:1;
u64 AdvancedDenoise:1;
u64 CadenceDetect:1;
u64 MotionMap:1;
u64 MMapCombine:1;
u64 IsEven:1;
u64 ChromaEven:1;
u64 CurrentFieldEnable:1;
u64 PrevFieldEnable:1;
u64 NextFieldEnable:1;
u64 NextNrFieldEnable:1;
u64 CurMotionFieldEnable:1;
u64 PrevMotionFieldEnable:1;
u64 PpMotionFieldEnable:1;
u64 CombMotionFieldEnable:1;
u64 FrameFormat:4;
u64 FilterLengthY:2;
u64 FilterLengthX:2;
u64 Panoramic:12;
u64 rsvd1:22;
u64 DetailFltClamp:6;
u64 FilterNoise:10;
u64 FilterDetail:10;
u64 ChromaNoise:10;
u64 ChromaDetail:10;
u64 DeinterlaceMode:4;
u64 MotionAccumWeight:3;
u64 NoiseIir:11;
u64 LightLevel:4;
u64 rsvd4:2;
u64 SoftClampLow:10;
u64 SoftClampHigh:10;
u64 rsvd5:3;
u64 rsvd6:9;
u64 PlanarAlpha:10;
u64 ConstantAlpha:1;
u64 StereoInterleave:3;
u64 ClipEnabled:1;
u64 ClearRectMask:8;
u64 DegammaMode:2;
u64 rsvd7:1;
u64 DecompressEnable:1;
u64 rsvd9:5;
u64 DecompressCtbCount:8;
u64 DecompressZbcColor:32;
u64 rsvd12:24;
u64 SourceRectLeft:30;
u64 rsvd14:2;
u64 SourceRectRight:30;
u64 rsvd15:2;
u64 SourceRectTop:30;
u64 rsvd16:2;
u64 SourceRectBottom:30;
u64 rsvd17:2;
u64 DestRectLeft:14;
u64 rsvd18:2;
u64 DestRectRight:14;
u64 rsvd19:2;
u64 DestRectTop:14;
u64 rsvd20:2;
u64 DestRectBottom:14;
u64 rsvd21:2;
u64 rsvd22:32;
u64 rsvd23:32;
} SlotConfig;
typedef struct _SlotSurfaceConfig {
u64 SlotPixelFormat:7;
u64 SlotChromaLocHoriz:2;
u64 SlotChromaLocVert:2;
u64 SlotBlkKind:4;
u64 SlotBlkHeight:4;
u64 SlotCacheWidth:3;
u64 rsvd0:10;
u64 SlotSurfaceWidth:14;
u64 SlotSurfaceHeight:14;
u64 rsvd1:4;
u64 SlotLumaWidth:14;
u64 SlotLumaHeight:14;
u64 rsvd2:4;
u64 SlotChromaWidth:14;
u64 SlotChromaHeight:14;
u64 rsvd3:4;
} SlotSurfaceConfig;
typedef struct _SlotStruct {
SlotConfig slot_cfg;
SlotSurfaceConfig slot_sfc_cfg;
// No need to configure. Reset to zeros.
u8 lumaKeyStruct[0x10];
u8 colorMatrixStruct[0x20];
u8 gamutMatrixStruct[0x20];
u8 blendingSlotStruct[0x10];
} SlotStruct;
typedef struct _vic_config_t {
// No need to configure. Reset to zeros.
u8 pipeConfig[0x10];
OutputConfig out_cfg;
OutputSurfaceConfig out_sfc_cfg;
// No need to configure. Reset to zeros.
u8 out_color_matrix[0x20];
u8 clear_rect[0x10 * 4];
SlotStruct slots[8];
} vic_config_t;
// VIC Fetch Control Engine microcode. Dumped from L4T r33.
u8 vic_fce_ucode[] = {
0x66, 0x00, 0x00, 0x00, 0x60, 0x07, 0x00, 0x00, 0x42, 0x40, 0x10, 0x00, 0x4E, 0x01, 0x40, 0x00,
0x6A, 0x07, 0x00, 0x00, 0x6E, 0x23, 0x04, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x4E, 0x01, 0x04, 0x00,
0x6A, 0x0B, 0x00, 0x00, 0x6E, 0x1F, 0x04, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x4E, 0x01, 0x10, 0x00,
0x6A, 0x0F, 0x00, 0x00, 0x6E, 0x1F, 0x04, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x48, 0x80, 0x02, 0x00,
0x0E, 0x11, 0x00, 0x00, 0x6A, 0x14, 0x00, 0x00, 0x6E, 0x08, 0x06, 0x00, 0x6C, 0x00, 0x00, 0x00,
0x4E, 0x01, 0x08, 0x00, 0x6A, 0x18, 0x00, 0x00, 0x6E, 0x26, 0x04, 0x00, 0x6C, 0x00, 0x00, 0x00,
0x4E, 0x01, 0x20, 0x00, 0x6A, 0x1C, 0x00, 0x00, 0x6E, 0x26, 0x04, 0x00, 0x6C, 0x00, 0x00, 0x00,
0x4E, 0x01, 0x02, 0x00, 0x6A, 0x20, 0x00, 0x00, 0x6E, 0x24, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00,
0x56, 0x00, 0x10, 0x00, 0x56, 0x40, 0x10, 0x00, 0x22, 0x41, 0x01, 0x00, 0x6C, 0x00, 0x00, 0x00,
0x62, 0x80, 0x01, 0x00, 0x60, 0x47, 0x00, 0x00, 0x60, 0x87, 0x00, 0x00, 0x01, 0x4A, 0x00, 0x00,
0x55, 0xC0, 0x20, 0x00, 0x00, 0x59, 0x00, 0x00, 0x60, 0x87, 0x00, 0x00, 0x60, 0xC7, 0x00, 0x00,
0x01, 0x93, 0x00, 0x00, 0x40, 0x82, 0x02, 0x00, 0x4E, 0x02, 0x00, 0x00, 0x6B, 0x34, 0x00, 0x00,
0x43, 0xC1, 0x10, 0x00, 0x42, 0x02, 0x03, 0x00, 0x00, 0x23, 0x01, 0x00, 0x24, 0xD4, 0x00, 0x00,
0x56, 0x40, 0x3D, 0x00, 0x04, 0xEB, 0x00, 0x00, 0x60, 0x07, 0x01, 0x00, 0x60, 0x47, 0x00, 0x00,
0x6A, 0x3E, 0x00, 0x00, 0x55, 0xC0, 0x30, 0x00, 0x48, 0x00, 0x01, 0x00, 0x48, 0x40, 0x01, 0x00,
0x48, 0x80, 0x01, 0x00, 0x6B, 0x28, 0x02, 0x00, 0x56, 0x40, 0x09, 0x00, 0x04, 0x4D, 0x01, 0x00,
0x06, 0x4D, 0x00, 0x00, 0x42, 0xC0, 0x03, 0x00, 0x56, 0x80, 0x09, 0x00, 0x04, 0xFE, 0x01, 0x00,
0x00, 0xF9, 0x01, 0x00, 0x4E, 0x02, 0x00, 0x00, 0x6B, 0x32, 0x02, 0x00, 0x55, 0x40, 0x2F, 0x00,
0x56, 0x80, 0x0D, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x6A, 0x0D, 0x02, 0x00, 0x55, 0x40, 0x31, 0x00,
0x56, 0x80, 0x0B, 0x00, 0x0C, 0x2B, 0x00, 0x00, 0x6A, 0x13, 0x02, 0x00, 0x43, 0x45, 0x03, 0x00,
0x42, 0x86, 0x03, 0x00, 0x4D, 0x06, 0x02, 0x00, 0x6A, 0x0D, 0x02, 0x00, 0x42, 0x86, 0x03, 0x00,
0x22, 0x7E, 0x01, 0x00, 0x4E, 0x04, 0x00, 0x00, 0x6B, 0x32, 0x02, 0x00, 0x55, 0x40, 0x17, 0x00,
0x0D, 0x2C, 0x00, 0x00, 0x56, 0xC0, 0x09, 0x00, 0x6A, 0x1E, 0x02, 0x00, 0x48, 0xC0, 0x01, 0x00,
0x43, 0x04, 0x03, 0x00, 0x6C, 0x20, 0x02, 0x00, 0x55, 0x40, 0x19, 0x00, 0x01, 0x2C, 0x01, 0x00,
0x65, 0x23, 0x01, 0x00, 0x42, 0x42, 0x03, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x24, 0x14, 0x01, 0x00,
0x00, 0x2C, 0x01, 0x00, 0x24, 0x14, 0x01, 0x00, 0x00, 0x3C, 0x01, 0x00, 0x42, 0x04, 0x09, 0x00,
0x42, 0xC3, 0x02, 0x00, 0x65, 0x54, 0x01, 0x00, 0x65, 0x55, 0x01, 0x00, 0x42, 0x45, 0x0D, 0x00,
0x62, 0x03, 0x00, 0x00, 0x62, 0x44, 0x00, 0x00, 0x62, 0x85, 0x00, 0x00, 0x62, 0xC2, 0x00, 0x00,
0x22, 0x48, 0x1F, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x48, 0x00, 0x01, 0x00, 0x6C, 0x28, 0x02, 0x00,
0x62, 0x80, 0x01, 0x00, 0x60, 0x07, 0x00, 0x00, 0x60, 0x47, 0x00, 0x00, 0x60, 0x87, 0x00, 0x00,
0x01, 0x01, 0x00, 0x00, 0x43, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x01, 0xCA, 0x01, 0x00,
0x60, 0x03, 0x01, 0x00, 0x01, 0xA0, 0x01, 0x00, 0x60, 0x40, 0x00, 0x00, 0x65, 0x01, 0x00, 0x00,
0x55, 0xC0, 0x2E, 0x00, 0x01, 0x18, 0x00, 0x00, 0x43, 0x00, 0x04, 0x00, 0x43, 0x41, 0x06, 0x00,
0x6F, 0x00, 0x00, 0x00, 0x61, 0xC1, 0x00, 0x00, 0x61, 0x42, 0x01, 0x00, 0x65, 0xB5, 0x00, 0x00,
0x65, 0x73, 0x01, 0x00, 0x65, 0x35, 0x01, 0x00, 0x65, 0x34, 0x01, 0x00, 0x42, 0x04, 0x0D, 0x00,
0x01, 0x14, 0x01, 0x00, 0x42, 0x04, 0x03, 0x00, 0x00, 0x20, 0x00, 0x00, 0x43, 0x03, 0x05, 0x00,
0x43, 0x85, 0x02, 0x00, 0x00, 0xAA, 0x00, 0x00, 0x48, 0x46, 0x01, 0x00, 0x65, 0xEB, 0x00, 0x00,
0x00, 0x9A, 0x00, 0x00, 0x65, 0xB2, 0x01, 0x00, 0x00, 0xA6, 0x01, 0x00, 0x42, 0x86, 0x0D, 0x00,
0x61, 0x42, 0x01, 0x00, 0x01, 0xAE, 0x01, 0x00, 0x00, 0x71, 0x00, 0x00, 0x42, 0x82, 0x08, 0x00,
0x42, 0xC3, 0x08, 0x00, 0x48, 0x40, 0x01, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x6E, 0x34, 0x02, 0x00,
0x65, 0x79, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x6C, 0x36, 0x04, 0x00, 0x6E, 0x34, 0x02, 0x00,
0x48, 0x7F, 0x01, 0x00, 0x6C, 0x0A, 0x06, 0x00, 0x6E, 0x34, 0x02, 0x00, 0x6E, 0x05, 0x04, 0x00,
0x65, 0x79, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x41, 0x87, 0x03, 0x00, 0x65, 0xBA, 0x00, 0x00,
0x65, 0xB2, 0x00, 0x00, 0x42, 0x82, 0x02, 0x00, 0x00, 0x51, 0x00, 0x00, 0x61, 0xC1, 0x00, 0x00,
0x65, 0xFB, 0x00, 0x00, 0x65, 0xF3, 0x00, 0x00, 0x41, 0x87, 0x05, 0x00, 0x65, 0xF3, 0x00, 0x00,
0x42, 0xC3, 0x08, 0x00, 0x00, 0x59, 0x00, 0x00, 0x60, 0xC7, 0x00, 0x00, 0x60, 0xC7, 0x00, 0x00,
0x56, 0xC0, 0x21, 0x00, 0x04, 0xDF, 0x01, 0x00, 0x43, 0xC7, 0x15, 0x00, 0x00, 0x38, 0x00, 0x00,
0x00, 0x79, 0x00, 0x00, 0x42, 0xC3, 0x20, 0x00, 0x43, 0xC3, 0x04, 0x00, 0x42, 0x00, 0x30, 0x00,
0x42, 0x41, 0x30, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x60, 0xC7, 0x01, 0x00,
0x22, 0x78, 0x01, 0x00, 0x22, 0x79, 0x03, 0x00, 0x22, 0x7F, 0x1F, 0x00, 0x6F, 0x00, 0x00, 0x00,
0x6E, 0x34, 0x02, 0x00, 0x6E, 0x05, 0x04, 0x00, 0x4B, 0x41, 0x00, 0x00, 0x60, 0xC7, 0x01, 0x00,
0x60, 0x87, 0x01, 0x00, 0x43, 0x86, 0x15, 0x00, 0x00, 0x30, 0x00, 0x00, 0x65, 0x39, 0x01, 0x00,
0x42, 0x04, 0x05, 0x00, 0x4E, 0x05, 0x7E, 0x00, 0x6A, 0x1B, 0x06, 0x00, 0x55, 0xC0, 0x3D, 0x00,
0x0A, 0x3C, 0x01, 0x00, 0x60, 0xC7, 0x01, 0x00, 0x22, 0x78, 0x01, 0x00, 0x22, 0x79, 0x03, 0x00,
0x22, 0x7C, 0x09, 0x00, 0x22, 0x7F, 0x1F, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x65, 0x7A, 0x01, 0x00,
0x42, 0x45, 0x05, 0x00, 0x65, 0xBB, 0x01, 0x00, 0x42, 0x86, 0x05, 0x00, 0x55, 0xC0, 0x3D, 0x00,
0x0A, 0x7D, 0x01, 0x00, 0x0A, 0xBE, 0x01, 0x00, 0x07, 0xC7, 0x01, 0x00, 0x0B, 0x7D, 0x01, 0x00,
0x0B, 0xBE, 0x01, 0x00, 0x55, 0xC0, 0x3D, 0x00, 0x0A, 0x3C, 0x01, 0x00, 0x60, 0xC7, 0x01, 0x00,
0x22, 0x78, 0x01, 0x00, 0x22, 0x79, 0x03, 0x00, 0x22, 0x7A, 0x05, 0x00, 0x22, 0x7B, 0x07, 0x00,
0x22, 0x7C, 0x09, 0x00, 0x22, 0x7D, 0x0B, 0x00, 0x22, 0x7E, 0x0D, 0x00, 0x22, 0x7F, 0x1F, 0x00,
0x6F, 0x00, 0x00, 0x00
};
vic_config_t __attribute__((aligned (0x100))) vic_cfg = {0};
u32 _vic_read_priv(u32 addr)
{
u32 addr_lsb = addr & 0xFF;
// Set address LSB.
if (addr_lsb)
VIC(PVIC_FALCON_ADDR) = addr_lsb >> 2;
// Set address.
u32 val = VIC(PVIC_FALCON_PA_OFFSET + (addr >> 6));
// Unset address LSB.
if (addr_lsb)
VIC(PVIC_FALCON_ADDR) = 0;
return val;
}
static void _vic_write_priv(u32 addr, u32 data)
{
u32 addr_lsb = addr & 0xFF;
// Set address LSB.
if (addr_lsb)
VIC(PVIC_FALCON_ADDR) = addr_lsb >> 2;
// Set address.
VIC(PVIC_FALCON_PA_OFFSET + (addr >> 6)) = data;
// Unset address LSB.
if (addr_lsb)
VIC(PVIC_FALCON_ADDR) = 0;
}
static int _vic_wait_idle()
{
u32 timeout_count = 15000; // 150ms.
while (VIC(PVIC_FALCON_IDLESTATE))
{
usleep(10);
timeout_count--;
if (!timeout_count)
return -1;
};
return 0;
}
void vic_set_surface(vic_surface_t *sfc)
{
u32 flip_x = 0;
u32 flip_y = 0;
u32 swap_xy = 0;
u32 const_alpha = 0;
u32 width = sfc->width;
u32 height = sfc->height;
u32 pix_fmt = sfc->pix_fmt;
u32 src_buf = sfc->src_buf;
u32 dst_buf = sfc->dst_buf;
// Get format alpha type.
switch (sfc->pix_fmt)
{
case VIC_PIX_FORMAT_X8B8G8R8:
case VIC_PIX_FORMAT_X8R8G8B8:
case VIC_PIX_FORMAT_B8G8R8X8:
case VIC_PIX_FORMAT_R8G8B8X8:
const_alpha = 1;
break;
case VIC_PIX_FORMAT_A8B8G8R8:
case VIC_PIX_FORMAT_A8R8G8B8:
case VIC_PIX_FORMAT_B8G8R8A8:
case VIC_PIX_FORMAT_R8G8B8A8:
default:
break;
}
// Get rotation parameters.
switch (sfc->rotation)
{
case VIC_ROTATION_90:
swap_xy = 1;
break;
case VIC_ROTATION_180:
flip_x = 1;
flip_y = 1;
break;
case VIC_ROTATION_270:
flip_x = 1;
swap_xy = 1;
break;
case VIC_ROTATION_0:
default:
break;
}
// Set output surface format.
vic_cfg.out_sfc_cfg.OutPixelFormat = pix_fmt;
vic_cfg.out_sfc_cfg.OutBlkKind = BLK_KIND_PITCH;
vic_cfg.out_sfc_cfg.OutBlkHeight = 0;
// Set output rotation/flip.
vic_cfg.out_cfg.OutputFlipX = flip_x;
vic_cfg.out_cfg.OutputFlipY = flip_y;
vic_cfg.out_cfg.OutputTranspose = swap_xy;
// Set output surface resolution.
vic_cfg.out_sfc_cfg.OutSurfaceWidth = width - 1;
vic_cfg.out_sfc_cfg.OutSurfaceHeight = height - 1;
vic_cfg.out_sfc_cfg.OutLumaWidth = width - 1;
vic_cfg.out_sfc_cfg.OutLumaHeight = height - 1;
// Set output destination rectangle. Anything outside will not be touched at output buffer.
vic_cfg.out_cfg.TargetRectLeft = 0;
vic_cfg.out_cfg.TargetRectRight = width - 1;
vic_cfg.out_cfg.TargetRectTop = 0;
vic_cfg.out_cfg.TargetRectBottom = height - 1;
// Initialize slot parameters.
vic_cfg.slots[0].slot_cfg.SlotEnable = 1;
vic_cfg.slots[0].slot_cfg.SoftClampLow = SOFT_CLAMP_MIN;
vic_cfg.slots[0].slot_cfg.SoftClampHigh = SOFT_CLAMP_MAX;
vic_cfg.slots[0].slot_cfg.PlanarAlpha = ALPHA_1_0;
vic_cfg.slots[0].slot_cfg.ConstantAlpha = const_alpha;
vic_cfg.slots[0].slot_cfg.FrameFormat = FORMAT_PROGRESSIVE;
// Set input source rectangle.
vic_cfg.slots[0].slot_cfg.SourceRectLeft = 0;
vic_cfg.slots[0].slot_cfg.SourceRectRight = (width - 1) << 16;
vic_cfg.slots[0].slot_cfg.SourceRectTop = 0;
vic_cfg.slots[0].slot_cfg.SourceRectBottom = (height - 1) << 16;
// Set input destination rectangle.
vic_cfg.slots[0].slot_cfg.DestRectLeft = 0;
vic_cfg.slots[0].slot_cfg.DestRectRight = (width - 1);
vic_cfg.slots[0].slot_cfg.DestRectTop = 0;
vic_cfg.slots[0].slot_cfg.DestRectBottom = (height - 1);
// Set input surface format.
vic_cfg.slots[0].slot_sfc_cfg.SlotPixelFormat = pix_fmt;
vic_cfg.slots[0].slot_sfc_cfg.SlotBlkKind = BLK_KIND_PITCH;
vic_cfg.slots[0].slot_sfc_cfg.SlotBlkHeight = 0;
vic_cfg.slots[0].slot_sfc_cfg.SlotCacheWidth = CACHE_WIDTH_64BX4;
// Set input surface resolution.
vic_cfg.slots[0].slot_sfc_cfg.SlotSurfaceWidth = width - 1;
vic_cfg.slots[0].slot_sfc_cfg.SlotSurfaceHeight = height - 1;
vic_cfg.slots[0].slot_sfc_cfg.SlotLumaWidth = width - 1;
vic_cfg.slots[0].slot_sfc_cfg.SlotLumaHeight = height - 1;
// Flush data.
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLEAN_WAY, false);
// Set parameters base and size. Causes a parse by surface cache.
_vic_write_priv(VIC_SC_PRAMBASE, (u32)&vic_cfg >> 8);
_vic_write_priv(VIC_SC_PRAMSIZE, sizeof(vic_config_t) >> 6);
// Wait for surface cache to get ready.
_vic_wait_idle();
// Set slot mapping.
_vic_write_priv(VIC_FC_SLOT_MAP, 0xFFFFFFF0);
// Set input surface buffer.
_vic_write_priv(VIC_SC_SFC0_BASE_LUMA(0), src_buf >> 8);
// Set output surface buffer.
_vic_write_priv(VIC_BL_TARGET_BASADR, dst_buf >> 8);
// Set blending config and push changes to surface cache.
_vic_write_priv(VIC_BL_CONFIG, SLOTMASK(0x1F) | PROCESS_CFG_STRUCT_TRIGGER | SUBPARTITION_MODE);
// Wait for surface cache to get ready.
_vic_wait_idle();
}
int vic_compose()
{
// Wait for surface cache to get ready. Otherwise VIC will hang.
int res = _vic_wait_idle();
// Start composition of a single frame.
_vic_write_priv(VIC_FC_COMPOSE, COMPOSE_START);
return res;
}
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++)
{
_vic_write_priv(VIC_FC_FCE_UCODE_ADDR, (i * sizeof(u32)));
_vic_write_priv(VIC_FC_FCE_UCODE_INST, *(u32 *)&vic_fce_ucode[i * sizeof(u32)]);
}
// Start Fetch Control Engine.
_vic_write_priv(VIC_FC_FCE_CTRL, START_TRIGGER);
return _vic_wait_idle();
}
void vic_end()
{
clock_disable_vic();
}

63
bdk/display/vic.h Normal file
View File

@@ -0,0 +1,63 @@
/*
* VIC driver for Tegra X1
*
* Copyright (c) 2018-2019 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _VIC_H_
#define _VIC_H_
#include <utils/types.h>
#define VIC_THI_SLCG_OVERRIDE_LOW_A 0x8C
typedef enum _vic_rotation_t
{
VIC_ROTATION_0 = 0,
VIC_ROTATION_90 = 1,
VIC_ROTATION_180 = 2,
VIC_ROTATION_270 = 3,
} vic_rotation_t;
typedef enum _vic_pix_format_t
{
VIC_PIX_FORMAT_A8B8G8R8 = 31, // 32-bit ABGR.
VIC_PIX_FORMAT_A8R8G8B8 = 32, // 32-bit ARGB.
VIC_PIX_FORMAT_B8G8R8A8 = 33, // 32-bit BGRA.
VIC_PIX_FORMAT_R8G8B8A8 = 34, // 32-bit RGBA.
VIC_PIX_FORMAT_X8B8G8R8 = 35, // 32-bit XBGR.
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
{
u32 src_buf;
u32 dst_buf;
u32 width;
u32 height;
u32 pix_fmt;
u32 rotation;
} vic_surface_t;
void vic_set_surface(vic_surface_t *sfc);
int vic_compose();
int vic_init();
void vic_end();
#endif

View File

@@ -97,6 +97,10 @@ _irq_setup:
MSR CPSR, #(MODE_IRQ | IRQ | FIQ) /* IRQ mode, IRQ/FIQ disabled */ MSR CPSR, #(MODE_IRQ | IRQ | FIQ) /* IRQ mode, IRQ/FIQ disabled */
LDR SP, =0x40040000 LDR SP, =0x40040000
/* Setup FIQ stack pointer */
MSR CPSR, #(MODE_FIQ | IRQ | FIQ) /* FIQ mode, IRQ/FIQ disabled */
LDR SP, =0x40040000
/* Setup SYS stack pointer */ /* Setup SYS stack pointer */
MSR CPSR, #(MODE_SYS | IRQ | FIQ) /* SYSTEM mode, IRQ/FIQ disabled */ MSR CPSR, #(MODE_SYS | IRQ | FIQ) /* SYSTEM mode, IRQ/FIQ disabled */
LDR SP, =0x4003FF00 /* Will be changed later to DRAM */ LDR SP, =0x4003FF00 /* Will be changed later to DRAM */
@@ -111,7 +115,9 @@ _irq_setup:
B ipl_main B ipl_main
B . B .
_reset: .globl excp_reset
.type excp_reset, %function
excp_reset:
LDR R0, =EXCP_EN_ADDR LDR R0, =EXCP_EN_ADDR
LDR R1, =0x30505645 /* EVP0 */ LDR R1, =0x30505645 /* EVP0 */
STR R1, [R0] /* EVP0 in EXCP_EN_ADDR */ STR R1, [R0] /* EVP0 in EXCP_EN_ADDR */
@@ -129,25 +135,25 @@ _reset_handler:
LDR R0, =EXCP_TYPE_ADDR LDR R0, =EXCP_TYPE_ADDR
LDR R1, =0x545352 /* RST */ LDR R1, =0x545352 /* RST */
STR R1, [R0] /* RST in EXCP_TYPE_ADDR */ STR R1, [R0] /* RST in EXCP_TYPE_ADDR */
B _reset B excp_reset
_undefined_handler: _undefined_handler:
LDR R0, =EXCP_TYPE_ADDR LDR R0, =EXCP_TYPE_ADDR
LDR R1, =0x464455 /* UDF */ LDR R1, =0x464455 /* UDF */
STR R1, [R0] /* UDF in EXCP_TYPE_ADDR */ STR R1, [R0] /* UDF in EXCP_TYPE_ADDR */
B _reset B excp_reset
_prefetch_abort_handler: _prefetch_abort_handler:
LDR R0, =EXCP_TYPE_ADDR LDR R0, =EXCP_TYPE_ADDR
LDR R1, =0x54424150 /* PABT */ LDR R1, =0x54424150 /* PABT */
STR R1, [R0] /* PABT in EXCP_TYPE_ADDR */ STR R1, [R0] /* PABT in EXCP_TYPE_ADDR */
B _reset B excp_reset
_data_abort_handler: _data_abort_handler:
LDR R0, =EXCP_TYPE_ADDR LDR R0, =EXCP_TYPE_ADDR
LDR R1, =0x54424144 /* DABT */ LDR R1, =0x54424144 /* DABT */
STR R1, [R0] /* DABT in EXCP_TYPE_ADDR */ STR R1, [R0] /* DABT in EXCP_TYPE_ADDR */
B _reset B excp_reset
.globl irq_enable_cpu_irq_exceptions .globl irq_enable_cpu_irq_exceptions
.type irq_enable_cpu_irq_exceptions, %function .type irq_enable_cpu_irq_exceptions, %function

View File

@@ -17,8 +17,12 @@
#ifndef _FATFS_CFG_H_ #ifndef _FATFS_CFG_H_
#define _FATFS_CFG_H_ #define _FATFS_CFG_H_
// define FFCFG_INC in a project to use a specific FatFS configuration.
// Example: FFCFG_INC := '"../$(PROJECT_DIR)/libs/fatfs/ffconf.h"'
#ifdef FFCFG_INC #ifdef FFCFG_INC
#include FFCFG_INC #include FFCFG_INC
#else
#include "fatfs_conf.h"
#endif #endif
#endif #endif

305
bdk/fatfs_conf.h Normal file
View File

@@ -0,0 +1,305 @@
/*---------------------------------------------------------------------------/
/ FatFs Functional Configurations
/---------------------------------------------------------------------------*/
#define FFCONF_DEF 86604 /* Revision ID */
/*---------------------------------------------------------------------------/
/ Function Configurations
/---------------------------------------------------------------------------*/
#define FF_FS_READONLY 0
/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
/ Read-only configuration removes writing API functions, f_write(), f_sync(),
/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
/ and optional writing functions as well. */
#define FF_FS_MINIMIZE 0
/* This option defines minimization level to remove some basic API functions.
/
/ 0: Basic functions are fully enabled.
/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename()
/ are removed.
/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
/ 3: f_lseek() function is removed in addition to 2. */
#define FF_USE_STRFUNC 2
/* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf().
/
/ 0: Disable string functions.
/ 1: Enable without LF-CRLF conversion.
/ 2: Enable with LF-CRLF conversion. */
#define FF_USE_FIND 1
/* This option switches filtered directory read functions, f_findfirst() and
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
#define FF_USE_MKFS 0
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
#if FF_USE_MKFS
#define FF_MKFS_LABEL "SWITCH SD "
#endif
/* This sets FAT/FAT32 label. Exactly 11 characters, all caps. */
#define FF_USE_FASTSEEK 0
/* This option switches fast seek function. (0:Disable or 1:Enable) */
#define FF_FASTFS 0
#if FF_FASTFS
#undef FF_USE_FASTSEEK
#define FF_USE_FASTSEEK 1
#endif
/* This option switches fast access to chained clusters. (0:Disable or 1:Enable) */
#define FF_SIMPLE_GPT 1
/* This option switches support for the first GPT partition. (0:Disable or 1:Enable) */
#define FF_USE_EXPAND 0
/* This option switches f_expand function. (0:Disable or 1:Enable) */
#define FF_USE_CHMOD 1
/* This option switches attribute manipulation functions, f_chmod() and f_utime().
/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */
#define FF_USE_LABEL 0
/* This option switches volume label functions, f_getlabel() and f_setlabel().
/ (0:Disable or 1:Enable) */
#define FF_USE_FORWARD 0
/* This option switches f_forward() function. (0:Disable or 1:Enable) */
/*---------------------------------------------------------------------------/
/ Locale and Namespace Configurations
/---------------------------------------------------------------------------*/
#define FF_CODE_PAGE 850
/* This option specifies the OEM code page to be used on the target system.
/ Incorrect code page setting can cause a file open failure.
/
/ 437 - U.S.
/ 720 - Arabic
/ 737 - Greek
/ 771 - KBL
/ 775 - Baltic
/ 850 - Latin 1
/ 852 - Latin 2
/ 855 - Cyrillic
/ 857 - Turkish
/ 860 - Portuguese
/ 861 - Icelandic
/ 862 - Hebrew
/ 863 - Canadian French
/ 864 - Arabic
/ 865 - Nordic
/ 866 - Russian
/ 869 - Greek 2
/ 932 - Japanese (DBCS)
/ 936 - Simplified Chinese (DBCS)
/ 949 - Korean (DBCS)
/ 950 - Traditional Chinese (DBCS)
/ 0 - Include all code pages above and configured by f_setcp()
*/
#define FF_USE_LFN 3
#define FF_MAX_LFN 255
/* The FF_USE_LFN switches the support for LFN (long file name).
/
/ 0: Disable LFN. FF_MAX_LFN has no effect.
/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
/ 2: Enable LFN with dynamic working buffer on the STACK.
/ 3: Enable LFN with dynamic working buffer on the HEAP.
/
/ To enable the LFN, ffunicode.c needs to be added to the project. The LFN function
/ requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and
/ additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled.
/ The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can
/ be in range of 12 to 255. It is recommended to be set 255 to fully support LFN
/ specification.
/ When use stack for the working buffer, take care on stack overflow. When use heap
/ memory for the working buffer, memory management functions, ff_memalloc() and
/ ff_memfree() in ffsystem.c, need to be added to the project. */
#define FF_LFN_UNICODE 0
/* This option switches the character encoding on the API when LFN is enabled.
/
/ 0: ANSI/OEM in current CP (TCHAR = char)
/ 1: Unicode in UTF-16 (TCHAR = WCHAR)
/ 2: Unicode in UTF-8 (TCHAR = char)
/ 3: Unicode in UTF-32 (TCHAR = DWORD)
/
/ Also behavior of string I/O functions will be affected by this option.
/ When LFN is not enabled, this option has no effect. */
#define FF_LFN_BUF 255
#define FF_SFN_BUF 12
/* This set of options defines size of file name members in the FILINFO structure
/ which is used to read out directory items. These values should be suffcient for
/ the file names to read. The maximum possible length of the read file name depends
/ on character encoding. When LFN is not enabled, these options have no effect. */
#define FF_STRF_ENCODE 0
/* When FF_LFN_UNICODE >= 1 with LFN enabled, string I/O functions, f_gets(),
/ f_putc(), f_puts and f_printf() convert the character encoding in it.
/ This option selects assumption of character encoding ON THE FILE to be
/ read/written via those functions.
/
/ 0: ANSI/OEM in current CP
/ 1: Unicode in UTF-16LE
/ 2: Unicode in UTF-16BE
/ 3: Unicode in UTF-8
*/
#define FF_FS_RPATH 0
/* This option configures support for relative path.
/
/ 0: Disable relative path and remove related functions.
/ 1: Enable relative path. f_chdir() and f_chdrive() are available.
/ 2: f_getcwd() function is available in addition to 1.
*/
/*---------------------------------------------------------------------------/
/ Drive/Volume Configurations
/---------------------------------------------------------------------------*/
#define FF_VOLUMES 1
/* Number of volumes (logical drives) to be used. (1-10) */
#define FF_STR_VOLUME_ID 0
#define FF_VOLUME_STRS "sd"
/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive
/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
/ logical drives. Number of items must not be less than FF_VOLUMES. Valid
/ characters for the volume ID strings are A-Z, a-z and 0-9, however, they are
/ compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is
/ not defined, a user defined volume string table needs to be defined as:
/
/ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",...
/ Order is important. Any change to order, must also be reflected to diskio drive enum.
*/
#define FF_MULTI_PARTITION 0
/* This option switches support for multiple volumes on the physical drive.
/ By default (0), each logical drive number is bound to the same physical drive
/ number and only an FAT volume found on the physical drive will be mounted.
/ When this function is enabled (1), each logical drive number can be bound to
/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
/ funciton will be available. */
#define FF_MIN_SS 512
#define FF_MAX_SS 512
/* This set of options configures the range of sector size to be supported. (512,
/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and
/ harddisk. But a larger value may be required for on-board flash memory and some
/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured
/ for variable sector size mode and disk_ioctl() function needs to implement
/ GET_SECTOR_SIZE command. */
#define FF_USE_TRIM 0
/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable)
/ To enable Trim function, also CTRL_TRIM command should be implemented to the
/ disk_ioctl() function. */
#define FF_FS_NOFSINFO 1
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
/ option, and f_getfree() function at first time after volume mount will force
/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
/
/ bit0=0: Use free cluster count in the FSINFO if available.
/ bit0=1: Do not trust free cluster count in the FSINFO.
/ bit1=0: Use last allocated cluster number in the FSINFO if available.
/ bit1=1: Do not trust last allocated cluster number in the FSINFO.
*/
/*---------------------------------------------------------------------------/
/ System Configurations
/---------------------------------------------------------------------------*/
#define FF_FS_TINY 0
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
/ At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes.
/ Instead of private sector buffer eliminated from the file object, common sector
/ buffer in the filesystem object (FATFS) is used for the file data transfer. */
#define FF_FS_EXFAT 1
/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
/ To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1)
/ Note that enabling exFAT discards ANSI C (C89) compatibility. */
#define FF_FS_NORTC 1
#define FF_NORTC_MON 1
#define FF_NORTC_MDAY 1
#define FF_NORTC_YEAR 2022
/* The option FF_FS_NORTC switches timestamp function. If the system does not have
/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable
/ the timestamp function. Every object modified by FatFs will have a fixed timestamp
/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time.
/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be
/ added to the project to read current time form real-time clock. FF_NORTC_MON,
/ FF_NORTC_MDAY and FF_NORTC_YEAR have no effect.
/ These options have no effect at read-only configuration (FF_FS_READONLY = 1). */
#define FF_FS_LOCK 0
/* The option FF_FS_LOCK switches file lock function to control duplicated file open
/ and illegal operation to open objects. This option must be 0 when FF_FS_READONLY
/ is 1.
/
/ 0: Disable file lock function. To avoid volume corruption, application program
/ should avoid illegal open, remove and rename to the open objects.
/ >0: Enable file lock function. The value defines how many files/sub-directories
/ can be opened simultaneously under file lock control. Note that the file
/ lock control is independent of re-entrancy. */
/* #include <somertos.h> // O/S definitions */
#define FF_FS_REENTRANT 0
#define FF_FS_TIMEOUT 1000
#define FF_SYNC_t HANDLE
/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
/ module itself. Note that regardless of this option, file access to different
/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
/ and f_fdisk() function, are always not re-entrant. Only file/directory access
/ to the same volume is under control of this function.
/
/ 0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect.
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
/ function, must be added to the project. Samples are available in
/ option/syscall.c.
/
/ The FF_FS_TIMEOUT defines timeout period in unit of time tick.
/ The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be
/ included somewhere in the scope of ff.h. */
/*--- End of configuration options ---*/

View File

@@ -29,33 +29,34 @@
#ifndef ELF_H #ifndef ELF_H
#define ELF_H #define ELF_H
#include <stdint.h>
typedef uint8_t Elf_Byte; #include <utils/types.h>
typedef uint32_t Elf32_Addr; /* Unsigned program address */ typedef u8 Elf_Byte;
typedef uint32_t Elf32_Off; /* Unsigned file offset */
typedef int32_t Elf32_Sword; /* Signed large integer */
typedef uint32_t Elf32_Word; /* Unsigned large integer */
typedef uint16_t Elf32_Half; /* Unsigned medium integer */
typedef uint64_t Elf64_Addr; typedef u32 Elf32_Addr; /* Unsigned program address */
typedef uint64_t Elf64_Off; typedef u32 Elf32_Off; /* Unsigned file offset */
typedef int32_t Elf64_Shalf; typedef s32 Elf32_Sword; /* Signed large integer */
typedef u32 Elf32_Word; /* Unsigned large integer */
typedef u16 Elf32_Half; /* Unsigned medium integer */
typedef u64 Elf64_Addr;
typedef u64 Elf64_Off;
typedef s32 Elf64_Shalf;
#ifdef __alpha__ #ifdef __alpha__
typedef int64_t Elf64_Sword; typedef s64 Elf64_Sword;
typedef uint64_t Elf64_Word; typedef u64 Elf64_Word;
#else #else
typedef int32_t Elf64_Sword; typedef s32 Elf64_Sword;
typedef uint32_t Elf64_Word; typedef u32 Elf64_Word;
#endif #endif
typedef int64_t Elf64_Sxword; typedef s64 Elf64_Sxword;
typedef uint64_t Elf64_Xword; typedef u64 Elf64_Xword;
typedef uint32_t Elf64_Half; typedef u32 Elf64_Half;
typedef uint16_t Elf64_Quarter; typedef u16 Elf64_Quarter;
/* /*
* e_ident[] identification indexes * e_ident[] identification indexes
@@ -376,7 +377,7 @@ typedef struct
#define ELF64_R_SYM(info) ((info) >> 32) #define ELF64_R_SYM(info) ((info) >> 32)
#define ELF64_R_TYPE(info) ((info)&0xFFFFFFFF) #define ELF64_R_TYPE(info) ((info)&0xFFFFFFFF)
#define ELF64_R_INFO(s, t) (((s) << 32) + (__uint32_t)(t)) #define ELF64_R_INFO(s, t) (((s) << 32) + (u32)(t))
#if defined(__mips64__) && defined(__MIPSEL__) #if defined(__mips64__) && defined(__MIPSEL__)
/* /*
@@ -389,7 +390,7 @@ typedef struct
#undef ELF64_R_INFO #undef ELF64_R_INFO
#define ELF64_R_TYPE(info) (swap32((info) >> 32)) #define ELF64_R_TYPE(info) (swap32((info) >> 32))
#define ELF64_R_SYM(info) ((info)&0xFFFFFFFF) #define ELF64_R_SYM(info) ((info)&0xFFFFFFFF)
#define ELF64_R_INFO(s, t) (((__uint64_t)swap32(t) << 32) + (__uint32_t)(s)) #define ELF64_R_INFO(s, t) (((u64)swap32(t) << 32) + (u32)(s))
#endif /* __mips64__ && __MIPSEL__ */ #endif /* __mips64__ && __MIPSEL__ */
/* Program Header */ /* Program Header */
@@ -444,7 +445,7 @@ typedef struct
/* Dynamic structure */ /* Dynamic structure */
typedef struct typedef struct
{ {
Elf32_Sword d_tag; /* controls meaning of d_val */ Elf32_Word d_tag; /* controls meaning of d_val */
union { union {
Elf32_Word d_val; /* Multiple meanings - see d_tag */ Elf32_Word d_val; /* Multiple meanings - see d_tag */
Elf32_Addr d_ptr; /* program virtual address */ Elf32_Addr d_ptr; /* program virtual address */

View File

@@ -25,7 +25,7 @@ el_status el_pread(el_ctx *ctx, void *def, size_t nb, size_t offset)
} }
#define EL_PHOFF(ctx, num) (((ctx)->ehdr.e_phoff + (num) *(ctx)->ehdr.e_phentsize)) #define EL_PHOFF(ctx, num) (((ctx)->ehdr.e_phoff + (num) *(ctx)->ehdr.e_phentsize))
el_status el_findphdr(el_ctx *ctx, Elf_Phdr *phdr, uint32_t type, unsigned *i) el_status el_findphdr(el_ctx *ctx, Elf_Phdr *phdr, u32 type, unsigned *i)
{ {
el_status rv = EL_OK; el_status rv = EL_OK;
for (; *i < ctx->ehdr.e_phnum; (*i)++) for (; *i < ctx->ehdr.e_phnum; (*i)++)
@@ -44,7 +44,7 @@ el_status el_findphdr(el_ctx *ctx, Elf_Phdr *phdr, uint32_t type, unsigned *i)
} }
#define EL_SHOFF(ctx, num) (((ctx)->ehdr.e_shoff + (num) *(ctx)->ehdr.e_shentsize)) #define EL_SHOFF(ctx, num) (((ctx)->ehdr.e_shoff + (num) *(ctx)->ehdr.e_shentsize))
el_status el_findshdr(el_ctx *ctx, Elf_Shdr *shdr, uint32_t type, unsigned *i) el_status el_findshdr(el_ctx *ctx, Elf_Shdr *shdr, u32 type, unsigned *i)
{ {
el_status rv = EL_OK; el_status rv = EL_OK;
@@ -213,7 +213,7 @@ el_status el_load(el_ctx *ctx, el_alloc_cb alloc)
return rv; return rv;
} }
el_status el_finddyn(el_ctx *ctx, Elf_Dyn *dyn, uint32_t tag) el_status el_finddyn(el_ctx *ctx, Elf_Dyn *dyn, u32 tag)
{ {
el_status rv = EL_OK; el_status rv = EL_OK;
size_t ndyn = ctx->dynsize / sizeof(Elf_Dyn); size_t ndyn = ctx->dynsize / sizeof(Elf_Dyn);
@@ -231,7 +231,7 @@ el_status el_finddyn(el_ctx *ctx, Elf_Dyn *dyn, uint32_t tag)
return EL_OK; return EL_OK;
} }
el_status el_findrelocs(el_ctx *ctx, el_relocinfo *ri, uint32_t type) el_status el_findrelocs(el_ctx *ctx, el_relocinfo *ri, u32 type)
{ {
el_status rv = EL_OK; el_status rv = EL_OK;

View File

@@ -22,8 +22,6 @@
#include "elfarch.h" #include "elfarch.h"
#include "elf.h" #include "elf.h"
#include <utils/types.h>
#ifdef DEBUG #ifdef DEBUG
#include <gfx_utils.h> #include <gfx_utils.h>
#define EL_DEBUG(format, ...) \ #define EL_DEBUG(format, ...) \
@@ -100,7 +98,7 @@ el_status el_load(el_ctx *ctx, el_alloc_cb alloccb);
* If the end of the phdrs table was reached, *i is set to -1 and the contents * If the end of the phdrs table was reached, *i is set to -1 and the contents
* of *phdr are undefined * of *phdr are undefined
*/ */
el_status el_findphdr(el_ctx *ctx, Elf_Phdr *phdr, uint32_t type, unsigned *i); el_status el_findphdr(el_ctx *ctx, Elf_Phdr *phdr, u32 type, unsigned *i);
/* Relocate the loaded executable */ /* Relocate the loaded executable */
el_status el_relocate(el_ctx *ctx); el_status el_relocate(el_ctx *ctx);
@@ -108,7 +106,7 @@ el_status el_relocate(el_ctx *ctx);
/* find a dynamic table entry /* find a dynamic table entry
* returns the entry on success, dyn->d_tag = DT_NULL on failure * returns the entry on success, dyn->d_tag = DT_NULL on failure
*/ */
el_status el_finddyn(el_ctx *ctx, Elf_Dyn *dyn, uint32_t type); el_status el_finddyn(el_ctx *ctx, Elf_Dyn *dyn, u32 type);
typedef struct typedef struct
{ {
@@ -122,6 +120,6 @@ typedef struct
* pass DT_REL or DT_RELA for type * pass DT_REL or DT_RELA for type
* sets ri->entrysize = 0 if not found * sets ri->entrysize = 0 if not found
*/ */
el_status el_findrelocs(el_ctx *ctx, el_relocinfo *ri, uint32_t type); el_status el_findrelocs(el_ctx *ctx, el_relocinfo *ri, u32 type);
#endif #endif

View File

@@ -23,9 +23,9 @@
el_status el_applyrela(el_ctx *ctx, Elf_RelA *rel) el_status el_applyrela(el_ctx *ctx, Elf_RelA *rel)
{ {
uintptr_t *p = (uintptr_t *)(rel->r_offset + ctx->base_load_paddr); uptr *p = (uptr *)(rel->r_offset + ctx->base_load_paddr);
uint32_t type = ELF_R_TYPE(rel->r_info); u32 type = ELF_R_TYPE(rel->r_info);
uint32_t sym = ELF_R_SYM(rel->r_info); u32 sym = ELF_R_SYM(rel->r_info);
switch (type) switch (type)
{ {
@@ -53,9 +53,9 @@ el_status el_applyrela(el_ctx *ctx, Elf_RelA *rel)
el_status el_applyrel(el_ctx *ctx, Elf_Rel *rel) el_status el_applyrel(el_ctx *ctx, Elf_Rel *rel)
{ {
uintptr_t *p = (uintptr_t *)(rel->r_offset + ctx->base_load_paddr); uptr *p = (uptr *)(rel->r_offset + ctx->base_load_paddr);
uint32_t type = ELF_R_TYPE(rel->r_info); u32 type = ELF_R_TYPE(rel->r_info);
uint32_t sym = ELF_R_SYM(rel->r_info); u32 sym = ELF_R_SYM(rel->r_info);
switch (type) switch (type)
{ {

View File

@@ -20,9 +20,9 @@
el_status el_applyrel(el_ctx *ctx, Elf_Rel *rel) el_status el_applyrel(el_ctx *ctx, Elf_Rel *rel)
{ {
uint32_t sym = ELF_R_SYM(rel->r_info); // Symbol offset u32 sym = ELF_R_SYM(rel->r_info); // Symbol offset
uint32_t type = ELF_R_TYPE(rel->r_info); // Relocation Type u32 type = ELF_R_TYPE(rel->r_info); // Relocation Type
uintptr_t *p = (uintptr_t *)(rel->r_offset + ctx->base_load_paddr); // Target Addr uptr *p = (uptr *)(rel->r_offset + ctx->base_load_paddr); // Target Addr
#if 0 // For later symbol usage #if 0 // For later symbol usage
Elf32_Sym *elfSym; Elf32_Sym *elfSym;

View File

@@ -22,7 +22,7 @@
#include <module.h> #include <module.h>
#include <mem/heap.h> #include <mem/heap.h>
#include <power/max7762x.h> #include <power/max7762x.h>
#include <storage/nx_sd.h> #include <storage/sd.h>
#include <utils/types.h> #include <utils/types.h>
#include <gfx_utils.h> #include <gfx_utils.h>
@@ -74,19 +74,16 @@ uintptr_t ianos_loader(char *path, elfType_t type, void *moduleConfig)
el_ctx ctx; el_ctx ctx;
uintptr_t epaddr = 0; uintptr_t epaddr = 0;
if (!sd_mount())
goto elfLoadFinalOut;
// Read library. // Read library.
fileBuf = sd_file_read(path, NULL); fileBuf = sd_file_read(path, NULL);
if (!fileBuf) if (!fileBuf)
goto elfLoadFinalOut; goto out;
ctx.pread = _ianos_read_cb; ctx.pread = _ianos_read_cb;
if (el_init(&ctx)) if (el_init(&ctx))
goto elfLoadFinalOut; goto out;
// Set our relocated library's buffer. // Set our relocated library's buffer.
switch (type & 0xFFFF) switch (type & 0xFFFF)
@@ -100,15 +97,15 @@ uintptr_t ianos_loader(char *path, elfType_t type, void *moduleConfig)
} }
if (!elfBuf) if (!elfBuf)
goto elfLoadFinalOut; goto out;
// Load and relocate library. // Load and relocate library.
ctx.base_load_vaddr = ctx.base_load_paddr = (uintptr_t)elfBuf; ctx.base_load_vaddr = ctx.base_load_paddr = (uintptr_t)elfBuf;
if (el_load(&ctx, _ianos_alloc_cb)) if (el_load(&ctx, _ianos_alloc_cb))
goto elfFreeOut; goto out_free;
if (el_relocate(&ctx)) if (el_relocate(&ctx))
goto elfFreeOut; goto out_free;
// Launch. // Launch.
epaddr = ctx.ehdr.e_entry + (uintptr_t)elfBuf; epaddr = ctx.ehdr.e_entry + (uintptr_t)elfBuf;
@@ -116,11 +113,11 @@ uintptr_t ianos_loader(char *path, elfType_t type, void *moduleConfig)
_ianos_call_ep(ep, moduleConfig); _ianos_call_ep(ep, moduleConfig);
elfFreeOut: out_free:
free(fileBuf); free(fileBuf);
elfBuf = NULL; elfBuf = NULL;
fileBuf = NULL; fileBuf = NULL;
elfLoadFinalOut: out:
return epaddr; return epaddr;
} }

View File

@@ -73,7 +73,7 @@ void set_als_cfg(als_ctxt_t *als_ctxt, u8 gain, u8 cycle)
else if (cycle > 255) else if (cycle > 255)
cycle = 255; cycle = 255;
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_GAIN_REG), gain); i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_GAIN_REG), gain);
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_TIMING_REG), (256 - cycle)); i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_TIMING_REG), (256 - cycle));
als_ctxt->gain = gain; als_ctxt->gain = gain;
@@ -83,25 +83,25 @@ void set_als_cfg(als_ctxt_t *als_ctxt, u8 gain, u8 cycle)
void get_als_lux(als_ctxt_t *als_ctxt) void get_als_lux(als_ctxt_t *als_ctxt)
{ {
u32 data[2]; u32 data[2];
u32 visible_light; u32 vi_light;
u32 ir_light; u32 ir_light;
u64 lux = 0; u64 lux = 0;
u32 itime_us = BH1730_ITIME_CYCLE_TO_US * als_ctxt->cycle; u32 itime_us = BH1730_ITIME_CYCLE_TO_US * als_ctxt->cycle;
// Get visible and ir light raw data. Mode is continuous so waiting for new values doesn't matter. // Get visible and ir light raw data. Mode is continuous so waiting for new values doesn't matter.
data[0] = i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA0LOW_REG)) + data[0] = i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA0LOW_REG)) +
(i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA0HIGH_REG)) << 8); (i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA0HIGH_REG)) << 8);
data[1] = i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA1LOW_REG)) + data[1] = i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA1LOW_REG)) +
(i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA1HIGH_REG)) << 8); (i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA1HIGH_REG)) << 8);
visible_light = data[0]; vi_light = data[0];
ir_light = data[1]; ir_light = data[1];
als_ctxt->over_limit = visible_light > 65534 || ir_light > 65534; als_ctxt->vi_light = vi_light;
als_ctxt->vi_light = visible_light;
als_ctxt->ir_light = ir_light; als_ctxt->ir_light = ir_light;
als_ctxt->over_limit = vi_light > 65534 || ir_light > 65534;
if (!visible_light) if (!vi_light)
{ {
als_ctxt->lux = 0; als_ctxt->lux = 0;
@@ -116,7 +116,7 @@ void get_als_lux(als_ctxt_t *als_ctxt)
// Apply optical window calibration coefficients. // Apply optical window calibration coefficients.
for (u32 i = 0; i < opt_win_cal_count; i++) for (u32 i = 0; i < opt_win_cal_count; i++)
{ {
if (1000 * ir_light / visible_light < opt_win_cal[i].rc) if (1000 * ir_light / vi_light < opt_win_cal[i].rc)
{ {
lux = ((u64)opt_win_cal[i].cv * data[0]) - (opt_win_cal[i].ci * data[1]); lux = ((u64)opt_win_cal[i].cv * data[0]) - (opt_win_cal[i].ci * data[1]);
break; break;

File diff suppressed because it is too large Load Diff

View File

@@ -83,13 +83,23 @@ typedef struct _jc_gamepad_rpt_t
bool center_stick_r; bool center_stick_r;
bool conn_l; bool conn_l;
bool conn_r; bool conn_r;
u8 batt_info_l; bool sio_mode;
u8 batt_info_r; u8 batt_info_l; // Also Sio Connected status.
u8 batt_info_r; // Also Sio IRQ.
jc_bt_conn_t bt_conn_l; jc_bt_conn_t bt_conn_l;
jc_bt_conn_t bt_conn_r; jc_bt_conn_t bt_conn_r;
} jc_gamepad_rpt_t; } jc_gamepad_rpt_t;
void jc_power_supply(u8 uart, bool enable); typedef struct _jc_calib_t
{
u16 x_max:12;
u16 y_max:12;
u16 x_center:12;
u16 y_center:12;
u16 x_min:12;
u16 y_min:12;
} __attribute__((packed)) jc_calib_t;
void jc_init_hw(); void jc_init_hw();
void jc_deinit(); void jc_deinit();
jc_gamepad_rpt_t *joycon_poll(); jc_gamepad_rpt_t *joycon_poll();

View File

@@ -2,7 +2,7 @@
* Touch driver for Nintendo Switch's STM FingerTip S (4CD60D) touch controller * Touch driver for Nintendo Switch's STM FingerTip S (4CD60D) touch controller
* *
* Copyright (c) 2018 langerhans * Copyright (c) 2018 langerhans
* Copyright (c) 2018-2020 CTCaer * Copyright (c) 2018-2023 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -24,9 +24,9 @@
#include <soc/pinmux.h> #include <soc/pinmux.h>
#include <power/max7762x.h> #include <power/max7762x.h>
#include <soc/gpio.h> #include <soc/gpio.h>
#include <soc/timer.h>
#include <soc/t210.h> #include <soc/t210.h>
#include <utils/btn.h> #include <utils/btn.h>
#include <utils/util.h>
#include "touch.h" #include "touch.h"
@@ -35,12 +35,12 @@
static touch_panel_info_t _panels[] = static touch_panel_info_t _panels[] =
{ {
{ 0, 1, 1, 1, "NISSHA NFT-K12D" }, { 0, 1, 1, 1, "NISSHA NFT-K12D" },// 0.
{ 1, 0, 1, 1, "GiS GGM6 B2X" }, { 1, 0, 1, 1, "GiS GGM6 B2X" },// 1.
{ 2, 0, 0, 0, "NISSHA NBF-K9A" }, { 2, 0, 0, 0, "NISSHA NBF-K9A" },// 3.
{ 3, 1, 0, 0, "GiS 5.5\"" }, { 3, 1, 0, 0, "GiS 5.5\"" },// 4.
{ 4, 0, 0, 1, "Samsung BH2109" }, { 4, 0, 0, 1, "Samsung BH2109" },// 5?
{ -1, 1, 0, 1, "GiS VA 6.2\"" } { -1, 1, 0, 1, "GiS VA 6.2\"" } // 2.
}; };
static int touch_command(u8 cmd, u8 *buf, u8 size) static int touch_command(u8 cmd, u8 *buf, u8 size)
@@ -87,19 +87,19 @@ static int touch_wait_event(u8 event, u8 status, u32 timeout, u8 *buf)
static void _touch_compensate_limits(touch_event *event, bool touching) static void _touch_compensate_limits(touch_event *event, bool touching)
{ {
event->x = MAX(event->x, EDGE_OFFSET); event->x = MAX(event->x, EDGE_OFFSET);
event->x = MIN(event->x, X_REAL_MAX); event->x = MIN(event->x, X_REAL_MAX);
event->x -= EDGE_OFFSET; event->x -= EDGE_OFFSET;
u32 x_adj = (1280 * 1000) / (X_REAL_MAX - EDGE_OFFSET); u32 x_adj = (1280 * 1000) / (X_REAL_MAX - EDGE_OFFSET);
event->x = ((u32)event->x * x_adj) / 1000; event->x = ((u32)event->x * x_adj) / 1000;
if (touching) if (touching)
{ {
event->y = MAX(event->y, EDGE_OFFSET); event->y = MAX(event->y, EDGE_OFFSET);
event->y = MIN(event->y, Y_REAL_MAX); event->y = MIN(event->y, Y_REAL_MAX);
event->y -= EDGE_OFFSET; event->y -= EDGE_OFFSET;
u32 y_adj = (720 * 1000) / (Y_REAL_MAX - EDGE_OFFSET); u32 y_adj = (720 * 1000) / (Y_REAL_MAX - EDGE_OFFSET);
event->y = ((u32)event->y * y_adj) / 1000; event->y = ((u32)event->y * y_adj) / 1000;
} }
} }
@@ -115,6 +115,7 @@ static void _touch_process_contact_event(touch_event *event, bool touching)
event->z = event->raw[5] | (event->raw[6] << 8); event->z = event->raw[5] | (event->raw[6] << 8);
event->z = event->z << 6; event->z = event->z << 6;
u16 tmp = 0x40; u16 tmp = 0x40;
if ((event->raw[7] & 0x3F) != 1 && (event->raw[7] & 0x3F) != 0x3F) if ((event->raw[7] & 0x3F) != 1 && (event->raw[7] & 0x3F) != 0x3F)
tmp = event->raw[7] & 0x3F; tmp = event->raw[7] & 0x3F;
@@ -245,7 +246,7 @@ int touch_get_fw_info(touch_fw_info_t *fw)
res = touch_read_reg(cmd, 3, buf, 8); res = touch_read_reg(cmd, 3, buf, 8);
if (!res) if (!res)
{ {
fw->fw_id = (buf[1] << 24) | (buf[2] << 16) | (buf[3] << 8) | buf[4]; fw->fw_id = (buf[1] << 24) | (buf[2] << 16) | (buf[3] << 8) | buf[4];
fw->ftb_ver = (buf[6] << 8) | buf[5]; fw->ftb_ver = (buf[6] << 8) | buf[5];
} }
@@ -400,30 +401,29 @@ static int touch_init()
int touch_power_on() int touch_power_on()
{ {
// Enable LDO6 for touchscreen AVDD supply.
max7762x_regulator_set_voltage(REGULATOR_LDO6, 2900000);
max7762x_regulator_enable(REGULATOR_LDO6, true);
// Configure touchscreen VDD GPIO.
PINMUX_AUX(PINMUX_AUX_DAP4_SCLK) = PINMUX_PULL_DOWN | 1;
gpio_config(GPIO_PORT_J, GPIO_PIN_7, GPIO_MODE_GPIO);
gpio_output_enable(GPIO_PORT_J, GPIO_PIN_7, GPIO_OUTPUT_ENABLE);
gpio_write(GPIO_PORT_J, GPIO_PIN_7, GPIO_HIGH);
// IRQ and more.
// PINMUX_AUX(PINMUX_AUX_TOUCH_INT) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE | PINMUX_PULL_UP | 3;
// gpio_config(GPIO_PORT_X, GPIO_PIN_1, GPIO_MODE_GPIO);
// gpio_write(GPIO_PORT_X, GPIO_PIN_1, GPIO_LOW);
// Configure Touscreen and GCAsic shared GPIO. // Configure Touscreen and GCAsic shared GPIO.
PINMUX_AUX(PINMUX_AUX_CAM_I2C_SDA) = PINMUX_LPDR | PINMUX_INPUT_ENABLE | PINMUX_TRISTATE | PINMUX_PULL_UP | 2; PINMUX_AUX(PINMUX_AUX_CAM_I2C_SDA) = PINMUX_LPDR | PINMUX_INPUT_ENABLE | PINMUX_TRISTATE | PINMUX_PULL_UP | 2;
PINMUX_AUX(PINMUX_AUX_CAM_I2C_SCL) = PINMUX_IO_HV | PINMUX_LPDR | PINMUX_TRISTATE | PINMUX_PULL_DOWN | 2; PINMUX_AUX(PINMUX_AUX_CAM_I2C_SCL) = PINMUX_IO_HV | PINMUX_LPDR | PINMUX_TRISTATE | PINMUX_PULL_DOWN | 2; // Unused.
gpio_config(GPIO_PORT_S, GPIO_PIN_3, GPIO_MODE_GPIO); // GC detect. gpio_config(GPIO_PORT_S, GPIO_PIN_3, GPIO_MODE_GPIO); // GC detect.
// Configure touchscreen Touch Reset pin.
PINMUX_AUX(PINMUX_AUX_DAP4_SCLK) = PINMUX_PULL_DOWN | 1;
gpio_direction_output(GPIO_PORT_J, GPIO_PIN_7, GPIO_LOW);
usleep(20);
// Enable LDO6 for touchscreen AVDD and DVDD supply.
max7762x_regulator_set_voltage(REGULATOR_LDO6, 2900000);
max7762x_regulator_enable(REGULATOR_LDO6, true);
// Initialize I2C3. // Initialize I2C3.
pinmux_config_i2c(I2C_3); pinmux_config_i2c(I2C_3);
clock_enable_i2c(I2C_3); clock_enable_i2c(I2C_3);
i2c_init(I2C_3); i2c_init(I2C_3);
usleep(1000);
// Set Touch Reset pin.
gpio_write(GPIO_PORT_J, GPIO_PIN_7, GPIO_HIGH);
usleep(10000);
// Wait for the touchscreen module to get ready. // Wait for the touchscreen module to get ready.
touch_wait_event(STMFTS_EV_CONTROLLER_READY, 0, 20, NULL); touch_wait_event(STMFTS_EV_CONTROLLER_READY, 0, 20, NULL);

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2019 CTCaer * Copyright (c) 2018-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -38,8 +38,9 @@
#include "ff.h" /* Declarations of FatFs API */ #include "ff.h" /* Declarations of FatFs API */
#include "diskio.h" /* Declarations of device I/O functions */ #include "diskio.h" /* Declarations of device I/O functions */
#include <storage/mbr_gpt.h>
#include <gfx_utils.h> #include <gfx_utils.h>
#include "../../storage/nx_sd.h" #include <storage/sdmmc.h>
#define EFSPRINTF(text, ...) print_error(); gfx_printf("%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF); #define EFSPRINTF(text, ...) print_error(); gfx_printf("%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF);
//#define EFSPRINTF(...) //#define EFSPRINTF(...)
@@ -3274,7 +3275,6 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
stat = disk_status(fs->pdrv); stat = disk_status(fs->pdrv);
if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized */ if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized */
if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check write protection if needed */ if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check write protection if needed */
EFSPRINTF("WPEN1");
return FR_WRITE_PROTECTED; return FR_WRITE_PROTECTED;
} }
return FR_OK; /* The filesystem object is valid */ return FR_OK; /* The filesystem object is valid */
@@ -3285,14 +3285,13 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
/* Following code attempts to mount the volume. (analyze BPB and initialize the filesystem object) */ /* Following code attempts to mount the volume. (analyze BPB and initialize the filesystem object) */
fs->fs_type = 0; /* Clear the filesystem object */ fs->fs_type = 0; /* Clear the filesystem object */
fs->part_type = 0; /* Clear the Partition object */
fs->pdrv = LD2PD(vol); /* Bind the logical drive and a physical drive */ fs->pdrv = LD2PD(vol); /* Bind the logical drive and a physical drive */
stat = disk_initialize(fs->pdrv); /* Initialize the physical drive */ stat = disk_initialize(fs->pdrv); /* Initialize the physical drive */
if (stat & STA_NOINIT) { /* Check if the initialization succeeded */ if (stat & STA_NOINIT) { /* Check if the initialization succeeded */
EFSPRINTF("MDNR");
return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */ return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */
} }
if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check disk write protection if needed */ if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check disk write protection if needed */
EFSPRINTF("WPEN2");
return FR_WRITE_PROTECTED; return FR_WRITE_PROTECTED;
} }
#if FF_MAX_SS != FF_MIN_SS /* Get sector size (multiple sector size cfg only) */ #if FF_MAX_SS != FF_MIN_SS /* Get sector size (multiple sector size cfg only) */
@@ -3319,6 +3318,20 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
EFSPRINTF("BRNL"); EFSPRINTF("BRNL");
return FR_DISK_ERR; /* An error occured in the disk I/O layer */ return FR_DISK_ERR; /* An error occured in the disk I/O layer */
} }
#if FF_SIMPLE_GPT
if (fmt >= 2) {
/* If GPT Check the first partition */
gpt_header_t *gpt_header = (gpt_header_t *)fs->win;
if (move_window(fs, 1) != FR_OK) return FR_DISK_ERR;
if (!mem_cmp(&gpt_header->signature, "EFI PART", 8)) {
if (move_window(fs, gpt_header->part_ent_lba) != FR_OK) return FR_DISK_ERR;
gpt_entry_t *gpt_entry = (gpt_entry_t *)fs->win;
fs->part_type = 1;
bsect = gpt_entry->lba_start;
fmt = bsect ? check_fs(fs, bsect) : 3; /* Check the partition */
}
}
#endif
if (fmt >= 2) { if (fmt >= 2) {
EFSPRINTF("NOFAT"); EFSPRINTF("NOFAT");
return FR_NO_FILESYSTEM; /* No FAT volume is found */ return FR_NO_FILESYSTEM; /* No FAT volume is found */
@@ -4049,8 +4062,7 @@ FRESULT f_write (
} }
if (clst == 0) { if (clst == 0) {
EFSPRINTF("DSKFULL"); EFSPRINTF("DSKFULL");
fp->flag |= FA_MODIFIED; break; /* Could not allocate a new cluster (disk full) */
ABORT(fs, FR_DISK_ERR); /* Could not allocate a new cluster (disk full) */
} }
if (clst == 1) { if (clst == 1) {
EFSPRINTF("CCHK"); EFSPRINTF("CCHK");
@@ -4698,9 +4710,9 @@ DWORD *f_expand_cltbl (
} }
if (f_lseek(fp, CREATE_LINKMAP)) { /* Create cluster link table */ if (f_lseek(fp, CREATE_LINKMAP)) { /* Create cluster link table */
ff_memfree(fp->cltbl); ff_memfree(fp->cltbl);
fp->cltbl = NULL; fp->cltbl = (void *)0;
EFSPRINTF("CLTBLSZ"); EFSPRINTF("CLTBLSZ");
return NULL; return (void *)0;
} }
f_lseek(fp, 0); f_lseek(fp, 0);
@@ -5862,7 +5874,7 @@ FRESULT f_mkfs (
if (vol < 0) return FR_INVALID_DRIVE; if (vol < 0) return FR_INVALID_DRIVE;
if (FatFs[vol]) FatFs[vol]->fs_type = 0; /* Clear the volume if mounted */ if (FatFs[vol]) FatFs[vol]->fs_type = 0; /* Clear the volume if mounted */
pdrv = LD2PD(vol); /* Physical drive */ pdrv = LD2PD(vol); /* Physical drive */
part = 1; /* Partition (0:create as new, 1-4:get from partition table) */ part = LD2PT(vol); /* Partition (0:create as new, 1-4:get from partition table) */
/* Check physical drive status */ /* Check physical drive status */
stat = disk_initialize(pdrv); stat = disk_initialize(pdrv);
@@ -5893,7 +5905,7 @@ FRESULT f_mkfs (
if (!buf || sz_buf == 0) return FR_NOT_ENOUGH_CORE; if (!buf || sz_buf == 0) return FR_NOT_ENOUGH_CORE;
/* Determine where the volume to be located (b_vol, sz_vol) */ /* Determine where the volume to be located (b_vol, sz_vol) */
if (part > 0) { if (FF_MULTI_PARTITION && part != 0) {
/* Get partition information from partition table in the MBR */ /* Get partition information from partition table in the MBR */
if (disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Load MBR */ if (disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Load MBR */
if (ld_word(buf + BS_55AA) != 0xAA55) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if MBR is valid */ if (ld_word(buf + BS_55AA) != 0xAA55) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if MBR is valid */
@@ -6172,7 +6184,9 @@ FRESULT f_mkfs (
#endif #endif
/* Create FAT VBR */ /* Create FAT VBR */
mem_set(buf, 0, ss); mem_set(buf, 0, ss);
mem_cpy(buf + BS_JmpBoot, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code (x86), OEM name */ /* Boot jump code (x86), OEM name */
if (!(opt & FM_PRF2)) mem_cpy(buf + BS_JmpBoot, "\xEB\xFE\x90" "NYX1.0.0", 11);
else mem_cpy(buf + BS_JmpBoot, "\xEB\xE9\x90\x00\x00\x00\x00\x00\x00\x00\x00", 11);
st_word(buf + BPB_BytsPerSec, ss); /* Sector size [byte] */ st_word(buf + BPB_BytsPerSec, ss); /* Sector size [byte] */
buf[BPB_SecPerClus] = (BYTE)pau; /* Cluster size [sector] */ buf[BPB_SecPerClus] = (BYTE)pau; /* Cluster size [sector] */
st_word(buf + BPB_RsvdSecCnt, (WORD)sz_rsv); /* Size of reserved area */ st_word(buf + BPB_RsvdSecCnt, (WORD)sz_rsv); /* Size of reserved area */
@@ -6185,23 +6199,27 @@ FRESULT f_mkfs (
} }
buf[BPB_Media] = 0xF8; /* Media descriptor byte */ buf[BPB_Media] = 0xF8; /* Media descriptor byte */
st_word(buf + BPB_SecPerTrk, 63); /* Number of sectors per track (for int13) */ st_word(buf + BPB_SecPerTrk, 63); /* Number of sectors per track (for int13) */
st_word(buf + BPB_NumHeads, 255); /* Number of heads (for int13) */ st_word(buf + BPB_NumHeads, (opt & FM_PRF2) ? 16 : 255); /* Number of heads (for int13) */
st_dword(buf + BPB_HiddSec, b_vol); /* Volume offset in the physical drive [sector] */ st_dword(buf + BPB_HiddSec, b_vol); /* Volume offset in the physical drive [sector] */
if (fmt == FS_FAT32) { if (fmt == FS_FAT32) {
st_dword(buf + BS_VolID32, GET_FATTIME()); /* VSN */ st_dword(buf + BS_VolID32, (opt & FM_PRF2) ? 0 : GET_FATTIME()); /* VSN */
st_dword(buf + BPB_FATSz32, sz_fat); /* FAT size [sector] */ st_dword(buf + BPB_FATSz32, sz_fat); /* FAT size [sector] */
st_dword(buf + BPB_RootClus32, 2); /* Root directory cluster # (2) */ st_dword(buf + BPB_RootClus32, 2); /* Root directory cluster # (2) */
st_word(buf + BPB_FSInfo32, 1); /* Offset of FSINFO sector (VBR + 1) */ st_word(buf + BPB_FSInfo32, 1); /* Offset of FSINFO sector (VBR + 1) */
st_word(buf + BPB_BkBootSec32, 6); /* Offset of backup VBR (VBR + 6) */ st_word(buf + BPB_BkBootSec32, 6); /* Offset of backup VBR (VBR + 6) */
buf[BS_DrvNum32] = 0x80; /* Drive number (for int13) */ buf[BS_DrvNum32] = 0x80; /* Drive number (for int13) */
buf[BS_BootSig32] = 0x29; /* Extended boot signature */ buf[BS_BootSig32] = 0x29; /* Extended boot signature */
mem_cpy(buf + BS_VolLab32, "SWITCH SD " "FAT32 ", 19); /* Volume label, FAT signature */ /* Volume label, FAT signature */
if (!(opt & FM_PRF2)) mem_cpy(buf + BS_VolLab32, FF_MKFS_LABEL "FAT32 ", 19);
else mem_cpy(buf + BS_VolLab32, "NO NAME " "FAT32 ", 19);
} else { } else {
st_dword(buf + BS_VolID, GET_FATTIME()); /* VSN */ st_dword(buf + BS_VolID, GET_FATTIME()); /* VSN */
st_word(buf + BPB_FATSz16, (WORD)sz_fat); /* FAT size [sector] */ st_word(buf + BPB_FATSz16, (WORD)sz_fat); /* FAT size [sector] */
buf[BS_DrvNum] = 0x80; /* Drive number (for int13) */ buf[BS_DrvNum] = 0x80; /* Drive number (for int13) */
buf[BS_BootSig] = 0x29; /* Extended boot signature */ buf[BS_BootSig] = 0x29; /* Extended boot signature */
mem_cpy(buf + BS_VolLab, "SWITCH SD " "FAT ", 19); /* Volume label, FAT signature */ /* Volume label, FAT signature */
if (!(opt & FM_PRF2)) mem_cpy(buf + BS_VolLab, FF_MKFS_LABEL "FAT ", 19);
else mem_cpy(buf + BS_VolLab, "NO NAME " "FAT ", 19);
} }
st_word(buf + BS_55AA, 0xAA55); /* Signature (offset is fixed here regardless of sector size) */ st_word(buf + BS_55AA, 0xAA55); /* Signature (offset is fixed here regardless of sector size) */
if (disk_write(pdrv, buf, b_vol, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it to the VBR sector */ if (disk_write(pdrv, buf, b_vol, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it to the VBR sector */
@@ -6219,6 +6237,16 @@ FRESULT f_mkfs (
disk_write(pdrv, buf, b_vol + 1, 1); /* Write original FSINFO (VBR + 1) */ disk_write(pdrv, buf, b_vol + 1, 1); /* Write original FSINFO (VBR + 1) */
} }
/* Create PRF2SAFE info */
if (fmt == FS_FAT32 && opt & FM_PRF2) {
mem_set(buf, 0, ss);
buf[16] = 0x64; /* Record type */
st_dword(buf + 32, 0x03); /* Unknown. SYSTEM: 0x3F00. USER: 0x03. Volatile. */
st_dword(buf + 36, 25); /* Entries. SYSTEM: 22. USER: 25.Static? */
st_dword(buf + 508, 0x517BBFE0); /* Custom CRC32. SYSTEM: 0x6B673904. USER: 0x517BBFE0. */
disk_write(pdrv, buf, b_vol + 3, 1); /* Write PRF2SAFE info (VBR + 3) */
}
/* Initialize FAT area */ /* Initialize FAT area */
mem_set(buf, 0, (UINT)szb_buf); mem_set(buf, 0, (UINT)szb_buf);
sect = b_fat; /* FAT start sector */ sect = b_fat; /* FAT start sector */
@@ -6264,7 +6292,7 @@ FRESULT f_mkfs (
} }
/* Update partition information */ /* Update partition information */
if (part != 0) { /* Created in the existing partition */ if (FF_MULTI_PARTITION && part != 0) { /* Created in the existing partition */
/* Update system ID in the partition table */ /* Update system ID in the partition table */
if (disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Read the MBR */ if (disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Read the MBR */
buf[MBR_Table + (part - 1) * SZ_PTE + PTE_System] = sys; /* Set system ID */ buf[MBR_Table + (part - 1) * SZ_PTE + PTE_System] = sys; /* Set system ID */
@@ -6372,6 +6400,7 @@ FRESULT f_fdisk (
#endif /* FF_MULTI_PARTITION */ #endif /* FF_MULTI_PARTITION */
#endif /* FF_USE_MKFS && !FF_FS_READONLY */ #endif /* FF_USE_MKFS && !FF_FS_READONLY */
// We don't need these where we're going...
extern sdmmc_storage_t sd_storage; extern sdmmc_storage_t sd_storage;
@@ -6449,7 +6478,6 @@ FRESULT f_fdisk_mod (
LEAVE_MKFS(res); LEAVE_MKFS(res);
} }
#if FF_USE_STRFUNC #if FF_USE_STRFUNC
#if FF_USE_LFN && FF_LFN_UNICODE && (FF_STRF_ENCODE < 0 || FF_STRF_ENCODE > 3) #if FF_USE_LFN && FF_LFN_UNICODE && (FF_STRF_ENCODE < 0 || FF_STRF_ENCODE > 3)
#error Wrong FF_STRF_ENCODE setting #error Wrong FF_STRF_ENCODE setting
@@ -6782,6 +6810,8 @@ int f_puts (
putbuff pb; putbuff pb;
if (str == (void *)0) return EOF; /* String is NULL */
putc_init(&pb, fp); putc_init(&pb, fp);
while (*str) putc_bfd(&pb, *str++); /* Put the string */ while (*str) putc_bfd(&pb, *str++); /* Put the string */
return putc_flush(&pb); return putc_flush(&pb);
@@ -6808,6 +6838,8 @@ int f_printf (
TCHAR c, d, str[32], *p; TCHAR c, d, str[32], *p;
if (fmt == (void *)0) return EOF; /* String is NULL */
putc_init(&pb, fp); putc_init(&pb, fp);
va_start(arp, fmt); va_start(arp, fmt);

View File

@@ -95,8 +95,8 @@ typedef DWORD FSIZE_t;
/* Filesystem object structure (FATFS) */ /* Filesystem object structure (FATFS) */
typedef struct { typedef struct {
BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
BYTE fs_type; /* Filesystem type (0:not mounted) */ BYTE fs_type; /* Filesystem type (0:not mounted) */
BYTE part_type; /* Partition type (0:MBR, 1:GPT) */
BYTE pdrv; /* Associated physical drive */ BYTE pdrv; /* Associated physical drive */
BYTE n_fats; /* Number of FATs (1 or 2) */ BYTE n_fats; /* Number of FATs (1 or 2) */
BYTE wflag; /* win[] flag (b0:dirty) */ BYTE wflag; /* win[] flag (b0:dirty) */
@@ -138,6 +138,7 @@ typedef struct {
DWORD bitbase; /* Allocation bitmap base sector */ DWORD bitbase; /* Allocation bitmap base sector */
#endif #endif
DWORD winsect; /* Current sector appearing in the win[] */ DWORD winsect; /* Current sector appearing in the win[] */
BYTE win[FF_MAX_SS] __attribute__((aligned(8))); /* Disk access window for Directory, FAT (and file data at tiny cfg). DMA aligned. */
} FATFS; } FATFS;
@@ -168,9 +169,6 @@ typedef struct {
/* File object structure (FIL) */ /* File object structure (FIL) */
typedef struct { typedef struct {
#if !FF_FS_TINY
BYTE buf[FF_MAX_SS]; /* File private data read/write window */
#endif
FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */ FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */
BYTE flag; /* File status flags */ BYTE flag; /* File status flags */
BYTE err; /* Abort flag (error code) */ BYTE err; /* Abort flag (error code) */
@@ -184,6 +182,9 @@ typedef struct {
#if FF_USE_FASTSEEK #if FF_USE_FASTSEEK
DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */ DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */
#endif #endif
#if !FF_FS_TINY
BYTE buf[FF_MAX_SS] __attribute__((aligned(8))); /* File private data read/write window. DMA aligned. */
#endif
} FIL; } FIL;
@@ -291,7 +292,7 @@ FRESULT f_expand (FIL* fp, FSIZE_t fsz, BYTE opt); /* Allocate a contiguous
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */ FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */
FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */ FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */
FRESULT f_fdisk (BYTE pdrv, const DWORD* szt, void* work); /* Divide a physical drive into some partitions */ FRESULT f_fdisk (BYTE pdrv, const DWORD* szt, void* work); /* Divide a physical drive into some partitions */
FRESULT f_fdisk_mod (BYTE pdrv, const DWORD* szt, void* work); // Modded version of f_fdisk that works:tm: FRESULT f_fdisk_mod (BYTE pdrv, const DWORD* szt, void* work);
FRESULT f_setcp (WORD cp); /* Set current code page */ FRESULT f_setcp (WORD cp); /* Set current code page */
int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */ int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */
int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */ int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */
@@ -366,6 +367,7 @@ int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */
#define FM_EXFAT 0x04 #define FM_EXFAT 0x04
#define FM_ANY 0x07 #define FM_ANY 0x07
#define FM_SFD 0x08 #define FM_SFD 0x08
#define FM_PRF2 0x10
/* Filesystem type (FATFS.fs_type) */ /* Filesystem type (FATFS.fs_type) */
#define FS_FAT12 1 #define FS_FAT12 1

View File

@@ -17,7 +17,7 @@
#ifndef LV_CONF_H #ifndef LV_CONF_H
#define LV_CONF_H #define LV_CONF_H
#include <utils/types.h> #include <soc/timer.h>
#include <memory_map.h> #include <memory_map.h>
/*=================== /*===================
Dynamic memory Dynamic memory
@@ -147,10 +147,10 @@
#define LV_COMPILER_VLA_SUPPORTED 1 /* 1: Variable length array is supported*/ #define LV_COMPILER_VLA_SUPPORTED 1 /* 1: Variable length array is supported*/
/*HAL settings*/ /*HAL settings*/
#define LV_TICK_CUSTOM 1 /*1: use a custom tick source (removing the need to manually update the tick with `lv_tick_inc`) */ #define LV_TICK_CUSTOM 1 /*1: use a custom tick source (removing the need to manually update the tick with `lv_tick_inc`) */
#if LV_TICK_CUSTOM == 1 #if LV_TICK_CUSTOM == 1
#define LV_TICK_CUSTOM_INCLUDE <utils/util.h> /*Header for the sys time function*/ #define LV_TICK_CUSTOM_INCLUDE <soc/timer.h> /*Header for the sys time function*/
#define LV_TICK_CUSTOM_SYS_TIME_EXPR (get_tmr_ms()) /*Expression evaluating to current systime in ms*/ #define LV_TICK_CUSTOM_SYS_TIME_EXPR ((u32)get_tmr_ms()) /*Expression evaluating to current systime in ms*/
#endif /*LV_TICK_CUSTOM*/ #endif /*LV_TICK_CUSTOM*/
@@ -296,6 +296,9 @@
/*Message box (dependencies: lv_rect, lv_btnm, lv_label)*/ /*Message box (dependencies: lv_rect, lv_btnm, lv_label)*/
#define USE_LV_MBOX 1 #define USE_LV_MBOX 1
#if USE_LV_MBOX != 0
# define LV_MBOX_CLOSE_ANIM_TIME 200 /*ms*/
#endif
/*Text area (dependencies: lv_label, lv_page)*/ /*Text area (dependencies: lv_label, lv_page)*/
#define USE_LV_TA 1 #define USE_LV_TA 1

View File

@@ -546,8 +546,8 @@ static void obj_to_foreground(lv_obj_t * obj)
/*Move the last_top object to the foreground*/ /*Move the last_top object to the foreground*/
lv_obj_t * par = lv_obj_get_parent(last_top); lv_obj_t * par = lv_obj_get_parent(last_top);
/*After list change it will be the new head*/ /*After list change it will be the new head*/
lv_ll_chg_list(&par->child_ll, &par->child_ll, last_top); if (lv_ll_chg_list(&par->child_ll, &par->child_ll, last_top))
lv_obj_invalidate(last_top); lv_obj_invalidate(last_top); /*Only invalidate if not top*/
} }
} }

View File

@@ -646,8 +646,8 @@ static void indev_proc_press(lv_indev_proc_t * proc)
/*Move the last_top object to the foreground*/ /*Move the last_top object to the foreground*/
lv_obj_t * par = lv_obj_get_parent(last_top); lv_obj_t * par = lv_obj_get_parent(last_top);
/*After list change it will be the new head*/ /*After list change it will be the new head*/
lv_ll_chg_list(&par->child_ll, &par->child_ll, last_top); if (lv_ll_chg_list(&par->child_ll, &par->child_ll, last_top))
lv_obj_invalidate(last_top); lv_obj_invalidate(last_top); /*Only invalidate if not top*/
} }
/*Send a signal about the press*/ /*Send a signal about the press*/

View File

@@ -412,17 +412,17 @@ static inline uint8_t lv_color_brightness(lv_color_t color)
#endif #endif
#if LV_COLOR_DEPTH == 32 // Concatenate into one 32-bit set. #if LV_COLOR_DEPTH == 32 // Concatenate into one 32-bit set.
#define LV_COLOR_HEX(c) ((lv_color_t){.full = (c | 0xFF000000)}) #define LV_COLOR_HEX(c) ((lv_color_t){.full = ((c) | 0xFF000000)})
#else #else
#define LV_COLOR_HEX(c) LV_COLOR_MAKE(((uint32_t)((uint32_t)c >> 16) & 0xFF), \ #define LV_COLOR_HEX(c) LV_COLOR_MAKE(((uint32_t)((uint32_t)(c) >> 16) & 0xFF), \
((uint32_t)((uint32_t)c >> 8) & 0xFF), \ ((uint32_t)((uint32_t)(c) >> 8) & 0xFF), \
((uint32_t) c & 0xFF)) ((uint32_t) (c) & 0xFF))
#endif #endif
/*Usage LV_COLOR_HEX3(0x16C) which means LV_COLOR_HEX(0x1166CC)*/ /*Usage LV_COLOR_HEX3(0x16C) which means LV_COLOR_HEX(0x1166CC)*/
#define LV_COLOR_HEX3(c) LV_COLOR_MAKE((((c >> 4) & 0xF0) | ((c >> 8) & 0xF)), \ #define LV_COLOR_HEX3(c) LV_COLOR_MAKE(((((c) >> 4) & 0xF0) | (((c) >> 8) & 0xF)), \
((uint32_t)(c & 0xF0) | ((c & 0xF0) >> 4)), \ ((uint32_t)((c) & 0xF0) | (((c) & 0xF0) >> 4)), \
((uint32_t)(c & 0xF) | ((c & 0xF) << 4))) ((uint32_t)((c) & 0xF) | (((c) & 0xF) << 4)))
/** /**

View File

@@ -215,9 +215,12 @@ void lv_ll_clear(lv_ll_t * ll_p)
* @param ll_ori_p pointer to the original (old) linked list * @param ll_ori_p pointer to the original (old) linked list
* @param ll_new_p pointer to the new linked list * @param ll_new_p pointer to the new linked list
* @param node pointer to a node * @param node pointer to a node
* @return head changed
*/ */
void lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node) bool lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node)
{ {
bool changed = ll_new_p->head != node;
lv_ll_rem(ll_ori_p, node); lv_ll_rem(ll_ori_p, node);
/*Set node as head*/ /*Set node as head*/
@@ -232,6 +235,8 @@ void lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node)
if(ll_new_p->tail == NULL) { /*If there is no tail (first node) set the tail too*/ if(ll_new_p->tail == NULL) { /*If there is no tail (first node) set the tail too*/
ll_new_p->tail = node; ll_new_p->tail = node;
} }
return changed;
} }
/** /**

View File

@@ -89,8 +89,9 @@ void lv_ll_clear(lv_ll_t * ll_p);
* @param ll_ori_p pointer to the original (old) linked list * @param ll_ori_p pointer to the original (old) linked list
* @param ll_new_p pointer to the new linked list * @param ll_new_p pointer to the new linked list
* @param node pointer to a node * @param node pointer to a node
* @return head changed
*/ */
void lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node); bool lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node);
/** /**
* Return with head node of the linked list * Return with head node of the linked list

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018-2019 CTCaer * Copyright (c) 2018-2022 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -32,13 +32,16 @@
#define COLOR_HOS_TEAL_LIGHT (lv_color_hsv_to_rgb(_hue, 100, 72)) // 0x00B78F #define COLOR_HOS_TEAL_LIGHT (lv_color_hsv_to_rgb(_hue, 100, 72)) // 0x00B78F
#define COLOR_HOS_TEAL (lv_color_hsv_to_rgb(_hue, 100, 64)) // 0x00A273 #define COLOR_HOS_TEAL (lv_color_hsv_to_rgb(_hue, 100, 64)) // 0x00A273
#define COLOR_HOS_ORANGE LV_COLOR_HEX(0xFF5500) #define COLOR_HOS_ORANGE LV_COLOR_HEX(0xFF5500)
#define COLOR_HOS_BG_DARKER LV_COLOR_HEX(0x1B1B1B)
#define COLOR_HOS_BG_DARK LV_COLOR_HEX(0x222222)
#define COLOR_HOS_BG LV_COLOR_HEX(0x2D2D2D)
#define COLOR_HOS_BG_LIGHT LV_COLOR_HEX(0x3D3D3D)
#define COLOR_HOS_LIGHT_BORDER LV_COLOR_HEX(0x4D4D4D)
#define COLOR_HOS_TXT_WHITE LV_COLOR_HEX(0xFBFBFB) #define COLOR_HOS_TXT_WHITE LV_COLOR_HEX(0xFBFBFB)
#define COLOR_BG_DARKER LV_COLOR_HEX(theme_bg_color ? (theme_bg_color - 0x121212) : 0x0B0B0B) // 0x1B1B1B.
#define COLOR_BG_DARK LV_COLOR_HEX(theme_bg_color ? (theme_bg_color - 0x0B0B0B) : 0x121212) // 0x222222.
#define COLOR_BG LV_COLOR_HEX(theme_bg_color) // 0x2D2D2D.
#define COLOR_BG_LIGHT LV_COLOR_HEX(theme_bg_color ? (theme_bg_color + 0x101010) : 0x2D2D2D) // 0x3D3D3D.
#define COLOR_BG_LIGHTER LV_COLOR_HEX(theme_bg_color ? (theme_bg_color + 0x191919) : 0x363636) // 0x464646.
#define COLOR_LIGHT_BORDER LV_COLOR_HEX(theme_bg_color ? (theme_bg_color + 0x202020) : 0x3D3D3D) // 0x4D4D4D.
/********************** /**********************
* TYPEDEFS * TYPEDEFS
**********************/ **********************/
@@ -57,8 +60,9 @@ static lv_style_t def;
static lv_style_t sb; static lv_style_t sb;
/*Saved input parameters*/ /*Saved input parameters*/
static uint16_t _hue; static uint16_t _hue;
static lv_font_t * _font; static lv_font_t * _font;
uint32_t theme_bg_color;
/********************** /**********************
* MACROS * MACROS
@@ -80,18 +84,17 @@ static void basic_init(void)
//def.image.opa = LV_OPA_COVER; //def.image.opa = LV_OPA_COVER;
lv_style_copy(&bg, &def); lv_style_copy(&bg, &def);
bg.body.main_color = COLOR_HOS_BG; bg.body.main_color = COLOR_BG;
//bg.body.main_color = LV_COLOR_BLACK;
bg.body.grad_color = bg.body.main_color; bg.body.grad_color = bg.body.main_color;
bg.body.radius = 0; bg.body.radius = 0;
bg.body.empty = 1; bg.body.empty = 1;
lv_style_copy(&panel, &def); lv_style_copy(&panel, &def);
panel.body.radius = DEF_RADIUS; panel.body.radius = DEF_RADIUS;
panel.body.main_color = COLOR_HOS_BG; panel.body.main_color = COLOR_BG;
panel.body.grad_color = COLOR_HOS_BG; panel.body.grad_color = COLOR_BG;
panel.body.border.width = 1; panel.body.border.width = 1;
panel.body.border.color = COLOR_HOS_LIGHT_BORDER; panel.body.border.color = COLOR_LIGHT_BORDER;
panel.body.border.opa = LV_OPA_COVER; panel.body.border.opa = LV_OPA_COVER;
panel.body.shadow.color = COLOR_SHADOW_LIGHT; panel.body.shadow.color = COLOR_SHADOW_LIGHT;
panel.body.shadow.type = LV_SHADOW_BOTTOM; panel.body.shadow.type = LV_SHADOW_BOTTOM;
@@ -129,7 +132,7 @@ static void btn_init(void)
static lv_style_t rel, pr, tgl_rel, tgl_pr, ina; static lv_style_t rel, pr, tgl_rel, tgl_pr, ina;
lv_style_copy(&rel, &def); lv_style_copy(&rel, &def);
rel.body.main_color = COLOR_HOS_BG_LIGHT; rel.body.main_color = COLOR_BG_LIGHT;
rel.body.grad_color = rel.body.main_color; rel.body.grad_color = rel.body.main_color;
rel.body.radius = 6; rel.body.radius = 6;
rel.body.padding.hor = LV_DPI / 3; rel.body.padding.hor = LV_DPI / 3;
@@ -139,7 +142,7 @@ static void btn_init(void)
rel.body.shadow.type = LV_SHADOW_BOTTOM; rel.body.shadow.type = LV_SHADOW_BOTTOM;
rel.body.shadow.width = 6; rel.body.shadow.width = 6;
rel.body.border.width = 0; rel.body.border.width = 0;
rel.body.border.color = COLOR_HOS_BG_LIGHT; rel.body.border.color = COLOR_BG_LIGHT;
rel.body.border.part = LV_BORDER_FULL; rel.body.border.part = LV_BORDER_FULL;
//rel.text.color = COLOR_HOS_TXT_WHITE; //rel.text.color = COLOR_HOS_TXT_WHITE;
@@ -162,7 +165,7 @@ static void btn_init(void)
tgl_pr.body.shadow.width = 0; tgl_pr.body.shadow.width = 0;
lv_style_copy(&ina, &rel); lv_style_copy(&ina, &rel);
ina.body.main_color = COLOR_HOS_BG_DARK; ina.body.main_color = COLOR_BG_DARK;
ina.body.grad_color = ina.body.main_color; ina.body.grad_color = ina.body.main_color;
//ina.body.shadow.width = 0; //ina.body.shadow.width = 0;
ina.text.color = LV_COLOR_HEX(0x888888); ina.text.color = LV_COLOR_HEX(0x888888);
@@ -207,7 +210,7 @@ static void img_init(void)
img_light.image.intense = LV_OPA_80; img_light.image.intense = LV_OPA_80;
lv_style_copy(&img_dark, &def); lv_style_copy(&img_dark, &def);
img_dark.image.color = COLOR_HOS_BG_DARKER; img_dark.image.color = COLOR_BG_DARKER;
img_dark.image.intense = LV_OPA_80; img_dark.image.intense = LV_OPA_80;
@@ -250,7 +253,7 @@ static void bar_init(void)
static lv_style_t bar_bg, bar_indic; static lv_style_t bar_bg, bar_indic;
lv_style_copy(&bar_bg, &def); lv_style_copy(&bar_bg, &def);
bar_bg.body.main_color = COLOR_HOS_LIGHT_BORDER; bar_bg.body.main_color = COLOR_LIGHT_BORDER;
bar_bg.body.grad_color = bar_bg.body.main_color; bar_bg.body.grad_color = bar_bg.body.main_color;
bar_bg.body.radius = 3; bar_bg.body.radius = 3;
bar_bg.body.border.width = 0; bar_bg.body.border.width = 0;
@@ -536,9 +539,9 @@ static void mbox_init(void)
static lv_style_t bg; static lv_style_t bg;
lv_style_copy(&bg, theme.panel); lv_style_copy(&bg, theme.panel);
bg.body.main_color = LV_COLOR_HEX(0x464646); bg.body.main_color = COLOR_BG_LIGHTER;
bg.body.grad_color = bg.body.main_color; bg.body.grad_color = bg.body.main_color;
bg.body.shadow.color = COLOR_HOS_BG; bg.body.shadow.color = COLOR_BG;
bg.body.shadow.type = LV_SHADOW_FULL; bg.body.shadow.type = LV_SHADOW_FULL;
bg.body.shadow.width = 8; bg.body.shadow.width = 8;
@@ -628,7 +631,7 @@ static void list_init(void)
// pr.text.font = _font; // pr.text.font = _font;
lv_style_copy(&tgl_rel, &pr); lv_style_copy(&tgl_rel, &pr);
tgl_rel.body.main_color = COLOR_HOS_BG_LIGHT; tgl_rel.body.main_color = COLOR_BG_LIGHT;
tgl_rel.body.grad_color = tgl_rel.body.main_color; tgl_rel.body.grad_color = tgl_rel.body.main_color;
//tgl_rel.text.color = lv_color_hsv_to_rgb(_hue, 5, 95); //tgl_rel.text.color = lv_color_hsv_to_rgb(_hue, 5, 95);
tgl_rel.text.color = COLOR_HOS_TEAL_LIGHTER; tgl_rel.text.color = COLOR_HOS_TEAL_LIGHTER;
@@ -639,7 +642,7 @@ static void list_init(void)
tgl_pr.body.border.width = 0; tgl_pr.body.border.width = 0;
lv_style_copy(&ina, &pr); lv_style_copy(&ina, &pr);
ina.body.main_color = COLOR_HOS_BG_DARK; ina.body.main_color = COLOR_BG_DARK;
ina.body.grad_color = ina.body.main_color; ina.body.grad_color = ina.body.main_color;
theme.list.sb = &sb; theme.list.sb = &sb;
@@ -667,7 +670,7 @@ static void ddlist_init(void)
bg.text.color = COLOR_HOS_TURQUOISE; bg.text.color = COLOR_HOS_TURQUOISE;
lv_style_copy(&sel, &bg); lv_style_copy(&sel, &bg);
sel.body.main_color = COLOR_HOS_BG_LIGHT; sel.body.main_color = COLOR_BG_LIGHT;
sel.body.grad_color = sel.body.main_color; sel.body.grad_color = sel.body.main_color;
theme.ddlist.bg = &bg; theme.ddlist.bg = &bg;
@@ -713,7 +716,7 @@ static void tabview_init(void)
indic.body.opa = LV_OPA_0; indic.body.opa = LV_OPA_0;
lv_style_copy(&btn_bg, &def); lv_style_copy(&btn_bg, &def);
btn_bg.body.main_color = COLOR_HOS_BG; btn_bg.body.main_color = COLOR_BG;
btn_bg.body.grad_color = btn_bg.body.main_color; btn_bg.body.grad_color = btn_bg.body.main_color;
btn_bg.body.radius = 0; btn_bg.body.radius = 0;
btn_bg.body.empty = 1; btn_bg.body.empty = 1;
@@ -734,7 +737,7 @@ static void tabview_init(void)
rel.text.font = _font; rel.text.font = _font;
lv_style_copy(&pr, &def); lv_style_copy(&pr, &def);
pr.body.main_color = COLOR_HOS_BG_LIGHT; pr.body.main_color = COLOR_BG_LIGHT;
pr.body.grad_color = pr.body.main_color; pr.body.grad_color = pr.body.main_color;
pr.body.border.width = 0; pr.body.border.width = 0;
pr.body.empty = 0; pr.body.empty = 0;
@@ -750,7 +753,7 @@ static void tabview_init(void)
tgl_rel.text.color = COLOR_HOS_TURQUOISE; tgl_rel.text.color = COLOR_HOS_TURQUOISE;
lv_style_copy(&tgl_pr, &def); lv_style_copy(&tgl_pr, &def);
tgl_pr.body.main_color = COLOR_HOS_BG_LIGHT; tgl_pr.body.main_color = COLOR_BG_LIGHT;
tgl_pr.body.grad_color = tgl_pr.body.main_color; tgl_pr.body.grad_color = tgl_pr.body.main_color;
tgl_pr.body.border.width = 0; tgl_pr.body.border.width = 0;
tgl_pr.body.empty = 0; tgl_pr.body.empty = 0;
@@ -797,7 +800,7 @@ static void win_init(void)
static lv_style_t header, rel, pr; static lv_style_t header, rel, pr;
lv_style_copy(&header, &def); lv_style_copy(&header, &def);
header.body.main_color = COLOR_HOS_BG; header.body.main_color = COLOR_BG;
header.body.grad_color = header.body.main_color; header.body.grad_color = header.body.main_color;
header.body.radius = 0; header.body.radius = 0;
header.body.border.width = 0; header.body.border.width = 0;
@@ -843,10 +846,11 @@ static void win_init(void)
* @param font pointer to a font (NULL to use the default) * @param font pointer to a font (NULL to use the default)
* @return pointer to the initialized theme * @return pointer to the initialized theme
*/ */
lv_theme_t * lv_theme_hekate_init(uint16_t hue, lv_font_t * font) lv_theme_t * lv_theme_hekate_init(uint32_t bg_color, uint16_t hue, lv_font_t * font)
{ {
if(font == NULL) font = LV_FONT_DEFAULT; if(font == NULL) font = LV_FONT_DEFAULT;
theme_bg_color = bg_color;
_hue = hue; _hue = hue;
_font = font; _font = font;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018-2019 CTCaer * Copyright (c) 2018-2022 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -35,6 +35,14 @@ extern "C" {
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#define COLOR_HOS_BG_BASE_DEFAULT 0x1B1B1B
#define COLOR_HOS_BG_BASE_BLACK 0x000000
#define COLOR_HOS_BG_DARKER 0x1B1B1B
#define COLOR_HOS_BG_DARK 0x222222
#define COLOR_HOS_BG 0x2D2D2D
#define COLOR_HOS_BG_LIGHT 0x3D3D3D
#define COLOR_HOS_LIGHT_BORDER 0x4D4D4D
/********************** /**********************
* TYPEDEFS * TYPEDEFS
@@ -44,13 +52,15 @@ extern "C" {
* GLOBAL PROTOTYPES * GLOBAL PROTOTYPES
**********************/ **********************/
extern uint32_t theme_bg_color;
/** /**
* Initialize the material theme * Initialize the material theme
* @param hue [0..360] hue value from HSV color space to define the theme's base color * @param hue [0..360] hue value from HSV color space to define the theme's base color
* @param font pointer to a font (NULL to use the default) * @param font pointer to a font (NULL to use the default)
* @return pointer to the initialized theme * @return pointer to the initialized theme
*/ */
lv_theme_t * lv_theme_hekate_init(uint16_t hue, lv_font_t *font); lv_theme_t * lv_theme_hekate_init(uint32_t bg_color, uint16_t hue, lv_font_t *font);
/** /**
* Get a pointer to the theme * Get a pointer to the theme

View File

@@ -38,7 +38,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <mem/heap.h> #include <mem/heap.h>
#include <rtc/max77620-rtc.h> #include <rtc/max77620-rtc.h>
#include <sec/se.h> #include <sec/se.h>
#include <storage/nx_sd.h> #include <storage/sd.h>
#include <utils/ini.h> #include <utils/ini.h>
#include <utils/sprintf.h> #include <utils/sprintf.h>

View File

@@ -698,6 +698,8 @@
typedef enum _emc_mr_t typedef enum _emc_mr_t
{ {
MR0_FEAT = 0,
MR4_TEMP = 4,
MR5_MAN_ID = 5, MR5_MAN_ID = 5,
MR6_REV_ID1 = 6, MR6_REV_ID1 = 6,
MR7_REV_ID2 = 7, MR7_REV_ID2 = 7,

View File

@@ -19,33 +19,44 @@
#include "heap.h" #include "heap.h"
#include <gfx_utils.h> #include <gfx_utils.h>
static void _heap_create(heap_t *heap, u32 start) heap_t _heap;
static void _heap_create(void *start)
{ {
heap->start = start; _heap.start = start;
heap->first = NULL; _heap.first = NULL;
_heap.last = NULL;
} }
// Node info is before node address. // Node info is before node address.
static u32 _heap_alloc(heap_t *heap, u32 size) static void *_heap_alloc(u32 size)
{ {
hnode_t *node, *new_node; hnode_t *node, *new_node;
// Align to cache line size. // Align to cache line size.
size = ALIGN(size, sizeof(hnode_t)); size = ALIGN(size, sizeof(hnode_t));
if (!heap->first) // First allocation.
if (!_heap.first)
{ {
node = (hnode_t *)heap->start; node = (hnode_t *)_heap.start;
node->used = 1; node->used = 1;
node->size = size; node->size = size;
node->prev = NULL; node->prev = NULL;
node->next = NULL; node->next = NULL;
heap->first = node;
return (u32)node + sizeof(hnode_t); _heap.first = node;
_heap.last = node;
return (void *)node + sizeof(hnode_t);
} }
node = heap->first; #ifdef BDK_MALLOC_NO_DEFRAG
// Get the last allocated block.
node = _heap.last;
#else
// Get first block and find the first available one.
node = _heap.first;
while (true) while (true)
{ {
// Check if there's available unused node. // Check if there's available unused node.
@@ -53,7 +64,7 @@ static u32 _heap_alloc(heap_t *heap, u32 size)
{ {
// Size and offset of the new unused node. // Size and offset of the new unused node.
u32 new_size = node->size - size; u32 new_size = node->size - size;
new_node = (hnode_t *)((u32)node + sizeof(hnode_t) + size); new_node = (hnode_t *)((void *)node + sizeof(hnode_t) + size);
// If there's aligned unused space from the old node, // If there's aligned unused space from the old node,
// create a new one and set the leftover size. // create a new one and set the leftover size.
@@ -76,7 +87,7 @@ static u32 _heap_alloc(heap_t *heap, u32 size)
node->size = size; node->size = size;
node->used = 1; node->used = 1;
return (u32)node + sizeof(hnode_t); return (void *)node + sizeof(hnode_t);
} }
// No unused node found, try the next one. // No unused node found, try the next one.
@@ -85,23 +96,29 @@ static u32 _heap_alloc(heap_t *heap, u32 size)
else else
break; break;
} }
#endif
// No unused node found, create a new one. // No unused node found, create a new one.
new_node = (hnode_t *)((u32)node + sizeof(hnode_t) + node->size); new_node = (hnode_t *)((void *)node + sizeof(hnode_t) + node->size);
new_node->used = 1; new_node->used = 1;
new_node->size = size; new_node->size = size;
new_node->prev = node; new_node->prev = node;
new_node->next = NULL; new_node->next = NULL;
node->next = new_node;
return (u32)new_node + sizeof(hnode_t); node->next = new_node;
_heap.last = new_node;
return (void *)new_node + sizeof(hnode_t);
} }
static void _heap_free(heap_t *heap, u32 addr) static void _heap_free(void *addr)
{ {
hnode_t *node = (hnode_t *)(addr - sizeof(hnode_t)); hnode_t *node = (hnode_t *)(addr - sizeof(hnode_t));
node->used = 0; node->used = 0;
node = heap->first; node = _heap.first;
#ifndef BDK_MALLOC_NO_DEFRAG
// Do simple defragmentation on next blocks.
while (node) while (node)
{ {
if (!node->used) if (!node->used)
@@ -117,36 +134,35 @@ static void _heap_free(heap_t *heap, u32 addr)
} }
node = node->next; node = node->next;
} }
#endif
} }
heap_t _heap; void heap_init(void *base)
void heap_init(u32 base)
{ {
_heap_create(&_heap, base); _heap_create(base);
} }
void heap_copy(heap_t *heap) void heap_set(heap_t *heap)
{ {
memcpy(&_heap, heap, sizeof(heap_t)); memcpy(&_heap, heap, sizeof(heap_t));
} }
void *malloc(u32 size) void *malloc(u32 size)
{ {
return (void *)_heap_alloc(&_heap, size); return _heap_alloc(size);
} }
void *calloc(u32 num, u32 size) void *calloc(u32 num, u32 size)
{ {
void *res = (void *)_heap_alloc(&_heap, num * size); void *res = (void *)_heap_alloc(num * size);
memset(res, 0, ALIGN(num * size, sizeof(hnode_t))); // Clear the aligned size. memset(res, 0, ALIGN(num * size, sizeof(hnode_t))); // Clear the aligned size.
return res; return res;
} }
void free(void *buf) void free(void *buf)
{ {
if ((u32)buf >= _heap.start) if (buf >= _heap.start)
_heap_free(&_heap, (u32)buf); _heap_free(buf);
} }
void heap_monitor(heap_monitor_t *mon, bool print_node_stats) void heap_monitor(heap_monitor_t *mon, bool print_node_stats)
@@ -158,7 +174,10 @@ void heap_monitor(heap_monitor_t *mon, bool print_node_stats)
while (true) while (true)
{ {
if (node->used) if (node->used)
{
mon->nodes_used++;
mon->used += node->size + sizeof(hnode_t); mon->used += node->size + sizeof(hnode_t);
}
else else
mon->total += node->size + sizeof(hnode_t); mon->total += node->size + sizeof(hnode_t);
@@ -174,4 +193,5 @@ void heap_monitor(heap_monitor_t *mon, bool print_node_stats)
break; break;
} }
mon->total += mon->used; mon->total += mon->used;
mon->nodes_total = count;
} }

View File

@@ -31,18 +31,21 @@ typedef struct _hnode
typedef struct _heap typedef struct _heap
{ {
u32 start; void *start;
hnode_t *first; hnode_t *first;
hnode_t *last;
} heap_t; } heap_t;
typedef struct typedef struct
{ {
u32 total; u32 total;
u32 used; u32 used;
u32 nodes_total;
u32 nodes_used;
} heap_monitor_t; } heap_monitor_t;
void heap_init(u32 base); void heap_init(void *base);
void heap_copy(heap_t *heap); void heap_set(heap_t *heap);
void *malloc(u32 size); void *malloc(u32 size);
void *calloc(u32 num, u32 size); void *calloc(u32 num, u32 size);
void free(void *buf); void free(void *buf);

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -17,11 +17,9 @@
#include <memory_map.h> #include <memory_map.h>
#include <mem/mc.h> #include <mem/mc.h>
#include <soc/timer.h>
#include <soc/t210.h> #include <soc/t210.h>
#include <soc/clock.h> #include <soc/clock.h>
#include <utils/util.h>
//#define CONFIG_ENABLE_AHB_REDIRECT
void mc_config_tsec_carveout(u32 bom, u32 size1mb, bool lock) void mc_config_tsec_carveout(u32 bom, u32 size1mb, bool lock)
{ {
@@ -125,13 +123,13 @@ void mc_config_carveout()
MC(MC_SECURITY_CARVEOUT5_CFG0) = 0x8F; MC(MC_SECURITY_CARVEOUT5_CFG0) = 0x8F;
} }
void mc_enable_ahb_redirect(bool full_aperture) void mc_enable_ahb_redirect()
{ {
// Enable ARC_CLK_OVR_ON. // Enable ARC_CLK_OVR_ON.
CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) = (CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) & 0xFFF7FFFF) | 0x80000; CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) |= BIT(19);
//MC(MC_IRAM_REG_CTRL) &= 0xFFFFFFFE; //MC(MC_IRAM_REG_CTRL) &= ~BIT(0);
MC(MC_IRAM_BOM) = 0x40000000; MC(MC_IRAM_BOM) = IRAM_BASE;
MC(MC_IRAM_TOM) = full_aperture ? DRAM_START : 0x4003F000; MC(MC_IRAM_TOM) = DRAM_START; // Default is only IRAM: 0x4003F000.
} }
void mc_disable_ahb_redirect() void mc_disable_ahb_redirect()
@@ -139,15 +137,27 @@ void mc_disable_ahb_redirect()
MC(MC_IRAM_BOM) = 0xFFFFF000; MC(MC_IRAM_BOM) = 0xFFFFF000;
MC(MC_IRAM_TOM) = 0; MC(MC_IRAM_TOM) = 0;
// Disable IRAM_CFG_WRITE_ACCESS (sticky). // Disable IRAM_CFG_WRITE_ACCESS (sticky).
//MC(MC_IRAM_REG_CTRL) = MC(MC_IRAM_REG_CTRL) & 0xFFFFFFFE | 1; //MC(MC_IRAM_REG_CTRL) |= BIT(0);
// Disable ARC_CLK_OVR_ON. // Disable ARC_CLK_OVR_ON.
CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) &= 0xFFF7FFFF; CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) &= ~BIT(19);
}
bool mc_client_has_access(void *address)
{
// Check if address is in DRAM or if arbitration for IRAM is enabled.
if ((u32)address >= DRAM_START)
return true; // Access by default.
else if ((u32)address >= IRAM_BASE && MC(MC_IRAM_BOM) == IRAM_BASE)
return true; // Access by AHB arbitration.
// No access to address space.
return false;
} }
void mc_enable() void mc_enable()
{ {
// Reset EMC source to PLLP. // Reset EMC source to PLLP.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) & 0x1FFFFFFF) | 0x40000000; CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) & 0x1FFFFFFF) | (2 << 29);
// Enable memory clocks. // Enable memory clocks.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_EMC); CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_EMC);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_MEM); CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_MEM);
@@ -156,7 +166,7 @@ void mc_enable()
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_EMC) | BIT(CLK_H_MEM); CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_EMC) | BIT(CLK_H_MEM);
usleep(5); usleep(5);
#ifdef CONFIG_ENABLE_AHB_REDIRECT #ifdef BDK_MC_ENABLE_AHB_REDIRECT
mc_enable_ahb_redirect(); mc_enable_ahb_redirect();
#else #else
mc_disable_ahb_redirect(); mc_disable_ahb_redirect();

View File

@@ -23,8 +23,9 @@
void mc_config_tsec_carveout(u32 bom, u32 size1mb, bool lock); void mc_config_tsec_carveout(u32 bom, u32 size1mb, bool lock);
void mc_config_carveout(); void mc_config_carveout();
void mc_config_carveout_finalize(); void mc_config_carveout_finalize();
void mc_enable_ahb_redirect(bool full_aperture); void mc_enable_ahb_redirect();
void mc_disable_ahb_redirect(); void mc_disable_ahb_redirect();
bool mc_client_has_access(void *address);
void mc_enable(); void mc_enable();
#endif #endif

View File

@@ -464,11 +464,111 @@
#define MC_UNTRANSLATED_REGION_CHECK 0x948 #define MC_UNTRANSLATED_REGION_CHECK 0x948
#define MC_DA_CONFIG0 0x9dc #define MC_DA_CONFIG0 0x9dc
/* 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)
#define SEC_CARVEOUT_CA0_R_DISPLAY0B BIT(3)
#define SEC_CARVEOUT_CA0_R_DISPLAY0BB BIT(4)
#define SEC_CARVEOUT_CA0_R_DISPLAY0C BIT(5)
#define SEC_CARVEOUT_CA0_R_DISPLAY0CB BIT(6)
#define SEC_CARVEOUT_CA0_R_AFI BIT(14)
#define SEC_CARVEOUT_CA0_R_BPMP_C BIT(15)
#define SEC_CARVEOUT_CA0_R_DISPLAYHC BIT(16)
#define SEC_CARVEOUT_CA0_R_DISPLAYHCB BIT(17)
#define SEC_CARVEOUT_CA0_R_HDA BIT(21)
#define SEC_CARVEOUT_CA0_R_HOST1XDMA BIT(22)
#define SEC_CARVEOUT_CA0_R_HOST1X BIT(23)
#define SEC_CARVEOUT_CA0_R_NVENC BIT(28)
#define SEC_CARVEOUT_CA0_R_PPCSAHBDMA BIT(29)
#define SEC_CARVEOUT_CA0_R_PPCSAHBSLV BIT(30)
#define SEC_CARVEOUT_CA0_R_SATAR BIT(31)
/* 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)
#define SEC_CARVEOUT_CA1_R_VDETPE BIT(5)
#define SEC_CARVEOUT_CA1_R_CCPLEXLP_C BIT(6)
#define SEC_CARVEOUT_CA1_R_CCPLEX_C BIT(7)
#define SEC_CARVEOUT_CA1_W_NVENC BIT(11)
#define SEC_CARVEOUT_CA1_W_AFI BIT(17)
#define SEC_CARVEOUT_CA1_W_BPMP_C BIT(18)
#define SEC_CARVEOUT_CA1_W_HDA BIT(21)
#define SEC_CARVEOUT_CA1_W_HOST1X BIT(22)
#define SEC_CARVEOUT_CA1_W_CCPLEXLP_C BIT(24)
#define SEC_CARVEOUT_CA1_W_CCPLEX_C BIT(25)
#define SEC_CARVEOUT_CA1_W_PPCSAHBDMA BIT(27)
#define SEC_CARVEOUT_CA1_W_PPCSAHBSLV BIT(28)
#define SEC_CARVEOUT_CA1_W_SATA BIT(29)
#define SEC_CARVEOUT_CA1_W_VDEBSEV BIT(30)
#define SEC_CARVEOUT_CA1_W_VDEDBG BIT(31)
/* 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)
#define SEC_CARVEOUT_CA2_W_ISPWA BIT(6)
#define SEC_CARVEOUT_CA2_W_ISPWB BIT(7)
#define SEC_CARVEOUT_CA2_R_XUSB_HOST BIT(10)
#define SEC_CARVEOUT_CA2_W_XUSB_HOST BIT(11)
#define SEC_CARVEOUT_CA2_R_XUSB_DEV BIT(12)
#define SEC_CARVEOUT_CA2_W_XUSB_DEV BIT(13)
#define SEC_CARVEOUT_CA2_R_SE2 BIT(14)
#define SEC_CARVEOUT_CA2_W_SE2 BIT(16)
#define SEC_CARVEOUT_CA2_R_TSEC BIT(20)
#define SEC_CARVEOUT_CA2_W_TSEC BIT(21)
#define SEC_CARVEOUT_CA2_R_ADSP_SC BIT(22)
#define SEC_CARVEOUT_CA2_W_ADSP_SC BIT(23)
#define SEC_CARVEOUT_CA2_R_GPU BIT(24)
#define SEC_CARVEOUT_CA2_W_GPU BIT(25)
#define SEC_CARVEOUT_CA2_R_DISPLAYT BIT(26)
/* 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)
#define SEC_CARVEOUT_CA3_R_SDMMCAB BIT(3)
#define SEC_CARVEOUT_CA3_W_SDMMCA BIT(4)
#define SEC_CARVEOUT_CA3_W_SDMMCAA BIT(5)
#define SEC_CARVEOUT_CA3_W_SDMMC BIT(6)
#define SEC_CARVEOUT_CA3_W_SDMMCAB BIT(7)
#define SEC_CARVEOUT_CA3_R_VIC BIT(12)
#define SEC_CARVEOUT_CA3_W_VIC BIT(13)
#define SEC_CARVEOUT_CA3_W_VIW BIT(18)
#define SEC_CARVEOUT_CA3_R_DISPLAYD BIT(19)
#define SEC_CARVEOUT_CA3_R_NVDEC BIT(24)
#define SEC_CARVEOUT_CA3_W_NVDEC BIT(25)
#define SEC_CARVEOUT_CA3_R_APE BIT(26)
#define SEC_CARVEOUT_CA3_W_APE BIT(27)
#define SEC_CARVEOUT_CA3_R_NVJPG BIT(30)
#define SEC_CARVEOUT_CA3_W_NVJPG BIT(31)
/* 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)
#define SEC_CARVEOUT_CA4_W_AXIAP BIT(3)
#define SEC_CARVEOUT_CA4_R_ETR BIT(4)
#define SEC_CARVEOUT_CA4_W_ETR BIT(5)
#define SEC_CARVEOUT_CA4_R_TSECB BIT(6)
#define SEC_CARVEOUT_CA4_W_TSECB BIT(7)
#define SEC_CARVEOUT_CA4_R_GPU2 BIT(8)
#define SEC_CARVEOUT_CA4_W_GPU2 BIT(9)
// MC_VIDEO_PROTECT_REG_CTRL
#define VPR_LOCK_MODE_SHIFT 0
#define VPR_CTRL_UNLOCKED (0 << VPR_LOCK_MODE_SHIFT)
#define VPR_CTRL_LOCKED (1 << VPR_LOCK_MODE_SHIFT)
#define VPR_PROTECT_MODE_SHIFT 1
#define SEC_CTRL_SECURE (0 << VPR_PROTECT_MODE_SHIFT)
#define VPR_CTRL_TZ_SECURE (1 << VPR_PROTECT_MODE_SHIFT)
// MC_SECURITY_CARVEOUTX_CFG0 // MC_SECURITY_CARVEOUTX_CFG0
// Mode of LOCK_MODE. // Mode of LOCK_MODE.
#define PROTECT_MODE_SHIFT 0 #define PROTECT_MODE_SHIFT 0
#define SEC_CARVEOUT_CFG_SECURE (0 << PROTECT_MODE_SHIFT0) #define SEC_CARVEOUT_CFG_ALL_SECURE (0 << PROTECT_MODE_SHIFT)
#define SEC_CARVEOUT_CFG_TZ_SECURE (1 << PROTECT_MODE_SHIFT0) #define SEC_CARVEOUT_CFG_TZ_SECURE (1 << PROTECT_MODE_SHIFT)
// Enables PROTECT_MODE. // Enables PROTECT_MODE.
#define LOCK_MODE_SHIFT 1 #define LOCK_MODE_SHIFT 1
#define SEC_CARVEOUT_CFG_UNLOCKED (0 << LOCK_MODE_SHIFT) #define SEC_CARVEOUT_CFG_UNLOCKED (0 << LOCK_MODE_SHIFT)
@@ -479,30 +579,31 @@
#define SEC_CARVEOUT_CFG_UNTRANSLATED_ONLY (1 << ADDRESS_TYPE_SHIFT) #define SEC_CARVEOUT_CFG_UNTRANSLATED_ONLY (1 << ADDRESS_TYPE_SHIFT)
#define READ_ACCESS_LEVEL_SHIFT 3 #define READ_ACCESS_LEVEL_SHIFT 3
#define SEC_CARVEOUT_CFG_RD_ALL (1 << READ_ACCESS_LEVEL_SHIFT) #define SEC_CARVEOUT_CFG_RD_NS (1 << READ_ACCESS_LEVEL_SHIFT)
#define SEC_CARVEOUT_CFG_RD_UNK (2 << READ_ACCESS_LEVEL_SHIFT) #define SEC_CARVEOUT_CFG_RD_SEC (2 << READ_ACCESS_LEVEL_SHIFT)
#define SEC_CARVEOUT_CFG_RD_FALCON_LS (4 << READ_ACCESS_LEVEL_SHIFT) #define SEC_CARVEOUT_CFG_RD_FALCON_LS (4 << READ_ACCESS_LEVEL_SHIFT)
#define SEC_CARVEOUT_CFG_RD_FALCON_HS (8 << READ_ACCESS_LEVEL_SHIFT) #define SEC_CARVEOUT_CFG_RD_FALCON_HS (8 << READ_ACCESS_LEVEL_SHIFT)
#define WRITE_ACCESS_LEVEL_SHIFT 7 #define WRITE_ACCESS_LEVEL_SHIFT 7
#define SEC_CARVEOUT_CFG_WR_ALL (1 << WRITE_ACCESS_LEVEL_SHIFT) #define SEC_CARVEOUT_CFG_WR_NS (1 << WRITE_ACCESS_LEVEL_SHIFT)
#define SEC_CARVEOUT_CFG_WR_UNK (2 << WRITE_ACCESS_LEVEL_SHIFT) #define SEC_CARVEOUT_CFG_WR_SEC (2 << WRITE_ACCESS_LEVEL_SHIFT)
#define SEC_CARVEOUT_CFG_WR_FALCON_LS (4 << WRITE_ACCESS_LEVEL_SHIFT) #define SEC_CARVEOUT_CFG_WR_FALCON_LS (4 << WRITE_ACCESS_LEVEL_SHIFT)
#define SEC_CARVEOUT_CFG_WR_FALCON_HS (8 << WRITE_ACCESS_LEVEL_SHIFT) #define SEC_CARVEOUT_CFG_WR_FALCON_HS (8 << WRITE_ACCESS_LEVEL_SHIFT)
#define SEC_CARVEOUT_CFG_APERTURE_ID_MASK (3 << 11) #define SEC_CARVEOUT_CFG_APERTURE_ID_MASK (3 << 11)
#define SEC_CARVEOUT_CFG_APERTURE_ID(id) ((id) << 11)
#define DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT 14 #define DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT 14
#define SEC_CARVEOUT_CFG_DIS_RD_CHECK_L0 (1 << DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT) #define SEC_CARVEOUT_CFG_DIS_RD_CHECK_NS (1 << DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT)
#define SEC_CARVEOUT_CFG_DIS_RD_CHECK_L1 (2 << DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT) #define SEC_CARVEOUT_CFG_DIS_RD_CHECK_SEC (2 << DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT)
#define SEC_CARVEOUT_CFG_DIS_RD_CHECK_L2 (4 << DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT) #define SEC_CARVEOUT_CFG_DIS_RD_CHECK_FLCN_LS (4 << DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT)
#define SEC_CARVEOUT_CFG_DIS_RD_CHECK_L3 (8 << DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT) #define SEC_CARVEOUT_CFG_DIS_RD_CHECK_FLCN_HS (8 << DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT)
#define DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT 18 #define DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT 18
#define SEC_CARVEOUT_CFG_DIS_WR_CHECK_L0 (1 << DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT) #define SEC_CARVEOUT_CFG_DIS_WR_CHECK_NS (1 << DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT)
#define SEC_CARVEOUT_CFG_DIS_WR_CHECK_L1 (2 << DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT) #define SEC_CARVEOUT_CFG_DIS_WR_CHECK_SEC (2 << DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT)
#define SEC_CARVEOUT_CFG_DIS_WR_CHECK_L2 (4 << DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT) #define SEC_CARVEOUT_CFG_DIS_WR_CHECK_FLCN_LS (4 << DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT)
#define SEC_CARVEOUT_CFG_DIS_WR_CHECK_L3 (8 << DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT) #define SEC_CARVEOUT_CFG_DIS_WR_CHECK_FLCN_HS (8 << DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT)
#define SEC_CARVEOUT_CFG_SEND_CFG_TO_GPU BIT(22) #define SEC_CARVEOUT_CFG_SEND_CFG_TO_GPU BIT(22)

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019 CTCaer * Copyright (c) 2019-2022 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -19,21 +19,26 @@
#include "minerva.h" #include "minerva.h"
#include <soc/clock.h>
#include <ianos/ianos.h> #include <ianos/ianos.h>
#include <mem/emc.h>
#include <soc/clock.h> #include <soc/clock.h>
#include <soc/fuse.h> #include <soc/fuse.h>
#include <soc/hw_init.h> #include <soc/hw_init.h>
#include <soc/t210.h> #include <soc/t210.h>
#include <utils/util.h> #include <utils/util.h>
#define LA_REGS_OFFSET_T210 0x1284
#define LA_REGS_OFFSET_T210B01 0xFA4
#define LA_SDMMC1_INDEX 6
#define LA_SDMMC4_INDEX 9
extern volatile nyx_storage_t *nyx_str; extern volatile nyx_storage_t *nyx_str;
void (*minerva_cfg)(mtc_config_t *mtc_cfg, void *); void (*minerva_cfg)(mtc_config_t *mtc_cfg, void *);
u32 minerva_init() u32 minerva_init()
{ {
u32 curr_ram_idx = 0; u32 tbl_idx = 0;
minerva_cfg = NULL; minerva_cfg = NULL;
mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg; mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
@@ -42,7 +47,7 @@ u32 minerva_init()
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01) if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01)
return 0; return 0;
#ifdef NYX #ifdef BDK_MINERVA_CFG_FROM_RAM
// Set table to nyx storage. // Set table to nyx storage.
mtc_cfg->mtc_table = (emc_table_t *)nyx_str->mtc_table; mtc_cfg->mtc_table = (emc_table_t *)nyx_str->mtc_table;
@@ -97,13 +102,14 @@ u32 minerva_init()
return 1; return 1;
// Get current frequency // Get current frequency
for (curr_ram_idx = 0; curr_ram_idx < 10; curr_ram_idx++) u32 current_emc_clk_src = CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC);
for (tbl_idx = 0; tbl_idx < mtc_cfg->table_entries; tbl_idx++)
{ {
if (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) == mtc_cfg->mtc_table[curr_ram_idx].clk_src_emc) if (current_emc_clk_src == mtc_cfg->mtc_table[tbl_idx].clk_src_emc)
break; break;
} }
mtc_cfg->rate_from = mtc_cfg->mtc_table[curr_ram_idx].rate_khz; mtc_cfg->rate_from = mtc_cfg->mtc_table[tbl_idx].rate_khz;
mtc_cfg->rate_to = FREQ_204; mtc_cfg->rate_to = FREQ_204;
mtc_cfg->train_mode = OP_TRAIN; mtc_cfg->train_mode = OP_TRAIN;
minerva_cfg(mtc_cfg, NULL); minerva_cfg(mtc_cfg, NULL);
@@ -139,6 +145,15 @@ void minerva_change_freq(minerva_freq_t freq)
} }
} }
void minerva_sdmmc_la_program(void *table, bool t210b01)
{
u32 *la_scale_regs = (u32 *)(table + (t210b01 ? LA_REGS_OFFSET_T210B01 : LA_REGS_OFFSET_T210));
// Promote SDMMC1 latency allowance to SDMMC4 (SD to eMMC).
la_scale_regs[LA_SDMMC1_INDEX] = la_scale_regs[LA_SDMMC4_INDEX];
}
void minerva_prep_boot_freq() void minerva_prep_boot_freq()
{ {
if (!minerva_cfg) if (!minerva_cfg)
@@ -156,6 +171,67 @@ void minerva_prep_boot_freq()
minerva_change_freq(FREQ_800); minerva_change_freq(FREQ_800);
} }
void minerva_prep_boot_l4t(int oc_freq)
{
if (!minerva_cfg)
return;
mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
// Program SDMMC LA regs.
for (u32 i = 0; i < mtc_cfg->table_entries; i++)
minerva_sdmmc_la_program(&mtc_cfg->mtc_table[i], false);
// Add OC frequency.
if (oc_freq && mtc_cfg->mtc_table[mtc_cfg->table_entries - 1].rate_khz == FREQ_1600)
{
memcpy(&mtc_cfg->mtc_table[mtc_cfg->table_entries],
&mtc_cfg->mtc_table[mtc_cfg->table_entries - 1],
sizeof(emc_table_t));
mtc_cfg->mtc_table[mtc_cfg->table_entries].rate_khz = oc_freq;
mtc_cfg->table_entries++;
}
// Set init frequency.
minerva_change_freq(FREQ_204);
// Train the rest of the frequencies.
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)
continue;
// Train frequency.
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_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;
}
void minerva_periodic_training() void minerva_periodic_training()
{ {
if (!minerva_cfg) if (!minerva_cfg)
@@ -167,4 +243,22 @@ void minerva_periodic_training()
mtc_cfg->train_mode = OP_PERIODIC_TRAIN; mtc_cfg->train_mode = OP_PERIODIC_TRAIN;
minerva_cfg(mtc_cfg, NULL); minerva_cfg(mtc_cfg, NULL);
} }
} }
emc_table_t *minerva_get_mtc_table()
{
if (!minerva_cfg)
return NULL;
mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
return mtc_cfg->mtc_table;
}
int minerva_get_mtc_table_entries()
{
if (!minerva_cfg)
return 0;
mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
return mtc_cfg->table_entries;
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019 CTCaer * Copyright (c) 2019-2022 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -53,6 +53,7 @@ enum train_mode_t
typedef enum typedef enum
{ {
FREQ_204 = 204000, FREQ_204 = 204000,
FREQ_666 = 665600,
FREQ_800 = 800000, FREQ_800 = 800000,
FREQ_1600 = 1600000 FREQ_1600 = 1600000
} minerva_freq_t; } minerva_freq_t;
@@ -60,7 +61,11 @@ typedef enum
extern void (*minerva_cfg)(mtc_config_t *mtc_cfg, void *); extern void (*minerva_cfg)(mtc_config_t *mtc_cfg, void *);
u32 minerva_init(); u32 minerva_init();
void minerva_change_freq(minerva_freq_t freq); void minerva_change_freq(minerva_freq_t freq);
void minerva_sdmmc_la_program(void *table, bool t210b01);
void minerva_prep_boot_freq(); void minerva_prep_boot_freq();
void minerva_prep_boot_l4t(int oc_freq);
void minerva_periodic_training(); void minerva_periodic_training();
emc_table_t *minerva_get_mtc_table();
int minerva_get_mtc_table_entries();
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2020-2021 CTCaer * Copyright (c) 2020-2023 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -23,26 +23,20 @@
/* /*
* Tegra X1/X1+ EMC/DRAM Bandwidth Chart: * Tegra X1/X1+ EMC/DRAM Bandwidth Chart:
* *
* Note: BWbits T210 = Hz x ddr x bus width x channels = Hz x 2 x 32 x 2. * Note: Max BWbits = Hz x ddr x bus width x channels = Hz x 2 x 32 x 2.
* BWbits T210B01 = Hz x ddr x bus width x channels = Hz x 2 x 64 x 2. * Max BWbits = Hz x ddr x bus width x channels = Hz x 2 x 64 x 1.
* Both assume that both sub-partitions are used and thus reaching max * Configurations supported: 1x32, 2x32, 1x64.
* bandwidth per channel. (T210: 2x16-bit, T210B01: 2x32-bit). * x64 ram modules can be used by combining the 2 32-bit channels into one.
* Retail Mariko use one sub-partition, in order to meet Erista perf.
*
* T210 T210B01
* 40.8 MHz: 0.61 1.22 GiB/s
* 68.0 MHz: 1.01 2.02 GiB/s
* 102.0 MHz: 1.52 3.04 GiB/s
* 204.0 MHz: 3.04 6.08 GiB/s <-- Tegra X1/X1+ Init/SC7 Frequency
* 408.0 MHz: 6.08 12.16 GiB/s
* 665.6 MHz: 9.92 19.84 GiB/s
* 800.0 MHz: 11.92 23.84 GiB/s <-- Tegra X1/X1+ Nvidia OS Boot Frequency
* 1065.6 MHz: 15.89 31.78 GiB/s
* 1331.2 MHz: 19.84 39.68 GiB/s
* 1600.0 MHz: 23.84 47.68 GiB/s <-- Tegra X1/X1+ HOS Max Frequency
* 1862.4 MHz: 27.75 55.50 GiB/s <-- Tegra X1 Official Max Frequency
* 2131.2 MHz: 31.76 63.52 GiB/s <-- Tegra X1+ Official Max Frequency
* *
* 204.0 MHz: 3.04 <-- Tegra X1/X1+ Init/SC7 Frequency
* 408.0 MHz: 6.08
* 665.6 MHz: 9.92
* 800.0 MHz: 11.92 <-- Tegra X1/X1+ Nvidia OS Boot Frequency
* 1065.6 MHz: 15.89
* 1331.2 MHz: 19.84
* 1600.0 MHz: 23.84
* 1862.4 MHz: 27.75 <-- Tegra X1 Official Max Frequency
* 2131.2 MHz: 31.76 <-- Tegra X1+ Official Max Frequency. Not all regs have support for > 2046 MHz.
*/ */
enum sdram_ids_erista enum sdram_ids_erista
@@ -51,73 +45,75 @@ enum sdram_ids_erista
LPDDR4_ICOSA_4GB_SAMSUNG_K4F6E304HB_MGCH = 0, LPDDR4_ICOSA_4GB_SAMSUNG_K4F6E304HB_MGCH = 0,
LPDDR4_ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 1, LPDDR4_ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 1,
LPDDR4_ICOSA_4GB_MICRON_MT53B512M32D2NP_062_WT = 2, // WT:C. LPDDR4_ICOSA_4GB_MICRON_MT53B512M32D2NP_062_WT = 2, // WT:C.
LPDDR4_COPPER_4GB_SAMSUNG_K4F6E304HB_MGCH = 3, // Changed to Iowa Hynix 4GB 1Y-A.
LPDDR4_ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH = 4, LPDDR4_ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH = 4,
LPDDR4_COPPER_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 5, // Changed to Hoag Hynix 4GB 1Y-A.
LPDDR4_COPPER_4GB_MICRON_MT53B512M32D2NP_062_WT = 6, // Changed to Aula Hynix 4GB 1Y-A. LPDDR4_ICOSA_8GB_SAMSUNG_K4FBE3D4HM_MGXX = 7, // Custom 8GB. XX: CH/CJ/CL. 7 since it can be easily applied in fuses.
}; };
enum sdram_ids_mariko enum sdram_ids_mariko
{ {
// LPDDR4X 4266Mbps. // LPDDR4X 4266Mbps.
LPDDR4X_IOWA_4GB_HYNIX_1Y_A = 3, // Replaced from Copper. LPDDR4X_HOAG_4GB_HYNIX_H9HCNNNBKMMLXR_NEE = 3, // Replaced from Copper. Die-M. (1y-01).
LPDDR4X_HOAG_4GB_HYNIX_1Y_A = 5, // Replaced from Copper. LPDDR4X_AULA_4GB_HYNIX_H9HCNNNBKMMLXR_NEE = 5, // Replaced from Copper. Die-M. (1y-01).
LPDDR4X_AULA_4GB_HYNIX_1Y_A = 6, // Replaced from Copper. LPDDR4X_IOWA_4GB_HYNIX_H9HCNNNBKMMLXR_NEE = 6, // Replaced from Copper. Die-M. (1y-01).
// LPDDR4X 3733Mbps. // LPDDR4X 3733Mbps.
LPDDR4X_IOWA_4GB_SAMSUNG_X1X2 = 7, LPDDR4X_IOWA_4GB_SAMSUNG_K4U6E3S4AM_MGCJ = 8, // Die-M. 1st gen. 8 banks. 3733Mbps.
LPDDR4X_IOWA_4GB_SAMSUNG_K4U6E3S4AM_MGCJ = 8, // Die-M.
LPDDR4X_IOWA_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 9, // Die-M. LPDDR4X_IOWA_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 9, // Die-M.
LPDDR4X_IOWA_4GB_HYNIX_H9HCNNNBKMMLHR_NME = 10, // Die-M. LPDDR4X_IOWA_4GB_HYNIX_H9HCNNNBKMMLHR_NME = 10, // Die-M.
LPDDR4X_IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTE = 11, // 4266Mbps. Die-E. LPDDR4X_IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTE = 11, // 4266Mbps. Die-E. D9WGB.
LPDDR4X_HOAG_4GB_SAMSUNG_K4U6E3S4AM_MGCJ = 12, // Die-M. LPDDR4X_HOAG_4GB_SAMSUNG_K4U6E3S4AM_MGCJ = 12, // Die-M. 1st gen. 8 banks. 3733Mbps.
LPDDR4X_HOAG_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 13, // Die-M. LPDDR4X_HOAG_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 13, // Die-M.
LPDDR4X_HOAG_4GB_HYNIX_H9HCNNNBKMMLHR_NME = 14, // Die-M. LPDDR4X_HOAG_4GB_HYNIX_H9HCNNNBKMMLHR_NME = 14, // Die-M.
LPDDR4X_HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTE = 15, // 4266Mbps. Die-E. LPDDR4X_HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTE = 15, // 4266Mbps. Die-E. D9WGB.
// LPDDR4X 4266Mbps. // LPDDR4X 4266Mbps.
LPDDR4X_IOWA_4GB_SAMSUNG_Y = 16, LPDDR4X_IOWA_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 17, // Die-A. (1y-X03). 2nd gen. 8 banks. 4266Mbps.
LPDDR4X_IOWA_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 18, // Die-A. (1y-X03).
LPDDR4X_HOAG_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 19, // Die-A. (1y-X03). 2nd gen. 8 banks. 4266Mbps.
LPDDR4X_IOWA_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 17, // Die-A. LPDDR4X_IOWA_4GB_SAMSUNG_K4U6E3S4AB_MGCL = 20, // Die-B. 1z nm. 40% lower power usage. (1z-01).
LPDDR4X_IOWA_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 18, // Die-A. LPDDR4X_HOAG_4GB_SAMSUNG_K4U6E3S4AB_MGCL = 21, // Die-B. 1z nm. 40% lower power usage. (1z-01).
LPDDR4X_HOAG_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 19, // Die-A. LPDDR4X_AULA_4GB_SAMSUNG_K4U6E3S4AB_MGCL = 22, // Die-B. 1z nm. 40% lower power usage. (1z-01).
LPDDR4X_IOWA_4GB_SAMSUNG_1Y_Y = 20, LPDDR4X_HOAG_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 23, // Die-A. (1y-X03).
LPDDR4X_IOWA_8GB_SAMSUNG_1Y_Y = 21, LPDDR4X_AULA_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 24, // Die-A. (1y-X03). 2nd gen. 8 banks. 4266Mbps.
// LPDDR4X_AULA_8GB_SAMSUNG_1Y_A = 22, // Unused. LPDDR4X_IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTF = 25, // 4266Mbps. Die-F. D9XRR. 10nm-class (1y-01).
LPDDR4X_HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTF = 26, // 4266Mbps. Die-F. D9XRR. 10nm-class (1y-01).
LPDDR4X_HOAG_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 23, // Die-A. LPDDR4X_AULA_4GB_MICRON_MT53E512M32D2NP_046_WTF = 27, // 4266Mbps. Die-F. D9XRR. 10nm-class (1y-01).
LPDDR4X_AULA_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 24, // Die-A.
LPDDR4X_IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTF = 25, // 4266Mbps. Die-F.
LPDDR4X_HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTF = 26, // 4266Mbps. Die-F.
LPDDR4X_AULA_4GB_MICRON_MT53E512M32D2NP_046_WTF = 27, // 4266Mbps. Die-F.
LPDDR4X_AULA_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 28, // Die-A. LPDDR4X_AULA_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 28, // Die-A.
LPDDR4X_UNK0_4GB_HYNIX_H9HCNNNBKMMLXR_NEI = 29, // Die-M. 1a nm. 61% lower power usage. (1a-01).
LPDDR4X_UNK1_4GB_HYNIX_H9HCNNNBKMMLXR_NEI = 30, // Die-M. 1a nm. 61% lower power usage. (1a-01).
LPDDR4X_UNK2_4GB_HYNIX_H9HCNNNBKMMLXR_NEI = 31, // Die-M. 1a nm. 61% lower power usage. (1a-01).
LPDDR4X_UNK0_4GB_MICRON_1A = 32, // 1a nm. 61% lower power usage. (1a-01).
LPDDR4X_UNK1_4GB_MICRON_1A = 33, // 1a nm. 61% lower power usage. (1a-01).
LPDDR4X_UNK2_4GB_MICRON_1A = 34, // 1a nm. 61% lower power usage. (1a-01).
}; };
enum sdram_codes_mariko enum sdram_codes_mariko
{ {
LPDDR4X_NO_PATCH = 0, LPDDR4X_NO_PATCH = 0,
LPDDR4X_UNUSED = 0, LPDDR4X_UNUSED = 0,
// LPDDR4X_4GB_SAMSUNG_K4U6E3S4AM_MGCJ DRAM IDs: 08, 12. // LPDDR4X_4GB_SAMSUNG_K4U6E3S4AM_MGCJ DRAM IDs: 08, 12.
// LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLHR_NME DRAM IDs: 10, 14. // LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLHR_NME DRAM IDs: 10, 14.
LPDDR4X_4GB_SAMSUNG_X1X2 = 1, // DRAM IDs: 07. LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 1, // DRAM IDs: 09, 13.
LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 2, // DRAM IDs: 09, 13. LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE = 2, // DRAM IDs: 11, 15.
LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE = 3, // DRAM IDs: 11, 15. LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 3, // DRAM IDs: 17, 19, 24.
LPDDR4X_4GB_SAMSUNG_Y = 4, // DRAM IDs: 16. LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 4, // DRAM IDs: 18, 23, 28.
LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 5, // DRAM IDs: 17, 19, 24. LPDDR4X_4GB_SAMSUNG_K4U6E3S4AB_MGCL = 5, // DRAM IDs: 20, 21, 22.
LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 6, // DRAM IDs: 18, 23, 28. LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF = 6, // DRAM IDs: 25, 26, 27.
LPDDR4X_4GB_SAMSUNG_1Y_Y = 7, // DRAM IDs: 20. LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEE = 7, // DRAM IDs: 03, 05, 06.
LPDDR4X_8GB_SAMSUNG_1Y_Y = 8, // DRAM IDs: 21.
//LPDDR4X_8GB_SAMSUNG_1Y_A = 9, // DRAM IDs: 22. Unused. LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEI = 8, // DRAM IDs: 29, 30, 31.
LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF = 10, // DRAM IDs: 25, 26, 27. LPDDR4X_4GB_MICRON_1A = 9, // DRAM IDs: 32, 33, 34.
LPDDR4X_4GB_HYNIX_1Y_A = 11, // DRAM IDs: 03, 05, 06.
}; };
void sdram_init(); void sdram_init();

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2020-2021 CTCaer * Copyright (c) 2020-2022 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -17,8 +17,6 @@
#define DRAM_CFG_T210_SIZE 1896 #define DRAM_CFG_T210_SIZE 1896
#define DRAM_ID(x) BIT(x)
static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = { static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = {
/* Specifies the type of memory device */ /* Specifies the type of memory device */
.memory_type = MEMORY_TYPE_LPDDR4, .memory_type = MEMORY_TYPE_LPDDR4,
@@ -543,8 +541,12 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = {
.mc_video_protect_bom = 0xFFF00000, .mc_video_protect_bom = 0xFFF00000,
.mc_video_protect_bom_adr_hi = 0x00000000, .mc_video_protect_bom_adr_hi = 0x00000000,
.mc_video_protect_size_mb = 0x00000000, .mc_video_protect_size_mb = 0x00000000,
// AFI, BPMP, HC, ISP2, CCPLEX, PPCS (AHB), SATA, VI, XUSB_HOST, XUSB_DEV, ADSP, PPCS1 (AHB), DC1, SDMMC1A, SDMMC2A, SDMMC3A.
.mc_video_protect_vpr_override = 0xE4BAC343, .mc_video_protect_vpr_override = 0xE4BAC343,
// SDMMC4A, ISP2B, PPCS2 (AHB), APE, SE, HC1, SE1, AXIAP, ETR.
.mc_video_protect_vpr_override1 = 0x00001ED3, .mc_video_protect_vpr_override1 = 0x00001ED3,
.mc_video_protect_gpu_override0 = 0x00000000, .mc_video_protect_gpu_override0 = 0x00000000,
.mc_video_protect_gpu_override1 = 0x00000000, .mc_video_protect_gpu_override1 = 0x00000000,
.mc_sec_carveout_bom = 0xFFF00000, .mc_sec_carveout_bom = 0xFFF00000,
@@ -657,40 +659,13 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210[] = {
{ 0x000C0302, 0x570 / 4, DRAM_ID(4) }, // mc_emem_adr_cfg_dev1. 768MB Rank 1 density. { 0x000C0302, 0x570 / 4, DRAM_ID(4) }, // mc_emem_adr_cfg_dev1. 768MB Rank 1 density.
{ 0x00001800, 0x584 / 4, DRAM_ID(4) }, // mc_emem_cfg. 6GB total density. { 0x00001800, 0x584 / 4, DRAM_ID(4) }, // mc_emem_cfg. 6GB total density.
#ifdef CONFIG_SDRAM_COPPER_SUPPORT // Samsung 8GB density config.
// Copper prototype Samsung/Hynix/Micron timing configs. { 0x0000003A, 0xEC / 4, DRAM_ID(7) }, // emc_rfc.
{ 0x0000003A, 0xEC / 4, DRAM_ID(6) }, // emc_rfc. Auto refresh. { 0x0000001D, 0xF0 / 4, DRAM_ID(7) }, // emc_rfc_pb.
{ 0x0000001D, 0xF0 / 4, DRAM_ID(6) }, // emc_rfc_pb. Bank Auto refresh. { 0x0000003B, 0x1C0 / 4, DRAM_ID(7) }, // emc_txsr.
{ 0x0000000D, 0x10C / 4, DRAM_ID(5) }, // emc_r2w. { 0x0000003B, 0x1C4 / 4, DRAM_ID(7) }, // emc_txsr_dll.
{ 0x00000001, 0x16C / 4, DRAM_ID(5) }, // emc_puterm_extra. { 0x00000713, 0x2B4 / 4, DRAM_ID(7) }, // emc_dyn_self_ref_control.
{ 0x80000000, 0x170 / 4, DRAM_ID(5) }, // emc_puterm_width. { 0x00080302, 0x56C / 4, DRAM_ID(7) }, // mc_emem_adr_cfg_dev0. 1024MB Rank 0 density.
{ 0x00000012, 0x1B0 / 4, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_rw2pden. { 0x00080302, 0x570 / 4, DRAM_ID(7) }, // mc_emem_adr_cfg_dev1. 1024MB Rank 1 density.
{ 0x0000003B, 0x1C0 / 4, DRAM_ID(6) }, // emc_txsr. { 0x00002000, 0x584 / 4, DRAM_ID(7) }, // mc_emem_cfg. 8GB total density.
{ 0x0000003B, 0x1C4 / 4, DRAM_ID(6) }, // emc_txsr_dll.
{ 0x00000003, 0x1DC / 4, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_tclkstable.
{ 0x00120015, 0x334 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank0_4.
{ 0x00160012, 0x338 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank0_5.
{ 0x00120015, 0x34C / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank1_4.
{ 0x00160012, 0x350 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank1_5.
{ 0x002F0032, 0x354 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_0.
{ 0x00310032, 0x358 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_1.
{ 0x00360034, 0x35C / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_2.
{ 0x0033002F, 0x360 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_3.
{ 0x00000006, 0x364 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_4.
{ 0x002F0032, 0x36C / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_0.
{ 0x00310032, 0x370 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_1.
{ 0x00360034, 0x374 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_2.
{ 0x0033002F, 0x378 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_3.
{ 0x00000006, 0x37C / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_4.
{ 0x00150015, 0x3A4 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_0.
{ 0x00120012, 0x3AC / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_2.
{ 0x00160016, 0x3B0 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_3.
{ 0x00000015, 0x3B4 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_4.
{ 0x00000012, 0x49C / 4, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_cmd_brlshft2.
{ 0x00000012, 0x4A0 / 4, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_cmd_brlshft3.
{ 0x00000210, 0x4F4 / 4, DRAM_ID(5) }, // emc_pmacro_data_rx_term_mode.
{ 0x00000005, 0x5C0 / 4, DRAM_ID(5) }, // mc_emem_arb_timing_r2w.
{ 0x00000007, 0x5C8 / 4, DRAM_ID(6) }, // mc_emem_arb_timing_rfcpb. Bank refresh.
{ 0x72A30504, 0x5D4 / 4, DRAM_ID(6) }, // mc_emem_arb_misc0.
#endif
}; };

View File

@@ -1,124 +0,0 @@
/*
* Copyright (c) 2018 naehrwert
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
static const u8 _dram_cfg_lz[1262] = {
0x17, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00,
0x00, 0x2C, 0x17, 0x04, 0x09, 0x00, 0x17, 0x04, 0x04, 0x17, 0x08, 0x08,
0x17, 0x10, 0x10, 0x00, 0x00, 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00,
0x00, 0x04, 0xB4, 0x01, 0x70, 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00,
0x70, 0x17, 0x10, 0x24, 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40,
0x00, 0x00, 0x00, 0x17, 0x04, 0x04, 0x17, 0x09, 0x18, 0xFF, 0xFF, 0x1F,
0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x77,
0x00, 0x17, 0x04, 0x04, 0x17, 0x08, 0x08, 0x17, 0x08, 0x08, 0xA6, 0xA6,
0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, 0x04, 0x04,
0x04, 0x04, 0x17, 0x04, 0x04, 0x17, 0x04, 0x3C, 0x1F, 0x1F, 0x1F, 0x1F,
0x17, 0x04, 0x04, 0x17, 0x06, 0x06, 0x00, 0x00, 0x04, 0x08, 0x17, 0x06,
0x46, 0xA1, 0x01, 0x00, 0x00, 0x32, 0x17, 0x0B, 0x64, 0x01, 0x17, 0x04,
0x7C, 0x17, 0x07, 0x0C, 0x03, 0x17, 0x04, 0x04, 0x00, 0x00, 0x00, 0x1E,
0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x13,
0x17, 0x0B, 0x2C, 0x09, 0x00, 0x00, 0x00, 0x17, 0x05, 0x5D, 0x17, 0x07,
0x10, 0x0B, 0x17, 0x07, 0x28, 0x08, 0x17, 0x07, 0x0C, 0x17, 0x04, 0x1C,
0x20, 0x00, 0x00, 0x00, 0x06, 0x17, 0x04, 0x04, 0x17, 0x07, 0x08, 0x17,
0x04, 0x50, 0x17, 0x04, 0x2C, 0x17, 0x04, 0x1C, 0x17, 0x04, 0x10, 0x17,
0x08, 0x6C, 0x17, 0x04, 0x10, 0x17, 0x04, 0x38, 0x17, 0x04, 0x40, 0x05,
0x17, 0x07, 0x1C, 0x17, 0x08, 0x58, 0x17, 0x04, 0x24, 0x17, 0x04, 0x18,
0x17, 0x08, 0x64, 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14,
0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x17, 0x09, 0x0C, 0x17, 0x05, 0x82,
0x58, 0x17, 0x07, 0x61, 0xC1, 0x17, 0x07, 0x50, 0x17, 0x04, 0x04, 0x17,
0x08, 0x81, 0x48, 0x17, 0x04, 0x04, 0x17, 0x04, 0x28, 0x17, 0x04, 0x60,
0x17, 0x08, 0x54, 0x27, 0x17, 0x04, 0x04, 0x17, 0x07, 0x14, 0x17, 0x04,
0x04, 0x04, 0x17, 0x07, 0x81, 0x58, 0x17, 0x0C, 0x0C, 0x1C, 0x03, 0x00,
0x00, 0x0D, 0xA0, 0x60, 0x91, 0xBF, 0x3B, 0x17, 0x04, 0x5A, 0xF3, 0x0C,
0x04, 0x05, 0x1B, 0x06, 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05,
0x08, 0x1D, 0x09, 0x0A, 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03,
0x02, 0x1B, 0x1C, 0x23, 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02,
0x0A, 0x0B, 0x1D, 0x0D, 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08,
0x24, 0x06, 0x07, 0x9A, 0x12, 0x17, 0x05, 0x83, 0x41, 0x00, 0xFF, 0x17,
0x10, 0x83, 0x6C, 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00,
0x00, 0x0D, 0x08, 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00,
0x00, 0x0B, 0x08, 0x72, 0x72, 0x0E, 0x0C, 0x17, 0x04, 0x20, 0x08, 0x08,
0x0D, 0x0C, 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x17, 0x06,
0x2C, 0x11, 0x08, 0x17, 0x10, 0x84, 0x67, 0x15, 0x00, 0xCC, 0x00, 0x0A,
0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, 0xFF,
0x0F, 0xFF, 0x0F, 0x17, 0x08, 0x83, 0x4C, 0x01, 0x03, 0x00, 0x70, 0x00,
0x0C, 0x00, 0x01, 0x17, 0x04, 0x0C, 0x08, 0x44, 0x00, 0x10, 0x04, 0x04,
0x00, 0x06, 0x13, 0x07, 0x00, 0x80, 0x17, 0x04, 0x10, 0xA0, 0x00, 0x2C,
0x00, 0x01, 0x37, 0x00, 0x00, 0x00, 0x80, 0x17, 0x06, 0x48, 0x08, 0x00,
0x04, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28,
0x28, 0x28, 0x17, 0x04, 0x04, 0x11, 0x11, 0x11, 0x11, 0x17, 0x04, 0x04,
0xBE, 0x00, 0x00, 0x17, 0x05, 0x58, 0x17, 0x08, 0x5C, 0x17, 0x22, 0x85,
0x6A, 0x17, 0x1A, 0x1A, 0x14, 0x00, 0x12, 0x00, 0x10, 0x17, 0x05, 0x83,
0x0A, 0x17, 0x16, 0x18, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00,
0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x17, 0x05, 0x83, 0x0C, 0x17,
0x04, 0x20, 0x17, 0x18, 0x18, 0x28, 0x00, 0x28, 0x17, 0x04, 0x04, 0x17,
0x08, 0x08, 0x17, 0x10, 0x10, 0x00, 0x14, 0x17, 0x05, 0x5A, 0x17, 0x04,
0x5C, 0x17, 0x04, 0x5E, 0x17, 0x04, 0x0E, 0x17, 0x0E, 0x78, 0x17, 0x09,
0x82, 0x50, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51,
0x17, 0x08, 0x18, 0x80, 0x01, 0x00, 0x00, 0x40, 0x17, 0x04, 0x20, 0x03,
0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, 0x11, 0x17, 0x08, 0x82, 0x58,
0x17, 0x0C, 0x38, 0x17, 0x1B, 0x81, 0x6C, 0x17, 0x08, 0x85, 0x60, 0x17,
0x08, 0x86, 0x50, 0x17, 0x08, 0x86, 0x60, 0x17, 0x06, 0x83, 0x21, 0x22,
0x04, 0xFF, 0xFF, 0xAF, 0x4F, 0x17, 0x0C, 0x86, 0x74, 0x17, 0x08, 0x2C,
0x8B, 0xFF, 0x07, 0x17, 0x06, 0x81, 0x04, 0x32, 0x54, 0x76, 0x10, 0x47,
0x32, 0x65, 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75,
0x64, 0x32, 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45,
0x32, 0x67, 0x17, 0x04, 0x24, 0x49, 0x92, 0x24, 0x17, 0x04, 0x04, 0x17,
0x11, 0x7C, 0x1B, 0x17, 0x04, 0x04, 0x17, 0x13, 0x81, 0x14, 0x2F, 0x41,
0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x17, 0x04, 0x7C, 0xFF, 0xFF, 0xFF,
0x7F, 0x0B, 0xD7, 0x06, 0x40, 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03,
0x00, 0x00, 0x5C, 0x01, 0x00, 0x10, 0x10, 0x10, 0x17, 0x06, 0x86, 0x59,
0x17, 0x0F, 0x89, 0x14, 0x37, 0x17, 0x07, 0x82, 0x72, 0x10, 0x17, 0x06,
0x83, 0x0D, 0x00, 0x11, 0x01, 0x17, 0x05, 0x85, 0x39, 0x17, 0x04, 0x0E,
0x0A, 0x17, 0x07, 0x89, 0x29, 0x17, 0x04, 0x1B, 0x17, 0x08, 0x86, 0x77,
0x17, 0x09, 0x12, 0x20, 0x00, 0x00, 0x00, 0x81, 0x10, 0x09, 0x28, 0x93,
0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, 0x17, 0x18, 0x82, 0x2C, 0xFF,
0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0x17, 0x04, 0x04, 0xDC, 0xDC,
0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x17, 0x04, 0x04, 0x17, 0x04, 0x04,
0x17, 0x05, 0x82, 0x24, 0x03, 0x07, 0x17, 0x04, 0x04, 0x00, 0x00, 0x24,
0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, 0x00, 0x28, 0x72, 0x39, 0x00, 0x10,
0x9C, 0x4B, 0x17, 0x04, 0x64, 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00,
0x80, 0x20, 0x10, 0x0A, 0x00, 0x28, 0x10, 0x17, 0x06, 0x85, 0x60, 0x17,
0x10, 0x82, 0x74, 0x17, 0x08, 0x08, 0x17, 0x08, 0x88, 0x00, 0x17, 0x04,
0x10, 0x04, 0x17, 0x0B, 0x87, 0x6C, 0x01, 0x00, 0x02, 0x02, 0x01, 0x02,
0x03, 0x00, 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x17, 0x08, 0x8B, 0x18,
0x1F, 0x17, 0x09, 0x81, 0x73, 0x00, 0xFF, 0x00, 0xFF, 0x17, 0x05, 0x86,
0x48, 0x17, 0x04, 0x0C, 0x17, 0x07, 0x86, 0x34, 0x00, 0x00, 0xF0, 0x17,
0x09, 0x87, 0x54, 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x17, 0x0C, 0x81,
0x52, 0x17, 0x0A, 0x1C, 0x17, 0x10, 0x81, 0x6C, 0x17, 0x0A, 0x82, 0x21,
0x17, 0x07, 0x82, 0x4D, 0x17, 0x0A, 0x8A, 0x1B, 0x17, 0x11, 0x2C, 0x76,
0x0C, 0x17, 0x0A, 0x8A, 0x67, 0x17, 0x0F, 0x84, 0x28, 0x17, 0x06, 0x34,
0x17, 0x17, 0x3A, 0x7E, 0x16, 0x40, 0x17, 0x0C, 0x8B, 0x1F, 0x17, 0x2A,
0x38, 0x1E, 0x17, 0x0A, 0x38, 0x17, 0x13, 0x81, 0x28, 0x00, 0xC0, 0x17,
0x17, 0x55, 0x46, 0x24, 0x17, 0x0A, 0x81, 0x28, 0x17, 0x14, 0x38, 0x17,
0x18, 0x81, 0x60, 0x46, 0x2C, 0x17, 0x06, 0x38, 0xEC, 0x17, 0x0D, 0x16,
0x17, 0x0E, 0x82, 0x3C, 0x17, 0x82, 0x0C, 0x8E, 0x68, 0x17, 0x04, 0x24,
0x17, 0x5C, 0x8E, 0x68, 0x17, 0x07, 0x82, 0x5F, 0x80, 0x17, 0x87, 0x01,
0x8E, 0x68, 0x02, 0x17, 0x81, 0x4A, 0x8E, 0x68, 0x17, 0x0C, 0x87, 0x78,
0x17, 0x85, 0x28, 0x8E, 0x68, 0x17, 0x8E, 0x68, 0x9D, 0x50, 0x17, 0x81,
0x24, 0x8E, 0x68, 0x17, 0x04, 0x2C, 0x17, 0x28, 0x8E, 0x68, 0x17, 0x04,
0x30, 0x17, 0x85, 0x3C, 0x8E, 0x68, 0x12, 0x17, 0x07, 0x85, 0x70, 0x17,
0x88, 0x74, 0x8E, 0x68, 0x17, 0x87, 0x3E, 0x9D, 0x50, 0x0C, 0x17, 0x04,
0x04, 0x17, 0x12, 0x8E, 0x68, 0x18, 0x17, 0x87, 0x12, 0xBB, 0x20, 0x17,
0x83, 0x04, 0x9D, 0x50, 0x15, 0x17, 0x05, 0x8D, 0x76, 0x17, 0x0F, 0x8B,
0x49, 0x17, 0x0B, 0x18, 0x32, 0x00, 0x2F, 0x00, 0x32, 0x00, 0x31, 0x00,
0x34, 0x00, 0x36, 0x00, 0x2F, 0x00, 0x33, 0x17, 0x09, 0x84, 0x0C, 0x17,
0x18, 0x18, 0x17, 0x20, 0x8E, 0x68, 0x15, 0x17, 0x07, 0x5A, 0x17, 0x06,
0x5E, 0x16, 0x00, 0x15, 0x17, 0x82, 0x40, 0x9D, 0x50, 0x17, 0x86, 0x5F,
0xBB, 0x20, 0x3A, 0x00, 0x00, 0x00, 0x1D, 0x17, 0x81, 0x4F, 0xAC, 0x38,
0x3B, 0x17, 0x04, 0x04, 0x17, 0x86, 0x30, 0x8E, 0x68, 0x17, 0x81, 0x53,
0xAC, 0x38, 0x07, 0x17, 0x0D, 0x8E, 0x68, 0xA3, 0x72, 0x17, 0x83, 0x10,
0x8E, 0x68
};

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 CTCaer * Copyright (c) 2020-2022 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -594,10 +594,15 @@ static const sdram_params_t210b01_t _dram_cfg_08_10_12_14_samsung_hynix_4gb = {
.mc_video_protect_bom = 0xFFF00000, .mc_video_protect_bom = 0xFFF00000,
.mc_video_protect_bom_adr_hi = 0x00000000, .mc_video_protect_bom_adr_hi = 0x00000000,
.mc_video_protect_size_mb = 0x00000000, .mc_video_protect_size_mb = 0x00000000,
// AFI, BPMP, HC, ISP2, CCPLEX, PPCS (AHB), SATA, VI, XUSB_HOST, XUSB_DEV, ADSP, PPCS1 (AHB), DC1, SDMMC1A, SDMMC2A, SDMMC3A.
.mc_video_protect_vpr_override = 0xE4BAC343, .mc_video_protect_vpr_override = 0xE4BAC343,
.mc_video_protect_vpr_override1 = 0x06001ED3, // Add SE2, SE2B. // SDMMC4A, ISP2B, PPCS2 (AHB), APE, SE, HC1, SE1, AXIAP, ETR. Plus SE2, SE2B.
.mc_video_protect_vpr_override1 = 0x06001ED3,
.mc_video_protect_gpu_override0 = 0x00000000, .mc_video_protect_gpu_override0 = 0x00000000,
.mc_video_protect_gpu_override1 = 0x00000000, .mc_video_protect_gpu_override1 = 0x00000000,
.mc_sec_carveout_bom = 0xFFF00000, .mc_sec_carveout_bom = 0xFFF00000,
.mc_sec_carveout_adr_hi = 0x00000000, .mc_sec_carveout_adr_hi = 0x00000000,
.mc_sec_carveout_size_mb = 0x00000000, .mc_sec_carveout_size_mb = 0x00000000,
@@ -701,292 +706,102 @@ static const sdram_params_t210b01_t _dram_cfg_08_10_12_14_samsung_hynix_4gb = {
.bct_na = 0x00000000, .bct_na = 0x00000000,
}; };
//!TODO Find out what mc_video_protect_gpu_override0 and mc_video_protect_gpu_override1 new bits are. #define DRAM_CC_LPDDR4X_PMACRO_IB (DRAM_CC(LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ))
#define DRAM_CC_LPDDR4X_AUTOCAL_VPR (DRAM_CC(LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ) | \
DRAM_CC(LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE) | \
DRAM_CC(LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL) | \
DRAM_CC(LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL) | \
DRAM_CC(LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF) | \
DRAM_CC(LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEE) | \
DRAM_CC(LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEI) | \
DRAM_CC(LPDDR4X_4GB_MICRON_1A) | \
DRAM_CC(LPDDR4X_4GB_SAMSUNG_K4U6E3S4AB_MGCL))
#define DRAM_CC_LPDDR4X_DYN_SELF_CTRL (DRAM_CC(LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE) | \
DRAM_CC(LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL) | \
DRAM_CC(LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF) | \
DRAM_CC(LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEE) | \
DRAM_CC(LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEI) | \
DRAM_CC(LPDDR4X_4GB_MICRON_1A) | \
DRAM_CC(LPDDR4X_4GB_SAMSUNG_K4U6E3S4AB_MGCL))
#define DRAM_CC_LPDDR4X_QUSE_EINPUT (DRAM_CC(LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ) | \
DRAM_CC(LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL) | \
DRAM_CC(LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL) | \
DRAM_CC(LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF) | \
DRAM_CC(LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEE) | \
DRAM_CC(LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEI) | \
DRAM_CC(LPDDR4X_4GB_MICRON_1A) | \
DRAM_CC(LPDDR4X_4GB_SAMSUNG_K4U6E3S4AB_MGCL))
#define DRAM_CC_LPDDR4X_FAW (DRAM_CC(LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL) | \
DRAM_CC(LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF) | \
DRAM_CC(LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEE) | \
DRAM_CC(LPDDR4X_4GB_MICRON_1A))
#define DRAM_CC_LPDDR4X_VPR (DRAM_CC(LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEE) | \
DRAM_CC(LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEI) | \
DRAM_CC(LPDDR4X_4GB_MICRON_1A) | \
DRAM_CC(LPDDR4X_4GB_SAMSUNG_K4U6E3S4AB_MGCL))
#define DRAM_CC_LPDDR4X_8GB (DRAM_CC(LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ) | \
DRAM_CC(LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL))
static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = { static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = {
// Samsung LPDDR4X 4GB X1X2 for prototype Iowa.
{ 0x000E0022, 0x3AC / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dq_rank0_4.
{ 0x001B0010, 0x3B0 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dq_rank0_5.
{ 0x000E0022, 0x3C4 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dq_rank1_4.
{ 0x001B0010, 0x3C8 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dq_rank1_5.
{ 0x00490043, 0x3CC / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank0_0.
{ 0x00420045, 0x3D0 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank0_1.
{ 0x00490047, 0x3D4 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank0_2.
{ 0x00460047, 0x3D8 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank0_3.
{ 0x00000016, 0x3DC / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank0_4.
{ 0x00100000, 0x3E0 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank0_5.
{ 0x00490043, 0x3E4 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank1_0.
{ 0x00420045, 0x3E8 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank1_1.
{ 0x00490047, 0x3EC / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank1_2.
{ 0x00460047, 0x3F0 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank1_3.
{ 0x00000016, 0x3F4 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank1_4.
{ 0x00100000, 0x3F8 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank1_5.
{ 0x00220022, 0x41C / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ddll_long_cmd_0.
{ 0x000E000E, 0x420 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ddll_long_cmd_1.
{ 0x00100010, 0x424 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ddll_long_cmd_2.
{ 0x001B001B, 0x428 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ddll_long_cmd_3.
{ 0x00000022, 0x42C / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ddll_long_cmd_4.
// Samsung LPDDR4X 8GB K4UBE3D4AM-MGCJ Die-M for SDEV Iowa and Hoag. // Samsung LPDDR4X 8GB K4UBE3D4AM-MGCJ Die-M for SDEV Iowa and Hoag.
{ 0x05500000, 0x0D4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_auto_cal_config2. { 0x35353535, 0x350 / 4, DRAM_CC_LPDDR4X_PMACRO_IB }, // emc_pmacro_ib_vref_dq_0.
{ 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_auto_cal_vref_sel0. { 0x35353535, 0x354 / 4, DRAM_CC_LPDDR4X_PMACRO_IB }, // emc_pmacro_ib_vref_dq_1.
{ 0x00000001, 0x134 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_adr_cfg. 2 Ranks. { 0x00100010, 0x3FC / 4, DRAM_CC_LPDDR4X_PMACRO_IB }, // emc_pmacro_ib_ddll_long_dqs_rank0_0.
{ 0x00000006, 0x1CC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_quse. { 0x00100010, 0x400 / 4, DRAM_CC_LPDDR4X_PMACRO_IB }, // emc_pmacro_ib_ddll_long_dqs_rank0_1.
{ 0x00000005, 0x1D0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_quse_width. { 0x00100010, 0x404 / 4, DRAM_CC_LPDDR4X_PMACRO_IB }, // emc_pmacro_ib_ddll_long_dqs_rank0_2.
{ 0x00000003, 0x1DC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_einput. { 0x00100010, 0x408 / 4, DRAM_CC_LPDDR4X_PMACRO_IB }, // emc_pmacro_ib_ddll_long_dqs_rank0_3.
{ 0x0000000C, 0x1E0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_einput_duration. { 0x00100010, 0x40C / 4, DRAM_CC_LPDDR4X_PMACRO_IB }, // emc_pmacro_ib_ddll_long_dqs_rank1_0.
{ 0x08010004, 0x2B8 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw1. { 0x00100010, 0x410 / 4, DRAM_CC_LPDDR4X_PMACRO_IB }, // emc_pmacro_ib_ddll_long_dqs_rank1_1.
{ 0x08020000, 0x2BC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw2. { 0x00100010, 0x414 / 4, DRAM_CC_LPDDR4X_PMACRO_IB }, // emc_pmacro_ib_ddll_long_dqs_rank1_2.
{ 0x080D0000, 0x2C0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw3. { 0x00100010, 0x418 / 4, DRAM_CC_LPDDR4X_PMACRO_IB }, // emc_pmacro_ib_ddll_long_dqs_rank1_3.
{ 0x08033131, 0x2C8 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw6.
{ 0x080B0000, 0x2CC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw8.
{ 0x0C0E5D5D, 0x2D0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw9.
{ 0x080C5D5D, 0x2D4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw10.
{ 0x0C0D0808, 0x2D8 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw12.
{ 0x0C0D0000, 0x2DC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw13.
{ 0x08161414, 0x2E0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw14.
{ 0x08010004, 0x2E4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw_extra.
{ 0x00000000, 0x340 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_dev_select. Both devices.
{ 0x35353535, 0x350 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_vref_dq_0.
{ 0x35353535, 0x354 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_vref_dq_1.
{ 0x00100010, 0x3FC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank0_0.
{ 0x00100010, 0x400 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank0_1.
{ 0x00100010, 0x404 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank0_2.
{ 0x00100010, 0x408 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank0_3.
{ 0x00100010, 0x40C / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank1_0.
{ 0x00100010, 0x410 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank1_1.
{ 0x00100010, 0x414 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank1_2.
{ 0x00100010, 0x418 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank1_3.
{ 0x0051004F, 0x450 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_zcal_mrw_cmd.
{ 0x40000001, 0x45C / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_zcal_init_dev1.
{ 0x00000000, 0x594 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_tx_pwrd4.
{ 0x00001000, 0x598 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_tx_pwrd5.
{ 0x00000001, 0x630 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // mc_emem_adr_cfg. 2 Ranks.
{ 0x00002000, 0x64C / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // mc_emem_cfg. 8GB total density.
{ 0x00000002, 0x680 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // mc_emem_arb_timing_r2r.
{ 0x02020001, 0x694 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // mc_emem_arb_da_turns.
{ 0x2A800000, 0x6DC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // mc_video_protect_gpu_override1.
// Micron LPDDR4X 4GB MT53D1024M32D1NP-053-WT:E Die-E for retail Iowa and Hoag. /*! Shared patched between DRAM Codes. */
{ 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE }, // emc_auto_cal_config2. { 0x05500000, 0x0D4 / 4, DRAM_CC_LPDDR4X_AUTOCAL_VPR }, // emc_auto_cal_config2.
{ 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE }, // emc_auto_cal_vref_sel0. { 0xC9AFBCBC, 0x0F4 / 4, DRAM_CC_LPDDR4X_AUTOCAL_VPR }, // emc_auto_cal_vref_sel0.
{ 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE }, // emc_mrw14. { 0x2A800000, 0x6DC / 4, DRAM_CC_LPDDR4X_AUTOCAL_VPR }, // mc_video_protect_gpu_override0.
{ 0x80000713, 0x32C / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE }, // emc_dyn_self_ref_control. { 0x00000002, 0x6E0 / 4, DRAM_CC_LPDDR4X_AUTOCAL_VPR }, // mc_video_protect_gpu_override1.
{ 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE }, // mc_video_protect_gpu_override0. //!TODO Find out what mc_video_protect_gpu_override0 and mc_video_protect_gpu_override1 new bits are.
{ 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE }, // mc_video_protect_gpu_override1.
// Samsung LPDDR4X 4GB (Y01) Die-? for Iowa. { 0x88161414, 0x2E0 / 4, DRAM_CC_LPDDR4X_DYN_SELF_CTRL }, // emc_mrw14.
{ 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_auto_cal_config2. { 0x80000713, 0x32C / 4, DRAM_CC_LPDDR4X_DYN_SELF_CTRL }, // emc_dyn_self_ref_control.
{ 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_auto_cal_vref_sel0.
{ 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_mrw14.
{ 0x80000713, 0x32C / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_dyn_self_ref_control.
{ 0x32323232, 0x350 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_vref_dq_0.
{ 0x32323232, 0x354 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_vref_dq_1.
{ 0x000F0018, 0x3AC / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dq_rank0_4.
{ 0x000F0018, 0x3C4 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dq_rank1_4.
{ 0x00440048, 0x3CC / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_0.
{ 0x00440045, 0x3D0 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_1.
{ 0x00470047, 0x3D4 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_2.
{ 0x0005000D, 0x3DC / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_4.
{ 0x00440048, 0x3E4 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_0.
{ 0x00440045, 0x3E8 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_1.
{ 0x00470047, 0x3EC / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_2.
{ 0x0005000D, 0x3F4 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_4.
{ 0x00780078, 0x3FC / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank0_0.
{ 0x00780078, 0x400 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank0_1.
{ 0x00780078, 0x404 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank0_2.
{ 0x00780078, 0x408 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank0_3.
{ 0x00780078, 0x40C / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank1_0.
{ 0x00780078, 0x410 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank1_1.
{ 0x00780078, 0x414 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank1_2.
{ 0x00780078, 0x418 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank1_3.
{ 0x00180018, 0x41C / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ddll_long_cmd_0.
{ 0x000F000F, 0x420 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ddll_long_cmd_1.
{ 0x00000018, 0x42C / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ddll_long_cmd_4.
{ 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_SAMSUNG_Y }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // mc_video_protect_gpu_override1.
// Samsung LPDDR4X 4GB K4U6E3S4AA-MGCL 10nm-class (1y-X03) Die-A for retail Iowa, Hoag and Aula. { 0x00000006, 0x1CC / 4, DRAM_CC_LPDDR4X_QUSE_EINPUT }, // emc_quse.
{ 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_auto_cal_config2. { 0x00000005, 0x1D0 / 4, DRAM_CC_LPDDR4X_QUSE_EINPUT }, // emc_quse_width.
{ 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_auto_cal_vref_sel0. { 0x00000003, 0x1DC / 4, DRAM_CC_LPDDR4X_QUSE_EINPUT }, // emc_einput.
{ 0x00000006, 0x1CC / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_quse. { 0x0000000C, 0x1E0 / 4, DRAM_CC_LPDDR4X_QUSE_EINPUT }, // emc_einput_duration.
{ 0x00000005, 0x1D0 / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_quse_width.
{ 0x00000003, 0x1DC / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_einput.
{ 0x0000000C, 0x1E0 / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_einput_duration.
{ 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_mrw14.
{ 0x80000713, 0x32C / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_dyn_self_ref_control.
{ 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // mc_video_protect_gpu_override1.
// Samsung LPDDR4X 8GB K4UBE3D4AA-MGCL 10nm-class (1y-X03) Die-A for SDEV Iowa, Hoag and Aula. { 0x00000008, 0x24C / 4, DRAM_CC_LPDDR4X_FAW }, // emc_tfaw.
{ 0x05500000, 0x0D4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_auto_cal_config2. { 0x00000001, 0x670 / 4, DRAM_CC_LPDDR4X_FAW }, // mc_emem_arb_timing_faw.
{ 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_auto_cal_vref_sel0.
{ 0x00000001, 0x134 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_adr_cfg. 2 Ranks.
{ 0x00000006, 0x1CC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_quse.
{ 0x00000005, 0x1D0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_quse_width.
{ 0x00000003, 0x1DC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_einput.
{ 0x0000000C, 0x1E0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_einput_duration.
{ 0x00000008, 0x24C / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_tfaw.
{ 0x08010004, 0x2B8 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw1.
{ 0x08020000, 0x2BC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw2.
{ 0x080D0000, 0x2C0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw3.
{ 0x08033131, 0x2C8 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw6.
{ 0x080B0000, 0x2CC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw8.
{ 0x0C0E5D5D, 0x2D0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw9.
{ 0x080C5D5D, 0x2D4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw10.
{ 0x0C0D0808, 0x2D8 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw12.
{ 0x0C0D0000, 0x2DC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw13.
{ 0x08161414, 0x2E0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw14.
{ 0x08010004, 0x2E4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw_extra.
{ 0x00000000, 0x340 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_dev_select. Both devices.
{ 0x0051004F, 0x450 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_zcal_mrw_cmd.
{ 0x40000001, 0x45C / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_zcal_init_dev1.
{ 0x00000000, 0x594 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_pmacro_tx_pwrd4.
{ 0x00001000, 0x598 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_pmacro_tx_pwrd5.
{ 0x00000001, 0x630 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_emem_adr_cfg. 2 Ranks.
{ 0x00002000, 0x64C / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_emem_cfg. 8GB total density.
{ 0x00000001, 0x670 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_emem_arb_timing_faw.
{ 0x00000002, 0x680 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_emem_arb_timing_r2r.
{ 0x02020001, 0x694 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_emem_arb_da_turns.
{ 0x2A800000, 0x6DC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_video_protect_gpu_override1.
// Samsung LPDDR4X 4GB 10nm-class (1y-Y01) Die-? for Iowa. { 0xE4FACB43, 0x6D4 / 4, DRAM_CC_LPDDR4X_VPR }, // mc_video_protect_vpr_override. + TSEC, NVENC.
{ 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_auto_cal_config2. { 0x0600FED3, 0x6D8 / 4, DRAM_CC_LPDDR4X_VPR }, // mc_video_protect_vpr_override1. + TSECB, TSEC1, TSECB1.
{ 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_auto_cal_vref_sel0.
{ 0x00000008, 0x24C / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_tfaw.
{ 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_mrw14.
{ 0x80000713, 0x32C / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_dyn_self_ref_control.
{ 0x000F0018, 0x3AC / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dq_rank0_4.
{ 0x000F0018, 0x3C4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dq_rank1_4.
{ 0x00440048, 0x3CC / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_0.
{ 0x00440045, 0x3D0 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_1.
{ 0x00470047, 0x3D4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_2.
{ 0x0005000D, 0x3DC / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_4.
{ 0x00440048, 0x3E4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_0.
{ 0x00440045, 0x3E8 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_1.
{ 0x00470047, 0x3EC / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_2.
{ 0x0005000D, 0x3F4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_4.
{ 0x00180018, 0x41C / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ddll_long_cmd_0.
{ 0x000F000F, 0x420 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ddll_long_cmd_1.
{ 0x00000018, 0x42C / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ddll_long_cmd_4.
{ 0x00000001, 0x670 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // mc_emem_arb_timing_faw.
{ 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // mc_video_protect_gpu_override1.
// Samsung LPDDR4X 8GB 10nm-class (1y-Y01) Die-? for SDEV Iowa. { 0x00000001, 0x134 / 4, DRAM_CC_LPDDR4X_8GB }, // emc_adr_cfg. 2 Ranks.
{ 0x05500000, 0x0D4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_auto_cal_config2. { 0x08010004, 0x2B8 / 4, DRAM_CC_LPDDR4X_8GB }, // emc_mrw1.
{ 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_auto_cal_vref_sel0. { 0x08020000, 0x2BC / 4, DRAM_CC_LPDDR4X_8GB }, // emc_mrw2.
{ 0x00000001, 0x134 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_adr_cfg. 2 Ranks. { 0x080D0000, 0x2C0 / 4, DRAM_CC_LPDDR4X_8GB }, // emc_mrw3.
{ 0x00000008, 0x24C / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_tfaw. { 0x08033131, 0x2C8 / 4, DRAM_CC_LPDDR4X_8GB }, // emc_mrw6.
{ 0x08010004, 0x2B8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw1. { 0x080B0000, 0x2CC / 4, DRAM_CC_LPDDR4X_8GB }, // emc_mrw8.
{ 0x08020000, 0x2BC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw2. { 0x0C0E5D5D, 0x2D0 / 4, DRAM_CC_LPDDR4X_8GB }, // emc_mrw9.
{ 0x080D0000, 0x2C0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw3. { 0x080C5D5D, 0x2D4 / 4, DRAM_CC_LPDDR4X_8GB }, // emc_mrw10.
{ 0x08033131, 0x2C8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw6. { 0x0C0D0808, 0x2D8 / 4, DRAM_CC_LPDDR4X_8GB }, // emc_mrw12.
{ 0x080B0000, 0x2CC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw8. { 0x0C0D0000, 0x2DC / 4, DRAM_CC_LPDDR4X_8GB }, // emc_mrw13.
{ 0x0C0E5D5D, 0x2D0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw9. { 0x08161414, 0x2E0 / 4, DRAM_CC_LPDDR4X_8GB }, // emc_mrw14.
{ 0x080C5D5D, 0x2D4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw10. { 0x08010004, 0x2E4 / 4, DRAM_CC_LPDDR4X_8GB }, // emc_mrw_extra.
{ 0x0C0D0808, 0x2D8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw12. { 0x00000000, 0x340 / 4, DRAM_CC_LPDDR4X_8GB }, // emc_dev_select. Both devices.
{ 0x0C0D0000, 0x2DC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw13. { 0x0051004F, 0x450 / 4, DRAM_CC_LPDDR4X_8GB }, // emc_zcal_mrw_cmd.
{ 0x08161414, 0x2E0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw14. { 0x40000001, 0x45C / 4, DRAM_CC_LPDDR4X_8GB }, // emc_zcal_init_dev1.
{ 0x08010004, 0x2E4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw_extra. { 0x00000000, 0x594 / 4, DRAM_CC_LPDDR4X_8GB }, // emc_pmacro_tx_pwrd4.
{ 0x00000000, 0x340 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_dev_select. Both devices. { 0x00001000, 0x598 / 4, DRAM_CC_LPDDR4X_8GB }, // emc_pmacro_tx_pwrd5.
{ 0x32323232, 0x350 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ib_vref_dq_0. { 0x00000001, 0x630 / 4, DRAM_CC_LPDDR4X_8GB }, // mc_emem_adr_cfg. 2 Ranks.
{ 0x32323232, 0x354 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ib_vref_dq_1. { 0x00002000, 0x64C / 4, DRAM_CC_LPDDR4X_8GB }, // mc_emem_cfg. 8GB total density.
{ 0x000F0018, 0x3AC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dq_rank0_4. { 0x00000002, 0x680 / 4, DRAM_CC_LPDDR4X_8GB }, // mc_emem_arb_timing_r2r.
{ 0x000F0018, 0x3C4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dq_rank1_4. { 0x02020001, 0x694 / 4, DRAM_CC_LPDDR4X_8GB }, // mc_emem_arb_da_turns.
{ 0x00440048, 0x3CC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_0.
{ 0x00440045, 0x3D0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_1.
{ 0x00470047, 0x3D4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_2.
{ 0x0005000D, 0x3DC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_4.
{ 0x00440048, 0x3E4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_0.
{ 0x00440045, 0x3E8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_1.
{ 0x00470047, 0x3EC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_2.
{ 0x0005000D, 0x3F4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_4.
{ 0x00180018, 0x41C / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ddll_long_cmd_0.
{ 0x000F000F, 0x420 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ddll_long_cmd_1.
{ 0x00000018, 0x42C / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ddll_long_cmd_4.
{ 0x0051004F, 0x450 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_zcal_mrw_cmd.
{ 0x40000001, 0x45C / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_zcal_init_dev1.
{ 0x00000000, 0x594 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_tx_pwrd4.
{ 0x00001000, 0x598 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_tx_pwrd5.
{ 0x00000001, 0x630 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_emem_adr_cfg. 2 Ranks.
{ 0x00002000, 0x64C / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_emem_cfg. 8GB total density.
{ 0x00000001, 0x670 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_emem_arb_timing_faw.
{ 0x00000002, 0x680 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_emem_arb_timing_r2r.
{ 0x02020001, 0x694 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_emem_arb_da_turns.
{ 0x2A800000, 0x6DC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_video_protect_gpu_override1.
/*
// Samsung LPDDR4X 8GB 10nm-class (1y-A01) Die-? for SDEV Aula?
{ 0x00000001, 0x134 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_adr_cfg. 2 Ranks.
{ 0x08010004, 0x2B8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw1.
{ 0x08020000, 0x2BC / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw2.
{ 0x080D0000, 0x2C0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw3.
{ 0x08033131, 0x2C8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw6.
{ 0x080B0000, 0x2CC / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw8.
{ 0x0C0E5D5D, 0x2D0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw9.
{ 0x080C5D5D, 0x2D4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw10.
{ 0x0C0D0808, 0x2D8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw12.
{ 0x0C0D0000, 0x2DC / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw13.
{ 0x08161414, 0x2E0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw14.
{ 0x08010004, 0x2E4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw_extra.
{ 0x00000000, 0x340 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_dev_select. Both devices.
{ 0x35353535, 0x350 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_vref_dq_0.
{ 0x35353535, 0x354 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_vref_dq_1.
{ 0x35353535, 0x358 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_vref_dqs_0.
{ 0x35353535, 0x35C / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_vref_dqs_1.
{ 0x00480048, 0x3FC / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank0_0.
{ 0x00480048, 0x400 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank0_1.
{ 0x00480048, 0x404 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank0_2.
{ 0x00480048, 0x408 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank0_3.
{ 0x00480048, 0x40C / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank1_0.
{ 0x00480048, 0x410 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank1_1.
{ 0x00480048, 0x414 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank1_2.
{ 0x00480048, 0x418 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank1_3.
{ 0x0051004F, 0x450 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_zcal_mrw_cmd.
{ 0x40000001, 0x45C / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_zcal_init_dev1.
{ 0x00010100, 0x594 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_tx_pwrd4.
{ 0x00400010, 0x598 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_tx_pwrd5.
{ 0x00000001, 0x630 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // mc_emem_adr_cfg. 2 Ranks.
{ 0x00002000, 0x64C / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // mc_emem_cfg. 8GB total density.
{ 0x00000002, 0x670 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // mc_emem_arb_timing_faw.
{ 0x00000002, 0x680 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // mc_emem_arb_timing_r2r.
{ 0x02020001, 0x694 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // mc_emem_arb_da_turns.
*/
// Micron LPDDR4X 4GB MT53D1024M32D1NP-053-WT:F 10nm-class (1y-01) Die-F for Newer Iowa/Hoag/Aula.
{ 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_auto_cal_config2.
{ 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_auto_cal_vref_sel0.
{ 0x00000006, 0x1CC / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_quse.
{ 0x00000005, 0x1D0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_quse_width.
{ 0x00000003, 0x1DC / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_einput.
{ 0x0000000C, 0x1E0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_einput_duration.
{ 0x00000008, 0x24C / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_tfaw.
{ 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_mrw14.
{ 0x80000713, 0x32C / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_dyn_self_ref_control.
{ 0x00000001, 0x670 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // mc_emem_arb_timing_faw.
{ 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // mc_video_protect_gpu_override1.
// Hynix LPDDR4X 4GB 10nm-class (1y-01) Die-A for Unknown Iowa/Hoag/Aula.
{ 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_auto_cal_config2.
{ 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_auto_cal_vref_sel0.
{ 0x00000006, 0x1CC / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_quse.
{ 0x00000005, 0x1D0 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_quse_width.
{ 0x00000003, 0x1DC / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_einput.
{ 0x0000000C, 0x1E0 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_einput_duration.
{ 0x00000008, 0x24C / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_tfaw.
{ 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_mrw14.
{ 0x80000713, 0x32C / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_dyn_self_ref_control.
{ 0x00000001, 0x670 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // mc_emem_arb_timing_faw.
{ 0xE4FACB43, 0x6D4 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // mc_video_protect_vpr_override. + TSEC, NVENC.
{ 0x0600FED3, 0x6D8 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // mc_video_protect_vpr_override1. + TSECB, TSEC1, TSECB1.
{ 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // mc_video_protect_gpu_override1.
//!TODO: Too many duplicates.
}; };

View File

@@ -1125,7 +1125,7 @@ static void _sdram_lp0_save_params_t210(const void *params)
c32(0, scratch4); c32(0, scratch4);
s(PllMStableTime, 9:0, scratch4, 9:0); s(PllMStableTime, 9:0, scratch4, 9:0);
} }
/*
#pragma GCC diagnostic ignored "-Wparentheses" #pragma GCC diagnostic ignored "-Wparentheses"
static void _sdram_lp0_save_params_t210b01(const void *params) static void _sdram_lp0_save_params_t210b01(const void *params)
@@ -1526,13 +1526,13 @@ static void _sdram_lp0_save_params_t210b01(const void *params)
} }
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
*/
void sdram_lp0_save_params(const void *params) void sdram_lp0_save_params(const void *params)
{ {
// u32 chip_id = (APB_MISC(APB_MISC_GP_HIDREV) >> 4) & 0xF; u32 chip_id = (APB_MISC(APB_MISC_GP_HIDREV) >> 4) & 0xF;
// if (chip_id != GP_HIDREV_MAJOR_T210B01) if (chip_id != GP_HIDREV_MAJOR_T210B01)
_sdram_lp0_save_params_t210(params); _sdram_lp0_save_params_t210(params);
// else else
// _sdram_lp0_save_params_t210b01(params); _sdram_lp0_save_params_t210b01(params);
} }

View File

@@ -1,6 +1,7 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018 balika011 * Copyright (c) 2018 balika011
* Copyright (c) 2018-2022 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -18,10 +19,10 @@
#include <string.h> #include <string.h>
#include <soc/ccplex.h> #include <soc/ccplex.h>
#include <soc/timer.h>
#include <soc/t210.h> #include <soc/t210.h>
#include <mem/mc_t210.h> #include <mem/mc_t210.h>
#include <mem/smmu.h> #include <mem/smmu.h>
#include <utils/util.h>
#include <utils/aarch64_util.h> #include <utils/aarch64_util.h>
bool smmu_used = false; bool smmu_used = false;
@@ -70,18 +71,19 @@ void smmu_flush_all()
{ {
MC(MC_SMMU_PTC_FLUSH) = 0; MC(MC_SMMU_PTC_FLUSH) = 0;
smmu_flush_regs(); smmu_flush_regs();
MC(MC_SMMU_TLB_FLUSH) = 0; MC(MC_SMMU_TLB_FLUSH) = 0;
smmu_flush_regs(); smmu_flush_regs();
} }
void smmu_init(u32 secmon_base) void smmu_init(u32 secmon_base)
{ {
MC(MC_SMMU_PTB_ASID) = 0; MC(MC_SMMU_PTB_ASID) = 0;
MC(MC_SMMU_PTB_DATA) = 0; MC(MC_SMMU_PTB_DATA) = 0;
MC(MC_SMMU_TLB_CONFIG) = 0x30000030; MC(MC_SMMU_TLB_CONFIG) = 0x30000030;
MC(MC_SMMU_PTC_CONFIG) = 0x28000F3F; MC(MC_SMMU_PTC_CONFIG) = 0x28000F3F;
MC(MC_SMMU_PTC_FLUSH) = 0; MC(MC_SMMU_PTC_FLUSH) = 0;
MC(MC_SMMU_TLB_FLUSH) = 0; MC(MC_SMMU_TLB_FLUSH) = 0;
// Set the secmon address // Set the secmon address
*(u32 *)(smmu_payload + 0x30) = secmon_base; *(u32 *)(smmu_payload + 0x30) = secmon_base;
@@ -163,8 +165,8 @@ u32 *smmu_init_for_tsec()
void smmu_deinit_for_tsec() void smmu_deinit_for_tsec()
{ {
MC(MC_SMMU_PTB_ASID) = 1; MC(MC_SMMU_PTB_ASID) = 1;
MC(MC_SMMU_PTB_DATA) = 0; MC(MC_SMMU_PTB_DATA) = 0;
MC(MC_SMMU_TSEC_ASID) = 0; MC(MC_SMMU_TSEC_ASID) = 0;
smmu_flush_regs(); smmu_flush_regs();
} }

View File

@@ -30,6 +30,7 @@
#define MC_SMMU_TLB_FLUSH 0x30 #define MC_SMMU_TLB_FLUSH 0x30
#define MC_SMMU_PTC_FLUSH 0x34 #define MC_SMMU_PTC_FLUSH 0x34
#define MC_SMMU_ASID_SECURITY 0x38 #define MC_SMMU_ASID_SECURITY 0x38
#define MC_SMMU_AVPC_ASID 0x23C
#define MC_SMMU_TSEC_ASID 0x294 #define MC_SMMU_TSEC_ASID 0x294
#define MC_SMMU_TRANSLATION_ENABLE_0 0x228 #define MC_SMMU_TRANSLATION_ENABLE_0 0x228
#define MC_SMMU_TRANSLATION_ENABLE_1 0x22c #define MC_SMMU_TRANSLATION_ENABLE_1 0x22c

View File

@@ -117,6 +117,6 @@
#define NX_BIS_CACHE_ADDR 0xC5000000 #define NX_BIS_CACHE_ADDR 0xC5000000
#define NX_BIS_CACHE_SZ 0x10020000 // 256MB. #define NX_BIS_CACHE_SZ 0x10020000 // 256MB.
#define NX_BIS_LOOKUP_ADDR DRAM_MEM_HOLE_ADR #define NX_BIS_LOOKUP_ADDR DRAM_MEM_HOLE_ADR
#define NX_BIS_LOOKUP_SZ DRAM_MEM_HOLE_SZ #define NX_BIS_LOOKUP_SZ DRAM_MEM_HOLE_SZ // 240MB.
#endif #endif

View File

@@ -1,7 +1,7 @@
/* /*
* USB-PD driver for Nintendo Switch's TI BM92T36 * USB-PD driver for Nintendo Switch's TI BM92T36
* *
* Copyright (c) 2020 CTCaer * Copyright (c) 2020-2023 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -73,18 +73,23 @@ void bm92t36_get_sink_info(bool *inserted, usb_pd_objects_t *usb_pd)
if (inserted) if (inserted)
{ {
memset(buf, 0, sizeof(buf));
_bm92t36_read_reg(buf, 2, STATUS1_REG); _bm92t36_read_reg(buf, 2, STATUS1_REG);
*inserted = buf[0] & STATUS1_INSERT ? true : false; *inserted = buf[0] & STATUS1_INSERT ? true : false;
} }
if (usb_pd) if (usb_pd)
{ {
memset(buf, 0, sizeof(buf));
_bm92t36_read_reg(buf, 29, READ_PDOS_SRC_REG); _bm92t36_read_reg(buf, 29, READ_PDOS_SRC_REG);
memcpy(pdos, &buf[1], 28); memcpy(pdos, &buf[1], 28);
memset(usb_pd, 0, sizeof(usb_pd_objects_t)); memset(usb_pd, 0, sizeof(usb_pd_objects_t));
usb_pd->pdo_no = buf[0] / sizeof(pd_object_t); usb_pd->pdo_no = buf[0] / sizeof(pd_object_t);
if (usb_pd->pdo_no > 7)
usb_pd->pdo_no = 7;
for (u32 i = 0; i < usb_pd->pdo_no; i++) for (u32 i = 0; i < usb_pd->pdo_no; i++)
{ {
usb_pd->pdos[i].amperage = pdos[i].amp * 10; usb_pd->pdos[i].amperage = pdos[i].amp * 10;

View File

@@ -28,7 +28,7 @@
// REG 1 masks. // REG 1 masks.
#define BQ24193_PORCONFIG_BOOST_MASK (1<<0) #define BQ24193_PORCONFIG_BOOST_MASK (1<<0)
#define BQ24193_PORCONFIG_SYSMIN_MASK (7<<1) #define BQ24193_PORCONFIG_SYSMIN_MASK (7<<1) // 3000uV HOS default.
#define BQ24193_PORCONFIG_CHGCONFIG_MASK (3<<4) #define BQ24193_PORCONFIG_CHGCONFIG_MASK (3<<4)
#define BQ24193_PORCONFIG_CHGCONFIG_CHARGER_EN (1<<4) #define BQ24193_PORCONFIG_CHGCONFIG_CHARGER_EN (1<<4)
#define BQ24193_PORCONFIG_I2CWATCHDOG_MASK (1<<6) #define BQ24193_PORCONFIG_I2CWATCHDOG_MASK (1<<6)

View File

@@ -24,7 +24,7 @@
#include "max17050.h" #include "max17050.h"
#include <soc/i2c.h> #include <soc/i2c.h>
#include <utils/util.h> #include <soc/timer.h>
#define BASE_SNS_UOHM 5000 #define BASE_SNS_UOHM 5000

View File

@@ -95,9 +95,9 @@
#define MAX77620_IRQSD_PFI_SD1 BIT(6) #define MAX77620_IRQSD_PFI_SD1 BIT(6)
#define MAX77620_IRQSD_PFI_SD0 BIT(7) #define MAX77620_IRQSD_PFI_SD0 BIT(7)
#define MAX77620_REG_IRQ_LVL2_L0_7 0x08 // LDO number that irq occured. #define MAX77620_REG_IRQ_LVL2_L0_7 0x08 // LDO number that irq occurred.
#define MAX77620_REG_IRQ_MSK_L0_7 0x10 #define MAX77620_REG_IRQ_MSK_L0_7 0x10
#define MAX77620_REG_IRQ_LVL2_L8 0x09 // LDO number that irq occured. Only bit0: LDO8 is valid. #define MAX77620_REG_IRQ_LVL2_L8 0x09 // LDO number that irq occurred. Only bit0: LDO8 is valid.
#define MAX77620_REG_IRQ_MSK_L8 0x11 #define MAX77620_REG_IRQ_MSK_L8 0x11
#define MAX77620_REG_IRQ_LVL2_GPIO 0x0A // Edge detection interrupt. #define MAX77620_REG_IRQ_LVL2_GPIO 0x0A // Edge detection interrupt.
@@ -139,8 +139,8 @@
#define MAX77620_REG_DVSSD0 0x1B #define MAX77620_REG_DVSSD0 0x1B
#define MAX77620_REG_DVSSD1 0x1C #define MAX77620_REG_DVSSD1 0x1C
#define MAX77620_SDX_VOLT_MASK 0xFF #define MAX77620_SDX_VOLT_MASK 0xFF
#define MAX77620_SD0_VOLT_MASK 0x3F #define MAX77620_SD0_VOLT_MASK 0x7F // Max is 0x40.
#define MAX77620_SD1_VOLT_MASK 0x7F #define MAX77620_SD1_VOLT_MASK 0x7F // Max is 0x4C.
#define MAX77620_LDO_VOLT_MASK 0x3F #define MAX77620_LDO_VOLT_MASK 0x3F
#define MAX77620_REG_SD0_CFG 0x1D #define MAX77620_REG_SD0_CFG 0x1D
@@ -318,7 +318,7 @@
#define MAX77620_REG_CID2 0x5A #define MAX77620_REG_CID2 0x5A
#define MAX77620_REG_CID3 0x5B #define MAX77620_REG_CID3 0x5B
#define MAX77620_REG_CID4 0x5C // OTP version. #define MAX77620_REG_CID4 0x5C // OTP version.
#define MAX77620_REG_CID5 0x5D #define MAX77620_REG_CID5 0x5D // ES version.
#define MAX77620_CID_DIDO_MASK 0xF #define MAX77620_CID_DIDO_MASK 0xF
#define MAX77620_CID_DIDO_SHIFT 0 #define MAX77620_CID_DIDO_SHIFT 0
#define MAX77620_CID_DIDM_MASK 0xF0 #define MAX77620_CID_DIDM_MASK 0xF0

View File

@@ -20,8 +20,8 @@
#include <power/max77812.h> #include <power/max77812.h>
#include <soc/fuse.h> #include <soc/fuse.h>
#include <soc/i2c.h> #include <soc/i2c.h>
#include <soc/timer.h>
#include <soc/t210.h> #include <soc/t210.h>
#include <utils/util.h>
#define REGULATOR_SD 0 #define REGULATOR_SD 0
#define REGULATOR_LDO 1 #define REGULATOR_LDO 1
@@ -75,7 +75,7 @@ typedef struct _max77620_regulator_t
static const max77620_regulator_t _pmic_regulators[] = { static const max77620_regulator_t _pmic_regulators[] = {
{ "sd0", 12500, 600000, 625000, 1400000, REGULATOR_SD, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, MAX77620_SD0_VOLT_MASK, {{ MAX77620_REG_FPS_SD0, 1, 7, 1 }} }, { "sd0", 12500, 600000, 625000, 1400000, REGULATOR_SD, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, MAX77620_SD0_VOLT_MASK, {{ MAX77620_REG_FPS_SD0, 1, 7, 1 }} },
{ "sd1", 12500, 600000, 1125000, 1250000, REGULATOR_SD, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, MAX77620_SD1_VOLT_MASK, {{ MAX77620_REG_FPS_SD1, 0, 1, 5 }} }, { "sd1", 12500, 600000, 1125000, 1175000, REGULATOR_SD, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, MAX77620_SD1_VOLT_MASK, {{ MAX77620_REG_FPS_SD1, 0, 1, 5 }} },
{ "sd2", 12500, 600000, 1325000, 1350000, REGULATOR_SD, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD2, 1, 5, 2 }} }, { "sd2", 12500, 600000, 1325000, 1350000, REGULATOR_SD, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD2, 1, 5, 2 }} },
{ "sd3", 12500, 600000, 1800000, 1800000, REGULATOR_SD, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD3, 0, 3, 3 }} }, { "sd3", 12500, 600000, 1800000, 1800000, REGULATOR_SD, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD3, 0, 3, 3 }} },
{ "ldo0", 25000, 800000, 1200000, 1200000, REGULATOR_LDO, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO0, 3, 7, 0 }} }, { "ldo0", 25000, 800000, 1200000, 1200000, REGULATOR_LDO, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO0, 3, 7, 0 }} },
@@ -88,11 +88,11 @@ static const max77620_regulator_t _pmic_regulators[] = {
{ "ldo7", 50000, 800000, 1050000, 1050000, REGULATOR_LDO, MAX77620_REG_LDO7_CFG, MAX77620_REG_LDO7_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO7, 1, 4, 3 }} }, { "ldo7", 50000, 800000, 1050000, 1050000, REGULATOR_LDO, MAX77620_REG_LDO7_CFG, MAX77620_REG_LDO7_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO7, 1, 4, 3 }} },
{ "ldo8", 50000, 800000, 1050000, 2800000, REGULATOR_LDO, MAX77620_REG_LDO8_CFG, MAX77620_REG_LDO8_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO8, 3, 7, 0 }} }, { "ldo8", 50000, 800000, 1050000, 2800000, REGULATOR_LDO, MAX77620_REG_LDO8_CFG, MAX77620_REG_LDO8_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO8, 3, 7, 0 }} },
{ "max77621_CPU", 6250, 606250, 1000000, 1400000, REGULATOR_BC0, MAX77621_VOUT_REG, MAX77621_VOUT_DVS_REG, MAX77621_DVC_DVS_VOLT_MASK, {{ MAX77621_CPU_CTRL1_POR_DEFAULT, MAX77621_CPU_CTRL1_HOS_DEFAULT, MAX77621_CPU_CTRL2_POR_DEFAULT, MAX77621_CPU_CTRL2_HOS_DEFAULT }} }, { "max77621_CPU", 6250, 606250, 1000000, 1400000, REGULATOR_BC0, MAX77621_REG_VOUT, MAX77621_REG_VOUT_DVS, MAX77621_DVC_DVS_VOLT_MASK, {{ MAX77621_CPU_CTRL1_POR_DEFAULT, MAX77621_CPU_CTRL1_HOS_DEFAULT, MAX77621_CPU_CTRL2_POR_DEFAULT, MAX77621_CPU_CTRL2_HOS_DEFAULT }} },
{ "max77621_GPU", 6250, 606250, 1200000, 1400000, REGULATOR_BC0, MAX77621_VOUT_REG, MAX77621_VOUT_DVS_REG, MAX77621_DVC_DVS_VOLT_MASK, {{ MAX77621_CPU_CTRL1_POR_DEFAULT, MAX77621_CPU_CTRL1_HOS_DEFAULT, MAX77621_CPU_CTRL2_POR_DEFAULT, MAX77621_CPU_CTRL2_HOS_DEFAULT }} }, { "max77621_GPU", 6250, 606250, 1200000, 1400000, REGULATOR_BC0, MAX77621_REG_VOUT, MAX77621_REG_VOUT_DVS, MAX77621_DVC_DVS_VOLT_MASK, {{ MAX77621_CPU_CTRL1_POR_DEFAULT, MAX77621_CPU_CTRL1_HOS_DEFAULT, MAX77621_CPU_CTRL2_POR_DEFAULT, MAX77621_CPU_CTRL2_HOS_DEFAULT }} },
{ "max77812_CPU", 5000, 250000, 600000, 1525000, REGULATOR_BC1, MAX77812_REG_M4_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M4_MASK, MAX77812_EN_CTRL_EN_M4_SHIFT, 0, 0 }} }, { "max77812_CPU", 5000, 250000, 600000, 1525000, REGULATOR_BC1, MAX77812_REG_M4_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M4_MASK, MAX77812_EN_CTRL_EN_M4_SHIFT, 0, 0 }} },
{ "max77812_RAM", 5000, 250000, 600000, 650000, REGULATOR_BC1, MAX77812_REG_M3_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M3_MASK, MAX77812_EN_CTRL_EN_M3_SHIFT, 0, 0 }} } // Only on PHASE211 configuration.
//{ "max77812_GPU", 5000, 250000, 600000, 1525000, REGULATOR_BC1, MAX77812_REG_M1_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M1_MASK, MAX77812_EN_CTRL_EN_M1_SHIFT, 0, 0 }} }, //{ "max77812_GPU", 5000, 250000, 600000, 1525000, REGULATOR_BC1, MAX77812_REG_M1_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M1_MASK, MAX77812_EN_CTRL_EN_M1_SHIFT, 0, 0 }} },
//{ "max77812_RAM", 5000, 250000, 600000, 1525000, REGULATOR_BC1, MAX77812_REG_M3_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M3_MASK, MAX77812_EN_CTRL_EN_M3_SHIFT, 0, 0 }} } // Only on PHASE211 configuration.
}; };
static u8 _max77812_get_address() static u8 _max77812_get_address()
@@ -121,7 +121,12 @@ static u8 _max7762x_get_i2c_address(u32 id)
case REGULATOR_BC0: case REGULATOR_BC0:
return (id == REGULATOR_CPU0 ? MAX77621_CPU_I2C_ADDR : MAX77621_GPU_I2C_ADDR); return (id == REGULATOR_CPU0 ? MAX77621_CPU_I2C_ADDR : MAX77621_GPU_I2C_ADDR);
case REGULATOR_BC1: case REGULATOR_BC1:
return _max77812_get_address(); {
u8 reg_addr = _max77812_get_address();
if (id == REGULATOR_RAM0 && reg_addr == MAX77812_PHASE31_CPU_I2C_ADDR)
reg_addr = 0;
return reg_addr;
}
default: default:
return 0; return 0;
} }
@@ -175,20 +180,22 @@ int max77620_regulator_config_fps(u32 id)
return 1; return 1;
} }
int max7762x_regulator_set_voltage(u32 id, u32 mv) int max7762x_regulator_set_voltage(u32 id, u32 uv)
{ {
if (id > REGULATOR_MAX) if (id > REGULATOR_MAX)
return 0; return 0;
const max77620_regulator_t *reg = &_pmic_regulators[id]; const max77620_regulator_t *reg = &_pmic_regulators[id];
if (mv < reg->uv_min || mv > reg->uv_max) if (uv < reg->uv_min || uv > reg->uv_max)
return 0; return 0;
u8 addr = _max7762x_get_i2c_address(id); u8 addr = _max7762x_get_i2c_address(id);
if (!addr)
return 0;
// Calculate voltage multiplier. // Calculate voltage multiplier.
u32 mult = (mv + reg->uv_step - 1 - reg->uv_min) / reg->uv_step; u32 mult = (uv + reg->uv_step - 1 - reg->uv_min) / reg->uv_step;
u8 val = i2c_recv_byte(I2C_5, addr, reg->volt_addr); u8 val = i2c_recv_byte(I2C_5, addr, reg->volt_addr);
val = (val & ~reg->volt_mask) | (mult & reg->volt_mask); val = (val & ~reg->volt_mask) | (mult & reg->volt_mask);
@@ -249,6 +256,8 @@ int max7762x_regulator_enable(u32 id, bool enable)
} }
u8 addr = _max7762x_get_i2c_address(id); u8 addr = _max7762x_get_i2c_address(id);
if (!addr)
return 0;
// Read and enable/disable. // Read and enable/disable.
u8 val = i2c_recv_byte(I2C_5, addr, reg_addr); u8 val = i2c_recv_byte(I2C_5, addr, reg_addr);
@@ -291,6 +300,8 @@ void max77621_config_default(u32 id, bool por)
return; return;
u8 addr = _max7762x_get_i2c_address(id); u8 addr = _max7762x_get_i2c_address(id);
if (!addr)
return;
if (por) if (por)
{ {
@@ -299,13 +310,13 @@ void max77621_config_default(u32 id, bool por)
max7762x_regulator_enable(id, false); max7762x_regulator_enable(id, false);
// Configure to default. // Configure to default.
i2c_send_byte(I2C_5, addr, MAX77621_CONTROL1_REG, reg->ctrl.ctrl1_por); i2c_send_byte(I2C_5, addr, MAX77621_REG_CONTROL1, reg->ctrl.ctrl1_por);
i2c_send_byte(I2C_5, addr, MAX77621_CONTROL2_REG, reg->ctrl.ctrl2_por); i2c_send_byte(I2C_5, addr, MAX77621_REG_CONTROL2, reg->ctrl.ctrl2_por);
} }
else else
{ {
i2c_send_byte(I2C_5, addr, MAX77621_CONTROL1_REG, reg->ctrl.ctrl1_hos); i2c_send_byte(I2C_5, addr, MAX77621_REG_CONTROL1, reg->ctrl.ctrl1_hos);
i2c_send_byte(I2C_5, addr, MAX77621_CONTROL2_REG, reg->ctrl.ctrl2_hos); i2c_send_byte(I2C_5, addr, MAX77621_REG_CONTROL2, reg->ctrl.ctrl2_hos);
} }
} }

View File

@@ -20,6 +20,14 @@
#include <utils/types.h> #include <utils/types.h>
/*
* SDx actual min is 625 mV. Multipliers 0/1 reserved.
* SD0 max is 1400 mV
* SD1 max is 1550 mV
* SD2 max is 3787.5 mV
* SD3 max is 3787.5 mV
*/
/* /*
* Switch Power domains (max77620): * Switch Power domains (max77620):
* Name | Usage | uV step | uV min | uV default | uV max | Init * Name | Usage | uV step | uV min | uV default | uV max | Init
@@ -58,22 +66,22 @@
#define REGULATOR_LDO6 10 #define REGULATOR_LDO6 10
#define REGULATOR_LDO7 11 #define REGULATOR_LDO7 11
#define REGULATOR_LDO8 12 #define REGULATOR_LDO8 12
#define REGULATOR_CPU0 13 #define REGULATOR_CPU0 13 // T210 CPU.
#define REGULATOR_GPU0 14 #define REGULATOR_GPU0 14 // T210 CPU.
#define REGULATOR_CPU1 15 #define REGULATOR_CPU1 15 // T210B01 CPU.
//#define REGULATOR_GPU1 16 #define REGULATOR_RAM0 16 // T210B01 RAM for PHASE211.
//#define REGULATOR_GPU1 17 //#define REGULATOR_GPU1 17 // T210B01 CPU.
#define REGULATOR_MAX 15 #define REGULATOR_MAX REGULATOR_RAM0
#define MAX77621_CPU_I2C_ADDR 0x1B #define MAX77621_CPU_I2C_ADDR 0x1B
#define MAX77621_GPU_I2C_ADDR 0x1C #define MAX77621_GPU_I2C_ADDR 0x1C
#define MAX77621_VOUT_REG 0x00 #define MAX77621_REG_VOUT 0x00
#define MAX77621_VOUT_DVS_REG 0x01 #define MAX77621_REG_VOUT_DVS 0x01
#define MAX77621_CONTROL1_REG 0x02 #define MAX77621_REG_CONTROL1 0x02
#define MAX77621_CONTROL2_REG 0x03 #define MAX77621_REG_CONTROL2 0x03
#define MAX77621_CHIPID1_REG 0x04 #define MAX77621_REG_CHIPID1 0x04
#define MAX77621_CHIPID2_REG 0x05 #define MAX77621_REG_CHIPID2 0x05
/* MAX77621_VOUT_DVC_DVS */ /* MAX77621_VOUT_DVC_DVS */
#define MAX77621_DVC_DVS_VOLT_MASK 0x7F #define MAX77621_DVC_DVS_VOLT_MASK 0x7F
@@ -106,11 +114,10 @@
#define MAX77621_INDUCTOR_PLUS_60_PER 3 #define MAX77621_INDUCTOR_PLUS_60_PER 3
#define MAX77621_INDUCTOR_MASK 3 #define MAX77621_INDUCTOR_MASK 3
#define MAX77621_CKKADV_TRIP_75mV_PER_US 0x0 #define MAX77621_CKKADV_TRIP_75mV_PER_US (0 << 2)
#define MAX77621_CKKADV_TRIP_150mV_PER_US BIT(2) #define MAX77621_CKKADV_TRIP_150mV_PER_US (1u << 2)
#define MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS BIT(3) #define MAX77621_CKKADV_TRIP_DISABLE (3u << 2)
#define MAX77621_CKKADV_TRIP_DISABLE (BIT(2) | BIT(3)) #define MAX77621_CKKADV_TRIP_MASK (3u << 2)
#define MAX77621_CKKADV_TRIP_MASK (BIT(2) | BIT(3))
#define MAX77621_FT_ENABLE BIT(4) #define MAX77621_FT_ENABLE BIT(4)
#define MAX77621_DISCH_ENABLE BIT(5) #define MAX77621_DISCH_ENABLE BIT(5)
@@ -118,18 +125,17 @@
#define MAX77621_T_JUNCTION_120 BIT(7) #define MAX77621_T_JUNCTION_120 BIT(7)
#define MAX77621_CPU_CTRL1_POR_DEFAULT (MAX77621_RAMP_50mV_PER_US) #define MAX77621_CPU_CTRL1_POR_DEFAULT (MAX77621_RAMP_50mV_PER_US)
#define MAX77621_CPU_CTRL1_HOS_DEFAULT (MAX77621_AD_ENABLE | \ #define MAX77621_CPU_CTRL1_HOS_DEFAULT (MAX77621_AD_ENABLE | \
MAX77621_NFSR_ENABLE | \ MAX77621_NFSR_ENABLE | \
MAX77621_SNS_ENABLE | \ MAX77621_SNS_ENABLE | \
MAX77621_RAMP_12mV_PER_US) MAX77621_RAMP_12mV_PER_US)
#define MAX77621_CPU_CTRL2_POR_DEFAULT (MAX77621_T_JUNCTION_120 | \ #define MAX77621_CPU_CTRL2_POR_DEFAULT (MAX77621_T_JUNCTION_120 | \
MAX77621_FT_ENABLE | \ MAX77621_FT_ENABLE | \
MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS | \ MAX77621_CKKADV_TRIP_DISABLE | \
MAX77621_CKKADV_TRIP_150mV_PER_US | \
MAX77621_INDUCTOR_NOMINAL) MAX77621_INDUCTOR_NOMINAL)
#define MAX77621_CPU_CTRL2_HOS_DEFAULT (MAX77621_T_JUNCTION_120 | \ #define MAX77621_CPU_CTRL2_HOS_DEFAULT (MAX77621_T_JUNCTION_120 | \
MAX77621_WDTMR_ENABLE | \ MAX77621_WDTMR_ENABLE | \
MAX77621_CKKADV_TRIP_75mV_PER_US | \ MAX77621_CKKADV_TRIP_75mV_PER_US | \
MAX77621_INDUCTOR_NOMINAL) MAX77621_INDUCTOR_NOMINAL)
#define MAX77621_CTRL_HOS_CFG 0 #define MAX77621_CTRL_HOS_CFG 0
@@ -137,7 +143,7 @@
int max77620_regulator_get_status(u32 id); int max77620_regulator_get_status(u32 id);
int max77620_regulator_config_fps(u32 id); int max77620_regulator_config_fps(u32 id);
int max7762x_regulator_set_voltage(u32 id, u32 mv); int max7762x_regulator_set_voltage(u32 id, u32 uv);
int max7762x_regulator_enable(u32 id, bool enable); int max7762x_regulator_enable(u32 id, bool enable);
void max77620_config_gpio(u32 id, bool enable); void max77620_config_gpio(u32 id, bool enable);
void max77620_config_default(); void max77620_config_default();

View File

@@ -17,8 +17,8 @@
#ifndef _MAX77812_H_ #ifndef _MAX77812_H_
#define _MAX77812_H_ #define _MAX77812_H_
#define MAX77812_PHASE31_CPU_I2C_ADDR 0x31 // 2 Outputs: 3-phase M1 + 1-phase M4. #define MAX77812_PHASE31_CPU_I2C_ADDR 0x31 // High power GPU. 2 Outputs: 3-phase M1 + 1-phase M4.
#define MAX77812_PHASE211_CPU_I2C_ADDR 0x33 // 3 Outputs: 2-phase M1 + 1-phase M3 + 1-phase M4. #define MAX77812_PHASE211_CPU_I2C_ADDR 0x33 // Low power GPU. 3 Outputs: 2-phase M1 + 1-phase M3 + 1-phase M4.
#define MAX77812_REG_RSET 0x00 #define MAX77812_REG_RSET 0x00
#define MAX77812_REG_INT_SRC 0x01 #define MAX77812_REG_INT_SRC 0x01
@@ -66,22 +66,23 @@
#define MAX77812_REG_M2_VOUT_S 0x2C #define MAX77812_REG_M2_VOUT_S 0x2C
#define MAX77812_REG_M3_VOUT_S 0x2D #define MAX77812_REG_M3_VOUT_S 0x2D
#define MAX77812_REG_M4_VOUT_S 0x2E #define MAX77812_REG_M4_VOUT_S 0x2E
#define MAX77812_REG_M1_CFG 0x2F #define MAX77812_REG_M1_CFG 0x2F // HOS: M1_ILIM - 7.2A/4.8A.
#define MAX77812_REG_M2_CFG 0x30 #define MAX77812_REG_M2_CFG 0x30 // HOS: M2_ILIM - 7.2A/4.8A.
#define MAX77812_REG_M3_CFG 0x31 #define MAX77812_REG_M3_CFG 0x31 // HOS: M3_ILIM - 7.2A/4.8A.
#define MAX77812_REG_M4_CFG 0x32 #define MAX77812_REG_M4_CFG 0x32 // HOS: M4_ILIM - 7.2A/4.8A.
#define MAX77812_REG_GLB_CFG1 0x33 #define MAX77812_REG_GLB_CFG1 0x33 // HOS: B_SD_SR/B_SS_SR - 5mV/us.
#define MAX77812_REG_GLB_CFG2 0x34 #define MAX77812_REG_GLB_CFG2 0x34 // HOS: B_RD_SR/B_RU_SR - 5mV/us
#define MAX77812_REG_GLB_CFG3 0x35 #define MAX77812_REG_GLB_CFG3 0x35
/*! Protected area and settings only for MAX77812_REG_VERSION 4 */ /*! Protected area and settings only for MAX77812_ES2_VERSION */
#define MAX77812_REG_GLB_CFG4 0x36 #define MAX77812_REG_GLB_CFG4 0x36
#define MAX77812_REG_GLB_CFG5 0x37 #define MAX77812_REG_GLB_CFG5 0x37 // HOS: 0x3E. Unmasked write.
#define MAX77812_REG_GLB_CFG6 0x38 #define MAX77812_REG_GLB_CFG6 0x38 // HOS: 0x90. Unmasked write.
#define MAX77812_REG_GLB_CFG7 0x39 #define MAX77812_REG_GLB_CFG7 0x39
#define MAX77812_REG_GLB_CFG8 0x3A #define MAX77812_REG_GLB_CFG8 0x3A // HOS: 0x3A. Unmasked write.
#define MAX77812_REG_PROT_ACCESS 0xFD
#define MAX77812_REG_MAX 0xFE #define MAX77812_REG_PROT_ACCESS 0xFD // 0x00: Lock, 0x5A: Unlock.
#define MAX77812_REG_MAX 0xFD
#define MAX77812_REG_EN_CTRL_MASK(n) BIT(n) #define MAX77812_REG_EN_CTRL_MASK(n) BIT(n)
#define MAX77812_START_SLEW_RATE_MASK 0x07 #define MAX77812_START_SLEW_RATE_MASK 0x07

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019-2021 CTCaer * Copyright (c) 2019-2023 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -27,38 +27,31 @@ static bool usb_src = false;
void regulator_5v_enable(u8 dev) void regulator_5v_enable(u8 dev)
{ {
bool tegra_t210 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210;
// The power supply selection from battery or USB is automatic. // The power supply selection from battery or USB is automatic.
if (!reg_5v_dev) if (!reg_5v_dev)
{ {
// Fan and Rail power from battery 5V regulator. // Fan and Rail power from battery 5V regulator.
PINMUX_AUX(PINMUX_AUX_SATA_LED_ACTIVE) = 1; PINMUX_AUX(PINMUX_AUX_SATA_LED_ACTIVE) = 1;
gpio_config(GPIO_PORT_A, GPIO_PIN_5, GPIO_MODE_GPIO); gpio_direction_output(GPIO_PORT_A, GPIO_PIN_5, GPIO_HIGH);
gpio_output_enable(GPIO_PORT_A, GPIO_PIN_5, GPIO_OUTPUT_ENABLE);
gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_HIGH);
// Only Icosa and Iowa have USB 5V VBUS rails. Skip on Hoag/Aula. // Only Icosa has USB 5V VBUS rails.
u32 hw_type = fuse_read_hw_type(); if (tegra_t210)
if (hw_type == FUSE_NX_HW_TYPE_ICOSA ||
hw_type == FUSE_NX_HW_TYPE_IOWA)
{ {
// Fan and Rail power from USB 5V VBUS. // Fan and Rail power from USB 5V VBUS.
PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN0) = PINMUX_LPDR | 1; PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN0) = PINMUX_LPDR | 1;
gpio_config(GPIO_PORT_CC, GPIO_PIN_4, GPIO_MODE_GPIO); gpio_direction_output(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW);
gpio_output_enable(GPIO_PORT_CC, GPIO_PIN_4, GPIO_OUTPUT_ENABLE);
gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW);
} }
// Enable GPIO AO IO rail for T210. // Make sure GPIO IO power is enabled.
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210) PMC(APBDEV_PMC_NO_IOPOWER) &= ~PMC_NO_IOPOWER_GPIO_IO_EN;
{ (void)PMC(APBDEV_PMC_NO_IOPOWER); // Commit write.
// Make sure GPIO power is enabled.
PMC(APBDEV_PMC_NO_IOPOWER) &= ~PMC_NO_IOPOWER_GPIO_IO_EN; // Override power detect for GPIO AO IO rails.
(void)PMC(APBDEV_PMC_NO_IOPOWER); // Commit write. PMC(APBDEV_PMC_PWR_DET_VAL) &= ~PMC_PWR_DET_GPIO_IO_EN;
(void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write.
// Override power detect for GPIO AO IO rails.
PMC(APBDEV_PMC_PWR_DET_VAL) &= ~PMC_PWR_DET_GPIO_IO_EN;
(void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write.
}
usb_src = false; usb_src = false;
} }
reg_5v_dev |= dev; reg_5v_dev |= dev;
@@ -66,36 +59,23 @@ void regulator_5v_enable(u8 dev)
void regulator_5v_disable(u8 dev) void regulator_5v_disable(u8 dev)
{ {
bool tegra_t210 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210;
reg_5v_dev &= ~dev; reg_5v_dev &= ~dev;
if (!reg_5v_dev) if (!reg_5v_dev)
{ {
// Rail power from battery 5V regulator. // Rail power from battery 5V regulator.
gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_LOW); gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_LOW);
gpio_output_enable(GPIO_PORT_A, GPIO_PIN_5, GPIO_OUTPUT_DISABLE);
gpio_config(GPIO_PORT_A, GPIO_PIN_5, GPIO_MODE_SPIO);
PINMUX_AUX(PINMUX_AUX_SATA_LED_ACTIVE) = PINMUX_PARKED | PINMUX_INPUT_ENABLE;
// Only Icosa and Iowa have USB 5V VBUS rails. Skip on Hoag/Aula. // Only Icosa has USB 5V VBUS rails.
u32 hw_type = fuse_read_hw_type(); if (tegra_t210)
if (hw_type == FUSE_NX_HW_TYPE_ICOSA ||
hw_type == FUSE_NX_HW_TYPE_IOWA)
{ {
// Rail power from USB 5V VBUS. // Rail power from USB 5V VBUS.
gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW); gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW);
gpio_output_enable(GPIO_PORT_CC, GPIO_PIN_4, GPIO_OUTPUT_DISABLE);
gpio_config(GPIO_PORT_CC, GPIO_PIN_4, GPIO_MODE_SPIO);
PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN0) = PINMUX_IO_HV | PINMUX_LPDR | PINMUX_PARKED | PINMUX_INPUT_ENABLE;
usb_src = false; usb_src = false;
} }
// GPIO AO IO rails.
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210)
{
PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_GPIO_IO_EN;
(void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write.
}
} }
} }
@@ -106,10 +86,8 @@ bool regulator_5v_get_dev_enabled(u8 dev)
void regulator_5v_usb_src_enable(bool enable) void regulator_5v_usb_src_enable(bool enable)
{ {
// Only for Icosa/Iowa. Skip on Hoag/Aula. // Only for Icosa.
u32 hw_type = fuse_read_hw_type(); if (hw_get_chip_id() != GP_HIDREV_MAJOR_T210)
if (hw_type != FUSE_NX_HW_TYPE_ICOSA &&
hw_type != FUSE_NX_HW_TYPE_IOWA)
return; return;
if (enable && !usb_src) if (enable && !usb_src)

View File

@@ -1,7 +1,7 @@
/* /*
* PMIC Real Time Clock driver for Nintendo Switch's MAX77620-RTC * PMIC Real Time Clock driver for Nintendo Switch's MAX77620-RTC
* *
* Copyright (c) 2018-2019 CTCaer * Copyright (c) 2018-2022 CTCaer
* Copyright (c) 2019 shchmue * Copyright (c) 2019 shchmue
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
@@ -19,7 +19,14 @@
#include <rtc/max77620-rtc.h> #include <rtc/max77620-rtc.h>
#include <soc/i2c.h> #include <soc/i2c.h>
#include <utils/util.h> #include <soc/pmc.h>
#include <soc/timer.h>
#include <soc/t210.h>
void max77620_rtc_prep_read()
{
i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_UPDATE0_REG, MAX77620_RTC_READ_UPDATE);
}
void max77620_rtc_get_time(rtc_time_t *time) void max77620_rtc_get_time(rtc_time_t *time)
{ {
@@ -35,7 +42,7 @@ void max77620_rtc_get_time(rtc_time_t *time)
// Get time. // Get time.
time->sec = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_SEC_REG) & 0x7F; time->sec = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_SEC_REG) & 0x7F;
time->min = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_MIN_REG) & 0x7F; time->min = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_MIN_REG) & 0x7F;
u8 hour = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_HOUR_REG); u8 hour = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_HOUR_REG);
time->hour = hour & 0x1F; time->hour = hour & 0x1F;
if (!(val & MAX77620_RTC_24H) && (hour & MAX77620_RTC_HOUR_PM_MASK)) if (!(val & MAX77620_RTC_24H) && (hour & MAX77620_RTC_HOUR_PM_MASK))
@@ -53,7 +60,7 @@ void max77620_rtc_get_time(rtc_time_t *time)
} }
// Get date. // Get date.
time->day = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_DATE_REG) & 0x1f; time->day = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_DATE_REG) & 0x1f;
time->month = (i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_MONTH_REG) & 0xF) - 1; time->month = (i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_MONTH_REG) & 0xF) - 1;
time->year = (i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_YEAR_REG) & 0x7F) + 2000; time->year = (i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_YEAR_REG) & 0x7F) + 2000;
} }
@@ -64,6 +71,7 @@ void max77620_rtc_stop_alarm()
// Update RTC regs from RTC clock. // Update RTC regs from RTC clock.
i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_UPDATE0_REG, MAX77620_RTC_READ_UPDATE); i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_UPDATE0_REG, MAX77620_RTC_READ_UPDATE);
msleep(16);
// Stop alarm for both ALARM1 and ALARM2. Horizon uses ALARM2. // Stop alarm for both ALARM1 and ALARM2. Horizon uses ALARM2.
for (int i = 0; i < (MAX77620_RTC_NR_TIME_REGS * 2); i++) for (int i = 0; i < (MAX77620_RTC_NR_TIME_REGS * 2); i++)
@@ -82,9 +90,9 @@ void max77620_rtc_epoch_to_date(u32 epoch, rtc_time_t *time)
u32 tmp, edays, year, month, day; u32 tmp, edays, year, month, day;
// Set time. // Set time.
time->sec = epoch % 60; time->sec = epoch % 60;
epoch /= 60; epoch /= 60;
time->min = epoch % 60; time->min = epoch % 60;
epoch /= 60; epoch /= 60;
time->hour = epoch % 24; time->hour = epoch % 24;
epoch /= 24; epoch /= 24;
@@ -99,14 +107,14 @@ void max77620_rtc_epoch_to_date(u32 epoch, rtc_time_t *time)
day = edays - month * 30 - month * 601 / 1000; day = edays - month * 30 - month * 601 / 1000;
// Month/Year offset. // Month/Year offset.
if(month < 14) if (month < 14)
{ {
year -= 4716; year -= 4716;
month--; month--;
} }
else else
{ {
year -= 4715; year -= 4715;
month -= 13; month -= 13;
} }
@@ -129,13 +137,13 @@ u32 max77620_rtc_date_to_epoch(const rtc_time_t *time)
month = time->month; month = time->month;
// Month/Year offset. // Month/Year offset.
if(month < 3) if (month < 3)
{ {
month += 12; month += 12;
year--; year--;
} }
epoch = (365 * year) + (year >> 2) - (year / 100) + (year / 400); // Years to days. epoch = (365 * year) + (year >> 2) - (year / 100) + (year / 400); // Years to days.
epoch += (30 * month) + (3 * (month + 1) / 5) + time->day; // Months to days. epoch += (30 * month) + (3 * (month + 1) / 5) + time->day; // Months to days.
epoch -= 719561; // Epoch time is 1/1/1970. epoch -= 719561; // Epoch time is 1/1/1970.
@@ -145,3 +153,45 @@ u32 max77620_rtc_date_to_epoch(const rtc_time_t *time)
return epoch; return epoch;
} }
void max77620_rtc_set_reboot_reason(rtc_reboot_reason_t *rr)
{
max77620_rtc_stop_alarm();
// Set reboot reason.
i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM1_YEAR_REG, rr->enc.val1);
i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM2_YEAR_REG, rr->enc.val2);
// Set reboot reason magic.
i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM1_WEEKDAY_REG, RTC_REBOOT_REASON_MAGIC);
i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM2_WEEKDAY_REG, RTC_REBOOT_REASON_MAGIC);
// Update RTC clock from RTC regs.
i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_UPDATE0_REG, MAX77620_RTC_WRITE_UPDATE);
msleep(16);
}
bool max77620_rtc_get_reboot_reason(rtc_reboot_reason_t *rr)
{
u8 magic[2];
// Get reboot reason magic.
magic[0] = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM1_WEEKDAY_REG);
magic[1] = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM2_WEEKDAY_REG);
// Magic must be correct and match on both registers.
if (magic[0] != RTC_REBOOT_REASON_MAGIC || magic[0] != magic[1])
return false;
// Reboot reason setter is expected to have updated the actual regs already.
rr->enc.val1 = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM1_YEAR_REG);
rr->enc.val2 = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM2_YEAR_REG);
// Clear magic and update actual regs.
i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM1_WEEKDAY_REG, 0);
i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM2_WEEKDAY_REG, 0);
i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_UPDATE0_REG, MAX77620_RTC_WRITE_UPDATE);
// Return reboot reason. False if [config] was selected.
return true;
}

View File

@@ -1,7 +1,7 @@
/* /*
* PMIC Real Time Clock driver for Nintendo Switch's MAX77620-RTC * PMIC Real Time Clock driver for Nintendo Switch's MAX77620-RTC
* *
* Copyright (c) 2018 CTCaer * Copyright (c) 2018-2022 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -25,6 +25,8 @@
#define MAX77620_RTC_NR_TIME_REGS 7 #define MAX77620_RTC_NR_TIME_REGS 7
#define MAX77620_RTC_RTCINT_REG 0x00
#define MAX77620_RTC_RTCINTM_REG 0x01
#define MAX77620_RTC_CONTROLM_REG 0x02 #define MAX77620_RTC_CONTROLM_REG 0x02
#define MAX77620_RTC_CONTROL_REG 0x03 #define MAX77620_RTC_CONTROL_REG 0x03
#define MAX77620_RTC_BIN_FORMAT BIT(0) #define MAX77620_RTC_BIN_FORMAT BIT(0)
@@ -34,6 +36,9 @@
#define MAX77620_RTC_WRITE_UPDATE BIT(0) #define MAX77620_RTC_WRITE_UPDATE BIT(0)
#define MAX77620_RTC_READ_UPDATE BIT(4) #define MAX77620_RTC_READ_UPDATE BIT(4)
#define MAX77620_RTC_UPDATE1_REG 0x05
#define MAX77620_RTC_RTCSMPL_REG 0x06
#define MAX77620_RTC_SEC_REG 0x07 #define MAX77620_RTC_SEC_REG 0x07
#define MAX77620_RTC_MIN_REG 0x08 #define MAX77620_RTC_MIN_REG 0x08
#define MAX77620_RTC_HOUR_REG 0x09 #define MAX77620_RTC_HOUR_REG 0x09
@@ -69,9 +74,45 @@ typedef struct _rtc_time_t {
u16 year; u16 year;
} rtc_time_t; } rtc_time_t;
#define RTC_REBOOT_REASON_MAGIC 0x77 // 7-bit reg.
enum {
REBOOT_REASON_NOP = 0, // Use [config].
REBOOT_REASON_SELF = 1, // Use autoboot_idx/autoboot_list.
REBOOT_REASON_MENU = 2, // Force menu.
REBOOT_REASON_UMS = 3, // Force selected UMS partition.
REBOOT_REASON_REC = 4, // Set PMC_SCRATCH0_MODE_RECOVERY and reboot to self.
REBOOT_REASON_PANIC = 5 // Inform bootloader that panic occured if T210B01.
};
typedef struct _rtc_rr_decoded_t
{
u16 reason:4;
u16 autoboot_idx:4;
u16 autoboot_list:1;
u16 ums_idx:3;
} rtc_rr_decoded_t;
typedef struct _rtc_rr_encoded_t
{
u16 val1:6; // 6-bit reg.
u16 val2:6; // 6-bit reg.
} rtc_rr_encoded_t;
typedef struct _rtc_reboot_reason_t
{
union {
rtc_rr_decoded_t dec;
rtc_rr_encoded_t enc;
};
} rtc_reboot_reason_t;
void max77620_rtc_prep_read();
void max77620_rtc_get_time(rtc_time_t *time); void max77620_rtc_get_time(rtc_time_t *time);
void max77620_rtc_stop_alarm(); void max77620_rtc_stop_alarm();
void max77620_rtc_epoch_to_date(u32 epoch, rtc_time_t *time); void max77620_rtc_epoch_to_date(u32 epoch, rtc_time_t *time);
u32 max77620_rtc_date_to_epoch(const rtc_time_t *time); u32 max77620_rtc_date_to_epoch(const rtc_time_t *time);
void max77620_rtc_set_reboot_reason(rtc_reboot_reason_t *rr);
bool max77620_rtc_get_reboot_reason(rtc_reboot_reason_t *rr);
#endif /* _MFD_MAX77620_RTC_H_ */ #endif /* _MFD_MAX77620_RTC_H_ */

View File

@@ -1,8 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2021 CTCaer * Copyright (c) 2018-2022 CTCaer
* Copyright (c) 2018 Atmosphère-NX
* Copyright (c) 2019-2021 shchmue
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -20,13 +18,13 @@
#include <string.h> #include <string.h>
#include "se.h" #include "se.h"
#include "se_t210.h"
#include <memory_map.h> #include <memory_map.h>
#include <mem/heap.h> #include <mem/heap.h>
#include <soc/bpmp.h> #include <soc/bpmp.h>
#include <soc/hw_init.h>
#include <soc/pmc.h> #include <soc/pmc.h>
#include <soc/timer.h>
#include <soc/t210.h> #include <soc/t210.h>
#include <utils/util.h>
typedef struct _se_ll_t typedef struct _se_ll_t
{ {
@@ -35,8 +33,8 @@ typedef struct _se_ll_t
vu32 size; vu32 size;
} se_ll_t; } se_ll_t;
static u32 _se_rsa_mod_sizes[SE_RSA_KEYSLOT_COUNT]; se_ll_t ll_src, ll_dst;
static u32 _se_rsa_exp_sizes[SE_RSA_KEYSLOT_COUNT]; se_ll_t *ll_src_ptr, *ll_dst_ptr; // Must be u32 aligned.
static void _gf256_mul_x(void *block) static void _gf256_mul_x(void *block)
{ {
@@ -72,67 +70,57 @@ static void _gf256_mul_x_le(void *block)
static void _se_ll_init(se_ll_t *ll, u32 addr, u32 size) static void _se_ll_init(se_ll_t *ll, u32 addr, u32 size)
{ {
ll->num = 0; ll->num = 0;
ll->addr = addr; ll->addr = addr;
ll->size = size; ll->size = size;
} }
static void _se_ll_set(se_ll_t *dst, se_ll_t *src) static void _se_ll_set(se_ll_t *src, se_ll_t *dst)
{ {
SE(SE_IN_LL_ADDR_REG) = (u32)src; SE(SE_IN_LL_ADDR_REG) = (u32)src;
SE(SE_OUT_LL_ADDR_REG) = (u32)dst; SE(SE_OUT_LL_ADDR_REG) = (u32)dst;
} }
static int _se_wait() static int _se_wait()
{ {
bool tegra_t210 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210;
// Wait for operation to be done.
while (!(SE(SE_INT_STATUS_REG) & SE_INT_OP_DONE)) while (!(SE(SE_INT_STATUS_REG) & SE_INT_OP_DONE))
; ;
if (SE(SE_INT_STATUS_REG) & SE_INT_ERR_STAT ||
(SE(SE_STATUS_REG) & SE_STATUS_STATE_MASK) != SE_STATUS_STATE_IDLE || // Check for errors.
SE(SE_ERR_STATUS_REG) != 0) if ((SE(SE_INT_STATUS_REG) & SE_INT_ERR_STAT) ||
(SE(SE_STATUS_REG) & SE_STATUS_STATE_MASK) != SE_STATUS_STATE_IDLE ||
(SE(SE_ERR_STATUS_REG) != 0)
)
{
return 0; return 0;
return 1;
}
se_ll_t *ll_dst, *ll_src;
static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size, bool is_oneshot)
{
ll_dst = NULL;
ll_src = NULL;
if (dst)
{
ll_dst = (se_ll_t *)malloc(sizeof(se_ll_t));
_se_ll_init(ll_dst, (u32)dst, dst_size);
} }
if (src) // T210B01: IRAM/TZRAM/DRAM AHB coherency WAR.
if (!tegra_t210 && ll_dst_ptr)
{ {
ll_src = (se_ll_t *)malloc(sizeof(se_ll_t)); u32 timeout = get_tmr_us() + 1000000;
_se_ll_init(ll_src, (u32)src, src_size); // Ensure data is out from SE.
} while (SE(SE_STATUS_REG) & SE_STATUS_MEM_IF_BUSY)
{
if (get_tmr_us() > timeout)
return 0;
usleep(1);
}
_se_ll_set(ll_dst, ll_src); // Ensure data is out from AHB.
if (ll_dst_ptr->addr >= DRAM_START)
SE(SE_ERR_STATUS_REG) = SE(SE_ERR_STATUS_REG); {
SE(SE_INT_STATUS_REG) = SE(SE_INT_STATUS_REG); timeout = get_tmr_us() + 200000;
while (AHB_GIZMO(AHB_ARBITRATION_AHB_MEM_WRQUE_MST_ID) & MEM_WRQUE_SE_MST_ID)
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); {
if (get_tmr_us() > timeout)
SE(SE_OPERATION_REG) = op; return 0;
usleep(1);
if (is_oneshot) }
{ }
int res = _se_wait();
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
if (src)
free(ll_src);
if (dst)
free(ll_dst);
return res;
} }
return 1; return 1;
@@ -142,22 +130,48 @@ static int _se_execute_finalize()
{ {
int res = _se_wait(); int res = _se_wait();
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); // Invalidate data after OP is done.
bpmp_mmu_maintenance(BPMP_MMU_MAINT_INVALID_WAY, false);
if (ll_src) ll_src_ptr = NULL;
{ ll_dst_ptr = NULL;
free(ll_src);
ll_src = NULL;
}
if (ll_dst)
{
free(ll_dst);
ll_dst = NULL;
}
return res; return res;
} }
static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size, bool is_oneshot)
{
ll_src_ptr = NULL;
ll_dst_ptr = NULL;
if (src)
{
ll_src_ptr = &ll_src;
_se_ll_init(ll_src_ptr, (u32)src, src_size);
}
if (dst)
{
ll_dst_ptr = &ll_dst;
_se_ll_init(ll_dst_ptr, (u32)dst, dst_size);
}
_se_ll_set(ll_src_ptr, ll_dst_ptr);
SE(SE_ERR_STATUS_REG) = SE(SE_ERR_STATUS_REG);
SE(SE_INT_STATUS_REG) = SE(SE_INT_STATUS_REG);
// Flush data before starting OP.
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLEAN_WAY, false);
SE(SE_OPERATION_REG) = op;
if (is_oneshot)
return _se_execute_finalize();
return 1;
}
static int _se_execute_oneshot(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size) static int _se_execute_oneshot(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size)
{ {
return _se_execute(op, dst, dst_size, src, src_size, true); return _se_execute(op, dst, dst_size, src, src_size, true);
@@ -168,8 +182,7 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr
if (!src || !dst) if (!src || !dst)
return 0; return 0;
u8 *block = (u8 *)malloc(SE_AES_BLOCK_SIZE); u8 *block = (u8 *)calloc(1, SE_AES_BLOCK_SIZE);
memset(block, 0, SE_AES_BLOCK_SIZE);
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1; SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
@@ -181,7 +194,7 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr
return res; return res;
} }
static void _se_aes_ctr_set(const void *ctr) static void _se_aes_ctr_set(void *ctr)
{ {
u32 data[SE_AES_IV_SIZE / 4]; u32 data[SE_AES_IV_SIZE / 4];
memcpy(data, ctr, SE_AES_IV_SIZE); memcpy(data, ctr, SE_AES_IV_SIZE);
@@ -194,72 +207,12 @@ void se_rsa_acc_ctrl(u32 rs, u32 flags)
{ {
if (flags & SE_RSA_KEY_TBL_DIS_KEY_ACCESS_FLAG) if (flags & SE_RSA_KEY_TBL_DIS_KEY_ACCESS_FLAG)
SE(SE_RSA_KEYTABLE_ACCESS_REG + 4 * rs) = SE(SE_RSA_KEYTABLE_ACCESS_REG + 4 * rs) =
(((flags >> 4) & SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG) |(flags & SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG)) ^ (((flags >> 4) & SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG) | (flags & SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG)) ^
SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_USE_FLAG; SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_USE_FLAG;
if (flags & SE_RSA_KEY_LOCK_FLAG) if (flags & SE_RSA_KEY_LOCK_FLAG)
SE(SE_RSA_SECURITY_PERKEY_REG) &= ~BIT(rs); SE(SE_RSA_SECURITY_PERKEY_REG) &= ~BIT(rs);
} }
// se_rsa_key_set() was derived from Atmosphère's set_rsa_keyslot
void se_rsa_key_set(u32 ks, const void *mod, u32 mod_size, const void *exp, u32 exp_size)
{
u32 *data = (u32 *)mod;
for (u32 i = 0; i < mod_size / 4; i++)
{
SE(SE_RSA_KEYTABLE_ADDR_REG) = RSA_KEY_NUM(ks) | SE_RSA_KEYTABLE_TYPE(RSA_KEY_TYPE_MOD) | i;
SE(SE_RSA_KEYTABLE_DATA_REG) = byte_swap_32(data[mod_size / 4 - i - 1]);
}
data = (u32 *)exp;
for (u32 i = 0; i < exp_size / 4; i++)
{
SE(SE_RSA_KEYTABLE_ADDR_REG) = RSA_KEY_NUM(ks) | SE_RSA_KEYTABLE_TYPE(RSA_KEY_TYPE_EXP) | i;
SE(SE_RSA_KEYTABLE_DATA_REG) = byte_swap_32(data[exp_size / 4 - i - 1]);
}
_se_rsa_mod_sizes[ks] = mod_size;
_se_rsa_exp_sizes[ks] = exp_size;
}
// se_rsa_key_clear() was derived from Atmosphère's clear_rsa_keyslot
void se_rsa_key_clear(u32 ks)
{
for (u32 i = 0; i < SE_RSA2048_DIGEST_SIZE / 4; i++)
{
SE(SE_RSA_KEYTABLE_ADDR_REG) = RSA_KEY_NUM(ks) | SE_RSA_KEYTABLE_TYPE(RSA_KEY_TYPE_MOD) | i;
SE(SE_RSA_KEYTABLE_DATA_REG) = 0;
}
for (u32 i = 0; i < SE_RSA2048_DIGEST_SIZE / 4; i++)
{
SE(SE_RSA_KEYTABLE_ADDR_REG) = RSA_KEY_NUM(ks) | SE_RSA_KEYTABLE_TYPE(RSA_KEY_TYPE_EXP) | i;
SE(SE_RSA_KEYTABLE_DATA_REG) = 0;
}
}
// se_rsa_exp_mod() was derived from Atmosphère's se_synchronous_exp_mod and se_get_exp_mod_output
int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size)
{
int res;
u8 stack_buf[SE_RSA2048_DIGEST_SIZE];
for (u32 i = 0; i < src_size; i++)
stack_buf[i] = *((u8 *)src + src_size - i - 1);
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_RSA) | SE_CONFIG_DST(DST_RSAREG);
SE(SE_RSA_CONFIG) = RSA_KEY_SLOT(ks);
SE(SE_RSA_KEY_SIZE_REG) = (_se_rsa_mod_sizes[ks] >> 6) - 1;
SE(SE_RSA_EXP_SIZE_REG) = _se_rsa_exp_sizes[ks] >> 2;
res = _se_execute_oneshot(SE_OP_START, NULL, 0, stack_buf, src_size);
// Copy output hash.
u32 *dst32 = (u32 *)dst;
for (u32 i = 0; i < dst_size / 4; i++)
dst32[dst_size / 4 - i - 1] = byte_swap_32(SE(SE_RSA_OUTPUT_REG + (i * 4)));
return res;
}
void se_key_acc_ctrl(u32 ks, u32 flags) void se_key_acc_ctrl(u32 ks, u32 flags)
{ {
if (flags & SE_KEY_TBL_DIS_KEY_ACCESS_FLAG) if (flags & SE_KEY_TBL_DIS_KEY_ACCESS_FLAG)
@@ -273,7 +226,7 @@ u32 se_key_acc_ctrl_get(u32 ks)
return SE(SE_CRYPTO_KEYTABLE_ACCESS_REG + 4 * ks); return SE(SE_CRYPTO_KEYTABLE_ACCESS_REG + 4 * ks);
} }
void se_aes_key_set(u32 ks, const void *key, u32 size) void se_aes_key_set(u32 ks, void *key, u32 size)
{ {
u32 data[SE_AES_MAX_KEY_SIZE / 4]; u32 data[SE_AES_MAX_KEY_SIZE / 4];
memcpy(data, key, size); memcpy(data, key, size);
@@ -285,13 +238,7 @@ void se_aes_key_set(u32 ks, const void *key, u32 size)
} }
} }
void se_aes_key_partial_set(u32 ks, u32 index, u32 data) void se_aes_iv_set(u32 ks, void *iv)
{
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | index;
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = data;
}
void se_aes_iv_set(u32 ks, const void *iv)
{ {
u32 data[SE_AES_IV_SIZE / 4]; u32 data[SE_AES_IV_SIZE / 4];
memcpy(data, iv, SE_AES_IV_SIZE); memcpy(data, iv, SE_AES_IV_SIZE);
@@ -334,10 +281,11 @@ void se_aes_iv_clear(u32 ks)
} }
} }
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input) int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input)
{ {
SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_KEYTABLE); SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_KEYTABLE);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT); SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1; SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
SE(SE_CRYPTO_KEYTABLE_DST_REG) = SE_KEYTABLE_DST_KEY_INDEX(ks_dst) | SE_KEYTABLE_DST_WORD_QUAD(KEYS_0_3); SE(SE_CRYPTO_KEYTABLE_DST_REG) = SE_KEYTABLE_DST_KEY_INDEX(ks_dst) | SE_KEYTABLE_DST_WORD_QUAD(KEYS_0_3);
@@ -365,14 +313,14 @@ int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src,
if (enc) if (enc)
{ {
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) | SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) |
SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_XOR_POS(XOR_TOP); SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_XOR_POS(XOR_TOP);
} }
else else
{ {
SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY); SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVMEM) | SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVMEM) |
SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM); SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM);
} }
SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1; SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1;
return _se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size); return _se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size);
@@ -383,15 +331,16 @@ int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src)
return se_aes_crypt_ecb(ks, enc, dst, SE_AES_BLOCK_SIZE, src, SE_AES_BLOCK_SIZE); return se_aes_crypt_ecb(ks, enc, dst, SE_AES_BLOCK_SIZE, src, SE_AES_BLOCK_SIZE);
} }
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, const void *ctr) int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr)
{ {
SE(SE_SPARE_REG) = SE_ECO(SE_ERRATA_FIX_ENABLE); SE(SE_SPARE_REG) = SE_ECO(SE_ERRATA_FIX_ENABLE);
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) |
SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_LNR_CTR) | SE_CRYPTO_CTR_CNTN(1); SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_LNR_CTR) |
SE_CRYPTO_CTR_CNTN(1);
_se_aes_ctr_set(ctr); _se_aes_ctr_set(ctr);
u32 src_size_aligned = ALIGN_DOWN(src_size, 0x10); u32 src_size_aligned = src_size & 0xFFFFFFF0;
u32 src_size_delta = src_size & 0xF; u32 src_size_delta = src_size & 0xF;
if (src_size_aligned) if (src_size_aligned)
@@ -409,89 +358,69 @@ int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_s
return 1; return 1;
} }
// random calls were derived from Atmosphère's int se_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, void *src, u32 secsize)
int se_initialize_rng()
{ {
static bool initialized = false; int res = 0;
u8 *tweak = (u8 *)malloc(SE_AES_BLOCK_SIZE);
u8 *pdst = (u8 *)dst;
u8 *psrc = (u8 *)src;
if (initialized) // Generate tweak.
return 1;
u8 *output_buf = (u8 *)malloc(0x10);
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_MODE(MODE_FORCE_INSTANTION) | SE_RNG_CONFIG_SRC(SRC_ENTROPY);
SE(SE_RNG_RESEED_INTERVAL_REG) = 70001;
SE(SE_RNG_SRC_CONFIG_REG) = SE_RNG_SRC_CONFIG_ENTR_SRC(RO_ENTR_ENABLE) |
SE_RNG_SRC_CONFIG_ENTR_SRC_LOCK(RO_ENTR_LOCK_ENABLE);
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 0;
int res =_se_execute_oneshot(SE_OP_START, output_buf, 0x10, NULL, 0);
free(output_buf);
if (res)
initialized = true;
return res;
}
int se_generate_random(void *dst, u32 size)
{
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_MODE(MODE_NORMAL) | SE_RNG_CONFIG_SRC(SRC_ENTROPY);
u32 num_blocks = size >> 4;
u32 aligned_size = num_blocks << 4;
if (num_blocks)
{
SE(SE_CRYPTO_BLOCK_COUNT_REG) = num_blocks - 1;
if (!_se_execute_oneshot(SE_OP_START, dst, aligned_size, NULL, 0))
return 0;
}
if (size > aligned_size)
return _se_execute_one_block(SE_OP_START, dst + aligned_size, size - aligned_size, NULL, 0);
return 1;
}
int se_generate_random_key(u32 ks_dst, u32 ks_src)
{
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) |
SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_MODE(MODE_NORMAL) | SE_RNG_CONFIG_SRC(SRC_ENTROPY);
SE(SE_CRYPTO_KEYTABLE_DST_REG) = SE_KEYTABLE_DST_KEY_INDEX(ks_dst);
if (!_se_execute_oneshot(SE_OP_START, NULL, 0, NULL, 0))
return 0;
SE(SE_CRYPTO_KEYTABLE_DST_REG) = SE_KEYTABLE_DST_KEY_INDEX(ks_dst) | 1;
if (!_se_execute_oneshot(SE_OP_START, NULL, 0, NULL, 0))
return 0;
return 1;
}
int se_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, const void *src, u32 sec_size)
{
u8 tweak[0x10];
u8 orig_tweak[0x10];
u32 *pdst = (u32 *)dst;
u32 *psrc = (u32 *)src;
u32 *ptweak = (u32 *)tweak;
//Generate tweak.
for (int i = 0xF; i >= 0; i--) for (int i = 0xF; i >= 0; i--)
{ {
tweak[i] = sec & 0xFF; tweak[i] = sec & 0xFF;
sec >>= 8; sec >>= 8;
} }
if (!se_aes_crypt_block_ecb(tweak_ks, ENCRYPT, tweak, tweak)) if (!se_aes_crypt_block_ecb(tweak_ks, ENCRYPT, tweak, tweak))
return 0; goto out;
memcpy(orig_tweak, tweak, 0x10);
// We are assuming a 0x10-aligned sector size in this implementation. // We are assuming a 0x10-aligned sector size in this implementation.
for (u32 i = 0; i < sec_size / 0x10; i++) for (u32 i = 0; i < secsize / SE_AES_BLOCK_SIZE; i++)
{
for (u32 j = 0; j < SE_AES_BLOCK_SIZE; j++)
pdst[j] = psrc[j] ^ tweak[j];
if (!se_aes_crypt_block_ecb(crypt_ks, enc, pdst, pdst))
goto out;
for (u32 j = 0; j < SE_AES_BLOCK_SIZE; j++)
pdst[j] = pdst[j] ^ tweak[j];
_gf256_mul_x(tweak);
psrc += SE_AES_BLOCK_SIZE;
pdst += SE_AES_BLOCK_SIZE;
}
res = 1;
out:;
free(tweak);
return res;
}
int se_aes_xts_crypt_sec_nx(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, u8 *tweak, bool regen_tweak, u32 tweak_exp, void *dst, void *src, u32 sec_size)
{
u32 *pdst = (u32 *)dst;
u32 *psrc = (u32 *)src;
u32 *ptweak = (u32 *)tweak;
if (regen_tweak)
{
for (int i = 0xF; i >= 0; i--)
{
tweak[i] = sec & 0xFF;
sec >>= 8;
}
if (!se_aes_crypt_block_ecb(tweak_ks, ENCRYPT, tweak, tweak))
return 0;
}
// tweak_exp allows using a saved tweak to reduce _gf256_mul_x_le calls.
for (u32 i = 0; i < (tweak_exp << 5); i++)
_gf256_mul_x_le(tweak);
u8 orig_tweak[SE_KEY_128_SIZE] __attribute__((aligned(4)));
memcpy(orig_tweak, tweak, SE_KEY_128_SIZE);
// We are assuming a 16 sector aligned size in this implementation.
for (u32 i = 0; i < (sec_size >> 4); i++)
{ {
for (u32 j = 0; j < 4; j++) for (u32 j = 0; j < 4; j++)
pdst[j] = psrc[j] ^ ptweak[j]; pdst[j] = psrc[j] ^ ptweak[j];
@@ -506,7 +435,7 @@ int se_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst
pdst = (u32 *)dst; pdst = (u32 *)dst;
ptweak = (u32 *)orig_tweak; ptweak = (u32 *)orig_tweak;
for (u32 i = 0; i < sec_size / 0x10; i++) for (u32 i = 0; i < (sec_size >> 4); i++)
{ {
for (u32 j = 0; j < 4; j++) for (u32 j = 0; j < 4; j++)
pdst[j] = pdst[j] ^ ptweak[j]; pdst[j] = pdst[j] ^ ptweak[j];
@@ -518,73 +447,18 @@ int se_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst
return 1; return 1;
} }
int se_aes_xts_crypt(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, const void *src, u32 sec_size, u32 num_secs) int se_aes_xts_crypt(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, void *src, u32 secsize, u32 num_secs)
{ {
u8 *pdst = (u8 *)dst; u8 *pdst = (u8 *)dst;
u8 *psrc = (u8 *)src; u8 *psrc = (u8 *)src;
for (u32 i = 0; i < num_secs; i++) for (u32 i = 0; i < num_secs; i++)
if (!se_aes_xts_crypt_sec(tweak_ks, crypt_ks, enc, sec + i, pdst + sec_size * i, psrc + sec_size * i, sec_size)) if (!se_aes_xts_crypt_sec(tweak_ks, crypt_ks, enc, sec + i, pdst + secsize * i, psrc + secsize * i, secsize))
return 0; return 0;
return 1; return 1;
} }
// se_aes_cmac() was derived from Atmosphère's se_compute_aes_cmac
int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size)
{
int res = 0;
u8 *key = (u8 *)calloc(0x10, 1);
u8 *last_block = (u8 *)calloc(0x10, 1);
// generate derived key
if (!se_aes_crypt_block_ecb(ks, ENCRYPT, key, key))
goto out;
_gf256_mul_x(key);
if (src_size & 0xF)
_gf256_mul_x(key);
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_HASHREG);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_INPUT_SEL(INPUT_MEMORY) |
SE_CRYPTO_XOR_POS(XOR_TOP) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) | SE_CRYPTO_HASH(HASH_ENABLE) |
SE_CRYPTO_CORE_SEL(CORE_ENCRYPT);
se_aes_iv_clear(ks);
u32 num_blocks = (src_size + 0xf) >> 4;
if (num_blocks > 1)
{
SE(SE_CRYPTO_BLOCK_COUNT_REG) = num_blocks - 2;
if (!_se_execute_oneshot(SE_OP_START, NULL, 0, src, src_size))
goto out;
SE(SE_CRYPTO_CONFIG_REG) |= SE_CRYPTO_IV_SEL(IV_UPDATED);
}
if (src_size & 0xf)
{
memcpy(last_block, src + (src_size & ~0xf), src_size & 0xf);
last_block[src_size & 0xf] = 0x80;
}
else if (src_size >= 0x10)
{
memcpy(last_block, src + src_size - 0x10, 0x10);
}
for (u32 i = 0; i < 0x10; i++)
last_block[i] ^= key[i];
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 0;
res = _se_execute_oneshot(SE_OP_START, NULL, 0, last_block, 0x10);
u32 *dst32 = (u32 *)dst;
for (u32 i = 0; i < (dst_size >> 2); i++)
dst32[i] = SE(SE_HASH_RESULT_REG + (i << 2));
out:;
free(key);
free(last_block);
return res;
}
int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot) int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot)
{ {
int res; int res;
@@ -674,6 +548,80 @@ int se_calc_sha256_finalize(void *hash, u32 *msg_left)
return res; return res;
} }
int se_gen_prng128(void *dst)
{
// Setup config for X931 PRNG.
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_HASH(HASH_DISABLE) | SE_CRYPTO_XOR_POS(XOR_BYPASS) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_SRC(SRC_ENTROPY) | SE_RNG_CONFIG_MODE(MODE_NORMAL);
//SE(SE_RNG_SRC_CONFIG_REG) =
// SE_RNG_SRC_CONFIG_ENTR_SRC(RO_ENTR_ENABLE) | SE_RNG_SRC_CONFIG_ENTR_SRC_LOCK(RO_ENTR_LOCK_ENABLE);
SE(SE_RNG_RESEED_INTERVAL_REG) = 1;
SE(SE_CRYPTO_BLOCK_COUNT_REG) = (16 >> 4) - 1;
// Trigger the operation.
return _se_execute_oneshot(SE_OP_START, dst, 16, NULL, 0);
}
void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize)
{
u8 *aligned_buf = (u8 *)ALIGN((u32)buf, 0x40);
// Set Secure Random Key.
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_SRK);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(0) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_SRC(SRC_ENTROPY) | SE_RNG_CONFIG_MODE(MODE_FORCE_RESEED);
SE(SE_CRYPTO_LAST_BLOCK) = 0;
_se_execute_oneshot(SE_OP_START, NULL, 0, NULL, 0);
// Save AES keys.
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
for (u32 i = 0; i < SE_AES_KEYSLOT_COUNT; i++)
{
SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(AES_KEYTABLE) | SE_KEYTABLE_DST_KEY_INDEX(i) |
SE_CONTEXT_AES_KEY_INDEX(0) | SE_CONTEXT_AES_WORD_QUAD(KEYS_0_3);
SE(SE_CRYPTO_LAST_BLOCK) = 0;
_se_execute_oneshot(SE_OP_CTX_SAVE, aligned_buf, SE_AES_BLOCK_SIZE, NULL, 0);
memcpy(keys + i * keysize, aligned_buf, SE_AES_BLOCK_SIZE);
if (keysize > SE_KEY_128_SIZE)
{
SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(AES_KEYTABLE) | SE_KEYTABLE_DST_KEY_INDEX(i) |
SE_CONTEXT_AES_KEY_INDEX(0) | SE_CONTEXT_AES_WORD_QUAD(KEYS_4_7);
SE(SE_CRYPTO_LAST_BLOCK) = 0;
_se_execute_oneshot(SE_OP_CTX_SAVE, aligned_buf, SE_AES_BLOCK_SIZE, NULL, 0);
memcpy(keys + i * keysize + SE_AES_BLOCK_SIZE, aligned_buf, SE_AES_BLOCK_SIZE);
}
}
// Save SRK to PMC secure scratches.
SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(SRK);
SE(SE_CRYPTO_LAST_BLOCK) = 0;
_se_execute_oneshot(SE_OP_CTX_SAVE, NULL, 0, NULL, 0);
// End context save.
SE(SE_CONFIG_REG) = 0;
_se_execute_oneshot(SE_OP_CTX_SAVE, NULL, 0, NULL, 0);
// Get SRK.
u32 srk[4];
srk[0] = PMC(APBDEV_PMC_SECURE_SCRATCH4);
srk[1] = PMC(APBDEV_PMC_SECURE_SCRATCH5);
srk[2] = PMC(APBDEV_PMC_SECURE_SCRATCH6);
srk[3] = PMC(APBDEV_PMC_SECURE_SCRATCH7);
// Decrypt context.
se_aes_key_clear(3);
se_aes_key_set(3, srk, SE_KEY_128_SIZE);
se_aes_crypt_cbc(3, DECRYPT, keys, SE_AES_KEYSLOT_COUNT * keysize, keys, SE_AES_KEYSLOT_COUNT * keysize);
se_aes_key_clear(3);
}
int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size) int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size)
{ {
int res = 0; int res = 0;
@@ -718,59 +666,57 @@ out:;
return res; return res;
} }
void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize) // se_aes_cmac() was derived from Atmosphère's se_compute_aes_cmac
int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size)
{ {
u8 *aligned_buf = (u8 *)ALIGN((u32)buf, 0x40); int res = 0;
u8 *key = (u8 *)calloc(0x10, 1);
u8 *last_block = (u8 *)calloc(0x10, 1);
// Set Secure Random Key. // generate derived key
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_SRK); if (!se_aes_crypt_block_ecb(ks, ENCRYPT, key, key))
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(0) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM); goto out;
SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_SRC(SRC_ENTROPY) | SE_RNG_CONFIG_MODE(MODE_FORCE_RESEED); _gf256_mul_x(key);
SE(SE_CRYPTO_LAST_BLOCK) = 0; if (src_size & 0xF)
_se_execute_oneshot(SE_OP_START, NULL, 0, NULL, 0); _gf256_mul_x(key);
// Save AES keys. SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_HASHREG);
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_INPUT_SEL(INPUT_MEMORY) |
SE_CRYPTO_XOR_POS(XOR_TOP) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) | SE_CRYPTO_HASH(HASH_ENABLE) |
SE_CRYPTO_CORE_SEL(CORE_ENCRYPT);
se_aes_iv_clear(ks);
for (u32 i = 0; i < SE_AES_KEYSLOT_COUNT; i++) u32 num_blocks = (src_size + 0xf) >> 4;
if (num_blocks > 1)
{ {
SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(AES_KEYTABLE) | SE_KEYTABLE_DST_KEY_INDEX(i) | SE(SE_CRYPTO_BLOCK_COUNT_REG) = num_blocks - 2;
SE_CONTEXT_AES_KEY_INDEX(0) | SE_CONTEXT_AES_WORD_QUAD(KEYS_0_3); if (!_se_execute_oneshot(SE_OP_START, NULL, 0, src, src_size))
goto out;
SE(SE_CRYPTO_LAST_BLOCK) = 0; SE(SE_CRYPTO_CONFIG_REG) |= SE_CRYPTO_IV_SEL(IV_UPDATED);
_se_execute_oneshot(SE_OP_CTX_SAVE, aligned_buf, SE_AES_BLOCK_SIZE, NULL, 0);
memcpy(keys + i * keysize, aligned_buf, SE_AES_BLOCK_SIZE);
if (keysize > SE_KEY_128_SIZE)
{
SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(AES_KEYTABLE) | SE_KEYTABLE_DST_KEY_INDEX(i) |
SE_CONTEXT_AES_KEY_INDEX(0) | SE_CONTEXT_AES_WORD_QUAD(KEYS_4_7);
SE(SE_CRYPTO_LAST_BLOCK) = 0;
_se_execute_oneshot(SE_OP_CTX_SAVE, aligned_buf, SE_AES_BLOCK_SIZE, NULL, 0);
memcpy(keys + i * keysize + SE_AES_BLOCK_SIZE, aligned_buf, SE_AES_BLOCK_SIZE);
}
} }
// Save SRK to PMC secure scratches. if (src_size & 0xf)
SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(SRK); {
SE(SE_CRYPTO_LAST_BLOCK) = 0; memcpy(last_block, src + (src_size & ~0xf), src_size & 0xf);
_se_execute_oneshot(SE_OP_CTX_SAVE, NULL, 0, NULL, 0); last_block[src_size & 0xf] = 0x80;
}
else if (src_size >= 0x10)
{
memcpy(last_block, src + src_size - 0x10, 0x10);
}
// End context save. for (u32 i = 0; i < 0x10; i++)
SE(SE_CONFIG_REG) = 0; last_block[i] ^= key[i];
_se_execute_oneshot(SE_OP_CTX_SAVE, NULL, 0, NULL, 0);
// Get SRK. SE(SE_CRYPTO_BLOCK_COUNT_REG) = 0;
u32 srk[4]; res = _se_execute_oneshot(SE_OP_START, NULL, 0, last_block, 0x10);
srk[0] = PMC(APBDEV_PMC_SECURE_SCRATCH4);
srk[1] = PMC(APBDEV_PMC_SECURE_SCRATCH5);
srk[2] = PMC(APBDEV_PMC_SECURE_SCRATCH6);
srk[3] = PMC(APBDEV_PMC_SECURE_SCRATCH7);
// Decrypt context. u32 *dst32 = (u32 *)dst;
se_aes_key_clear(3); for (u32 i = 0; i < (dst_size >> 2); i++)
se_aes_key_set(3, srk, SE_KEY_128_SIZE); dst32[i] = SE(SE_HASH_RESULT_REG + (i << 2));
se_aes_crypt_cbc(3, DECRYPT, keys, SE_AES_KEYSLOT_COUNT * keysize, keys, SE_AES_KEYSLOT_COUNT * keysize);
se_aes_key_clear(3); out:;
} free(key);
free(last_block);
return res;
}

View File

@@ -1,53 +1,48 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2019-2021 CTCaer * Copyright (c) 2019-2022 CTCaer
* Copyright (c) 2019-2021 shchmue *
* * This program is free software; you can redistribute it and/or modify it
* This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License,
* under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation.
* version 2, as published by the Free Software Foundation. *
* * This program is distributed in the hope it will be useful, but WITHOUT
* This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details.
* more details. *
* * You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>.
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
*/
#ifndef _SE_H_ #ifndef _SE_H_
#define _SE_H_ #define _SE_H_
#include "se_t210.h"
#include <utils/types.h> #include <utils/types.h>
void se_rsa_acc_ctrl(u32 rs, u32 flags); void se_rsa_acc_ctrl(u32 rs, u32 flags);
void se_rsa_key_set(u32 ks, const void *mod, u32 mod_size, const void *exp, u32 exp_size);
void se_rsa_key_clear(u32 ks);
int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size);
void se_key_acc_ctrl(u32 ks, u32 flags); void se_key_acc_ctrl(u32 ks, u32 flags);
u32 se_key_acc_ctrl_get(u32 ks); u32 se_key_acc_ctrl_get(u32 ks);
void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize); void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize);
void se_aes_key_set(u32 ks, const void *key, u32 size); void se_aes_key_set(u32 ks, void *key, u32 size);
void se_aes_iv_set(u32 ks, const void *iv); void se_aes_iv_set(u32 ks, void *iv);
void se_aes_key_partial_set(u32 ks, u32 index, u32 data);
void se_aes_key_get(u32 ks, void *key, u32 size); void se_aes_key_get(u32 ks, void *key, u32 size);
void se_aes_key_clear(u32 ks); void se_aes_key_clear(u32 ks);
void se_aes_iv_clear(u32 ks); void se_aes_iv_clear(u32 ks);
int se_initialize_rng(); int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input);
int se_generate_random(void *dst, u32 size); int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size);
int se_generate_random_key(u32 ks_dst, u32 ks_src); int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size);
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input); int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src);
int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size); int se_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, void *src, u32 secsize);
int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size); int se_aes_xts_crypt_sec_nx(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, u8 *tweak, bool regen_tweak, u32 tweak_exp, void *dst, void *src, u32 sec_size);
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src); int se_aes_xts_crypt(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, void *src, u32 secsize, u32 num_secs);
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, const void *ctr); int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr);
int se_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, const void *src, u32 sec_size); int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot);
int se_aes_xts_crypt(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, const void *src, u32 sec_size, u32 num_secs); int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size);
int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size); int se_calc_sha256_finalize(void *hash, u32 *msg_left);
int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot); int se_gen_prng128(void *dst);
int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size); int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size);
int se_calc_sha256_finalize(void *hash, u32 *msg_left); int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size);
int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size);
#endif #endif

View File

@@ -304,6 +304,8 @@
#define SE_STATUS_STATE_WAIT_OUT 2 #define SE_STATUS_STATE_WAIT_OUT 2
#define SE_STATUS_STATE_WAIT_IN 3 #define SE_STATUS_STATE_WAIT_IN 3
#define SE_STATUS_STATE_MASK 3 #define SE_STATUS_STATE_MASK 3
#define SE_STATUS_MEM_IF_IDLE (0 << 2)
#define SE_STATUS_MEM_IF_BUSY BIT(2)
#define SE_ERR_STATUS_REG 0x804 #define SE_ERR_STATUS_REG 0x804
#define SE_ERR_STATUS_SE_NS_ACCESS BIT(0) #define SE_ERR_STATUS_SE_NS_ACCESS BIT(0)

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2021 CTCaer * Copyright (c) 2018-2023 CTCaer
* Copyright (c) 2018 balika011 * Copyright (c) 2018 balika011
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
@@ -20,16 +20,17 @@
#include "tsec.h" #include "tsec.h"
#include "tsec_t210.h" #include "tsec_t210.h"
#include <memory_map.h>
#include <mem/heap.h>
#include <mem/mc.h>
#include <mem/smmu.h>
#include <sec/se_t210.h> #include <sec/se_t210.h>
#include <soc/bpmp.h> #include <soc/bpmp.h>
#include <soc/clock.h> #include <soc/clock.h>
#include <soc/kfuse.h> #include <soc/kfuse.h>
#include <soc/pmc.h> #include <soc/pmc.h>
#include <soc/t210.h> #include <soc/t210.h>
#include <mem/heap.h> #include <soc/timer.h>
#include <mem/mc.h>
#include <mem/smmu.h>
#include <utils/util.h>
// #include <gfx_utils.h> // #include <gfx_utils.h>
@@ -57,9 +58,9 @@ static int _tsec_dma_pa_to_internal_100(int not_imem, int i_offset, int pa_offse
else else
cmd = TSEC_DMATRFCMD_IMEM; // DMA IMEM (Instruction memmory) cmd = TSEC_DMATRFCMD_IMEM; // DMA IMEM (Instruction memmory)
TSEC(TSEC_DMATRFMOFFS) = i_offset; TSEC(TSEC_DMATRFMOFFS) = i_offset;
TSEC(TSEC_DMATRFFBOFFS) = pa_offset; TSEC(TSEC_DMATRFFBOFFS) = pa_offset;
TSEC(TSEC_DMATRFCMD) = cmd; TSEC(TSEC_DMATRFCMD) = cmd;
return _tsec_dma_wait_idle(); return _tsec_dma_wait_idle();
} }
@@ -76,16 +77,16 @@ int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt)
bpmp_freq_t prev_fid = bpmp_clk_rate_set(BPMP_CLK_NORMAL); bpmp_freq_t prev_fid = bpmp_clk_rate_set(BPMP_CLK_NORMAL);
// Enable clocks. // Enable clocks.
clock_enable_host1x();
usleep(2);
clock_enable_tsec(); clock_enable_tsec();
clock_enable_sor_safe(); clock_enable_sor_safe();
clock_enable_sor0(); clock_enable_sor0();
clock_enable_sor1(); clock_enable_sor1();
clock_enable_kfuse(); clock_enable_kfuse();
kfuse_wait_ready(); kfuse_wait_ready();
// Disable AHB aperture.
mc_disable_ahb_redirect();
if (type == TSEC_FW_TYPE_NEW) if (type == TSEC_FW_TYPE_NEW)
{ {
// Disable all CCPLEX core rails. // Disable all CCPLEX core rails.
@@ -95,23 +96,23 @@ int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt)
pmc_enable_partition(POWER_RAIL_CE3, DISABLE); pmc_enable_partition(POWER_RAIL_CE3, DISABLE);
// Enable AHB aperture and set it to full mmio. // Enable AHB aperture and set it to full mmio.
mc_enable_ahb_redirect(true); mc_enable_ahb_redirect();
} }
// Configure Falcon. // Configure Falcon.
TSEC(TSEC_DMACTL) = 0; TSEC(TSEC_DMACTL) = 0;
TSEC(TSEC_IRQMSET) = TSEC(TSEC_IRQMSET) =
TSEC_IRQMSET_EXT(0xFF) | TSEC_IRQMSET_EXT(0xFF) |
TSEC_IRQMSET_WDTMR | TSEC_IRQMSET_WDTMR |
TSEC_IRQMSET_HALT | TSEC_IRQMSET_HALT |
TSEC_IRQMSET_EXTERR | TSEC_IRQMSET_EXTERR |
TSEC_IRQMSET_SWGEN0 | TSEC_IRQMSET_SWGEN0 |
TSEC_IRQMSET_SWGEN1; TSEC_IRQMSET_SWGEN1;
TSEC(TSEC_IRQDEST) = TSEC(TSEC_IRQDEST) =
TSEC_IRQDEST_EXT(0xFF) | TSEC_IRQDEST_EXT(0xFF) |
TSEC_IRQDEST_HALT | TSEC_IRQDEST_HALT |
TSEC_IRQDEST_EXTERR | TSEC_IRQDEST_EXTERR |
TSEC_IRQDEST_SWGEN0 | TSEC_IRQDEST_SWGEN0 |
TSEC_IRQDEST_SWGEN1; TSEC_IRQDEST_SWGEN1;
TSEC(TSEC_ITFEN) = TSEC_ITFEN_CTXEN | TSEC_ITFEN_MTHDEN; TSEC(TSEC_ITFEN) = TSEC_ITFEN_CTXEN | TSEC_ITFEN_MTHDEN;
if (!_tsec_dma_wait_idle()) if (!_tsec_dma_wait_idle())
@@ -128,6 +129,7 @@ int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt)
fwbuf = (u8 *)malloc(SZ_16K); fwbuf = (u8 *)malloc(SZ_16K);
u8 *fwbuf_aligned = (u8 *)ALIGN((u32)fwbuf, 0x100); u8 *fwbuf_aligned = (u8 *)ALIGN((u32)fwbuf, 0x100);
memcpy(fwbuf_aligned, tsec_ctxt->fw, tsec_ctxt->size); memcpy(fwbuf_aligned, tsec_ctxt->fw, tsec_ctxt->size);
TSEC(TSEC_DMATRFBASE) = (u32)fwbuf_aligned >> 8; TSEC(TSEC_DMATRFBASE) = (u32)fwbuf_aligned >> 8;
} }
@@ -180,7 +182,7 @@ int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt)
mc = page_alloc(1); mc = page_alloc(1);
memcpy(mc, (void *)MC_BASE, SZ_PAGE); memcpy(mc, (void *)MC_BASE, SZ_PAGE);
mc[MC_IRAM_BOM / 4] = 0; mc[MC_IRAM_BOM / 4] = 0;
mc[MC_IRAM_TOM / 4] = 0x80000000; mc[MC_IRAM_TOM / 4] = DRAM_START;
smmu_map(pdir, MC_BASE, (u32)mc, 1, _READABLE | _NONSECURE); smmu_map(pdir, MC_BASE, (u32)mc, 1, _READABLE | _NONSECURE);
// IRAM // IRAM
@@ -197,15 +199,15 @@ int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt)
// Execute firmware. // Execute firmware.
HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0x34C2E1DA; HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0x34C2E1DA;
TSEC(TSEC_STATUS) = 0; TSEC(TSEC_MAILBOX1) = 0;
TSEC(TSEC_BOOTKEYVER) = 1; // HOS uses key version 1. TSEC(TSEC_MAILBOX0) = 1; // Set HOS key version.
TSEC(TSEC_BOOTVEC) = 0; TSEC(TSEC_BOOTVEC) = 0;
TSEC(TSEC_CPUCTL) = TSEC_CPUCTL_STARTCPU; TSEC(TSEC_CPUCTL) = TSEC_CPUCTL_STARTCPU;
if (type == TSEC_FW_TYPE_EMU) if (type == TSEC_FW_TYPE_EMU)
{ {
u32 start = get_tmr_us();
u32 k = se[SE_CRYPTO_KEYTABLE_DATA_REG / 4]; u32 k = se[SE_CRYPTO_KEYTABLE_DATA_REG / 4];
u32 timeout = get_tmr_us() + 125000;
u32 key[16] = {0}; u32 key[16] = {0};
u32 kidx = 0; u32 kidx = 0;
@@ -220,7 +222,7 @@ int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt)
} }
// Failsafe. // Failsafe.
if ((u32)get_tmr_us() - start > 125000) if ((u32)get_tmr_us() > timeout)
break; break;
} }
@@ -243,7 +245,7 @@ int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt)
// for (int i = 0; i < kidx; i++) // for (int i = 0; i < kidx; i++)
// gfx_printf("key %08X\n", key[i]); // gfx_printf("key %08X\n", key[i]);
// gfx_printf("cpuctl (%08X) mbox (%08X)\n", TSEC(TSEC_CPUCTL), TSEC(TSEC_STATUS)); // gfx_printf("cpuctl (%08X) mbox (%08X)\n", TSEC(TSEC_CPUCTL), TSEC(TSEC_MAILBOX1));
// u32 errst = MC(MC_ERR_STATUS); // u32 errst = MC(MC_ERR_STATUS);
// gfx_printf(" MC %08X %08X %08X\n", MC(MC_INTSTATUS), errst, MC(MC_ERR_ADR)); // gfx_printf(" MC %08X %08X %08X\n", MC(MC_INTSTATUS), errst, MC(MC_ERR_ADR));
@@ -259,14 +261,18 @@ int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt)
res = -3; res = -3;
goto out_free; goto out_free;
} }
u32 timeout = get_tmr_ms() + 2000; u32 timeout = get_tmr_ms() + 2000;
while (!TSEC(TSEC_STATUS)) while (!TSEC(TSEC_MAILBOX1))
{
if (get_tmr_ms() > timeout) if (get_tmr_ms() > timeout)
{ {
res = -4; res = -4;
goto out_free; goto out_free;
} }
if (TSEC(TSEC_STATUS) != 0xB0B0B0B0) }
if (TSEC(TSEC_MAILBOX1) != 0xB0B0B0B0)
{ {
res = -5; res = -5;
goto out_free; goto out_free;
@@ -275,23 +281,22 @@ int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt)
// Fetch result. // Fetch result.
HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0; HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0;
u32 buf[4]; u32 buf[4];
buf[0] = SOR1(SOR_NV_PDISP_SOR_DP_HDCP_BKSV_LSB); buf[0] = SOR1(SOR_DP_HDCP_BKSV_LSB);
buf[1] = SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_BKSV_LSB); buf[1] = SOR1(SOR_TMDS_HDCP_BKSV_LSB);
buf[2] = SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_MSB); buf[2] = SOR1(SOR_TMDS_HDCP_CN_MSB);
buf[3] = SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_LSB); buf[3] = SOR1(SOR_TMDS_HDCP_CN_LSB);
SOR1(SOR_NV_PDISP_SOR_DP_HDCP_BKSV_LSB) = 0; SOR1(SOR_DP_HDCP_BKSV_LSB) = 0;
SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_BKSV_LSB) = 0; SOR1(SOR_TMDS_HDCP_BKSV_LSB) = 0;
SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_MSB) = 0; SOR1(SOR_TMDS_HDCP_CN_MSB) = 0;
SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_LSB) = 0; SOR1(SOR_TMDS_HDCP_CN_LSB) = 0;
memcpy(tsec_keys, &buf, SE_KEY_128_SIZE); memcpy(tsec_keys, &buf, SE_KEY_128_SIZE);
} }
out_free:; out_free:
free(fwbuf); free(fwbuf);
out:; out:
// Disable clocks. // Disable clocks.
clock_disable_kfuse(); clock_disable_kfuse();
clock_disable_sor1(); clock_disable_sor1();
@@ -301,9 +306,10 @@ out:;
bpmp_mmu_enable(); bpmp_mmu_enable();
bpmp_clk_rate_set(prev_fid); bpmp_clk_rate_set(prev_fid);
// Disable AHB aperture. #ifdef BDK_MC_ENABLE_AHB_REDIRECT
if (type == TSEC_FW_TYPE_NEW) // Re-enable AHB aperture.
mc_disable_ahb_redirect(); mc_enable_ahb_redirect();
#endif
return res; return res;
} }

View File

@@ -24,13 +24,13 @@ enum tsec_fw_type
{ {
// Retail Hovi Keygen. // Retail Hovi Keygen.
TSEC_FW_TYPE_OLD = 0, // 1.0.0 - 6.1.0. TSEC_FW_TYPE_OLD = 0, // 1.0.0 - 6.1.0.
TSEC_FW_TYPE_EMU = 1, // 6.2.0 emulated enviroment. TSEC_FW_TYPE_EMU = 1, // 6.2.0 emulated environment.
TSEC_FW_TYPE_NEW = 2, // 7.0.0+. TSEC_FW_TYPE_NEW = 2, // 7.0.0+.
}; };
typedef struct _tsec_ctxt_t typedef struct _tsec_ctxt_t
{ {
const void *fw; void *fw;
u32 size; u32 size;
u32 type; u32 type;
void *pkg1; void *pkg1;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018 CTCaer * Copyright (c) 2018-2023 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -17,8 +17,8 @@
#ifndef _TSEC_T210_H_ #ifndef _TSEC_T210_H_
#define _TSEC_T210_H_ #define _TSEC_T210_H_
#define TSEC_BOOTKEYVER 0x1040 #define TSEC_MAILBOX0 0x1040
#define TSEC_STATUS 0x1044 #define TSEC_MAILBOX1 0x1044
#define TSEC_ITFEN 0x1048 #define TSEC_ITFEN 0x1048
#define TSEC_ITFEN_CTXEN BIT(0) #define TSEC_ITFEN_CTXEN BIT(0)
#define TSEC_ITFEN_MTHDEN BIT(1) #define TSEC_ITFEN_MTHDEN BIT(1)

173
bdk/soc/actmon.c Normal file
View File

@@ -0,0 +1,173 @@
/*
* Activity Monitor driver for Tegra X1
*
* Copyright (c) 2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "actmon.h"
#include "clock.h"
#include "t210.h"
/* Global registers */
#define ACTMON_GLB_STATUS 0x0
#define ACTMON_MCCPU_MON_ACT BIT(8)
#define ACTMON_MCALL_MON_ACT BIT(9)
#define ACTMON_CPU_FREQ_MON_ACT BIT(10)
#define ACTMON_APB_MON_ACT BIT(12)
#define ACTMON_AHB_MON_ACT BIT(13)
#define ACTMON_BPMP_MON_ACT BIT(14)
#define ACTMON_CPU_MON_ACT BIT(15)
#define ACTMON_MCCPU_INTR BIT(25)
#define ACTMON_MCALL_INTR BIT(26)
#define ACTMON_CPU_FREQ_INTR BIT(27)
#define ACTMON_APB_INTR BIT(28)
#define ACTMON_AHB_INTR BIT(29)
#define ACTMON_BPMP_INTR BIT(30)
#define ACTMON_CPU_INTR BIT(31)
#define ACTMON_GLB_PERIOD_CTRL 0x4
#define ACTMON_GLB_PERIOD_USEC BIT(8)
#define ACTMON_GLB_PERIOD_SAMPLE(n) (((n) - 1) & 0xFF)
/* Device Registers */
#define ACTMON_DEV_BASE ACTMON_BASE + 0x80
#define ACTMON_DEV_SIZE 0x40
/* CTRL */
#define ACTMON_DEV_CTRL_K_VAL(k) (((k) & 7) << 10)
#define ACTMON_DEV_CTRL_ENB_PERIODIC BIT(18)
#define ACTMON_DEV_CTRL_AT_END_EN BIT(19)
#define ACTMON_DEV_CTRL_AVG_BELOW_WMARK_EN BIT(20)
#define ACTMON_DEV_CTRL_AVG_ABOVE_WMARK_EN BIT(21)
#define ACTMON_DEV_CTRL_WHEN_OVERFLOW_EN BIT(22)
#define ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_NUM(n) (((n) & 7) << 23)
#define ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_NUM(n) (((n) & 7) << 26)
#define ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN BIT(29)
#define ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN BIT(30)
#define ACTMON_DEV_CTRL_ENB BIT(31)
/* INTR_STATUS */
#define ACTMON_DEV_ISTS_AVG_ABOVE_WMARK BIT(24)
#define ACTMON_DEV_ISTS_AVG_BELOW_WMARK BIT(25)
#define ACTMON_DEV_ISTS_WHEN_OVERFLOW BIT(26)
#define ACTMON_DEV_ISTS_AT_END BIT(29)
#define ACTMON_DEV_ISTS_CONSECUTIVE_LOWER BIT(30)
#define ACTMON_DEV_ISTS_CONSECUTIVE_UPPER BIT(31)
/* Histogram Registers */
#define ACTMON_HISTOGRAM_CONFIG 0x300
#define ACTMON_HIST_CFG_ACTIVE BIT(0)
#define ACTMON_HIST_CFG_LINEAR_MODE BIT(1)
#define ACTMON_HIST_CFG_NO_UNDERFLOW_BUCKET BIT(2)
#define ACTMON_HIST_CFG_STALL_ON_SINGLE_SATURATE BIT(3)
#define ACTMON_HIST_CFG_SHIFT(s) (((s) & 0x1F) << 4)
#define ACTMON_HIST_CFG_SOURCE(s) (((s) & 0xF) << 12)
#define ACTMON_HISTOGRAM_CTRL 0x304
#define ACTMON_HIST_CTRL_CLEAR_ALL BIT(0)
#define ACTMON_HISTOGRAM_DATA_BASE 0x380
#define ACTMON_HISTOGRAM_DATA_NUM 32
#define ACTMON_FREQ 19200000
typedef struct _actmon_dev_reg_t
{
vu32 ctrl;
vu32 upper_wnark;
vu32 lower_wmark;
vu32 init_avg;
vu32 avg_upper_wmark;
vu32 avg_lower_wmark;
vu32 count_weight;
vu32 count;
vu32 avg_count;
vu32 intr_status;
vu32 ctrl2;
vu32 unk[5];
} actmon_dev_reg_t;
u32 sample_period = 0;
void actmon_hist_enable(actmon_hist_src_t src)
{
ACTMON(ACTMON_HISTOGRAM_CONFIG) = ACTMON_HIST_CFG_SOURCE(src) | ACTMON_HIST_CFG_ACTIVE;
ACTMON(ACTMON_HISTOGRAM_CTRL) = ACTMON_HIST_CTRL_CLEAR_ALL;
}
void actmon_hist_disable()
{
ACTMON(ACTMON_HISTOGRAM_CONFIG) = 0;
}
void actmon_hist_get(u32 *histogram)
{
if (histogram)
{
for (u32 i = 0; i < ACTMON_HISTOGRAM_DATA_NUM; i++)
histogram[i] = ACTMON(ACTMON_HISTOGRAM_DATA_BASE + i * sizeof(u32));
}
}
void actmon_dev_enable(actmon_dev_t dev)
{
actmon_dev_reg_t *regs = (actmon_dev_reg_t *)(ACTMON_DEV_BASE + (dev * ACTMON_DEV_SIZE));
regs->init_avg = 0;
regs->count_weight = 5;
regs->ctrl = ACTMON_DEV_CTRL_ENB | ACTMON_DEV_CTRL_ENB_PERIODIC;
}
void actmon_dev_disable(actmon_dev_t dev)
{
actmon_dev_reg_t *regs = (actmon_dev_reg_t *)(ACTMON_DEV_BASE + (dev * ACTMON_DEV_SIZE));
regs->ctrl = 0;
}
u32 actmon_dev_get_load(actmon_dev_t dev)
{
actmon_dev_reg_t *regs = (actmon_dev_reg_t *)(ACTMON_DEV_BASE + (dev * ACTMON_DEV_SIZE));
// Get load-based sampling. 1 decimal point precision.
u32 load = regs->count / (ACTMON_FREQ / 1000);
return load;
}
u32 actmon_dev_get_load_avg(actmon_dev_t dev)
{
actmon_dev_reg_t *regs = (actmon_dev_reg_t *)(ACTMON_DEV_BASE + (dev * ACTMON_DEV_SIZE));
// Get load-based sampling. 1 decimal point precision.
u32 avg_load = regs->avg_count / (ACTMON_FREQ / 1000);
return avg_load;
}
void atmon_dev_all_disable()
{
// TODO: do a global reset?
}
void actmon_init()
{
clock_enable_actmon();
// Set period to 200ms.
ACTMON(ACTMON_GLB_PERIOD_CTRL) &= ~ACTMON_GLB_PERIOD_USEC;
ACTMON(ACTMON_GLB_PERIOD_CTRL) |= ACTMON_GLB_PERIOD_SAMPLE(200);
}
void actmon_end()
{
clock_disable_actmon();
}

62
bdk/soc/actmon.h Normal file
View File

@@ -0,0 +1,62 @@
/*
* Activity Monitor driver for Tegra X1
*
* Copyright (c) 2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __ACTMON_H_
#define __ACTMON_H_
#include <utils/types.h>
typedef enum _actmon_dev_t
{
ACTMON_DEV_CPU,
ACTMON_DEV_BPMP,
ACTMON_DEV_AHB,
ACTMON_DEV_APB,
ACTMON_DEV_CPU_FREQ,
ACTMON_DEV_MC_ALL,
ACTMON_DEV_MC_CPU,
ACTMON_DEV_NUM,
} actmon_dev_t;
typedef enum _actmon_hist_src_t
{
ACTMON_HIST_SRC_NONE = 0,
ACTMON_HIST_SRC_AHB = 1,
ACTMON_HIST_SRC_APB = 2,
ACTMON_HIST_SRC_BPMP = 3,
ACTMON_HIST_SRC_CPU = 4,
ACTMON_HIST_SRC_MC_ALL = 5,
ACTMON_HIST_SRC_MC_CPU = 6,
ACTMON_HIST_SRC_CPU_FREQ = 7,
ACTMON_HIST_SRC_NA = 8,
ACTMON_HIST_SRC_APB_MMIO = 9,
} actmon_hist_src_t;
void actmon_hist_enable(actmon_hist_src_t src);
void actmon_hist_disable();
void actmon_hist_get(u32 *histogram);
void actmon_dev_enable(actmon_dev_t dev);
void actmon_dev_disable(actmon_dev_t dev);
u32 actmon_dev_get_load(actmon_dev_t dev);
u32 actmon_dev_get_load_avg(actmon_dev_t dev);
void atmon_dev_all_disable();
void actmon_init();
void actmon_end();
#endif

View File

@@ -1,7 +1,7 @@
/* /*
* BPMP-Lite Cache/MMU and Frequency driver for Tegra X1 * BPMP-Lite Cache/MMU and Frequency driver for Tegra X1
* *
* Copyright (c) 2019-2021 CTCaer * Copyright (c) 2019-2023 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -18,9 +18,9 @@
#include <soc/bpmp.h> #include <soc/bpmp.h>
#include <soc/clock.h> #include <soc/clock.h>
#include <soc/timer.h>
#include <soc/t210.h> #include <soc/t210.h>
#include <memory_map.h> #include <memory_map.h>
#include <utils/util.h>
#define BPMP_MMU_CACHE_LINE_SIZE 0x20 #define BPMP_MMU_CACHE_LINE_SIZE 0x20
@@ -134,7 +134,7 @@ void bpmp_mmu_maintenance(u32 op, bool force)
// This is a blocking operation. // This is a blocking operation.
BPMP_CACHE_CTRL(BPMP_CACHE_MAINT_REQ) = MAINT_REQ_WAY_BITMAP(0xF) | op; BPMP_CACHE_CTRL(BPMP_CACHE_MAINT_REQ) = MAINT_REQ_WAY_BITMAP(0xF) | op;
while(!(BPMP_CACHE_CTRL(BPMP_CACHE_INT_RAW_EVENT) & INT_MAINT_DONE)) while (!(BPMP_CACHE_CTRL(BPMP_CACHE_INT_RAW_EVENT) & INT_MAINT_DONE))
; ;
BPMP_CACHE_CTRL(BPMP_CACHE_INT_CLEAR) = BPMP_CACHE_CTRL(BPMP_CACHE_INT_RAW_EVENT); BPMP_CACHE_CTRL(BPMP_CACHE_INT_CLEAR) = BPMP_CACHE_CTRL(BPMP_CACHE_INT_RAW_EVENT);
@@ -150,8 +150,8 @@ void bpmp_mmu_set_entry(int idx, bpmp_mmu_entry_t *entry, bool apply)
if (entry->enable) if (entry->enable)
{ {
mmu_entry->start_addr = ALIGN(entry->start_addr, BPMP_MMU_CACHE_LINE_SIZE); mmu_entry->start_addr = ALIGN(entry->start_addr, BPMP_MMU_CACHE_LINE_SIZE);
mmu_entry->end_addr = ALIGN_DOWN(entry->end_addr, BPMP_MMU_CACHE_LINE_SIZE); mmu_entry->end_addr = ALIGN_DOWN(entry->end_addr, BPMP_MMU_CACHE_LINE_SIZE);
mmu_entry->attr = entry->attr; mmu_entry->attr = entry->attr;
BPMP_CACHE_CTRL(BPMP_CACHE_MMU_SHADOW_COPY_MASK) |= BIT(idx); BPMP_CACHE_CTRL(BPMP_CACHE_MMU_SHADOW_COPY_MASK) |= BIT(idx);
@@ -166,9 +166,9 @@ void bpmp_mmu_enable()
return; return;
// Init BPMP MMU. // Init BPMP MMU.
BPMP_CACHE_CTRL(BPMP_CACHE_MMU_CMD) = MMU_CMD_INIT; BPMP_CACHE_CTRL(BPMP_CACHE_MMU_CMD) = MMU_CMD_INIT;
BPMP_CACHE_CTRL(BPMP_CACHE_MMU_FALLBACK_ENTRY) = MMU_EN_READ | MMU_EN_WRITE | MMU_EN_EXEC; // RWX for non-defined regions. BPMP_CACHE_CTRL(BPMP_CACHE_MMU_FALLBACK_ENTRY) = MMU_EN_READ | MMU_EN_WRITE | MMU_EN_EXEC; // RWX for non-defined regions.
BPMP_CACHE_CTRL(BPMP_CACHE_MMU_CFG) = MMU_CFG_SEQ_EN | MMU_CFG_TLB_EN | MMU_CFG_ABORT_STORE_LAST; BPMP_CACHE_CTRL(BPMP_CACHE_MMU_CFG) = MMU_CFG_SEQ_EN | MMU_CFG_TLB_EN | MMU_CFG_ABORT_STORE_LAST;
// Init BPMP MMU entries. // Init BPMP MMU entries.
BPMP_CACHE_CTRL(BPMP_CACHE_MMU_SHADOW_COPY_MASK) = 0; BPMP_CACHE_CTRL(BPMP_CACHE_MMU_SHADOW_COPY_MASK) = 0;
@@ -206,6 +206,7 @@ void bpmp_mmu_disable()
const u8 pll_divn[] = { const u8 pll_divn[] = {
0, // BPMP_CLK_NORMAL: 408MHz 0% - 136MHz APB. 0, // BPMP_CLK_NORMAL: 408MHz 0% - 136MHz APB.
85, // BPMP_CLK_HIGH_BOOST: 544MHz 33% - 136MHz APB. 85, // BPMP_CLK_HIGH_BOOST: 544MHz 33% - 136MHz APB.
88, // BPMP_CLK_HIGH2_BOOST: 563MHz 38% - 141MHz APB.
90, // BPMP_CLK_SUPER_BOOST: 576MHz 41% - 144MHz APB. 90, // BPMP_CLK_SUPER_BOOST: 576MHz 41% - 144MHz APB.
92 // BPMP_CLK_HYPER_BOOST: 589MHz 44% - 147MHz APB. 92 // BPMP_CLK_HYPER_BOOST: 589MHz 44% - 147MHz APB.
// Do not use for public releases! // Do not use for public releases!

View File

@@ -1,7 +1,7 @@
/* /*
* BPMP-Lite Cache/MMU and Frequency driver for Tegra X1 * BPMP-Lite Cache/MMU and Frequency driver for Tegra X1
* *
* Copyright (c) 2019-2021 CTCaer * Copyright (c) 2019-2023 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -47,12 +47,14 @@ typedef enum
{ {
BPMP_CLK_NORMAL, // 408MHz 0% - 136MHz APB. BPMP_CLK_NORMAL, // 408MHz 0% - 136MHz APB.
BPMP_CLK_HIGH_BOOST, // 544MHz 33% - 136MHz APB. BPMP_CLK_HIGH_BOOST, // 544MHz 33% - 136MHz APB.
BPMP_CLK_HIGH2_BOOST, // 563MHz 38% - 141MHz APB.
BPMP_CLK_SUPER_BOOST, // 576MHz 41% - 144MHz APB. BPMP_CLK_SUPER_BOOST, // 576MHz 41% - 144MHz APB.
BPMP_CLK_HYPER_BOOST, // 589MHz 44% - 147MHz APB. BPMP_CLK_HYPER_BOOST, // 589MHz 44% - 147MHz APB.
//BPMP_CLK_DEV_BOOST, // 608MHz 49% - 152MHz APB. //BPMP_CLK_DEV_BOOST, // 608MHz 49% - 152MHz APB.
BPMP_CLK_MAX BPMP_CLK_MAX
} bpmp_freq_t; } bpmp_freq_t;
#define BPMP_CLK_LOWEST_BOOST BPMP_CLK_HIGH2_BOOST
#define BPMP_CLK_LOWER_BOOST BPMP_CLK_SUPER_BOOST #define BPMP_CLK_LOWER_BOOST BPMP_CLK_SUPER_BOOST
#define BPMP_CLK_DEFAULT_BOOST BPMP_CLK_HYPER_BOOST #define BPMP_CLK_DEFAULT_BOOST BPMP_CLK_HYPER_BOOST

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer * Copyright (c) 2018-2022 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -15,6 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <memory_map.h>
#include <soc/ccplex.h> #include <soc/ccplex.h>
#include <soc/hw_init.h> #include <soc/hw_init.h>
#include <soc/i2c.h> #include <soc/i2c.h>
@@ -51,7 +52,7 @@ void _ccplex_enable_power_t210b01()
void ccplex_boot_cpu0(u32 entry) void ccplex_boot_cpu0(u32 entry)
{ {
// Set ACTIVE_CLUSER to FAST. // Set ACTIVE_CLUSER to FAST.
FLOW_CTLR(FLOW_CTLR_BPMP_CLUSTER_CONTROL) &= 0xFFFFFFFE; FLOW_CTLR(FLOW_CTLR_BPMP_CLUSTER_CONTROL) &= ~CLUSTER_CTRL_ACTIVE_SLOW;
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210) if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210)
_ccplex_enable_power_t210(); _ccplex_enable_power_t210();
@@ -62,12 +63,12 @@ void ccplex_boot_cpu0(u32 entry)
// Configure MSELECT source and enable clock to 102MHz. // Configure MSELECT source and enable clock to 102MHz.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) & 0x1FFFFF00) | 6; CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) & 0x1FFFFF00) | 6;
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = BIT(CLK_V_MSELECT); CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = BIT(CLK_V_MSELECT);
// Configure initial CPU clock frequency and enable clock. // Configure initial CPU clock frequency and enable clock.
CLOCK(CLK_RST_CONTROLLER_CCLK_BURST_POLICY) = 0x20008888; // PLLX_OUT0_LJ. 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) = 0x80000000;
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = BIT(CLK_V_CPUG); CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = BIT(CLK_V_CPUG);
clock_enable_coresight(); clock_enable_coresight();
@@ -81,9 +82,9 @@ void ccplex_boot_cpu0(u32 entry)
// Enable CPU0 rail. // Enable CPU0 rail.
pmc_enable_partition(POWER_RAIL_CE0, ENABLE); pmc_enable_partition(POWER_RAIL_CE0, ENABLE);
// Request and wait for RAM repair. // Request and wait for RAM repair. Needed for the Fast cluster.
FLOW_CTLR(FLOW_CTLR_RAM_REPAIR) = 1; FLOW_CTLR(FLOW_CTLR_RAM_REPAIR) = RAM_REPAIR_REQ;
while (!(FLOW_CTLR(FLOW_CTLR_RAM_REPAIR) & 2)) while (!(FLOW_CTLR(FLOW_CTLR_RAM_REPAIR) & RAM_REPAIR_STS))
; ;
EXCP_VEC(EVP_CPU_RESET_VECTOR) = 0; EXCP_VEC(EVP_CPU_RESET_VECTOR) = 0;
@@ -91,6 +92,7 @@ void ccplex_boot_cpu0(u32 entry)
// Set reset vector. // 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; SB(SB_AA64_RESET_HIGH) = 0;
// Non-secure reset vector write disable. // Non-secure reset vector write disable.
SB(SB_CSR) = SB_CSR_NS_RST_VEC_WR_DIS; SB(SB_CSR) = SB_CSR_NS_RST_VEC_WR_DIS;
(void)SB(SB_CSR); (void)SB(SB_CSR);
@@ -99,7 +101,7 @@ void ccplex_boot_cpu0(u32 entry)
// MC(MC_TZ_SECURITY_CTRL) = 1; // MC(MC_TZ_SECURITY_CTRL) = 1;
// Clear MSELECT reset. // Clear MSELECT reset.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_V_CLR) = BIT(CLK_V_MSELECT); CLOCK(CLK_RST_CONTROLLER_RST_DEV_V_CLR) = BIT(CLK_V_MSELECT);
// Clear NONCPU reset. // Clear NONCPU reset.
CLOCK(CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR) = 0x20000000; CLOCK(CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR) = 0x20000000;
// Clear CPU0 reset. // Clear CPU0 reset.

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer * Copyright (c) 2018-2023 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -17,9 +17,10 @@
#include <soc/clock.h> #include <soc/clock.h>
#include <soc/hw_init.h> #include <soc/hw_init.h>
#include <soc/pmc.h>
#include <soc/timer.h>
#include <soc/t210.h> #include <soc/t210.h>
#include <storage/sdmmc.h> #include <storage/sdmmc.h>
#include <utils/util.h>
typedef struct _clock_osc_t typedef struct _clock_osc_t
{ {
@@ -38,9 +39,9 @@ static const clock_osc_t _clock_osc_cnt[] = {
{ 48000, 2836, 3023 } { 48000, 2836, 3023 }
}; };
/* clock_t: reset, enable, source, index, clk_src, clk_div */ /* clk_rst_t: reset, enable, source, index, clk_src, clk_div */
static const clock_t _clock_uart[] = { 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_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_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_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_UARTC, CLK_H_UARTC, 0, 2 },
@@ -49,7 +50,7 @@ static const clock_t _clock_uart[] = {
}; };
//I2C default parameters - TLOW: 4, THIGH: 2, DEBOUNCE: 0, FM_DIV: 26. //I2C default parameters - TLOW: 4, THIGH: 2, DEBOUNCE: 0, FM_DIV: 26.
static const clock_t _clock_i2c[] = { 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_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_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_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_I2C3, CLK_U_I2C3, 0, 4 }, //81.6MHz -> 400KHz
@@ -58,49 +59,68 @@ static const clock_t _clock_i2c[] = {
{ 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_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_I2C6, CLK_X_I2C6, 0, 19 } //20.4MHz -> 100KHz
}; };
static clock_t _clock_se = { 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. 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.
}; };
static clk_rst_t _clock_tzram = {
static clock_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, 0
}; };
static clk_rst_t _clock_host1x = {
static clock_t _clock_host1x = { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X, CLK_L_HOST1X, 4, 3 // 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, 3 // 163.2MHz.
}; };
static clock_t _clock_tsec = { 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. 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.
}; };
static clock_t _clock_sor_safe = { static clk_rst_t _clock_nvdec = {
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_RST_CONTROLLER_CLK_SOURCE_NVDEC, CLK_Y_NVDEC, 4, 0 // 408 MHz. Max: 716.8/979.2MHz.
}; };
static clock_t _clock_sor0 = { static clk_rst_t _clock_nvjpg = {
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_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.
}; };
static clock_t _clock_sor1 = { static clk_rst_t _clock_vic = {
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_VIC, CLK_X_VIC, 2, 0 // 408 MHz. Max: 627.2/652.8MHz.
}; };
static clock_t _clock_kfuse = { static clk_rst_t _clock_sor_safe = {
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_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_NO_SOURCE, CLK_Y_SOR_SAFE, 0, 0
}; };
static clk_rst_t _clock_sor0 = {
static clock_t _clock_cl_dvfs = { 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_W, CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_NO_SOURCE, CLK_W_DVFS, 0, 0
}; };
static clock_t _clock_coresight = { static clk_rst_t _clock_sor1 = {
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_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_SOR1, CLK_X_SOR1, 0, 2 // 204MHz.
}; };
static clk_rst_t _clock_kfuse = {
static clock_t _clock_pwm = { 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_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, CLK_L_PWM, 6, 4 // Fref: 6.4MHz. HOS: PLLP / 54 = 7.55MHz.
}; };
static clk_rst_t _clock_cl_dvfs = {
static clock_t _clock_sdmmc_legacy_tm = { CLK_RST_CONTROLLER_RST_DEVICES_W, CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_NO_SOURCE, CLK_W_DVFS, 0, 0
};
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.
};
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.
};
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, 66
}; };
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.
};
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
};
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.
};
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
};
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
};
void clock_enable(const clock_t *clk) void clock_enable(const clk_rst_t *clk)
{ {
// Put clock into reset. // Put clock into reset.
CLOCK(clk->reset) = (CLOCK(clk->reset) & ~BIT(clk->index)) | BIT(clk->index); CLOCK(clk->reset) = (CLOCK(clk->reset) & ~BIT(clk->index)) | BIT(clk->index);
@@ -117,7 +137,7 @@ void clock_enable(const clock_t *clk)
CLOCK(clk->reset) &= ~BIT(clk->index); CLOCK(clk->reset) &= ~BIT(clk->index);
} }
void clock_disable(const clock_t *clk) void clock_disable(const clk_rst_t *clk)
{ {
// Put clock into reset. // Put clock into reset.
CLOCK(clk->reset) = (CLOCK(clk->reset) & ~BIT(clk->index)) | BIT(clk->index); CLOCK(clk->reset) = (CLOCK(clk->reset) & ~BIT(clk->index)) | BIT(clk->index);
@@ -147,7 +167,9 @@ int clock_uart_use_src_div(u32 idx, u32 baud)
{ {
u32 clk_src_div = CLOCK(_clock_uart[idx].source) & 0xE0000000; u32 clk_src_div = CLOCK(_clock_uart[idx].source) & 0xE0000000;
if (baud == 1000000) if (baud == 3000000)
CLOCK(_clock_uart[idx].source) = clk_src_div | UART_SRC_CLK_DIV_EN | 15;
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 | 49;
else else
{ {
@@ -203,6 +225,36 @@ void clock_disable_tsec()
clock_disable(&_clock_tsec); clock_disable(&_clock_tsec);
} }
void clock_enable_nvdec()
{
clock_enable(&_clock_nvdec);
}
void clock_disable_nvdec()
{
clock_disable(&_clock_nvdec);
}
void clock_enable_nvjpg()
{
clock_enable(&_clock_nvjpg);
}
void clock_disable_nvjpg()
{
clock_disable(&_clock_nvjpg);
}
void clock_enable_vic()
{
clock_enable(&_clock_vic);
}
void clock_disable_vic()
{
clock_disable(&_clock_vic);
}
void clock_enable_sor_safe() void clock_enable_sor_safe()
{ {
clock_enable(&_clock_sor_safe); clock_enable(&_clock_sor_safe);
@@ -279,6 +331,86 @@ void clock_disable_pwm()
clock_disable(&_clock_pwm); clock_disable(&_clock_pwm);
} }
void clock_enable_apbdma()
{
clock_enable(&_clock_apbdma);
}
void clock_disable_apbdma()
{
clock_disable(&_clock_apbdma);
}
void clock_enable_ahbdma()
{
clock_enable(&_clock_ahbdma);
}
void clock_disable_ahbdma()
{
clock_disable(&_clock_ahbdma);
}
void clock_enable_actmon()
{
clock_enable(&_clock_actmon);
}
void clock_disable_actmon()
{
clock_disable(&_clock_actmon);
}
void clock_enable_extperiph1()
{
clock_enable(&_clock_extperiph1);
PMC(APBDEV_PMC_CLK_OUT_CNTRL) |= PMC_CLK_OUT_CNTRL_CLK1_SRC_SEL(OSC_CAR) | PMC_CLK_OUT_CNTRL_CLK1_FORCE_EN;
usleep(5);
}
void clock_disable_extperiph1()
{
PMC(APBDEV_PMC_CLK_OUT_CNTRL) &= ~((PMC_CLK_OUT_CNTRL_CLK1_SRC_SEL(OSC_CAR)) | PMC_CLK_OUT_CNTRL_CLK1_FORCE_EN);
clock_disable(&_clock_extperiph1);
}
void clock_enable_extperiph2()
{
clock_enable(&_clock_extperiph2);
PMC(APBDEV_PMC_CLK_OUT_CNTRL) |= PMC_CLK_OUT_CNTRL_CLK2_SRC_SEL(OSC_CAR) | PMC_CLK_OUT_CNTRL_CLK2_FORCE_EN;
usleep(5);
}
void clock_disable_extperiph2()
{
PMC(APBDEV_PMC_CLK_OUT_CNTRL) &= ~((PMC_CLK_OUT_CNTRL_CLK2_SRC_SEL(OSC_CAR)) | PMC_CLK_OUT_CNTRL_CLK2_FORCE_EN);
clock_disable(&_clock_extperiph2);
}
void clock_enable_plld(u32 divp, u32 divn, bool lowpower, bool tegra_t210)
{
u32 plld_div = (divp << 20) | (divn << 11) | 1;
// N divider is fractional, so N = DIVN + 1/2 + PLLD_SDM_DIN/8192.
u32 misc = 0x2D0000 | 0xFC00; // Clock enable and PLLD_SDM_DIN: -1024 -> DIVN + 0.375.
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 dividers and enable PLLD.
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div;
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = tegra_t210 ? 0x20 : 0; // Keep default PLLD_SETUP.
// Set PLLD_SDM_DIN and enable PLLD to DSI pads.
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC) = misc;
}
void clock_enable_pllx() void clock_enable_pllx()
{ {
// Configure and enable PLLX if disabled. // Configure and enable PLLX if disabled.
@@ -315,7 +447,7 @@ void clock_enable_pllc(u32 divn)
// Take PLLC out of reset and set basic misc parameters. // Take PLLC out of reset and set basic misc parameters.
CLOCK(CLK_RST_CONTROLLER_PLLC_MISC) = CLOCK(CLK_RST_CONTROLLER_PLLC_MISC) =
((CLOCK(CLK_RST_CONTROLLER_PLLC_MISC) & 0xFFF0000F) & ~PLLC_MISC_RESET) | (0x80000 << 4); // PLLC_EXT_FRU. ((CLOCK(CLK_RST_CONTROLLER_PLLC_MISC) & 0xFFF0000F) & ~PLLC_MISC_RESET) | (0x8000 << 4); // PLLC_EXT_FRU.
CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_2) |= 0xF0 << 8; // PLLC_FLL_LD_MEM. CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_2) |= 0xF0 << 8; // PLLC_FLL_LD_MEM.
// Disable PLL and IDDQ in case they are on. // Disable PLL and IDDQ in case they are on.
@@ -342,11 +474,11 @@ void clock_enable_pllc(u32 divn)
void clock_disable_pllc() void clock_disable_pllc()
{ {
// Disable PLLC and PLLC_OUT1. // Disable PLLC and PLLC_OUT1.
CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) &= ~(PLLC_OUT1_CLKEN | PLLC_OUT1_RSTN_CLR); CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) &= ~PLLC_OUT1_RSTN_CLR;
CLOCK(CLK_RST_CONTROLLER_PLLC_MISC) = PLLC_MISC_RESET;
CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) &= ~PLLCX_BASE_ENABLE; CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) &= ~PLLCX_BASE_ENABLE;
CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) |= PLLCX_BASE_REF_DIS;
CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_1) |= PLLC_MISC1_IDDQ; CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_1) |= PLLC_MISC1_IDDQ;
CLOCK(CLK_RST_CONTROLLER_PLLC_MISC) |= PLLC_MISC_RESET; CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_2) &= ~(0xFF << 8); // PLLC_FLL_LD_MEM.
usleep(10); usleep(10);
} }
@@ -371,7 +503,7 @@ static void _clock_enable_pllc4(u32 mask)
usleep(10); usleep(10);
// Set PLLC4 dividers. // Set PLLC4 dividers.
CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) = (104 << 8) | 4; // DIVM: 4, DIVP: 1. CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) = (0 << 19) | (104 << 8) | 4; // DIVP: 1, DIVN: 104, DIVM: 4. 998MHz OUT0, 199MHz OUT2.
// Enable PLLC4 and wait for Phase and Frequency lock. // Enable PLLC4 and wait for Phase and Frequency lock.
CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) |= PLLCX_BASE_ENABLE; CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) |= PLLCX_BASE_ENABLE;
@@ -409,9 +541,9 @@ void clock_enable_pllu()
CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) = pllu_cfg | PLLCX_BASE_ENABLE; // Enable. CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) = pllu_cfg | PLLCX_BASE_ENABLE; // Enable.
// Wait for PLL to stabilize. // Wait for PLL to stabilize.
u32 timeout = (u32)TMR(TIMERUS_CNTR_1US) + 1300; u32 timeout = get_tmr_us() + 1300;
while (!(CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) & PLLCX_BASE_LOCK)) // PLL_LOCK. while (!(CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) & PLLCX_BASE_LOCK)) // PLL_LOCK.
if ((u32)TMR(TIMERUS_CNTR_1US) > timeout) if (get_tmr_us() > timeout)
break; break;
usleep(10); usleep(10);
@@ -421,9 +553,9 @@ void clock_enable_pllu()
void clock_disable_pllu() void clock_disable_pllu()
{ {
CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) &= ~0x2E00000; // Disable PLLU USB/HSIC/ICUSB/48M. CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) &= ~0x2E00000; // Disable PLLU USB/HSIC/ICUSB/48M.
CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) &= ~0x40000000; // Disable PLLU. CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) &= ~BIT(30); // Disable PLLU.
CLOCK(CLK_RST_CONTROLLER_PLLU_MISC) &= ~0x20000000; // Enable reference clock. CLOCK(CLK_RST_CONTROLLER_PLLU_MISC) &= ~BIT(29); // Enable reference clock.
} }
void clock_enable_utmipll() void clock_enable_utmipll()
@@ -552,7 +684,7 @@ static void _clock_sdmmc_clear_enable(u32 id)
static void _clock_sdmmc_config_legacy_tm() static void _clock_sdmmc_config_legacy_tm()
{ {
clock_t *clk = &_clock_sdmmc_legacy_tm; clk_rst_t *clk = &_clock_sdmmc_legacy_tm;
if (!(CLOCK(clk->enable) & BIT(clk->index))) if (!(CLOCK(clk->enable) & BIT(clk->index)))
clock_enable(clk); clock_enable(clk);
} }
@@ -567,6 +699,7 @@ static clock_sdmmc_t _clock_sdmmc_table[4] = { 0 };
#define SDMMC_CLOCK_SRC_PLLP_OUT0 0x0 #define SDMMC_CLOCK_SRC_PLLP_OUT0 0x0
#define SDMMC_CLOCK_SRC_PLLC4_OUT2 0x3 #define SDMMC_CLOCK_SRC_PLLC4_OUT2 0x3
#define SDMMC_CLOCK_SRC_PLLC4_OUT0 0x7
#define SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ 0x1 #define SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ 0x1
static int _clock_sdmmc_config_clock_host(u32 *pclock, u32 id, u32 val) static int _clock_sdmmc_config_clock_host(u32 *pclock, u32 id, u32 val)
@@ -584,79 +717,88 @@ static int _clock_sdmmc_config_clock_host(u32 *pclock, u32 id, u32 val)
*pclock = 24728; *pclock = 24728;
divisor = 31; // 16.5 div. divisor = 31; // 16.5 div.
break; break;
case 26000: case 26000:
*pclock = 25500; *pclock = 25500;
divisor = 30; // 16 div. divisor = 30; // 16 div.
break; break;
case 40800:
*pclock = 40800;
divisor = 18; // 10 div.
break;
case 50000: case 50000:
*pclock = 48000; *pclock = 48000;
divisor = 15; // 8.5 div. divisor = 15; // 8.5 div.
break; break;
case 52000: case 52000:
*pclock = 51000; *pclock = 51000;
divisor = 14; // 8 div. divisor = 14; // 8 div.
break; break;
case 82000:
*pclock = 81600;
divisor = 8; // 5 div.
break;
case 100000: case 100000:
source = SDMMC_CLOCK_SRC_PLLC4_OUT2; source = SDMMC_CLOCK_SRC_PLLC4_OUT2;
*pclock = 99840; *pclock = 99840;
divisor = 2; // 2 div. divisor = 2; // 2 div.
break; break;
case 164000: case 164000:
*pclock = 163200; *pclock = 163200;
divisor = 3; // 2.5 div. divisor = 3; // 2.5 div.
break; break;
case 200000: // 240MHz evo+.
case 200000:
switch (id) switch (id)
{ {
case SDMMC_1: case SDMMC_1:
source = SDMMC_CLOCK_SRC_PLLC4_OUT2;
break;
case SDMMC_2:
source = SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ;
break;
case SDMMC_3: case SDMMC_3:
source = SDMMC_CLOCK_SRC_PLLC4_OUT2; source = SDMMC_CLOCK_SRC_PLLC4_OUT2;
break; break;
case SDMMC_2:
case SDMMC_4: case SDMMC_4:
source = SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ; source = SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ; // div is ignored.
break; break;
} }
*pclock = 199680; *pclock = 199680;
divisor = 0; // 1 div. divisor = 0; // 1 div.
break; break;
default:
*pclock = 24728; #ifdef BDK_SDMMC_UHS_DDR200_SUPPORT
divisor = 31; // 16.5 div. case 400000:
source = SDMMC_CLOCK_SRC_PLLC4_OUT0;
*pclock = 399360;
divisor = 3; // 2.5 div
break;
#endif
} }
_clock_sdmmc_table[id].clock = val; _clock_sdmmc_table[id].clock = val;
_clock_sdmmc_table[id].real_clock = *pclock; _clock_sdmmc_table[id].real_clock = *pclock;
// Enable PLLC4 if in use by any SDMMC. // Enable PLLC4 if in use by any SDMMC.
if (source) if (source != SDMMC_CLOCK_SRC_PLLP_OUT0)
_clock_enable_pllc4(BIT(id)); _clock_enable_pllc4(BIT(id));
// Set SDMMC legacy timeout clock. // Set SDMMC legacy timeout clock.
_clock_sdmmc_config_legacy_tm(); _clock_sdmmc_config_legacy_tm();
// Set SDMMC clock. // Set SDMMC clock.
u32 src_div = (source << 29) | divisor;
switch (id) switch (id)
{ {
case SDMMC_1: case SDMMC_1:
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC1) = (source << 29) | divisor; CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC1) = src_div;
break; break;
case SDMMC_2: case SDMMC_2:
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC2) = (source << 29) | divisor; CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC2) = src_div;
break; break;
case SDMMC_3: case SDMMC_3:
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC3) = (source << 29) | divisor; CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC3) = src_div;
break; break;
case SDMMC_4: case SDMMC_4:
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC4) = (source << 29) | divisor; CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC4) = src_div;
break; break;
} }
@@ -686,54 +828,71 @@ void clock_sdmmc_get_card_clock_div(u32 *pclock, u16 *pdivisor, u32 type)
// Get Card clock divisor. // Get Card clock divisor.
switch (type) switch (type)
{ {
case SDHCI_TIMING_MMC_ID: // Actual IO Freq: 380.59 KHz. case SDHCI_TIMING_MMC_ID: // Actual card clock: 386.36 KHz.
*pclock = 26000; *pclock = 26000;
*pdivisor = 66; *pdivisor = 66;
break; break;
case SDHCI_TIMING_MMC_LS26: case SDHCI_TIMING_MMC_LS26:
*pclock = 26000; *pclock = 26000;
*pdivisor = 1; *pdivisor = 1;
break; break;
case SDHCI_TIMING_MMC_HS52: case SDHCI_TIMING_MMC_HS52:
*pclock = 52000; *pclock = 52000;
*pdivisor = 1; *pdivisor = 1;
break; break;
case SDHCI_TIMING_MMC_HS200: case SDHCI_TIMING_MMC_HS200:
case SDHCI_TIMING_MMC_HS400: case SDHCI_TIMING_MMC_HS400:
case SDHCI_TIMING_UHS_SDR104: case SDHCI_TIMING_UHS_SDR104:
*pclock = 200000; *pclock = 200000;
*pdivisor = 1; *pdivisor = 1;
break; break;
case SDHCI_TIMING_SD_ID: // Actual IO Freq: 380.43 KHz.
case SDHCI_TIMING_SD_ID: // Actual card clock: 386.38 KHz.
*pclock = 25000; *pclock = 25000;
*pdivisor = 64; *pdivisor = 64;
break; break;
case SDHCI_TIMING_SD_DS12: case SDHCI_TIMING_SD_DS12:
case SDHCI_TIMING_UHS_SDR12: case SDHCI_TIMING_UHS_SDR12:
*pclock = 25000; *pclock = 25000;
*pdivisor = 1; *pdivisor = 1;
break; break;
case SDHCI_TIMING_SD_HS25: case SDHCI_TIMING_SD_HS25:
case SDHCI_TIMING_UHS_SDR25: case SDHCI_TIMING_UHS_SDR25:
*pclock = 50000; *pclock = 50000;
*pdivisor = 1; *pdivisor = 1;
break; break;
case SDHCI_TIMING_UHS_SDR50: case SDHCI_TIMING_UHS_SDR50:
*pclock = 100000; *pclock = 100000;
*pdivisor = 1; *pdivisor = 1;
break; break;
case SDHCI_TIMING_UHS_SDR82: case SDHCI_TIMING_UHS_SDR82:
*pclock = 164000; *pclock = 164000;
*pdivisor = 1; *pdivisor = 1;
break; break;
case SDHCI_TIMING_UHS_DDR50:
*pclock = 40800; case SDHCI_TIMING_UHS_DDR50: // Actual card clock: 40.80 MHz.
*pdivisor = 1; *pclock = 82000;
*pdivisor = 2;
break; break;
case SDHCI_TIMING_MMC_HS102: // Actual IO Freq: 99.84 MHz.
case SDHCI_TIMING_MMC_HS100: // Actual card clock: 99.84 MHz.
*pclock = 200000; *pclock = 200000;
*pdivisor = 2; *pdivisor = 2;
break; break;
#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT
case SDHCI_TIMING_UHS_DDR200: // Actual card clock: 199.68 KHz.
*pclock = 400000;
*pdivisor = 2;
break;
#endif
} }
} }
@@ -752,7 +911,8 @@ void clock_sdmmc_enable(u32 id, u32 val)
_clock_sdmmc_config_clock_host(&clock, id, val); _clock_sdmmc_config_clock_host(&clock, id, val);
_clock_sdmmc_set_enable(id); _clock_sdmmc_set_enable(id);
_clock_sdmmc_is_reset(id); _clock_sdmmc_is_reset(id);
usleep((100000 + clock - 1) / clock); // Wait 100 cycles for reset and for clocks to stabilize.
usleep((100 * 1000 + clock - 1) / clock);
_clock_sdmmc_clear_reset(id); _clock_sdmmc_clear_reset(id);
_clock_sdmmc_is_reset(id); _clock_sdmmc_is_reset(id);
} }

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer * Copyright (c) 2018-2022 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -117,7 +117,10 @@
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD 0x3A4 #define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD 0x3A4
#define CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT 0x3B4 #define CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT 0x3B4
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C4 0x3C4 #define CLK_RST_CONTROLLER_CLK_SOURCE_I2C4 0x3C4
#define CLK_RST_CONTROLLER_CLK_SOURCE_AHUB 0x3D0
#define CLK_RST_CONTROLLER_CLK_SOURCE_ACTMON 0x3E8
#define CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH1 0x3EC #define CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH1 0x3EC
#define CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH2 0x3F0
#define CLK_RST_CONTROLLER_CLK_SOURCE_SYS 0x400 #define CLK_RST_CONTROLLER_CLK_SOURCE_SYS 0x400
#define CLK_RST_CONTROLLER_CLK_SOURCE_SOR1 0x410 #define CLK_RST_CONTROLLER_CLK_SOURCE_SOR1 0x410
#define CLK_RST_CONTROLLER_CLK_SOURCE_SE 0x42C #define CLK_RST_CONTROLLER_CLK_SOURCE_SE 0x42C
@@ -153,8 +156,12 @@
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C6 0x65C #define CLK_RST_CONTROLLER_CLK_SOURCE_I2C6 0x65C
#define CLK_RST_CONTROLLER_CLK_SOURCE_EMC_DLL 0x664 #define CLK_RST_CONTROLLER_CLK_SOURCE_EMC_DLL 0x664
#define CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIPI_CAL 0x66C #define CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIPI_CAL 0x66C
#define CLK_RST_CONTROLLER_CLK_SOURCE_VIC 0x678
#define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM 0x694 #define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM 0x694
#define CLK_RST_CONTROLLER_CLK_SOURCE_NVDEC 0x698
#define CLK_RST_CONTROLLER_CLK_SOURCE_NVJPG 0x69C
#define CLK_RST_CONTROLLER_CLK_SOURCE_NVENC 0x6A0 #define CLK_RST_CONTROLLER_CLK_SOURCE_NVENC 0x6A0
#define CLK_RST_CONTROLLER_CLK_SOURCE_APE 0x6C0
#define CLK_RST_CONTROLLER_CLK_SOURCE_USB2_HSIC_TRK 0x6CC #define CLK_RST_CONTROLLER_CLK_SOURCE_USB2_HSIC_TRK 0x6CC
#define CLK_RST_CONTROLLER_SE_SUPER_CLK_DIVIDER 0x704 #define CLK_RST_CONTROLLER_SE_SUPER_CLK_DIVIDER 0x704
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTAPE 0x710 #define CLK_RST_CONTROLLER_CLK_SOURCE_UARTAPE 0x710
@@ -220,138 +227,232 @@
/*! PTO IDs. */ /*! PTO IDs. */
typedef enum _clock_pto_id_t typedef enum _clock_pto_id_t
{ {
CLK_PTO_PCLK_SYS = 0x06, CLK_PTO_PCLK_SYS = 0x06,
CLK_PTO_HCLK_SYS = 0x07, CLK_PTO_HCLK_SYS = 0x07,
CLK_PTO_DMIC1 = 0x08,
CLK_PTO_DMIC2 = 0x09,
CLK_PTO_HDMI_SLOWCLK_DIV2 = 0x0A,
CLK_PTO_JTAG_REG = 0x0B,
CLK_PTO_UTMIP_240_A = 0x0C,
CLK_PTO_UTMIP_240_B = 0x0D,
CLK_PTO_UTMIP_240 = 0x0C, CLK_PTO_CCLK_G = 0x12,
CLK_PTO_CCLK_G_DIV2 = 0x13,
CLK_PTO_MIPIBIF = 0x14,
CLK_PTO_CCLK_G = 0x12, CLK_PTO_SPI1 = 0x17,
CLK_PTO_CCLK_G_DIV2 = 0x13, CLK_PTO_SPI2 = 0x18,
CLK_PTO_SPI3 = 0x19,
CLK_PTO_SPI4 = 0x1A,
CLK_PTO_MAUD = 0x1B,
CLK_PTO_SCLK = 0x1C,
CLK_PTO_SPI1 = 0x17, CLK_PTO_SDMMC1 = 0x20,
CLK_PTO_SPI2 = 0x18, CLK_PTO_SDMMC2 = 0x21,
CLK_PTO_SPI3 = 0x19, CLK_PTO_SDMMC3 = 0x22,
CLK_PTO_SPI4 = 0x1A, CLK_PTO_SDMMC4 = 0x23,
CLK_PTO_MAUD = 0x1B, CLK_PTO_EMC = 0x24,
CLK_PTO_SCLK = 0x1C,
CLK_PTO_SDMMC1 = 0x20, CLK_PTO_DMIC3 = 0x2A,
CLK_PTO_SDMMC2 = 0x21, CLK_PTO_CCLK_LP = 0x2B,
CLK_PTO_SDMMC3 = 0x22, CLK_PTO_CCLK_LP_DIV2 = 0x2C,
CLK_PTO_SDMMC4 = 0x23,
CLK_PTO_EMC = 0x24,
CLK_PTO_CCLK_LP = 0x2B, CLK_PTO_MSELECT = 0x2F,
CLK_PTO_CCLK_LP_DIV2 = 0x2C,
CLK_PTO_MSELECT = 0x2F, CLK_PTO_VI_SENSOR2 = 0x33,
CLK_PTO_VI_SENSOR = 0x34,
CLK_PTO_VIC = 0x35,
CLK_PTO_VIC_SKIP = 0x36,
CLK_PTO_ISP_SKIP = 0x37,
CLK_PTO_ISPB_SE2_SKIP = 0x38,
CLK_PTO_NVDEC_SKIP = 0x39,
CLK_PTO_NVENC_SKIP = 0x3A,
CLK_PTO_NVJPG_SKIP = 0x3B,
CLK_PTO_TSEC_SKIP = 0x3C,
CLK_PTO_TSECB_SKIP = 0x3D,
CLK_PTO_SE_SKIP = 0x3E,
CLK_PTO_VI_SKIP = 0x3F,
CLK_PTO_VIC = 0x36, CLK_PTO_PLLX_OBS = 0x40,
CLK_PTO_PLLC_OBS = 0x41,
CLK_PTO_PLLM_OBS = 0x42,
CLK_PTO_PLLP_OBS = 0x43,
CLK_PTO_PLLA_OBS = 0x44,
CLK_PTO_PLLMB_OBS = 0x45,
CLK_PTO_SATA_OOB = 0x46,
CLK_PTO_NVDEC = 0x39, CLK_PTO_FCPU_DVFS_DIV12_CPU = 0x48,
CLK_PTO_NVENC = 0x3A, CLK_PTO_EQOS_AXI = 0x4C,
CLK_PTO_NVJPG = 0x3B, CLK_PTO_EQOS_PTP_REF = 0x4D,
CLK_PTO_TSEC = 0x3C, CLK_PTO_EQOS_TX = 0x4E,
CLK_PTO_TSECB = 0x3D, CLK_PTO_EQOS_RX = 0x4F,
CLK_PTO_SE = 0x3E,
CLK_PTO_DSIA_LP = 0x62, CLK_PTO_CILAB = 0x52,
CLK_PTO_CILCD = 0x53,
CLK_PTO_ISP = 0x64, CLK_PTO_CILEF = 0x55,
CLK_PTO_MC = 0x6A, CLK_PTO_PLLA1_PTO_OBS = 0x56,
CLK_PTO_PLLC4_PTO_OBS = 0x57,
CLK_PTO_ACTMON = 0x6B, CLK_PTO_PLLC2_PTO_OBS = 0x59,
CLK_PTO_CSITE = 0x6C, CLK_PTO_PLLC3_PTO_OBS = 0x5B,
CLK_PTO_HOST1X = 0x6F, CLK_PTO_DSIA_LP = 0x62,
CLK_PTO_DSIB_LP = 0x63,
CLK_PTO_ISP = 0x64,
CLK_PTO_PEX_PAD = 0x65,
CLK_PTO_SE_2 = 0x74, // Same as CLK_PTO_SE. CLK_PTO_MC = 0x6A,
CLK_PTO_SOC_THERM = 0x75,
CLK_PTO_TSEC_2 = 0x77, // Same as CLK_PTO_TSEC. CLK_PTO_ACTMON = 0x6B,
CLK_PTO_CSITE = 0x6C,
CLK_PTO_VI_I2C = 0x6D,
CLK_PTO_ACLK = 0x7C, CLK_PTO_HOST1X = 0x6F,
CLK_PTO_QSPI = 0x7D,
CLK_PTO_I2S1 = 0x80, CLK_PTO_QSPI_2X = 0x71,
CLK_PTO_I2S2 = 0x81, CLK_PTO_NVDEC = 0x72,
CLK_PTO_I2S3 = 0x82, CLK_PTO_NVJPG = 0x73,
CLK_PTO_I2S4 = 0x83, CLK_PTO_SE = 0x74,
CLK_PTO_I2S5 = 0x84, CLK_PTO_SOC_THERM = 0x75,
CLK_PTO_AHUB = 0x85,
CLK_PTO_APE = 0x86,
CLK_PTO_DVFS_SOC = 0x88, CLK_PTO_TSEC = 0x77,
CLK_PTO_DVFS_REF = 0x89, CLK_PTO_TSECB = 0x78,
CLK_PTO_VI = 0x79,
CLK_PTO_LA = 0x7A,
CLK_PTO_SCLK_SKIP = 0x7B,
CLK_PTO_SPDIF = 0x8F, CLK_PTO_ADSP_SKIP = 0x7C,
CLK_PTO_SPDIF_IN = 0x90, CLK_PTO_QSPI = 0x7D,
CLK_PTO_SDMMC2_SHAPER = 0x7E,
CLK_PTO_SDMMC4_SHAPER = 0x7F,
CLK_PTO_I2S1 = 0x80,
CLK_PTO_I2S2 = 0x81,
CLK_PTO_I2S3 = 0x82,
CLK_PTO_I2S4 = 0x83,
CLK_PTO_I2S5 = 0x84,
CLK_PTO_AHUB = 0x85,
CLK_PTO_APE = 0x86,
CLK_PTO_DVFS_SOC = 0x88,
CLK_PTO_DVFS_REF = 0x89,
CLK_PTO_ADSP_CLK = 0x8A,
CLK_PTO_ADSP_DIV2_CLK = 0x8B,
CLK_PTO_SPDIF_OUT = 0x8F,
CLK_PTO_SPDIF_IN = 0x90,
CLK_PTO_UART_FST_MIPI_CAL = 0x91, CLK_PTO_UART_FST_MIPI_CAL = 0x91,
CLK_PTO_SYS2HSIO_SATA_CLK = 0x92,
CLK_PTO_PWM = 0x93,
CLK_PTO_I2C1 = 0x94,
CLK_PTO_I2C2 = 0x95,
CLK_PTO_I2C3 = 0x96,
CLK_PTO_I2C4 = 0x97,
CLK_PTO_I2C5 = 0x98,
CLK_PTO_I2C6 = 0x99,
CLK_PTO_I2C_SLOW = 0x9A,
CLK_PTO_UARTAPE = 0x9B,
CLK_PTO_PWM = 0x93, CLK_PTO_EXTPERIPH1 = 0x9D,
CLK_PTO_I2C1 = 0x94, CLK_PTO_EXTPERIPH2 = 0x9E,
CLK_PTO_I2C2 = 0x95, CLK_PTO_EXTPERIPH3 = 0x9F,
CLK_PTO_I2C3 = 0x96, CLK_PTO_ENTROPY = 0xA0,
CLK_PTO_I2C4 = 0x97, CLK_PTO_UARTA = 0xA1,
CLK_PTO_I2C5 = 0x98, CLK_PTO_UARTB = 0xA2,
CLK_PTO_I2C6 = 0x99, CLK_PTO_UARTC = 0xA3,
CLK_PTO_I2C_SLOW = 0x9A, CLK_PTO_UARTD = 0xA4,
CLK_PTO_UARTAPE = 0x9B, CLK_PTO_OWR = 0xA5,
CLK_PTO_TSENSOR = 0xA6,
CLK_PTO_HDA2CODEC_2X = 0xA7,
CLK_PTO_HDA = 0xA8,
CLK_PTO_EMC_LATENCY = 0xA9,
CLK_PTO_EMC_DLL = 0xAA,
CLK_PTO_SDMMC_LEGACY_TM = 0xAB,
CLK_PTO_DBGAPB = 0xAC,
CLK_PTO_EXTPERIPH1 = 0x9D, CLK_PTO_SOR0 = 0xC0,
CLK_PTO_EXTPERIPH2 = 0x9E, CLK_PTO_SOR1 = 0xC1,
CLK_PTO_HDMI = 0xC2,
CLK_PTO_ENTROPY = 0xA0, CLK_PTO_DISP2 = 0xC4,
CLK_PTO_UARTA = 0xA1, CLK_PTO_DISP1 = 0xC5,
CLK_PTO_UARTB = 0xA2,
CLK_PTO_UARTC = 0xA3,
CLK_PTO_UARTD = 0xA4,
CLK_PTO_OWR = 0xA5,
CLK_PTO_HDA2CODEC_2X = 0xA7, CLK_PTO_PLLD_OBS = 0xCA,
CLK_PTO_HDA = 0xA8, CLK_PTO_PLLD2_PTO_OBS = 0xCC,
CLK_PTO_PLLDP_OBS = 0xCE,
CLK_PTO_PLLE_OBS = 0x10A,
CLK_PTO_PLLU_OBS = 0x10C,
CLK_PTO_PLLREFE_OBS = 0x10E,
CLK_PTO_SDMMC_LEGACY_TM = 0xAB, CLK_PTO_XUSB_FALCON = 0x110,
CLK_PTO_XUSB_CLK480M_HSIC = 0x111,
CLK_PTO_USB_L0_RX = 0x112,
CLK_PTO_USB_L3_RX = 0x113,
CLK_PTO_USB_RX = 0x114,
CLK_PTO_USB3_L0_TXCLKREF = 0x115,
CLK_PTO_PEX_TXCLKREF_SWITCH_TMS = 0x116,
CLK_PTO_PEX_TXCLKREF_SWITCH_GRP0 = 0x117,
CLK_PTO_PEX_TXCLKREF_SWITCH_GRP1 = 0x118,
CLK_PTO_PEX_TXCLKREF_SWITCH_GRP2 = 0x119,
CLK_PTO_PEX_L4_RX = 0x11A,
CLK_PTO_PEX_TXCLKREF = 0x11B,
CLK_PTO_PEX_TXCLKREF_DIV2 = 0x11C,
CLK_PTO_PEX_TXCLKREF2 = 0x11D,
CLK_PTO_PEX_L0_RX = 0x11E,
CLK_PTO_PEX_L1_RX = 0x11F,
CLK_PTO_PEX_L2_RX = 0x120,
CLK_PTO_PEX_L3_RX = 0x121,
CLK_PTO_SATA_TXCLKREF = 0x122,
CLK_PTO_SATA_TXCLKREF_DIV2 = 0x123,
CLK_PTO_USB_L5_RX = 0x124,
CLK_PTO_SATA_TX = 0x125,
CLK_PTO_SATA_L0_RX = 0x126,
CLK_PTO_SOR0 = 0xC0, CLK_PTO_USB3_L1_TXCLKREF = 0x129,
CLK_PTO_SOR1 = 0xC1, CLK_PTO_USB3_L7_TXCLKREF = 0x12A,
CLK_PTO_USB3_L7_RX = 0x12B,
CLK_PTO_USB3_TX = 0x12C,
CLK_PTO_UTMIP_PLL_PAD = 0x12D,
CLK_PTO_DISP2 = 0xC4, CLK_PTO_XUSB_FS = 0x136,
CLK_PTO_DISP1 = 0xC5, CLK_PTO_XUSB_SS_HOST_DEV = 0x137,
CLK_PTO_XUSB_CORE_HOST = 0x138,
CLK_PTO_XUSB_CORE_DEV = 0x139,
CLK_PTO_XUSB_FALCON = 0x110, CLK_PTO_USB3_L2_TXCLKREF = 0x13C,
CLK_PTO_USB3_L3_TXCLKREF = 0x13D,
CLK_PTO_XUSB_FS = 0x136, CLK_PTO_USB_L4_RX = 0x13E,
CLK_PTO_XUSB_SS_HOST_DEV = 0x137, CLK_PTO_USB_L6_RX = 0x13F,
CLK_PTO_XUSB_CORE_HOST = 0x138,
CLK_PTO_XUSB_CORE_DEV = 0x139,
/* /*
* PLL need PTO enabled in MISC registers. * PLL need PTO enabled in MISC registers.
* Normal div is 2 so result is multiplied with it. * Normal div is 2 so result is multiplied with it.
*/ */
CLK_PTO_PLLC_DIV2 = 0x01, CLK_PTO_PLLC_DIV2 = 0x01,
CLK_PTO_PLLM_DIV2 = 0x02, CLK_PTO_PLLM_DIV2 = 0x02,
CLK_PTO_PLLP_DIV2 = 0x03, CLK_PTO_PLLP_DIV2 = 0x03,
CLK_PTO_PLLA_DIV2 = 0x04, CLK_PTO_PLLA_DIV2 = 0x04,
CLK_PTO_PLLX_DIV2 = 0x05, CLK_PTO_PLLX_DIV2 = 0x05,
CLK_PTO_PLLMB_DIV2 = 0x25, CLK_PTO_PLLMB_DIV2 = 0x25,
CLK_PTO_PLLC4_DIV2 = 0x51, CLK_PTO_PLLC4_DIV2 = 0x51,
CLK_PTO_PLLA1_DIV2 = 0x55, CLK_PTO_PLLA1_DIV2 = 0x55,
CLK_PTO_PLLC2_DIV2 = 0x58, CLK_PTO_PLLC2_DIV2 = 0x58,
CLK_PTO_PLLC3_DIV2 = 0x5A, CLK_PTO_PLLC3_DIV2 = 0x5A,
CLK_PTO_PLLD_DIV2 = 0xCB, CLK_PTO_PLLD_DIV2 = 0xCB,
CLK_PTO_PLLD2_DIV2 = 0xCD, CLK_PTO_PLLD2_DIV2 = 0xCD,
CLK_PTO_PLLDP_DIV2 = 0xCF, CLK_PTO_PLLDP_DIV2 = 0xCF,
CLK_PTO_PLLU_DIV2 = 0x10D, CLK_PTO_PLLE_DIV2 = 0x10B,
CLK_PTO_PLLREFE_DIV2 = 0x10F, CLK_PTO_PLLU_DIV2 = 0x10D,
CLK_PTO_PLLREFE_DIV2 = 0x10F,
} clock_pto_id_t; } clock_pto_id_t;
/* /*
@@ -618,7 +719,7 @@ enum CLK_Y_DEV
}; };
/*! Generic clock descriptor. */ /*! Generic clock descriptor. */
typedef struct _clock_t typedef struct _clk_rst_t
{ {
u16 reset; u16 reset;
u16 enable; u16 enable;
@@ -626,11 +727,11 @@ typedef struct _clock_t
u8 index; u8 index;
u8 clk_src; u8 clk_src;
u8 clk_div; u8 clk_div;
} clock_t; } clk_rst_t;
/*! Generic clock enable/disable. */ /*! Generic clock enable/disable. */
void clock_enable(const clock_t *clk); void clock_enable(const clk_rst_t *clk);
void clock_disable(const clock_t *clk); void clock_disable(const clk_rst_t *clk);
/*! Clock control for specific hardware portions. */ /*! Clock control for specific hardware portions. */
void clock_enable_fuse(bool enable); void clock_enable_fuse(bool enable);
@@ -645,6 +746,12 @@ void clock_enable_host1x();
void clock_disable_host1x(); void clock_disable_host1x();
void clock_enable_tsec(); void clock_enable_tsec();
void clock_disable_tsec(); void clock_disable_tsec();
void clock_enable_nvdec();
void clock_disable_nvdec();
void clock_enable_nvjpg();
void clock_disable_nvjpg();
void clock_enable_vic();
void clock_disable_vic();
void clock_enable_sor_safe(); void clock_enable_sor_safe();
void clock_disable_sor_safe(); void clock_disable_sor_safe();
void clock_enable_sor0(); void clock_enable_sor0();
@@ -659,12 +766,25 @@ void clock_enable_coresight();
void clock_disable_coresight(); void clock_disable_coresight();
void clock_enable_pwm(); void clock_enable_pwm();
void clock_disable_pwm(); void clock_disable_pwm();
void clock_enable_apbdma();
void clock_disable_apbdma();
void clock_enable_ahbdma();
void clock_disable_ahbdma();
void clock_enable_actmon();
void clock_disable_actmon();
void clock_enable_extperiph1();
void clock_disable_extperiph1();
void clock_enable_extperiph2();
void clock_disable_extperiph2();
void clock_enable_plld(u32 divp, u32 divn, bool lowpower, bool tegra_t210);
void clock_enable_pllx(); void clock_enable_pllx();
void clock_enable_pllc(u32 divn); void clock_enable_pllc(u32 divn);
void clock_disable_pllc(); void clock_disable_pllc();
void clock_enable_pllu(); void clock_enable_pllu();
void clock_disable_pllu(); void clock_disable_pllu();
void clock_enable_utmipll(); void clock_enable_utmipll();
void clock_sdmmc_config_clock_source(u32 *pclock, u32 id, u32 val); void clock_sdmmc_config_clock_source(u32 *pclock, u32 id, u32 val);
void clock_sdmmc_get_card_clock_div(u32 *pclock, u16 *pdivisor, u32 type); void clock_sdmmc_get_card_clock_div(u32 *pclock, u16 *pdivisor, u32 type);
int clock_sdmmc_is_not_reset_and_enabled(u32 id); int clock_sdmmc_is_not_reset_and_enabled(u32 id);

View File

@@ -2,8 +2,7 @@
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018 shuffle2 * Copyright (c) 2018 shuffle2
* Copyright (c) 2018 balika011 * Copyright (c) 2018 balika011
* Copyright (c) 2019-2021 CTCaer * Copyright (c) 2019-2022 CTCaer
* Copyright (c) 2021 shchmue
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -20,6 +19,7 @@
#include <string.h> #include <string.h>
#include <mem/heap.h>
#include <sec/se.h> #include <sec/se.h>
#include <sec/se_t210.h> #include <sec/se_t210.h>
#include <soc/fuse.h> #include <soc/fuse.h>
@@ -43,12 +43,19 @@ static const u32 evp_thunk_template[] = {
0xe3822001, // ORR R2, R2, #1 0xe3822001, // ORR R2, R2, #1
0xe8bd0003, // LDMFD SP!, {R0,R1} 0xe8bd0003, // LDMFD SP!, {R0,R1}
0xe12fff12, // BX R2 0xe12fff12, // BX R2
// idx: 15:
0x001007b0, // off_1007EC DCD evp_thunk_template 0x001007b0, // off_1007EC DCD evp_thunk_template
0x001007f8, // off_1007F0 DCD thunk_end 0x001007f8, // off_1007F0 DCD thunk_end
0x40004c30, // off_1007F4 DCD iram_evp_thunks 0x40004c30, // off_1007F4 DCD iram_evp_thunks
// thunk_end is here // thunk_end is here
}; };
static const u32 evp_thunk_template_len = sizeof(evp_thunk_template);
static const u32 evp_thunk_func_offsets_t210b01[] = {
0x0010022c, // off_100268 DCD evp_thunk_template
0x00100174, // off_10026C DCD thunk_end
0x40004164, // off_100270 DCD iram_evp_thunks
// thunk_end is here
};
// treated as 12bit values // treated as 12bit values
static const u32 hash_vals[] = {1, 2, 4, 8, 0, 3, 5, 6, 7, 9, 10, 11}; static const u32 hash_vals[] = {1, 2, 4, 8, 0, 3, 5, 6, 7, 9, 10, 11};
@@ -79,30 +86,28 @@ u32 fuse_read_odm_keygen_rev()
return 0; return 0;
} }
u32 fuse_read_bootrom_rev()
{
u32 rev = FUSE(FUSE_SOC_SPEEDO_1_CALIB);
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210)
return rev;
else
return rev | (1 << 12);
}
u32 fuse_read_dramid(bool raw_id) u32 fuse_read_dramid(bool raw_id)
{ {
u32 dramid = (fuse_read_odm(4) & 0xF8) >> 3; bool tegra_t210 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210;
u32 odm4 = fuse_read_odm(4);
u32 dramid = (odm4 & 0xF8) >> 3;
// Get extended dram id info.
if (!tegra_t210)
dramid |= (odm4 & 0x7000) >> 7;
if (raw_id) if (raw_id)
return dramid; return dramid;
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210) if (tegra_t210)
{ {
if (dramid > 6) if (dramid > 7)
dramid = 0; dramid = 0;
} }
else else
{ {
if (dramid > 28) if (dramid > 34)
dramid = 8; dramid = 8;
} }
@@ -180,7 +185,8 @@ u32 fuse_read(u32 addr)
void fuse_read_array(u32 *words) void fuse_read_array(u32 *words)
{ {
u32 array_size = (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01) ? 256 : 192; u32 array_size = (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01) ?
FUSE_ARRAY_WORDS_NUM_T210B01 : FUSE_ARRAY_WORDS_NUM;
for (u32 i = 0; i < array_size; i++) for (u32 i = 0; i < array_size; i++)
words[i] = fuse_read(i); words[i] = fuse_read(i);
@@ -190,9 +196,8 @@ static u32 _parity32_even(u32 *words, u32 count)
{ {
u32 acc = words[0]; u32 acc = words[0];
for (u32 i = 1; i < count; i++) for (u32 i = 1; i < count; i++)
{
acc ^= words[i]; acc ^= words[i];
}
u32 lo = ((acc & 0xffff) ^ (acc >> 16)) & 0xff; u32 lo = ((acc & 0xffff) ^ (acc >> 16)) & 0xff;
u32 hi = ((acc & 0xffff) ^ (acc >> 16)) >> 8; u32 hi = ((acc & 0xffff) ^ (acc >> 16)) >> 8;
u32 x = hi ^ lo; u32 x = hi ^ lo;
@@ -208,26 +213,26 @@ static int _patch_hash_one(u32 *word)
u32 bits20_31 = *word & 0xfff00000; u32 bits20_31 = *word & 0xfff00000;
u32 parity_bit = _parity32_even(&bits20_31, 1); u32 parity_bit = _parity32_even(&bits20_31, 1);
u32 hash = 0; u32 hash = 0;
for (u32 i = 0; i < 12; i++) for (u32 i = 0; i < 12; i++)
{ {
if (*word & (1 << (20 + i))) if (*word & (1 << (20 + i)))
{
hash ^= hash_vals[i]; hash ^= hash_vals[i];
}
} }
if (hash == 0) if (hash == 0)
{ {
if (parity_bit == 0) if (parity_bit == 0)
{
return 0; return 0;
}
*word ^= 1 << 24; *word ^= 1 << 24;
return 1; return 1;
} }
if (parity_bit == 0) if (parity_bit == 0)
{
return 3; return 3;
}
for (u32 i = 0; i < ARRAY_SIZE(hash_vals); i++) for (u32 i = 0; i < ARRAY_SIZE(hash_vals); i++)
{ {
if (hash_vals[i] == hash) if (hash_vals[i] == hash)
@@ -236,6 +241,7 @@ static int _patch_hash_one(u32 *word)
return 1; return 1;
} }
} }
return 2; return 2;
} }
@@ -256,9 +262,7 @@ static int _patch_hash_multi(u32 *words, u32 count)
for (u32 bitpos = 0; bitpos < 32; bitpos++) for (u32 bitpos = 0; bitpos < 32; bitpos++)
{ {
if ((w >> bitpos) & 1) if ((w >> bitpos) & 1)
{
hash ^= 0x4000 + i * 32 + bitpos; hash ^= 0x4000 + i * 32 + bitpos;
}
} }
} }
} }
@@ -270,16 +274,14 @@ static int _patch_hash_multi(u32 *words, u32 count)
if (hash == 0) if (hash == 0)
{ {
if (parity_bit == 0) if (parity_bit == 0)
{
return 0; return 0;
}
words[0] ^= 0x8000; words[0] ^= 0x8000;
return 1; return 1;
} }
if (parity_bit == 0) if (parity_bit == 0)
{
return 3; return 3;
}
u32 bitcount = hash - 0x4000; u32 bitcount = hash - 0x4000;
if (bitcount < 16 || bitcount >= count * 32) if (bitcount < 16 || bitcount >= count * 32)
{ {
@@ -287,14 +289,11 @@ static int _patch_hash_multi(u32 *words, u32 count)
for (u32 bitpos = 0; bitpos < 15; bitpos++) for (u32 bitpos = 0; bitpos < 15; bitpos++)
{ {
if ((hash >> bitpos) & 1) if ((hash >> bitpos) & 1)
{
num_set++; num_set++;
}
} }
if (num_set != 1) if (num_set != 1)
{
return 2; return 2;
}
words[0] ^= hash; words[0] ^= hash;
return 1; return 1;
} }
@@ -312,24 +311,30 @@ int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value))
word_count = FUSE(FUSE_FIRST_BOOTROM_PATCH_SIZE); word_count = FUSE(FUSE_FIRST_BOOTROM_PATCH_SIZE);
word_count &= 0x7F; word_count &= 0x7F;
word_addr = 191; word_addr = FUSE_ARRAY_WORDS_NUM - 1;
while (word_count) while (word_count)
{ {
total_read += word_count; total_read += word_count;
if (total_read >= ARRAY_SIZE(words)) if (total_read >= ARRAY_SIZE(words))
{
break; break;
}
for (u32 i = 0; i < word_count; i++) for (u32 i = 0; i < word_count; i++)
{
words[i] = fuse_read(word_addr--); words[i] = fuse_read(word_addr--);
// Parse extra T210B01 fuses when the difference is reached.
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01 &&
word_addr == ((FUSE_ARRAY_WORDS_NUM - 1) -
(FUSE_ARRAY_WORDS_NUM_T210B01 - FUSE_ARRAY_WORDS_NUM) / sizeof(u32)))
{
word_addr = FUSE_ARRAY_WORDS_NUM_T210B01 - 1;
}
}
word0 = words[0]; word0 = words[0];
if (_patch_hash_multi(words, word_count) >= 2) if (_patch_hash_multi(words, word_count) >= 2)
{
return 1; return 1;
}
u32 ipatch_count = (words[0] >> 16) & 0xF; u32 ipatch_count = (words[0] >> 16) & 0xF;
if (ipatch_count) if (ipatch_count)
{ {
@@ -342,13 +347,14 @@ int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value))
ipatch(addr, data); ipatch(addr, data);
} }
} }
words[0] = word0; words[0] = word0;
if ((word0 >> 25) == 0) if ((word0 >> 25) == 0)
break; break;
if (_patch_hash_one(&word0) >= 2) if (_patch_hash_one(&word0) >= 2)
{
return 3; return 3;
}
word_count = word0 >> 25; word_count = word0 >> 25;
} }
@@ -364,29 +370,44 @@ int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len)
u32 total_read = 0; u32 total_read = 0;
int evp_thunk_written = 0; int evp_thunk_written = 0;
void *evp_thunk_dst_addr = 0; void *evp_thunk_dst_addr = 0;
bool t210b01 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01;
u32 *evp_thunk_tmp = (u32 *)malloc(sizeof(evp_thunk_template));
memcpy(evp_thunk_tmp, evp_thunk_template, sizeof(evp_thunk_template));
memset(iram_evp_thunks, 0, *iram_evp_thunks_len); memset(iram_evp_thunks, 0, *iram_evp_thunks_len);
if (t210b01)
memcpy(&evp_thunk_tmp[15], evp_thunk_func_offsets_t210b01, sizeof(evp_thunk_func_offsets_t210b01));
word_count = FUSE(FUSE_FIRST_BOOTROM_PATCH_SIZE); word_count = FUSE(FUSE_FIRST_BOOTROM_PATCH_SIZE);
word_count &= 0x7F; word_count &= 0x7F;
word_addr = 191; word_addr = FUSE_ARRAY_WORDS_NUM - 1;
while (word_count) while (word_count)
{ {
total_read += word_count; total_read += word_count;
if (total_read >= ARRAY_SIZE(words)) if (total_read >= ARRAY_SIZE(words))
{
break; break;
}
for (u32 i = 0; i < word_count; i++) for (u32 i = 0; i < word_count; i++)
{
words[i] = fuse_read(word_addr--); words[i] = fuse_read(word_addr--);
// Parse extra T210B01 fuses when the difference is reached.
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01 &&
word_addr == ((FUSE_ARRAY_WORDS_NUM - 1) -
(FUSE_ARRAY_WORDS_NUM_T210B01 - FUSE_ARRAY_WORDS_NUM) / sizeof(u32)))
{
word_addr = FUSE_ARRAY_WORDS_NUM_T210B01 - 1;
}
}
word0 = words[0]; word0 = words[0];
if (_patch_hash_multi(words, word_count) >= 2) if (_patch_hash_multi(words, word_count) >= 2)
{ {
free(evp_thunk_tmp);
return 1; return 1;
} }
u32 ipatch_count = (words[0] >> 16) & 0xF; u32 ipatch_count = (words[0] >> 16) & 0xF;
u32 insn_count = word_count - ipatch_count - 1; u32 insn_count = word_count - ipatch_count - 1;
if (insn_count) if (insn_count)
@@ -395,10 +416,10 @@ int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len)
{ {
evp_thunk_dst_addr = (void *)iram_evp_thunks; evp_thunk_dst_addr = (void *)iram_evp_thunks;
memcpy(evp_thunk_dst_addr, (void *)evp_thunk_template, evp_thunk_template_len); memcpy(evp_thunk_dst_addr, (void *)evp_thunk_tmp, sizeof(evp_thunk_template));
evp_thunk_dst_addr += evp_thunk_template_len; evp_thunk_dst_addr += sizeof(evp_thunk_template);
evp_thunk_written = 1; evp_thunk_written = 1;
*iram_evp_thunks_len = evp_thunk_template_len; *iram_evp_thunks_len = sizeof(evp_thunk_template);
//write32(TEGRA_EXCEPTION_VECTORS_BASE + 0x208, iram_evp_thunks); //write32(TEGRA_EXCEPTION_VECTORS_BASE + 0x208, iram_evp_thunks);
} }
@@ -408,16 +429,22 @@ int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len)
evp_thunk_dst_addr += thunk_patch_len; evp_thunk_dst_addr += thunk_patch_len;
*iram_evp_thunks_len += thunk_patch_len; *iram_evp_thunks_len += thunk_patch_len;
} }
words[0] = word0; words[0] = word0;
if ((word0 >> 25) == 0) if ((word0 >> 25) == 0)
break; break;
if (_patch_hash_one(&word0) >= 2) if (_patch_hash_one(&word0) >= 2)
{ {
free(evp_thunk_tmp);
return 3; return 3;
} }
word_count = word0 >> 25; word_count = word0 >> 25;
} }
free(evp_thunk_tmp);
return 0; return 0;
} }
@@ -429,7 +456,7 @@ bool fuse_check_patched_rcm()
// Check if RCM is ipatched. // Check if RCM is ipatched.
u32 word_count = FUSE(FUSE_FIRST_BOOTROM_PATCH_SIZE) & 0x7F; u32 word_count = FUSE(FUSE_FIRST_BOOTROM_PATCH_SIZE) & 0x7F;
u32 word_addr = 191; u32 word_addr = FUSE_ARRAY_WORDS_NUM - 1;
while (word_count) while (word_count)
{ {

View File

@@ -2,8 +2,7 @@
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018 shuffle2 * Copyright (c) 2018 shuffle2
* Copyright (c) 2018 balika011 * Copyright (c) 2018 balika011
* Copyright (c) 2019-2021 CTCaer * Copyright (c) 2019-2022 CTCaer
* Copyright (c) 2021 shchmue
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -38,6 +37,8 @@
#define FUSE_DISABLEREGPROGRAM 0x2C #define FUSE_DISABLEREGPROGRAM 0x2C
#define FUSE_WRITE_ACCESS_SW 0x30 #define FUSE_WRITE_ACCESS_SW 0x30
#define FUSE_PWR_GOOD_SW 0x34 #define FUSE_PWR_GOOD_SW 0x34
/*! Fuse Cached registers */
#define FUSE_SKU_INFO 0x110 #define FUSE_SKU_INFO 0x110
#define FUSE_CPU_SPEEDO_0_CALIB 0x114 #define FUSE_CPU_SPEEDO_0_CALIB 0x114
#define FUSE_CPU_IDDQ_CALIB 0x118 #define FUSE_CPU_IDDQ_CALIB 0x118
@@ -65,8 +66,10 @@
#define FUSE_OPT_WAFER_ID 0x210 #define FUSE_OPT_WAFER_ID 0x210
#define FUSE_OPT_X_COORDINATE 0x214 #define FUSE_OPT_X_COORDINATE 0x214
#define FUSE_OPT_Y_COORDINATE 0x218 #define FUSE_OPT_Y_COORDINATE 0x218
#define FUSE_OPT_OPS_RESERVED 0x220
#define FUSE_GPU_IDDQ_CALIB 0x228 #define FUSE_GPU_IDDQ_CALIB 0x228
#define FUSE_USB_CALIB_EXT 0x350 #define FUSE_USB_CALIB_EXT 0x350
#define FUSE_RESERVED_FIELD 0x354
#define FUSE_RESERVED_ODM28_T210B01 0x240 #define FUSE_RESERVED_ODM28_T210B01 0x240
@@ -79,6 +82,9 @@
/*! Fuse cache registers. */ /*! Fuse cache registers. */
#define FUSE_RESERVED_ODMX(x) (0x1C8 + 4 * (x)) #define FUSE_RESERVED_ODMX(x) (0x1C8 + 4 * (x))
#define FUSE_ARRAY_WORDS_NUM 192
#define FUSE_ARRAY_WORDS_NUM_T210B01 256
enum enum
{ {
FUSE_NX_HW_TYPE_ICOSA, FUSE_NX_HW_TYPE_ICOSA,
@@ -96,7 +102,6 @@ enum
void fuse_disable_program(); void fuse_disable_program();
u32 fuse_read_odm(u32 idx); u32 fuse_read_odm(u32 idx);
u32 fuse_read_odm_keygen_rev(); u32 fuse_read_odm_keygen_rev();
u32 fuse_read_bootrom_rev();
u32 fuse_read_dramid(bool raw_id); u32 fuse_read_dramid(bool raw_id);
u32 fuse_read_hw_state(); u32 fuse_read_hw_state();
u32 fuse_read_hw_type(); u32 fuse_read_hw_type();

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2019 CTCaer * Copyright (c) 2019-2023 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -18,23 +18,27 @@
#include <soc/gpio.h> #include <soc/gpio.h>
#include <soc/t210.h> #include <soc/t210.h>
#define GPIO_BANK_IDX(port) ((port) >> 2) #define GPIO_BANK_IDX(port) ((port) >> 2)
#define GPIO_PORT_OFFSET(port) ((GPIO_BANK_IDX(port) << 8) + (((port) % 4) << 2))
#define GPIO_CNF_OFFSET(port) (0x00 + (((port) >> 2) << 8) + (((port) % 4) << 2)) #define GPIO_CNF_OFFSET(port) (0x00 + GPIO_PORT_OFFSET(port))
#define GPIO_OE_OFFSET(port) (0x10 + (((port) >> 2) << 8) + (((port) % 4) << 2)) #define GPIO_OE_OFFSET(port) (0x10 + GPIO_PORT_OFFSET(port))
#define GPIO_OUT_OFFSET(port) (0x20 + (((port) >> 2) << 8) + (((port) % 4) << 2)) #define GPIO_OUT_OFFSET(port) (0x20 + GPIO_PORT_OFFSET(port))
#define GPIO_IN_OFFSET(port) (0x30 + (((port) >> 2) << 8) + (((port) % 4) << 2)) #define GPIO_IN_OFFSET(port) (0x30 + GPIO_PORT_OFFSET(port))
#define GPIO_INT_STA_OFFSET(port) (0x40 + (((port) >> 2) << 8) + (((port) % 4) << 2)) #define GPIO_INT_STA_OFFSET(port) (0x40 + GPIO_PORT_OFFSET(port))
#define GPIO_INT_ENB_OFFSET(port) (0x50 + (((port) >> 2) << 8) + (((port) % 4) << 2)) #define GPIO_INT_ENB_OFFSET(port) (0x50 + GPIO_PORT_OFFSET(port))
#define GPIO_INT_LVL_OFFSET(port) (0x60 + (((port) >> 2) << 8) + (((port) % 4) << 2)) #define GPIO_INT_LVL_OFFSET(port) (0x60 + GPIO_PORT_OFFSET(port))
#define GPIO_INT_CLR_OFFSET(port) (0x70 + (((port) >> 2) << 8) + (((port) % 4) << 2)) #define GPIO_INT_CLR_OFFSET(port) (0x70 + GPIO_PORT_OFFSET(port))
#define GPIO_CNF_MASKED_OFFSET(port) (0x80 + (((port) >> 2) << 8) + (((port) % 4) << 2)) #define GPIO_CNF_MASKED_OFFSET(port) (0x80 + GPIO_PORT_OFFSET(port))
#define GPIO_OE_MASKED_OFFSET(port) (0x90 + (((port) >> 2) << 8) + (((port) % 4) << 2)) #define GPIO_OE_MASKED_OFFSET(port) (0x90 + GPIO_PORT_OFFSET(port))
#define GPIO_OUT_MASKED_OFFSET(port) (0xA0 + (((port) >> 2) << 8) + (((port) % 4) << 2)) #define GPIO_OUT_MASKED_OFFSET(port) (0xA0 + GPIO_PORT_OFFSET(port))
#define GPIO_INT_STA_MASKED_OFFSET(port) (0xC0 + (((port) >> 2) << 8) + (((port) % 4) << 2)) #define GPIO_INT_STA_MASKED_OFFSET(port) (0xC0 + GPIO_PORT_OFFSET(port))
#define GPIO_INT_ENB_MASKED_OFFSET(port) (0xD0 + (((port) >> 2) << 8) + (((port) % 4) << 2)) #define GPIO_INT_ENB_MASKED_OFFSET(port) (0xD0 + GPIO_PORT_OFFSET(port))
#define GPIO_INT_LVL_MASKED_OFFSET(port) (0xE0 + (((port) >> 2) << 8) + (((port) % 4) << 2)) #define GPIO_INT_LVL_MASKED_OFFSET(port) (0xE0 + GPIO_PORT_OFFSET(port))
#define GPIO_DB_CTRL_OFFSET(port) (0xB0 + GPIO_PORT_OFFSET(port))
#define GPIO_DB_CNT_OFFSET(port) (0xF0 + GPIO_PORT_OFFSET(port))
#define GPIO_IRQ_BANK1 32 #define GPIO_IRQ_BANK1 32
#define GPIO_IRQ_BANK2 33 #define GPIO_IRQ_BANK2 33
@@ -52,7 +56,7 @@ static u8 gpio_bank_irq_ids[8] = {
void gpio_config(u32 port, u32 pins, int mode) void gpio_config(u32 port, u32 pins, int mode)
{ {
u32 offset = GPIO_CNF_OFFSET(port); const u32 offset = GPIO_CNF_OFFSET(port);
if (mode) if (mode)
GPIO(offset) |= pins; GPIO(offset) |= pins;
@@ -64,7 +68,7 @@ void gpio_config(u32 port, u32 pins, int mode)
void gpio_output_enable(u32 port, u32 pins, int enable) void gpio_output_enable(u32 port, u32 pins, int enable)
{ {
u32 port_offset = GPIO_OE_OFFSET(port); const u32 port_offset = GPIO_OE_OFFSET(port);
if (enable) if (enable)
GPIO(port_offset) |= pins; GPIO(port_offset) |= pins;
@@ -76,7 +80,7 @@ void gpio_output_enable(u32 port, u32 pins, int enable)
void gpio_write(u32 port, u32 pins, int high) void gpio_write(u32 port, u32 pins, int high)
{ {
u32 port_offset = GPIO_OUT_OFFSET(port); const u32 port_offset = GPIO_OUT_OFFSET(port);
if (high) if (high)
GPIO(port_offset) |= pins; GPIO(port_offset) |= pins;
@@ -86,16 +90,49 @@ void gpio_write(u32 port, u32 pins, int high)
(void)GPIO(port_offset); // Commit the write. (void)GPIO(port_offset); // Commit the write.
} }
void gpio_direction_input(u32 port, u32 pins)
{
gpio_config(port, pins, GPIO_MODE_GPIO);
gpio_output_enable(port, pins, GPIO_OUTPUT_DISABLE);
}
void gpio_direction_output(u32 port, u32 pins, int high)
{
gpio_config(port, pins, GPIO_MODE_GPIO);
gpio_write(port, pins, high);
gpio_output_enable(port, pins, GPIO_OUTPUT_ENABLE);
}
int gpio_read(u32 port, u32 pins) int gpio_read(u32 port, u32 pins)
{ {
u32 port_offset = GPIO_IN_OFFSET(port); const u32 port_offset = GPIO_IN_OFFSET(port);
return (GPIO(port_offset) & pins) ? 1 : 0; return (GPIO(port_offset) & pins) ? 1 : 0;
} }
void gpio_set_debounce(u32 port, u32 pins, u32 ms)
{
const u32 db_ctrl_offset = GPIO_DB_CTRL_OFFSET(port);
const u32 db_cnt_offset = GPIO_DB_CNT_OFFSET(port);
if (ms)
{
if (ms > 255)
ms = 255;
// Debounce time affects all pins of the same port.
GPIO(db_cnt_offset) = ms;
GPIO(db_ctrl_offset) = (pins << 8) | pins;
}
else
GPIO(db_ctrl_offset) = (pins << 8) | 0;
(void)GPIO(db_ctrl_offset); // Commit the write.
}
static void _gpio_interrupt_clear(u32 port, u32 pins) static void _gpio_interrupt_clear(u32 port, u32 pins)
{ {
u32 port_offset = GPIO_INT_CLR_OFFSET(port); const u32 port_offset = GPIO_INT_CLR_OFFSET(port);
GPIO(port_offset) |= pins; GPIO(port_offset) |= pins;
@@ -104,10 +141,10 @@ static void _gpio_interrupt_clear(u32 port, u32 pins)
int gpio_interrupt_status(u32 port, u32 pins) int gpio_interrupt_status(u32 port, u32 pins)
{ {
u32 port_offset = GPIO_INT_STA_OFFSET(port); const u32 port_offset = GPIO_INT_STA_OFFSET(port);
u32 enabled = GPIO(GPIO_INT_ENB_OFFSET(port)) & pins; const u32 enabled_mask = GPIO(GPIO_INT_ENB_OFFSET(port)) & pins;
int status = ((GPIO(port_offset) & pins) && enabled) ? 1 : 0; int status = ((GPIO(port_offset) & pins) && enabled_mask) ? 1 : 0;
// Clear the interrupt status. // Clear the interrupt status.
if (status) if (status)
@@ -118,7 +155,7 @@ int gpio_interrupt_status(u32 port, u32 pins)
void gpio_interrupt_enable(u32 port, u32 pins, int enable) void gpio_interrupt_enable(u32 port, u32 pins, int enable)
{ {
u32 port_offset = GPIO_INT_ENB_OFFSET(port); const u32 port_offset = GPIO_INT_ENB_OFFSET(port);
// Clear any possible stray interrupt. // Clear any possible stray interrupt.
_gpio_interrupt_clear(port, pins); _gpio_interrupt_clear(port, pins);
@@ -133,7 +170,7 @@ void gpio_interrupt_enable(u32 port, u32 pins, int enable)
void gpio_interrupt_level(u32 port, u32 pins, int high, int edge, int delta) void gpio_interrupt_level(u32 port, u32 pins, int high, int edge, int delta)
{ {
u32 port_offset = GPIO_INT_LVL_OFFSET(port); const u32 port_offset = GPIO_INT_LVL_OFFSET(port);
u32 val = GPIO(port_offset); u32 val = GPIO(port_offset);
@@ -162,7 +199,7 @@ void gpio_interrupt_level(u32 port, u32 pins, int high, int edge, int delta)
u32 gpio_get_bank_irq_id(u32 port) u32 gpio_get_bank_irq_id(u32 port)
{ {
u32 bank_idx = GPIO_BANK_IDX(port); const u32 bank_idx = GPIO_BANK_IDX(port);
return gpio_bank_irq_ids[bank_idx]; return gpio_bank_irq_ids[bank_idx];
} }

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2019 CTCaer * Copyright (c) 2019-2023 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -85,8 +85,11 @@
void gpio_config(u32 port, u32 pins, int mode); void gpio_config(u32 port, u32 pins, int mode);
void gpio_output_enable(u32 port, u32 pins, int enable); void gpio_output_enable(u32 port, u32 pins, int enable);
void gpio_direction_input(u32 port, u32 pins);
void gpio_direction_output(u32 port, u32 pins, int high);
void gpio_write(u32 port, u32 pins, int high); void gpio_write(u32 port, u32 pins, int high);
int gpio_read(u32 port, u32 pins); int gpio_read(u32 port, u32 pins);
void gpio_set_debounce(u32 port, u32 pins, u32 ms);
int gpio_interrupt_status(u32 port, u32 pins); int gpio_interrupt_status(u32 port, u32 pins);
void gpio_interrupt_enable(u32 port, u32 pins, int enable); void gpio_interrupt_enable(u32 port, u32 pins, int enable);
void gpio_interrupt_level(u32 port, u32 pins, int high, int edge, int delta); void gpio_interrupt_level(u32 port, u32 pins, int high, int edge, int delta);

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2021 CTCaer * Copyright (c) 2018-2023 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -19,6 +19,7 @@
#include <soc/hw_init.h> #include <soc/hw_init.h>
#include <display/di.h> #include <display/di.h>
#include <display/vic.h>
#include <input/joycon.h> #include <input/joycon.h>
#include <input/touch.h> #include <input/touch.h>
#include <sec/se.h> #include <sec/se.h>
@@ -31,6 +32,7 @@
#include <soc/pinmux.h> #include <soc/pinmux.h>
#include <soc/pmc.h> #include <soc/pmc.h>
#include <soc/uart.h> #include <soc/uart.h>
#include <soc/timer.h>
#include <soc/t210.h> #include <soc/t210.h>
#include <mem/mc.h> #include <mem/mc.h>
#include <mem/minerva.h> #include <mem/minerva.h>
@@ -39,7 +41,7 @@
#include <power/max77620.h> #include <power/max77620.h>
#include <power/max7762x.h> #include <power/max7762x.h>
#include <power/regulator_5v.h> #include <power/regulator_5v.h>
#include <storage/nx_sd.h> #include <storage/sd.h>
#include <storage/sdmmc.h> #include <storage/sdmmc.h>
#include <thermal/fan.h> #include <thermal/fan.h>
#include <thermal/tmp451.h> #include <thermal/tmp451.h>
@@ -71,24 +73,24 @@ u32 hw_get_chip_id()
static void _config_oscillators() static void _config_oscillators()
{ {
CLOCK(CLK_RST_CONTROLLER_SPARE_REG0) = (CLOCK(CLK_RST_CONTROLLER_SPARE_REG0) & 0xFFFFFFF3) | 4; // Set CLK_M_DIVISOR to 2. CLOCK(CLK_RST_CONTROLLER_SPARE_REG0) = (CLOCK(CLK_RST_CONTROLLER_SPARE_REG0) & 0xFFFFFFF3) | 4; // Set CLK_M_DIVISOR to 2.
SYSCTR0(SYSCTR0_CNTFID0) = 19200000; // Set counter frequency. SYSCTR0(SYSCTR0_CNTFID0) = 19200000; // Set counter frequency.
TMR(TIMERUS_USEC_CFG) = 0x45F; // For 19.2MHz clk_m. TMR(TIMERUS_USEC_CFG) = 0x45F; // For 19.2MHz clk_m.
CLOCK(CLK_RST_CONTROLLER_OSC_CTRL) = 0x50000071; // Set OSC to 38.4MHz and drive strength. CLOCK(CLK_RST_CONTROLLER_OSC_CTRL) = 0x50000071; // Set OSC to 38.4MHz and drive strength.
PMC(APBDEV_PMC_OSC_EDPD_OVER) = (PMC(APBDEV_PMC_OSC_EDPD_OVER) & 0xFFFFFF81) | 0xE; // Set LP0 OSC drive strength. PMC(APBDEV_PMC_OSC_EDPD_OVER) = (PMC(APBDEV_PMC_OSC_EDPD_OVER) & 0xFFFFFF81) | 0xE; // Set LP0 OSC drive strength.
PMC(APBDEV_PMC_OSC_EDPD_OVER) = (PMC(APBDEV_PMC_OSC_EDPD_OVER) & 0xFFBFFFFF) | PMC_OSC_EDPD_OVER_OSC_CTRL_OVER; PMC(APBDEV_PMC_OSC_EDPD_OVER) = (PMC(APBDEV_PMC_OSC_EDPD_OVER) & 0xFFBFFFFF) | PMC_OSC_EDPD_OVER_OSC_CTRL_OVER;
PMC(APBDEV_PMC_CNTRL2) = (PMC(APBDEV_PMC_CNTRL2) & 0xFFFFEFFF) | PMC_CNTRL2_HOLD_CKE_LOW_EN; PMC(APBDEV_PMC_CNTRL2) = (PMC(APBDEV_PMC_CNTRL2) & 0xFFFFEFFF) | PMC_CNTRL2_HOLD_CKE_LOW_EN;
PMC(APBDEV_PMC_SCRATCH188) = (PMC(APBDEV_PMC_SCRATCH188) & 0xFCFFFFFF) | (4 << 23); // LP0 EMC2TMC_CFG_XM2COMP_PU_VREF_SEL_RANGE. PMC(APB_MISC_GP_ASDBGREG) = (PMC(APB_MISC_GP_ASDBGREG) & 0xFCFFFFFF) | (2 << 24); // CFG2TMC_RAM_SVOP_PDP.
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 0x10; // Set HCLK div to 2 and PCLK div to 1. CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 0x10; // Set HCLK div to 2 and PCLK div to 1.
CLOCK(CLK_RST_CONTROLLER_PLLMB_BASE) &= 0xBFFFFFFF; // PLLMB disable. CLOCK(CLK_RST_CONTROLLER_PLLMB_BASE) &= 0xBFFFFFFF; // PLLMB disable.
PMC(APBDEV_PMC_TSC_MULT) = (PMC(APBDEV_PMC_TSC_MULT) & 0xFFFF0000) | 0x249F; //0x249F = 19200000 * (16 / 32.768 kHz) PMC(APBDEV_PMC_TSC_MULT) = (PMC(APBDEV_PMC_TSC_MULT) & 0xFFFF0000) | 0x249F; // 0x249F = 19200000 * (16 / 32.768 kHz).
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SYS) = 0; // Set BPMP/SCLK div to 1. CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SYS) = 0; // Set BPMP/SCLK div to 1.
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20004444; // Set BPMP/SCLK source to Run and PLLP_OUT2 (204MHz). CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20004444; // Set BPMP/SCLK source to Run and PLLP_OUT2 (204MHz).
CLOCK(CLK_RST_CONTROLLER_SUPER_SCLK_DIVIDER) = 0x80000000; // Enable SUPER_SDIV to 1. CLOCK(CLK_RST_CONTROLLER_SUPER_SCLK_DIVIDER) = 0x80000000; // Enable SUPER_SDIV to 1.
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // Set HCLK div to 1 and PCLK div to 3. CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // Set HCLK div to 1 and PCLK div to 3.
} }
// The uart is skipped for Copper, Hoag and Calcio. Used in Icosa, Iowa and Aula. // The uart is skipped for Copper, Hoag and Calcio. Used in Icosa, Iowa and Aula.
@@ -99,53 +101,39 @@ static void _config_gpios(bool nx_hoag)
if (!nx_hoag) if (!nx_hoag)
{ {
// Turn Joy-Con detect on. (GPIO mode and input logic for UARTB/C TX pins.)
PINMUX_AUX(PINMUX_AUX_UART2_TX) = 0; PINMUX_AUX(PINMUX_AUX_UART2_TX) = 0;
PINMUX_AUX(PINMUX_AUX_UART3_TX) = 0; PINMUX_AUX(PINMUX_AUX_UART3_TX) = 0;
gpio_direction_input(GPIO_PORT_G, GPIO_PIN_0);
// Set pin mode for UARTB/C TX pins. gpio_direction_input(GPIO_PORT_D, GPIO_PIN_1);
#if !defined (DEBUG_UART_PORT) || DEBUG_UART_PORT != UART_B
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_GPIO);
#endif
#if !defined (DEBUG_UART_PORT) || DEBUG_UART_PORT != UART_C
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_GPIO);
#endif
// Enable input logic for UARTB/C TX pins.
gpio_output_enable(GPIO_PORT_G, GPIO_PIN_0, GPIO_OUTPUT_DISABLE);
gpio_output_enable(GPIO_PORT_D, GPIO_PIN_1, GPIO_OUTPUT_DISABLE);
} }
// Set Joy-Con IsAttached direction. // Set Joy-Con IsAttached pinmux. Shared with UARTB/UARTC TX.
PINMUX_AUX(PINMUX_AUX_GPIO_PE6) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE; PINMUX_AUX(PINMUX_AUX_GPIO_PE6) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE;
PINMUX_AUX(PINMUX_AUX_GPIO_PH6) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE; PINMUX_AUX(PINMUX_AUX_GPIO_PH6) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE;
// Set Joy-Con IsAttached mode. // Configure Joy-Con IsAttached pins. Shared with UARTB/UARTC TX.
gpio_config(GPIO_PORT_E, GPIO_PIN_6, GPIO_MODE_GPIO); gpio_direction_input(GPIO_PORT_E, GPIO_PIN_6);
gpio_config(GPIO_PORT_H, GPIO_PIN_6, GPIO_MODE_GPIO); gpio_direction_input(GPIO_PORT_H, GPIO_PIN_6);
// Enable input logic for Joy-Con IsAttached pins.
gpio_output_enable(GPIO_PORT_E, GPIO_PIN_6, GPIO_OUTPUT_DISABLE);
gpio_output_enable(GPIO_PORT_H, GPIO_PIN_6, GPIO_OUTPUT_DISABLE);
pinmux_config_i2c(I2C_1); pinmux_config_i2c(I2C_1);
pinmux_config_i2c(I2C_5); pinmux_config_i2c(I2C_5);
pinmux_config_uart(UART_A); pinmux_config_uart(UART_A);
// Configure volume up/down as inputs. // Configure volume up/down as inputs.
gpio_config(GPIO_PORT_X, GPIO_PIN_6, GPIO_MODE_GPIO); gpio_direction_input(GPIO_PORT_X, GPIO_PIN_6 | GPIO_PIN_7);
gpio_config(GPIO_PORT_X, GPIO_PIN_7, GPIO_MODE_GPIO);
gpio_output_enable(GPIO_PORT_X, GPIO_PIN_6, GPIO_OUTPUT_DISABLE);
gpio_output_enable(GPIO_PORT_X, GPIO_PIN_7, GPIO_OUTPUT_DISABLE);
// Configure HOME as inputs. // Configure HOME as input. (Shared with UARTB RTS).
// PINMUX_AUX(PINMUX_AUX_BUTTON_HOME) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE; PINMUX_AUX(PINMUX_AUX_BUTTON_HOME) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE;
// gpio_config(GPIO_PORT_Y, GPIO_PIN_1, GPIO_MODE_GPIO); gpio_direction_input(GPIO_PORT_Y, GPIO_PIN_1);
// Power button can be configured for hoag here. Only SKU where it's connected.
} }
static void _config_pmc_scratch() static void _config_pmc_scratch()
{ {
PMC(APBDEV_PMC_SCRATCH20) &= 0xFFF3FFFF; // Unset Debug console from Customer Option. PMC(APBDEV_PMC_SCRATCH20) &= 0xFFF3FFFF; // Unset Debug console from Customer Option.
PMC(APBDEV_PMC_SCRATCH190) &= 0xFFFFFFFE; // Unset DATA_DQ_E_IVREF EMC_PMACRO_DATA_PAD_TX_CTRL PMC(APBDEV_PMC_SCRATCH190) &= 0xFFFFFFFE; // Unset WDT_DURING_BR.
PMC(APBDEV_PMC_SECURE_SCRATCH21) |= PMC_FUSE_PRIVATEKEYDISABLE_TZ_STICKY_BIT; PMC(APBDEV_PMC_SECURE_SCRATCH21) |= PMC_FUSE_PRIVATEKEYDISABLE_TZ_STICKY_BIT;
} }
@@ -178,8 +166,9 @@ static void _mbist_workaround()
I2S(I2S5_CTRL) |= I2S_CTRL_MASTER_EN; I2S(I2S5_CTRL) |= I2S_CTRL_MASTER_EN;
I2S(I2S5_CG) &= ~I2S_CG_SLCG_ENABLE; I2S(I2S5_CG) &= ~I2S_CG_SLCG_ENABLE;
// Set SLCG overrides.
DISPLAY_A(_DIREG(DC_COM_DSC_TOP_CTL)) |= 4; // DSC_SLCG_OVERRIDE. DISPLAY_A(_DIREG(DC_COM_DSC_TOP_CTL)) |= 4; // DSC_SLCG_OVERRIDE.
VIC(0x8C) = 0xFFFFFFFF; VIC(VIC_THI_SLCG_OVERRIDE_LOW_A) = 0xFFFFFFFF;
usleep(2); usleep(2);
// Set per-clock reset for APE/VIC/HOST1X/DISP1. // Set per-clock reset for APE/VIC/HOST1X/DISP1.
@@ -246,9 +235,9 @@ static void _mbist_workaround()
// Set child clock sources. // Set child clock sources.
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) &= 0x1F7FFFFF; // Disable PLLD and set reference clock and csi clock. CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) &= 0x1F7FFFFF; // Disable PLLD and set reference clock and csi clock.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SOR1) &= 0xFFFF3FFF; // Set SOR1 to automatic muxing of safe clock (24MHz) or SOR1 clk switch. CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SOR1) &= 0xFFFF3FFF; // Set SOR1 to automatic muxing of safe clock (24MHz) or SOR1 clk switch.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_VI) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_VI) & 0x1FFFFFFF) | 0x80000000; // Set clock source to PLLP_OUT. CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_VI) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_VI) & 0x1FFFFFFF) | 0x80000000; // Set clock source to PLLP_OUT.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X) & 0x1FFFFFFF) | 0x80000000; // Set clock source to PLLP_OUT. CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X) & 0x1FFFFFFF) | 0x80000000; // Set clock source to PLLP_OUT.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_NVENC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_NVENC) & 0x1FFFFFFF) | 0x80000000; // Set clock source to PLLP_OUT. CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_NVENC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_NVENC) & 0x1FFFFFFF) | 0x80000000; // Set clock source to PLLP_OUT.
} }
static void _config_se_brom() static void _config_se_brom()
@@ -263,17 +252,19 @@ static void _config_se_brom()
// se_key_acc_ctrl(15, SE_KEY_TBL_DIS_KEYREAD_FLAG); // se_key_acc_ctrl(15, SE_KEY_TBL_DIS_KEYREAD_FLAG);
// This memset needs to happen here, else TZRAM will behave weirdly later on. // This memset needs to happen here, else TZRAM will behave weirdly later on.
memset((void *)TZRAM_BASE, 0, SZ_64K); memset((void *)TZRAM_BASE, 0, TZRAM_SIZE);
PMC(APBDEV_PMC_CRYPTO_OP) = PMC_CRYPTO_OP_SE_ENABLE; PMC(APBDEV_PMC_CRYPTO_OP) = PMC_CRYPTO_OP_SE_ENABLE;
SE(SE_INT_STATUS_REG) = 0x1F; // Clear all SE interrupts.
// Clear SE interrupts.
SE(SE_INT_STATUS_REG) = SE_INT_OP_DONE | SE_INT_OUT_DONE | SE_INT_OUT_LL_BUF_WR | SE_INT_IN_DONE | SE_INT_IN_LL_BUF_RD;
// Save reset reason. // Save reset reason.
hw_rst_status = PMC(APBDEV_PMC_SCRATCH200); hw_rst_status = PMC(APBDEV_PMC_SCRATCH200);
hw_rst_reason = PMC(APBDEV_PMC_RST_STATUS) & PMC_RST_STATUS_MASK; hw_rst_reason = PMC(APBDEV_PMC_RST_STATUS) & PMC_RST_STATUS_MASK;
// Clear the boot reason to avoid problems later. // Clear the boot reason to avoid problems later.
PMC(APBDEV_PMC_SCRATCH200) = 0x0; PMC(APBDEV_PMC_SCRATCH200) = 0;
PMC(APBDEV_PMC_RST_STATUS) = 0x0; PMC(APBDEV_PMC_RST_STATUS) = PMC_RST_STATUS_POR;
APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) = (APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) & 0xF0) | (7 << 10); APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) = (APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) & 0xF0) | (7 << 10);
} }
@@ -291,6 +282,9 @@ static void _config_regulators(bool tegra_t210)
max7762x_regulator_enable(REGULATOR_LDO2, false); max7762x_regulator_enable(REGULATOR_LDO2, false);
sd_power_cycle_time_start = get_tmr_ms(); sd_power_cycle_time_start = get_tmr_ms();
// Disable LCD DVDD.
max7762x_regulator_enable(REGULATOR_LDO0, false);
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_CNFGBBC, MAX77620_CNFGBBC_RESISTOR_1K);
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, 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. MAX77620_ONOFFCNFG1_RSVD | (3 << MAX77620_ONOFFCNFG1_MRT_SHIFT)); // PWR delay for forced shutdown off.
@@ -327,15 +321,17 @@ static void _config_regulators(bool tegra_t210)
void hw_init() void hw_init()
{ {
// Get Chip ID. // Get Chip ID and SKU.
bool tegra_t210 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210; bool tegra_t210 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210;
bool nx_hoag = fuse_read_hw_type() == FUSE_NX_HW_TYPE_HOAG; bool nx_hoag = fuse_read_hw_type() == FUSE_NX_HW_TYPE_HOAG;
// Bootrom stuff we skipped by going through rcm. // Bootrom stuff we skipped by going through rcm.
_config_se_brom(); _config_se_brom();
//FUSE(FUSE_PRIVATEKEYDISABLE) = 0x11; //FUSE(FUSE_PRIVATEKEYDISABLE) = 0x11;
SYSREG(AHB_AHB_SPARE_REG) &= 0xFFFFFF9F; // Unset APB2JTAG_OVERRIDE_EN and OBS_OVERRIDE_EN.
PMC(APBDEV_PMC_SCRATCH49) = PMC(APBDEV_PMC_SCRATCH49) & 0xFFFFFFFC; // Unset APB2JTAG_OVERRIDE_EN and OBS_OVERRIDE_EN.
SYSREG(AHB_AHB_SPARE_REG) &= 0xFFFFFF9F;
PMC(APBDEV_PMC_SCRATCH49) &= 0xFFFFFFFC;
// Perform Memory Built-In Self Test WAR if T210. // Perform Memory Built-In Self Test WAR if T210.
if (tegra_t210) if (tegra_t210)
@@ -360,8 +356,14 @@ void hw_init()
_config_gpios(nx_hoag); _config_gpios(nx_hoag);
#ifdef DEBUG_UART_PORT #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); clock_enable_uart(DEBUG_UART_PORT);
uart_init(DEBUG_UART_PORT, DEBUG_UART_BAUDRATE); uart_init(DEBUG_UART_PORT, DEBUG_UART_BAUDRATE, UART_AO_TX_AO_RX);
uart_invert(DEBUG_UART_PORT, DEBUG_UART_INVERT, UART_INVERT_TXD); uart_invert(DEBUG_UART_PORT, DEBUG_UART_INVERT, UART_INVERT_TXD);
#endif #endif
@@ -378,7 +380,7 @@ void hw_init()
// Initialize I2C5, mandatory for PMIC. // Initialize I2C5, mandatory for PMIC.
i2c_init(I2C_5); i2c_init(I2C_5);
//! TODO: Why? Device is NFC MCU on Lite. // Enable LDO8 on HOAG as it also powers I2C1 IO pads.
if (nx_hoag) if (nx_hoag)
{ {
max7762x_regulator_set_voltage(REGULATOR_LDO8, 2800000); max7762x_regulator_set_voltage(REGULATOR_LDO8, 2800000);
@@ -391,35 +393,38 @@ void hw_init()
// Initialize various regulators based on Erista/Mariko platform. // Initialize various regulators based on Erista/Mariko platform.
_config_regulators(tegra_t210); _config_regulators(tegra_t210);
// Enable charger in case it's disabled.
bq24193_enable_charger();
_config_pmc_scratch(); // Missing from 4.x+ _config_pmc_scratch(); // Missing from 4.x+
// Set BPMP/SCLK to PLLP_OUT (408MHz). // Set BPMP/SCLK to PLLP_OUT (408MHz).
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003333; CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003333;
// Disable TZRAM shutdown control and lock the regs. // Power on T210B01 shadow TZRAM and lock the reg.
if (!tegra_t210) if (!tegra_t210)
{ {
PMC(APBDEV_PMC_TZRAM_PWR_CNTRL) &= 0xFFFFFFFE; PMC(APBDEV_PMC_TZRAM_PWR_CNTRL) &= ~PMC_TZRAM_PWR_CNTRL_SD;
PMC(APBDEV_PMC_TZRAM_NON_SEC_DISABLE) = 3; PMC(APBDEV_PMC_TZRAM_NON_SEC_DISABLE) = PMC_TZRAM_DISABLE_REG_WRITE | PMC_TZRAM_DISABLE_REG_READ;
PMC(APBDEV_PMC_TZRAM_SEC_DISABLE) = 3; PMC(APBDEV_PMC_TZRAM_SEC_DISABLE) = PMC_TZRAM_DISABLE_REG_WRITE | PMC_TZRAM_DISABLE_REG_READ;
} }
// Initialize External memory controller and configure DRAM parameters. // Initialize External memory controller and configure DRAM parameters.
sdram_init(); sdram_init();
bpmp_mmu_enable(); bpmp_mmu_enable();
// Enable HOST1X used by every display module (DC, VIC, NVDEC, NVENC, TSEC, etc).
clock_enable_host1x();
} }
void hw_reinit_workaround(bool coreboot, u32 bl_magic) void hw_reinit_workaround(bool coreboot, u32 bl_magic)
{ {
// Disable BPMP max clock. bool tegra_t210 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210;
// Scale down BPMP clock.
bpmp_clk_rate_set(BPMP_CLK_NORMAL); bpmp_clk_rate_set(BPMP_CLK_NORMAL);
#ifdef NYX #ifdef BDK_HW_EXTRA_DEINIT
// Disable temperature sensor, touchscreen, 5V regulators and Joy-Con. // Disable temperature sensor, touchscreen, 5V regulators, Joy-Con and VIC.
vic_end();
tmp451_end(); tmp451_end();
set_fan_duty(0); set_fan_duty(0);
touch_power_off(); touch_power_off();
@@ -427,14 +432,19 @@ void hw_reinit_workaround(bool coreboot, u32 bl_magic)
regulator_5v_disable(REGULATOR_5V_ALL); regulator_5v_disable(REGULATOR_5V_ALL);
#endif #endif
// Flush/disable MMU cache and set DRAM clock to 204MHz. // set DRAM clock to 204MHz.
bpmp_mmu_disable();
minerva_change_freq(FREQ_204); minerva_change_freq(FREQ_204);
nyx_str->mtc_cfg.init_done = 0; nyx_str->mtc_cfg.init_done = 0;
// Flush/disable MMU cache.
bpmp_mmu_disable();
// Re-enable clocks to Audio Processing Engine as a workaround to hanging. // Re-enable clocks to Audio Processing Engine as a workaround to hanging.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= BIT(CLK_V_AHUB); if (tegra_t210)
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= BIT(CLK_Y_APE); {
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= BIT(CLK_V_AHUB);
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= BIT(CLK_Y_APE);
}
// Do coreboot mitigations. // Do coreboot mitigations.
if (coreboot) if (coreboot)
@@ -443,11 +453,9 @@ void hw_reinit_workaround(bool coreboot, u32 bl_magic)
clock_disable_cl_dvfs(); clock_disable_cl_dvfs();
// Disable Joy-con GPIOs. // Disable Joy-con detect in order to restore UART TX.
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO); gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO);
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO); gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO);
gpio_config(GPIO_PORT_E, GPIO_PIN_6, GPIO_MODE_SPIO);
gpio_config(GPIO_PORT_H, GPIO_PIN_6, GPIO_MODE_SPIO);
// Reinstate SD controller power. // Reinstate SD controller power.
PMC(APBDEV_PMC_NO_IOPOWER) &= ~(PMC_NO_IOPOWER_SDMMC1_IO_EN); PMC(APBDEV_PMC_NO_IOPOWER) &= ~(PMC_NO_IOPOWER_SDMMC1_IO_EN);
@@ -463,17 +471,11 @@ void hw_reinit_workaround(bool coreboot, u32 bl_magic)
gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_GPIO); gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_GPIO);
display_backlight_brightness(brightness, 0); display_backlight_brightness(brightness, 0);
break; break;
case BL_MAGIC_L4TLDR_SLD:
// Do not disable display or backlight at all.
break;
default: default:
display_end(); display_end();
} clock_disable_host1x();
// Enable clock to USBD and init SDMMC1 to avoid hangs with bad hw inits.
if (bl_magic == BL_MAGIC_BROKEN_HWI)
{
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_USBD);
sdmmc_init(&sd_sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID, 0);
clock_disable_cl_dvfs();
msleep(200);
} }
} }

View File

@@ -21,7 +21,7 @@
#include <utils/types.h> #include <utils/types.h>
#define BL_MAGIC_CRBOOT_SLD 0x30444C53 // SLD0, seamless display type 0. #define BL_MAGIC_CRBOOT_SLD 0x30444C53 // SLD0, seamless display type 0.
#define BL_MAGIC_BROKEN_HWI 0xBAADF00D // Broken hwinit. #define BL_MAGIC_L4TLDR_SLD 0x31444C53 // SLD1, seamless display type 1.
extern u32 hw_rst_status; extern u32 hw_rst_status;
extern u32 hw_rst_reason; extern u32 hw_rst_reason;

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer * Copyright (c) 2018-2022 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -18,7 +18,7 @@
#include <string.h> #include <string.h>
#include <soc/i2c.h> #include <soc/i2c.h>
#include <utils/util.h> #include <soc/timer.h>
#define I2C_PACKET_PROT_I2C BIT(4) #define I2C_PACKET_PROT_I2C BIT(4)
#define I2C_HEADER_CONT_XFER BIT(15) #define I2C_HEADER_CONT_XFER BIT(15)
@@ -95,9 +95,9 @@ static void _i2c_load_cfg_wait(vu32 *base)
base[I2C_CONFIG_LOAD] = BIT(5) | TIMEOUT_CONFIG_LOAD | MSTR_CONFIG_LOAD; base[I2C_CONFIG_LOAD] = BIT(5) | TIMEOUT_CONFIG_LOAD | MSTR_CONFIG_LOAD;
for (u32 i = 0; i < 20; i++) for (u32 i = 0; i < 20; i++)
{ {
usleep(1);
if (!(base[I2C_CONFIG_LOAD] & MSTR_CONFIG_LOAD)) if (!(base[I2C_CONFIG_LOAD] & MSTR_CONFIG_LOAD))
break; break;
usleep(1);
} }
} }
@@ -205,8 +205,8 @@ static int _i2c_send_pkt(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr)
ARB_LOST | TX_FIFO_OVER | RX_FIFO_UNDER | TX_FIFO_DATA_REQ; ARB_LOST | TX_FIFO_OVER | RX_FIFO_UNDER | TX_FIFO_DATA_REQ;
base[I2C_INT_STATUS] = base[I2C_INT_STATUS]; base[I2C_INT_STATUS] = base[I2C_INT_STATUS];
// Set device address and recv mode. // Set device address and send mode.
base[I2C_CMD_ADDR0] = (dev_addr << 1) | ADDR0_READ; base[I2C_CMD_ADDR0] = (dev_addr << 1) | ADDR0_WRITE;
// Set recv mode. // Set recv mode.
base[I2C_CNFG] = DEBOUNCE_CNT_4T | NEW_MASTER_FSM | CMD1_WRITE; base[I2C_CNFG] = DEBOUNCE_CNT_4T | NEW_MASTER_FSM | CMD1_WRITE;
@@ -362,9 +362,9 @@ void i2c_init(u32 i2c_idx)
for (u32 i = 0; i < 10; i++) for (u32 i = 0; i < 10; i++)
{ {
usleep(20000);
if (base[I2C_INT_STATUS] & BUS_CLEAR_DONE) if (base[I2C_INT_STATUS] & BUS_CLEAR_DONE)
break; break;
usleep(25);
} }
(vu32)base[I2C_BUS_CLEAR_STATUS]; (vu32)base[I2C_BUS_CLEAR_STATUS];

View File

@@ -19,6 +19,7 @@
#include <string.h> #include <string.h>
#include "irq.h" #include "irq.h"
#include <soc/timer.h>
#include <soc/t210.h> #include <soc/t210.h>
#include <gfx_utils.h> #include <gfx_utils.h>
#include <mem/heap.h> #include <mem/heap.h>
@@ -26,6 +27,7 @@
//#define DPRINTF(...) gfx_printf(__VA_ARGS__) //#define DPRINTF(...) gfx_printf(__VA_ARGS__)
#define DPRINTF(...) #define DPRINTF(...)
extern void excp_reset();
extern void irq_disable(); extern void irq_disable();
extern void irq_enable_cpu_irq_exceptions(); extern void irq_enable_cpu_irq_exceptions();
extern void irq_disable_cpu_irq_exceptions(); extern void irq_disable_cpu_irq_exceptions();
@@ -69,7 +71,7 @@ static void _irq_disable_and_ack_all()
{ {
u32 enabled_irqs = ICTLR(ctrl_idx, PRI_ICTLR_COP_IER); 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_COP_IER_CLR) = enabled_irqs;
ICTLR(ctrl_idx, PRI_ICTLR_FIR_CLR) = enabled_irqs; ICTLR(ctrl_idx, PRI_ICTLR_FIR_CLR) = enabled_irqs;
} }
} }
@@ -88,10 +90,10 @@ void irq_free(u32 irq)
{ {
if (irqs[idx].irq == irq && irqs[idx].handler) if (irqs[idx].irq == irq && irqs[idx].handler)
{ {
irqs[idx].irq = 0; irqs[idx].irq = 0;
irqs[idx].handler = NULL; irqs[idx].handler = NULL;
irqs[idx].data = NULL; irqs[idx].data = NULL;
irqs[idx].flags = 0; irqs[idx].flags = 0;
_irq_disable_source(irq); _irq_disable_source(irq);
} }
@@ -106,10 +108,10 @@ static void _irq_free_all()
{ {
_irq_disable_source(irqs[idx].irq); _irq_disable_source(irqs[idx].irq);
irqs[idx].irq = 0; irqs[idx].irq = 0;
irqs[idx].handler = NULL; irqs[idx].handler = NULL;
irqs[idx].data = NULL; irqs[idx].data = NULL;
irqs[idx].flags = 0; irqs[idx].flags = 0;
} }
} }
} }
@@ -218,10 +220,10 @@ irq_status_t irq_request(u32 irq, irq_handler_t handler, void *data, irq_flags_t
DPRINTF("Registered handler, IRQ: %d, Slot: %d\n", irq, idx); DPRINTF("Registered handler, IRQ: %d, Slot: %d\n", irq, idx);
DPRINTF("Handler: %08p, Flags: %x\n", (u32)handler, flags); DPRINTF("Handler: %08p, Flags: %x\n", (u32)handler, flags);
irqs[idx].irq = irq; irqs[idx].irq = irq;
irqs[idx].handler = handler; irqs[idx].handler = handler;
irqs[idx].data = data; irqs[idx].data = data;
irqs[idx].flags = flags; irqs[idx].flags = flags;
_irq_enable_source(irq); _irq_enable_source(irq);
@@ -270,4 +272,14 @@ void __attribute__ ((target("arm"), interrupt ("FIQ"))) fiq_handler()
len--; len--;
} }
*/ */
#ifdef BDK_WATCHDOG_FIQ_ENABLE
// Set watchdog timeout status and disable WDT and its FIQ signal.
watchdog_handle();
#ifdef BDK_RESTART_BL_ON_WDT
// Restart bootloader.
excp_reset();
#endif
#endif
} }

View File

@@ -19,10 +19,10 @@
void pinmux_config_uart(u32 idx) void pinmux_config_uart(u32 idx)
{ {
PINMUX_AUX(PINMUX_AUX_UARTX_TX(idx)) = 0; PINMUX_AUX(PINMUX_AUX_UARTX_TX(idx)) = 0;
PINMUX_AUX(PINMUX_AUX_UARTX_RX(idx)) = PINMUX_INPUT_ENABLE | PINMUX_PULL_UP; PINMUX_AUX(PINMUX_AUX_UARTX_RX(idx)) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE;
PINMUX_AUX(PINMUX_AUX_UARTX_RTS(idx)) = 0; PINMUX_AUX(PINMUX_AUX_UARTX_RTS(idx)) = 0;
PINMUX_AUX(PINMUX_AUX_UARTX_CTS(idx)) = PINMUX_INPUT_ENABLE | PINMUX_PULL_DOWN; PINMUX_AUX(PINMUX_AUX_UARTX_CTS(idx)) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE;
} }
void pinmux_config_i2c(u32 idx) void pinmux_config_i2c(u32 idx)

View File

@@ -39,6 +39,7 @@
#define PINMUX_AUX_SDMMC3_DAT2 0x2C #define PINMUX_AUX_SDMMC3_DAT2 0x2C
#define PINMUX_AUX_SDMMC3_DAT3 0x30 #define PINMUX_AUX_SDMMC3_DAT3 0x30
#define PINMUX_AUX_SATA_LED_ACTIVE 0x4C #define PINMUX_AUX_SATA_LED_ACTIVE 0x4C
#define PINMUX_AUX_GPIO_PA5_T210B01 PINMUX_AUX_SATA_LED_ACTIVE
#define PINMUX_AUX_DMIC3_CLK 0xB4 #define PINMUX_AUX_DMIC3_CLK 0xB4
#define PINMUX_AUX_DMIC3_DAT 0xB8 #define PINMUX_AUX_DMIC3_DAT 0xB8
#define PINMUX_AUX_CAM_I2C_SCL 0xD4 #define PINMUX_AUX_CAM_I2C_SCL 0xD4
@@ -46,7 +47,9 @@
#define PINMUX_AUX_UART2_TX 0xF4 #define PINMUX_AUX_UART2_TX 0xF4
#define PINMUX_AUX_UART3_TX 0x104 #define PINMUX_AUX_UART3_TX 0x104
#define PINMUX_AUX_DAP4_DIN 0x148 #define PINMUX_AUX_DAP4_DIN 0x148
#define PINMUX_AUX_DAP4_DOUT 0x14C
#define PINMUX_AUX_DAP4_SCLK 0x150 #define PINMUX_AUX_DAP4_SCLK 0x150
#define PINMUX_AUX_CLK_32K_OUT 0x164
#define PINMUX_AUX_GPIO_X1_AUD 0x18C #define PINMUX_AUX_GPIO_X1_AUD 0x18C
#define PINMUX_AUX_GPIO_X3_AUD 0x190 #define PINMUX_AUX_GPIO_X3_AUD 0x190
#define PINMUX_AUX_SPDIF_IN 0x1A4 #define PINMUX_AUX_SPDIF_IN 0x1A4
@@ -57,19 +60,26 @@
#define PINMUX_AUX_AP_WAKE_NFC 0x1CC #define PINMUX_AUX_AP_WAKE_NFC 0x1CC
#define PINMUX_AUX_NFC_EN 0x1D0 #define PINMUX_AUX_NFC_EN 0x1D0
#define PINMUX_AUX_NFC_INT 0x1D4 #define PINMUX_AUX_NFC_INT 0x1D4
#define PINMUX_AUX_CAM_RST 0x1E0
#define PINMUX_AUX_CAM1_PWDN 0x1EC #define PINMUX_AUX_CAM1_PWDN 0x1EC
#define PINMUX_AUX_CAM2_PWDN 0x1F0 #define PINMUX_AUX_CAM2_PWDN 0x1F0
#define PINMUX_AUX_CAM1_STROBE 0x1F4
#define PINMUX_AUX_LCD_BL_PWM 0x1FC #define PINMUX_AUX_LCD_BL_PWM 0x1FC
#define PINMUX_AUX_LCD_BL_EN 0x200 #define PINMUX_AUX_LCD_BL_EN 0x200
#define PINMUX_AUX_LCD_RST 0x204 #define PINMUX_AUX_LCD_RST 0x204
#define PINMUX_AUX_LCD_GPIO1 0x208 #define PINMUX_AUX_LCD_GPIO1 0x208
#define PINMUX_AUX_LCD_GPIO2 0x20C #define PINMUX_AUX_LCD_GPIO2 0x20C
#define PINMUX_AUX_TOUCH_CLK 0x218
#define PINMUX_AUX_TOUCH_INT 0x220 #define PINMUX_AUX_TOUCH_INT 0x220
#define PINMUX_AUX_MOTION_INT 0x224 #define PINMUX_AUX_MOTION_INT 0x224
#define PINMUX_AUX_ALS_PROX_INT 0x228
#define PINMUX_AUX_BUTTON_POWER_ON 0x230
#define PINMUX_AUX_BUTTON_HOME 0x240 #define PINMUX_AUX_BUTTON_HOME 0x240
#define PINMUX_AUX_GPIO_PE6 0x248 #define PINMUX_AUX_GPIO_PE6 0x248
#define PINMUX_AUX_GPIO_PE7 0x24C
#define PINMUX_AUX_GPIO_PH6 0x250 #define PINMUX_AUX_GPIO_PH6 0x250
#define PINMUX_AUX_GPIO_PK3 0x260 #define PINMUX_AUX_GPIO_PK3 0x260
#define PINMUX_AUX_GPIO_PK7 0x270
#define PINMUX_AUX_GPIO_PZ1 0x280 #define PINMUX_AUX_GPIO_PZ1 0x280
/* Only in T210B01 */ /* Only in T210B01 */
#define PINMUX_AUX_SDMMC2_DAT0 0x294 #define PINMUX_AUX_SDMMC2_DAT0 0x294
@@ -116,6 +126,8 @@
#define PINMUX_DRIVE_3X (2 << 13) #define PINMUX_DRIVE_3X (2 << 13)
#define PINMUX_DRIVE_4X (3 << 13) #define PINMUX_DRIVE_4X (3 << 13)
#define PINMUX_PREEMP BIT(15)
void pinmux_config_uart(u32 idx); void pinmux_config_uart(u32 idx);
void pinmux_config_i2c(u32 idx); void pinmux_config_i2c(u32 idx);

View File

@@ -16,31 +16,28 @@
#include <soc/hw_init.h> #include <soc/hw_init.h>
#include <soc/pmc.h> #include <soc/pmc.h>
#include <soc/timer.h>
#include <soc/t210.h> #include <soc/t210.h>
#include <utils/util.h>
void pmc_scratch_lock(pmc_sec_lock_t lock_mask) void pmc_scratch_lock(pmc_sec_lock_t lock_mask)
{ {
// Lock Private key disable, Fuse write enable, MC carveout, Warmboot PA id and Warmboot address. // Lock Private key disable, Fuse write enable, MC carveout, Warmboot PA id and Warmboot address.
// Happens on T210B01 LP0 always.
if (lock_mask & PMC_SEC_LOCK_MISC) if (lock_mask & PMC_SEC_LOCK_MISC)
{ {
PMC(APBDEV_PMC_SEC_DISABLE) |= 0x700FF0; // RW lock: 0-3. PMC(APBDEV_PMC_SEC_DISABLE) |= 0x700FF0; // RW lock: 0-3.
PMC(APBDEV_PMC_SEC_DISABLE2) |= 0xFC000000; // RW lock: 21-23. PMC(APBDEV_PMC_SEC_DISABLE2) |= 0xFC000000; // RW lock: 21-23.
PMC(APBDEV_PMC_SEC_DISABLE3) |= 0x3F0FFF00; // RW lock: 28-33, 36-38. PMC(APBDEV_PMC_SEC_DISABLE3) |= 0x3F0FFF00; // RW lock: 28-33, 36-38.
PMC(APBDEV_PMC_SEC_DISABLE6) |= 0xC000000; // RW lock: 85. PMC(APBDEV_PMC_SEC_DISABLE6) |= 0xC000000; // RW lock: 85.
PMC(APBDEV_PMC_SEC_DISABLE8) |= 0xFF00FF00; // RW lock: 108-111, 116-119. // Default: 0xFF00FF00: RW lock: 108-111, 116-119. Gets locked in LP0.
PMC(APBDEV_PMC_SEC_DISABLE8) |= 0xFF005500; // W lock: 108-111, RW lock: 116-119.
// SE2 context.
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01)
{
PMC(APBDEV_PMC_SEC_DISABLE9) |= 0x3FF; // RW lock: 120-124. (0xB38)
PMC(APBDEV_PMC_SEC_DISABLE10) = 0xFFFFFFFF; // RW lock: 135-150.
}
} }
// Happens on T210B01 LP0 always.
if (lock_mask & PMC_SEC_LOCK_LP0_PARAMS) if (lock_mask & PMC_SEC_LOCK_LP0_PARAMS)
{ {
PMC(APBDEV_PMC_SEC_DISABLE2) |= 0x3FCFFFF; // RW lock: 8-15, 17-20. PMC(APBDEV_PMC_SEC_DISABLE2) |= 0x3FCFFFF; // RW lock: 8-15, 17-20. L4T expects 8-15 as write locked only.
PMC(APBDEV_PMC_SEC_DISABLE4) |= 0x3F3FFFFF; // RW lock: 40-50, 52-54. PMC(APBDEV_PMC_SEC_DISABLE4) |= 0x3F3FFFFF; // RW lock: 40-50, 52-54.
PMC(APBDEV_PMC_SEC_DISABLE5) = 0xFFFFFFFF; // RW lock: 56-71. PMC(APBDEV_PMC_SEC_DISABLE5) = 0xFFFFFFFF; // RW lock: 56-71.
PMC(APBDEV_PMC_SEC_DISABLE6) |= 0xF3FFC00F; // RW lock: 72-73, 79-84, 86-87. PMC(APBDEV_PMC_SEC_DISABLE6) |= 0xF3FFC00F; // RW lock: 72-73, 79-84, 86-87.
@@ -60,6 +57,7 @@ void pmc_scratch_lock(pmc_sec_lock_t lock_mask)
PMC(APBDEV_PMC_SEC_DISABLE7) |= 0xFFC00000; // RW lock: 99-103. PMC(APBDEV_PMC_SEC_DISABLE7) |= 0xFFC00000; // RW lock: 99-103.
} }
// HOS specific.
if (lock_mask & PMC_SEC_LOCK_TZ_CMAC_W) if (lock_mask & PMC_SEC_LOCK_TZ_CMAC_W)
PMC(APBDEV_PMC_SEC_DISABLE8) |= 0x550000; // W lock: 112-115. PMC(APBDEV_PMC_SEC_DISABLE8) |= 0x550000; // W lock: 112-115.
@@ -71,9 +69,34 @@ void pmc_scratch_lock(pmc_sec_lock_t lock_mask)
if (lock_mask & PMC_SEC_LOCK_TZ_KEK_R) if (lock_mask & PMC_SEC_LOCK_TZ_KEK_R)
PMC(APBDEV_PMC_SEC_DISABLE3) |= 0xAA; // R lock: 24-27. PMC(APBDEV_PMC_SEC_DISABLE3) |= 0xAA; // R lock: 24-27.
// End of HOS specific.
if (lock_mask & PMC_SEC_LOCK_SE_SRK) if (lock_mask & PMC_SEC_LOCK_SE_SRK)
PMC(APBDEV_PMC_SEC_DISABLE) |= 0xFF000; // RW lock: 4-7 PMC(APBDEV_PMC_SEC_DISABLE) |= 0xFF000; // RW lock: 4-7
if (lock_mask & PMC_SEC_LOCK_SE2_SRK_B01)
PMC(APBDEV_PMC_SEC_DISABLE9) |= 0x3FC; // RW lock: 120-123 (T210B01). LP0 also sets global bits (b0-1).
if (lock_mask & PMC_SEC_LOCK_MISC_B01)
PMC(APBDEV_PMC_SEC_DISABLE10) = 0xFFFFFFFF; // RW lock: 135-150. Happens on T210B01 LP0 always.
if (lock_mask & PMC_SEC_LOCK_CARVEOUTS_L4T)
PMC(APBDEV_PMC_SEC_DISABLE2) |= 0x5555; // W: 8-15 LP0 and Carveouts. Superseded by LP0 lock.
// NVTBOOT misses APBDEV_PMC_SCRATCH_WRITE_LOCK_DISABLE_STICKY. bit0: SCRATCH_WR_DIS_ON.
// They could also use the NS write disable registers instead.
if (lock_mask & PMC_SEC_LOCK_LP0_PARAMS_B01)
{
PMC(APBDEV_PMC_SCRATCH_WRITE_DISABLE0) |= 0xCBCFE0; // W lock: 5-11, 14-17, 19, 22-23.
PMC(APBDEV_PMC_SCRATCH_WRITE_DISABLE1) |= 0x583FF; // W lock: 24-33, 39-40, 42.
PMC(APBDEV_PMC_SCRATCH_WRITE_DISABLE2) |= 0x1BE; // W lock: 44-48, 50-51.
PMC(APBDEV_PMC_SCRATCH_WRITE_DISABLE3) = 0xFFFFFFFF; // W lock: 56-87.
PMC(APBDEV_PMC_SCRATCH_WRITE_DISABLE4) |= 0xFFFFFFF; // W lock: 88-115.
PMC(APBDEV_PMC_SCRATCH_WRITE_DISABLE5) |= 0xFFFFFFF8; // W lock: 123-151.
PMC(APBDEV_PMC_SCRATCH_WRITE_DISABLE6) = 0xFFFFFFFF; // W lock: 152-183.
PMC(APBDEV_PMC_SCRATCH_WRITE_DISABLE7) |= 0xFC00FFFF; // W lock: 184-199, 210-215.
PMC(APBDEV_PMC_SCRATCH_WRITE_DISABLE8) |= 0xF; // W lock: 216-219.
}
} }
int pmc_enable_partition(pmc_power_rail_t part, u32 enable) int pmc_enable_partition(pmc_power_rail_t part, u32 enable)

View File

@@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018 st4rk * Copyright (c) 2018 st4rk
* Copyright (c) 2018-2020 CTCaer * Copyright (c) 2018-2022 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -22,102 +22,183 @@
#include <utils/types.h> #include <utils/types.h>
/*! PMC registers. */ /*! PMC registers. */
#define APBDEV_PMC_CNTRL 0x0 #define APBDEV_PMC_CNTRL 0x0
#define PMC_CNTRL_MAIN_RST BIT(4) #define PMC_CNTRL_RTC_CLK_DIS BIT(1)
#define APBDEV_PMC_SEC_DISABLE 0x4 #define PMC_CNTRL_RTC_RST BIT(2)
#define APBDEV_PMC_PWRGATE_TOGGLE 0x30 #define PMC_CNTRL_MAIN_RST BIT(4)
#define APBDEV_PMC_PWRGATE_STATUS 0x38 #define PMC_CNTRL_LATCHWAKE_EN BIT(5)
#define APBDEV_PMC_NO_IOPOWER 0x44 #define PMC_CNTRL_BLINK_EN BIT(7)
#define PMC_NO_IOPOWER_SDMMC1_IO_EN BIT(12) #define PMC_CNTRL_PWRREQ_OE BIT(9)
#define PMC_NO_IOPOWER_AUDIO_HV BIT(18) #define PMC_CNTRL_SYSCLK_OE BIT(11)
#define PMC_NO_IOPOWER_GPIO_IO_EN BIT(21) #define PMC_CNTRL_PWRGATE_DIS BIT(12)
#define APBDEV_PMC_SCRATCH0 0x50 #define PMC_CNTRL_SIDE_EFFECT_LP0 BIT(14)
#define PMC_SCRATCH0_MODE_WARMBOOT BIT(0) #define PMC_CNTRL_CPUPWRREQ_OE BIT(16)
#define PMC_SCRATCH0_MODE_RCM BIT(1) #define PMC_CNTRL_FUSE_OVERRIDE BIT(18)
#define PMC_SCRATCH0_MODE_PAYLOAD BIT(29) #define PMC_CNTRL_SHUTDOWN_OE BIT(22)
#define PMC_SCRATCH0_MODE_FASTBOOT BIT(30) #define APBDEV_PMC_SEC_DISABLE 0x4
#define PMC_SCRATCH0_MODE_RECOVERY BIT(31) #define APBDEV_PMC_PWRGATE_TOGGLE 0x30
#define PMC_SCRATCH0_MODE_CUSTOM_ALL (PMC_SCRATCH0_MODE_RECOVERY | PMC_SCRATCH0_MODE_FASTBOOT | PMC_SCRATCH0_MODE_PAYLOAD) #define APBDEV_PMC_PWRGATE_STATUS 0x38
#define APBDEV_PMC_SCRATCH1 0x54 #define APBDEV_PMC_NO_IOPOWER 0x44
#define APBDEV_PMC_SCRATCH20 0xA0 #define PMC_NO_IOPOWER_SDMMC1_IO_EN BIT(12)
#define APBDEV_PMC_SECURE_SCRATCH4 0xC0 #define PMC_NO_IOPOWER_SDMMC4_IO_EN BIT(14)
#define APBDEV_PMC_SECURE_SCRATCH5 0xC4 #define PMC_NO_IOPOWER_AUDIO_HV BIT(18)
#define APBDEV_PMC_PWR_DET_VAL 0xE4 #define PMC_NO_IOPOWER_GPIO_IO_EN BIT(21)
#define PMC_PWR_DET_SDMMC1_IO_EN BIT(12) #define APBDEV_PMC_SCRATCH0 0x50
#define PMC_PWR_DET_AUDIO_HV BIT(18) #define PMC_SCRATCH0_MODE_WARMBOOT BIT(0)
#define PMC_PWR_DET_GPIO_IO_EN BIT(21) #define PMC_SCRATCH0_MODE_RCM BIT(1)
#define APBDEV_PMC_DDR_PWR 0xE8 #define PMC_SCRATCH0_MODE_PAYLOAD BIT(29)
#define APBDEV_PMC_USB_AO 0xF0 #define PMC_SCRATCH0_MODE_BOOTLOADER BIT(30)
#define APBDEV_PMC_CRYPTO_OP 0xF4 #define PMC_SCRATCH0_MODE_RECOVERY BIT(31)
#define PMC_CRYPTO_OP_SE_ENABLE 0 #define PMC_SCRATCH0_MODE_CUSTOM_ALL (PMC_SCRATCH0_MODE_RECOVERY | \
#define PMC_CRYPTO_OP_SE_DISABLE 1 PMC_SCRATCH0_MODE_BOOTLOADER | \
#define APBDEV_PMC_SCRATCH33 0x120 PMC_SCRATCH0_MODE_PAYLOAD)
#define APBDEV_PMC_SCRATCH37 0x130 #define APBDEV_PMC_BLINK_TIMER 0x40
#define PMC_SCRATCH37_KERNEL_PANIC_FLAG BIT(24) #define PMC_BLINK_ON(n) ((n & 0x7FFF))
#define APBDEV_PMC_SCRATCH40 0x13C #define PMC_BLINK_FORCE BIT(15)
#define APBDEV_PMC_OSC_EDPD_OVER 0x1A4 #define PMC_BLINK_OFF(n) ((u32)(n & 0xFFFF) << 16)
#define PMC_OSC_EDPD_OVER_OSC_CTRL_OVER 0x400000 #define APBDEV_PMC_SCRATCH1 0x54
#define APBDEV_PMC_CLK_OUT_CNTRL 0x1A8 #define APBDEV_PMC_SCRATCH20 0xA0 // ODM data/config scratch.
#define PMC_CLK_OUT_CNTRL_CLK1_FORCE_EN BIT(2) #define APBDEV_PMC_SECURE_SCRATCH4 0xC0
#define APBDEV_PMC_RST_STATUS 0x1B4 #define APBDEV_PMC_SECURE_SCRATCH5 0xC4
#define PMC_RST_STATUS_MASK 0x7 #define APBDEV_PMC_PWR_DET_VAL 0xE4
#define PMC_RST_STATUS_POR 0 #define PMC_PWR_DET_SDMMC1_IO_EN BIT(12)
#define PMC_RST_STATUS_WATCHDOG 1 #define PMC_PWR_DET_AUDIO_HV BIT(18)
#define PMC_RST_STATUS_SENSOR 2 #define PMC_PWR_DET_GPIO_IO_EN BIT(21)
#define PMC_RST_STATUS_SW_MAIN 3 #define APBDEV_PMC_DDR_PWR 0xE8
#define PMC_RST_STATUS_LP0 4 #define APBDEV_PMC_USB_AO 0xF0
#define PMC_RST_STATUS_AOTAG 5 #define APBDEV_PMC_CRYPTO_OP 0xF4
#define APBDEV_PMC_IO_DPD_REQ 0x1B8 #define PMC_CRYPTO_OP_SE_ENABLE 0
#define PMC_IO_DPD_REQ_DPD_OFF BIT(30) #define PMC_CRYPTO_OP_SE_DISABLE 1
#define APBDEV_PMC_IO_DPD2_REQ 0x1C0 #define APBDEV_PMC_PLLP_WB0_OVERRIDE 0xF8
#define APBDEV_PMC_VDDP_SEL 0x1CC #define PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE_ENABLE BIT(11)
#define APBDEV_PMC_DDR_CFG 0x1D0 #define PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE BIT(12)
#define APBDEV_PMC_SECURE_SCRATCH6 0x224 #define APBDEV_PMC_SCRATCH33 0x120
#define APBDEV_PMC_SECURE_SCRATCH7 0x228 #define APBDEV_PMC_SCRATCH37 0x130
#define APBDEV_PMC_SCRATCH45 0x234 #define PMC_SCRATCH37_KERNEL_PANIC_MAGIC 0x4E415054 // "TPAN"
#define APBDEV_PMC_SCRATCH46 0x238 #define APBDEV_PMC_SCRATCH39 0x138
#define APBDEV_PMC_SCRATCH49 0x244 #define APBDEV_PMC_SCRATCH40 0x13C
#define APBDEV_PMC_TSC_MULT 0x2B4 #define APBDEV_PMC_OSC_EDPD_OVER 0x1A4
#define APBDEV_PMC_SEC_DISABLE2 0x2C4 #define PMC_OSC_EDPD_OVER_OSC_CTRL_OVER BIT(22)
#define APBDEV_PMC_WEAK_BIAS 0x2C8 #define APBDEV_PMC_CLK_OUT_CNTRL 0x1A8
#define APBDEV_PMC_REG_SHORT 0x2CC #define PMC_CLK_OUT_CNTRL_CLK1_FORCE_EN BIT(2)
#define APBDEV_PMC_SEC_DISABLE3 0x2D8 #define PMC_CLK_OUT_CNTRL_CLK2_FORCE_EN BIT(10)
#define APBDEV_PMC_SECURE_SCRATCH21 0x334 #define PMC_CLK_OUT_CNTRL_CLK3_FORCE_EN BIT(18)
#define PMC_FUSE_PRIVATEKEYDISABLE_TZ_STICKY_BIT 0x10 #define PMC_CLK_OUT_CNTRL_CLK1_SRC_SEL(src) (((src) & 3) << 6)
#define APBDEV_PMC_SECURE_SCRATCH32 0x360 #define PMC_CLK_OUT_CNTRL_CLK2_SRC_SEL(src) (((src) & 3) << 14)
#define APBDEV_PMC_SECURE_SCRATCH49 0x3A4 #define PMC_CLK_OUT_CNTRL_CLK3_SRC_SEL(src) (((src) & 3) << 22)
#define APBDEV_PMC_CNTRL2 0x440 #define OSC_DIV1 0
#define PMC_CNTRL2_HOLD_CKE_LOW_EN 0x1000 #define OSC_DIV2 1
#define APBDEV_PMC_IO_DPD3_REQ 0x45C #define OSC_DIV4 2
#define APBDEV_PMC_IO_DPD4_REQ 0x464 #define OSC_CAR 3
#define APBDEV_PMC_UTMIP_PAD_CFG1 0x4C4 #define APBDEV_PMC_RST_STATUS 0x1B4
#define APBDEV_PMC_UTMIP_PAD_CFG3 0x4CC #define PMC_RST_STATUS_MASK 7
#define APBDEV_PMC_DDR_CNTRL 0x4E4 #define PMC_RST_STATUS_POR 0
#define APBDEV_PMC_SEC_DISABLE4 0x5B0 #define PMC_RST_STATUS_WATCHDOG 1
#define APBDEV_PMC_SEC_DISABLE5 0x5B4 #define PMC_RST_STATUS_SENSOR 2
#define APBDEV_PMC_SEC_DISABLE6 0x5B8 #define PMC_RST_STATUS_SW_MAIN 3
#define APBDEV_PMC_SEC_DISABLE7 0x5BC #define PMC_RST_STATUS_LP0 4
#define APBDEV_PMC_SEC_DISABLE8 0x5C0 #define PMC_RST_STATUS_AOTAG 5
#define APBDEV_PMC_SEC_DISABLE9 0x5C4 #define APBDEV_PMC_IO_DPD_REQ 0x1B8
#define APBDEV_PMC_SEC_DISABLE10 0x5C8 #define PMC_IO_DPD_REQ_DPD_OFF BIT(30)
#define APBDEV_PMC_SCRATCH188 0x810 #define APBDEV_PMC_IO_DPD2_REQ 0x1C0
#define APBDEV_PMC_SCRATCH190 0x818 #define APBDEV_PMC_VDDP_SEL 0x1CC
#define APBDEV_PMC_SCRATCH200 0x840 #define APBDEV_PMC_DDR_CFG 0x1D0
#define APBDEV_PMC_TZRAM_PWR_CNTRL 0xBE8 #define APBDEV_PMC_SECURE_SCRATCH6 0x224
#define APBDEV_PMC_TZRAM_SEC_DISABLE 0xBEC #define APBDEV_PMC_SECURE_SCRATCH7 0x228
#define APBDEV_PMC_TZRAM_NON_SEC_DISABLE 0xBF0 #define APBDEV_PMC_SCRATCH45 0x234
#define APBDEV_PMC_SCRATCH46 0x238
#define APBDEV_PMC_SCRATCH49 0x244
#define APBDEV_PMC_SCRATCH52 0x250
#define APBDEV_PMC_SCRATCH53 0x254
#define APBDEV_PMC_SCRATCH54 0x258
#define APBDEV_PMC_SCRATCH55 0x25C
#define APBDEV_PMC_TSC_MULT 0x2B4
#define APBDEV_PMC_STICKY_BITS 0x2C0
#define PMC_STICKY_BITS_HDA_LPBK_DIS BIT(0)
#define APBDEV_PMC_SEC_DISABLE2 0x2C4
#define APBDEV_PMC_WEAK_BIAS 0x2C8
#define APBDEV_PMC_REG_SHORT 0x2CC
#define APBDEV_PMC_SEC_DISABLE3 0x2D8
#define APBDEV_PMC_SECURE_SCRATCH21 0x334
#define PMC_FUSE_PRIVATEKEYDISABLE_TZ_STICKY_BIT BIT(4)
#define APBDEV_PMC_SECURE_SCRATCH22 0x338 // AArch32 reset address.
#define APBDEV_PMC_SECURE_SCRATCH32 0x360
#define APBDEV_PMC_SECURE_SCRATCH34 0x368 // AArch64 reset address.
#define APBDEV_PMC_SECURE_SCRATCH35 0x36C // AArch64 reset hi-address.
#define APBDEV_PMC_SECURE_SCRATCH49 0x3A4
#define APBDEV_PMC_CNTRL2 0x440
#define PMC_CNTRL2_WAKE_INT_EN BIT(0)
#define PMC_CNTRL2_WAKE_DET_EN BIT(9)
#define PMC_CNTRL2_SYSCLK_ORRIDE BIT(10)
#define PMC_CNTRL2_HOLD_CKE_LOW_EN BIT(12)
#define PMC_CNTRL2_ALLOW_PULSE_WAKE BIT(14)
#define APBDEV_PMC_IO_DPD3_REQ 0x45C
#define APBDEV_PMC_IO_DPD4_REQ 0x464
#define APBDEV_PMC_UTMIP_PAD_CFG1 0x4C4
#define APBDEV_PMC_UTMIP_PAD_CFG3 0x4CC
#define APBDEV_PMC_DDR_CNTRL 0x4E4
#define APBDEV_PMC_SEC_DISABLE4 0x5B0
#define APBDEV_PMC_SEC_DISABLE5 0x5B4
#define APBDEV_PMC_SEC_DISABLE6 0x5B8
#define APBDEV_PMC_SEC_DISABLE7 0x5BC
#define APBDEV_PMC_SEC_DISABLE8 0x5C0
#define APBDEV_PMC_SEC_DISABLE9 0x5C4
#define APBDEV_PMC_SEC_DISABLE10 0x5C8
#define APBDEV_PMC_SCRATCH188 0x810
#define APBDEV_PMC_SCRATCH190 0x818
#define APBDEV_PMC_SCRATCH200 0x840
#define APBDEV_PMC_SCRATCH201 0x844
#define APBDEV_PMC_SCRATCH250 0x908
#define APBDEV_PMC_SECURE_SCRATCH108 0xB08
#define APBDEV_PMC_SECURE_SCRATCH109 0xB0C
#define APBDEV_PMC_SECURE_SCRATCH110 0xB10
#define APBDEV_PMC_SECURE_SCRATCH112 0xB18
#define APBDEV_PMC_SECURE_SCRATCH113 0xB1C
#define APBDEV_PMC_SECURE_SCRATCH114 0xB20
#define APBDEV_PMC_SECURE_SCRATCH119 0xB34
// Only in T210B01.
#define APBDEV_PMC_SCRATCH_WRITE_DISABLE0 0xA48
#define APBDEV_PMC_SCRATCH_WRITE_DISABLE1 0xA4C
#define APBDEV_PMC_SCRATCH_WRITE_DISABLE2 0xA50
#define APBDEV_PMC_SCRATCH_WRITE_DISABLE3 0xA54
#define APBDEV_PMC_SCRATCH_WRITE_DISABLE4 0xA58
#define APBDEV_PMC_SCRATCH_WRITE_DISABLE5 0xA5C
#define APBDEV_PMC_SCRATCH_WRITE_DISABLE6 0xA60
#define APBDEV_PMC_SCRATCH_WRITE_DISABLE7 0xA64
#define APBDEV_PMC_SCRATCH_WRITE_DISABLE8 0xA68
#define APBDEV_PMC_LED_BREATHING_CTRL 0xB48
#define PMC_LED_BREATHING_CTRL_ENABLE BIT(0)
#define PMC_LED_BREATHING_CTRL_COUNTER1_EN BIT(1)
#define APBDEV_PMC_LED_BREATHING_SLOPE_STEPS 0xB4C
#define APBDEV_PMC_LED_BREATHING_ON_COUNTER 0xB50
#define APBDEV_PMC_LED_BREATHING_OFF_COUNTER1 0xB54
#define APBDEV_PMC_LED_BREATHING_OFF_COUNTER0 0xB58
#define PMC_LED_BREATHING_COUNTER_HZ 32768
#define APBDEV_PMC_LED_BREATHING_STATUS 0xB5C
#define PMC_LED_BREATHING_FSM_STATUS_MASK 0x7
#define APBDEV_PMC_TZRAM_PWR_CNTRL 0xBE8
#define PMC_TZRAM_PWR_CNTRL_SD BIT(0)
#define APBDEV_PMC_TZRAM_SEC_DISABLE 0xBEC
#define APBDEV_PMC_TZRAM_NON_SEC_DISABLE 0xBF0
#define PMC_TZRAM_DISABLE_REG_WRITE BIT(0)
#define PMC_TZRAM_DISABLE_REG_READ BIT(1)
typedef enum _pmc_sec_lock_t typedef enum _pmc_sec_lock_t
{ {
PMC_SEC_LOCK_MISC = BIT(0), PMC_SEC_LOCK_MISC = BIT(0),
PMC_SEC_LOCK_LP0_PARAMS = BIT(1), PMC_SEC_LOCK_LP0_PARAMS = BIT(1),
PMC_SEC_LOCK_RST_VECTOR = BIT(2), PMC_SEC_LOCK_RST_VECTOR = BIT(2),
PMC_SEC_LOCK_CARVEOUTS = BIT(3), PMC_SEC_LOCK_CARVEOUTS = BIT(3),
PMC_SEC_LOCK_TZ_CMAC_W = BIT(4), PMC_SEC_LOCK_TZ_CMAC_W = BIT(4),
PMC_SEC_LOCK_TZ_CMAC_R = BIT(5), PMC_SEC_LOCK_TZ_CMAC_R = BIT(5),
PMC_SEC_LOCK_TZ_KEK_W = BIT(6), PMC_SEC_LOCK_TZ_KEK_W = BIT(6),
PMC_SEC_LOCK_TZ_KEK_R = BIT(7), PMC_SEC_LOCK_TZ_KEK_R = BIT(7),
PMC_SEC_LOCK_SE_SRK = BIT(8), PMC_SEC_LOCK_SE_SRK = BIT(8),
PMC_SEC_LOCK_SE2_SRK_B01 = BIT(9),
PMC_SEC_LOCK_MISC_B01 = BIT(10),
PMC_SEC_LOCK_CARVEOUTS_L4T = BIT(11),
PMC_SEC_LOCK_LP0_PARAMS_B01 = BIT(12),
} pmc_sec_lock_t; } pmc_sec_lock_t;
typedef enum _pmc_power_rail_t typedef enum _pmc_power_rail_t

View File

@@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2023 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -26,8 +27,10 @@
#define DISPLAY_A_BASE 0x54200000 #define DISPLAY_A_BASE 0x54200000
#define DSI_BASE 0x54300000 #define DSI_BASE 0x54300000
#define VIC_BASE 0x54340000 #define VIC_BASE 0x54340000
#define NVDEC_BASE 0x54480000
#define TSEC_BASE 0x54500000 #define TSEC_BASE 0x54500000
#define SOR1_BASE 0x54580000 #define SOR1_BASE 0x54580000
#define MSELECT_BASE 0x50060000
#define ICTLR_BASE 0x60004000 #define ICTLR_BASE 0x60004000
#define TMR_BASE 0x60005000 #define TMR_BASE 0x60005000
#define CLOCK_BASE 0x60006000 #define CLOCK_BASE 0x60006000
@@ -35,6 +38,7 @@
#define AHBDMA_BASE 0x60008000 #define AHBDMA_BASE 0x60008000
#define SYSREG_BASE 0x6000C000 #define SYSREG_BASE 0x6000C000
#define SB_BASE (SYSREG_BASE + 0x200) #define SB_BASE (SYSREG_BASE + 0x200)
#define ACTMON_BASE 0x6000C800
#define GPIO_BASE 0x6000D000 #define GPIO_BASE 0x6000D000
#define GPIO_1_BASE (GPIO_BASE) #define GPIO_1_BASE (GPIO_BASE)
#define GPIO_2_BASE (GPIO_BASE + 0x100) #define GPIO_2_BASE (GPIO_BASE + 0x100)
@@ -69,6 +73,8 @@
#define I2S_BASE 0x702D1000 #define I2S_BASE 0x702D1000
#define ADMA_BASE 0x702E2000 #define ADMA_BASE 0x702E2000
#define TZRAM_BASE 0x7C010000 #define TZRAM_BASE 0x7C010000
#define TZRAM_SIZE 0x10000
#define TZRAM_T210B01_SIZE 0x3C000
#define USB_BASE 0x7D000000 #define USB_BASE 0x7D000000
#define USB_OTG_BASE USB_BASE #define USB_OTG_BASE USB_BASE
#define USB1_BASE 0x7D004000 #define USB1_BASE 0x7D004000
@@ -80,8 +86,10 @@
#define DISPLAY_A(off) _REG(DISPLAY_A_BASE, off) #define DISPLAY_A(off) _REG(DISPLAY_A_BASE, off)
#define DSI(off) _REG(DSI_BASE, off) #define DSI(off) _REG(DSI_BASE, off)
#define VIC(off) _REG(VIC_BASE, off) #define VIC(off) _REG(VIC_BASE, off)
#define NVDEC(off) _REG(NVDEC_BASE, off)
#define TSEC(off) _REG(TSEC_BASE, off) #define TSEC(off) _REG(TSEC_BASE, off)
#define SOR1(off) _REG(SOR1_BASE, off) #define SOR1(off) _REG(SOR1_BASE, off)
#define MSELECT(off) _REG(MSELECT_BASE, off)
#define ICTLR(cidx, off) _REG(ICTLR_BASE + (0x100 * (cidx)), off) #define ICTLR(cidx, off) _REG(ICTLR_BASE + (0x100 * (cidx)), off)
#define TMR(off) _REG(TMR_BASE, off) #define TMR(off) _REG(TMR_BASE, off)
#define CLOCK(off) _REG(CLOCK_BASE, off) #define CLOCK(off) _REG(CLOCK_BASE, off)
@@ -89,6 +97,7 @@
#define SYSREG(off) _REG(SYSREG_BASE, off) #define SYSREG(off) _REG(SYSREG_BASE, off)
#define AHB_GIZMO(off) _REG(SYSREG_BASE, off) #define AHB_GIZMO(off) _REG(SYSREG_BASE, off)
#define SB(off) _REG(SB_BASE, off) #define SB(off) _REG(SB_BASE, off)
#define ACTMON(off) _REG(ACTMON_BASE, off)
#define GPIO(off) _REG(GPIO_BASE, off) #define GPIO(off) _REG(GPIO_BASE, off)
#define GPIO_1(off) _REG(GPIO_1_BASE, off) #define GPIO_1(off) _REG(GPIO_1_BASE, off)
#define GPIO_2(off) _REG(GPIO_2_BASE, off) #define GPIO_2(off) _REG(GPIO_2_BASE, off)
@@ -126,95 +135,99 @@
#define USB1(off) _REG(USB1_BASE, off) #define USB1(off) _REG(USB1_BASE, off)
#define TEST_REG(off) _REG(0x0, off) #define TEST_REG(off) _REG(0x0, off)
/* HOST1X registers. */ /* HOST1X v3 registers. */
#define HOST1X_CH0_SYNC_BASE 0x2100 #define HOST1X_CH0_SYNC_BASE 0x2100
#define HOST1X_CH0_SYNC_SYNCPT_9 (HOST1X_CH0_SYNC_BASE + 0xFA4) #define HOST1X_CH0_SYNC_SYNCPT_BASE (HOST1X_CH0_SYNC_BASE + 0xF80)
#define HOST1X_CH0_SYNC_SYNCPT_160 (HOST1X_CH0_SYNC_BASE + 0x1200) #define HOST1X_CH0_SYNC_SYNCPT_9 (HOST1X_CH0_SYNC_SYNCPT_BASE + 0x24)
#define HOST1X_CH0_SYNC_SYNCPT_160 (HOST1X_CH0_SYNC_SYNCPT_BASE + 0x280)
/*! EVP registers. */ /*! EVP registers. */
#define EVP_CPU_RESET_VECTOR 0x100 #define EVP_CPU_RESET_VECTOR 0x100
#define EVP_COP_RESET_VECTOR 0x200 #define EVP_COP_RESET_VECTOR 0x200
#define EVP_COP_UNDEF_VECTOR 0x204 #define EVP_COP_UNDEF_VECTOR 0x204
#define EVP_COP_SWI_VECTOR 0x208 #define EVP_COP_SWI_VECTOR 0x208
#define EVP_COP_PREFETCH_ABORT_VECTOR 0x20C #define EVP_COP_PREFETCH_ABORT_VECTOR 0x20C
#define EVP_COP_DATA_ABORT_VECTOR 0x210 #define EVP_COP_DATA_ABORT_VECTOR 0x210
#define EVP_COP_RSVD_VECTOR 0x214 #define EVP_COP_RSVD_VECTOR 0x214
#define EVP_COP_IRQ_VECTOR 0x218 #define EVP_COP_IRQ_VECTOR 0x218
#define EVP_COP_FIQ_VECTOR 0x21C #define EVP_COP_FIQ_VECTOR 0x21C
#define EVP_COP_IRQ_STS 0x220 #define EVP_COP_IRQ_STS 0x220
/*! Primary Interrupt Controller registers. */ /*! Primary Interrupt Controller registers. */
#define PRI_ICTLR_FIR 0x14 #define PRI_ICTLR_FIR 0x14
#define PRI_ICTLR_FIR_SET 0x18 #define PRI_ICTLR_FIR_SET 0x18
#define PRI_ICTLR_FIR_CLR 0x1C #define PRI_ICTLR_FIR_CLR 0x1C
#define PRI_ICTLR_CPU_IER 0x20 #define PRI_ICTLR_CPU_IER 0x20
#define PRI_ICTLR_CPU_IER_SET 0x24 #define PRI_ICTLR_CPU_IER_SET 0x24
#define PRI_ICTLR_CPU_IER_CLR 0x28 #define PRI_ICTLR_CPU_IER_CLR 0x28
#define PRI_ICTLR_CPU_IEP_CLASS 0x2C #define PRI_ICTLR_CPU_IEP_CLASS 0x2C
#define PRI_ICTLR_COP_IER 0x30 #define PRI_ICTLR_COP_IER 0x30
#define PRI_ICTLR_COP_IER_SET 0x34 #define PRI_ICTLR_COP_IER_SET 0x34
#define PRI_ICTLR_COP_IER_CLR 0x38 #define PRI_ICTLR_COP_IER_CLR 0x38
#define PRI_ICTLR_COP_IEP_CLASS 0x3C #define PRI_ICTLR_COP_IEP_CLASS 0x3C
/*! AHB Gizmo registers. */ /*! AHB Gizmo registers. */
#define AHB_ARBITRATION_PRIORITY_CTRL 0x8 #define AHB_ARBITRATION_PRIORITY_CTRL 0x8
#define PRIORITY_CTRL_WEIGHT(x) (((x) & 7) << 29) #define PRIORITY_CTRL_WEIGHT(x) (((x) & 7) << 29)
#define PRIORITY_SELECT_USB BIT(6) // USB-OTG. #define PRIORITY_SELECT_USB BIT(6) // USB-OTG.
#define PRIORITY_SELECT_USB2 BIT(18) // USB-HSIC. #define PRIORITY_SELECT_USB2 BIT(18) // USB-HSIC.
#define PRIORITY_SELECT_USB3 BIT(17) // XUSB. #define PRIORITY_SELECT_USB3 BIT(17) // XUSB.
#define AHB_GIZMO_AHB_MEM 0x10 #define AHB_GIZMO_AHB_MEM 0x10
#define AHB_MEM_ENB_FAST_REARBITRATE BIT(2) #define AHB_MEM_ENB_FAST_REARBITRATE BIT(2)
#define AHB_MEM_DONT_SPLIT_AHB_WR BIT(7) #define AHB_MEM_DONT_SPLIT_AHB_WR BIT(7)
#define AHB_MEM_IMMEDIATE BIT(18) #define AHB_MEM_IMMEDIATE BIT(18)
#define AHB_GIZMO_APB_DMA 0x14 #define AHB_GIZMO_APB_DMA 0x14
#define AHB_GIZMO_USB 0x20 #define AHB_GIZMO_USB 0x20
#define AHB_GIZMO_SDMMC4 0x48 #define AHB_GIZMO_SDMMC4 0x48
#define AHB_GIZMO_USB2 0x7C #define AHB_GIZMO_USB2 0x7C
#define AHB_GIZMO_USB3 0x80 #define AHB_GIZMO_USB3 0x80
#define AHB_GIZMO_IMMEDIATE BIT(18) #define AHB_GIZMO_IMMEDIATE BIT(18)
#define AHB_ARBITRATION_XBAR_CTRL 0xE0 #define AHB_ARBITRATION_XBAR_CTRL 0xE0
#define AHB_AHB_MEM_PREFETCH_CFG3 0xE4 #define AHB_AHB_MEM_PREFETCH_CFG3 0xE4
#define AHB_AHB_MEM_PREFETCH_CFG4 0xE8 #define AHB_AHB_MEM_PREFETCH_CFG4 0xE8
#define AHB_AHB_MEM_PREFETCH_CFG1 0xF0 #define AHB_AHB_MEM_PREFETCH_CFG1 0xF0
#define AHB_AHB_MEM_PREFETCH_CFG2 0xF4 #define AHB_AHB_MEM_PREFETCH_CFG2 0xF4
#define MST_ID(x) (((x) & 0x1F) << 26) #define MST_ID(x) (((x) & 0x1F) << 26)
#define MEM_PREFETCH_AHBDMA_MST_ID MST_ID(5) #define MEM_PREFETCH_AHBDMA_MST_ID MST_ID(5)
#define MEM_PREFETCH_USB_MST_ID MST_ID(6) // USB-OTG. #define MEM_PREFETCH_USB_MST_ID MST_ID(6) // USB-OTG.
#define MEM_PREFETCH_USB2_MST_ID MST_ID(18) // USB-HSIC. #define MEM_PREFETCH_USB2_MST_ID MST_ID(18) // USB-HSIC.
#define MEM_PREFETCH_USB3_MST_ID MST_ID(17) // XUSB. #define MEM_PREFETCH_USB3_MST_ID MST_ID(17) // XUSB.
#define MEM_PREFETCH_ADDR_BNDRY(x) (((x) & 0xF) << 21) #define MEM_PREFETCH_ADDR_BNDRY(x) (((x) & 0xF) << 21)
#define MEM_PREFETCH_ENABLE BIT(31) #define MEM_PREFETCH_ENABLE BIT(31)
#define AHB_AHB_SPARE_REG 0x110 #define AHB_ARBITRATION_AHB_MEM_WRQUE_MST_ID 0xFC
#define MEM_WRQUE_SE_MST_ID BIT(14)
#define AHB_AHB_SPARE_REG 0x110
/*! Misc registers. */ /*! Misc registers. */
#define APB_MISC_PP_STRAPPING_OPT_A 0x08 #define APB_MISC_PP_STRAPPING_OPT_A 0x8
#define APB_MISC_PP_PINMUX_GLOBAL 0x40 #define APB_MISC_PP_PINMUX_GLOBAL 0x40
#define APB_MISC_GP_HIDREV 0x804 #define APB_MISC_GP_HIDREV 0x804
#define GP_HIDREV_MAJOR_T210 0x1 #define GP_HIDREV_MAJOR_T210 0x1
#define GP_HIDREV_MAJOR_T210B01 0x2 #define GP_HIDREV_MAJOR_T210B01 0x2
#define APB_MISC_GP_AUD_MCLK_CFGPADCTRL 0x8F4 #define APB_MISC_GP_ASDBGREG 0x810
#define APB_MISC_GP_LCD_BL_PWM_CFGPADCTRL 0xA34 #define APB_MISC_GP_AUD_MCLK_CFGPADCTRL 0x8F4
#define APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL 0xA98 #define APB_MISC_GP_LCD_BL_PWM_CFGPADCTRL 0xA34
#define APB_MISC_GP_EMMC2_PAD_CFGPADCTRL 0xA9C #define APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL 0xA98
#define APB_MISC_GP_EMMC4_PAD_CFGPADCTRL 0xAB4 #define APB_MISC_GP_EMMC2_PAD_CFGPADCTRL 0xA9C
#define APB_MISC_GP_EMMC4_PAD_CFGPADCTRL 0xAB4
#define APB_MISC_GP_EMMC4_PAD_PUPD_CFGPADCTRL 0xABC #define APB_MISC_GP_EMMC4_PAD_PUPD_CFGPADCTRL 0xABC
#define APB_MISC_GP_DSI_PAD_CONTROL 0xAC0 #define APB_MISC_GP_DSI_PAD_CONTROL 0xAC0
#define APB_MISC_GP_WIFI_EN_CFGPADCTRL 0xB64 #define APB_MISC_GP_WIFI_EN_CFGPADCTRL 0xB64
#define APB_MISC_GP_WIFI_RST_CFGPADCTRL 0xB68 #define APB_MISC_GP_WIFI_RST_CFGPADCTRL 0xB68
/*! Secure boot registers. */ /*! Secure boot registers. */
#define SB_CSR 0x0 #define SB_CSR 0x0
#define SB_CSR_NS_RST_VEC_WR_DIS BIT(1) #define SB_CSR_NS_RST_VEC_WR_DIS BIT(1)
#define SB_CSR_PIROM_DISABLE BIT(4) #define SB_CSR_PIROM_DISABLE BIT(4)
#define SB_AA64_RESET_LOW 0x30 #define SB_AA64_RESET_LOW 0x30
#define SB_AA64_RST_AARCH64_MODE_EN BIT(0) #define SB_AA64_RST_AARCH64_MODE_EN BIT(0)
#define SB_AA64_RESET_HIGH 0x34 #define SB_AA64_RESET_HIGH 0x34
/*! SOR registers. */ /*! SOR registers. */
#define SOR_NV_PDISP_SOR_DP_HDCP_BKSV_LSB 0x1E8 #define SOR_DP_HDCP_BKSV_LSB 0x1E8
#define SOR_NV_PDISP_SOR_TMDS_HDCP_BKSV_LSB 0x21C #define SOR_TMDS_HDCP_BKSV_LSB 0x21C
#define SOR_NV_PDISP_SOR_TMDS_HDCP_CN_MSB 0x208 #define SOR_TMDS_HDCP_CN_MSB 0x208
#define SOR_NV_PDISP_SOR_TMDS_HDCP_CN_LSB 0x20C #define SOR_TMDS_HDCP_CN_LSB 0x20C
/*! RTC registers. */ /*! RTC registers. */
#define APBDEV_RTC_SECONDS 0x8 #define APBDEV_RTC_SECONDS 0x8
@@ -222,42 +235,22 @@
#define APBDEV_RTC_MILLI_SECONDS 0x10 #define APBDEV_RTC_MILLI_SECONDS 0x10
/*! SYSCTR0 registers. */ /*! SYSCTR0 registers. */
#define SYSCTR0_CNTFID0 0x20 #define SYSCTR0_CNTCR 0x00
#define SYSCTR0_CNTCR 0x00 #define SYSCTR0_CNTFID0 0x20
#define SYSCTR0_COUNTERID0 0xFE0 #define SYSCTR0_COUNTERS_BASE 0xFD0
#define SYSCTR0_COUNTERID1 0xFE4 #define SYSCTR0_COUNTERS 12
#define SYSCTR0_COUNTERID2 0xFE8 #define SYSCTR0_COUNTERID0 0xFE0
#define SYSCTR0_COUNTERID3 0xFEC #define SYSCTR0_COUNTERID1 0xFE4
#define SYSCTR0_COUNTERID4 0xFD0 #define SYSCTR0_COUNTERID2 0xFE8
#define SYSCTR0_COUNTERID5 0xFD4 #define SYSCTR0_COUNTERID3 0xFEC
#define SYSCTR0_COUNTERID6 0xFD8 #define SYSCTR0_COUNTERID4 0xFD0
#define SYSCTR0_COUNTERID7 0xFDC #define SYSCTR0_COUNTERID5 0xFD4
#define SYSCTR0_COUNTERID8 0xFF0 #define SYSCTR0_COUNTERID6 0xFD8
#define SYSCTR0_COUNTERID9 0xFF4 #define SYSCTR0_COUNTERID7 0xFDC
#define SYSCTR0_COUNTERID10 0xFF8 #define SYSCTR0_COUNTERID8 0xFF0
#define SYSCTR0_COUNTERID11 0xFFC #define SYSCTR0_COUNTERID9 0xFF4
#define SYSCTR0_COUNTERID10 0xFF8
/*! TMR registers. */ #define SYSCTR0_COUNTERID11 0xFFC
#define TIMERUS_CNTR_1US (0x10 + 0x0)
#define TIMERUS_USEC_CFG (0x10 + 0x4)
#define TIMER_TMR8_TMR_PTV 0x78
#define TIMER_TMR9_TMR_PTV 0x80
#define TIMER_PER_EN BIT(30)
#define TIMER_EN BIT(31)
#define TIMER_TMR8_TMR_PCR 0x7C
#define TIMER_TMR9_TMR_PCR 0x8C
#define TIMER_INTR_CLR BIT(30)
#define TIMER_WDT4_CONFIG (0x100 + 0x80)
#define TIMER_SRC(TMR) ((TMR) & 0xF)
#define TIMER_PER(PER) (((PER) & 0xFF) << 4)
#define TIMER_SYSRESET_EN BIT(14)
#define TIMER_PMCRESET_EN BIT(15)
#define TIMER_WDT4_COMMAND (0x108 + 0x80)
#define TIMER_START_CNT BIT(0)
#define TIMER_CNT_DISABLE BIT(1)
#define TIMER_WDT4_UNLOCK_PATTERN (0x10C + 0x80)
#define TIMER_MAGIC_PTRN 0xC45A
/*! I2S registers. */ /*! I2S registers. */
#define I2S1_CG 0x88 #define I2S1_CG 0x88
@@ -283,25 +276,42 @@
#define EMC_HEKA_UPD BIT(30) #define EMC_HEKA_UPD BIT(30)
/*! Flow controller registers. */ /*! Flow controller registers. */
#define FLOW_CTLR_HALT_COP_EVENTS 0x4 #define FLOW_CTLR_HALT_COP_EVENTS 0x4
#define HALT_COP_GIC_IRQ BIT(9) #define HALT_COP_GIC_IRQ BIT(9)
#define HALT_COP_LIC_IRQ BIT(11) #define HALT_COP_LIC_IRQ BIT(11)
#define HALT_COP_SEC BIT(23) #define HALT_COP_SEC BIT(23)
#define HALT_COP_MSEC BIT(24) #define HALT_COP_MSEC BIT(24)
#define HALT_COP_USEC BIT(25) #define HALT_COP_USEC BIT(25)
#define HALT_COP_JTAG BIT(28) #define HALT_COP_JTAG BIT(28)
#define HALT_COP_WAIT_EVENT BIT(30) #define HALT_COP_WAIT_EVENT BIT(30)
#define HALT_COP_STOP_UNTIL_IRQ BIT(31) #define HALT_COP_STOP_UNTIL_IRQ BIT(31)
#define HALT_COP_MAX_CNT 0xFF #define HALT_COP_MAX_CNT 0xFF
#define FLOW_CTLR_HALT_CPU0_EVENTS 0x0 #define FLOW_CTLR_HALT_CPU0_EVENTS 0x0
#define FLOW_CTLR_HALT_CPU1_EVENTS 0x14 #define FLOW_CTLR_HALT_CPU1_EVENTS 0x14
#define FLOW_CTLR_HALT_CPU2_EVENTS 0x1C #define FLOW_CTLR_HALT_CPU2_EVENTS 0x1C
#define FLOW_CTLR_HALT_CPU3_EVENTS 0x24 #define FLOW_CTLR_HALT_CPU3_EVENTS 0x24
#define FLOW_CTLR_CPU0_CSR 0x8 #define FLOW_CTLR_CPU0_CSR 0x8
#define FLOW_CTLR_CPU1_CSR 0x18 #define FLOW_CTLR_CPU1_CSR 0x18
#define FLOW_CTLR_CPU2_CSR 0x20 #define FLOW_CTLR_CPU2_CSR 0x20
#define FLOW_CTLR_CPU3_CSR 0x28 #define FLOW_CTLR_CPU3_CSR 0x28
#define FLOW_CTLR_RAM_REPAIR 0x40 #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 FLOW_CTLR_BPMP_CLUSTER_CONTROL 0x98
#define CLUSTER_CTRL_ACTIVE_SLOW BIT(0)
/* MSelect registers */
#define MSELECT_CONFIG 0x00
#define MSELECT_CFG_ERR_RESP_EN_PCIE BIT(24)
#define MSELECT_CFG_ERR_RESP_EN_GPU BIT(25)
#define MSELECT_CFG_WRAP_TO_INCR_BPMP BIT(27)
#define MSELECT_CFG_WRAP_TO_INCR_PCIE BIT(28)
#define MSELECT_CFG_WRAP_TO_INCR_GPU BIT(29)
/* NVDEC registers */
#define NVDEC_SA_KEYSLOT_FALCON 0x2100
#define NVDEC_SA_KEYSLOT_TZ 0x2104
#define NVDEC_SA_KEYSLOT_OTF 0x210C
#define NVDEC_SA_KEYSLOT_GLOBAL_RW 0x2118
#define NVDEC_VPR_ALL_OTF_GOTO_VPR 0x211C
#endif #endif

121
bdk/soc/timer.c Normal file
View File

@@ -0,0 +1,121 @@
/*
* Timer/Watchdog driver for Tegra X1
*
* Copyright (c) 2019 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <soc/bpmp.h>
#include <soc/irq.h>
#include <soc/timer.h>
#include <soc/t210.h>
#include <utils/types.h>
#define EXCP_TYPE_ADDR 0x4003FFF8
#define EXCP_TYPE_WDT 0x544457 // "WDT".
u32 get_tmr_s()
{
(void)RTC(APBDEV_RTC_MILLI_SECONDS);
return (u32)RTC(APBDEV_RTC_SECONDS);
}
u32 get_tmr_ms()
{
// The registers must be read with the following order:
// RTC_MILLI_SECONDS (0x10) -> RTC_SHADOW_SECONDS (0xC)
return (u32)(RTC(APBDEV_RTC_MILLI_SECONDS) + (RTC(APBDEV_RTC_SHADOW_SECONDS) * 1000));
}
u32 get_tmr_us()
{
return (u32)TMR(TIMERUS_CNTR_1US);
}
void msleep(u32 ms)
{
#ifdef USE_RTC_TIMER
u32 start = (u32)RTC(APBDEV_RTC_MILLI_SECONDS) + (RTC(APBDEV_RTC_SHADOW_SECONDS) * 1000);
// Casting to u32 is important!
while (((u32)(RTC(APBDEV_RTC_MILLI_SECONDS) + (RTC(APBDEV_RTC_SHADOW_SECONDS) * 1000)) - start) <= ms)
;
#else
bpmp_msleep(ms);
#endif
}
void usleep(u32 us)
{
#ifdef USE_RTC_TIMER
u32 start = (u32)TMR(TIMERUS_CNTR_1US);
// Check if timer is at upper limits and use BPMP sleep so it doesn't wake up immediately.
if ((start + us) < start)
bpmp_usleep(us);
else
while ((u32)(TMR(TIMERUS_CNTR_1US) - start) <= us) // Casting to u32 is important!
;
#else
bpmp_usleep(us);
#endif
}
// Instruction wait loop. Each loop is 3 cycles (SUBS+BGT). Usage: isleep(ILOOP(instr)). Base 408MHz: 7.35ns.
void __attribute__((target("arm"))) isleep(u32 is)
{
asm volatile( "0:" "SUBS %[is_cnt], #1;" "BGT 0b;" : [is_cnt] "+r" (is));
}
void timer_usleep(u32 us)
{
TMR(TIMER_TMR8_TMR_PTV) = TIMER_EN | us;
irq_wait_event(IRQ_TMR8);
TMR(TIMER_TMR8_TMR_PCR) = TIMER_INTR_CLR;
}
void watchdog_start(u32 us, u32 mode)
{
// WDT4 is for BPMP.
TMR(TIMER_WDT4_UNLOCK_PATTERN) = TIMER_MAGIC_PTRN;
TMR(TIMER_TMR9_TMR_PTV) = TIMER_EN | TIMER_PER_EN | us;
TMR(TIMER_WDT4_CONFIG) = TIMER_SRC(9) | TIMER_PER(1) | mode;
TMR(TIMER_WDT4_COMMAND) = TIMER_START_CNT;
}
void watchdog_end()
{
// WDT4 is for BPMP.
TMR(TIMER_TMR9_TMR_PTV) = 0;
TMR(TIMER_WDT4_UNLOCK_PATTERN) = TIMER_MAGIC_PTRN;
TMR(TIMER_WDT4_COMMAND) = TIMER_START_CNT; // Re-arm to clear any interrupts.
TMR(TIMER_WDT4_COMMAND) = TIMER_CNT_DISABLE;
TMR(TIMER_TMR9_TMR_PCR) = TIMER_INTR_CLR;
}
void watchdog_handle()
{
// Disable watchdog and clear its interrupts.
watchdog_end();
// Set watchdog magic.
*(u32 *)EXCP_TYPE_ADDR = EXCP_TYPE_WDT;
}
bool watchdog_fired()
{
// Return if watchdog got fired. User handles clearing.
return (*(u32 *)EXCP_TYPE_ADDR == EXCP_TYPE_WDT);
}

64
bdk/soc/timer.h Normal file
View File

@@ -0,0 +1,64 @@
/*
* Timer/Watchdog driver for Tegra X1
*
* Copyright (c) 2019 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TIMER_H_
#define _TIMER_H_
#include <utils/types.h>
// TMR registers.
#define TIMERUS_CNTR_1US (0x10 + 0x0)
#define TIMERUS_USEC_CFG (0x10 + 0x4)
#define TIMER_TMR8_TMR_PTV 0x78
#define TIMER_TMR9_TMR_PTV 0x80
#define TIMER_PER_EN BIT(30)
#define TIMER_EN BIT(31)
#define TIMER_TMR8_TMR_PCR 0x7C
#define TIMER_TMR9_TMR_PCR 0x8C
#define TIMER_INTR_CLR BIT(30)
// WDT registers.
#define TIMER_WDT4_CONFIG (0x100 + 0x80)
#define TIMER_SRC(TMR) ((TMR) & 0xF)
#define TIMER_PER(PER) (((PER) & 0xFF) << 4)
#define TIMER_IRQENABL_EN BIT(12)
#define TIMER_FIQENABL_EN BIT(13)
#define TIMER_SYSRESET_EN BIT(14)
#define TIMER_PMCRESET_EN BIT(15)
#define TIMER_WDT4_COMMAND (0x108 + 0x80)
#define TIMER_START_CNT BIT(0)
#define TIMER_CNT_DISABLE BIT(1)
#define TIMER_WDT4_UNLOCK_PATTERN (0x10C + 0x80)
#define TIMER_MAGIC_PTRN 0xC45A
u32 get_tmr_us();
u32 get_tmr_ms();
u32 get_tmr_s();
void usleep(u32 us);
void msleep(u32 ms);
#define ILOOP(is) ((is) / 3)
void isleep(u32 is);
void timer_usleep(u32 us);
void watchdog_start(u32 us, u32 mode);
void watchdog_end();
void watchdog_handle();
bool watchdog_fired();
#endif

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2019-2020 CTCaer * Copyright (c) 2019-2022 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -17,45 +17,58 @@
#include <soc/uart.h> #include <soc/uart.h>
#include <soc/clock.h> #include <soc/clock.h>
#include <soc/timer.h>
#include <soc/t210.h> #include <soc/t210.h>
#include <utils/util.h>
/* UART A, B, C, D and E. */ /* UART A, B, C, D and E. */
static const u32 uart_baseoff[5] = { 0, 0x40, 0x200, 0x300, 0x400 }; static const u32 uart_baseoff[5] = { 0, 0x40, 0x200, 0x300, 0x400 };
void uart_init(u32 idx, u32 baud) void uart_init(u32 idx, u32 baud, u32 mode)
{ {
uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]); uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]);
// Make sure no data is being sent. // Make sure no data is being sent.
uart_wait_idle(idx, UART_TX_IDLE); if (!(mode & (UART_MCR_CTS_EN | UART_MCR_DTR)))
uart_wait_xfer(idx, UART_TX_IDLE);
// Set clock. // Set clock.
bool clk_type = clock_uart_use_src_div(idx, baud); bool clk_type = clock_uart_use_src_div(idx, baud);
// 2 STOP bits for rates > 1M. (Reduced efficiency but less errors on high baudrates).
u32 uart_lcr_stop = baud > 1000000 ? UART_LCR_STOP : 0;
// Misc settings. // Misc settings.
u32 div = clk_type ? ((8 * baud + 408000000) / (16 * baud)) : 1; // DIV_ROUND_CLOSEST. u32 div = clk_type ? ((8 * baud + 408000000) / (16 * baud)) : 1; // DIV_ROUND_CLOSEST.
uart->UART_IER_DLAB = 0; // Disable interrupts. uart->UART_IER_DLAB = 0; // Disable interrupts.
uart->UART_LCR = UART_LCR_DLAB | UART_LCR_WORD_LENGTH_8; // Enable DLAB & set 8n1 mode. uart->UART_LCR = UART_LCR_DLAB | UART_LCR_WORD_LENGTH_8; // Enable DLAB & set 8n1 mode.
uart->UART_THR_DLAB = (u8)div; // Divisor latch LSB. uart->UART_THR_DLAB = (u8)div; // Divisor latch LSB.
uart->UART_IER_DLAB = (u8)(div >> 8); // Divisor latch MSB. uart->UART_IER_DLAB = (u8)(div >> 8); // Divisor latch MSB.
uart->UART_LCR = UART_LCR_WORD_LENGTH_8; // Disable DLAB.
// Disable DLAB and set STOP bits setting if applicable.
uart->UART_LCR = uart_lcr_stop | UART_LCR_WORD_LENGTH_8;
(void)uart->UART_SPR; (void)uart->UART_SPR;
// Setup and flush fifo. // Enable fifo.
uart->UART_IIR_FCR = UART_IIR_FCR_EN_FIFO; uart->UART_IIR_FCR = UART_IIR_FCR_EN_FIFO;
(void)uart->UART_SPR; (void)uart->UART_SPR;
usleep(20); usleep(20);
uart->UART_MCR = 0; // Disable hardware flow control.
// Disable hardware flow control.
uart->UART_MCR = 0;
usleep(96); usleep(96);
// Clear tx/rx fifos.
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 | UART_IIR_FCR_TX_CLR | UART_IIR_FCR_RX_CLR;
// Set hardware flow control.
uart->UART_MCR = mode;
// Wait 3 symbols for baudrate change. // Wait 3 symbols for baudrate change.
usleep(3 * ((baud + 999999) / baud)); usleep(3 * ((baud + 999999) / baud));
uart_wait_idle(idx, UART_TX_IDLE | UART_RX_IDLE); uart_wait_xfer(idx, UART_TX_IDLE | UART_RX_RDYR);
} }
void uart_wait_idle(u32 idx, u32 which) void uart_wait_xfer(u32 idx, u32 which)
{ {
uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]); uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]);
if (UART_TX_IDLE & which) if (UART_TX_IDLE & which)
@@ -63,10 +76,10 @@ void uart_wait_idle(u32 idx, u32 which)
while (!(uart->UART_LSR & UART_LSR_TMTY)) while (!(uart->UART_LSR & UART_LSR_TMTY))
; ;
} }
if (UART_RX_IDLE & which) if (UART_RX_RDYR & which)
{ {
while (uart->UART_LSR & UART_LSR_RDR) while (uart->UART_LSR & UART_LSR_RDR)
; (void)uart->UART_THR_DLAB;
} }
} }
@@ -85,26 +98,31 @@ void uart_send(u32 idx, const u8 *buf, u32 len)
u32 uart_recv(u32 idx, u8 *buf, u32 len) u32 uart_recv(u32 idx, u8 *buf, u32 len)
{ {
uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]); uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]);
bool manual_mode = uart->UART_MCR & UART_MCR_RTS;
u32 timeout = get_tmr_us() + 250; u32 timeout = get_tmr_us() + 250;
u32 i; u32 i;
if (manual_mode)
uart->UART_MCR &= ~UART_MCR_RTS;
for (i = 0; ; i++) for (i = 0; ; i++)
{ {
while (!(uart->UART_LSR & UART_LSR_RDR)) if (len && len <= i)
{
if (timeout < get_tmr_us())
break;
if (len && len < i)
break;
}
if (timeout < get_tmr_us())
break; break;
while (!(uart->UART_LSR & UART_LSR_RDR))
if (timeout < get_tmr_us())
goto out;
buf[i] = uart->UART_THR_DLAB; buf[i] = uart->UART_THR_DLAB;
timeout = get_tmr_us() + 250; timeout = get_tmr_us() + 250;
} }
return i ? (len ? (i - 1) : i) : 0; out:
if (manual_mode)
uart->UART_MCR |= UART_MCR_RTS;
return i;
} }
void uart_invert(u32 idx, bool enable, u32 invert_mask) void uart_invert(u32 idx, bool enable, u32 invert_mask)
@@ -118,6 +136,14 @@ void uart_invert(u32 idx, bool enable, u32 invert_mask)
(void)uart->UART_SPR; (void)uart->UART_SPR;
} }
void uart_set_mode(u32 idx, u32 mode)
{
uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]);
uart->UART_MCR = mode;
(void)uart->UART_SPR;
}
u32 uart_get_IIR(u32 idx) u32 uart_get_IIR(u32 idx)
{ {
uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]); uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]);
@@ -172,3 +198,24 @@ void uart_empty_fifo(u32 idx, u32 which)
} }
} }
} }
#ifdef DEBUG_UART_PORT
#include <stdarg.h>
#include <string.h>
#include <utils/sprintf.h>
void uart_printf(const char *fmt, ...)
{
va_list ap;
//! NOTE: Anything more and it will hang. Heap usage is out of the question.
char text[256];
va_start(ap, fmt);
s_vprintf(text, fmt, ap);
va_end(ap);
uart_send(DEBUG_UART_PORT, (u8 *)text, strlen(text));
}
#endif

View File

@@ -28,33 +28,33 @@
#define BAUD_115200 115200 #define BAUD_115200 115200
#define UART_TX_IDLE 0x1 #define UART_TX_IDLE BIT(0)
#define UART_RX_IDLE 0x2 #define UART_RX_RDYR BIT(1)
#define UART_TX_FIFO_FULL 0x100 #define UART_TX_FIFO_FULL BIT(8)
#define UART_RX_FIFO_EMPTY 0x200 #define UART_RX_FIFO_EMPTY BIT(9)
#define UART_INVERT_RXD 0x01 #define UART_INVERT_RXD BIT(0)
#define UART_INVERT_TXD 0x02 #define UART_INVERT_TXD BIT(1)
#define UART_INVERT_CTS 0x04 #define UART_INVERT_CTS BIT(2)
#define UART_INVERT_RTS 0x08 #define UART_INVERT_RTS BIT(3)
#define UART_IER_DLAB_IE_EORD 0x20 #define UART_IER_DLAB_IE_EORD BIT(5)
#define UART_LCR_DLAB 0x80
#define UART_LCR_STOP 0x4
#define UART_LCR_WORD_LENGTH_8 0x3 #define UART_LCR_WORD_LENGTH_8 0x3
#define UART_LCR_STOP BIT(2)
#define UART_LCR_DLAB BIT(7)
#define UART_LSR_RDR 0x1 #define UART_LSR_RDR BIT(0)
#define UART_LSR_THRE 0x20 #define UART_LSR_THRE BIT(5)
#define UART_LSR_TMTY 0x40 #define UART_LSR_TMTY BIT(6)
#define UART_LSR_FIFOE 0x80 #define UART_LSR_FIFOE BIT(7)
#define UART_IIR_FCR_TX_CLR 0x4 #define UART_IIR_FCR_EN_FIFO BIT(0)
#define UART_IIR_FCR_RX_CLR 0x2 #define UART_IIR_FCR_RX_CLR BIT(1)
#define UART_IIR_FCR_EN_FIFO 0x1 #define UART_IIR_FCR_TX_CLR BIT(2)
#define UART_IIR_NO_INT BIT(0) #define UART_IIR_NO_INT BIT(0)
#define UART_IIR_INT_MASK 0xF #define UART_IIR_INT_MASK 0xF
/* Custom returned interrupt results. Actual interrupts are -1 */ /* Custom returned interrupt results. Actual interrupts are -1 */
#define UART_IIR_NOI 0 // No interrupt. #define UART_IIR_NOI 0 // No interrupt.
@@ -65,8 +65,10 @@
#define UART_IIR_REDI 5 // Receiver end of data interrupt. #define UART_IIR_REDI 5 // Receiver end of data interrupt.
#define UART_IIR_RDTI 7 // Receiver data timeout interrupt. #define UART_IIR_RDTI 7 // Receiver data timeout interrupt.
#define UART_MCR_RTS 0x2 #define UART_MCR_DTR BIT(0)
#define UART_MCR_DTR 0x1 #define UART_MCR_RTS BIT(1)
#define UART_MCR_CTS_EN BIT(5)
#define UART_MCR_RTS_EN BIT(6)
typedef struct _uart_t typedef struct _uart_t
{ {
@@ -86,13 +88,29 @@ typedef struct _uart_t
/* 0x3C */ vu32 UART_ASR; /* 0x3C */ vu32 UART_ASR;
} uart_t; } uart_t;
void uart_init(u32 idx, u32 baud); //! TODO: Commented out modes are not supported yet.
void uart_wait_idle(u32 idx, u32 which); typedef enum _uart_mode_t
{
UART_AO_TX_AO_RX = 0,
//UART_MN_TX_AO_RX = UART_MCR_RTS | UART_MCR_DTR,
UART_AO_TX_MN_RX = UART_MCR_RTS, // Up to 36 bytes read.
//UART_MN_TX_AO_RX = UART_MCR_DTR,
//UART_HW_TX_HW_RX = UART_MCR_RTS_EN | UART_MCR_CTS_EN,
UART_AO_TX_HW_RX = UART_MCR_RTS_EN,
//UART_HW_TX_AO_RX = UART_MCR_CTS_EN,
} uart_mode_t;
void uart_init(u32 idx, u32 baud, u32 mode);
void uart_wait_xfer(u32 idx, u32 which);
void uart_send(u32 idx, const u8 *buf, u32 len); void uart_send(u32 idx, const u8 *buf, u32 len);
u32 uart_recv(u32 idx, u8 *buf, u32 len); u32 uart_recv(u32 idx, u8 *buf, u32 len);
void uart_invert(u32 idx, bool enable, u32 invert_mask); void uart_invert(u32 idx, bool enable, u32 invert_mask);
void uart_set_mode(u32 idx, u32 mode);
u32 uart_get_IIR(u32 idx); u32 uart_get_IIR(u32 idx);
void uart_set_IIR(u32 idx); void uart_set_IIR(u32 idx);
void uart_empty_fifo(u32 idx, u32 which); void uart_empty_fifo(u32 idx, u32 which);
#ifdef DEBUG_UART_PORT
void uart_printf(const char *fmt, ...);
#endif
#endif #endif

227
bdk/storage/emmc.c Normal file
View File

@@ -0,0 +1,227 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2019-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,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "emmc.h"
#include <mem/heap.h>
#include <soc/fuse.h>
#include <storage/mbr_gpt.h>
#include <utils/list.h>
static u16 emmc_errors[3] = { 0 }; // Init and Read/Write errors.
static u32 emmc_mode = EMMC_MMC_HS400;
sdmmc_t emmc_sdmmc;
sdmmc_storage_t emmc_storage;
FATFS emmc_fs;
#ifdef BDK_EMUMMC_ENABLE
int emummc_storage_read(u32 sector, u32 num_sectors, void *buf);
int emummc_storage_write(u32 sector, u32 num_sectors, void *buf);
#endif
void emmc_error_count_increment(u8 type)
{
switch (type)
{
case EMMC_ERROR_INIT_FAIL:
emmc_errors[0]++;
break;
case EMMC_ERROR_RW_FAIL:
emmc_errors[1]++;
break;
case EMMC_ERROR_RW_RETRY:
emmc_errors[2]++;
break;
}
}
u16 *emmc_get_error_count()
{
return emmc_errors;
}
u32 emmc_get_mode()
{
return emmc_mode;
}
void emmc_end() { sdmmc_storage_end(&emmc_storage); }
int emmc_init_retry(bool power_cycle)
{
u32 bus_width = SDMMC_BUS_WIDTH_8;
u32 type = SDHCI_TIMING_MMC_HS400;
// Power cycle SD eMMC.
if (power_cycle)
{
emmc_mode--;
emmc_end();
}
// Get init parameters.
switch (emmc_mode)
{
case EMMC_INIT_FAIL: // Reset to max.
return 0;
case EMMC_1BIT_HS52:
bus_width = SDMMC_BUS_WIDTH_1;
type = SDHCI_TIMING_MMC_HS52;
break;
case EMMC_8BIT_HS52:
type = SDHCI_TIMING_MMC_HS52;
break;
case EMMC_MMC_HS200:
type = SDHCI_TIMING_MMC_HS200;
break;
case EMMC_MMC_HS400:
type = SDHCI_TIMING_MMC_HS400;
break;
default:
emmc_mode = EMMC_MMC_HS400;
}
return sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, bus_width, type);
}
bool emmc_initialize(bool power_cycle)
{
// Reset mode in case of previous failure.
if (emmc_mode == EMMC_INIT_FAIL)
emmc_mode = EMMC_MMC_HS400;
if (power_cycle)
emmc_end();
int res = !emmc_init_retry(false);
while (true)
{
if (!res)
return true;
else
{
emmc_errors[EMMC_ERROR_INIT_FAIL]++;
if (emmc_mode == EMMC_INIT_FAIL)
break;
else
res = !emmc_init_retry(true);
}
}
emmc_end();
return false;
}
int emmc_set_partition(u32 partition) { return sdmmc_storage_set_mmc_partition(&emmc_storage, partition); }
void emmc_gpt_parse(link_t *gpt)
{
gpt_t *gpt_buf = (gpt_t *)calloc(GPT_NUM_BLOCKS, EMMC_BLOCKSIZE);
#ifdef BDK_EMUMMC_ENABLE
emummc_storage_read(GPT_FIRST_LBA, GPT_NUM_BLOCKS, gpt_buf);
#else
sdmmc_storage_read(&emmc_storage, GPT_FIRST_LBA, GPT_NUM_BLOCKS, gpt_buf);
#endif
// Check if no GPT or more than max allowed entries.
if (memcmp(&gpt_buf->header.signature, "EFI PART", 8) || gpt_buf->header.num_part_ents > 128)
goto out;
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);
if (gpt_buf->entries[i].lba_start < gpt_buf->header.first_use_lba)
continue;
part->index = i;
part->lba_start = gpt_buf->entries[i].lba_start;
part->lba_end = gpt_buf->entries[i].lba_end;
part->attrs = gpt_buf->entries[i].attrs;
// ASCII conversion. Copy only the LSByte of the UTF-16LE name.
for (u32 j = 0; j < 36; j++)
part->name[j] = gpt_buf->entries[i].name[j];
part->name[35] = 0;
list_append(gpt, &part->link);
}
out:
free(gpt_buf);
}
void emmc_gpt_free(link_t *gpt)
{
LIST_FOREACH_SAFE(iter, gpt)
free(CONTAINER_OF(iter, emmc_part_t, link));
}
emmc_part_t *emmc_part_find(link_t *gpt, const char *name)
{
LIST_FOREACH_ENTRY(emmc_part_t, part, gpt, link)
if (!strcmp(part->name, name))
return part;
return NULL;
}
int emmc_part_read(emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf)
{
// The last LBA is inclusive.
if (part->lba_start + sector_off > part->lba_end)
return 0;
#ifdef BDK_EMUMMC_ENABLE
return emummc_storage_read(part->lba_start + sector_off, num_sectors, buf);
#else
return sdmmc_storage_read(&emmc_storage, part->lba_start + sector_off, num_sectors, buf);
#endif
}
int emmc_part_write(emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf)
{
// The last LBA is inclusive.
if (part->lba_start + sector_off > part->lba_end)
return 0;
#ifdef BDK_EMUMMC_ENABLE
return emummc_storage_write(part->lba_start + sector_off, num_sectors, buf);
#else
return sdmmc_storage_write(&emmc_storage, part->lba_start + sector_off, num_sectors, buf);
#endif
}
void nx_emmc_get_autorcm_masks(u8 *mod0, u8 *mod1)
{
if (fuse_read_hw_state() == FUSE_NX_HW_STATE_PROD)
{
*mod0 = 0xF7;
*mod1 = 0x86;
}
else
{
*mod0 = 0x37;
*mod1 = 0x84;
}
}

View File

@@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2019-2022 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -14,17 +15,34 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef _NX_EMMC_H_ #ifndef _EMMC_H_
#define _NX_EMMC_H_ #define _EMMC_H_
#include <storage/sdmmc.h> #include <storage/sdmmc.h>
#include <libs/fatfs/ff.h>
#include <utils/types.h> #include <utils/types.h>
#include <utils/list.h> #include <utils/list.h>
#define NX_GPT_FIRST_LBA 1 #include <libs/fatfs/ff.h>
#define NX_GPT_NUM_BLOCKS 33
#define NX_EMMC_BLOCKSIZE 512 #define GPT_FIRST_LBA 1
#define GPT_NUM_BLOCKS 33
#define EMMC_BLOCKSIZE 512
enum
{
EMMC_INIT_FAIL = 0,
EMMC_1BIT_HS52 = 1,
EMMC_8BIT_HS52 = 2,
EMMC_MMC_HS200 = 3,
EMMC_MMC_HS400 = 4,
};
enum
{
EMMC_ERROR_INIT_FAIL = 0,
EMMC_ERROR_RW_FAIL = 1,
EMMC_ERROR_RW_RETRY = 2
};
typedef struct _emmc_part_t typedef struct _emmc_part_t
{ {
@@ -40,10 +58,20 @@ extern sdmmc_t emmc_sdmmc;
extern sdmmc_storage_t emmc_storage; extern sdmmc_storage_t emmc_storage;
extern FATFS emmc_fs; extern FATFS emmc_fs;
void nx_emmc_gpt_parse(link_t *gpt, sdmmc_storage_t *storage); void emmc_error_count_increment(u8 type);
void nx_emmc_gpt_free(link_t *gpt); u16 *emmc_get_error_count();
emmc_part_t *nx_emmc_part_find(link_t *gpt, const char *name); u32 emmc_get_mode();
int nx_emmc_part_read(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf); int emmc_init_retry(bool power_cycle);
int nx_emmc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf); bool emmc_initialize(bool power_cycle);
int emmc_set_partition(u32 partition);
void emmc_end();
void emmc_gpt_parse(link_t *gpt);
void emmc_gpt_free(link_t *gpt);
emmc_part_t *emmc_part_find(link_t *gpt, const char *name);
int emmc_part_read(emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf);
int emmc_part_write(emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf);
void nx_emmc_get_autorcm_masks(u8 *mod0, u8 *mod1);
#endif #endif

View File

@@ -39,40 +39,40 @@ typedef struct _mbr_part_t
typedef struct _mbr_t typedef struct _mbr_t
{ {
u8 bootstrap[440]; /* 0x000 */ u8 bootstrap[440];
u32 signature; /* 0x1B8 */ u32 signature;
u16 copy_protected; /* 0x1BC */ u16 copy_protected;
mbr_part_t partitions[4]; /* 0x1BE */ mbr_part_t partitions[4];
u16 boot_signature; /* 0x1FE */ u16 boot_signature;
} __attribute__((packed)) mbr_t; } __attribute__((packed)) mbr_t;
typedef struct _gpt_entry_t typedef struct _gpt_entry_t
{ {
u8 type_guid[0x10]; /* 0x00 */ u8 type_guid[0x10];
u8 part_guid[0x10]; /* 0x10 */ u8 part_guid[0x10];
u64 lba_start; /* 0x20 */ u64 lba_start;
u64 lba_end; /* 0x28 */ u64 lba_end;
u64 attrs; /* 0x30 */ u64 attrs;
u16 name[36]; /* 0x38 */ u16 name[36];
} gpt_entry_t; } gpt_entry_t;
typedef struct _gpt_header_t typedef struct _gpt_header_t
{ {
u64 signature; // "EFI PART" /* 0x00 */ u64 signature; // "EFI PART"
u32 revision; /* 0x08 */ u32 revision;
u32 size; /* 0x0C */ u32 size;
u32 crc32; /* 0x10 */ u32 crc32;
u32 res1; /* 0x14 */ u32 res1;
u64 my_lba; /* 0x18 */ u64 my_lba;
u64 alt_lba; /* 0x20 */ u64 alt_lba;
u64 first_use_lba; /* 0x28 */ u64 first_use_lba;
u64 last_use_lba; /* 0x30 */ u64 last_use_lba;
u8 disk_guid[0x10]; /* 0x38 */ u8 disk_guid[0x10];
u64 part_ent_lba; /* 0x48 */ u64 part_ent_lba;
u32 num_part_ents; /* 0x50 */ u32 num_part_ents;
u32 part_ent_size; /* 0x54 */ u32 part_ent_size;
u32 part_ents_crc32; /* 0x58 */ u32 part_ents_crc32;
u8 res2[420]; // Used as first 3 partition entries backup for HOS. /* 0x5C */ u8 res2[420]; // Used as first 3 partition entries backup for HOS.
} gpt_header_t; } gpt_header_t;
typedef struct _gpt_t typedef struct _gpt_t

View File

@@ -408,7 +408,10 @@
/* /*
* BKOPS status level * BKOPS status level
*/ */
#define EXT_CSD_BKOPS_LEVEL_2 0x2 #define EXT_CSD_BKOPS_OK 0x0
#define EXT_CSD_BKOPS_NON_CRITICAL 0x1
#define EXT_CSD_BKOPS_PERF_IMPACTED 0x2
#define EXT_CSD_BKOPS_CRITICAL 0x3
/* /*
* BKOPS modes * BKOPS modes

325
bdk/storage/nx_emmc_bis.c Normal file
View File

@@ -0,0 +1,325 @@
/*
* eMMC BIS driver for Nintendo Switch
*
* Copyright (c) 2019-2020 shchmue
* Copyright (c) 2019-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,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <memory_map.h>
#include <mem/heap.h>
#include <sec/se.h>
#include <storage/emmc.h>
#include <storage/sd.h>
#include <storage/sdmmc.h>
#include <utils/types.h>
#define BIS_CLUSTER_SECTORS 32
#define BIS_CLUSTER_SIZE 16384
#define BIS_CACHE_MAX_ENTRIES 16384
#define BIS_CACHE_LOOKUP_TBL_EMPTY_ENTRY -1
typedef struct _cluster_cache_t
{
u32 cluster_idx; // Index of the cluster in the partition.
bool dirty; // Has been modified without write-back flag.
u8 data[BIS_CLUSTER_SIZE]; // The cached cluster itself. Aligned to 8 bytes for DMA engine.
} cluster_cache_t;
typedef struct _bis_cache_t
{
bool full;
bool enabled;
u32 dirty_cnt;
u32 top_idx;
u8 dma_buff[BIS_CLUSTER_SIZE]; // Aligned to 8 bytes for DMA engine.
cluster_cache_t clusters[];
} bis_cache_t;
static u8 ks_crypt = 0;
static u8 ks_tweak = 0;
static u32 emu_offset = 0;
static emmc_part_t *system_part = NULL;
static u32 *cache_lookup_tbl = (u32 *)NX_BIS_LOOKUP_ADDR;
static bis_cache_t *bis_cache = (bis_cache_t *)NX_BIS_CACHE_ADDR;
static int nx_emmc_bis_write_block(u32 sector, u32 count, void *buff, bool flush)
{
if (!system_part)
return 3; // Not ready.
int res;
u8 tweak[SE_KEY_128_SIZE] __attribute__((aligned(4)));
u32 cluster = sector / BIS_CLUSTER_SECTORS;
u32 aligned_sector = cluster * BIS_CLUSTER_SECTORS;
u32 sector_in_cluster = sector % BIS_CLUSTER_SECTORS;
u32 lookup_idx = cache_lookup_tbl[cluster];
bool is_cached = lookup_idx != (u32)BIS_CACHE_LOOKUP_TBL_EMPTY_ENTRY;
// Write to cached cluster.
if (is_cached)
{
if (buff)
memcpy(bis_cache->clusters[lookup_idx].data + sector_in_cluster * EMMC_BLOCKSIZE, buff, count * EMMC_BLOCKSIZE);
else
buff = bis_cache->clusters[lookup_idx].data;
if (!bis_cache->clusters[lookup_idx].dirty)
bis_cache->dirty_cnt++;
bis_cache->clusters[lookup_idx].dirty = true;
if (!flush)
return 0; // Success.
// Reset args to trigger a full cluster flush to emmc.
sector_in_cluster = 0;
sector = aligned_sector;
count = BIS_CLUSTER_SECTORS;
}
// Encrypt cluster.
if (!se_aes_xts_crypt_sec_nx(ks_tweak, ks_crypt, ENCRYPT, cluster, tweak, true, sector_in_cluster, bis_cache->dma_buff, buff, count * EMMC_BLOCKSIZE))
return 1; // Encryption error.
// If not reading from cache, do a regular read and decrypt.
if (!emu_offset)
res = emmc_part_write(system_part, sector, count, bis_cache->dma_buff);
else
res = sdmmc_storage_write(&sd_storage, emu_offset + system_part->lba_start + sector, count, bis_cache->dma_buff);
if (!res)
return 1; // R/W error.
// Mark cache entry not dirty if write succeeds.
if (is_cached)
{
bis_cache->clusters[lookup_idx].dirty = false;
bis_cache->dirty_cnt--;
}
return 0; // Success.
}
static void _nx_emmc_bis_cluster_cache_init(bool enable_cache)
{
u32 cache_lookup_tbl_size = (system_part->lba_end - system_part->lba_start + 1) / BIS_CLUSTER_SECTORS * sizeof(*cache_lookup_tbl);
// Clear cache header.
memset(bis_cache, 0, sizeof(bis_cache_t));
// Clear cluster lookup table.
memset(cache_lookup_tbl, BIS_CACHE_LOOKUP_TBL_EMPTY_ENTRY, cache_lookup_tbl_size);
// Enable cache.
bis_cache->enabled = enable_cache;
}
static void _nx_emmc_bis_flush_cache()
{
if (!bis_cache->enabled || !bis_cache->dirty_cnt)
return;
for (u32 i = 0; i < bis_cache->top_idx && bis_cache->dirty_cnt; i++)
{
if (bis_cache->clusters[i].dirty) {
nx_emmc_bis_write_block(bis_cache->clusters[i].cluster_idx * BIS_CLUSTER_SECTORS, BIS_CLUSTER_SECTORS, NULL, true);
bis_cache->dirty_cnt--;
}
}
_nx_emmc_bis_cluster_cache_init(true);
}
static int nx_emmc_bis_read_block_normal(u32 sector, u32 count, void *buff)
{
static u32 prev_cluster = -1;
static u32 prev_sector = 0;
static u8 tweak[SE_KEY_128_SIZE] __attribute__((aligned(4)));
int res;
bool regen_tweak = true;
u32 tweak_exp = 0;
u32 cluster = sector / BIS_CLUSTER_SECTORS;
u32 sector_in_cluster = sector % BIS_CLUSTER_SECTORS;
// If not reading from cache, do a regular read and decrypt.
if (!emu_offset)
res = emmc_part_read(system_part, sector, count, bis_cache->dma_buff);
else
res = sdmmc_storage_read(&sd_storage, emu_offset + system_part->lba_start + sector, count, bis_cache->dma_buff);
if (!res)
return 1; // R/W error.
if (prev_cluster != cluster) // Sector in different cluster than last read.
{
prev_cluster = cluster;
tweak_exp = sector_in_cluster;
}
else if (sector > prev_sector) // Sector in same cluster and past last sector.
{
// Calculates the new tweak using the saved one, reducing expensive _gf256_mul_x_le calls.
tweak_exp = sector - prev_sector - 1;
regen_tweak = false;
}
else // Sector in same cluster and before or same as last sector.
tweak_exp = sector_in_cluster;
// Maximum one cluster (1 XTS crypto block 16KB).
if (!se_aes_xts_crypt_sec_nx(ks_tweak, ks_crypt, DECRYPT, prev_cluster, tweak, regen_tweak, tweak_exp, buff, bis_cache->dma_buff, count * EMMC_BLOCKSIZE))
return 1; // R/W error.
prev_sector = sector + count - 1;
return 0; // Success.
}
static int nx_emmc_bis_read_block_cached(u32 sector, u32 count, void *buff)
{
int res;
u8 cache_tweak[SE_KEY_128_SIZE] __attribute__((aligned(4)));
u32 cluster = sector / BIS_CLUSTER_SECTORS;
u32 cluster_sector = cluster * BIS_CLUSTER_SECTORS;
u32 sector_in_cluster = sector % BIS_CLUSTER_SECTORS;
u32 lookup_idx = cache_lookup_tbl[cluster];
// Read from cached cluster.
if (lookup_idx != (u32)BIS_CACHE_LOOKUP_TBL_EMPTY_ENTRY)
{
memcpy(buff, bis_cache->clusters[lookup_idx].data + sector_in_cluster * EMMC_BLOCKSIZE, count * EMMC_BLOCKSIZE);
return 0; // Success.
}
// Flush cache if full.
if (bis_cache->top_idx >= BIS_CACHE_MAX_ENTRIES)
_nx_emmc_bis_flush_cache();
// Set new cached cluster parameters.
bis_cache->clusters[bis_cache->top_idx].cluster_idx = cluster;
bis_cache->clusters[bis_cache->top_idx].dirty = false;
cache_lookup_tbl[cluster] = bis_cache->top_idx;
// Read the whole cluster the sector resides in.
if (!emu_offset)
res = emmc_part_read(system_part, cluster_sector, BIS_CLUSTER_SECTORS, bis_cache->dma_buff);
else
res = sdmmc_storage_read(&sd_storage, emu_offset + system_part->lba_start + cluster_sector, BIS_CLUSTER_SECTORS, bis_cache->dma_buff);
if (!res)
return 1; // R/W error.
// Decrypt cluster.
if (!se_aes_xts_crypt_sec_nx(ks_tweak, ks_crypt, DECRYPT, cluster, cache_tweak, true, 0, bis_cache->dma_buff, bis_cache->dma_buff, BIS_CLUSTER_SIZE))
return 1; // Decryption error.
// Copy to cluster cache.
memcpy(bis_cache->clusters[bis_cache->top_idx].data, bis_cache->dma_buff, BIS_CLUSTER_SIZE);
memcpy(buff, bis_cache->dma_buff + sector_in_cluster * EMMC_BLOCKSIZE, count * EMMC_BLOCKSIZE);
// Increment cache count.
bis_cache->top_idx++;
return 0; // Success.
}
static int nx_emmc_bis_read_block(u32 sector, u32 count, void *buff)
{
if (!system_part)
return 3; // Not ready.
if (bis_cache->enabled)
return nx_emmc_bis_read_block_cached(sector, count, buff);
else
return nx_emmc_bis_read_block_normal(sector, count, buff);
}
int nx_emmc_bis_read(u32 sector, u32 count, void *buff)
{
u8 *buf = (u8 *)buff;
u32 curr_sct = sector;
while (count)
{
// Get sector index in cluster and use it as boundary check.
u32 cnt_max = (curr_sct % BIS_CLUSTER_SECTORS);
cnt_max = BIS_CLUSTER_SECTORS - cnt_max;
u32 sct_cnt = MIN(count, cnt_max); // Only allow cluster sized access.
if (nx_emmc_bis_read_block(curr_sct, sct_cnt, buf))
return 0;
count -= sct_cnt;
curr_sct += sct_cnt;
buf += sct_cnt * EMMC_BLOCKSIZE;
}
return 1;
}
int nx_emmc_bis_write(u32 sector, u32 count, void *buff)
{
u8 *buf = (u8 *)buff;
u32 curr_sct = sector;
while (count)
{
// Get sector index in cluster and use it as boundary check.
u32 cnt_max = (curr_sct % BIS_CLUSTER_SECTORS);
cnt_max = BIS_CLUSTER_SECTORS - cnt_max;
u32 sct_cnt = MIN(count, cnt_max); // Only allow cluster sized access.
if (nx_emmc_bis_write_block(curr_sct, sct_cnt, buf, false))
return 0;
count -= sct_cnt;
curr_sct += sct_cnt;
buf += sct_cnt * EMMC_BLOCKSIZE;
}
return 1;
}
void nx_emmc_bis_init(emmc_part_t *part, bool enable_cache, u32 emummc_offset)
{
system_part = part;
emu_offset = emummc_offset;
_nx_emmc_bis_cluster_cache_init(enable_cache);
if (!strcmp(part->name, "PRODINFO") || !strcmp(part->name, "PRODINFOF"))
{
ks_crypt = 0;
ks_tweak = 1;
}
else if (!strcmp(part->name, "SAFE"))
{
ks_crypt = 2;
ks_tweak = 3;
}
else if (!strcmp(part->name, "SYSTEM") || !strcmp(part->name, "USER"))
{
ks_crypt = 4;
ks_tweak = 5;
}
else
system_part = NULL;
}
void nx_emmc_bis_end()
{
_nx_emmc_bis_flush_cache();
system_part = NULL;
}

View File

@@ -18,7 +18,7 @@
#ifndef NX_EMMC_BIS_H #ifndef NX_EMMC_BIS_H
#define NX_EMMC_BIS_H #define NX_EMMC_BIS_H
#include "../storage/nx_emmc.h" #include <storage/emmc.h>
#include <storage/sdmmc.h> #include <storage/sdmmc.h>
typedef struct _nx_emmc_cal0_spk_t typedef struct _nx_emmc_cal0_spk_t
@@ -85,13 +85,13 @@ typedef struct _nx_emmc_cal0_t
u8 bd_mac[6]; u8 bd_mac[6];
u8 crc16_pad4[2]; u8 crc16_pad4[2];
u8 rsvd2[8]; u8 rsvd2[8];
u8 acc_offset[6]; u16 acc_offset[3];
u8 crc16_pad5[2]; u8 crc16_pad5[2];
u8 acc_scale[6]; u16 acc_scale[3];
u8 crc16_pad6[2]; u8 crc16_pad6[2];
u8 gyro_offset[6]; u16 gyro_offset[3];
u8 crc16_pad7[2]; u8 crc16_pad7[2];
u8 gyro_scale[6]; u16 gyro_scale[3];
u8 crc16_pad8[2]; u8 crc16_pad8[2];
char serial_number[0x18]; char serial_number[0x18];
u8 crc16_pad9[8]; u8 crc16_pad9[8];
@@ -163,10 +163,8 @@ typedef struct _nx_emmc_cal0_t
u8 crc16_pad36[0x10]; u8 crc16_pad36[0x10];
u8 ext_ecc_b233_eticket_key[0x50]; u8 ext_ecc_b233_eticket_key[0x50];
u8 crc16_pad37[0x10]; u8 crc16_pad37[0x10];
u8 ext_ecc_rsa2048_eticket_key_iv[0x10]; u8 ext_ecc_rsa2048_eticket_key[0x240];
u8 ext_ecc_rsa2048_eticket_key[0x230]; u8 crc16_pad38[0x10];
u32 ext_ecc_rsa2048_eticket_key_ver;
u8 crc16_pad38[0xC];
u8 ext_ssl_key[0x130]; u8 ext_ssl_key[0x130];
u8 crc16_pad39[0x10]; u8 crc16_pad39[0x10];
u8 ext_gc_key[0x130]; u8 ext_gc_key[0x130];
@@ -215,26 +213,23 @@ typedef struct _nx_emmc_cal0_t
// 6.0.0 and up. // 6.0.0 and up.
u8 battery_ver; u8 battery_ver;
u8 crc16_pad58[0x1F]; u8 crc16_pad58[0xF];
// 10.0.0 and up.
u8 touch_ic_vendor_id;
u8 crc16_pad59[0xF];
// 9.0.0 and up. // 9.0.0 and up.
u32 home_menu_scheme_model; u32 color_model;
u8 crc16_pad59[0xC]; u8 crc16_pad60[0xC];
// 10.0.0 and up. // 10.0.0 and up.
u8 console_6axis_sensor_mount_type; u8 console_6axis_sensor_mount_type;
} __attribute__((packed)) nx_emmc_cal0_t; } __attribute__((packed)) nx_emmc_cal0_t;
#define MAGIC_CAL0 0x304C4143 int nx_emmc_bis_read(u32 sector, u32 count, void *buff);
#define NX_EMMC_CALIBRATION_OFFSET 0x4400 int nx_emmc_bis_write(u32 sector, u32 count, void *buff);
#define NX_EMMC_CALIBRATION_SIZE 0x8000 void nx_emmc_bis_init(emmc_part_t *part, bool enable_cache, u32 emummc_offset);
#define XTS_CLUSTER_SIZE 0x4000 void nx_emmc_bis_end();
int nx_emmc_bis_read(u32 sector, u32 count, void *buff); #endif
int nx_emmc_bis_write(u32 sector, u32 count, void *buff);
void nx_emmc_bis_cluster_cache_init();
void nx_emmc_bis_init(emmc_part_t *part);
void nx_emmc_bis_finalize();
void nx_emmc_bis_cache_lock(bool lock);
#endif

View File

@@ -1,60 +0,0 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NX_SD_H
#define NX_SD_H
#include <storage/sdmmc.h>
#include <storage/sdmmc_driver.h>
#include <libs/fatfs/ff.h>
enum
{
SD_INIT_FAIL = 0,
SD_1BIT_HS25 = 1,
SD_4BIT_HS25 = 2,
SD_UHS_SDR82 = 3,
SD_UHS_SDR104 = 4
};
enum
{
SD_ERROR_INIT_FAIL = 0,
SD_ERROR_RW_FAIL = 1,
SD_ERROR_RW_RETRY = 2
};
extern sdmmc_t sd_sdmmc;
extern sdmmc_storage_t sd_storage;
extern FATFS sd_fs;
void sd_error_count_increment(u8 type);
u16 *sd_get_error_count();
bool sd_get_card_removed();
bool sd_get_card_initialized();
bool sd_get_card_mounted();
u32 sd_get_mode();
int sd_init_retry(bool power_cycle);
bool sd_initialize(bool power_cycle);
bool sd_mount();
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);
#endif

View File

@@ -20,6 +20,7 @@
#include "ramdisk.h" #include "ramdisk.h"
#include <libs/fatfs/diskio.h> #include <libs/fatfs/diskio.h>
#include <libs/fatfs/ff.h>
#include <mem/heap.h> #include <mem/heap.h>
#include <utils/types.h> #include <utils/types.h>
@@ -27,10 +28,11 @@
static u32 disk_size = 0; static u32 disk_size = 0;
int ram_disk_init(FATFS *ram_fs, u32 ramdisk_size) int ram_disk_init(void *ram_fs, u32 ramdisk_size)
{ {
int res = 0; int res = 0;
disk_size = ramdisk_size; disk_size = ramdisk_size;
FATFS *ram_fatfs = (FATFS *)ram_fs;
// If ramdisk is not raw, format it. // If ramdisk is not raw, format it.
if (ram_fs) if (ram_fs)
@@ -49,7 +51,7 @@ int ram_disk_init(FATFS *ram_fs, u32 ramdisk_size)
// Mount ramdisk. // Mount ramdisk.
if (!res) if (!res)
res = f_mount(ram_fs, "ram:", 1); res = f_mount(ram_fatfs, "ram:", 1);
free(buf); free(buf);
} }

View File

@@ -19,11 +19,11 @@
#ifndef RAM_DISK_H #ifndef RAM_DISK_H
#define RAM_DISK_H #define RAM_DISK_H
#include <libs/fatfs/ff.h> #include <utils/types.h>
#define RAMDISK_CLUSTER_SZ 32768 #define RAMDISK_CLUSTER_SZ 32768
int ram_disk_init(FATFS *ram_fs, u32 ramdisk_size); int ram_disk_init(void *ram_fs, u32 ramdisk_size);
int ram_disk_read(u32 sector, u32 sector_count, void *buf); int ram_disk_read(u32 sector, u32 sector_count, void *buf);
int ram_disk_write(u32 sector, u32 sector_count, const void *buf); int ram_disk_write(u32 sector, u32 sector_count, const void *buf);

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2019 CTCaer * Copyright (c) 2018-2023 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -15,16 +15,25 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <storage/nx_sd.h> #include <storage/sd.h>
#include <storage/sdmmc.h> #include <storage/sdmmc.h>
#include <storage/sdmmc_driver.h> #include <storage/sdmmc_driver.h>
#include <gfx_utils.h> #include <gfx_utils.h>
#include <libs/fatfs/ff.h> #include <libs/fatfs/ff.h>
#include <mem/heap.h> #include <mem/heap.h>
bool sd_mounted = false; #ifndef BDK_SDMMC_UHS_DDR200_SUPPORT
#define SD_DEFAULT_SPEED SD_UHS_SDR104
#else
#define SD_DEFAULT_SPEED SD_UHS_DDR208
#endif
static bool sd_mounted = false;
static bool sd_init_done = false;
static bool insertion_event = false;
static u16 sd_errors[3] = { 0 }; // Init and Read/Write errors. static u16 sd_errors[3] = { 0 }; // Init and Read/Write errors.
static u32 sd_mode = SD_UHS_SDR82; static u32 sd_mode = SD_DEFAULT_SPEED;
sdmmc_t sd_sdmmc; sdmmc_t sd_sdmmc;
sdmmc_storage_t sd_storage; sdmmc_storage_t sd_storage;
@@ -53,12 +62,22 @@ u16 *sd_get_error_count()
bool sd_get_card_removed() bool sd_get_card_removed()
{ {
if (!sdmmc_get_sd_inserted()) if (insertion_event && !sdmmc_get_sd_inserted())
return true; return true;
return false; return false;
} }
bool sd_get_card_initialized()
{
return sd_init_done;
}
bool sd_get_card_mounted()
{
return sd_mounted;
}
u32 sd_get_mode() u32 sd_get_mode()
{ {
return sd_mode; return sd_mode;
@@ -67,7 +86,11 @@ u32 sd_get_mode()
int sd_init_retry(bool power_cycle) int sd_init_retry(bool power_cycle)
{ {
u32 bus_width = SDMMC_BUS_WIDTH_4; u32 bus_width = SDMMC_BUS_WIDTH_4;
u32 type = SDHCI_TIMING_UHS_SDR82; #ifndef BDK_SDMMC_UHS_DDR200_SUPPORT
u32 type = SDHCI_TIMING_UHS_SDR104;
#else
u32 type = SDHCI_TIMING_UHS_DDR200;
#endif
// Power cycle SD card. // Power cycle SD card.
if (power_cycle) if (power_cycle)
@@ -81,21 +104,45 @@ int sd_init_retry(bool power_cycle)
{ {
case SD_INIT_FAIL: // Reset to max. case SD_INIT_FAIL: // Reset to max.
return 0; return 0;
case SD_1BIT_HS25: case SD_1BIT_HS25:
bus_width = SDMMC_BUS_WIDTH_1; bus_width = SDMMC_BUS_WIDTH_1;
type = SDHCI_TIMING_SD_HS25; type = SDHCI_TIMING_SD_HS25;
break; break;
case SD_4BIT_HS25: case SD_4BIT_HS25:
type = SDHCI_TIMING_SD_HS25; type = SDHCI_TIMING_SD_HS25;
break; break;
case SD_UHS_SDR82: case SD_UHS_SDR82:
type = SDHCI_TIMING_UHS_SDR82; type = SDHCI_TIMING_UHS_SDR82;
break; break;
case SD_UHS_SDR104:
type = SDHCI_TIMING_UHS_SDR104;
break;
#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT
case SD_UHS_DDR208:
type = SDHCI_TIMING_UHS_DDR200;
break;
#endif
default: default:
sd_mode = SD_UHS_SDR82; sd_mode = SD_DEFAULT_SPEED;
break;
} }
return sdmmc_storage_init_sd(&sd_storage, &sd_sdmmc, bus_width, type); int res = sdmmc_storage_init_sd(&sd_storage, &sd_sdmmc, bus_width, type);
if (res)
{
sd_init_done = true;
insertion_event = true;
}
else
sd_init_done = false;
return res;
} }
bool sd_initialize(bool power_cycle) bool sd_initialize(bool power_cycle)
@@ -111,7 +158,7 @@ bool sd_initialize(bool power_cycle)
return true; return true;
else if (!sdmmc_get_sd_inserted()) // SD Card is not inserted. else if (!sdmmc_get_sd_inserted()) // SD Card is not inserted.
{ {
sd_mode = SD_UHS_SDR82; sd_mode = SD_DEFAULT_SPEED;
break; break;
} }
else else
@@ -130,15 +177,15 @@ bool sd_initialize(bool power_cycle)
return false; return false;
} }
bool is_sd_inited = false;
bool sd_mount() bool sd_mount()
{ {
if (sd_mounted) if (sd_init_done && sd_mounted)
return true; return true;
int res = !sd_initialize(false); int res = 0;
is_sd_inited = !res;
if (!sd_init_done)
res = !sd_initialize(false);
if (res) if (res)
{ {
@@ -151,7 +198,8 @@ bool sd_mount()
} }
else else
{ {
res = f_mount(&sd_fs, "", 1); if (!sd_mounted)
res = f_mount(&sd_fs, "0:", 1); // Volume 0 is SD.
if (res == FR_OK) if (res == FR_OK)
{ {
sd_mounted = true; sd_mounted = true;
@@ -167,26 +215,43 @@ bool sd_mount()
return false; return false;
} }
static void _sd_deinit() static void _sd_deinit(bool deinit)
{ {
if (sd_mode == SD_INIT_FAIL) if (deinit)
sd_mode = SD_UHS_SDR82;
if (sd_mounted)
{ {
f_mount(NULL, "", 1); insertion_event = false;
sdmmc_storage_end(&sd_storage); if (sd_mode == SD_INIT_FAIL)
sd_mounted = false; sd_mode = SD_DEFAULT_SPEED;
is_sd_inited = false;
} }
if (sd_init_done)
{
if (sd_mounted)
f_mount(NULL, "0:", 1); // Volume 0 is SD.
if (deinit)
{
sdmmc_storage_end(&sd_storage);
sd_init_done = false;
}
}
sd_mounted = false;
} }
void sd_unmount() { _sd_deinit(); } void sd_unmount() { _sd_deinit(false); }
void sd_end() { _sd_deinit(); } void sd_end() { _sd_deinit(true); }
bool sd_is_gpt()
{
return sd_fs.part_type;
}
void *sd_file_read(const char *path, u32 *fsize) void *sd_file_read(const char *path, u32 *fsize)
{ {
FIL fp; FIL fp;
if (!sd_get_card_mounted())
return NULL;
if (f_open(&fp, path, FA_READ) != FR_OK) if (f_open(&fp, path, FA_READ) != FR_OK)
return NULL; return NULL;
@@ -214,6 +279,9 @@ int sd_save_to_file(void *buf, u32 size, const char *filename)
{ {
FIL fp; FIL fp;
u32 res = 0; u32 res = 0;
if (!sd_get_card_mounted())
return FR_DISK_ERR;
res = f_open(&fp, filename, FA_CREATE_ALWAYS | FA_WRITE); res = f_open(&fp, filename, FA_CREATE_ALWAYS | FA_WRITE);
if (res) if (res)
{ {

Some files were not shown because too many files have changed in this diff Show More