uplift libbdk

Signed-off-by: Damien Zhao <zdm65477730@126.com>
This commit is contained in:
Damien Zhao
2025-11-21 22:20:38 +08:00
parent 3454c13e4a
commit ec6518ccbf
73 changed files with 5114 additions and 1659 deletions

View File

@@ -24,7 +24,7 @@
#include <input/als.h> #include <input/als.h>
#include <input/joycon.h> #include <input/joycon.h>
#include <input/touch.h> #include <input/touch.h>
#include <mem/emc.h> #include <mem/emc_t210.h>
#include <mem/heap.h> #include <mem/heap.h>
#include <mem/mc.h> #include <mem/mc.h>
#include <mem/minerva.h> #include <mem/minerva.h>
@@ -58,7 +58,7 @@
#include <soc/uart.h> #include <soc/uart.h>
#include <storage/emmc.h> #include <storage/emmc.h>
#include <storage/mbr_gpt.h> #include <storage/mbr_gpt.h>
#include <storage/mmc.h> #include <storage/mmc_def.h>
#include <storage/nx_emmc_bis.h> #include <storage/nx_emmc_bis.h>
#include <storage/ramdisk.h> #include <storage/ramdisk.h>
#include <storage/sd.h> #include <storage/sd.h>
@@ -72,6 +72,8 @@
#include <utils/ini.h> #include <utils/ini.h>
#include <utils/list.h> #include <utils/list.h>
#include <utils/sprintf.h> #include <utils/sprintf.h>
#include <utils/tegra_bct.h>
#include <utils/tegra_bit.h>
#include <utils/types.h> #include <utils/types.h>
#include <utils/util.h> #include <utils/util.h>

View File

@@ -20,7 +20,6 @@
#include "di.h" #include "di.h"
#include <power/max77620.h> #include <power/max77620.h>
#include <power/max7762x.h> #include <power/max7762x.h>
#include <mem/heap.h>
#include <soc/clock.h> #include <soc/clock.h>
#include <soc/fuse.h> #include <soc/fuse.h>
#include <soc/gpio.h> #include <soc/gpio.h>
@@ -132,7 +131,6 @@ static void _display_dsi_read_rx_fifo(u32 *data)
int display_dsi_read(u8 cmd, u32 len, void *data) int display_dsi_read(u8 cmd, u32 len, void *data)
{ {
int res = 0;
u32 fifo[DSI_STATUS_RX_FIFO_SIZE] = {0}; u32 fifo[DSI_STATUS_RX_FIFO_SIZE] = {0};
// Drain RX FIFO. // Drain RX FIFO.
@@ -181,14 +179,13 @@ int display_dsi_read(u8 cmd, u32 len, void *data)
case ACK_ERROR_RES: case ACK_ERROR_RES:
default: default:
res = 1; return 1;
break;
} }
} }
else else
res = 1; return 1;
return res; return 0;
} }
int display_dsi_vblank_read(u8 cmd, u32 len, void *data) int display_dsi_vblank_read(u8 cmd, u32 len, void *data)
@@ -375,7 +372,7 @@ void display_init()
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_SET) = BIT(CLK_W_DSIA_LP); CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_SET) = BIT(CLK_W_DSIA_LP);
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP) = CLK_SRC_DIV(6); // Set PLLP_OUT and div 6 (68MHz). CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP) = CLK_SRC_DIV(6); // Set PLLP_OUT and div 6 (68MHz).
// Bring every IO rail out of deep power down. // Bring every IO rail out of deep power down. (Though no rail bit is set.)
PMC(APBDEV_PMC_IO_DPD_REQ) = PMC_IO_DPD_REQ_DPD_OFF; PMC(APBDEV_PMC_IO_DPD_REQ) = PMC_IO_DPD_REQ_DPD_OFF;
PMC(APBDEV_PMC_IO_DPD2_REQ) = PMC_IO_DPD_REQ_DPD_OFF; PMC(APBDEV_PMC_IO_DPD2_REQ) = PMC_IO_DPD_REQ_DPD_OFF;
@@ -414,9 +411,9 @@ void display_init()
APB_MISC(APB_MISC_GP_DSI_PAD_CONTROL) = 0; APB_MISC(APB_MISC_GP_DSI_PAD_CONTROL) = 0;
} }
// Set DISP1 clock source, parent clock and DSI/PCLK to low power mode. // Set DISP1 clock source, parent clock and DSI/PCLK to command mode.
// T210: DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 100.0 MHz, PLLD_OUT0 (DSI-PCLK): 50.0 MHz. (PCLK: 16.66 MHz) // T210: DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 100.0 MHz, PLLD_OUT0 (DSI-BCLK): 50.0 MHz. (PCLK: 16.66 MHz)
// T210B01: DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 97.8 MHz, PLLD_OUT0 (DSI-PCLK): 48.9 MHz. (PCLK: 16.30 MHz) // T210B01: DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 97.8 MHz, PLLD_OUT0 (DSI-BCLK): 48.9 MHz. (PCLK: 16.30 MHz)
clock_enable_plld(3, 20, true, tegra_t210); clock_enable_plld(3, 20, true, tegra_t210);
// Setup Display Interface initial window configuration. // Setup Display Interface initial window configuration.
@@ -538,11 +535,11 @@ void display_init()
// Unblank display. // Unblank display.
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_SET_DISPLAY_ON, 20000); _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_SET_DISPLAY_ON, 20000);
// Setup final dsi clock. // Switch to DSI HS mode.
// DIVM: 1, DIVN: 24, DIVP: 1. PLLD_OUT: 468.0 MHz, PLLD_OUT0 (DSI): 234.0 MHz. // DIVM: 1, DIVN: 24, DIVP: 1. PLLD_OUT: 468.0 MHz, PLLD_OUT0 (DSI-BCLK): 234.0 MHz. (PCLK: 78 MHz)
clock_enable_plld(1, 24, false, tegra_t210); clock_enable_plld(1, 24, false, tegra_t210);
// Finalize DSI init packet sequence configuration. // Set HS PHY timing and finalize DSI packet sequence configuration.
reg_write_array((u32 *)DSI_BASE, _di_dsi_seq_pkt_video_non_burst_no_eot_config, ARRAY_SIZE(_di_dsi_seq_pkt_video_non_burst_no_eot_config)); reg_write_array((u32 *)DSI_BASE, _di_dsi_seq_pkt_video_non_burst_no_eot_config, ARRAY_SIZE(_di_dsi_seq_pkt_video_non_burst_no_eot_config));
// Set 1-by-1 pixel/clock and pixel clock to 234 / 3 = 78 MHz. For 60 Hz refresh rate. // Set 1-by-1 pixel/clock and pixel clock to 234 / 3 = 78 MHz. For 60 Hz refresh rate.
@@ -569,8 +566,8 @@ void display_init()
// Set pad trimmers and set MIPI DSI cal offsets. // Set pad trimmers and set MIPI DSI cal offsets.
if (tegra_t210) if (tegra_t210)
{ {
reg_write_array((u32 *)DSI_BASE, _di_dsi_pad_cal_config_t210, ARRAY_SIZE(_di_dsi_pad_cal_config_t210)); reg_write_array((u32 *)DSI_BASE, _di_dsi_pad_cal_config_t210, ARRAY_SIZE(_di_dsi_pad_cal_config_t210));
reg_write_array((u32 *)MIPI_CAL_BASE, _di_mipi_dsi_cal_prod_config_t210, ARRAY_SIZE(_di_mipi_dsi_cal_prod_config_t210)); reg_write_array((u32 *)MIPI_CAL_BASE, _di_mipi_dsi_cal_prod_config_t210, ARRAY_SIZE(_di_mipi_dsi_cal_prod_config_t210));
} }
else else
{ {
@@ -700,9 +697,9 @@ static void _display_panel_and_hw_end(bool no_panel_deinit)
// De-initialize video controller. // De-initialize video controller.
reg_write_array((u32 *)DISPLAY_A_BASE, _di_dc_video_disable_config, ARRAY_SIZE(_di_dc_video_disable_config)); reg_write_array((u32 *)DISPLAY_A_BASE, _di_dc_video_disable_config, ARRAY_SIZE(_di_dc_video_disable_config));
// Set DISP1 clock source, parent clock and DSI/PCLK to low power mode. // Set DISP1 clock source, parent clock and DSI/PCLK to command mode.
// T210: DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 100.0 MHz, PLLD_OUT0 (DSI-PCLK): 50.0 MHz. (PCLK: 16.66 MHz) // T210: DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 100.0 MHz, PLLD_OUT0 (DSI-BCLK): 50.0 MHz. (PCLK: 16.66 MHz)
// T210B01: DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 97.8 MHz, PLLD_OUT0 (DSI-PCLK): 48.9 MHz. (PCLK: 16.30 MHz) // T210B01: DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 97.8 MHz, PLLD_OUT0 (DSI-BCLK): 48.9 MHz. (PCLK: 16.30 MHz)
clock_enable_plld(3, 20, true, hw_get_chip_id() == GP_HIDREV_MAJOR_T210); clock_enable_plld(3, 20, true, hw_get_chip_id() == GP_HIDREV_MAJOR_T210);
// Set timings for lowpower clocks. // Set timings for lowpower clocks.

View File

@@ -730,7 +730,7 @@
#define MIPI_DCS_PRIV_UNK_D9 0xD9 #define MIPI_DCS_PRIV_UNK_D9 0xD9
#define MIPI_DCS_PRIV_SM_DISPLAY_ID 0xDD #define MIPI_DCS_PRIV_SM_DISPLAY_ID 0xDD
// LVL1 LVL2 LVL3 UNK0 UNK1 // 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_SM_SET_REGS_LOCK 0xE2 // Samsung: Lock (default): 5A5A A5A5 A5A5 A500 A500. Lock/Unlock: A5/5A. LVL1 group is normal registers.
#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.
@@ -842,8 +842,8 @@
enum enum
{ {
PANEL_JDI_XXX062M = 0x10, PANEL_JDI_XXX062M = 0x10,
PANEL_JDI_LAM062M109A = 0x0910, PANEL_JDI_LAM062M109A = 0x0910, // SI.
PANEL_JDI_LPM062M326A = 0x2610, PANEL_JDI_LPM062M326A = 0x2610, // LTPS.
PANEL_INL_P062CCA_AZ1 = 0x0F20, PANEL_INL_P062CCA_AZ1 = 0x0F20,
PANEL_AUO_A062TAN01 = 0x0F30, PANEL_AUO_A062TAN01 = 0x0F30,
PANEL_INL_2J055IA_27A = 0x1020, PANEL_INL_2J055IA_27A = 0x1020,
@@ -851,12 +851,14 @@ enum
PANEL_SHP_LQ055T1SW10 = 0x1040, PANEL_SHP_LQ055T1SW10 = 0x1040,
PANEL_SAM_AMS699VC01 = 0x2050, PANEL_SAM_AMS699VC01 = 0x2050,
// Found on 6/2" clones. Unknown markings. Quality seems JDI like. Has bad low backlight scaling. ID: [83] 94 [0F]. // Found on 6/2" clones. Unknown markings. Clone of AUO A062TAN01.
// Quality seems JDI like. Has bad low backlight scaling. ID: [83] 94 [0F]. Sometimes reports [30] 94 [0F]. Both IDs have correct CRC16.
PANEL_OEM_CLONE_6_2 = 0x0F83, PANEL_OEM_CLONE_6_2 = 0x0F83,
// Found on 5.5" clones with AUO A055TAN02 (59.05A30.001) fake markings. // Found on 5.5" clones with AUO A055TAN02 (59.05A30.001) fake markings.
PANEL_OEM_CLONE_5_5 = 0x00B3, PANEL_OEM_CLONE_5_5 = 0x00B3,
// Found on 5.5" clones with AUO A055TAN02 (59.05A30.001) fake markings. // Found on 5.5" clones with AUO A055TAN02 (59.05A30.001) fake markings.
PANEL_OEM_CLONE = 0x0000 PANEL_OEM_CLONE = 0x0000
//0x0F40 [40] 94 [0F], 5.5" clone
}; };
void display_init(); void display_init();

View File

@@ -20,7 +20,7 @@ static const reg_cfg_t _di_dc_setup_win_config[] = {
{DC_CMD_STATE_ACCESS, READ_MUX_ASSEMBLY | WRITE_MUX_ASSEMBLY}, {DC_CMD_STATE_ACCESS, READ_MUX_ASSEMBLY | WRITE_MUX_ASSEMBLY},
{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, WIN_A_ACT_HCNTR_SEL | WIN_B_ACT_HCNTR_SEL | WIN_C_ACT_HCNTR_SEL}, {DC_CMD_REG_ACT_CONTROL, WIN_A_ACT_HCNTR_SEL | WIN_B_ACT_HCNTR_SEL | WIN_C_ACT_HCNTR_SEL | WIN_D_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_DISP_DC_MCCIF_FIFOCTRL, 0}, {DC_DISP_DC_MCCIF_FIFOCTRL, 0},
@@ -197,7 +197,7 @@ static const reg_cfg_t _di_dsi_panel_init_config_jdi[] = {
{DSI_TRIGGER, DSI_TRIGGER_HOST} {DSI_TRIGGER, DSI_TRIGGER_HOST}
}; };
// DSI packet config. // DSI HS packet config.
static const reg_cfg_t _di_dsi_seq_pkt_video_non_burst_no_eot_config[] = { static const reg_cfg_t _di_dsi_seq_pkt_video_non_burst_no_eot_config[] = {
{DSI_PAD_CONTROL_1, 0}, {DSI_PAD_CONTROL_1, 0},
@@ -211,6 +211,7 @@ static const reg_cfg_t _di_dsi_seq_pkt_video_non_burst_no_eot_config[] = {
{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 packet sequence */
{DSI_PKT_SEQ_0_LO, 0x40000208}, {DSI_PKT_SEQ_0_LO, 0x40000208},
{DSI_PKT_SEQ_2_LO, 0x40000308}, {DSI_PKT_SEQ_2_LO, 0x40000308},
{DSI_PKT_SEQ_4_LO, 0x40000308}, {DSI_PKT_SEQ_4_LO, 0x40000308},

View File

@@ -1,5 +1,5 @@
/* /*
* Touch driver for Nintendo Switch's STM FingerTip S (4CD60D) touch controller * Touch driver for Nintendo Switch's STM FingerTip S (FTM4CD60DA1BE/FTM4CD50TA1BE) touch controller
* *
* Copyright (c) 2018 langerhans * Copyright (c) 2018 langerhans
* Copyright (c) 2018-2023 CTCaer * Copyright (c) 2018-2023 CTCaer
@@ -458,4 +458,4 @@ void touch_power_off()
max7762x_regulator_enable(REGULATOR_LDO6, false); max7762x_regulator_enable(REGULATOR_LDO6, false);
clock_disable_i2c(I2C_3); clock_disable_i2c(I2C_3);
} }

View File

@@ -61,27 +61,7 @@ DRESULT disk_set_info (BYTE pdrv, BYTE cmd, void *buff);
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */ #define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */ #define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */
#define SET_SECTOR_OFFSET 5 /* Set media logical offset */ #define SET_SECTOR_OFFSET 5 /* Set media logical offset */
#define SET_WRITE_PROTECT 6 /* Lock/Unlock media removal */
/* Generic command (Not used by FatFs) */
#define CTRL_POWER 5 /* Get/Set power status */
#define CTRL_LOCK 6 /* Lock/Unlock media removal */
#define CTRL_EJECT 7 /* Eject media */
#define CTRL_FORMAT 8 /* Create physical format on the media */
/* MMC/SDC specific ioctl command */
#define MMC_GET_TYPE 10 /* Get card type */
#define MMC_GET_CSD 11 /* Get CSD */
#define MMC_GET_CID 12 /* Get CID */
#define MMC_GET_OCR 13 /* Get OCR */
#define MMC_GET_SDSTAT 14 /* Get SD status */
#define ISDIO_READ 55 /* Read data form SD iSDIO register */
#define ISDIO_WRITE 56 /* Write data to SD iSDIO register */
#define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */
/* ATA/CF specific ioctl command */
#define ATA_GET_REV 20 /* Get F/W revision */
#define ATA_GET_MODEL 21 /* Get model name */
#define ATA_GET_SN 22 /* Get serial number */
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2022 CTCaer * Copyright (c) 2018-2025 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,
@@ -39,7 +39,7 @@
#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 <storage/mbr_gpt.h>
#include <storage/sd.h> #include <utils/util.h>
#include <gfx_utils.h> #include <gfx_utils.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);
@@ -6119,10 +6119,26 @@ FRESULT f_mkfs (
for (i = 0, pau = 1; cst32[i] && cst32[i] <= n; i++, pau <<= 1) ; /* Get from table */ for (i = 0, pau = 1; cst32[i] && cst32[i] <= n; i++, pau <<= 1) ; /* Get from table */
} }
n_clst = sz_vol / pau; /* Number of clusters */ n_clst = sz_vol / pau; /* Number of clusters */
sz_fat = (n_clst * 4 + 8 + ss - 1) / ss; /* FAT size [sector] */ while (1) {
sz_rsv = 32; /* Number of reserved sectors */ /* Do not account for reserved/root cluster on FAT size for better alignment. */
sz_dir = 0; /* No static directory */ sz_fat = (n_clst * 4 + ss - 1) / ss; /* FAT size [sector]. */
if (n_clst <= MAX_FAT16 || n_clst > MAX_FAT32) LEAVE_MKFS(FR_MKFS_ABORTED); sz_rsv = 2048; /* Number of reserved sectors. Use 1MB for better performance (for flash memory media) */
sz_dir = 0; /* No static directory */
if (n_clst <= MAX_FAT16 || n_clst > MAX_FAT32) LEAVE_MKFS(FR_MKFS_ABORTED);
b_fat = b_vol + sz_rsv; /* FAT base */
b_data = b_fat + sz_fat * n_fats + sz_dir; /* Data base */
/* Align data base to erase block boundary (for flash memory media) */
n = ((b_data + sz_blk - 1) & ~(sz_blk - 1)) - b_data; /* Next nearest erase block from current data base */
b_fat += n; /* FAT32: Move FAT base */
/* Make sure FAT base is aligned to reserved size for performance (PRF2SAFE min cluster alignment) */
if ((b_fat & (sz_rsv - 1) || (n_fats == 2 && sz_fat & (sz_rsv - 1)))) {
n_clst++; /* FAT size must always be bigger than real free size */
continue;
}
sz_rsv += n;
break;
}
} else { /* FAT volume */ } else { /* FAT volume */
if (pau == 0) { /* au auto-selection */ if (pau == 0) { /* au auto-selection */
n = sz_vol / 0x1000; /* Volume size in unit of 4KS */ n = sz_vol / 0x1000; /* Volume size in unit of 4KS */
@@ -6138,17 +6154,13 @@ FRESULT f_mkfs (
sz_fat = (n + ss - 1) / ss; /* FAT size [sector] */ sz_fat = (n + ss - 1) / ss; /* FAT size [sector] */
sz_rsv = 1; /* Number of reserved sectors */ sz_rsv = 1; /* Number of reserved sectors */
sz_dir = (DWORD)n_rootdir * SZDIRE / ss; /* Rootdir size [sector] */ sz_dir = (DWORD)n_rootdir * SZDIRE / ss; /* Rootdir size [sector] */
} b_fat = b_vol + sz_rsv; /* FAT base */
b_fat = b_vol + sz_rsv; /* FAT base */ b_data = b_fat + sz_fat * n_fats + sz_dir; /* Data base */
b_data = b_fat + sz_fat * n_fats + sz_dir; /* Data base */
/* Align data base to erase block boundary (for flash memory media) */ /* Align data base to erase block boundary (for flash memory media) */
n = ((b_data + sz_blk - 1) & ~(sz_blk - 1)) - b_data; /* Next nearest erase block from current data base */ n = ((b_data + sz_blk - 1) & ~(sz_blk - 1)) - b_data; /* Next nearest erase block from current data base */
if (fmt == FS_FAT32) { /* FAT32: Move FAT base */
sz_rsv += n; b_fat += n;
} else { /* FAT: Expand FAT size */
if (n % n_fats) { /* Adjust fractional error if needed */ if (n % n_fats) { /* Adjust fractional error if needed */
n--; sz_rsv++; b_fat++; n--; sz_rsv++; b_fat++; /* FAT: Expand FAT size */
} }
sz_fat += n / n_fats; sz_fat += n / n_fats;
} }
@@ -6191,7 +6203,7 @@ FRESULT f_mkfs (
/* Create FAT VBR */ /* Create FAT VBR */
mem_set(buf, 0, ss); mem_set(buf, 0, ss);
/* 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); if (!(opt & FM_PRF2)) mem_cpy(buf + BS_JmpBoot, "\xEB\xFE\x90" "NYX1.8.0", 11);
else mem_cpy(buf + BS_JmpBoot, "\xEB\xE9\x90\x00\x00\x00\x00\x00\x00\x00\x00", 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] */
@@ -6248,21 +6260,10 @@ 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 */ /* Clear PRF2SAFE info so PrFILE2 can recreate it and upgrade it if old */
if (fmt == FS_FAT32 && opt & FM_PRF2) { if (fmt == FS_FAT32 && opt & FM_PRF2) {
mem_set(buf, 0, ss); mem_set(buf, 0, ss);
st_dword(buf + 0, 0x32465250); /* Magic PRF2 */ disk_write(pdrv, buf, b_vol + 3, 1); /* Write PRF2SAFE info (VBR + 3) */
st_dword(buf + 4, 0x45464153); /* Magic SAFE */
buf[16] = 0x64; /* Record type */
st_dword(buf + 32, 0x03); /* Unknown. SYSTEM: 0x3F00. USER: 0x03. Volatile. */
if (sz_vol < 0x1000000) {
st_dword(buf + 36, 21 + 1); /* 22 Entries. */
st_dword(buf + 508, 0x90BB2F39); /* Sector CRC32 */
} else {
st_dword(buf + 36, 21 + 2); /* 23 Entries. */
st_dword(buf + 508, 0x5EA8AFC8); /* Sector CRC32 */
}
disk_write(pdrv, buf, b_vol + 3, 1); /* Write PRF2SAFE info (VBR + 3) */
} }
/* Initialize FAT area */ /* Initialize FAT area */
@@ -6419,81 +6420,8 @@ 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 */
extern sdmmc_storage_t sd_storage;
FRESULT f_fdisk_mod (
BYTE pdrv, /* Physical drive number */
const DWORD* szt, /* Pointer to the size table for each partitions */
void* work
)
{
UINT i, n, sz_cyl, tot_cyl, e_cyl;
BYTE s_hd, e_hd, *p, *buf = (BYTE*)work;
DSTATUS stat;
DWORD sz_disk, p_sect, b_cyl, b_sect;
FRESULT res;
stat = disk_initialize(pdrv);
if (stat & STA_NOINIT) return FR_NOT_READY;
if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
sz_disk = sd_storage.csd.capacity;
if (!buf) return FR_NOT_ENOUGH_CORE;
/* Determine the CHS without any consideration of the drive geometry */
for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ;
if (n == 256) n--;
e_hd = (BYTE)(n - 1);
sz_cyl = 63 * n;
tot_cyl = sz_disk / sz_cyl;
/* Create partition table */
mem_set(buf, 0, 0x10000);
p = buf + MBR_Table; b_cyl = 0, b_sect = 0;
for (i = 0; i < 4; i++, p += SZ_PTE) {
p_sect = szt[i]; /* Number of sectors */
if (p_sect == 0)
continue;
if (i == 0) { /* Exclude first 16MiB of sd */
s_hd = 1;
b_sect += 32768; p_sect -= 32768;
}
else
s_hd = 0;
b_cyl = b_sect / sz_cyl;
e_cyl = ((b_sect + p_sect) / sz_cyl) - 1; /* End cylinder */
if (e_cyl >= tot_cyl)
LEAVE_MKFS(FR_INVALID_PARAMETER);
/* Set partition table */
p[1] = s_hd; /* Start head */
p[2] = (BYTE)(((b_cyl >> 2) & 0xC0) | 1); /* Start sector */
p[3] = (BYTE)b_cyl; /* Start cylinder */
p[4] = 0x07; /* System type (temporary setting) */
p[5] = e_hd; /* End head */
p[6] = (BYTE)(((e_cyl >> 2) & 0xC0) | 63); /* End sector */
p[7] = (BYTE)e_cyl; /* End cylinder */
st_dword(p + 8, b_sect); /* Start sector in LBA */
st_dword(p + 12, p_sect); /* Number of sectors */
/* Next partition */
for (u32 cursect = 0; cursect < 512; cursect++){
disk_write(pdrv, buf + 0x4000, b_sect + (64 * cursect), 64);
}
b_sect += p_sect;
}
st_word(p, 0xAA55); /* MBR signature (always at offset 510) */
/* Write it to the MBR */
res = (disk_write(pdrv, buf, 0, 1) == RES_OK && disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR;
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)

View File

@@ -292,7 +292,6 @@ 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_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 */

View File

@@ -116,8 +116,8 @@
#define LV_INDEV_POINT_MARKER 0 /*Mark the pressed points (required: USE_LV_REAL_DRAW = 1)*/ #define LV_INDEV_POINT_MARKER 0 /*Mark the pressed points (required: USE_LV_REAL_DRAW = 1)*/
#define LV_INDEV_DRAG_LIMIT 10 /*Drag threshold in pixels */ #define LV_INDEV_DRAG_LIMIT 10 /*Drag threshold in pixels */
#define LV_INDEV_DRAG_THROW 20 /*Drag throw slow-down in [%]. Greater value means faster slow-down */ #define LV_INDEV_DRAG_THROW 20 /*Drag throw slow-down in [%]. Greater value means faster slow-down */
#define LV_INDEV_LONG_PRESS_TIME 400 /*Long press time in milliseconds*/ #define LV_INDEV_LONG_PRESS_TIME 5000 /*Long press time in milliseconds*/
#define LV_INDEV_LONG_PRESS_REP_TIME 1000 //Fix keyb /*Repeated trigger period in long press [ms] */ #define LV_INDEV_LONG_PRESS_REP_TIME 1000 //Fix lv_kb /*Repeated trigger period in long press [ms] */
/*Color settings*/ /*Color settings*/
#define LV_COLOR_DEPTH 32 /*Color depth: 1/8/16/32*/ #define LV_COLOR_DEPTH 32 /*Color depth: 1/8/16/32*/

View File

@@ -316,7 +316,8 @@ static bool lv_task_exec(lv_task_t * lv_task_p)
lv_task_p->last_run = lv_tick_get(); lv_task_p->last_run = lv_tick_get();
task_deleted = false; task_deleted = false;
task_created = false; task_created = false;
lv_task_p->task(lv_task_p->param); if (lv_task_p->task)
lv_task_p->task(lv_task_p->param);
/*Delete if it was a one shot lv_task*/ /*Delete if it was a one shot lv_task*/
if(task_deleted == false) { /*The task might be deleted by itself as well*/ if(task_deleted == false) { /*The task might be deleted by itself as well*/

View File

@@ -36,7 +36,7 @@
#define COLOR_BG_DARKER LV_COLOR_HEX(theme_bg_color ? (theme_bg_color - 0x121212) : 0x0B0B0B) // 0x1B1B1B. #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_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 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_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_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. #define COLOR_LIGHT_BORDER LV_COLOR_HEX(theme_bg_color ? (theme_bg_color + 0x202020) : 0x3D3D3D) // 0x4D4D4D.

View File

@@ -41,6 +41,52 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <string.h> #include <string.h>
int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size)
{
int res = 0;
u8 tmp1[0x40] = {0};
u8 tmp2[0x40 + src_size];
u8 tmp3[0x60] = {0};
memset(tmp2, 0, 0x40 + src_size);
u8 *secret = (u8 *)tmp1;
u8 *ipad = (u8 *)tmp2;
u8 *opad = (u8 *)tmp3;
if (key_size > 0x40)
{
if (!se_calc_sha256_oneshot(secret, key, key_size))
goto out;
memset(secret + 0x20, 0, 0x20);
}
else
{
memcpy(secret, key, key_size);
memset(secret + key_size, 0, 0x40 - key_size);
}
u32 *secret32 = (u32 *)secret;
u32 *ipad32 = (u32 *)ipad;
u32 *opad32 = (u32 *)opad;
for (u32 i = 0; i < 0x10; i++)
{
ipad32[i] = secret32[i] ^ 0x36363636;
opad32[i] = secret32[i] ^ 0x5C5C5C5C;
}
memcpy(ipad + 0x40, src, src_size);
if (!se_calc_sha256_oneshot(dst, ipad, 0x40 + src_size))
goto out;
memcpy(opad + 0x40, dst, 0x20);
if (!se_calc_sha256_oneshot(dst, opad, 0x60))
goto out;
res = 1;
out:;
return res;
}
void save_hierarchical_integrity_verification_storage_control_area_query_size(ivfc_size_set_t *out, const ivfc_storage_control_input_param_t *input_param, int32_t layer_count, uint64_t data_size) { void save_hierarchical_integrity_verification_storage_control_area_query_size(ivfc_size_set_t *out, const ivfc_storage_control_input_param_t *input_param, int32_t layer_count, uint64_t data_size) {
int64_t level_size[IVFC_MAX_LEVEL + 1]; int64_t level_size[IVFC_MAX_LEVEL + 1];
int32_t level = layer_count - 1; int32_t level = layer_count - 1;

1528
bdk/mem/emc_t210.h Normal file

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-2024 CTCaer * Copyright (c) 2018-2025 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,56 +17,88 @@
#include <memory_map.h> #include <memory_map.h>
#include <mem/mc.h> #include <mem/mc.h>
#include <soc/bpmp.h>
#include <soc/timer.h> #include <soc/timer.h>
#include <soc/t210.h> #include <soc/t210.h>
#include <soc/clock.h> #include <soc/clock.h>
void mc_config_tzdram_carveout(u32 bom, u32 size1mb, bool lock) #define HOS_WPR1_BASE 0x80020000
{
MC(MC_SEC_CARVEOUT_BOM) = bom;
MC(MC_SEC_CARVEOUT_SIZE_MB) = size1mb;
if (lock)
MC(MC_SEC_CARVEOUT_REG_CTRL) = 1;
}
void mc_config_carveout() void mc_config_carveout_hos()
{ {
// Enable ACR GSR3. // Enable ACR GSR3 and flush data to ram.
*(vu32 *)0x8005FFFC = 0xC0EDBBCC; *(u32 *)(HOS_WPR1_BASE + SZ_256K - sizeof(u32)) = ACR_GSC3_ENABLE_MAGIC;
MC(MC_VIDEO_PROTECT_GPU_OVERRIDE_0) = 1; bpmp_mmu_maintenance(BPMP_MMU_MAINT_INVALID_WAY, false);
// Set VPR CYA TRUSTED DEFAULT.
MC(MC_VIDEO_PROTECT_GPU_OVERRIDE_0) = VPR_OVR0_CYA_TRUST_DEFAULT;
MC(MC_VIDEO_PROTECT_GPU_OVERRIDE_1) = 0; MC(MC_VIDEO_PROTECT_GPU_OVERRIDE_1) = 0;
MC(MC_VIDEO_PROTECT_BOM) = 0;
// Disable VPR carveout.
MC(MC_VIDEO_PROTECT_BOM) = 0;
MC(MC_VIDEO_PROTECT_SIZE_MB) = 0;
MC(MC_VIDEO_PROTECT_REG_CTRL) = VPR_CTRL_LOCKED; MC(MC_VIDEO_PROTECT_REG_CTRL) = VPR_CTRL_LOCKED;
// Configure TZDRAM carveout @ 0x90000000, 1MB. // Disable TZDRAM carveout.
//mc_config_tzdram_carveout(0x90000000, 1, false); MC(MC_SEC_CARVEOUT_BOM) = 0;
mc_config_tzdram_carveout(0, 0, true); MC(MC_SEC_CARVEOUT_SIZE_MB) = 0;
MC(MC_SEC_CARVEOUT_REG_CTRL) = BIT(0);
MC(MC_MTS_CARVEOUT_BOM) = 0; // Disable CPU FW carveout.
MC(MC_MTS_CARVEOUT_REG_CTRL) = 1; MC(MC_MTS_CARVEOUT_BOM) = 0;
MC(MC_MTS_CARVEOUT_SIZE_MB) = 0;
MC(MC_MTS_CARVEOUT_REG_CTRL) = BIT(0);
// Disable GEN1 carveout.
MC(MC_SECURITY_CARVEOUT1_SIZE_128KB) = 0; MC(MC_SECURITY_CARVEOUT1_SIZE_128KB) = 0;
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2) = 0;
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3) = 0;
MC(MC_SECURITY_CARVEOUT1_CFG0) = SEC_CARVEOUT_CFG_LOCKED | MC(MC_SECURITY_CARVEOUT1_CFG0) = SEC_CARVEOUT_CFG_LOCKED |
SEC_CARVEOUT_CFG_UNTRANSLATED_ONLY | SEC_CARVEOUT_CFG_UNTRANSLATED_ONLY |
SEC_CARVEOUT_CFG_APERTURE_ID(0) | SEC_CARVEOUT_CFG_APERTURE_ID(0) |
SEC_CARVEOUT_CFG_FORCE_APERTURE_ID_MATCH; SEC_CARVEOUT_CFG_FORCE_APERTURE_ID_MATCH;
MC(MC_SECURITY_CARVEOUT2_BOM) = 0x80020000; // Enable GEN2 carveout as WPR1.
MC(MC_SECURITY_CARVEOUT2_BOM) = HOS_WPR1_BASE;
MC(MC_SECURITY_CARVEOUT2_SIZE_128KB) = SZ_256K / SZ_128K;
MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2) = SEC_CARVEOUT_CA2_R_GPU | SEC_CARVEOUT_CA2_W_GPU | SEC_CARVEOUT_CA2_R_TSEC; MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2) = SEC_CARVEOUT_CA2_R_GPU | SEC_CARVEOUT_CA2_W_GPU | SEC_CARVEOUT_CA2_R_TSEC;
MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4) = SEC_CARVEOUT_CA4_R_GPU2 | SEC_CARVEOUT_CA4_W_GPU2;
MC(MC_SECURITY_CARVEOUT2_CFG0) = SEC_CARVEOUT_CFG_LOCKED |
SEC_CARVEOUT_CFG_UNTRANSLATED_ONLY |
SEC_CARVEOUT_CFG_RD_NS |
SEC_CARVEOUT_CFG_RD_SEC |
SEC_CARVEOUT_CFG_RD_FALCON_LS |
SEC_CARVEOUT_CFG_RD_FALCON_HS |
SEC_CARVEOUT_CFG_WR_FALCON_LS |
SEC_CARVEOUT_CFG_WR_FALCON_HS |
SEC_CARVEOUT_CFG_APERTURE_ID(2) |
SEC_CARVEOUT_CFG_SEND_CFG_TO_GPU |
SEC_CARVEOUT_CFG_FORCE_APERTURE_ID_MATCH;
// Prepare GEN3 carveout as WPR2.
MC(MC_SECURITY_CARVEOUT3_SIZE_128KB) = 0;
MC(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2) = SEC_CARVEOUT_CA2_R_GPU | SEC_CARVEOUT_CA2_W_GPU;
MC(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4) = SEC_CARVEOUT_CA4_R_GPU2 | SEC_CARVEOUT_CA4_W_GPU2;
MC(MC_SECURITY_CARVEOUT3_CFG0) = SEC_CARVEOUT_CFG_LOCKED |
SEC_CARVEOUT_CFG_UNTRANSLATED_ONLY |
SEC_CARVEOUT_CFG_RD_NS |
SEC_CARVEOUT_CFG_RD_SEC |
SEC_CARVEOUT_CFG_RD_FALCON_LS |
SEC_CARVEOUT_CFG_RD_FALCON_HS |
SEC_CARVEOUT_CFG_WR_FALCON_LS |
SEC_CARVEOUT_CFG_WR_FALCON_HS |
SEC_CARVEOUT_CFG_APERTURE_ID(3) |
SEC_CARVEOUT_CFG_SEND_CFG_TO_GPU |
SEC_CARVEOUT_CFG_FORCE_APERTURE_ID_MATCH;
// Disable GEN4 carveout.
MC(MC_SECURITY_CARVEOUT4_SIZE_128KB) = 0; MC(MC_SECURITY_CARVEOUT4_SIZE_128KB) = 0;
MC(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS2) = 0;
MC(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS4) = 0;
MC(MC_SECURITY_CARVEOUT4_CFG0) = SEC_CARVEOUT_CFG_TZ_SECURE | MC(MC_SECURITY_CARVEOUT4_CFG0) = SEC_CARVEOUT_CFG_TZ_SECURE |
SEC_CARVEOUT_CFG_LOCKED | SEC_CARVEOUT_CFG_LOCKED |
SEC_CARVEOUT_CFG_UNTRANSLATED_ONLY | SEC_CARVEOUT_CFG_UNTRANSLATED_ONLY |
SEC_CARVEOUT_CFG_RD_NS | SEC_CARVEOUT_CFG_RD_NS |
SEC_CARVEOUT_CFG_WR_NS; SEC_CARVEOUT_CFG_WR_NS;
// Disable GEN5 carveout.
MC(MC_SECURITY_CARVEOUT5_SIZE_128KB) = 0; MC(MC_SECURITY_CARVEOUT5_SIZE_128KB) = 0;
MC(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS2) = 0;
MC(MC_SECURITY_CARVEOUT5_CFG0) = SEC_CARVEOUT_CFG_TZ_SECURE | MC(MC_SECURITY_CARVEOUT5_CFG0) = SEC_CARVEOUT_CFG_TZ_SECURE |
SEC_CARVEOUT_CFG_LOCKED | SEC_CARVEOUT_CFG_LOCKED |
SEC_CARVEOUT_CFG_UNTRANSLATED_ONLY | SEC_CARVEOUT_CFG_UNTRANSLATED_ONLY |
@@ -74,9 +106,10 @@ void mc_config_carveout()
SEC_CARVEOUT_CFG_WR_NS; SEC_CARVEOUT_CFG_WR_NS;
} }
// SDMMC, TSEC, XUSB and probably more need it to access < DRAM_START.
void mc_enable_ahb_redirect() void mc_enable_ahb_redirect()
{ {
// Enable ARC_CLK_OVR_ON. // Bypass ARC clock gating.
CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) |= BIT(19); CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) |= BIT(19);
//MC(MC_IRAM_REG_CTRL) &= ~BIT(0); //MC(MC_IRAM_REG_CTRL) &= ~BIT(0);
MC(MC_IRAM_BOM) = IRAM_BASE; MC(MC_IRAM_BOM) = IRAM_BASE;
@@ -89,7 +122,7 @@ void mc_disable_ahb_redirect()
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) |= BIT(0); //MC(MC_IRAM_REG_CTRL) |= BIT(0);
// Disable ARC_CLK_OVR_ON. // Set ARC clock gating to automatic.
CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) &= ~BIT(19); CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) &= ~BIT(19);
} }
@@ -109,6 +142,7 @@ 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) | (2 << 29u); CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) & 0x1FFFFFFF) | (2 << 29u);
// Enable and clear reset for memory clocks. // Enable and clear reset for memory clocks.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_EMC) | BIT(CLK_H_MEM); CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_EMC) | BIT(CLK_H_MEM);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = BIT(CLK_X_EMC_DLL); CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = BIT(CLK_X_EMC_DLL);

View File

@@ -21,8 +21,7 @@
#include <mem/mc_t210.h> #include <mem/mc_t210.h>
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_hos();
void mc_config_carveout_finalize();
void mc_enable_ahb_redirect(); void mc_enable_ahb_redirect();
void mc_disable_ahb_redirect(); void mc_disable_ahb_redirect();
bool mc_client_has_access(void *address); bool mc_client_has_access(void *address);

File diff suppressed because it is too large Load Diff

View File

@@ -20,7 +20,7 @@
#include "minerva.h" #include "minerva.h"
#include <ianos/ianos.h> #include <ianos/ianos.h>
#include <mem/emc.h> #include <mem/emc_t210.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>
@@ -147,7 +147,6 @@ void minerva_change_freq(minerva_freq_t freq)
void minerva_sdmmc_la_program(void *table, bool t210b01) void minerva_sdmmc_la_program(void *table, bool t210b01)
{ {
u32 freq = *(u32 *)(table + TABLE_FREQ_KHZ_OFFSET); u32 freq = *(u32 *)(table + TABLE_FREQ_KHZ_OFFSET);
u32 *la_scale_regs = (u32 *)(table + (t210b01 ? TABLE_LA_REGS_T210B01_OFFSET : TABLE_LA_REGS_T210_OFFSET)); u32 *la_scale_regs = (u32 *)(table + (t210b01 ? TABLE_LA_REGS_T210B01_OFFSET : TABLE_LA_REGS_T210_OFFSET));
@@ -183,7 +182,7 @@ void minerva_prep_boot_freq()
minerva_change_freq(FREQ_800); minerva_change_freq(FREQ_800);
} }
void minerva_prep_boot_l4t(u32 oc_freq, u32 opt_custom) void minerva_prep_boot_l4t(u32 oc_freq, u32 opt_custom, bool prg_sdmmc_la)
{ {
if (!minerva_cfg) if (!minerva_cfg)
return; return;
@@ -191,8 +190,9 @@ void minerva_prep_boot_l4t(u32 oc_freq, u32 opt_custom)
mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg; mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
// Program SDMMC LA regs. // Program SDMMC LA regs.
for (u32 i = 0; i < mtc_cfg->table_entries; i++) if (prg_sdmmc_la)
minerva_sdmmc_la_program(&mtc_cfg->mtc_table[i], false); for (u32 i = 0; i < mtc_cfg->table_entries; i++)
minerva_sdmmc_la_program(&mtc_cfg->mtc_table[i], false);
// Add OC frequency. // Add OC frequency.
if (oc_freq && mtc_cfg->mtc_table[mtc_cfg->table_entries - 1].rate_khz == FREQ_1600) if (oc_freq && mtc_cfg->mtc_table[mtc_cfg->table_entries - 1].rate_khz == FREQ_1600)

View File

@@ -64,7 +64,7 @@ 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_sdmmc_la_program(void *table, bool t210b01);
void minerva_prep_boot_freq(); void minerva_prep_boot_freq();
void minerva_prep_boot_l4t(u32 oc_freq, u32 opt_custom); void minerva_prep_boot_l4t(u32 oc_freq, u32 opt_custom, bool prg_sdmmc_la);
void minerva_periodic_training(); void minerva_periodic_training();
emc_table_t *minerva_get_mtc_table(); emc_table_t *minerva_get_mtc_table();
int minerva_get_mtc_table_entries(); int minerva_get_mtc_table_entries();

View File

@@ -19,7 +19,7 @@
#include <string.h> #include <string.h>
#include <mem/mc.h> #include <mem/mc.h>
#include <mem/emc.h> #include <mem/emc_t210.h>
#include <mem/sdram.h> #include <mem/sdram.h>
#include <mem/sdram_param_t210.h> #include <mem/sdram_param_t210.h>
#include <mem/sdram_param_t210b01.h> #include <mem/sdram_param_t210b01.h>
@@ -260,7 +260,7 @@ static void _sdram_config_t210(const sdram_params_t210_t *params)
u32 pllm_div = (params->pllm_feedback_divider << 8) | params->pllm_input_divider | ((params->pllm_post_divider & 0xFFFF) << 20); u32 pllm_div = (params->pllm_feedback_divider << 8) | params->pllm_input_divider | ((params->pllm_post_divider & 0xFFFF) << 20);
CLOCK(CLK_RST_CONTROLLER_PLLM_BASE) = pllm_div; CLOCK(CLK_RST_CONTROLLER_PLLM_BASE) = pllm_div;
CLOCK(CLK_RST_CONTROLLER_PLLM_BASE) = pllm_div | PLLCX_BASE_ENABLE; CLOCK(CLK_RST_CONTROLLER_PLLM_BASE) = pllm_div | PLL_BASE_ENABLE;
u32 wait_end = get_tmr_us() + 300; u32 wait_end = get_tmr_us() + 300;
while (!(CLOCK(CLK_RST_CONTROLLER_PLLM_BASE) & BIT(27))) while (!(CLOCK(CLK_RST_CONTROLLER_PLLM_BASE) & BIT(27)))
@@ -1012,26 +1012,26 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params)
EMC(EMC_PMACRO_TX_SEL_CLK_SRC_5) = params->emc_pmacro_tx_sel_clk_src5; EMC(EMC_PMACRO_TX_SEL_CLK_SRC_5) = params->emc_pmacro_tx_sel_clk_src5;
// Program per bit pad macros. // Program per bit pad macros.
EMC(EMC_PMACRO_PERBIT_FGCG_CTRL_0) = params->emc_pmacro_perbit_fgcg_ctrl0; EMC(EMC_PMACRO_PERBIT_FGCG_CTRL_0_B01) = params->emc_pmacro_perbit_fgcg_ctrl0;
EMC(EMC_PMACRO_PERBIT_FGCG_CTRL_1) = params->emc_pmacro_perbit_fgcg_ctrl1; EMC(EMC_PMACRO_PERBIT_FGCG_CTRL_1_B01) = params->emc_pmacro_perbit_fgcg_ctrl1;
EMC(EMC_PMACRO_PERBIT_FGCG_CTRL_2) = params->emc_pmacro_perbit_fgcg_ctrl2; EMC(EMC_PMACRO_PERBIT_FGCG_CTRL_2_B01) = params->emc_pmacro_perbit_fgcg_ctrl2;
EMC(EMC_PMACRO_PERBIT_FGCG_CTRL_3) = params->emc_pmacro_perbit_fgcg_ctrl3; EMC(EMC_PMACRO_PERBIT_FGCG_CTRL_3_B01) = params->emc_pmacro_perbit_fgcg_ctrl3;
EMC(EMC_PMACRO_PERBIT_FGCG_CTRL_4) = params->emc_pmacro_perbit_fgcg_ctrl4; EMC(EMC_PMACRO_PERBIT_FGCG_CTRL_4_B01) = params->emc_pmacro_perbit_fgcg_ctrl4;
EMC(EMC_PMACRO_PERBIT_FGCG_CTRL_5) = params->emc_pmacro_perbit_fgcg_ctrl5; EMC(EMC_PMACRO_PERBIT_FGCG_CTRL_5_B01) = params->emc_pmacro_perbit_fgcg_ctrl5;
EMC(EMC_PMACRO_PERBIT_RFU_CTRL_0) = params->emc_pmacro_perbit_rfu_ctrl0; EMC(EMC_PMACRO_PERBIT_RFU_CTRL_0_B01) = params->emc_pmacro_perbit_rfu_ctrl0;
EMC(EMC_PMACRO_PERBIT_RFU_CTRL_1) = params->emc_pmacro_perbit_rfu_ctrl1; EMC(EMC_PMACRO_PERBIT_RFU_CTRL_1_B01) = params->emc_pmacro_perbit_rfu_ctrl1;
EMC(EMC_PMACRO_PERBIT_RFU_CTRL_2) = params->emc_pmacro_perbit_rfu_ctrl2; EMC(EMC_PMACRO_PERBIT_RFU_CTRL_2_B01) = params->emc_pmacro_perbit_rfu_ctrl2;
EMC(EMC_PMACRO_PERBIT_RFU_CTRL_3) = params->emc_pmacro_perbit_rfu_ctrl3; EMC(EMC_PMACRO_PERBIT_RFU_CTRL_3_B01) = params->emc_pmacro_perbit_rfu_ctrl3;
EMC(EMC_PMACRO_PERBIT_RFU_CTRL_4) = params->emc_pmacro_perbit_rfu_ctrl4; EMC(EMC_PMACRO_PERBIT_RFU_CTRL_4_B01) = params->emc_pmacro_perbit_rfu_ctrl4;
EMC(EMC_PMACRO_PERBIT_RFU_CTRL_5) = params->emc_pmacro_perbit_rfu_ctrl5; EMC(EMC_PMACRO_PERBIT_RFU_CTRL_5_B01) = params->emc_pmacro_perbit_rfu_ctrl5;
EMC(EMC_PMACRO_PERBIT_RFU1_CTRL_0) = params->emc_pmacro_perbit_rfu1_ctrl0; EMC(EMC_PMACRO_PERBIT_RFU1_CTRL_0_B01) = params->emc_pmacro_perbit_rfu1_ctrl0;
EMC(EMC_PMACRO_PERBIT_RFU1_CTRL_1) = params->emc_pmacro_perbit_rfu1_ctrl1; EMC(EMC_PMACRO_PERBIT_RFU1_CTRL_1_B01) = params->emc_pmacro_perbit_rfu1_ctrl1;
EMC(EMC_PMACRO_PERBIT_RFU1_CTRL_2) = params->emc_pmacro_perbit_rfu1_ctrl2; EMC(EMC_PMACRO_PERBIT_RFU1_CTRL_2_B01) = params->emc_pmacro_perbit_rfu1_ctrl2;
EMC(EMC_PMACRO_PERBIT_RFU1_CTRL_3) = params->emc_pmacro_perbit_rfu1_ctrl3; EMC(EMC_PMACRO_PERBIT_RFU1_CTRL_3_B01) = params->emc_pmacro_perbit_rfu1_ctrl3;
EMC(EMC_PMACRO_PERBIT_RFU1_CTRL_4) = params->emc_pmacro_perbit_rfu1_ctrl4; EMC(EMC_PMACRO_PERBIT_RFU1_CTRL_4_B01) = params->emc_pmacro_perbit_rfu1_ctrl4;
EMC(EMC_PMACRO_PERBIT_RFU1_CTRL_5) = params->emc_pmacro_perbit_rfu1_ctrl5; EMC(EMC_PMACRO_PERBIT_RFU1_CTRL_5_B01) = params->emc_pmacro_perbit_rfu1_ctrl5;
EMC(EMC_PMACRO_DATA_PI_CTRL) = params->emc_pmacro_data_pi_ctrl; EMC(EMC_PMACRO_DATA_PI_CTRL_B01) = params->emc_pmacro_data_pi_ctrl;
EMC(EMC_PMACRO_CMD_PI_CTRL) = params->emc_pmacro_cmd_pi_ctrl; EMC(EMC_PMACRO_CMD_PI_CTRL_B01) = params->emc_pmacro_cmd_pi_ctrl;
EMC(EMC_PMACRO_DDLL_BYPASS) = params->emc_pmacro_ddll_bypass; EMC(EMC_PMACRO_DDLL_BYPASS) = params->emc_pmacro_ddll_bypass;
EMC(EMC_PMACRO_DDLL_PWRD_0) = params->emc_pmacro_ddll_pwrd0; EMC(EMC_PMACRO_DDLL_PWRD_0) = params->emc_pmacro_ddll_pwrd0;
@@ -1220,7 +1220,7 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params)
if (params->emc_bct_spare8) if (params->emc_bct_spare8)
*(vu32 *)params->emc_bct_spare8 = params->emc_bct_spare9; *(vu32 *)params->emc_bct_spare8 = params->emc_bct_spare9;
EMC(EMC_AUTO_CAL_CONFIG9) = params->emc_auto_cal_config9; EMC(EMC_AUTO_CAL_CONFIG9_B01) = params->emc_auto_cal_config9;
// Program EMC timing configuration. // Program EMC timing configuration.
EMC(EMC_CFG_2) = params->emc_cfg2; EMC(EMC_CFG_2) = params->emc_cfg2;
@@ -1240,11 +1240,11 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params)
EMC(EMC_RAS) = params->emc_ras; EMC(EMC_RAS) = params->emc_ras;
EMC(EMC_RP) = params->emc_rp; EMC(EMC_RP) = params->emc_rp;
EMC(EMC_TPPD) = params->emc_tppd; EMC(EMC_TPPD) = params->emc_tppd;
EMC(EMC_CTT) = params->emc_trtm; EMC(EMC_TRTM_B01) = params->emc_trtm;
EMC(EMC_FBIO_TWTM) = params->emc_twtm; EMC(EMC_TWTM_B01) = params->emc_twtm;
EMC(EMC_FBIO_TRATM) = params->emc_tratm; EMC(EMC_TRATM_B01) = params->emc_tratm;
EMC(EMC_FBIO_TWATM) = params->emc_twatm; EMC(EMC_TWATM_B01) = params->emc_twatm;
EMC(EMC_FBIO_TR2REF) = params->emc_tr2ref; EMC(EMC_TR2REF_B01) = params->emc_tr2ref;
EMC(EMC_R2R) = params->emc_r2r; EMC(EMC_R2R) = params->emc_r2r;
EMC(EMC_W2W) = params->emc_w2w; EMC(EMC_W2W) = params->emc_w2w;
EMC(EMC_R2W) = params->emc_r2w; EMC(EMC_R2W) = params->emc_r2w;
@@ -1321,7 +1321,7 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params)
EMC(EMC_PMC_SCRATCH3) = params->emc_pmc_scratch3; EMC(EMC_PMC_SCRATCH3) = params->emc_pmc_scratch3;
EMC(EMC_ACPD_CONTROL) = params->emc_acpd_control; EMC(EMC_ACPD_CONTROL) = params->emc_acpd_control;
EMC(EMC_TXDSRVTTGEN) = params->emc_txdsrvttgen; EMC(EMC_TXDSRVTTGEN) = params->emc_txdsrvttgen;
EMC(EMC_PMACRO_DSR_VTTGEN_CTRL0) = params->emc_pmacro_dsr_vttgen_ctrl0; EMC(EMC_PMACRO_DSR_VTTGEN_CTRL_0_B01) = params->emc_pmacro_dsr_vttgen_ctrl0;
// Set pipe bypass enable bits before sending any DRAM commands. // Set pipe bypass enable bits before sending any DRAM commands.
EMC(EMC_CFG) = (params->emc_cfg & 0xE) | 0x3C00000; EMC(EMC_CFG) = (params->emc_cfg & 0xE) | 0x3C00000;
@@ -1465,7 +1465,7 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params)
EMC(EMC_FDPD_CTRL_CMD_NO_RAMP) = params->emc_fdpd_ctrl_cmd_no_ramp; EMC(EMC_FDPD_CTRL_CMD_NO_RAMP) = params->emc_fdpd_ctrl_cmd_no_ramp;
// Set untranslated region requirements. // Set untranslated region requirements.
MC(MC_UNTRANSLATED_REGION_CHECK) = params->mc_untranslated_region_check; MC(MC_UNTRANSLATED_REGION_CHECK_B01) = params->mc_untranslated_region_check;
// Lock carveouts per BCT cfg. // Lock carveouts per BCT cfg.
MC(MC_VIDEO_PROTECT_REG_CTRL) = params->mc_video_protect_write_access; MC(MC_VIDEO_PROTECT_REG_CTRL) = params->mc_video_protect_write_access;

View File

@@ -18,7 +18,7 @@
#ifndef _SDRAM_H_ #ifndef _SDRAM_H_
#define _SDRAM_H_ #define _SDRAM_H_
#include <mem/emc.h> #include <mem/emc_t210.h>
/* /*
* Tegra X1/X1+ EMC/DRAM Bandwidth Chart: * Tegra X1/X1+ EMC/DRAM Bandwidth Chart:

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2020-2024 CTCaer * Copyright (c) 2020-2025 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,
@@ -538,18 +538,32 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = {
.mc_clken_override = 0x00008000, .mc_clken_override = 0x00008000,
.mc_stat_control = 0x00000000, .mc_stat_control = 0x00000000,
/* VPR carveout configuration */
.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. Plus TSEC, NVENC. // Disable access:
.mc_video_protect_vpr_override = 0xE4FACB43, // Default: 0xE4BAC343. New: 0xE4FACB43. + TSEC, NVENC. // AFI (PCIE), BPMP, HC (HOST1x), ISP2, CCPLEX, PPCS (AHB), SATA, VI, XUSB_HOST, XUSB_DEV, ADSP, PPCS1 (AHB), DC1 (WinT), SDMMC1/2/3. Plus TSEC, NVENC.
// SDMMC4A, ISP2B, PPCS2 (AHB), APE, SE, HC1, SE1, AXIAP, ETR. Plus TSECB, TSEC1, TSECB1. // Enable access:
.mc_video_protect_vpr_override1 = 0x0000FED3, // Default: 0x00001ED3. New: 0x0000FED3. + TSECB, TSEC1, TSECB1. // DC, DCB, HDA, VIC.
.mc_video_protect_vpr_override = 0xE4FACB43, // Stock/Reset: 0xE4BAC343. HOS new: 0xE4FACB43. + TSEC, NVENC.
// Disable access:
// SDMMC4, ISP2B, PPCS2 (AHB), APE, SE, HC1, SE1, AXIAP, ETR. Plus TSECB, TSEC1, TSECB1.
// Enable access:
// GPU, GPUB, NVDEC, NVJPG, NVDEC1.
.mc_video_protect_vpr_override1 = 0x0000FED3, // Stock/Reset: 0x00001ED3. HOS new: 0x0000FED3. + TSECB, TSEC1, TSECB1.
.mc_video_protect_gpu_override0 = 0x2A800000, // Default: 0x00000000. Forced to 1 by HOS Secmon. // VPR CYA. L4T override (set PD, SCC, SKED, L1 as UNTRUSTED).
.mc_video_protect_gpu_override1 = 0x00000002, // Default: 0x00000000. Forced to 0 by HOS Secmon. .mc_video_protect_gpu_override0 = VPR_OVR0_CYA_TRUST_GCC(VPR_TRUST_GRAPHICS) |
VPR_OVR0_CYA_TRUST_RASTER(VPR_TRUST_GRAPHICS) |
VPR_OVR0_CYA_TRUST_PE(VPR_TRUST_GRAPHICS) |
VPR_OVR0_CYA_TRUST_TEX(VPR_TRUST_GRAPHICS) |
VPR_OVR0_CYA_TRUST_OVERRIDE, // Stock: 0. HOS: VPR_OVR0_CYA_TRUST_DEFAULT.
.mc_video_protect_gpu_override1 = VPR_OVR1_CYA_TRUST_PROP(VPR_TRUST_GRAPHICS), // Stock: 0. HOS: 0.
/* TZDRAM carveout configuration */
.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,
@@ -642,6 +656,7 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = {
/* Specifies data for patched boot rom write */ /* Specifies data for patched boot rom write */
.boot_rom_patch_data = 0x00000000, .boot_rom_patch_data = 0x00000000,
/* CPU FW carveout configuration */
.mc_mts_carveout_bom = 0xFFF00000, .mc_mts_carveout_bom = 0xFFF00000,
.mc_mts_carveout_adr_hi = 0x00000000, .mc_mts_carveout_adr_hi = 0x00000000,
.mc_mts_carveout_size_mb = 0x00000000, .mc_mts_carveout_size_mb = 0x00000000,

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2024 CTCaer * Copyright (c) 2020-2025 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,
@@ -595,14 +595,26 @@ static const sdram_params_t210b01_t _dram_cfg_08_10_12_14_samsung_hynix_4gb = {
.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. Plus TSEC, NVENC. // Disable access:
.mc_video_protect_vpr_override = 0xE4FACB43, // Default: 0xE4BAC343. // AFI (PCIE), BPMP, HC (HOST1x), ISP2, CCPLEX, PPCS (AHB), SATA, VI, XUSB_HOST, XUSB_DEV, ADSP, PPCS1 (AHB), DC1 (WinT), SDMMC1/2/3. Plus TSEC, NVENC.
// SDMMC4A, ISP2B, PPCS2 (AHB), APE, SE, HC1, SE1, AXIAP, ETR. Plus SE2, SE2B and TSECB, TSEC1, TSECB1. // Enable access:
.mc_video_protect_vpr_override1 = 0x0600FED3, // Default: 0x06001ED3. // DC, DCB, HDA, VIC.
.mc_video_protect_vpr_override = 0xE4FACB43, // Stock/Reset: 0xE4BAC343. HOS new: 0xE4FACB43. + TSEC, NVENC.
// Disable access:
// SDMMC4, ISP2B, PPCS2 (AHB), APE, SE, HC1, SE1, AXIAP, ETR, SE2, SE2B. Plus TSECB, TSEC1, TSECB1.
// Enable access:
// GPU, GPUB, NVDEC, NVJPG, NVDEC1.
.mc_video_protect_vpr_override1 = 0x0600FED3, // Reset: 0x06001ED3. HOS new: 0x0600FED3. + TSECB, TSEC1, TSECB1.
.mc_video_protect_gpu_override0 = 0x2A800000, // Default: 0x00000000. Forced to 1 by HOS Secmon. // VPR CYA. L4T override (set PD, SCC, SKED, L1 as UNTRUSTED).
.mc_video_protect_gpu_override1 = 0x00000002, // Default: 0x00000000. Forced to 0 by HOS Secmon. .mc_video_protect_gpu_override0 = VPR_OVR0_CYA_TRUST_GCC(VPR_TRUST_GRAPHICS) |
VPR_OVR0_CYA_TRUST_RASTER(VPR_TRUST_GRAPHICS) |
VPR_OVR0_CYA_TRUST_PE(VPR_TRUST_GRAPHICS) |
VPR_OVR0_CYA_TRUST_TEX(VPR_TRUST_GRAPHICS) |
VPR_OVR0_CYA_TRUST_OVERRIDE, // Stock: 0. HOS: VPR_OVR0_CYA_TRUST_DEFAULT.
.mc_video_protect_gpu_override1 = VPR_OVR1_CYA_TRUST_PROP(VPR_TRUST_GRAPHICS), // Stock: 0. HOS: 0.
/* TZDRAM carveout configuration */
.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,

View File

@@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018 balika011 * Copyright (c) 2018 balika011
* Copyright (c) 2018-2024 CTCaer * Copyright (c) 2018-2025 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,
@@ -54,10 +54,12 @@
#define SMMU_PDN_TO_ADDR(pdn) ((pdn) << SMMU_PDN_SHIFT) #define SMMU_PDN_TO_ADDR(pdn) ((pdn) << SMMU_PDN_SHIFT)
#define SMMU_PTB(page, attr) (((attr) << 29u) | ((page) >> SMMU_PAGE_SHIFT)) #define SMMU_PTB(page, attr) (((attr) << 29u) | ((page) >> SMMU_PAGE_SHIFT))
static void *smmu_heap = (void *)SMMU_HEAP_ADDR; #define SMMU_PAYLOAD_EN_SHIFT 4
#define SMMU_PAYLOAD_EN_SET 0x20
#define SMMU_PAYLOAD_EN_UNSET 0x00
// Enabling SMMU requires a TZ (EL3) secure write. MC(MC_SMMU_CONFIG) = 1; // Enabling SMMU requires a TZ (EL3) secure write. MC(MC_SMMU_CONFIG) = 1;
static const u8 smmu_enable_payload[] = { static u8 smmu_enable_payload[] = {
0xC1, 0x00, 0x00, 0x18, // 0x00: LDR W1, =0x70019010 0xC1, 0x00, 0x00, 0x18, // 0x00: LDR W1, =0x70019010
0x20, 0x00, 0x80, 0xD2, // 0x04: MOV X0, #0x1 0x20, 0x00, 0x80, 0xD2, // 0x04: MOV X0, #0x1
0x20, 0x00, 0x00, 0xB9, // 0x08: STR W0, [X1] 0x20, 0x00, 0x00, 0xB9, // 0x08: STR W0, [X1]
@@ -67,6 +69,9 @@ static const u8 smmu_enable_payload[] = {
0x10, 0x90, 0x01, 0x70, // 0x18: MC_SMMU_CONFIG 0x10, 0x90, 0x01, 0x70, // 0x18: MC_SMMU_CONFIG
}; };
static void *smmu_heap = (void *)SMMU_HEAP_ADDR;
static bool smmu_enabled = false;
void *smmu_page_zalloc(u32 num) void *smmu_page_zalloc(u32 num)
{ {
void *page = smmu_heap; void *page = smmu_heap;
@@ -95,7 +100,6 @@ static void _smmu_flush_regs()
void smmu_flush_all() void smmu_flush_all()
{ {
// Flush the entire page table cache. // Flush the entire page table cache.
MC(MC_SMMU_PTC_FLUSH) = 0; MC(MC_SMMU_PTC_FLUSH) = 0;
_smmu_flush_regs(); _smmu_flush_regs();
@@ -117,9 +121,7 @@ void smmu_init()
void smmu_enable() void smmu_enable()
{ {
static bool enabled = false; if (smmu_enabled)
if (enabled)
return; return;
// Launch payload on CCPLEX in order to set SMMU enable bit. // Launch payload on CCPLEX in order to set SMMU enable bit.
@@ -129,7 +131,31 @@ void smmu_enable()
smmu_flush_all(); smmu_flush_all();
enabled = true; smmu_enabled = true;
}
void smmu_disable()
{
if (!smmu_enabled)
return;
// Set payload to disable SMMU.
smmu_enable_payload[SMMU_PAYLOAD_EN_SHIFT] = SMMU_PAYLOAD_EN_UNSET;
smmu_flush_all();
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
// Launch payload on CCPLEX in order to set SMMU enable bit.
ccplex_boot_cpu0((u32)smmu_enable_payload, false);
msleep(100);
ccplex_powergate_cpu0();
smmu_flush_all();
// Restore payload to SMMU enable.
smmu_enable_payload[SMMU_PAYLOAD_EN_SHIFT] = SMMU_PAYLOAD_EN_SET;
smmu_enabled = false;
} }
void smmu_reset_heap() void smmu_reset_heap()

View File

@@ -63,6 +63,7 @@ void *smmu_page_zalloc(u32 num);
void smmu_flush_all(); void smmu_flush_all();
void smmu_init(); void smmu_init();
void smmu_enable(); void smmu_enable();
void smmu_disable();
void smmu_reset_heap(); void smmu_reset_heap();
void *smmu_init_domain(u32 dev_base, u32 asid); void *smmu_init_domain(u32 dev_base, u32 asid);
void smmu_deinit_domain(u32 dev_base, u32 asid); void smmu_deinit_domain(u32 dev_base, u32 asid);

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019-2021 CTCaer * Copyright (c) 2019-2025 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,
@@ -29,7 +29,6 @@
#define SECMON_MIN_START 0x4002B000 // Minimum reserved address for secmon. #define SECMON_MIN_START 0x4002B000 // Minimum reserved address for secmon.
#define SDRAM_PARAMS_ADDR 0x40030000 // SDRAM extraction buffer during sdram init. #define SDRAM_PARAMS_ADDR 0x40030000 // SDRAM extraction buffer during sdram init.
#define CBFS_DRAM_EN_ADDR 0x4003e000 // u32.
/* start.S / exception_handlers.S */ /* start.S / exception_handlers.S */
#define SYS_STACK_TOP_INIT 0x4003FF00 #define SYS_STACK_TOP_INIT 0x4003FF00
@@ -48,29 +47,27 @@
#define NYX_SZ_MAX SZ_16M #define NYX_SZ_MAX SZ_16M
/* --- Gap: 0x82000000 - 0x82FFFFFF --- */ /* --- Gap: 0x82000000 - 0x82FFFFFF --- */
/* Stack theoretical max: 33MB */ // Heap buffer.
#define IPL_STACK_TOP 0x83100000 #define IPL_HEAP_START 0x82000000
#define IPL_HEAP_START 0x84000000 #define IPL_HEAP_SZ (SZ_256M)
#define IPL_HEAP_SZ (SZ_512M - SZ_64M)
#define SMMU_HEAP_ADDR 0xA0000000 #define SMMU_HEAP_ADDR 0x92000000
/* --- Gap: 1040MB 0xA4000000 - 0xE4FFFFFF --- */ /* --- Gap: 1280MB 0x96000000 - 0xE4FFFFFF --- */
// Virtual disk / Chainloader buffers. // Virtual disk / Chainloader buffers.
#define RAM_DISK_ADDR 0xA4000000 #define RAM_DISK_ADDR 0x95000000
#define RAM_DISK_SZ 0x41000000 // 1040MB. #define RAM_DISK_SZ 0x50000000 // 1280MB.
#define RAM_DISK2_SZ 0x21000000 // 528MB.
// NX BIS driver sector cache.
#define NX_BIS_CACHE_ADDR 0xC5000000
#define NX_BIS_CACHE_SZ 0x10020000 // 256MB.
#define NX_BIS_LOOKUP_ADDR 0xD6000000
#define NX_BIS_LOOKUP_SZ 0xF000000 // 240MB.
// L4T Kernel Panic Storage (PSTORE). // L4T Kernel Panic Storage (PSTORE).
#define PSTORE_ADDR 0xB0000000 #define PSTORE_ADDR 0xB0000000
#define PSTORE_SZ SZ_2M #define PSTORE_SZ SZ_2M
// NX BIS driver sector cache.
#define NX_BIS_CACHE_ADDR 0xC7000000
#define NX_BIS_CACHE_SZ 0x10020000 // 256MB.
#define NX_BIS_LOOKUP_ADDR 0xD8000000
#define NX_BIS_LOOKUP_SZ 0x8000000 // 128MB. 512GB eMMC partition max.
//#define DRAM_LIB_ADDR 0xE0000000 //#define DRAM_LIB_ADDR 0xE0000000
/* --- Chnldr: 252MB 0xC03C0000 - 0xCFFFFFFF --- */ //! Only used when chainloading. /* --- Chnldr: 252MB 0xC03C0000 - 0xCFFFFFFF --- */ //! Only used when chainloading.
@@ -78,7 +75,7 @@
#define SDMMC_UPPER_BUFFER 0xE5000000 #define SDMMC_UPPER_BUFFER 0xE5000000
#define SDMMC_UP_BUF_SZ SZ_128M #define SDMMC_UP_BUF_SZ SZ_128M
// Nyx buffers. // Nyx buffers. !Do not change!
#define NYX_STORAGE_ADDR 0xED000000 #define NYX_STORAGE_ADDR 0xED000000
#define NYX_RES_ADDR 0xEE000000 #define NYX_RES_ADDR 0xEE000000
#define NYX_RES_SZ SZ_16M #define NYX_RES_SZ SZ_16M
@@ -86,7 +83,6 @@
// SDMMC DMA buffers 2 // SDMMC DMA buffers 2
#define SDXC_BUF_ALIGNED 0xEF000000 #define SDXC_BUF_ALIGNED 0xEF000000
#define MIXD_BUF_ALIGNED 0xF0000000 #define MIXD_BUF_ALIGNED 0xF0000000
#define TITLEKEY_BUF_ADR MIXD_BUF_ALIGNED
#define EMMC_BUF_ALIGNED MIXD_BUF_ALIGNED #define EMMC_BUF_ALIGNED MIXD_BUF_ALIGNED
#define SDMMC_DMA_BUF_SZ SZ_16M // 4MB currently used. #define SDMMC_DMA_BUF_SZ SZ_16M // 4MB currently used.
@@ -96,7 +92,7 @@
#define NYX_LV_MEM_ADR 0xF1400000 #define NYX_LV_MEM_ADR 0xF1400000
#define NYX_LV_MEM_SZ 0x6600000 // 70MB. #define NYX_LV_MEM_SZ 0x6600000 // 70MB.
// Framebuffer addresses. // Framebuffer addresses. !Do not change!
#define IPL_FB_ADDRESS 0xF5A00000 #define IPL_FB_ADDRESS 0xF5A00000
#define IPL_FB_SZ 0x384000 // 720 x 1280 x 4. #define IPL_FB_SZ 0x384000 // 720 x 1280 x 4.
#define LOG_FB_ADDRESS 0xF5E00000 #define LOG_FB_ADDRESS 0xF5E00000
@@ -105,13 +101,6 @@
#define NYX_FB2_ADDRESS 0xF6600000 #define NYX_FB2_ADDRESS 0xF6600000
#define NYX_FB_SZ 0x384000 // 1280 x 720 x 4. #define NYX_FB_SZ 0x384000 // 1280 x 720 x 4.
/* OBSOLETE: Very old hwinit based payloads were setting a carveout here. */
#define DRAM_MEM_HOLE_ADR 0xF6A00000
#define NX_BIS_LOOKUP_ADR DRAM_MEM_HOLE_ADR
#define DRAM_MEM_HOLE_SZ 0x8140000
/* --- Hole: 129MB 0xF6A00000 - 0xFEB3FFFF --- */
#define DRAM_START2 0xFEB40000
// USB buffers. // USB buffers.
#define USBD_ADDR 0xFEF00000 #define USBD_ADDR 0xFEF00000
#define USB_DESCRIPTOR_ADDR 0xFEF40000 #define USB_DESCRIPTOR_ADDR 0xFEF40000

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-2023 CTCaer * Copyright (c) 2020-2025 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,
@@ -54,6 +54,10 @@
#define STATUS1_INSERT BIT(7) // Cable inserted. #define STATUS1_INSERT BIT(7) // Cable inserted.
#define VER_36 0x36
#define MAX_ROHM 0x4B5
#define DEV_BM92T 0x3B0
typedef struct _pd_object_t { typedef struct _pd_object_t {
unsigned int amp:10; unsigned int amp:10;
unsigned int volt:10; unsigned int volt:10;
@@ -63,9 +67,29 @@ typedef struct _pd_object_t {
static int _bm92t36_read_reg(u8 *buf, u32 size, u32 reg) static int _bm92t36_read_reg(u8 *buf, u32 size, u32 reg)
{ {
memset(buf, 0, size);
return i2c_recv_buf_big(buf, size, I2C_1, BM92T36_I2C_ADDR, reg); return i2c_recv_buf_big(buf, size, I2C_1, BM92T36_I2C_ADDR, reg);
} }
int bm92t36_get_version(u32 *value)
{
u8 buf[2];
u16 version, man, dev;
_bm92t36_read_reg(buf, 2, FW_TYPE_REG);
version = (buf[0] << 4) | buf[1];
_bm92t36_read_reg(buf, 2, MAN_ID_REG);
man = (buf[1] << 8) | buf[0];
_bm92t36_read_reg(buf, 2, DEV_ID_REG);
dev = (buf[1] << 8) | buf[0];
if (value)
*value = (dev << 16) | version;
if (version == VER_36 && man == MAX_ROHM && dev == DEV_BM92T)
return 0;
else
return -1;
}
void bm92t36_get_sink_info(bool *inserted, usb_pd_objects_t *usb_pd) void bm92t36_get_sink_info(bool *inserted, usb_pd_objects_t *usb_pd)
{ {
u8 buf[32]; u8 buf[32];
@@ -73,14 +97,12 @@ 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);

View File

@@ -36,6 +36,7 @@ typedef struct _usb_pd_objects_t
usb_pd_object_t selected_pdo; usb_pd_object_t selected_pdo;
} usb_pd_objects_t; } usb_pd_objects_t;
int bm92t36_get_version(u32 *value);
void bm92t36_get_sink_info(bool *inserted, usb_pd_objects_t *usb_pd); void bm92t36_get_sink_info(bool *inserted, usb_pd_objects_t *usb_pd);
#endif #endif

View File

@@ -1,7 +1,7 @@
/* /*
* Battery charger driver for Nintendo Switch's TI BQ24193 * Battery charger driver for Nintendo Switch's TI BQ24193
* *
* Copyright (c) 2018 CTCaer * Copyright (c) 2018-2025 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,18 @@ static u8 bq24193_get_reg(u8 reg)
return i2c_recv_byte(I2C_1, BQ24193_I2C_ADDR, reg); return i2c_recv_byte(I2C_1, BQ24193_I2C_ADDR, reg);
} }
int bq24193_get_version(u32 *value)
{
u16 data = bq24193_get_reg(BQ24193_VendorPart);
if (value)
*value = data;
if (data == 0x2F)
return 0;
else
return -1;
}
int bq24193_get_property(enum BQ24193_reg_prop prop, int *value) int bq24193_get_property(enum BQ24193_reg_prop prop, int *value)
{ {
u8 data; u8 data;

View File

@@ -19,6 +19,8 @@
#ifndef __BQ24193_H_ #ifndef __BQ24193_H_
#define __BQ24193_H_ #define __BQ24193_H_
#include <utils/types.h>
#define BQ24193_I2C_ADDR 0x6B #define BQ24193_I2C_ADDR 0x6B
// REG 0 masks. // REG 0 masks.
@@ -114,7 +116,8 @@ enum BQ24193_reg_prop {
BQ24193_ProductNumber, // REG A. BQ24193_ProductNumber, // REG A.
}; };
int bq24193_get_property(enum BQ24193_reg_prop prop, int *value); int bq24193_get_version(u32 *value);
int bq24193_get_property(enum BQ24193_reg_prop prop, int *value);
void bq24193_enable_charger(); void bq24193_enable_charger();
void bq24193_fake_battery_removal(); void bq24193_fake_battery_removal();

View File

@@ -3,7 +3,7 @@
* *
* Copyright (c) 2011 Samsung Electronics * Copyright (c) 2011 Samsung Electronics
* MyungJoo Ham <myungjoo.ham@samsung.com> * MyungJoo Ham <myungjoo.ham@samsung.com>
* Copyright (c) 2018 CTCaer * Copyright (c) 2018-2025 CTCaer
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -60,6 +60,18 @@ static u16 max17050_get_reg(u8 reg)
return data; return data;
} }
int max17050_get_version(u32 *value)
{
u16 data = max17050_get_reg(MAX17050_DevName);
if (value)
*value = data;
if (data == 0x00AC)
return 0;
else
return -1;
}
int max17050_get_property(enum MAX17050_reg reg, int *value) int max17050_get_property(enum MAX17050_reg reg, int *value)
{ {
u16 data; u16 data;

View File

@@ -130,6 +130,7 @@ enum MAX17050_reg {
MAX17050_VFSOC = 0xFF, MAX17050_VFSOC = 0xFF,
}; };
int max17050_get_version(u32 *value);
int max17050_get_property(enum MAX17050_reg reg, int *value); int max17050_get_property(enum MAX17050_reg reg, int *value);
int max17050_fix_configuration(); int max17050_fix_configuration();
void max17050_dump_regs(void *buf); void max17050_dump_regs(void *buf);

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-2022 CTCaer * Copyright (c) 2018-2025 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
@@ -23,7 +23,8 @@
#include <soc/timer.h> #include <soc/timer.h>
#include <soc/t210.h> #include <soc/t210.h>
int epoch_offset = 0; bool auto_dst = false;
int epoch_offset = 0;
void max77620_rtc_prep_read() void max77620_rtc_prep_read()
{ {
@@ -39,20 +40,24 @@ void max77620_rtc_get_time(rtc_time_t *time)
// Get control reg config. // Get control reg config.
val = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_CONTROL_REG); val = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_CONTROL_REG);
// TODO: Check for binary format also? // TODO: Make also sure it's binary format?
// 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) & 0x1F;
time->hour = hour & 0x1F; time->hour = hour & 0x1F;
if (!(val & MAX77620_RTC_24H) && (hour & MAX77620_RTC_HOUR_PM_MASK)) if (!(val & MAX77620_RTC_24H))
time->hour = (time->hour & 0xF) + 12; {
time->hour = hour & 0xF;
if (hour & MAX77620_RTC_HOUR_PM_MASK)
time->hour += 12;
}
// Get day of week. 1: Monday to 7: Sunday. // Get day of week. 1: Monday to 7: Sunday.
time->weekday = 0; time->weekday = 0;
val = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_WEEKDAY_REG); val = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_WEEKDAY_REG) & 0x7F;
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
{ {
time->weekday++; time->weekday++;
@@ -62,8 +67,9 @@ 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_DAY_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->month++; // Normally minus 1, but everything else expects 1 as January.
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;
} }
@@ -126,7 +132,7 @@ void max77620_rtc_epoch_to_date(u32 epoch, rtc_time_t *time)
time->day = day; time->day = day;
// Set weekday. // Set weekday.
time->weekday = 0; //! TODO. time->weekday = (day + 4) % 7;
} }
u32 max77620_rtc_date_to_epoch(const rtc_time_t *time) u32 max77620_rtc_date_to_epoch(const rtc_time_t *time)
@@ -162,10 +168,21 @@ void max77620_rtc_get_time_adjusted(rtc_time_t *time)
if (epoch_offset) if (epoch_offset)
{ {
u32 epoch = (u32)((s64)max77620_rtc_date_to_epoch(time) + epoch_offset); u32 epoch = (u32)((s64)max77620_rtc_date_to_epoch(time) + epoch_offset);
// Adjust for DST between 28 march and 28 october. Good enough to cover all years as week info is not valid.
u16 md = (time->month << 8) | time->day;
if (auto_dst && md >= 0x31C && md < 0xA1C)
epoch += 3600;
max77620_rtc_epoch_to_date(epoch, time); max77620_rtc_epoch_to_date(epoch, time);
} }
} }
void max77620_rtc_set_auto_dst(bool enable)
{
auto_dst = enable;
}
void max77620_rtc_set_epoch_offset(int offset) void max77620_rtc_set_epoch_offset(int offset)
{ {
epoch_offset = offset; epoch_offset = offset;

View File

@@ -46,7 +46,7 @@
#define MAX77620_RTC_WEEKDAY_REG 0x0A #define MAX77620_RTC_WEEKDAY_REG 0x0A
#define MAX77620_RTC_MONTH_REG 0x0B #define MAX77620_RTC_MONTH_REG 0x0B
#define MAX77620_RTC_YEAR_REG 0x0C #define MAX77620_RTC_YEAR_REG 0x0C
#define MAX77620_RTC_DATE_REG 0x0D #define MAX77620_RTC_DAY_REG 0x0D
#define MAX77620_ALARM1_SEC_REG 0x0E #define MAX77620_ALARM1_SEC_REG 0x0E
#define MAX77620_ALARM1_MIN_REG 0x0F #define MAX77620_ALARM1_MIN_REG 0x0F
@@ -111,6 +111,7 @@ 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_get_time_adjusted(rtc_time_t *time); void max77620_rtc_get_time_adjusted(rtc_time_t *time);
void max77620_rtc_set_epoch_offset(int offset); void max77620_rtc_set_epoch_offset(int offset);
void max77620_rtc_set_auto_dst(bool enable);
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);

View File

@@ -32,9 +32,6 @@ 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];
static u32 _se_rsa_exp_sizes[SE_RSA_KEYSLOT_COUNT];
se_ll_t ll_src, ll_dst; se_ll_t ll_src, ll_dst;
se_ll_t *ll_src_ptr, *ll_dst_ptr; // Must be u32 aligned. se_ll_t *ll_src_ptr, *ll_dst_ptr; // Must be u32 aligned.
@@ -214,66 +211,6 @@ void se_rsa_acc_ctrl(u32 rs, u32 flags)
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)
@@ -299,12 +236,6 @@ void se_aes_key_set(u32 ks, const void *key, u32 size)
} }
} }
void se_aes_key_partial_set(u32 ks, u32 index, u32 data)
{
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) void se_aes_iv_set(u32 ks, const void *iv)
{ {
u32 data[SE_AES_IV_SIZE / 4]; u32 data[SE_AES_IV_SIZE / 4];
@@ -648,52 +579,6 @@ int se_calc_sha256_finalize(void *hash, u32 *msg_left)
return res; return res;
} }
int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size)
{
int res = 0;
u8 tmp1[0x40] = {0};
u8 tmp2[0x40 + src_size];
u8 tmp3[0x60] = {0};
memset(tmp2, 0, 0x40 + src_size);
u8 *secret = (u8 *)tmp1;
u8 *ipad = (u8 *)tmp2;
u8 *opad = (u8 *)tmp3;
if (key_size > 0x40)
{
if (!se_calc_sha256_oneshot(secret, key, key_size))
goto out;
memset(secret + 0x20, 0, 0x20);
}
else
{
memcpy(secret, key, key_size);
memset(secret + key_size, 0, 0x40 - key_size);
}
u32 *secret32 = (u32 *)secret;
u32 *ipad32 = (u32 *)ipad;
u32 *opad32 = (u32 *)opad;
for (u32 i = 0; i < 0x10; i++)
{
ipad32[i] = secret32[i] ^ 0x36363636;
opad32[i] = secret32[i] ^ 0x5C5C5C5C;
}
memcpy(ipad + 0x40, src, src_size);
if (!se_calc_sha256_oneshot(dst, ipad, 0x40 + src_size))
goto out;
memcpy(opad + 0x40, dst, 0x20);
if (!se_calc_sha256_oneshot(dst, opad, 0x60))
goto out;
res = 1;
out:;
return res;
}
int se_gen_prng128(void *dst) int se_gen_prng128(void *dst)
{ {
// Setup config for X931 PRNG. // Setup config for X931 PRNG.

View File

@@ -22,15 +22,11 @@
#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, const void *key, u32 size);
void se_aes_iv_set(u32 ks, const void *iv); void se_aes_iv_set(u32 ks, const void *iv);
void se_aes_key_partial_set(u32 ks, u32 index, u32 data);
void se_aes_key_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);
@@ -47,7 +43,6 @@ int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_
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 se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size); int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size);
int se_calc_sha256_finalize(void *hash, u32 *msg_left); int se_calc_sha256_finalize(void *hash, u32 *msg_left);
int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size);
int se_gen_prng128(void *dst); int se_gen_prng128(void *dst);
int se_aes_cmac_128(u32 ks, void *dst, const void *src, u32 src_size); int se_aes_cmac_128(u32 ks, void *dst, const void *src, u32 src_size);

View File

@@ -91,10 +91,10 @@ int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt)
if (type == TSEC_FW_TYPE_NEW) if (type == TSEC_FW_TYPE_NEW)
{ {
// Disable all CCPLEX core rails. // Disable all CCPLEX core rails.
pmc_enable_partition(POWER_RAIL_CE0, DISABLE); pmc_domain_pwrgate_set(POWER_RAIL_CE0, DISABLE);
pmc_enable_partition(POWER_RAIL_CE1, DISABLE); pmc_domain_pwrgate_set(POWER_RAIL_CE1, DISABLE);
pmc_enable_partition(POWER_RAIL_CE2, DISABLE); pmc_domain_pwrgate_set(POWER_RAIL_CE2, DISABLE);
pmc_enable_partition(POWER_RAIL_CE3, DISABLE); pmc_domain_pwrgate_set(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(); mc_enable_ahb_redirect();

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-2024 CTCaer * Copyright (c) 2019-2025 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,
@@ -64,9 +64,13 @@ typedef enum
BPMP_STATE_FIQ = BIT(3), BPMP_STATE_FIQ = BIT(3),
} bpmp_state_t; } bpmp_state_t;
#define BPMP_CLK_LOWEST_BOOST BPMP_CLK_HIGH2_BOOST #define BPMP_CLK_BIN0_BOOST BPMP_CLK_HYPER_BOOST
#define BPMP_CLK_LOWER_BOOST BPMP_CLK_SUPER_BOOST #define BPMP_CLK_BIN1_BOOST BPMP_CLK_SUPER_BOOST
#define BPMP_CLK_DEFAULT_BOOST BPMP_CLK_HYPER_BOOST #define BPMP_CLK_BIN2_BOOST BPMP_CLK_HIGH2_BOOST
#define BPMP_CLK_BIN3_BOOST BPMP_CLK_HIGH_BOOST
#define BPMP_CLK_LOWER_BOOST BPMP_CLK_BIN1_BOOST
#define BPMP_CLK_DEFAULT_BOOST BPMP_CLK_BIN0_BOOST
void bpmp_mmu_maintenance(u32 op, bool force); void bpmp_mmu_maintenance(u32 op, bool force);
void bpmp_mmu_set_entry(int idx, const bpmp_mmu_entry_t *entry, bool apply); void bpmp_mmu_set_entry(int idx, const bpmp_mmu_entry_t *entry, bool apply);

View File

@@ -90,11 +90,11 @@ void ccplex_boot_cpu0(u32 entry, bool lock)
CLOCK(CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2) &= 0xFFFFF000; CLOCK(CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2) &= 0xFFFFF000;
// Enable CPU main rail. // Enable CPU main rail.
pmc_enable_partition(POWER_RAIL_CRAIL, ENABLE); pmc_domain_pwrgate_set(POWER_RAIL_CRAIL, ENABLE);
// Enable cluster 0 non-CPU rail. // Enable cluster 0 non-CPU rail.
pmc_enable_partition(POWER_RAIL_C0NC, ENABLE); pmc_domain_pwrgate_set(POWER_RAIL_C0NC, ENABLE);
// Enable CPU0 rail. // Enable CPU0 rail.
pmc_enable_partition(POWER_RAIL_CE0, ENABLE); pmc_domain_pwrgate_set(POWER_RAIL_CE0, ENABLE);
// Request and wait for RAM repair. Needed for the Fast cluster. // Request and wait for RAM repair. Needed for the Fast cluster.
FLOW_CTLR(FLOW_CTLR_RAM_REPAIR) = RAM_REPAIR_REQ; FLOW_CTLR(FLOW_CTLR_RAM_REPAIR) = RAM_REPAIR_REQ;
@@ -115,7 +115,7 @@ void ccplex_boot_cpu0(u32 entry, bool lock)
} }
// Tighten up the security aperture. // Tighten up the security aperture.
// MC(MC_TZ_SECURITY_CTRL) = 1; // MC(MC_TZ_SECURITY_CTRL) = TZ_SEC_CTRL_CPU_STRICT_TZ_APERTURE_CHECK;
// 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);
@@ -150,11 +150,11 @@ void ccplex_powergate_cpu0()
CLOCK(CLK_RST_CONTROLLER_RST_DEV_V_SET) = BIT(CLK_V_MSELECT); CLOCK(CLK_RST_CONTROLLER_RST_DEV_V_SET) = BIT(CLK_V_MSELECT);
// Disable CE0. // Disable CE0.
pmc_enable_partition(POWER_RAIL_CE0, DISABLE); pmc_domain_pwrgate_set(POWER_RAIL_CE0, DISABLE);
// Disable cluster 0 non-CPU. // Disable cluster 0 non-CPU.
pmc_enable_partition(POWER_RAIL_C0NC, DISABLE); pmc_domain_pwrgate_set(POWER_RAIL_C0NC, DISABLE);
// Disable CPU rail. // Disable CPU rail.
pmc_enable_partition(POWER_RAIL_CRAIL, DISABLE); pmc_domain_pwrgate_set(POWER_RAIL_CRAIL, DISABLE);
clock_disable_coresight(); clock_disable_coresight();

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2024 CTCaer * Copyright (c) 2018-2025 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,6 +23,14 @@
#include <soc/t210.h> #include <soc/t210.h>
#include <storage/sdmmc.h> #include <storage/sdmmc.h>
typedef struct _clk_rst_mgd_t
{
u16 reset;
u16 enable;
u16 source;
u8 index;
} clk_rst_mgd_t;
typedef struct _clock_osc_t typedef struct _clock_osc_t
{ {
u32 freq; u32 freq;
@@ -40,6 +48,15 @@ static const clock_osc_t _clock_osc_cnt[] = {
{ 48000, 2836, 3023 } { 48000, 2836, 3023 }
}; };
/* clk_rst_mgd_t: reset, enable, source, index */
static const clk_rst_mgd_t _clock_sdmmc[] = {
{ CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC1, CLK_L_SDMMC1 },
{ CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC2, CLK_L_SDMMC2 },
{ CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC3, CLK_U_SDMMC3 },
{ CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC4, CLK_L_SDMMC4 },
};
/* clk_rst_t: reset, enable, source, index, clk_src, clk_div */ /* clk_rst_t: reset, enable, source, index, clk_src, clk_div */
static const clk_rst_t _clock_uart[] = { static const clk_rst_t _clock_uart[] = {
@@ -52,43 +69,43 @@ static const clk_rst_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 clk_rst_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, CLK_SRC_DIV(10.5) }, //20.4MHz -> 100KHz { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_I2C1, CLK_L_I2C1, 0, CLK_SRC_DIV(10.5) }, // 20.4 MHz -> 100 KHz
{ CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_I2C2, CLK_H_I2C2, 0, CLK_SRC_DIV(3) }, //81.6MHz -> 400KHz { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_I2C2, CLK_H_I2C2, 0, CLK_SRC_DIV(3) }, // 81.6 MHz -> 400 KHz
{ CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_I2C3, CLK_U_I2C3, 0, CLK_SRC_DIV(3) }, //81.6MHz -> 400KHz { CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_I2C3, CLK_U_I2C3, 0, CLK_SRC_DIV(3) }, // 81.6 MHz -> 400 KHz
{ CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_I2C4, CLK_V_I2C4, 0, CLK_SRC_DIV(10.5) }, //20.4MHz -> 100KHz { CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_I2C4, CLK_V_I2C4, 0, CLK_SRC_DIV(10.5) }, // 20.4 MHz -> 100 KHz
{ CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_I2C5, CLK_H_I2C5, 0, CLK_SRC_DIV(3) }, //81.6MHz -> 400KHz { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_I2C5, CLK_H_I2C5, 0, CLK_SRC_DIV(3) }, // 81.6 MHz -> 400 KHz
{ CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_I2C6, CLK_X_I2C6, 0, CLK_SRC_DIV(10.5) } //20.4MHz -> 100KHz { CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_I2C6, CLK_X_I2C6, 0, CLK_SRC_DIV(10.5) } // 20.4 MHz -> 100 KHz
}; };
static clk_rst_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, CLK_SRC_DIV(1) // 408MHz. Default: 408MHz. Max: 627.2 MHz. CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_SE, CLK_V_SE, 0, CLK_SRC_DIV(1) // 408 MHz. Max: 627.2 MHz.
}; };
static clk_rst_t _clock_tzram = { static clk_rst_t _clock_tzram = {
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_NO_SOURCE, CLK_V_TZRAM, 0, CLK_SRC_DIV(1) CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_NO_SOURCE, CLK_V_TZRAM, 0, CLK_SRC_DIV(1)
}; };
static clk_rst_t _clock_host1x = { static clk_rst_t _clock_host1x = { // Has idle divisor.
CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X, CLK_L_HOST1X, 4, CLK_SRC_DIV(2.5) // 163.2MHz. Max: 408MHz. CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X, CLK_L_HOST1X, 4, CLK_SRC_DIV(2.5) // 163.2MHz. Max: 408 MHz.
}; };
static clk_rst_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, CLK_SRC_DIV(2) // 204MHz. Max: 408MHz. CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_TSEC, CLK_U_TSEC, 0, CLK_SRC_DIV(2) // 204 MHz. Max: 408 MHz.
}; };
static clk_rst_t _clock_nvdec = { static clk_rst_t _clock_nvdec = {
CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_NVDEC, CLK_Y_NVDEC, 4, CLK_SRC_DIV(1) // 408 MHz. Max: 716.8/979.2MHz. CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_NVDEC, CLK_Y_NVDEC, 4, CLK_SRC_DIV(1) // 408 MHz. Max: 716.8/979.2 MHz.
}; };
static clk_rst_t _clock_nvjpg = { static clk_rst_t _clock_nvjpg = {
CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_NVJPG, CLK_Y_NVJPG, 4, CLK_SRC_DIV(1) // 408 MHz. Max: 627.2/652.8MHz. CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_NVJPG, CLK_Y_NVJPG, 4, CLK_SRC_DIV(1) // 408 MHz. Max: 627.2/652.8 MHz.
}; };
static clk_rst_t _clock_vic = { static clk_rst_t _clock_vic = { // Has idle divisor.
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_VIC, CLK_X_VIC, 2, CLK_SRC_DIV(1) // 408 MHz. Max: 627.2/652.8MHz. CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_VIC, CLK_X_VIC, 2, CLK_SRC_DIV(1) // 408 MHz. Max: 627.2/652.8 MHz.
}; };
static clk_rst_t _clock_sor_safe = { static clk_rst_t _clock_sor_safe = {
CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_NO_SOURCE, CLK_Y_SOR_SAFE, 0, CLK_SRC_DIV(1) CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_NO_SOURCE, CLK_Y_SOR_SAFE, 0, CLK_SRC_DIV(1) // 24 MHz.
}; };
static clk_rst_t _clock_sor0 = { static clk_rst_t _clock_sor0 = {
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_NOT_USED, CLK_X_SOR0, 0, CLK_SRC_DIV(1) CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_NOT_USED, CLK_X_SOR0, 0, CLK_SRC_DIV(1)
}; };
static clk_rst_t _clock_sor1 = { static clk_rst_t _clock_sor1 = {
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_SOR1, CLK_X_SOR1, 0, CLK_SRC_DIV(2) // 204MHz. CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_SOR1, CLK_X_SOR1, 0, CLK_SRC_DIV(2) // 204 MHz.
}; };
static clk_rst_t _clock_kfuse = { static clk_rst_t _clock_kfuse = {
CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_KFUSE, 0, CLK_SRC_DIV(1) CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_KFUSE, 0, CLK_SRC_DIV(1)
@@ -97,7 +114,7 @@ static clk_rst_t _clock_cl_dvfs = {
CLK_RST_CONTROLLER_RST_DEVICES_W, CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_NO_SOURCE, CLK_W_DVFS, 0, CLK_SRC_DIV(1) CLK_RST_CONTROLLER_RST_DEVICES_W, CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_NO_SOURCE, CLK_W_DVFS, 0, CLK_SRC_DIV(1)
}; };
static clk_rst_t _clock_coresight = { 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, CLK_SRC_DIV(3) // 136MHz. CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_CSITE, CLK_U_CSITE, 0, CLK_SRC_DIV(3) // 136 MHz.
}; };
static clk_rst_t _clock_pwm = { 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, CLK_SRC_DIV(3) // Fref: 6.4MHz. HOS: PLLP / 54 = 7.55MHz. CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, CLK_L_PWM, 6, CLK_SRC_DIV(3) // Fref: 6.4MHz. HOS: PLLP / 54 = 7.55MHz.
@@ -106,32 +123,32 @@ 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, CLK_SRC_DIV(34) // 12MHz. CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM, CLK_Y_SDMMC_LEGACY_TM, 4, CLK_SRC_DIV(34) // 12MHz.
}; };
static clk_rst_t _clock_apbdma = { 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, CLK_SRC_DIV(1) // Max: 204MHz. CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_APBDMA, 0, CLK_SRC_DIV(1) // Max: 204 MHz.
}; };
static clk_rst_t _clock_ahbdma = { 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, CLK_SRC_DIV(1) CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_AHBDMA, 0, CLK_SRC_DIV(1)
}; };
static clk_rst_t _clock_actmon = { 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, CLK_SRC_DIV(1) // 19.2MHz. CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_ACTMON, CLK_V_ACTMON, 6, CLK_SRC_DIV(1) // 19.2 MHz.
}; };
static clk_rst_t _clock_extperiph1 = { 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, CLK_SRC_DIV(1) CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH1, CLK_V_EXTPERIPH1, 0, CLK_SRC_DIV(1)
}; };
static clk_rst_t _clock_extperiph2 = { 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, CLK_SRC_DIV(102) // 4.0MHz CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH2, CLK_V_EXTPERIPH2, 2, CLK_SRC_DIV(102) // 4.0 MHz
}; };
void clock_enable(const clk_rst_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) |= BIT(clk->index);
// Disable. // Disable.
CLOCK(clk->enable) &= ~BIT(clk->index); CLOCK(clk->enable) &= ~BIT(clk->index);
// Configure clock source if required. // Configure clock source if required.
if (clk->source) if (clk->source)
CLOCK(clk->source) = clk->clk_div | (clk->clk_src << 29u); CLOCK(clk->source) = (clk->clk_src << 29u) | clk->clk_div;
// Enable. // Enable.
CLOCK(clk->enable) = (CLOCK(clk->enable) & ~BIT(clk->index)) | BIT(clk->index); CLOCK(clk->enable) |= BIT(clk->index);
usleep(2); usleep(2);
// Take clock off reset. // Take clock off reset.
@@ -141,7 +158,7 @@ void clock_enable(const clk_rst_t *clk)
void clock_disable(const clk_rst_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) |= BIT(clk->index);
// Disable. // Disable.
CLOCK(clk->enable) &= ~BIT(clk->index); CLOCK(clk->enable) &= ~BIT(clk->index);
} }
@@ -215,6 +232,9 @@ void clock_enable_tzram()
void clock_enable_host1x() void clock_enable_host1x()
{ {
clock_enable(&_clock_host1x); clock_enable(&_clock_host1x);
// Set idle frequency to 81.6 MHz.
// CLOCK(_clock_host1x.clk_src) |= CLK_SRC_DIV(5) << 8;
} }
void clock_disable_host1x() void clock_disable_host1x()
@@ -259,6 +279,9 @@ void clock_enable_vic()
clock_enable(&_clock_vic); clock_enable(&_clock_vic);
// Set idle frequency to 136 MHz.
// CLOCK(_clock_vic.clk_src) |= CLK_SRC_DIV(3) << 8;
// Restore sys clock. // Restore sys clock.
bpmp_clk_rate_relaxed(false); bpmp_clk_rate_relaxed(false);
} }
@@ -421,17 +444,23 @@ void clock_enable_plld(u32 divp, u32 divn, bool lowpower, bool tegra_t210)
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DISP1) = 2 << 29u; // PLLD_OUT0. CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DISP1) = 2 << 29u; // PLLD_OUT0.
// Set dividers and enable PLLD. // Set dividers and enable PLLD.
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div; CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLL_BASE_ENABLE | PLL_BASE_LOCK | plld_div;
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = tegra_t210 ? 0x20 : 0; // Keep default PLLD_SETUP. CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = tegra_t210 ? 0x20 : 0; // Keep default PLLD_SETUP.
// Set PLLD_SDM_DIN and enable PLLD to DSI pads. // Set PLLD_SDM_DIN and enable (T210) PLLD to DSI pads.
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC) = misc; CLOCK(CLK_RST_CONTROLLER_PLLD_MISC) = misc;
// Wait for PLL to stabilize.
while (!(CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) & PLL_BASE_LOCK))
;
usleep(10);
} }
void clock_enable_pllx() void clock_enable_pllx()
{ {
// Configure and enable PLLX if disabled. // Configure and enable PLLX if disabled.
if (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & PLLX_BASE_ENABLE)) // PLLX_ENABLE. if (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & PLL_BASE_ENABLE)) // PLLX_ENABLE.
{ {
CLOCK(CLK_RST_CONTROLLER_PLLX_MISC_3) &= ~PLLX_MISC3_IDDQ; // Disable IDDQ. CLOCK(CLK_RST_CONTROLLER_PLLX_MISC_3) &= ~PLLX_MISC3_IDDQ; // Disable IDDQ.
usleep(2); usleep(2);
@@ -440,18 +469,20 @@ void clock_enable_pllx()
const u32 pllx_div_cfg = (2 << 20) | (156 << 8) | 2; // P div: 2 (3), N div: 156, M div: 2. 998.4 MHz. const u32 pllx_div_cfg = (2 << 20) | (156 << 8) | 2; // P div: 2 (3), N div: 156, M div: 2. 998.4 MHz.
// Bypass dividers. // Bypass dividers.
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = PLLX_BASE_BYPASS | pllx_div_cfg; CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = PLL_BASE_BYPASS | pllx_div_cfg;
// Disable bypass // Disable bypass
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = pllx_div_cfg; CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = pllx_div_cfg;
// Set PLLX_LOCK_ENABLE. // Set PLLX_LOCK_ENABLE.
CLOCK(CLK_RST_CONTROLLER_PLLX_MISC) |= PLLX_MISC_LOCK_EN; CLOCK(CLK_RST_CONTROLLER_PLLX_MISC) |= PLLX_MISC_LOCK_EN;
// Enable PLLX. // Enable PLLX.
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = PLLX_BASE_ENABLE | pllx_div_cfg; CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = PLL_BASE_ENABLE | pllx_div_cfg;
} }
// Wait for PLL to stabilize. // Wait for PLL to stabilize.
while (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & PLLX_BASE_LOCK)) while (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & PLL_BASE_LOCK))
; ;
usleep(10);
} }
void clock_enable_pllc(u32 divn) void clock_enable_pllc(u32 divn)
@@ -459,7 +490,7 @@ void clock_enable_pllc(u32 divn)
u8 pll_divn_curr = (CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) >> 10) & 0xFF; u8 pll_divn_curr = (CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) >> 10) & 0xFF;
// Check if already enabled and configured. // Check if already enabled and configured.
if ((CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) & PLLCX_BASE_ENABLE) && (pll_divn_curr == divn)) if ((CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) & PLL_BASE_ENABLE) && (pll_divn_curr == divn))
return; return;
// Take PLLC out of reset and set basic misc parameters. // Take PLLC out of reset and set basic misc parameters.
@@ -468,7 +499,7 @@ void clock_enable_pllc(u32 divn)
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.
CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) &= ~PLLCX_BASE_ENABLE; CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) &= ~PLL_BASE_ENABLE;
CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_1) &= ~PLLC_MISC1_IDDQ; CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_1) &= ~PLLC_MISC1_IDDQ;
usleep(10); usleep(10);
@@ -476,8 +507,8 @@ void clock_enable_pllc(u32 divn)
CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) = (divn << 10) | 4; // DIVM: 4, DIVP: 1. CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) = (divn << 10) | 4; // DIVM: 4, DIVP: 1.
// Enable PLLC and wait for Phase and Frequency lock. // Enable PLLC and wait for Phase and Frequency lock.
CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) |= PLLCX_BASE_ENABLE; CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) |= PLL_BASE_ENABLE;
while (!(CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) & PLLCX_BASE_LOCK)) while (!(CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) & PLL_BASE_LOCK))
; ;
// Disable PLLC_OUT1, enable reset and set div to 1.5. // Disable PLLC_OUT1, enable reset and set div to 1.5.
@@ -493,7 +524,7 @@ void clock_disable_pllc()
// Disable PLLC and PLLC_OUT1. // Disable PLLC and PLLC_OUT1.
CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) &= ~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_MISC) = PLLC_MISC_RESET;
CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) &= ~PLLCX_BASE_ENABLE; CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) &= ~PLL_BASE_ENABLE;
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_2) &= ~(0xFF << 8); // PLLC_FLL_LD_MEM. CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_2) &= ~(0xFF << 8); // PLLC_FLL_LD_MEM.
usleep(10); usleep(10);
@@ -515,7 +546,7 @@ static void _clock_enable_pllc4(u32 mask)
//CLOCK(CLK_RST_CONTROLLER_PLLC4_MISC) = PLLC4_MISC_EN_LCKDET; //CLOCK(CLK_RST_CONTROLLER_PLLC4_MISC) = PLLC4_MISC_EN_LCKDET;
// Disable PLL and IDDQ in case they are on. // Disable PLL and IDDQ in case they are on.
CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) &= ~PLLCX_BASE_ENABLE; CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) &= ~PLL_BASE_ENABLE;
CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) &= ~PLLC4_BASE_IDDQ; CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) &= ~PLLC4_BASE_IDDQ;
usleep(10); usleep(10);
@@ -523,8 +554,8 @@ static void _clock_enable_pllc4(u32 mask)
CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) = (0 << 19) | (104 << 8) | 4; // DIVP: 1, DIVN: 104, DIVM: 4. 998MHz OUT0, 199MHz OUT2. 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) |= PLL_BASE_ENABLE;
while (!(CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) & PLLCX_BASE_LOCK)) while (!(CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) & PLL_BASE_LOCK))
; ;
msleep(1); // Wait a bit for PLL to stabilize. msleep(1); // Wait a bit for PLL to stabilize.
@@ -542,7 +573,7 @@ static void _clock_disable_pllc4(u32 mask)
// Disable PLLC4. // Disable PLLC4.
msleep(1); // Wait at least 1ms to prevent glitching. msleep(1); // Wait at least 1ms to prevent glitching.
CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) &= ~PLLCX_BASE_ENABLE; CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) &= ~PLL_BASE_ENABLE;
CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) |= PLLC4_BASE_IDDQ; CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) |= PLLC4_BASE_IDDQ;
usleep(10); usleep(10);
@@ -555,11 +586,11 @@ void clock_enable_pllu()
CLOCK(CLK_RST_CONTROLLER_PLLU_MISC) |= BIT(29); // Disable reference clock. CLOCK(CLK_RST_CONTROLLER_PLLU_MISC) |= BIT(29); // Disable reference clock.
u32 pllu_cfg = (CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) & 0xFFE00000) | BIT(24) | (1 << 16) | (0x19 << 8) | 2; u32 pllu_cfg = (CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) & 0xFFE00000) | BIT(24) | (1 << 16) | (0x19 << 8) | 2;
CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) = pllu_cfg; CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) = pllu_cfg;
CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) = pllu_cfg | PLLCX_BASE_ENABLE; // Enable. CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) = pllu_cfg | PLL_BASE_ENABLE; // Enable.
// Wait for PLL to stabilize. // Wait for PLL to stabilize.
u32 timeout = get_tmr_us() + 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) & PLL_BASE_LOCK)) // PLL_LOCK.
if (get_tmr_us() > timeout) if (get_tmr_us() > timeout)
break; break;
usleep(10); usleep(10);
@@ -593,115 +624,50 @@ void clock_enable_utmipll()
static int _clock_sdmmc_is_reset(u32 id) static int _clock_sdmmc_is_reset(u32 id)
{ {
switch (id) const clk_rst_mgd_t *clk = &_clock_sdmmc[id];
{
case SDMMC_1: return CLOCK(clk->reset) & BIT(clk->index);
return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_L) & BIT(CLK_L_SDMMC1);
case SDMMC_2:
return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_L) & BIT(CLK_L_SDMMC2);
case SDMMC_3:
return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_U) & BIT(CLK_U_SDMMC3);
case SDMMC_4:
return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_L) & BIT(CLK_L_SDMMC4);
}
return 0;
} }
static void _clock_sdmmc_set_reset(u32 id) static void _clock_sdmmc_set_reset(u32 id)
{ {
switch (id) const clk_rst_mgd_t *clk = &_clock_sdmmc[id];
{
case SDMMC_1: CLOCK(clk->reset) |= BIT(clk->index);
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_SDMMC1);
break;
case SDMMC_2:
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_SDMMC2);
break;
case SDMMC_3:
CLOCK(CLK_RST_CONTROLLER_RST_DEV_U_SET) = BIT(CLK_U_SDMMC3);
break;
case SDMMC_4:
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_SDMMC4);
break;
}
} }
static void _clock_sdmmc_clear_reset(u32 id) static void _clock_sdmmc_clear_reset(u32 id)
{ {
switch (id) const clk_rst_mgd_t *clk = &_clock_sdmmc[id];
{
case SDMMC_1: CLOCK(clk->reset) &= ~BIT(clk->index);
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = BIT(CLK_L_SDMMC1);
break;
case SDMMC_2:
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = BIT(CLK_L_SDMMC2);
break;
case SDMMC_3:
CLOCK(CLK_RST_CONTROLLER_RST_DEV_U_CLR) = BIT(CLK_U_SDMMC3);
break;
case SDMMC_4:
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = BIT(CLK_L_SDMMC4);
break;
}
} }
static int _clock_sdmmc_is_enabled(u32 id) static int _clock_sdmmc_is_enabled(u32 id)
{ {
switch (id) const clk_rst_mgd_t *clk = &_clock_sdmmc[id];
{
case SDMMC_1: return CLOCK(clk->enable) & BIT(clk->index);
return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & BIT(CLK_L_SDMMC1);
case SDMMC_2:
return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & BIT(CLK_L_SDMMC2);
case SDMMC_3:
return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_U) & BIT(CLK_U_SDMMC3);
case SDMMC_4:
return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & BIT(CLK_L_SDMMC4);
}
return 0;
} }
static void _clock_sdmmc_set_enable(u32 id) static void _clock_sdmmc_set_enable(u32 id)
{ {
switch (id) const clk_rst_mgd_t *clk = &_clock_sdmmc[id];
{
case SDMMC_1: CLOCK(clk->enable) |= BIT(clk->index);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_SDMMC1);
break;
case SDMMC_2:
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_SDMMC2);
break;
case SDMMC_3:
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_U_SET) = BIT(CLK_U_SDMMC3);
break;
case SDMMC_4:
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_SDMMC4);
break;
}
} }
static void _clock_sdmmc_clear_enable(u32 id) static void _clock_sdmmc_clear_enable(u32 id)
{ {
switch (id) const clk_rst_mgd_t *clk = &_clock_sdmmc[id];
{
case SDMMC_1: CLOCK(clk->enable) &= ~BIT(clk->index);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = BIT(CLK_L_SDMMC1);
break;
case SDMMC_2:
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = BIT(CLK_L_SDMMC2);
break;
case SDMMC_3:
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_U_CLR) = BIT(CLK_U_SDMMC3);
break;
case SDMMC_4:
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = BIT(CLK_L_SDMMC4);
break;
}
} }
static void _clock_sdmmc_config_legacy_tm() static void _clock_sdmmc_config_legacy_tm()
{ {
const clk_rst_t *clk = &_clock_sdmmc_legacy_tm; const 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);
} }
@@ -709,7 +675,7 @@ static void _clock_sdmmc_config_legacy_tm()
typedef struct _clock_sdmmc_t typedef struct _clock_sdmmc_t
{ {
u32 clock; u32 clock;
u32 real_clock; u32 pclock;
} clock_sdmmc_t; } clock_sdmmc_t;
static clock_sdmmc_t _clock_sdmmc_table[4] = { 0 }; static clock_sdmmc_t _clock_sdmmc_table[4] = { 0 };
@@ -719,16 +685,16 @@ static clock_sdmmc_t _clock_sdmmc_table[4] = { 0 };
#define SDMMC_CLOCK_SRC_PLLC4_OUT0 0x7 #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 clock)
{ {
u32 divisor = 0; u32 divisor = 0;
u32 source = SDMMC_CLOCK_SRC_PLLP_OUT0; u32 source = SDMMC_CLOCK_SRC_PLLP_OUT0;
if (id > SDMMC_4) if (id > SDMMC_4)
return 0; return 0;
// Get IO clock divisor. // Get IO clock divisor.
switch (val) switch (clock)
{ {
case 25000: case 25000:
*pclock = 24728; *pclock = 24728;
@@ -775,7 +741,7 @@ static int _clock_sdmmc_config_clock_host(u32 *pclock, u32 id, u32 val)
break; break;
case SDMMC_2: case SDMMC_2:
case SDMMC_4: case SDMMC_4:
source = SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ; // div is ignored. source = SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ; // CLK RST divisor is ignored.
break; break;
} }
*pclock = 199680; *pclock = 199680;
@@ -791,8 +757,8 @@ static int _clock_sdmmc_config_clock_host(u32 *pclock, u32 id, u32 val)
#endif #endif
} }
_clock_sdmmc_table[id].clock = val; _clock_sdmmc_table[id].clock = clock;
_clock_sdmmc_table[id].real_clock = *pclock; _clock_sdmmc_table[id].pclock = *pclock;
// Enable PLLC4 if in use by any SDMMC. // Enable PLLC4 if in use by any SDMMC.
if (source != SDMMC_CLOCK_SRC_PLLP_OUT0) if (source != SDMMC_CLOCK_SRC_PLLP_OUT0)
@@ -802,40 +768,30 @@ static int _clock_sdmmc_config_clock_host(u32 *pclock, u32 id, u32 val)
_clock_sdmmc_config_legacy_tm(); _clock_sdmmc_config_legacy_tm();
// Set SDMMC clock. // Set SDMMC clock.
u32 src_div = (source << 29u) | divisor; const clk_rst_mgd_t *clk = &_clock_sdmmc[id];
switch (id) CLOCK(clk->source) = (source << 29u) | divisor;
{
case SDMMC_1:
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC1) = src_div;
break;
case SDMMC_2:
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC2) = src_div;
break;
case SDMMC_3:
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC3) = src_div;
break;
case SDMMC_4:
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC4) = src_div;
break;
}
return 1; return 1;
} }
void clock_sdmmc_config_clock_source(u32 *pclock, u32 id, u32 val) void clock_sdmmc_config_clock_source(u32 *pclock, u32 id, u32 clock)
{ {
if (_clock_sdmmc_table[id].clock == val) if (_clock_sdmmc_table[id].clock == clock)
{ {
*pclock = _clock_sdmmc_table[id].real_clock; *pclock = _clock_sdmmc_table[id].pclock;
} }
else else
{ {
int is_enabled = _clock_sdmmc_is_enabled(id); int is_enabled = _clock_sdmmc_is_enabled(id);
if (is_enabled) if (is_enabled)
_clock_sdmmc_clear_enable(id); _clock_sdmmc_clear_enable(id);
_clock_sdmmc_config_clock_host(pclock, id, val);
_clock_sdmmc_config_clock_host(pclock, id, clock);
if (is_enabled) if (is_enabled)
_clock_sdmmc_set_enable(id); _clock_sdmmc_set_enable(id);
// Commit changes.
_clock_sdmmc_is_reset(id); _clock_sdmmc_is_reset(id);
} }
} }
@@ -918,18 +874,17 @@ int clock_sdmmc_is_not_reset_and_enabled(u32 id)
return !_clock_sdmmc_is_reset(id) && _clock_sdmmc_is_enabled(id); return !_clock_sdmmc_is_reset(id) && _clock_sdmmc_is_enabled(id);
} }
void clock_sdmmc_enable(u32 id, u32 val) void clock_sdmmc_enable(u32 id, u32 clock)
{ {
u32 clock = 0; _clock_sdmmc_clear_enable(id);
if (_clock_sdmmc_is_enabled(id))
_clock_sdmmc_clear_enable(id);
_clock_sdmmc_set_reset(id); _clock_sdmmc_set_reset(id);
_clock_sdmmc_config_clock_host(&clock, id, val); _clock_sdmmc_config_clock_host(&clock, id, clock);
_clock_sdmmc_set_enable(id); _clock_sdmmc_set_enable(id);
// // Commit changes and wait 100 cycles for reset and for clocks to stabilize.
_clock_sdmmc_is_reset(id); _clock_sdmmc_is_reset(id);
// Wait 100 cycles for reset and for clocks to stabilize.
usleep((100 * 1000 + clock - 1) / clock); 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

@@ -172,18 +172,14 @@
#define CLK_NOT_USED 0x0 #define CLK_NOT_USED 0x0
/*! PLL control and status bits */ /*! PLL control and status bits */
#define PLLX_BASE_LOCK BIT(27) #define PLL_BASE_LOCK BIT(27)
#define PLLX_BASE_REF_DIS BIT(29) #define PLL_BASE_REF_DIS BIT(29)
#define PLLX_BASE_ENABLE BIT(30) #define PLL_BASE_ENABLE BIT(30)
#define PLLX_BASE_BYPASS BIT(31) #define PLL_BASE_BYPASS BIT(31)
#define PLLX_MISC_LOCK_EN BIT(18) #define PLLX_MISC_LOCK_EN BIT(18)
#define PLLX_MISC3_IDDQ BIT(3) #define PLLX_MISC3_IDDQ BIT(3)
#define PLLCX_BASE_LOCK BIT(27)
#define PLLCX_BASE_REF_DIS BIT(29)
#define PLLCX_BASE_ENABLE BIT(30)
#define PLLCX_BASE_BYPASS BIT(31)
#define PLLA_OUT0_RSTN_CLR BIT(0) #define PLLA_OUT0_RSTN_CLR BIT(0)
#define PLLA_OUT0_CLKEN BIT(1) #define PLLA_OUT0_CLKEN BIT(1)
#define PLLA_BASE_IDDQ BIT(25) #define PLLA_BASE_IDDQ BIT(25)
@@ -473,109 +469,85 @@ typedef enum _clock_pto_id_t
enum CLK_L_DEV enum CLK_L_DEV
{ {
CLK_L_CPU = 0, // Only reset. Deprecated. CLK_L_CPU = 0, // Deprecated.
CLK_L_BPMP = 1, // Only reset. CLK_L_BPMP = 1, // Only reset.
CLK_L_SYS = 2, // Only reset. CLK_L_SYS = 2, // Only reset.
CLK_L_ISPB = 3, CLK_L_ISPB = 3,
CLK_L_RTC = 4, CLK_L_RTC = 4, // Only enable.
CLK_L_TMR = 5, CLK_L_TMR = 5,
CLK_L_UARTA = 6, CLK_L_UARTA = 6,
CLK_L_UARTB = 7, CLK_L_UARTB = 7,
CLK_L_GPIO = 8, CLK_L_GPIO = 8,
CLK_L_SDMMC2 = 9, CLK_L_SDMMC2 = 9,
CLK_L_SPDIF = 10, CLK_L_SPDIF = 10, // Only enable.
CLK_L_I2S2 = 11, // I2S1 CLK_L_I2S2 = 11, // Only enable.
CLK_L_I2C1 = 12, CLK_L_I2C1 = 12,
CLK_L_NDFLASH = 13, // HIDDEN. CLK_L_SDMMC1 = 14,
CLK_L_SDMMC1 = 14, CLK_L_SDMMC4 = 15,
CLK_L_SDMMC4 = 15, CLK_L_TWC = 16, // 3-Wire Controller. Deprecated.
CLK_L_TWC = 16, // HIDDEN. CLK_L_PWM = 17,
CLK_L_PWM = 17, CLK_L_I2S3 = 18, // Only enable.
CLK_L_I2S3 = 18, CLK_L_VI = 20,
CLK_L_EPP = 19, // HIDDEN. CLK_L_USBD = 22,
CLK_L_VI = 20, CLK_L_ISP = 23,
CLK_L_2D = 21, // HIDDEN. CLK_L_DISP2 = 26,
CLK_L_USBD = 22, CLK_L_DISP1 = 27,
CLK_L_ISP = 23, CLK_L_HOST1X = 28,
CLK_L_3D = 24, // HIDDEN. CLK_L_I2S1 = 30, // Only enable.
CLK_L_IDE = 25, // RESERVED. CLK_L_BPMP_CACHE_CTRL = 31, // Controller.
CLK_L_DISP2 = 26,
CLK_L_DISP1 = 27,
CLK_L_HOST1X = 28,
CLK_L_VCP = 29, // HIDDEN.
CLK_L_I2S1 = 30, // I2S0
CLK_L_BPMP_CACHE_CTRL = 31, // CONTROLLER
}; };
enum CLK_H_DEV enum CLK_H_DEV
{ {
CLK_H_MEM = 0, // MC. CLK_H_MEM = 0, // MC.
CLK_H_AHBDMA = 1, CLK_H_AHBDMA = 1,
CLK_H_APBDMA = 2, CLK_H_APBDMA = 2,
//CLK_H_ = 3, CLK_H_STAT_MON = 5,
CLK_H_KBC = 4, // HIDDEN. CLK_H_PMC = 6, // Only enable.
CLK_H_STAT_MON = 5, CLK_H_FUSE = 7,
CLK_H_PMC = 6, CLK_H_KFUSE = 8,
CLK_H_FUSE = 7, CLK_H_SPI1 = 9,
CLK_H_KFUSE = 8,
CLK_H_SPI1 = 9,
CLK_H_SNOR = 10, // HIDDEN.
CLK_H_JTAG2TBC = 11,
CLK_H_SPI2 = 12, CLK_H_SPI2 = 12,
CLK_H_XIO = 13, // HIDDEN. CLK_H_XIO = 13, // Misc IO. Deprecated?
CLK_H_SPI3 = 14, CLK_H_SPI3 = 14,
CLK_H_I2C5 = 15, CLK_H_I2C5 = 15,
CLK_H_DSI = 16, CLK_H_DSI = 16,
CLK_H_TVO = 17, // RESERVED.
CLK_H_HSI = 18, // HIDDEN.
CLK_H_HDMI = 19, // HIDDEN.
CLK_H_CSI = 20, CLK_H_CSI = 20,
CLK_H_TVDAC = 21, // RESERVED.
CLK_H_I2C2 = 22, CLK_H_I2C2 = 22,
CLK_H_UARTC = 23, CLK_H_UARTC = 23,
CLK_H_MIPI_CAL = 24, CLK_H_MIPI_CAL = 24,
CLK_H_EMC = 25, CLK_H_EMC = 25,
CLK_H_USB2 = 26, CLK_H_USB2 = 26,
CLK_H_USB3 = 27, // HIDDEN.
CLK_H_MPE = 28, // HIDDEN.
CLK_H_VDE = 29, // HIDDEN.
CLK_H_BSEA = 30, // HIDDEN.
CLK_H_BSEV = 31, CLK_H_BSEV = 31,
}; };
enum CLK_U_DEV enum CLK_U_DEV
{ {
CLK_U_SPEEDO = 0, // RESERVED. //CLK_U_SPEEDO = 0, // RESERVED. Old speedo ring oscillator.
CLK_U_UARTD = 1, CLK_U_UARTD = 1,
CLK_U_UARTE = 2, // HIDDEN. CLK_U_I2C3 = 3,
CLK_U_I2C3 = 3, CLK_U_SPI4 = 4,
CLK_U_SPI4 = 4, CLK_U_SDMMC3 = 5,
CLK_U_SDMMC3 = 5, CLK_U_PCIE = 6,
CLK_U_PCIE = 6, CLK_U_OWR = 7, // 1-Wire Controller. Deprecated.
CLK_U_OWR = 7, // RESERVED. CLK_U_AFI = 8,
CLK_U_AFI = 8, CLK_U_CSITE = 9,
CLK_U_CSITE = 9,
CLK_U_PCIEXCLK = 10, // Only reset. CLK_U_PCIEXCLK = 10, // Only reset.
CLK_U_BPMPUCQ = 11, // HIDDEN. CLK_U_LA = 12, // DFD.
CLK_U_LA = 12,
CLK_U_TRACECLKIN = 13, // HIDDEN.
CLK_U_SOC_THERM = 14, CLK_U_SOC_THERM = 14,
CLK_U_DTV = 15, CLK_U_DTV = 15, // Deprecated.
CLK_U_NAND_SPEED = 16, // HIDDEN.
CLK_U_I2C_SLOW = 17, CLK_U_I2C_SLOW = 17,
CLK_U_DSIB = 18, CLK_U_DSIB = 18,
CLK_U_TSEC = 19, CLK_U_TSEC = 19,
CLK_U_IRAMA = 20, CLK_U_IRAMA = 20, // Only enable.
CLK_U_IRAMB = 21, CLK_U_IRAMB = 21, // Only enable.
CLK_U_IRAMC = 22, CLK_U_IRAMC = 22, // Only enable.
CLK_U_IRAMD = 23, // EMUCIF ON RESET CLK_U_IRAMD = 23, // EMUCIF ON RESET
CLK_U_BPMP_CACHE_RAM = 24, CLK_U_BPMP_CACHE_RAM = 24, // Only enable.
CLK_U_XUSB_HOST = 25, CLK_U_XUSB_HOST = 25,
CLK_U_CLK_M_DOUBLER = 26, CLK_U_SUS_OUT = 28, // Only enable. VI MCLK. Deprecated?
CLK_U_MSENC = 27, // HIDDEN. CLK_U_DEV2_OUT = 29, // Only enable. DAP MCLK. Deprecated?
CLK_U_SUS_OUT = 28, CLK_U_DEV1_OUT = 30, // Only enable. DAP MCLK. Deprecated?
CLK_U_DEV2_OUT = 29,
CLK_U_DEV1_OUT = 30,
CLK_U_XUSB_DEV = 31, CLK_U_XUSB_DEV = 31,
}; };
@@ -583,133 +555,109 @@ enum CLK_V_DEV
{ {
CLK_V_CPUG = 0, CLK_V_CPUG = 0,
CLK_V_CPULP = 1, // Reserved. CLK_V_CPULP = 1, // Reserved.
CLK_V_3D2 = 2, // HIDDEN.
CLK_V_MSELECT = 3, CLK_V_MSELECT = 3,
CLK_V_TSENSOR = 4, CLK_V_TSENSOR = 4, // Only enable.
CLK_V_I2S4 = 5, CLK_V_I2S4 = 5, // Only enable.
CLK_V_I2S5 = 6, CLK_V_I2S5 = 6, // Only enable.
CLK_V_I2C4 = 7, CLK_V_I2C4 = 7,
CLK_V_SPI5 = 8, // HIDDEN. CLK_V_AHUB = 10, // AUDIO. Only enable.
CLK_V_SPI6 = 9, // HIDDEN. CLK_V_APB2APE = 11, // APBIF. Only enable.
CLK_V_AHUB = 10, // AUDIO.
CLK_V_APB2APE = 11, // APBIF.
CLK_V_DAM0 = 12, // HIDDEN.
CLK_V_DAM1 = 13, // HIDDEN.
CLK_V_DAM2 = 14, // HIDDEN.
CLK_V_HDA2CODEC_2X = 15, CLK_V_HDA2CODEC_2X = 15,
CLK_V_ATOMICS = 16, CLK_V_ATOMICS = 16,
//CLK_V_ = 17, CLK_V_SPDIF_DOUBLER = 22, // Only enable.
//CLK_V_ = 18,
//CLK_V_ = 19,
//CLK_V_ = 20,
//CLK_V_ = 21,
CLK_V_SPDIF_DOUBLER = 22,
CLK_V_ACTMON = 23, CLK_V_ACTMON = 23,
CLK_V_EXTPERIPH1 = 24, CLK_V_EXTPERIPH1 = 24,
CLK_V_EXTPERIPH2 = 25, CLK_V_EXTPERIPH2 = 25,
CLK_V_EXTPERIPH3 = 26, CLK_V_EXTPERIPH3 = 26,
CLK_V_SATA_OOB = 27, CLK_V_SATA_OOB = 27, // Only on T210.
CLK_V_SATA = 28, CLK_V_SATA = 28, // Only on T210.
CLK_V_HDA = 29, CLK_V_HDA = 29,
CLK_V_TZRAM = 30, // HIDDEN. CLK_V_TZRAM = 30,
CLK_V_SE = 31, // HIDDEN. CLK_V_SE = 31,
}; };
enum CLK_W_DEV enum CLK_W_DEV
{ {
CLK_W_HDA2HDMICODEC = 0, CLK_W_HDA2HDMICODEC = 0,
CLK_W_RESERVED0 = 1, //satacoldrstn CLK_W_SATACOLD = 1, // Enable reserved. Unused.
CLK_W_PCIERX0 = 2, CLK_W_PCIERX0 = 2, // Reset reserved.
CLK_W_PCIERX1 = 3, CLK_W_PCIERX1 = 3, // Reset reserved.
CLK_W_PCIERX2 = 4, CLK_W_PCIERX2 = 4, // Reset reserved.
CLK_W_PCIERX3 = 5, CLK_W_PCIERX3 = 5, // Reset reserved.
CLK_W_PCIERX4 = 6, CLK_W_PCIERX4 = 6, // Reset reserved.
CLK_W_PCIERX5 = 7, CLK_W_PCIERX5 = 7, // Reset reserved.
CLK_W_CEC = 8, CLK_W_CEC = 8,
CLK_W_PCIE2_IOBIST = 9, CLK_W_PCIE2_IOBIST = 9, // Reset reserved.
CLK_W_EMC_IOBIST = 10, CLK_W_EMC_IOBIST = 10, // Reset reserved.
CLK_W_HDMI_IOBIST = 11, // HIDDEN. CLK_W_SATA_IOBIST = 12, // Reset reserved.
CLK_W_SATA_IOBIST = 12, CLK_W_MIPI_IOBIST = 13, // Reset reserved.
CLK_W_MIPI_IOBIST = 13,
CLK_W_XUSB_PADCTL = 14, // Only reset. CLK_W_XUSB_PADCTL = 14, // Only reset.
CLK_W_XUSB = 15, CLK_W_XUSB = 15, // Only enable.
CLK_W_CILAB = 16, CLK_W_CILAB = 16, // Only enable.
CLK_W_CILCD = 17, CLK_W_CILCD = 17, // Only enable.
CLK_W_CILEF = 18, CLK_W_CILEF = 18, // Only enable.
CLK_W_DSIA_LP = 19, CLK_W_DSIA_LP = 19, // Only enable.
CLK_W_DSIB_LP = 20, CLK_W_DSIB_LP = 20, // Only enable.
CLK_W_ENTROPY = 21, CLK_W_ENTROPY = 21,
CLK_W_DDS = 22, // HIDDEN.
//CLK_W_ = 23,
CLK_W_DP2 = 24, // HIDDEN. CLK_W_DP2 = 24, // HIDDEN.
CLK_W_AMX0 = 25, // HIDDEN.
CLK_W_ADX0 = 26, // HIDDEN.
CLK_W_DVFS = 27, CLK_W_DVFS = 27,
CLK_W_XUSB_SS = 28, CLK_W_XUSB_SS = 28,
CLK_W_EMC_LATENCY = 29, CLK_W_EMC_LATENCY = 29, // Only enable.
CLK_W_MC1 = 30, CLK_W_MC1 = 30, // Only enable.
//CLK_W_ = 31,
}; };
enum CLK_X_DEV enum CLK_X_DEV
{ {
CLK_X_SPARE = 0, CLK_X_SPARE = 0,
CLK_X_DMIC1 = 1, CLK_X_DMIC1 = 1, // Only enable.
CLK_X_DMIC2 = 2, CLK_X_DMIC2 = 2, // Only enable.
CLK_X_ETR = 3, CLK_X_ETR = 3, // DFD.
CLK_X_CAM_MCLK = 4, CLK_X_CAM_MCLK = 4, // Only enable.
CLK_X_CAM_MCLK2 = 5, CLK_X_CAM_MCLK2 = 5, // Only enable.
CLK_X_I2C6 = 6, CLK_X_I2C6 = 6,
CLK_X_MC_CAPA = 7, // MC DAISY CHAIN1 CLK_X_MC_CAPA = 7, // MC Clients daisy chain 1. Only enable.
CLK_X_MC_CBPA = 8, // MC DAISY CHAIN2 CLK_X_MC_CBPA = 8, // MC Clients daisy chain 2. Only enable.
CLK_X_MC_CPU = 9, CLK_X_MC_CPU = 9, // MC CPU. Only enable.
CLK_X_MC_BBC = 10, CLK_X_MC_BBC = 10, // MC Backbone. Only enable.
CLK_X_VIM2_CLK = 11, CLK_X_VIM2_CLK = 11, // Only enable.
//CLK_X_ = 12, CLK_X_MIPIBIF = 13,
CLK_X_MIPIBIF = 13, //RESERVED CLK_X_EMC_DLL = 14, // Only enable.
CLK_X_EMC_DLL = 14, CLK_X_UART_FST_MIPI_CAL = 17, // Only enable.
//CLK_X_ = 15,
CLK_X_HDMI_AUDIO = 16, // HIDDEN.
CLK_X_UART_FST_MIPI_CAL = 17,
CLK_X_VIC = 18, CLK_X_VIC = 18,
//CLK_X_ = 19,
CLK_X_ADX1 = 20, // HIDDEN.
CLK_X_DPAUX = 21, CLK_X_DPAUX = 21,
CLK_X_SOR0 = 22, CLK_X_SOR0 = 22,
CLK_X_SOR1 = 23, CLK_X_SOR1 = 23,
CLK_X_GPU = 24, CLK_X_GPU = 24,
CLK_X_DBGAPB = 25, CLK_X_DBGAPB = 25, // Only enable.
CLK_X_HPLL_ADSP = 26, CLK_X_HPLL_ADSP = 26, // Only enable.
CLK_X_PLLP_ADSP = 27, CLK_X_PLLP_ADSP = 27, // Only enable.
CLK_X_PLLA_ADSP = 28, CLK_X_PLLA_ADSP = 28, // Only enable.
CLK_X_PLLG_REF = 29, CLK_X_PLLG_REF = 29, // Only enable.
//CLK_X_ = 30, CLK_X_EQOS = 30, // T210B01 only.
//CLK_X_ = 31,
}; };
enum CLK_Y_DEV enum CLK_Y_DEV
{ {
CLK_Y_SPARE1 = 0, CLK_Y_SPARE1 = 0,
CLK_Y_SDMMC_LEGACY_TM = 1, CLK_Y_SDMMC_LEGACY_TM = 1, // Only enable.
CLK_Y_NVDEC = 2, CLK_Y_NVDEC = 2,
CLK_Y_NVJPG = 3, CLK_Y_NVJPG = 3,
CLK_Y_AXIAP = 4, CLK_Y_AXIAP = 4, // DFD.
CLK_Y_DMIC3 = 5, CLK_Y_DMIC3 = 5, // Only enable.
CLK_Y_APE = 6, CLK_Y_APE = 6,
CLK_Y_ADSP = 7, CLK_Y_ADSP = 7,
CLK_Y_MC_CDPA = 8, // MC DAISY CHAIN4 CLK_Y_MC_CDPA = 8, // MC Clients daisy chain 4. Only enable.
CLK_Y_MC_CCPA = 9, // MC DAISY CHAIN3 CLK_Y_MC_CCPA = 9, // MC Clients daisy chain 3. Only enable.
CLK_Y_MAUD = 10, CLK_Y_MAUD = 10, // Only enable.
//CLK_Y_ = 11,
CLK_Y_SATA_USB_UPHY = 12, // Only reset. CLK_Y_SATA_USB_UPHY = 12, // Only reset.
CLK_Y_PEX_USB_UPHY = 13, // Only reset. CLK_Y_PEX_USB_UPHY = 13, // Only reset.
CLK_Y_TSECB = 14, CLK_Y_TSECB = 14,
CLK_Y_DPAUX1 = 15, CLK_Y_DPAUX1 = 15,
CLK_Y_VI_I2C = 16, CLK_Y_VI_I2C = 16,
CLK_Y_HSIC_TRK = 17, CLK_Y_HSIC_TRK = 17, // Only enable.
CLK_Y_USB2_TRK = 18, CLK_Y_USB2_TRK = 18, // Only enable.
CLK_Y_QSPI = 19, CLK_Y_QSPI = 19,
CLK_Y_UARTAPE = 20, CLK_Y_UARTAPE = 20, // Only enable.
CLK_Y_ADSPINTF = 21, // Only reset. CLK_Y_ADSPINTF = 21, // Only reset.
CLK_Y_ADSPPERIPH = 22, // Only reset. CLK_Y_ADSPPERIPH = 22, // Only reset.
CLK_Y_ADSPDBG = 23, // Only reset. CLK_Y_ADSPDBG = 23, // Only reset.
@@ -717,10 +665,10 @@ enum CLK_Y_DEV
CLK_Y_ADSPSCU = 25, // Only reset. CLK_Y_ADSPSCU = 25, // Only reset.
CLK_Y_ADSPNEON = 26, CLK_Y_ADSPNEON = 26,
CLK_Y_NVENC = 27, CLK_Y_NVENC = 27,
CLK_Y_IQC2 = 28, CLK_Y_IQC2 = 28, // Only enable. (Audio.)
CLK_Y_IQC1 = 29, CLK_Y_IQC1 = 29, // Only enable. (Audio.)
CLK_Y_SOR_SAFE = 30, CLK_Y_SOR_SAFE = 30, // Only enable.
CLK_Y_PLLP_OUT_CPU = 31, CLK_Y_PLLP_OUT_CPU = 31, // Only enable.
}; };
/*! Generic clock descriptor. */ /*! Generic clock descriptor. */
@@ -790,10 +738,10 @@ 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 clock);
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);
void clock_sdmmc_enable(u32 id, u32 val); void clock_sdmmc_enable(u32 id, u32 clock);
void clock_sdmmc_disable(u32 id); void clock_sdmmc_disable(u32 id);
u32 clock_get_osc_freq(); u32 clock_get_osc_freq();

View File

@@ -2,7 +2,7 @@
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018 shuffle2 * Copyright (c) 2018 shuffle2
* Copyright (c) 2018 balika011 * Copyright (c) 2018 balika011
* Copyright (c) 2019-2023 CTCaer * Copyright (c) 2019-2025 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -22,6 +22,7 @@
#include <mem/heap.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/clock.h>
#include <soc/fuse.h> #include <soc/fuse.h>
#include <soc/hw_init.h> #include <soc/hw_init.h>
#include <soc/pmc.h> #include <soc/pmc.h>
@@ -88,15 +89,6 @@ 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)
{ {
bool tegra_t210 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210; bool tegra_t210 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210;
@@ -182,10 +174,30 @@ void fuse_wait_idle()
; ;
} }
void fuse_sense()
{
clock_enable_fuse(false);
FUSE(FUSE_CTRL) = (FUSE(FUSE_CTRL) & (~FUSE_CMD_MASK)) | FUSE_SENSE;
usleep(1);
fuse_wait_idle();
FUSE(FUSE_PRIV2INTFC) = FUSE_PRIV2INTFC_SKIP_RECORDS | FUSE_PRIV2INTFC_START_DATA;
usleep(1);
while (!(FUSE(FUSE_CTRL) & BIT(30)) || ((FUSE(FUSE_CTRL) >> 16) & 0x1F) != FUSE_STATUS_IDLE)
;
clock_enable_fuse(true);
}
u32 fuse_read(u32 addr) u32 fuse_read(u32 addr)
{ {
FUSE(FUSE_ADDR) = addr; FUSE(FUSE_ADDR) = addr;
FUSE(FUSE_CTRL) = (FUSE(FUSE_ADDR) & ~FUSE_CMD_MASK) | FUSE_READ; FUSE(FUSE_CTRL) = (FUSE(FUSE_CTRL) & ~FUSE_CMD_MASK) | FUSE_READ;
fuse_wait_idle(); fuse_wait_idle();
return FUSE(FUSE_RDATA); return FUSE(FUSE_RDATA);

View File

@@ -2,7 +2,7 @@
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018 shuffle2 * Copyright (c) 2018 shuffle2
* Copyright (c) 2018 balika011 * Copyright (c) 2018 balika011
* Copyright (c) 2019-2023 CTCaer * Copyright (c) 2019-2025 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,8 +32,12 @@
#define FUSE_TIME_PGM1 0x18 #define FUSE_TIME_PGM1 0x18
#define FUSE_TIME_PGM2 0x1C #define FUSE_TIME_PGM2 0x1C
#define FUSE_PRIV2INTFC 0x20 #define FUSE_PRIV2INTFC 0x20
#define FUSE_PRIV2INTFC_START_DATA BIT(0)
#define FUSE_PRIV2INTFC_SKIP_RECORDS BIT(1)
#define FUSE_FUSEBYPASS 0x24 #define FUSE_FUSEBYPASS 0x24
#define FUSE_PRIVATEKEYDISABLE 0x28 #define FUSE_PRIVATEKEYDISABLE 0x28
#define FUSE_PRIVKEY_DISABLE BIT(0)
#define FUSE_PRIVKEY_TZ_STICKY_BIT BIT(4)
#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
@@ -113,14 +117,14 @@
#define FUSE_PUBLIC_KEY5 0x178 #define FUSE_PUBLIC_KEY5 0x178
#define FUSE_PUBLIC_KEY6 0x17C #define FUSE_PUBLIC_KEY6 0x17C
#define FUSE_PUBLIC_KEY7 0x180 #define FUSE_PUBLIC_KEY7 0x180
#define FUSE_TSENSOR1_CALIB 0x184 #define FUSE_TSENSOR1_CALIB 0x184 // CPU1.
#define FUSE_TSENSOR2_CALIB 0x188 #define FUSE_TSENSOR2_CALIB 0x188 // CPU2.
#define FUSE_OPT_SECURE_SCC_DIS_B01 0x18C #define FUSE_OPT_SECURE_SCC_DIS_B01 0x18C
#define FUSE_OPT_CP_REV 0x190 #define FUSE_OPT_CP_REV 0x190 // FUSE style revision - ATE. 0x101 0x100
#define FUSE_OPT_PFG 0x194 #define FUSE_OPT_PFG 0x194
#define FUSE_TSENSOR0_CALIB 0x198 #define FUSE_TSENSOR0_CALIB 0x198 // CPU0.
#define FUSE_FIRST_BOOTROM_PATCH_SIZE 0x19C #define FUSE_FIRST_BOOTROM_PATCH_SIZE 0x19C
#define FUSE_SECURITY_MODE 0x1A0 #define FUSE_SECURITY_MODE 0x1A0
#define FUSE_PRIVATE_KEY0 0x1A4 #define FUSE_PRIVATE_KEY0 0x1A4
@@ -164,22 +168,22 @@
#define FUSE_SPARE_REGISTER_ODM_B01 0x224 #define FUSE_SPARE_REGISTER_ODM_B01 0x224
#define FUSE_GPU_IDDQ_CALIB 0x228 #define FUSE_GPU_IDDQ_CALIB 0x228
#define FUSE_TSENSOR3_CALIB 0x22C #define FUSE_TSENSOR3_CALIB 0x22C // CPU3.
#define FUSE_CLOCK_BONDOUT0 0x230 #define FUSE_CLOCK_BONDOUT0 0x230
#define FUSE_CLOCK_BONDOUT1 0x234 #define FUSE_CLOCK_BONDOUT1 0x234
#define FUSE_RESERVED_ODM26_B01 0x238 #define FUSE_RESERVED_ODM26_B01 0x238
#define FUSE_RESERVED_ODM27_B01 0x23C #define FUSE_RESERVED_ODM27_B01 0x23C
#define FUSE_RESERVED_ODM28_B01 0x240 #define FUSE_RESERVED_ODM28_B01 0x240 // MAX77812 phase configuration.
#define FUSE_OPT_SAMPLE_TYPE 0x244 #define FUSE_OPT_SAMPLE_TYPE 0x244
#define FUSE_OPT_SUBREVISION 0x248 #define FUSE_OPT_SUBREVISION 0x248 // "", "p", "q", "r". e.g: A01p.
#define FUSE_OPT_SW_RESERVED_0 0x24C #define FUSE_OPT_SW_RESERVED_0 0x24C
#define FUSE_OPT_SW_RESERVED_1 0x250 #define FUSE_OPT_SW_RESERVED_1 0x250
#define FUSE_TSENSOR4_CALIB 0x254 #define FUSE_TSENSOR4_CALIB 0x254 // GPU.
#define FUSE_TSENSOR5_CALIB 0x258 #define FUSE_TSENSOR5_CALIB 0x258 // MEM0.
#define FUSE_TSENSOR6_CALIB 0x25C #define FUSE_TSENSOR6_CALIB 0x25C // MEM1.
#define FUSE_TSENSOR7_CALIB 0x260 #define FUSE_TSENSOR7_CALIB 0x260 // PLLX.
#define FUSE_OPT_PRIV_SEC_DIS 0x264 #define FUSE_OPT_PRIV_SEC_DIS 0x264
#define FUSE_PKC_DISABLE 0x268 #define FUSE_PKC_DISABLE 0x268
@@ -199,7 +203,7 @@
#define FUSE_RESERVED_ODM29_B01 0x294 #define FUSE_RESERVED_ODM29_B01 0x294
#define FUSE_APB2JTAG_DISABLE 0x298 #define FUSE_APB2JTAG_DISABLE 0x298
#define FUSE_ODM_INFO 0x29C #define FUSE_ODM_INFO 0x29C // Debug features disable.
#define FUSE_ARM_CRYPT_DE_FEATURE 0x2A8 #define FUSE_ARM_CRYPT_DE_FEATURE 0x2A8
#define FUSE_OPT_RAM_WTSEL_TSMCPDP_PO4SVT_B01 0x2B0 #define FUSE_OPT_RAM_WTSEL_TSMCPDP_PO4SVT_B01 0x2B0
@@ -210,9 +214,12 @@
#define FUSE_WOA_SKU_FLAG 0x2C0 #define FUSE_WOA_SKU_FLAG 0x2C0
#define FUSE_ECO_RESERVE_1 0x2C4 #define FUSE_ECO_RESERVE_1 0x2C4
#define FUSE_GCPLEX_CONFIG_FUSE 0x2C8 #define FUSE_GCPLEX_CONFIG_FUSE 0x2C8
#define FUSE_GPU_VPR_AUTO_FETCH_DIS BIT(0)
#define FUSE_GPU_VPR_ENABLED BIT(1)
#define FUSE_GPU_WPR_ENABLED BIT(2)
#define FUSE_PRODUCTION_MONTH 0x2CC #define FUSE_PRODUCTION_MONTH 0x2CC
#define FUSE_RAM_REPAIR_INDICATOR 0x2D0 #define FUSE_RAM_REPAIR_INDICATOR 0x2D0
#define FUSE_TSENSOR9_CALIB 0x2D4 #define FUSE_TSENSOR9_CALIB 0x2D4 // AOTAG.
#define FUSE_VMIN_CALIBRATION 0x2DC #define FUSE_VMIN_CALIBRATION 0x2DC
#define FUSE_AGING_SENSOR_CALIBRATION 0x2E0 #define FUSE_AGING_SENSOR_CALIBRATION 0x2E0
#define FUSE_DEBUG_AUTHENTICATION 0x2E4 #define FUSE_DEBUG_AUTHENTICATION 0x2E4
@@ -220,8 +227,8 @@
#define FUSE_SECURE_PROVISION_INFO 0x2EC #define FUSE_SECURE_PROVISION_INFO 0x2EC
#define FUSE_OPT_GPU_DISABLE_CP1 0x2F0 #define FUSE_OPT_GPU_DISABLE_CP1 0x2F0
#define FUSE_SPARE_ENDIS 0x2F4 #define FUSE_SPARE_ENDIS 0x2F4
#define FUSE_ECO_RESERVE_0 0x2F8 #define FUSE_ECO_RESERVE_0 0x2F8 // AID.
#define FUSE_RESERVED_CALIB0 0x304 #define FUSE_RESERVED_CALIB0 0x304 // GPCPLL ADC Calibration.
#define FUSE_RESERVED_CALIB1 0x308 #define FUSE_RESERVED_CALIB1 0x308
#define FUSE_OPT_GPU_TPC0_DISABLE 0x30C #define FUSE_OPT_GPU_TPC0_DISABLE 0x30C
#define FUSE_OPT_GPU_TPC0_DISABLE_CP1 0x310 #define FUSE_OPT_GPU_TPC0_DISABLE_CP1 0x310
@@ -239,7 +246,7 @@
#define FUSE_OPT_RAM_RCT_TSMCDP_PO4HVT_B01 0x328 #define FUSE_OPT_RAM_RCT_TSMCDP_PO4HVT_B01 0x328
#define FUSE_OPT_RAM_WCT_TSMCDP_PO4HVT_B01 0x32c #define FUSE_OPT_RAM_WCT_TSMCDP_PO4HVT_B01 0x32c
#define FUSE_OPT_RAM_KP_TSMCDP_PO4HVT_B01 0x330 #define FUSE_OPT_RAM_KP_TSMCDP_PO4HVT_B01 0x330
#define FUSE_OPT_ROM_SVOP_SP_B01 0x334 #define FUSE_OPT_RAM_SVOP_SP_B01 0x334
#define FUSE_OPT_GPU_TPC0_DISABLE_CP2 0x338 #define FUSE_OPT_GPU_TPC0_DISABLE_CP2 0x338
#define FUSE_OPT_GPU_TPC1_DISABLE 0x33C #define FUSE_OPT_GPU_TPC1_DISABLE 0x33C
@@ -248,7 +255,7 @@
#define FUSE_OPT_CPU_DISABLE_CP2 0x348 #define FUSE_OPT_CPU_DISABLE_CP2 0x348
#define FUSE_OPT_GPU_DISABLE_CP2 0x34C #define FUSE_OPT_GPU_DISABLE_CP2 0x34C
#define FUSE_USB_CALIB_EXT 0x350 #define FUSE_USB_CALIB_EXT 0x350
#define FUSE_RESERVED_FIELD 0x354 #define FUSE_RESERVED_FIELD 0x354 // RMA.
#define FUSE_SPARE_REALIGNMENT_REG 0x37C #define FUSE_SPARE_REALIGNMENT_REG 0x37C
#define FUSE_SPARE_BIT_0 0x380 #define FUSE_SPARE_BIT_0 0x380
//... //...
@@ -262,24 +269,24 @@
#define FUSE_CMD_MASK 0x3 #define FUSE_CMD_MASK 0x3
/*! Fuse status. */ /*! Fuse status. */
#define FUSE_STATUS_RESET 0 #define FUSE_STATUS_RESET 0
#define FUSE_STATUS_POST_RESET 1 #define FUSE_STATUS_POST_RESET 1
#define FUSE_STATUS_LOAD_ROW0 2 #define FUSE_STATUS_LOAD_ROW0 2
#define FUSE_STATUS_LOAD_ROW1 3 #define FUSE_STATUS_LOAD_ROW1 3
#define FUSE_STATUS_IDLE 4 #define FUSE_STATUS_IDLE 4
#define FUSE_STATUS_READ_SETUP 5 #define FUSE_STATUS_READ_SETUP 5
#define FUSE_STATUS_READ_STROBE 6 #define FUSE_STATUS_READ_STROBE 6
#define FUSE_STATUS_SAMPLE_FUSES 7 #define FUSE_STATUS_SAMPLE_FUSES 7
#define FUSE_STATUS_READ_HOLD 8 #define FUSE_STATUS_READ_HOLD 8
#define FUSE_STATUS_FUSE_SRC_SETUP 9 #define FUSE_STATUS_FUSE_SRC_SETUP 9
#define FUSE_STATUS_WRITE_SETUP 10 #define FUSE_STATUS_WRITE_SETUP 10
#define FUSE_STATUS_WRITE_ADDR_SETUP 11 #define FUSE_STATUS_WRITE_ADDR_SETUP 11
#define FUSE_STATUS_WRITE_PROGRAM 12 #define FUSE_STATUS_WRITE_PROGRAM 12
#define FUSE_STATUS_WRITE_ADDR_HOLD 13 #define FUSE_STATUS_WRITE_ADDR_HOLD 13
#define FUSE_STATUS_FUSE_SRC_HOLD 14 #define FUSE_STATUS_FUSE_SRC_HOLD 14
#define FUSE_STATUS_LOAD_RIR 15 #define FUSE_STATUS_LOAD_RIR 15
#define FUSE_STATUS_READ_BEFORE_WRITE_SETUP 16 #define FUSE_STATUS_READ_BEFORE_WRITE_SETUP 16
#define FUSE_STATUS_READ_DEASSERT_PD 17 #define FUSE_STATUS_READ_DEASSERT_PD 17
/*! Fuse cache registers. */ /*! Fuse cache registers. */
#define FUSE_RESERVED_ODMX(x) (0x1C8 + 4 * (x)) #define FUSE_RESERVED_ODMX(x) (0x1C8 + 4 * (x))
@@ -304,12 +311,13 @@ 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();
int fuse_set_sbk(); int fuse_set_sbk();
void fuse_wait_idle(); void fuse_wait_idle();
void fuse_sense();
u32 fuse_read(u32 addr);
int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value)); int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value));
int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len); int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len);
void fuse_read_array(u32 *words); void fuse_read_array(u32 *words);

View File

@@ -77,10 +77,10 @@ static void _config_oscillators()
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(APB_MISC_GP_ASDBGREG) = (PMC(APB_MISC_GP_ASDBGREG) & 0xFCFFFFFF) | (2 << 24); // CFG2TMC_RAM_SVOP_PDP. APB_MISC(APB_MISC_GP_ASDBGREG) = (APB_MISC(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.
@@ -155,16 +155,34 @@ static void _config_pmc_scratch()
PMC(APBDEV_PMC_SECURE_SCRATCH21) |= PMC_FUSE_PRIVATEKEYDISABLE_TZ_STICKY_BIT; PMC(APBDEV_PMC_SECURE_SCRATCH21) |= PMC_FUSE_PRIVATEKEYDISABLE_TZ_STICKY_BIT;
} }
static void _mbist_workaround() static void _mbist_workaround_bl()
{ {
// Make sure Audio clocks are enabled before accessing I2S. /*
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= BIT(CLK_V_AHUB); * DFT MBIST HW Errata for T210.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= BIT(CLK_Y_APE); * RAM Data corruption observed when MBIST_EN from DFT (Tegra X1 Si Errata)
*
* The MBIST_EN signals from the DFT logic can impact the functional logic of
* internal rams after power-on since they are driven by non-resetable flops.
* That can be worked around by enabling and then disabling the related clocks.
*
* The bootrom patches, already handle the LVL2 SLCG war by enabling all clocks
* and all LVL2 CLK overrides (power saving disable).
* The Bootloader then handles the IP block SLCG part and also restores the
* state for the clocks/lvl2 slcg.
* After these, per domain MBIST WAR is needed every time a domain gets
* unpowergated if it was previously powergated.
*
* Affected power domains: all except IRAM and CCPLEX.
*/
// Set mux output to SOR1 clock switch. // Set mux output to SOR1 clock switch (for VI).
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SOR1) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SOR1) | 0x8000) & 0xFFFFBFFF; CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SOR1) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SOR1) & ~BIT(14)) | BIT(15);
// Enabled PLLD and set csi to PLLD for test pattern generation. // Enable PLLD and set csi to PLLD for test pattern generation (for VI).
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) |= 0x40800000; CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) |= PLL_BASE_ENABLE | BIT(23);
// Make sure Audio clocks are enabled before accessing I2S.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = BIT(CLK_V_AHUB);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_Y_SET) = BIT(CLK_Y_APE);
// Clear per-clock resets for APE/VIC/HOST1X/DISP1. // Clear per-clock resets for APE/VIC/HOST1X/DISP1.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_Y_CLR) = BIT(CLK_Y_APE); CLOCK(CLK_RST_CONTROLLER_RST_DEV_Y_CLR) = BIT(CLK_Y_APE);
@@ -172,78 +190,73 @@ static void _mbist_workaround()
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = BIT(CLK_L_HOST1X) | BIT(CLK_L_DISP1); CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = BIT(CLK_L_HOST1X) | BIT(CLK_L_DISP1);
usleep(2); usleep(2);
// I2S channels to master and disable SLCG. // Set I2S to master to enable clocks and set SLCG overrides.
I2S(I2S1_CTRL) |= I2S_CTRL_MASTER_EN; for (u32 i2s_idx = 0; i2s_idx < 5; i2s_idx++)
I2S(I2S1_CG) &= ~I2S_CG_SLCG_ENABLE; {
I2S(I2S2_CTRL) |= I2S_CTRL_MASTER_EN; I2S(I2S_CTRL + (i2s_idx << 8u)) |= I2S_CTRL_MASTER_EN;
I2S(I2S2_CG) &= ~I2S_CG_SLCG_ENABLE; I2S(I2S_CG + (i2s_idx << 8u)) = I2S_CG_SLCG_DISABLE;
I2S(I2S3_CTRL) |= I2S_CTRL_MASTER_EN; }
I2S(I2S3_CG) &= ~I2S_CG_SLCG_ENABLE; // Set SLCG overrides for DISPA and VIC.
I2S(I2S4_CTRL) |= I2S_CTRL_MASTER_EN; DISPLAY_A(_DIREG(DC_COM_DSC_TOP_CTL)) |= BIT(2); // DSC_SLCG_OVERRIDE.
I2S(I2S4_CG) &= ~I2S_CG_SLCG_ENABLE;
I2S(I2S5_CTRL) |= I2S_CTRL_MASTER_EN;
I2S(I2S5_CG) &= ~I2S_CG_SLCG_ENABLE;
// Set SLCG overrides.
DISPLAY_A(_DIREG(DC_COM_DSC_TOP_CTL)) |= 4; // DSC_SLCG_OVERRIDE.
VIC(VIC_THI_SLCG_OVERRIDE_LOW_A) = 0xFFFFFFFF; VIC(VIC_THI_SLCG_OVERRIDE_LOW_A) = 0xFFFFFFFF;
// Wait a bit for MBIST_EN to get unstuck (1 cycle min).
usleep(2); usleep(2);
// Reset SLCG to automatic mode.
// for (u32 i2s_idx = 0; i2s_idx < 5; i2s_idx++)
// I2S(I2S_CG + (i2s_idx << 8u)) = I2S_CG_SLCG_ENABLE;
// DISPLAY_A(_DIREG(DC_COM_DSC_TOP_CTL)) &= ~BIT(2); // DSC_SLCG_OVERRIDE.
// VIC(VIC_THI_SLCG_OVERRIDE_LOW_A) = 0;
// Set per-clock reset for APE/VIC/HOST1X/DISP1. // Set per-clock reset for APE/VIC/HOST1X/DISP1.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_Y_SET) = BIT(CLK_Y_APE); CLOCK(CLK_RST_CONTROLLER_RST_DEV_Y_SET) = BIT(CLK_Y_APE);
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_HOST1X) | BIT(CLK_L_DISP1); CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_HOST1X) | BIT(CLK_L_DISP1);
CLOCK(CLK_RST_CONTROLLER_RST_DEV_X_SET) = BIT(CLK_X_VIC); CLOCK(CLK_RST_CONTROLLER_RST_DEV_X_SET) = BIT(CLK_X_VIC);
// Enable specific clocks and disable all others. // Disable all unneeded clocks that were enabled in bootrom.
// CLK L Devices. // CLK L Devices.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) = CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) = BIT(CLK_H_PMC) |
BIT(CLK_H_PMC) | BIT(CLK_H_FUSE);
BIT(CLK_H_FUSE);
// CLK H Devices. // CLK H Devices.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) = CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) = BIT(CLK_L_RTC) |
BIT(CLK_L_RTC) | BIT(CLK_L_TMR) |
BIT(CLK_L_TMR) | BIT(CLK_L_GPIO) |
BIT(CLK_L_GPIO) | BIT(CLK_L_BPMP_CACHE_CTRL);
BIT(CLK_L_BPMP_CACHE_CTRL);
// CLK U Devices. // CLK U Devices.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_U) = CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_U) = BIT(CLK_U_CSITE) |
BIT(CLK_U_CSITE) | BIT(CLK_U_IRAMA) |
BIT(CLK_U_IRAMA) | BIT(CLK_U_IRAMB) |
BIT(CLK_U_IRAMB) | BIT(CLK_U_IRAMC) |
BIT(CLK_U_IRAMC) | BIT(CLK_U_IRAMD) |
BIT(CLK_U_IRAMD) | BIT(CLK_U_BPMP_CACHE_RAM);
BIT(CLK_U_BPMP_CACHE_RAM);
// CLK V Devices. // CLK V Devices.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) = CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) = BIT(CLK_V_MSELECT) |
BIT(CLK_V_MSELECT) | BIT(CLK_V_APB2APE) |
BIT(CLK_V_APB2APE) | BIT(CLK_V_SPDIF_DOUBLER) |
BIT(CLK_V_SPDIF_DOUBLER) | BIT(CLK_V_SE);
BIT(CLK_V_SE);
// CLK W Devices. // CLK W Devices.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_W) = CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_W) = BIT(CLK_W_PCIERX0) |
BIT(CLK_W_PCIERX0) | BIT(CLK_W_PCIERX1) |
BIT(CLK_W_PCIERX1) | BIT(CLK_W_PCIERX2) |
BIT(CLK_W_PCIERX2) | BIT(CLK_W_PCIERX3) |
BIT(CLK_W_PCIERX3) | BIT(CLK_W_PCIERX4) |
BIT(CLK_W_PCIERX4) | BIT(CLK_W_PCIERX5) |
BIT(CLK_W_PCIERX5) | BIT(CLK_W_ENTROPY) |
BIT(CLK_W_ENTROPY) | BIT(CLK_W_MC1);
BIT(CLK_W_MC1);
// CLK X Devices. // CLK X Devices.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_X) = CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_X) = BIT(CLK_X_MC_CAPA) |
BIT(CLK_X_MC_CAPA) | BIT(CLK_X_MC_CBPA) |
BIT(CLK_X_MC_CBPA) | BIT(CLK_X_MC_CPU) |
BIT(CLK_X_MC_CPU) | BIT(CLK_X_MC_BBC) |
BIT(CLK_X_MC_BBC) | BIT(CLK_X_GPU) |
BIT(CLK_X_GPU) | BIT(CLK_X_DBGAPB) |
BIT(CLK_X_DBGAPB) | BIT(CLK_X_PLLG_REF);
BIT(CLK_X_PLLG_REF);
// CLK Y Devices. // CLK Y Devices.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) = CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) = BIT(CLK_Y_MC_CDPA) |
BIT(CLK_Y_MC_CDPA) | BIT(CLK_Y_MC_CCPA);
BIT(CLK_Y_MC_CCPA);
// Disable clock gate overrides. // Reset clock gate overrides to automatic mode.
CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRA) = 0; CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRA) = 0;
CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRB) = 0; CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRB) = 0;
CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRC) = 0; CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRC) = 0;
@@ -252,10 +265,10 @@ 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) &= ~(BIT(15) | BIT(14)); // 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) | (4 << 29u); // 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) | (4 << 29u); // 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) | (4 << 29u); // Set clock source to PLLP_OUT.
} }
static void _config_se_brom() static void _config_se_brom()
@@ -266,6 +279,9 @@ static void _config_se_brom()
// Try to set SBK from fuses. If patched, skip. // Try to set SBK from fuses. If patched, skip.
fuse_set_sbk(); fuse_set_sbk();
// Make SBK unreadable.
//FUSE(FUSE_PRIVATEKEYDISABLE) = FUSE_PRIVKEY_TZ_STICKY_BIT | FUSE_PRIVKEY_DISABLE;
// Lock SSK (although it's not set and unused anyways). // Lock SSK (although it's not set and unused anyways).
// se_key_acc_ctrl(15, SE_KEY_TBL_DIS_KEYREAD_FLAG); // se_key_acc_ctrl(15, SE_KEY_TBL_DIS_KEYREAD_FLAG);
@@ -365,17 +381,16 @@ void hw_init()
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 might skipped by going through rcm.
_config_se_brom(); _config_se_brom();
//FUSE(FUSE_PRIVATEKEYDISABLE) = 0x11;
// Unset APB2JTAG_OVERRIDE_EN and OBS_OVERRIDE_EN. // Unset APB2JTAG_OVERRIDE_EN and OBS_OVERRIDE_EN.
SYSREG(AHB_AHB_SPARE_REG) &= 0xFFFFFF9F; SYSREG(AHB_AHB_SPARE_REG) &= 0xFFFFFF9F;
PMC(APBDEV_PMC_SCRATCH49) &= 0xFFFFFFFC; PMC(APBDEV_PMC_SCRATCH49) &= 0xFFFFFFFC;
// Perform Memory Built-In Self Test WAR if T210. // Perform the bootloader part of the Memory Built-In Self Test WAR if T210.
if (tegra_t210) if (tegra_t210)
_mbist_workaround(); _mbist_workaround_bl();
// Make sure PLLP_OUT3/4 is set to 408 MHz and enabled. // Make sure PLLP_OUT3/4 is set to 408 MHz and enabled.
CLOCK(CLK_RST_CONTROLLER_PLLP_OUTB) = 0x30003; CLOCK(CLK_RST_CONTROLLER_PLLP_OUTB) = 0x30003;
@@ -422,9 +437,10 @@ void hw_init()
// 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;
// Power on T210B01 shadow TZRAM and lock the reg. // Disable T210B01 TZRAM power-gating and lock the reg.
if (!tegra_t210) if (!tegra_t210)
{ {
// This is not actually needed since it's done by bootrom. The read locks are extra.
PMC(APBDEV_PMC_TZRAM_PWR_CNTRL) &= ~PMC_TZRAM_PWR_CNTRL_SD; PMC(APBDEV_PMC_TZRAM_PWR_CNTRL) &= ~PMC_TZRAM_PWR_CNTRL_SD;
PMC(APBDEV_PMC_TZRAM_NON_SEC_DISABLE) = PMC_TZRAM_DISABLE_REG_WRITE | PMC_TZRAM_DISABLE_REG_READ; PMC(APBDEV_PMC_TZRAM_NON_SEC_DISABLE) = PMC_TZRAM_DISABLE_REG_WRITE | PMC_TZRAM_DISABLE_REG_READ;
PMC(APBDEV_PMC_TZRAM_SEC_DISABLE) = PMC_TZRAM_DISABLE_REG_WRITE | PMC_TZRAM_DISABLE_REG_READ; PMC(APBDEV_PMC_TZRAM_SEC_DISABLE) = PMC_TZRAM_DISABLE_REG_WRITE | PMC_TZRAM_DISABLE_REG_READ;
@@ -482,11 +498,11 @@ void hw_deinit(bool coreboot, u32 bl_magic)
// Reset arbiter. // Reset arbiter.
hw_config_arbiter(true); hw_config_arbiter(true);
// Re-enable clocks to Audio Processing Engine as a workaround to hanging. // Re-enable clocks to Audio Processing Engine as a workaround to rerunning mbist war.
if (tegra_t210) if (tegra_t210)
{ {
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= BIT(CLK_V_AHUB); CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = BIT(CLK_V_AHUB);
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= BIT(CLK_Y_APE); CLOCK(CLK_RST_CONTROLLER_CLK_ENB_Y_SET) = BIT(CLK_Y_APE);
} }
// Do coreboot mitigations. // Do coreboot mitigations.

View File

@@ -99,17 +99,26 @@ void pmc_scratch_lock(pmc_sec_lock_t lock_mask)
} }
} }
int pmc_enable_partition(pmc_power_rail_t part, u32 enable) /*
* !TODO: Non CCPLEX power domains power gating/ungating.
* Power gating: clock should be in reset if enabled and then
* pmc_domain_pwrgate_set is run.
* Power ungating: run pmc_domain_pwrgate_set, enable clocks and keep in
* reset, remove clamping, remove reset, run mbist war if T210 and then clocks
* can be disabled.
*/
int pmc_domain_pwrgate_set(pmc_power_rail_t part, u32 enable)
{ {
u32 part_mask = BIT(part); u32 part_mask = BIT(part);
u32 desired_state = enable << part; u32 desired_state = enable << part;
// Check if the partition has the state we want. // Check if the power domain has the state we want.
if ((PMC(APBDEV_PMC_PWRGATE_STATUS) & part_mask) == desired_state) if ((PMC(APBDEV_PMC_PWRGATE_STATUS) & part_mask) == desired_state)
return 1; return 1;
u32 i = 5001; u32 i = 5001;
while (PMC(APBDEV_PMC_PWRGATE_TOGGLE) & 0x100) while (PMC(APBDEV_PMC_PWRGATE_TOGGLE) & PMC_PWRGATE_TOGGLE_START)
{ {
usleep(1); usleep(1);
i--; i--;
@@ -118,7 +127,7 @@ int pmc_enable_partition(pmc_power_rail_t part, u32 enable)
} }
// Toggle power gating. // Toggle power gating.
PMC(APBDEV_PMC_PWRGATE_TOGGLE) = part | 0x100; PMC(APBDEV_PMC_PWRGATE_TOGGLE) = part | PMC_PWRGATE_TOGGLE_START;
i = 5001; i = 5001;
while (i > 0) while (i > 0)

View File

@@ -37,6 +37,7 @@
#define PMC_CNTRL_SHUTDOWN_OE BIT(22) #define PMC_CNTRL_SHUTDOWN_OE BIT(22)
#define APBDEV_PMC_SEC_DISABLE 0x4 #define APBDEV_PMC_SEC_DISABLE 0x4
#define APBDEV_PMC_PWRGATE_TOGGLE 0x30 #define APBDEV_PMC_PWRGATE_TOGGLE 0x30
#define PMC_PWRGATE_TOGGLE_START BIT(8)
#define APBDEV_PMC_PWRGATE_STATUS 0x38 #define APBDEV_PMC_PWRGATE_STATUS 0x38
#define APBDEV_PMC_NO_IOPOWER 0x44 #define APBDEV_PMC_NO_IOPOWER 0x44
#define PMC_NO_IOPOWER_MEM BIT(7) #define PMC_NO_IOPOWER_MEM BIT(7)
@@ -154,6 +155,8 @@
#define APBDEV_PMC_SCRATCH188 0x810 #define APBDEV_PMC_SCRATCH188 0x810
#define APBDEV_PMC_SCRATCH190 0x818 #define APBDEV_PMC_SCRATCH190 0x818
#define APBDEV_PMC_SCRATCH200 0x840 #define APBDEV_PMC_SCRATCH200 0x840
#define PMC_NX_PANIC_SAFE_MODE 0x20
#define PMC_NX_PANIC_BYPASS_FUSES 0x21
#define APBDEV_PMC_SCRATCH201 0x844 #define APBDEV_PMC_SCRATCH201 0x844
#define APBDEV_PMC_SCRATCH250 0x908 #define APBDEV_PMC_SCRATCH250 0x908
#define APBDEV_PMC_SECURE_SCRATCH108 0xB08 #define APBDEV_PMC_SECURE_SCRATCH108 0xB08
@@ -217,19 +220,14 @@ typedef enum _pmc_sec_lock_t
typedef enum _pmc_power_rail_t typedef enum _pmc_power_rail_t
{ {
POWER_RAIL_CRAIL = 0, POWER_RAIL_CRAIL = 0,
POWER_RAIL_3D0 = 1, POWER_RAIL_VE = 2,
POWER_RAIL_VENC = 2,
POWER_RAIL_PCIE = 3, POWER_RAIL_PCIE = 3,
POWER_RAIL_VDEC = 4, POWER_RAIL_NVENC = 6,
POWER_RAIL_L2C = 5,
POWER_RAIL_MPE = 6,
POWER_RAIL_HEG = 7,
POWER_RAIL_SATA = 8, POWER_RAIL_SATA = 8,
POWER_RAIL_CE1 = 9, POWER_RAIL_CE1 = 9,
POWER_RAIL_CE2 = 10, POWER_RAIL_CE2 = 10,
POWER_RAIL_CE3 = 11, POWER_RAIL_CE3 = 11,
POWER_RAIL_CELP = 12, POWER_RAIL_CELP = 12,
POWER_RAIL_3D1 = 13,
POWER_RAIL_CE0 = 14, POWER_RAIL_CE0 = 14,
POWER_RAIL_C0NC = 15, POWER_RAIL_C0NC = 15,
POWER_RAIL_C1NC = 16, POWER_RAIL_C1NC = 16,
@@ -249,6 +247,6 @@ typedef enum _pmc_power_rail_t
} pmc_power_rail_t; } pmc_power_rail_t;
void pmc_scratch_lock(pmc_sec_lock_t lock_mask); void pmc_scratch_lock(pmc_sec_lock_t lock_mask);
int pmc_enable_partition(pmc_power_rail_t part, u32 enable); int pmc_domain_pwrgate_set(pmc_power_rail_t part, u32 enable);
#endif #endif

View File

@@ -38,6 +38,7 @@
#define SOR1_BASE 0x54580000 #define SOR1_BASE 0x54580000
#define GPU_BASE 0x57000000 #define GPU_BASE 0x57000000
#define GPU_USER_BASE 0x58000000 #define GPU_USER_BASE 0x58000000
#define PG_BASE 0x60000000
#define RES_SEMAPH_BASE 0x60001000 #define RES_SEMAPH_BASE 0x60001000
#define ARB_SEMAPH_BASE 0x60002000 #define ARB_SEMAPH_BASE 0x60002000
#define ARB_PRI_BASE 0x60003000 #define ARB_PRI_BASE 0x60003000
@@ -68,6 +69,8 @@
#define ATOMICS_BASE 0x70016000 #define ATOMICS_BASE 0x70016000
#define MC_BASE 0x70019000 #define MC_BASE 0x70019000
#define EMC_BASE 0x7001B000 #define EMC_BASE 0x7001B000
#define MC0_BASE 0x7001C000
#define MC1_BASE 0x7001D000
#define EMC0_BASE 0x7001E000 #define EMC0_BASE 0x7001E000
#define EMC1_BASE 0x7001F000 #define EMC1_BASE 0x7001F000
#define XUSB_HOST_BASE 0x70090000 #define XUSB_HOST_BASE 0x70090000
@@ -114,6 +117,7 @@
#define SOR1(off) MMIO_REG32(SOR1_BASE, off) #define SOR1(off) MMIO_REG32(SOR1_BASE, off)
#define GPU(off) MMIO_REG32(GPU_BASE, off) #define GPU(off) MMIO_REG32(GPU_BASE, off)
#define GPU_USER(off) MMIO_REG32(GPU_USER_BASE, off) #define GPU_USER(off) MMIO_REG32(GPU_USER_BASE, off)
#define PG(off) MMIO_REG32(PG_BASE, off)
#define ARB_PRI(off) MMIO_REG32(ARB_PRI_BASE, off) #define ARB_PRI(off) MMIO_REG32(ARB_PRI_BASE, off)
#define ICTLR(cidx, off) MMIO_REG32(ICTLR_BASE + (0x100 * (cidx)), off) #define ICTLR(cidx, off) MMIO_REG32(ICTLR_BASE + (0x100 * (cidx)), off)
#define TMR(off) MMIO_REG32(TMR_BASE, off) #define TMR(off) MMIO_REG32(TMR_BASE, off)
@@ -140,6 +144,8 @@
#define SE(off) MMIO_REG32(SE_BASE, off) #define SE(off) MMIO_REG32(SE_BASE, off)
#define MC(off) MMIO_REG32(MC_BASE, off) #define MC(off) MMIO_REG32(MC_BASE, off)
#define EMC(off) MMIO_REG32(EMC_BASE, off) #define EMC(off) MMIO_REG32(EMC_BASE, off)
#define MC_CH0(off) MMIO_REG32(MC0_BASE, off)
#define MC_CH1(off) MMIO_REG32(MC1_BASE, off)
#define EMC_CH0(off) MMIO_REG32(EMC0_BASE, off) #define EMC_CH0(off) MMIO_REG32(EMC0_BASE, off)
#define EMC_CH1(off) MMIO_REG32(EMC1_BASE, off) #define EMC_CH1(off) MMIO_REG32(EMC1_BASE, off)
#define XUSB_HOST(off) MMIO_REG32(XUSB_HOST_BASE, off) #define XUSB_HOST(off) MMIO_REG32(XUSB_HOST_BASE, off)
@@ -297,8 +303,10 @@
#define IPATCH_CAM_ENTRIES 12 #define IPATCH_CAM_ENTRIES 12
/*! I2S registers. */ /*! I2S registers. */
#define I2S1_CG 0x88 #define I2S_CG 0x88
#define I2S1_CTRL 0xA0 #define I2S_CTRL 0xA0
#define I2S1_CG I2S_CG
#define I2S1_CTRL I2S_CTRL
#define I2S2_CG 0x188 #define I2S2_CG 0x188
#define I2S2_CTRL 0x1A0 #define I2S2_CTRL 0x1A0
#define I2S3_CG 0x288 #define I2S3_CG 0x288
@@ -307,8 +315,9 @@
#define I2S4_CTRL 0x3A0 #define I2S4_CTRL 0x3A0
#define I2S5_CG 0x488 #define I2S5_CG 0x488
#define I2S5_CTRL 0x4A0 #define I2S5_CTRL 0x4A0
#define I2S_CG_SLCG_ENABLE BIT(0) #define I2S_CG_SLCG_DISABLE 0
#define I2S_CTRL_MASTER_EN BIT(10) #define I2S_CG_SLCG_ENABLE BIT(0)
#define I2S_CTRL_MASTER_EN BIT(10)
/*! PWM registers. */ /*! PWM registers. */
#define PWM_CONTROLLER_PWM_CSR_0 0x00 #define PWM_CONTROLLER_PWM_CSR_0 0x00
@@ -318,7 +327,6 @@
/*! Special registers. */ /*! Special registers. */
#define EMC_SCRATCH0 0x324 #define EMC_SCRATCH0 0x324
#define EMC_HEKA_UPD BIT(30) #define EMC_HEKA_UPD BIT(30)
#define EMC_SEPT_RUN BIT(31)
/*! Flow controller registers. */ /*! Flow controller registers. */
#define FLOW_CTLR_HALT_COP_EVENTS 0x4 #define FLOW_CTLR_HALT_COP_EVENTS 0x4
@@ -377,4 +385,12 @@
#define NVDEC_SA_KEYSLOT_OTF 0x210C #define NVDEC_SA_KEYSLOT_OTF 0x210C
#define NVDEC_SA_KEYSLOT_GLOBAL_RW 0x2118 #define NVDEC_SA_KEYSLOT_GLOBAL_RW 0x2118
#define NVDEC_VPR_ALL_OTF_GOTO_VPR 0x211C #define NVDEC_VPR_ALL_OTF_GOTO_VPR 0x211C
/* PG registers */
#define PG_UP_TAG 0x0 // Changes depending on what does the reg read request.
#define TAG_PID_CCPLEX 0x55555555
#define TAG_PID_BPMP 0xAAAAAAAA
#define TAG_PID_COP2 0x99999999
#define TAG_PID_OTHER 0xCCCCCCCC
#endif #endif

454
bdk/storage/mmc_def.h Normal file
View File

@@ -0,0 +1,454 @@
/*
* Header for MultiMediaCard (MMC)
*
* Copyright 2002 Hewlett-Packard Company
* Copyright 2018-2021 CTCaer
*
* Use consistent with the GNU GPL is permitted,
* provided that this copyright notice is
* preserved in its entirety in all copies and derived works.
*
* HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
* AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
* FITNESS FOR ANY PARTICULAR PURPOSE.
*
* Many thanks to Alessandro Rubini and Jonathan Corbet!
*
* Based strongly on code by:
*
* Author: Yong-iL Joh <tolkien@mizi.com>
*
* Author: Andrew Christian
* 15 May 2002
*/
#ifndef MMC_H
#define MMC_H
/* Standard MMC commands (4.1) type argument response */
/* class 1 */
#define MMC_GO_IDLE_STATE 0 /* bc */
#define MMC_SEND_OP_COND 1 /* bcr [31:0] OCR R3 */
#define MMC_ALL_SEND_CID 2 /* bcr R2 */
#define MMC_SET_RELATIVE_ADDR 3 /* ac [31:16] RCA R1 */
#define MMC_SET_DSR 4 /* bc [31:16] RCA */
#define MMC_SLEEP_AWAKE 5 /* ac [31:16] RCA 15:flg R1b */
#define MMC_SWITCH 6 /* ac [31:0] See below R1b */
#define MMC_SELECT_CARD 7 /* ac [31:16] RCA R1 */
#define MMC_SEND_EXT_CSD 8 /* adtc R1 */
#define MMC_SEND_CSD 9 /* ac [31:16] RCA R2 */
#define MMC_SEND_CID 10 /* ac [31:16] RCA R2 */
#define MMC_READ_DAT_UNTIL_STOP 11 /* adtc [31:0] dadr R1 */
#define MMC_STOP_TRANSMISSION 12 /* ac R1b */
#define MMC_SEND_STATUS 13 /* ac [31:16] RCA R1 */
#define MMC_BUS_TEST_R 14 /* adtc R1 */
#define MMC_GO_INACTIVE_STATE 15 /* ac [31:16] RCA */
#define MMC_BUS_TEST_W 19 /* adtc R1 */
#define MMC_SPI_READ_OCR 58 /* spi spi_R3 */
#define MMC_SPI_CRC_ON_OFF 59 /* spi [0:0] flag spi_R1 */
/* class 2 */
#define MMC_SET_BLOCKLEN 16 /* ac [31:0] block len R1 */
#define MMC_READ_SINGLE_BLOCK 17 /* adtc [31:0] data addr R1 */
#define MMC_READ_MULTIPLE_BLOCK 18 /* adtc [31:0] data addr R1 */
#define MMC_SEND_TUNING_BLOCK 19 /* adtc R1 */
#define MMC_SEND_TUNING_BLOCK_HS200 21 /* adtc R1 */
/* class 3 */
#define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1 */
/* class 4 */
#define MMC_SET_BLOCK_COUNT 23 /* adtc [31:0] data addr R1 */
#define MMC_WRITE_BLOCK 24 /* adtc [31:0] data addr R1 */
#define MMC_WRITE_MULTIPLE_BLOCK 25 /* adtc R1 */
#define MMC_PROGRAM_CID 26 /* adtc R1 */
#define MMC_PROGRAM_CSD 27 /* adtc R1 */
/* class 6 */
#define MMC_SET_WRITE_PROT 28 /* ac [31:0] data addr R1b */
#define MMC_CLR_WRITE_PROT 29 /* ac [31:0] data addr R1b */
#define MMC_SEND_WRITE_PROT 30 /* adtc [31:0] wpdata addr R1 */
/* class 5 */
#define MMC_ERASE_GROUP_START 35 /* ac [31:0] data addr R1 */
#define MMC_ERASE_GROUP_END 36 /* ac [31:0] data addr R1 */
#define MMC_ERASE 38 /* ac R1b */
/* class 9 */
#define MMC_FAST_IO 39 /* ac <Complex> R4 */
#define MMC_GO_IRQ_STATE 40 /* bcr R5 */
/* class 7 */
#define MMC_LOCK_UNLOCK 42 /* adtc R1b */
/* class 8 */
#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */
#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */
#define MMC_VENDOR_60_CMD 60 /* Vendor Defined */
#define MMC_VENDOR_61_CMD 61 /* Vendor Defined */
#define MMC_VENDOR_62_CMD 62 /* Vendor Defined */
#define MMC_VENDOR_63_CMD 63 /* Vendor Defined */
/* class 11 */
#define MMC_QUE_TASK_PARAMS 44 /* ac [20:16] task id R1 */
#define MMC_QUE_TASK_ADDR 45 /* ac [31:0] data addr R1 */
#define MMC_EXECUTE_READ_TASK 46 /* adtc [20:16] task id R1 */
#define MMC_EXECUTE_WRITE_TASK 47 /* adtc [20:16] task id R1 */
#define MMC_CMDQ_TASK_MGMT 48 /* ac [20:16] task id R1b */
/*
* MMC_SWITCH argument format:
*
* [31:26] Always 0
* [25:24] Access Mode
* [23:16] Location of target Byte in EXT_CSD
* [15:08] Value Byte
* [07:03] Always 0
* [02:00] Command Set
*/
/*
* MMC status in R1, for native mode (SPI bits are different)
* Type
* e : error bit
* s : status bit
* r : detected and set for the actual command response
* x : detected and set during command execution. the host must poll
* the card by sending status command in order to read these bits.
* Clear condition
* a : according to the card state
* b : always related to the previous command. Reception of a valid
* command will clear it (with a delay of one command)
* c : clear by read
*/
#define R1_OUT_OF_RANGE (1 << 31) /* er, c */
#define R1_ADDRESS_ERROR (1 << 30) /* erx, c */
#define R1_BLOCK_LEN_ERROR (1 << 29) /* er, c */
#define R1_ERASE_SEQ_ERROR (1 << 28) /* er, c */
#define R1_ERASE_PARAM (1 << 27) /* ex, c */
#define R1_WP_VIOLATION (1 << 26) /* erx, c */
#define R1_CARD_IS_LOCKED (1 << 25) /* sx, a */
#define R1_LOCK_UNLOCK_FAILED (1 << 24) /* erx, c */
#define R1_COM_CRC_ERROR (1 << 23) /* er, b */
#define R1_ILLEGAL_COMMAND (1 << 22) /* er, b */
#define R1_CARD_ECC_FAILED (1 << 21) /* ex, c */
#define R1_CC_ERROR (1 << 20) /* erx, c */
#define R1_ERROR (1 << 19) /* erx, c */
#define R1_UNDERRUN (1 << 18) /* ex, c */
#define R1_OVERRUN (1 << 17) /* ex, c */
#define R1_CID_CSD_OVERWRITE (1 << 16) /* erx, c, CID/CSD overwrite */
#define R1_WP_ERASE_SKIP (1 << 15) /* sx, c */
#define R1_CARD_ECC_DISABLED (1 << 14) /* sx, a */
#define R1_ERASE_RESET (1 << 13) /* sr, c */
#define R1_STATUS(x) ((x) & 0xFFFFE000)
#define R1_CURRENT_STATE(x) (((x) & 0x00001E00) >> 9) /* sx, b (4 bits) */
#define R1_READY_FOR_DATA (1 << 8) /* sx, a */
#define R1_SWITCH_ERROR (1 << 7) /* sx, c */
#define R1_EXCEPTION_EVENT (1 << 6) /* sr, a */
#define R1_APP_CMD (1 << 5) /* sr, c */
#define R1_SKIP_STATE_CHECK (1 << 4) /* Custom state to skip expected state check */
#define R1_AKE_SEQ_ERROR (1 << 3)
/* R1_CURRENT_STATE 12:9 */
#define R1_STATE(x) ((x) << 9)
#define R1_STATE_IDLE 0
#define R1_STATE_READY 1
#define R1_STATE_IDENT 2
#define R1_STATE_STBY 3
#define R1_STATE_TRAN 4
#define R1_STATE_DATA 5
#define R1_STATE_RCV 6
#define R1_STATE_PRG 7
#define R1_STATE_DIS 8
/*
* MMC/SD in SPI mode reports R1 status always, and R2 for SEND_STATUS
* R1 is the low order byte; R2 is the next highest byte, when present.
*/
#define R1_SPI_IDLE (1 << 0)
#define R1_SPI_ERASE_RESET (1 << 1)
#define R1_SPI_ILLEGAL_COMMAND (1 << 2)
#define R1_SPI_COM_CRC (1 << 3)
#define R1_SPI_ERASE_SEQ (1 << 4)
#define R1_SPI_ADDRESS (1 << 5)
#define R1_SPI_PARAMETER (1 << 6)
/* R1 bit 7 is always zero */
#define R2_SPI_CARD_LOCKED (1 << 8)
#define R2_SPI_WP_ERASE_SKIP (1 << 9) /* or lock/unlock fail */
#define R2_SPI_LOCK_UNLOCK_FAIL R2_SPI_WP_ERASE_SKIP
#define R2_SPI_ERROR (1 << 10)
#define R2_SPI_CC_ERROR (1 << 11)
#define R2_SPI_CARD_ECC_ERROR (1 << 12)
#define R2_SPI_WP_VIOLATION (1 << 13)
#define R2_SPI_ERASE_PARAM (1 << 14)
#define R2_SPI_OUT_OF_RANGE (1 << 15) /* or CSD overwrite */
#define R2_SPI_CSD_OVERWRITE R2_SPI_OUT_OF_RANGE
/*
* OCR bits are mostly in host.h
*/
#define MMC_CARD_VDD_18 (1 << 7) /* Card VDD voltage 1.8 */
#define MMC_CARD_VDD_27_34 (0x7F << 15) /* Card VDD voltage 2.7 ~ 3.4 */
#define MMC_CARD_CCS (1 << 30) /* Card Capacity status bit */
#define MMC_CARD_BUSY (1 << 31) /* Card Power up status bit */
/*
* Card Command Classes (CCC)
*/
#define CCC_BASIC (1<<0) /* (0) Basic protocol functions */
/* (CMD0,1,2,3,4,7,9,10,12,13,15) */
/* (and for SPI, CMD58,59) */
#define CCC_STREAM_READ (1<<1) /* (1) Stream read commands */
/* (CMD11) */
#define CCC_BLOCK_READ (1<<2) /* (2) Block read commands */
/* (CMD16,17,18) */
#define CCC_STREAM_WRITE (1<<3) /* (3) Stream write commands */
/* (CMD20) */
#define CCC_BLOCK_WRITE (1<<4) /* (4) Block write commands */
/* (CMD16,24,25,26,27) */
#define CCC_ERASE (1<<5) /* (5) Ability to erase blocks */
/* (CMD32,33,34,35,36,37,38,39) */
#define CCC_WRITE_PROT (1<<6) /* (6) Able to write protect blocks */
/* (CMD28,29,30) */
#define CCC_LOCK_CARD (1<<7) /* (7) Able to lock down card */
/* (CMD16,CMD42) */
#define CCC_APP_SPEC (1<<8) /* (8) Application specific */
/* (CMD55,56,57,ACMD*) */
#define CCC_IO_MODE (1<<9) /* (9) I/O mode */
/* (CMD5,39,40,52,53) */
#define CCC_SWITCH (1<<10) /* (10) High speed switch */
/* (CMD6,34,35,36,37,50) */
/* (11) Reserved */
/* (CMD?) */
/*
* CSD field definitions
*/
#define CSD_STRUCT_VER_1_0 0 /* Valid for system specification 1.0 - 1.2 */
#define CSD_STRUCT_VER_1_1 1 /* Valid for system specification 1.4 - 2.2 */
#define CSD_STRUCT_VER_1_2 2 /* Valid for system specification 3.1 - 3.2 - 3.31 - 4.0 - 4.1 */
#define CSD_STRUCT_EXT_CSD 3 /* Version is coded in CSD_STRUCTURE in EXT_CSD */
#define CSD_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.2 */
#define CSD_SPEC_VER_1 1 /* Implements system specification 1.4 */
#define CSD_SPEC_VER_2 2 /* Implements system specification 2.0 - 2.2 */
#define CSD_SPEC_VER_3 3 /* Implements system specification 3.1 - 3.2 - 3.31 */
#define CSD_SPEC_VER_4 4 /* Implements system specification 4.0 - 4.1 */
/*
* EXT_CSD fields
*/
#define EXT_CSD_CMDQ_MODE_EN 15 /* R/W */
#define EXT_CSD_FLUSH_CACHE 32 /* W */
#define EXT_CSD_CACHE_CTRL 33 /* R/W */
#define EXT_CSD_POWER_OFF_NOTIFICATION 34 /* R/W */
#define EXT_CSD_PACKED_FAILURE_INDEX 35 /* RO */
#define EXT_CSD_PACKED_CMD_STATUS 36 /* RO */
#define EXT_CSD_EXP_EVENTS_STATUS 54 /* RO, 2 bytes */
#define EXT_CSD_EXP_EVENTS_CTRL 56 /* R/W, 2 bytes */
#define EXT_CSD_DATA_SECTOR_SIZE 61 /* R */
#define EXT_CSD_GP_SIZE_MULT 143 /* R/W */
#define EXT_CSD_PARTITION_SETTING_COMPLETED 155 /* R/W */
#define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */
#define EXT_CSD_MAX_ENH_SIZE_MULT 157 /* RO, 3 bytes */
#define EXT_CSD_PARTITION_SUPPORT 160 /* RO */
#define EXT_CSD_HPI_MGMT 161 /* R/W */
#define EXT_CSD_RST_N_FUNCTION 162 /* R/W */
#define EXT_CSD_BKOPS_EN 163 /* R/W */
#define EXT_CSD_BKOPS_START 164 /* W */
#define EXT_CSD_SANITIZE_START 165 /* W */
#define EXT_CSD_WR_REL_PARAM 166 /* RO */
#define EXT_CSD_RPMB_MULT 168 /* RO */
#define EXT_CSD_FW_CONFIG 169 /* R/W */
#define EXT_CSD_BOOT_WP 173 /* R/W */
#define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */
#define EXT_CSD_PART_CONFIG 179 /* R/W */
#define EXT_CSD_ERASED_MEM_CONT 181 /* RO */
#define EXT_CSD_BUS_WIDTH 183 /* R/W */
#define EXT_CSD_STROBE_SUPPORT 184 /* RO */
#define EXT_CSD_HS_TIMING 185 /* R/W */
#define EXT_CSD_POWER_CLASS 187 /* R/W */
#define EXT_CSD_REV 192 /* RO */
#define EXT_CSD_STRUCTURE 194 /* RO */
#define EXT_CSD_CARD_TYPE 196 /* RO */
#define EXT_CSD_DRIVER_STRENGTH 197 /* RO */
#define EXT_CSD_OUT_OF_INTERRUPT_TIME 198 /* RO */
#define EXT_CSD_PART_SWITCH_TIME 199 /* RO */
#define EXT_CSD_PWR_CL_52_195 200 /* RO */
#define EXT_CSD_PWR_CL_26_195 201 /* RO */
#define EXT_CSD_PWR_CL_52_360 202 /* RO */
#define EXT_CSD_PWR_CL_26_360 203 /* RO */
#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */
#define EXT_CSD_S_A_TIMEOUT 217 /* RO */
#define EXT_CSD_REL_WR_SEC_C 222 /* RO */
#define EXT_CSD_HC_WP_GRP_SIZE 221 /* RO */
#define EXT_CSD_ERASE_TIMEOUT_MULT 223 /* RO */
#define EXT_CSD_HC_ERASE_GRP_SIZE 224 /* RO */
#define EXT_CSD_BOOT_MULT 226 /* RO */
#define EXT_CSD_SEC_TRIM_MULT 229 /* RO */
#define EXT_CSD_SEC_ERASE_MULT 230 /* RO */
#define EXT_CSD_SEC_FEATURE_SUPPORT 231 /* RO */
#define EXT_CSD_TRIM_MULT 232 /* RO */
#define EXT_CSD_PWR_CL_200_195 236 /* RO */
#define EXT_CSD_PWR_CL_200_360 237 /* RO */
#define EXT_CSD_PWR_CL_DDR_52_195 238 /* RO */
#define EXT_CSD_PWR_CL_DDR_52_360 239 /* RO */
#define EXT_CSD_BKOPS_STATUS 246 /* RO */
#define EXT_CSD_POWER_OFF_LONG_TIME 247 /* RO */
#define EXT_CSD_GENERIC_CMD6_TIME 248 /* RO */
#define EXT_CSD_CACHE_SIZE 249 /* RO, 4 bytes */
#define EXT_CSD_PWR_CL_DDR_200_360 253 /* RO */
#define EXT_CSD_FIRMWARE_VERSION 254 /* RO, 8 bytes */
#define EXT_CSD_DEVICE_VERSION 262 /* RO, 2 bytes */
#define EXT_CSD_PRE_EOL_INFO 267 /* RO */
#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A 268 /* RO */
#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B 269 /* RO */
#define EXT_CSD_CMDQ_DEPTH 307 /* RO */
#define EXT_CSD_CMDQ_SUPPORT 308 /* RO */
#define EXT_CSD_SUPPORTED_MODE 493 /* RO */
#define EXT_CSD_TAG_UNIT_SIZE 498 /* RO */
#define EXT_CSD_DATA_TAG_SUPPORT 499 /* RO */
#define EXT_CSD_MAX_PACKED_WRITES 500 /* RO */
#define EXT_CSD_MAX_PACKED_READS 501 /* RO */
#define EXT_CSD_BKOPS_SUPPORT 502 /* RO */
#define EXT_CSD_HPI_FEATURES 503 /* RO */
/*
* EXT_CSD field definitions
*/
#define EXT_CSD_WR_REL_PARAM_EN (1<<2)
#define EXT_CSD_BOOT_WP_B_PWR_WP_DIS (0x40)
#define EXT_CSD_BOOT_WP_B_PERM_WP_DIS (0x10)
#define EXT_CSD_BOOT_WP_B_PERM_WP_EN (0x04)
#define EXT_CSD_BOOT_WP_B_PWR_WP_EN (0x01)
#define EXT_CSD_PART_CONFIG_ACC_MASK (0x7)
#define EXT_CSD_PART_CONFIG_ACC_BOOT0 (0x1)
#define EXT_CSD_PART_CONFIG_ACC_RPMB (0x3)
#define EXT_CSD_PART_CONFIG_ACC_GP0 (0x4)
#define EXT_CSD_PART_SETTING_COMPLETED (0x1)
#define EXT_CSD_PART_SUPPORT_PART_EN (0x1)
#define EXT_CSD_CMD_SET_NORMAL (1<<0)
#define EXT_CSD_CMD_SET_SECURE (1<<1)
#define EXT_CSD_CMD_SET_CPSECURE (1<<2)
#define EXT_CSD_CARD_TYPE_HS_26 (1<<0) /* Card can run at 26MHz */
#define EXT_CSD_CARD_TYPE_HS_52 (1<<1) /* Card can run at 52MHz */
#define EXT_CSD_CARD_TYPE_HS (EXT_CSD_CARD_TYPE_HS_26 | \
EXT_CSD_CARD_TYPE_HS_52)
#define EXT_CSD_CARD_TYPE_DDR_1_8V (1<<2) /* Card can run at 52MHz */
/* DDR mode @1.8V or 3V I/O */
#define EXT_CSD_CARD_TYPE_DDR_1_2V (1<<3) /* Card can run at 52MHz */
/* DDR mode @1.2V I/O */
#define EXT_CSD_CARD_TYPE_DDR_52 (EXT_CSD_CARD_TYPE_DDR_1_8V \
| EXT_CSD_CARD_TYPE_DDR_1_2V)
#define EXT_CSD_CARD_TYPE_HS200_1_8V (1<<4) /* Card can run at 200MHz */
#define EXT_CSD_CARD_TYPE_HS200_1_2V (1<<5) /* Card can run at 200MHz */
/* SDR mode @1.2V I/O */
#define EXT_CSD_CARD_TYPE_HS200 (EXT_CSD_CARD_TYPE_HS200_1_8V | \
EXT_CSD_CARD_TYPE_HS200_1_2V)
#define EXT_CSD_CARD_TYPE_HS400_1_8V (1<<6) /* Card can run at 200MHz DDR, 1.8V */
#define EXT_CSD_CARD_TYPE_HS400_1_2V (1<<7) /* Card can run at 200MHz DDR, 1.2V */
#define EXT_CSD_CARD_TYPE_HS400 (EXT_CSD_CARD_TYPE_HS400_1_8V | \
EXT_CSD_CARD_TYPE_HS400_1_2V)
#define EXT_CSD_CARD_TYPE_HS400ES (1<<8) /* Card can run at HS400ES */
#define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */
#define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */
#define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */
#define EXT_CSD_DDR_BUS_WIDTH_4 5 /* Card is in 4 bit DDR mode */
#define EXT_CSD_DDR_BUS_WIDTH_8 6 /* Card is in 8 bit DDR mode */
#define EXT_CSD_BUS_WIDTH_STROBE (1<<7) /* Enhanced strobe mode */
#define EXT_CSD_TIMING_BC 0 /* Backwards compatility */
#define EXT_CSD_TIMING_HS 1 /* High speed */
#define EXT_CSD_TIMING_HS200 2 /* HS200 */
#define EXT_CSD_TIMING_HS400 3 /* HS400 */
#define EXT_CSD_DRV_STR_SHIFT 4 /* Driver Strength shift */
#define EXT_CSD_SEC_ER_EN (1<<0)
#define EXT_CSD_SEC_BD_BLK_EN (1<<2)
#define EXT_CSD_SEC_GB_CL_EN (1<<4)
#define EXT_CSD_SEC_SANITIZE (1<<6) /* v4.5 only */
#define EXT_CSD_RST_N_EN_MASK 0x3
#define EXT_CSD_RST_N_ENABLED 1 /* RST_n is enabled on card */
#define EXT_CSD_NO_POWER_NOTIFICATION 0
#define EXT_CSD_POWER_ON 1
#define EXT_CSD_POWER_OFF_SHORT 2
#define EXT_CSD_POWER_OFF_LONG 3
#define EXT_CSD_PWR_CL_8BIT_MASK 0xF0 /* 8 bit PWR CLS */
#define EXT_CSD_PWR_CL_4BIT_MASK 0x0F /* 8 bit PWR CLS */
#define EXT_CSD_PWR_CL_8BIT_SHIFT 4
#define EXT_CSD_PWR_CL_4BIT_SHIFT 0
#define EXT_CSD_PACKED_EVENT_EN (1<<3)
/*
* EXCEPTION_EVENT_STATUS field
*/
#define EXT_CSD_URGENT_BKOPS (1<<0)
#define EXT_CSD_DYNCAP_NEEDED (1<<1)
#define EXT_CSD_SYSPOOL_EXHAUSTED (1<<2)
#define EXT_CSD_PACKED_FAILURE (1<<3)
#define EXT_CSD_PACKED_GENERIC_ERROR (1<<0)
#define EXT_CSD_PACKED_INDEXED_ERROR (1<<1)
/*
* BKOPS status level
*/
#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
*/
#define EXT_CSD_MANUAL_BKOPS_MASK 0x01
#define EXT_CSD_AUTO_BKOPS_MASK 0x02
/*
* Command Queue
*/
#define EXT_CSD_CMDQ_MODE_ENABLED (1<<0)
#define EXT_CSD_CMDQ_DEPTH_MASK 0x1F
#define EXT_CSD_CMDQ_SUPPORTED (1<<0)
/*
* MMC_SWITCH access modes
*/
#define MMC_SWITCH_MODE_CMD_SET 0x00 /* Change the command set */
#define MMC_SWITCH_MODE_SET_BITS 0x01 /* Set bits which are 1 in value */
#define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits which are 1 in value */
#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */
/*
* Erase/trim/discard
*/
#define MMC_ERASE_ARG 0x00000000
#define MMC_SECURE_ERASE_ARG 0x80000000
#define MMC_TRIM_ARG 0x00000001
#define MMC_DISCARD_ARG 0x00000003
#define MMC_SECURE_TRIM1_ARG 0x80000001
#define MMC_SECURE_TRIM2_ARG 0x80008000
#define MMC_SECURE_ARGS 0x80000000
#define MMC_TRIM_ARGS 0x00008001
/*
* Vendor definitions and structs
*/
#define MMC_SANDISK_HEALTH_REPORT 0x96C9D71C
#endif /* MMC_H */

View File

@@ -21,6 +21,8 @@
#include <storage/emmc.h> #include <storage/emmc.h>
#include <storage/sdmmc.h> #include <storage/sdmmc.h>
#define NAND_PATROL_SECTOR 0xC20
typedef struct _nx_emmc_cal0_spk_t typedef struct _nx_emmc_cal0_spk_t
{ {
u16 unk0; u16 unk0;
@@ -65,13 +67,18 @@ typedef struct _nx_emmc_cal0_spk_t
typedef struct _nx_emmc_cal0_t typedef struct _nx_emmc_cal0_t
{ {
// Header.
u32 magic; // 'CAL0'. u32 magic; // 'CAL0'.
u32 version; u32 version;
u32 body_size; u32 body_size;
u16 model; u16 model;
u16 update_cnt; u16 update_cnt;
u8 pad_crc16_0[0x10]; u8 pad_crc16_hdr[0x10];
// SHA256 for body.
u8 body_sha256[0x20]; u8 body_sha256[0x20];
// Body.
char cfg_id1[0x1E]; char cfg_id1[0x1E];
u8 crc16_pad1[2]; u8 crc16_pad1[2];
u8 rsvd0[0x20]; u8 rsvd0[0x20];
@@ -225,6 +232,7 @@ typedef struct _nx_emmc_cal0_t
// 10.0.0 and up. // 10.0.0 and up.
u8 console_6axis_sensor_mount_type; u8 console_6axis_sensor_mount_type;
u8 crc16_pad61[0xF];
} __attribute__((packed)) nx_emmc_cal0_t; } __attribute__((packed)) nx_emmc_cal0_t;
int nx_emmc_bis_read(u32 sector, u32 count, void *buff); int nx_emmc_bis_read(u32 sector, u32 count, void *buff);

View File

@@ -44,7 +44,7 @@ int ram_disk_init(void *ram_fs, u32 ramdisk_size)
disk_set_info(DRIVE_RAM, SET_SECTOR_COUNT, &ramdisk_size); disk_set_info(DRIVE_RAM, SET_SECTOR_COUNT, &ramdisk_size);
// Unmount ramdisk. // Unmount ramdisk.
f_mount(NULL, "ram:", 1); f_unmount("ram:");
// Format as exFAT w/ 32KB cluster with no MBR. // Format as exFAT w/ 32KB cluster with no MBR.
res = f_mkfs("ram:", FM_EXFAT | FM_SFD, RAMDISK_CLUSTER_SZ, buf, 0x400000); res = f_mkfs("ram:", FM_EXFAT | FM_SFD, RAMDISK_CLUSTER_SZ, buf, 0x400000);

View File

@@ -227,7 +227,7 @@ static void _sd_deinit(bool deinit)
if (sd_init_done) if (sd_init_done)
{ {
if (sd_mounted) if (sd_mounted)
f_mount(NULL, "0:", 1); // Volume 0 is SD. f_unmount("0:"); // Volume 0 is SD.
if (deinit) if (deinit)
{ {

View File

@@ -22,10 +22,9 @@
#include <soc/timer.h> #include <soc/timer.h>
#include <storage/emmc.h> #include <storage/emmc.h>
#include <storage/sdmmc.h> #include <storage/sdmmc.h>
#include <storage/mmc.h> #include <storage/mmc_def.h>
#include <storage/sd.h> #include <storage/sd.h>
#include <storage/sd_def.h> #include <storage/sd_def.h>
#include <mem/mc.h>
#include <memory_map.h> #include <memory_map.h>
#include <gfx_utils.h> #include <gfx_utils.h>
@@ -972,7 +971,7 @@ static int _sd_storage_send_if_cond(sdmmc_storage_t *storage, bool *is_sdsc)
{ {
sdmmc_cmd_t cmdbuf; sdmmc_cmd_t cmdbuf;
u16 vhd_pattern = SD_VHS_27_36 | 0xAA; u16 vhd_pattern = SD_VHS_27_36 | 0xAA;
sdmmc_init_cmd(&cmdbuf, SD_SEND_IF_COND, vhd_pattern, SDMMC_RSP_TYPE_5, 0); sdmmc_init_cmd(&cmdbuf, SD_SEND_IF_COND, vhd_pattern, SDMMC_RSP_TYPE_7, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
{ {
// The SD Card is version 1.X (SDSC) if there is no response. // The SD Card is version 1.X (SDSC) if there is no response.
@@ -987,7 +986,7 @@ static int _sd_storage_send_if_cond(sdmmc_storage_t *storage, bool *is_sdsc)
// For Card version >= 2.0, parse results. // For Card version >= 2.0, parse results.
u32 resp = 0; u32 resp = 0;
sdmmc_get_cached_rsp(storage->sdmmc, &resp, SDMMC_RSP_TYPE_5); sdmmc_get_cached_rsp(storage->sdmmc, &resp, SDMMC_RSP_TYPE_7);
// Check if VHD was accepted and pattern was properly returned. // Check if VHD was accepted and pattern was properly returned.
if ((resp & 0xFFF) == vhd_pattern) if ((resp & 0xFFF) == vhd_pattern)
@@ -1070,7 +1069,7 @@ static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, bool is_sdsc, int b
static int _sd_storage_get_rca(sdmmc_storage_t *storage) static int _sd_storage_get_rca(sdmmc_storage_t *storage)
{ {
sdmmc_cmd_t cmdbuf; sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmdbuf, SD_SEND_RELATIVE_ADDR, 0, SDMMC_RSP_TYPE_4, 0); sdmmc_init_cmd(&cmdbuf, SD_SEND_RELATIVE_ADDR, 0, SDMMC_RSP_TYPE_6, 0);
u32 timeout = get_tmr_ms() + 1500; u32 timeout = get_tmr_ms() + 1500;
@@ -1080,7 +1079,7 @@ static int _sd_storage_get_rca(sdmmc_storage_t *storage)
break; break;
u32 resp = 0; u32 resp = 0;
if (!sdmmc_get_cached_rsp(storage->sdmmc, &resp, SDMMC_RSP_TYPE_4)) if (!sdmmc_get_cached_rsp(storage->sdmmc, &resp, SDMMC_RSP_TYPE_6))
break; break;
if (resp >> 16) if (resp >> 16)

View File

@@ -17,7 +17,7 @@
#include <string.h> #include <string.h>
#include <storage/mmc.h> #include <storage/mmc_def.h>
#include <storage/sdmmc.h> #include <storage/sdmmc.h>
#include <gfx_utils.h> #include <gfx_utils.h>
#include <power/max7762x.h> #include <power/max7762x.h>
@@ -115,7 +115,7 @@ static int _sdmmc_config_tap_val(sdmmc_t *sdmmc, u32 type)
u32 tap_val = 0; u32 tap_val = 0;
if (type == SDHCI_TIMING_MMC_HS400) if (type == SDHCI_TIMING_MMC_HS400)
sdmmc->regs->vencapover = (sdmmc->regs->vencapover & 0xFFFFC0FF) | (dqs_trim_val << 8); sdmmc->regs->vencapover = (sdmmc->regs->vencapover & ~0x3F00) | (dqs_trim_val << 8);
sdmmc->regs->ventunctl0 &= ~SDHCI_TEGRA_TUNING_TAP_HW_UPDATED; sdmmc->regs->ventunctl0 &= ~SDHCI_TEGRA_TUNING_TAP_HW_UPDATED;
@@ -129,7 +129,7 @@ static int _sdmmc_config_tap_val(sdmmc_t *sdmmc, u32 type)
else else
tap_val = sdmmc->t210b01 ? 11 : tap_values_t210[sdmmc->id]; tap_val = sdmmc->t210b01 ? 11 : tap_values_t210[sdmmc->id];
sdmmc->regs->venclkctl = (sdmmc->regs->venclkctl & 0xFF00FFFF) | (tap_val << 16); sdmmc->regs->venclkctl = (sdmmc->regs->venclkctl & ~0xFF0000) | (tap_val << 16);
return 1; return 1;
} }
@@ -437,8 +437,8 @@ static int _sdmmc_cache_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 type)
{ {
case SDMMC_RSP_TYPE_1: case SDMMC_RSP_TYPE_1:
case SDMMC_RSP_TYPE_3: case SDMMC_RSP_TYPE_3:
case SDMMC_RSP_TYPE_4: case SDMMC_RSP_TYPE_6:
case SDMMC_RSP_TYPE_5: case SDMMC_RSP_TYPE_7:
rsp[0] = sdmmc->regs->rspreg[0]; rsp[0] = sdmmc->regs->rspreg[0];
break; break;
@@ -470,8 +470,8 @@ int sdmmc_get_cached_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 type)
{ {
case SDMMC_RSP_TYPE_1: case SDMMC_RSP_TYPE_1:
case SDMMC_RSP_TYPE_3: case SDMMC_RSP_TYPE_3:
case SDMMC_RSP_TYPE_4: case SDMMC_RSP_TYPE_6:
case SDMMC_RSP_TYPE_5: case SDMMC_RSP_TYPE_7:
rsp[0] = sdmmc->rsp[0]; rsp[0] = sdmmc->rsp[0];
break; break;
@@ -560,8 +560,8 @@ static int _sdmmc_send_cmd(sdmmc_t *sdmmc, const sdmmc_cmd_t *cmd, bool is_data_
break; break;
case SDMMC_RSP_TYPE_1: case SDMMC_RSP_TYPE_1:
case SDMMC_RSP_TYPE_4: case SDMMC_RSP_TYPE_6:
case SDMMC_RSP_TYPE_5: case SDMMC_RSP_TYPE_7:
if (cmd->check_busy) if (cmd->check_busy)
cmdflags = SDHCI_CMD_RESP_LEN48_BUSY | SDHCI_CMD_INDEX | SDHCI_CMD_CRC; cmdflags = SDHCI_CMD_RESP_LEN48_BUSY | SDHCI_CMD_INDEX | SDHCI_CMD_CRC;
else else

View File

@@ -37,8 +37,8 @@
#define SDMMC_RSP_TYPE_1 1 #define SDMMC_RSP_TYPE_1 1
#define SDMMC_RSP_TYPE_2 2 #define SDMMC_RSP_TYPE_2 2
#define SDMMC_RSP_TYPE_3 3 #define SDMMC_RSP_TYPE_3 3
#define SDMMC_RSP_TYPE_4 4 #define SDMMC_RSP_TYPE_6 4
#define SDMMC_RSP_TYPE_5 5 #define SDMMC_RSP_TYPE_7 5
/*! SDMMC bus widths. */ /*! SDMMC bus widths. */
#define SDMMC_BUS_WIDTH_1 0 #define SDMMC_BUS_WIDTH_1 0

View File

@@ -21,6 +21,7 @@
#include <soc/t210.h> #include <soc/t210.h>
#include <thermal/tmp451.h> #include <thermal/tmp451.h>
// Remote Sensor.
u16 tmp451_get_soc_temp(bool intenger) u16 tmp451_get_soc_temp(bool intenger)
{ {
u8 val; u8 val;
@@ -37,6 +38,7 @@ u16 tmp451_get_soc_temp(bool intenger)
return temp; return temp;
} }
// Local Sensor.
u16 tmp451_get_pcb_temp(bool intenger) u16 tmp451_get_pcb_temp(bool intenger)
{ {
u8 val; u8 val;
@@ -72,7 +74,7 @@ void tmp451_init()
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TMP_OFL_REG, 0x80); // + 0.5 oC. i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TMP_OFL_REG, 0x80); // + 0.5 oC.
} }
// Set conversion rate to 32/s and make a read to update the reg. // Set conversion rate to 31 ms and make a read to update the reg.
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CNV_RATE_REG, 9); i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CNV_RATE_REG, 9);
tmp451_get_soc_temp(false); tmp451_get_soc_temp(false);

View File

@@ -151,7 +151,7 @@ typedef struct _usb_cfg_hid_descr_t
usb_cfg_descr_t config; usb_cfg_descr_t config;
usb_inter_descr_t interface; usb_inter_descr_t interface;
usb_hid_descr_t hid; usb_hid_descr_t hid;
usb_ep_descr_t endpoint[2]; usb_ep_descr_t endpoint[1];
} __attribute__((packed)) usb_cfg_hid_descr_t; } __attribute__((packed)) usb_cfg_hid_descr_t;
typedef struct _usb_dev_bot_t typedef struct _usb_dev_bot_t

View File

@@ -1,7 +1,7 @@
/* /*
* USB driver for Tegra X1 * USB driver for Tegra X1
* *
* Copyright (c) 2019-2020 CTCaer * Copyright (c) 2019-2025 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,
@@ -409,10 +409,10 @@ static usb_cfg_hid_descr_t usb_configuration_descriptor_hid_jc =
.interface.bDescriptorType = USB_DESCRIPTOR_INTERFACE, .interface.bDescriptorType = USB_DESCRIPTOR_INTERFACE,
.interface.bInterfaceNumber = 0, .interface.bInterfaceNumber = 0,
.interface.bAlternateSetting = 0, .interface.bAlternateSetting = 0,
.interface.bNumEndpoints = 2, .interface.bNumEndpoints = 1,
.interface.bInterfaceClass = 0x03, // Human Interface Device Class. .interface.bInterfaceClass = 0x03, // Human Interface Device Class.
.interface.bInterfaceSubClass = 0x00, // SCSI Transparent Command Set. .interface.bInterfaceSubClass = 0x00, // No Subclass.
.interface.bInterfaceProtocol = 0x00, // Bulk-Only Transport. .interface.bInterfaceProtocol = 0x00, // None.
.interface.iInterface = 0x00, .interface.iInterface = 0x00,
.hid.bLength = 9, .hid.bLength = 9,
@@ -430,14 +430,6 @@ static usb_cfg_hid_descr_t usb_configuration_descriptor_hid_jc =
.endpoint[0].bmAttributes = USB_EP_TYPE_INTR, .endpoint[0].bmAttributes = USB_EP_TYPE_INTR,
.endpoint[0].wMaxPacketSize = 0x200, .endpoint[0].wMaxPacketSize = 0x200,
.endpoint[0].bInterval = 4, // 8ms on HS. .endpoint[0].bInterval = 4, // 8ms on HS.
/* Endpoint descriptor structure EP1 OUT */
.endpoint[1].bLength = 7,
.endpoint[1].bDescriptorType = USB_DESCRIPTOR_ENDPOINT,
.endpoint[1].bEndpointAddress = 0x01, // USB_EP_ADDR_BULK_OUT.
.endpoint[1].bmAttributes = USB_EP_TYPE_INTR,
.endpoint[1].wMaxPacketSize = 0x200,
.endpoint[1].bInterval = 4 // 8ms on HS.
}; };
static u8 usb_vendor_string_descriptor_hid[22] = static u8 usb_vendor_string_descriptor_hid[22] =
@@ -478,10 +470,10 @@ static usb_cfg_hid_descr_t usb_configuration_descriptor_hid_touch =
.interface.bDescriptorType = USB_DESCRIPTOR_INTERFACE, .interface.bDescriptorType = USB_DESCRIPTOR_INTERFACE,
.interface.bInterfaceNumber = 0, .interface.bInterfaceNumber = 0,
.interface.bAlternateSetting = 0, .interface.bAlternateSetting = 0,
.interface.bNumEndpoints = 2, .interface.bNumEndpoints = 1,
.interface.bInterfaceClass = 0x03, // Human Interface Device Class. .interface.bInterfaceClass = 0x03, // Human Interface Device Class.
.interface.bInterfaceSubClass = 0x00, // SCSI Transparent Command Set. .interface.bInterfaceSubClass = 0x00, // No Subclass.
.interface.bInterfaceProtocol = 0x00, // Bulk-Only Transport. .interface.bInterfaceProtocol = 0x00, // None.
.interface.iInterface = 0x00, .interface.iInterface = 0x00,
.hid.bLength = 9, .hid.bLength = 9,
@@ -499,14 +491,6 @@ static usb_cfg_hid_descr_t usb_configuration_descriptor_hid_touch =
.endpoint[0].bmAttributes = USB_EP_TYPE_INTR, .endpoint[0].bmAttributes = USB_EP_TYPE_INTR,
.endpoint[0].wMaxPacketSize = 0x200, .endpoint[0].wMaxPacketSize = 0x200,
.endpoint[0].bInterval = 3, // 4ms on HS. .endpoint[0].bInterval = 3, // 4ms on HS.
/* Endpoint descriptor structure EP1 OUT */
.endpoint[1].bLength = 7,
.endpoint[1].bDescriptorType = USB_DESCRIPTOR_ENDPOINT,
.endpoint[1].bEndpointAddress = 0x01, // USB_EP_ADDR_BULK_OUT.
.endpoint[1].bmAttributes = USB_EP_TYPE_INTR,
.endpoint[1].wMaxPacketSize = 0x200,
.endpoint[1].bInterval = 3 // 4ms on HS.
}; };
usb_desc_t usb_gadget_ums_descriptors = usb_desc_t usb_gadget_ums_descriptors =

View File

@@ -1,7 +1,7 @@
/* /*
* USB Gadget HID driver for Tegra X1 * USB Gadget HID driver for Tegra X1
* *
* Copyright (c) 2019-2022 CTCaer * Copyright (c) 2019-2025 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,
@@ -80,6 +80,8 @@ enum {
static jc_cal_t jc_cal_ctx; static jc_cal_t jc_cal_ctx;
static usb_ops_t usb_ops; static usb_ops_t usb_ops;
static void *rpt_buffer = (u8 *)USB_EP_BULK_IN_BUF_ADDR;
static bool _jc_calibration(const jc_gamepad_rpt_t *jc_pad) static bool _jc_calibration(const jc_gamepad_rpt_t *jc_pad)
{ {
// Calibrate left stick. // Calibrate left stick.
@@ -347,10 +349,10 @@ static bool _fts_touch_read(touchpad_report_t *rpt)
static u8 _hid_transfer_start(usb_ctxt_t *usbs, u32 len) static u8 _hid_transfer_start(usb_ctxt_t *usbs, u32 len)
{ {
u8 status = usb_ops.usb_device_ep1_in_write((u8 *)USB_EP_BULK_IN_BUF_ADDR, len, NULL, USB_XFER_SYNCED_CMD); u8 status = usb_ops.usb_device_ep1_in_write(rpt_buffer, len, NULL, USB_XFER_SYNCED_CMD);
if (status == USB_ERROR_XFER_ERROR) if (status == USB_ERROR_XFER_ERROR)
{ {
usbs->set_text(usbs->label, "#FFDD00 错误#EP IN传输"); usbs->set_text(usbs->label, "#FFDD00 错误:#端口IN传输错误!");
if (usb_ops.usbd_flush_endpoint) if (usb_ops.usbd_flush_endpoint)
usb_ops.usbd_flush_endpoint(USB_EP_BULK_IN); usb_ops.usbd_flush_endpoint(USB_EP_BULK_IN);
} }
@@ -364,12 +366,12 @@ static u8 _hid_transfer_start(usb_ctxt_t *usbs, u32 len)
static bool _hid_poll_jc(usb_ctxt_t *usbs) static bool _hid_poll_jc(usb_ctxt_t *usbs)
{ {
int res = _jc_poll((gamepad_report_t *)USB_EP_BULK_IN_BUF_ADDR); int res = _jc_poll(rpt_buffer);
if (res == INPUT_POLL_EXIT) if (res == INPUT_POLL_EXIT)
return true; return true;
// Send HID report. // Send HID report.
if (res == INPUT_POLL_HAS_PACKET) if (res == INPUT_POLL_HAS_PACKET || usbs->idle)
if (_hid_transfer_start(usbs, sizeof(gamepad_report_t))) if (_hid_transfer_start(usbs, sizeof(gamepad_report_t)))
return true; // EP Error. return true; // EP Error.
@@ -378,7 +380,7 @@ static bool _hid_poll_jc(usb_ctxt_t *usbs)
static bool _hid_poll_touch(usb_ctxt_t *usbs) static bool _hid_poll_touch(usb_ctxt_t *usbs)
{ {
_fts_touch_read((touchpad_report_t *)USB_EP_BULK_IN_BUF_ADDR); _fts_touch_read(rpt_buffer);
// Send HID report. // Send HID report.
if (_hid_transfer_start(usbs, sizeof(touchpad_report_t))) if (_hid_transfer_start(usbs, sizeof(touchpad_report_t)))
@@ -399,6 +401,10 @@ int usb_device_gadget_hid(usb_ctxt_t *usbs)
else else
xusb_device_get_ops(&usb_ops); xusb_device_get_ops(&usb_ops);
// Always push packets by default.
//! TODO: For now only per polling rate or on change is supported.
usbs->idle = 1;
if (usbs->type == USB_HID_GAMEPAD) if (usbs->type == USB_HID_GAMEPAD)
{ {
polling_time = 15000; polling_time = 15000;
@@ -410,7 +416,7 @@ int usb_device_gadget_hid(usb_ctxt_t *usbs)
gadget_type = USB_GADGET_HID_TOUCHPAD; gadget_type = USB_GADGET_HID_TOUCHPAD;
} }
usbs->set_text(usbs->label, "#C7EA46 状态#USB1已开启"); usbs->set_text(usbs->label, "#C7EA46 状态:#USB已启动");
if (usb_ops.usb_device_init()) if (usb_ops.usb_device_init())
{ {
@@ -418,24 +424,32 @@ int usb_device_gadget_hid(usb_ctxt_t *usbs)
return 1; return 1;
} }
usbs->set_text(usbs->label, "#C7EA46 状态#等待连接"); usbs->set_text(usbs->label, "#C7EA46 状态:#正在等待连接");
// Initialize Control Endpoint. // Initialize Control Endpoint.
if (usb_ops.usb_device_enumerate(gadget_type)) if (usb_ops.usb_device_enumerate(gadget_type))
goto error; goto error;
usbs->set_text(usbs->label, "#C7EA46 状态#等待HID报请求"); usbs->set_text(usbs->label, "#C7EA46 状态:#正在等待HID报请求");
if (usb_ops.usb_device_class_send_hid_report()) u32 rpt_size = usbs->type == USB_HID_GAMEPAD ? sizeof(gamepad_report_t) : sizeof(touchpad_report_t);
if (usb_ops.usb_device_class_send_hid_report(rpt_buffer, rpt_size))
goto error; goto error;
usbs->set_text(usbs->label, "#C7EA46 状态#HID模拟已开启"); usbs->set_text(usbs->label, "#C7EA46 状态:#HID仿真已启动");
u32 timer_sys = get_tmr_ms() + 5000; u32 timer_sys = get_tmr_ms() + 5000;
while (true) while (true)
{ {
u32 timer = get_tmr_us(); u32 timer = get_tmr_us();
// Check for suspended USB in case the cable was pulled.
if (usb_ops.usb_device_get_suspended())
break; // Disconnected.
// Handle control endpoint.
usb_ops.usbd_handle_ep0_ctrl_setup(&usbs->idle);
// Parse input device. // Parse input device.
if (usbs->type == USB_HID_GAMEPAD) if (usbs->type == USB_HID_GAMEPAD)
{ {
@@ -448,13 +462,6 @@ int usb_device_gadget_hid(usb_ctxt_t *usbs)
break; break;
} }
// Check for suspended USB in case the cable was pulled.
if (usb_ops.usb_device_get_suspended())
break; // Disconnected.
// Handle control endpoint.
usb_ops.usbd_handle_ep0_ctrl_setup();
// Wait max gadget timing. // Wait max gadget timing.
timer = get_tmr_us() - timer; timer = get_tmr_us() - timer;
if (timer < polling_time) if (timer < polling_time)
@@ -467,11 +474,11 @@ int usb_device_gadget_hid(usb_ctxt_t *usbs)
} }
} }
usbs->set_text(usbs->label, "#C7EA46 状态#HID已结束"); usbs->set_text(usbs->label, "#C7EA46 状态:#HID已结束");
goto exit; goto exit;
error: error:
usbs->set_text(usbs->label, "#FFDD00 错误#超时或已取消"); usbs->set_text(usbs->label, "#FFDD00 错误:#超时或已取消");
res = 1; res = 1;
exit: exit:

View File

@@ -28,11 +28,10 @@
#include <soc/t210.h> #include <soc/t210.h>
#include <storage/sd.h> #include <storage/sd.h>
#include <storage/sdmmc.h> #include <storage/sdmmc.h>
#include <storage/emmc.h>
#include <storage/sdmmc_driver.h> #include <storage/sdmmc_driver.h>
#include <storage/emmc.h>
#include <utils/btn.h> #include <utils/btn.h>
#include <utils/sprintf.h> #include <utils/sprintf.h>
#include <utils/util.h>
#include <memory_map.h> #include <memory_map.h>
@@ -287,7 +286,7 @@ static void raise_exception(usbd_gadget_ums_t *ums, enum ums_state new_state)
static void _handle_ep0_ctrl(usbd_gadget_ums_t *ums) static void _handle_ep0_ctrl(usbd_gadget_ums_t *ums)
{ {
if (usb_ops.usbd_handle_ep0_ctrl_setup()) if (usb_ops.usbd_handle_ep0_ctrl_setup(NULL))
raise_exception(ums, UMS_STATE_PROTOCOL_RESET); raise_exception(ums, UMS_STATE_PROTOCOL_RESET);
} }
@@ -328,11 +327,11 @@ static void _transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32
if (bulk_ctxt->bulk_in_status == USB_ERROR_XFER_ERROR) if (bulk_ctxt->bulk_in_status == USB_ERROR_XFER_ERROR)
{ {
ums->set_text(ums->label, "#FFDD00 错误:#EP IN传输"); ums->set_text(ums->label, "#FFDD00 错误:#端口IN传输错误!");
_flush_endpoint(bulk_ctxt->bulk_in); _flush_endpoint(bulk_ctxt->bulk_in);
} }
else if (bulk_ctxt->bulk_in_status == USB2_ERROR_XFER_NOT_ALIGNED) else if (bulk_ctxt->bulk_in_status == USB2_ERROR_XFER_NOT_ALIGNED)
ums->set_text(ums->label, "#FFDD00 错误:#EP IN缓冲区未对齐"); ums->set_text(ums->label, "#FFDD00 错误:#端口IN缓冲区未对齐!");
if (sync_timeout) if (sync_timeout)
bulk_ctxt->bulk_in_buf_state = BUF_STATE_EMPTY; bulk_ctxt->bulk_in_buf_state = BUF_STATE_EMPTY;
@@ -345,11 +344,11 @@ static void _transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32
if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR) if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR)
{ {
ums->set_text(ums->label, "#FFDD00 错误:#EP OUT传输"); ums->set_text(ums->label, "#FFDD00 错误:#端口OUT传输错误!");
_flush_endpoint(bulk_ctxt->bulk_out); _flush_endpoint(bulk_ctxt->bulk_out);
} }
else if (bulk_ctxt->bulk_out_status == USB2_ERROR_XFER_NOT_ALIGNED) else if (bulk_ctxt->bulk_out_status == USB2_ERROR_XFER_NOT_ALIGNED)
ums->set_text(ums->label, "#FFDD00 错误:#EP OUT缓冲区未对齐"); ums->set_text(ums->label, "#FFDD00 错误:#端口OUT缓冲区未对齐!");
if (sync_timeout) if (sync_timeout)
bulk_ctxt->bulk_out_buf_state = BUF_STATE_FULL; bulk_ctxt->bulk_out_buf_state = BUF_STATE_FULL;
@@ -364,7 +363,7 @@ static void _transfer_out_big_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctx
if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR) if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR)
{ {
ums->set_text(ums->label, "#FFDD00 错误:#EP OUT传输"); ums->set_text(ums->label, "#FFDD00 错误:#端口OUT传输错误!");
_flush_endpoint(bulk_ctxt->bulk_out); _flush_endpoint(bulk_ctxt->bulk_out);
} }
@@ -380,7 +379,7 @@ static void _transfer_finish(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32
if (bulk_ctxt->bulk_in_status == USB_ERROR_XFER_ERROR) if (bulk_ctxt->bulk_in_status == USB_ERROR_XFER_ERROR)
{ {
ums->set_text(ums->label, "#FFDD00 错误:#EP IN传输"); ums->set_text(ums->label, "#FFDD00 错误:#端口IN传输错误!");
_flush_endpoint(bulk_ctxt->bulk_in); _flush_endpoint(bulk_ctxt->bulk_in);
} }
@@ -393,7 +392,7 @@ static void _transfer_finish(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32
if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR) if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR)
{ {
ums->set_text(ums->label, "#FFDD00 错误:#EP OUT传输"); ums->set_text(ums->label, "#FFDD00 错误:#端口OUT传输!");
_flush_endpoint(bulk_ctxt->bulk_out); _flush_endpoint(bulk_ctxt->bulk_out);
} }
@@ -463,7 +462,7 @@ static int _scsi_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
} }
if (lba_offset >= ums->lun.num_sectors) if (lba_offset >= ums->lun.num_sectors)
{ {
ums->set_text(ums->label, "#FF8000 警告:#读取 - 超出范围!已通知主机"); ums->set_text(ums->label, "#FF8000 警告:#读取超出范围!主机已通知。");
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
return UMS_RES_INVALID_ARG; return UMS_RES_INVALID_ARG;
@@ -515,7 +514,7 @@ static int _scsi_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
// If an error occurred, report it and its position. // If an error occurred, report it and its position.
if (!amount) if (!amount)
{ {
ums->set_text(ums->label, "#FFDD00 错误:# SDMMC读取"); ums->set_text(ums->label, "#FFDD00 错误:#SDMMC读取失败");
ums->lun.sense_data = SS_UNRECOVERED_READ_ERROR; ums->lun.sense_data = SS_UNRECOVERED_READ_ERROR;
ums->lun.sense_data_info = lba_offset; ums->lun.sense_data_info = lba_offset;
ums->lun.info_valid = 1; ums->lun.info_valid = 1;
@@ -553,7 +552,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
if (ums->lun.ro) if (ums->lun.ro)
{ {
ums->set_text(ums->label, "#FF8000 警告:#写入 - 只读已通知主机。"); ums->set_text(ums->label, "#FF8000 警告:#写入受阻 - 只读模式! 已通知主机。");
ums->lun.sense_data = SS_WRITE_PROTECTED; ums->lun.sense_data = SS_WRITE_PROTECTED;
return UMS_RES_INVALID_ARG; return UMS_RES_INVALID_ARG;
@@ -577,7 +576,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
// Check that starting LBA is not past the end sector offset. // Check that starting LBA is not past the end sector offset.
if (lba_offset >= ums->lun.num_sectors) if (lba_offset >= ums->lun.num_sectors)
{ {
ums->set_text(ums->label, "#FF8000 警告:#写入 - 超出范围已通知主机。"); ums->set_text(ums->label, "#FF8000 警告:#写入超出范围! 已通知主机。");
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
return UMS_RES_INVALID_ARG; return UMS_RES_INVALID_ARG;
@@ -599,7 +598,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
if (usb_lba_offset >= ums->lun.num_sectors) if (usb_lba_offset >= ums->lun.num_sectors)
{ {
ums->set_text(ums->label, "#FFDD00 错误#写入 - 超出最后扇区"); ums->set_text(ums->label, "#FFDD00 错误:# 写入超过最后一个扇区!");
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
ums->lun.sense_data_info = usb_lba_offset; ums->lun.sense_data_info = usb_lba_offset;
ums->lun.info_valid = 1; ums->lun.info_valid = 1;
@@ -627,7 +626,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
ums->lun.sense_data_info = lba_offset; ums->lun.sense_data_info = lba_offset;
ums->lun.info_valid = 1; ums->lun.info_valid = 1;
s_printf(txt_buf, "#FFDD00 错误:#写入 - 通讯失败 %d", bulk_ctxt->bulk_out_status); s_printf(txt_buf, "#FFDD00 错误:#写入通信失败 %d", bulk_ctxt->bulk_out_status);
ums->set_text(ums->label, txt_buf); ums->set_text(ums->label, txt_buf);
break; break;
} }
@@ -665,7 +664,7 @@ DPRINTF("file write %X @ %X\n", amount, lba_offset);
// If an error occurred, report it and its position. // If an error occurred, report it and its position.
if (!amount) if (!amount)
{ {
ums->set_text(ums->label, "#FFDD00 错误:#SDMMC写入"); ums->set_text(ums->label, "#FFDD00 错误:#SDMMC写入失败");
ums->lun.sense_data = SS_WRITE_ERROR; ums->lun.sense_data = SS_WRITE_ERROR;
ums->lun.sense_data_info = lba_offset; ums->lun.sense_data_info = lba_offset;
ums->lun.info_valid = 1; ums->lun.info_valid = 1;
@@ -676,7 +675,7 @@ DPRINTF("file write %X @ %X\n", amount, lba_offset);
// Did the host decide to stop early? // Did the host decide to stop early?
if (bulk_ctxt->bulk_out_length_actual < bulk_ctxt->bulk_out_length) if (bulk_ctxt->bulk_out_length_actual < bulk_ctxt->bulk_out_length)
{ {
ums->set_text(ums->label, "#FFDD00 错误:#空写入"); ums->set_text(ums->label, "#FFDD00 错误:#空写入");
ums->short_packet_received = 1; ums->short_packet_received = 1;
break; break;
} }
@@ -692,7 +691,7 @@ static int _scsi_verify(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
u32 lba_offset = get_array_be_to_le32(&ums->cmnd[2]); u32 lba_offset = get_array_be_to_le32(&ums->cmnd[2]);
if (lba_offset >= ums->lun.num_sectors) if (lba_offset >= ums->lun.num_sectors)
{ {
ums->set_text(ums->label, "#FF8000 警告:#校验 - 超出范围已通知主机。"); ums->set_text(ums->label, "#FF8000 警告:#验证超出范围! 已通知主机。");
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
return UMS_RES_INVALID_ARG; return UMS_RES_INVALID_ARG;
@@ -731,7 +730,7 @@ DPRINTF("File read %X @ %X\n", amount, lba_offset);
if (!amount) if (!amount)
{ {
ums->set_text(ums->label, "#FFDD00 错误:#文件验!"); ums->set_text(ums->label, "#FFDD00 错误:#文件验证失败");
ums->lun.sense_data = SS_UNRECOVERED_READ_ERROR; ums->lun.sense_data = SS_UNRECOVERED_READ_ERROR;
ums->lun.sense_data_info = lba_offset; ums->lun.sense_data_info = lba_offset;
ums->lun.info_valid = 1; ums->lun.info_valid = 1;
@@ -764,7 +763,7 @@ static int _scsi_inquiry(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
switch (ums->lun.partition) switch (ums->lun.partition)
{ {
case 0: case 0:
strcpy((char *)buf + strlen((char *)buf), "原始"); strcpy((char *)buf + strlen((char *)buf), "RAW");
break; break;
case EMMC_GPP + 1: case EMMC_GPP + 1:
s_printf((char *)buf + strlen((char *)buf), "GPP"); s_printf((char *)buf + strlen((char *)buf), "GPP");
@@ -800,7 +799,7 @@ static int _scsi_inquiry(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
switch (ums->lun.partition) switch (ums->lun.partition)
{ {
case 0: case 0:
s_printf((char *)buf, "%s", "SD卡原始分区"); s_printf((char *)buf, "%s", "SD RAW");
break; break;
case EMMC_GPP + 1: case EMMC_GPP + 1:
s_printf((char *)buf, "%s%s", s_printf((char *)buf, "%s%s",
@@ -1060,7 +1059,7 @@ static int _scsi_start_stop(usbd_gadget_ums_t *ums)
// Check if we are allowed to unload the media. // Check if we are allowed to unload the media.
if (ums->lun.prevent_medium_removal) if (ums->lun.prevent_medium_removal)
{ {
ums->set_text(ums->label, "#C7EA46 状态:#卸载尝试已被阻止"); ums->set_text(ums->label, "#C7EA46 状态:#尝试卸载被阻止");
ums->lun.sense_data = SS_MEDIUM_REMOVAL_PREVENTED; ums->lun.sense_data = SS_MEDIUM_REMOVAL_PREVENTED;
return UMS_RES_INVALID_ARG; return UMS_RES_INVALID_ARG;
@@ -1468,7 +1467,7 @@ static int _finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{ {
_set_ep_stall(bulk_ctxt->bulk_out); _set_ep_stall(bulk_ctxt->bulk_out);
rc = _set_ep_stall(bulk_ctxt->bulk_in); rc = _set_ep_stall(bulk_ctxt->bulk_in);
ums->set_text(ums->label, "#FFDD00 错误:#方向不明。两端EP已暂停"); ums->set_text(ums->label, "#FFDD00 错误:#方向未知。已停止两个端口");
} // Else do nothing. } // Else do nothing.
break; break;
@@ -1489,7 +1488,7 @@ static int _finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{ {
_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_DATA); _transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_DATA);
rc = _set_ep_stall(bulk_ctxt->bulk_in); rc = _set_ep_stall(bulk_ctxt->bulk_in);
ums->set_text(ums->label, "#FFDD00 错误:#数据残留。EP IN已停止!"); ums->set_text(ums->label, "#FFDD00 错误:#残留。已停止端口IN");
} }
else else
rc = _pad_with_zeros(ums, bulk_ctxt); rc = _pad_with_zeros(ums, bulk_ctxt);
@@ -1562,7 +1561,7 @@ static int _received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{ {
if (usb_ops.usb_device_get_port_in_sleep()) if (usb_ops.usb_device_get_port_in_sleep())
{ {
ums->set_text(ums->label, "#C7EA46 状态#EP已休眠"); ums->set_text(ums->label, "#C7EA46 状态:#端口休眠");
ums->timeouts += 14; ums->timeouts += 14;
} }
else if (!ums->xusb) // Timeout only on USB2. else if (!ums->xusb) // Timeout only on USB2.
@@ -1581,7 +1580,7 @@ static int _received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
if (ums->lun.unmounted) if (ums->lun.unmounted)
{ {
ums->set_text(ums->label, "#C7EA46 状态#介质未挂"); ums->set_text(ums->label, "#C7EA46 状态:# 介质已卸");
ums->timeouts++; ums->timeouts++;
if (!bulk_ctxt->bulk_out_status) if (!bulk_ctxt->bulk_out_status)
ums->timeouts += 3; ums->timeouts += 3;
@@ -1633,7 +1632,7 @@ static int _received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{ {
_set_ep_stall(bulk_ctxt->bulk_out); _set_ep_stall(bulk_ctxt->bulk_out);
_set_ep_stall(bulk_ctxt->bulk_in); _set_ep_stall(bulk_ctxt->bulk_in);
ums->set_text(ums->label, "#FFDD00 错误:#CBW未知 - 两端EP已停止!"); ums->set_text(ums->label, "#FFDD00 错误:#CBW未知 - 已停止两个端口");
} }
return UMS_RES_INVALID_ARG; return UMS_RES_INVALID_ARG;
@@ -1712,7 +1711,7 @@ static void _send_status(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
if (ums->phase_error) if (ums->phase_error)
{ {
ums->set_text(ums->label, "#FFDD00 错误#相位错误"); ums->set_text(ums->label, "#FFDD00 错误:# 阶段性错误!");
status = USB_STATUS_PHASE_ERROR; status = USB_STATUS_PHASE_ERROR;
sd = SS_INVALID_COMMAND; sd = SS_INVALID_COMMAND;
} }
@@ -1826,7 +1825,7 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
xusb_device_get_ops(&usb_ops); xusb_device_get_ops(&usb_ops);
} }
usbs->set_text(usbs->label, "#C7EA46 状态:#USB已开启"); usbs->set_text(usbs->label, "#C7EA46 状态:#已启动USB");
if (usb_ops.usb_device_init()) if (usb_ops.usb_device_init())
{ {
@@ -1857,7 +1856,7 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
ums.set_text = usbs->set_text; ums.set_text = usbs->set_text;
ums.system_maintenance = usbs->system_maintenance; ums.system_maintenance = usbs->system_maintenance;
ums.set_text(ums.label, "#C7EA46 状态:#磁盘挂载中"); ums.set_text(ums.label, "#C7EA46 状态:#挂载磁盘");
// Initialize sdmmc. // Initialize sdmmc.
if (usbs->type == MMC_SD) if (usbs->type == MMC_SD)
@@ -1888,18 +1887,18 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
ums.lun.storage = &emmc_storage; ums.lun.storage = &emmc_storage;
} }
ums.set_text(ums.label, "#C7EA46 状态:#连接等待中"); ums.set_text(ums.label, "#C7EA46 状态:#正在等待连接");
// Initialize Control Endpoint. // Initialize Control Endpoint.
if (usb_ops.usb_device_enumerate(USB_GADGET_UMS)) if (usb_ops.usb_device_enumerate(USB_GADGET_UMS))
goto usb_enum_error; goto usb_enum_error;
ums.set_text(ums.label, "#C7EA46 状态:#LUN等待中"); ums.set_text(ums.label, "#C7EA46 状态:#正在等待LUN");
if (usb_ops.usb_device_class_send_max_lun(0)) // One device for now. if (usb_ops.usb_device_class_send_max_lun(0)) // One device for now.
goto usb_enum_error; goto usb_enum_error;
ums.set_text(ums.label, "#C7EA46 状态:#UMS已开启"); ums.set_text(ums.label, "#C7EA46 状态:#已启动UMS");
// If partition sectors are not set get them from hardware. // If partition sectors are not set get them from hardware.
if (!ums.lun.num_sectors) if (!ums.lun.num_sectors)
@@ -1920,7 +1919,7 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
{ {
// Check if we are allowed to unload the media. // Check if we are allowed to unload the media.
if (ums.lun.prevent_medium_removal) if (ums.lun.prevent_medium_removal)
ums.set_text(ums.label, "#C7EA46 状态:#卸载尝试已被阻止"); ums.set_text(ums.label, "#C7EA46 状态:#尝试卸载被阻止");
else else
break; break;
} }
@@ -1952,13 +1951,13 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
} while (ums.state != UMS_STATE_TERMINATED); } while (ums.state != UMS_STATE_TERMINATED);
if (ums.lun.prevent_medium_removal) if (ums.lun.prevent_medium_removal)
ums.set_text(ums.label, "#FFDD00 错误:#磁盘已未安全弹出"); ums.set_text(ums.label, "#FFDD00 错误:#磁盘安全弹出");
else else
ums.set_text(ums.label, "#C7EA46 状态:#磁盘已弹出"); ums.set_text(ums.label, "#C7EA46 状态:#磁盘已弹出");
goto exit; goto exit;
usb_enum_error: usb_enum_error:
ums.set_text(ums.label, "#FFDD00 错误:#超时或取消!"); ums.set_text(ums.label, "#FFDD00 错误:#超时或取消!");
res = 1; res = 1;
exit: exit:

View File

@@ -1,7 +1,7 @@
/* /*
* Enhanced USB Device (EDCI) driver for Tegra X1 * Enhanced USB Device (EDCI) driver for Tegra X1
* *
* Copyright (c) 2019-2024 CTCaer * Copyright (c) 2019-2025 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,
@@ -101,7 +101,11 @@ typedef struct _usbd_controller_t
bool configuration_set; bool configuration_set;
bool max_lun_set; bool max_lun_set;
bool bulk_reset_req; bool bulk_reset_req;
u32 intr_idle_rate;
bool intr_idle_req;
bool hid_report_sent; bool hid_report_sent;
void *hid_rpt_buffer;
u32 hid_rpt_size;
u32 charger_detect; u32 charger_detect;
} usbd_controller_t; } usbd_controller_t;
@@ -881,7 +885,7 @@ int usbd_set_ep_stall(u32 endpoint, int ep_stall)
return USB_RES_OK; return USB_RES_OK;
} }
static void _usbd_handle_get_class_request(bool *transmit_data, u8 *descriptor, int *size, bool *ep_stall) static void _usbd_handle_get_class_request(bool *transmit_data, u8 *desc, int *size, bool *ep_stall)
{ {
u8 _bRequest = usbd_otg->control_setup.bRequest; u8 _bRequest = usbd_otg->control_setup.bRequest;
u16 _wIndex = usbd_otg->control_setup.wIndex; u16 _wIndex = usbd_otg->control_setup.wIndex;
@@ -889,9 +893,9 @@ static void _usbd_handle_get_class_request(bool *transmit_data, u8 *descriptor,
u16 _wLength = usbd_otg->control_setup.wLength; u16 _wLength = usbd_otg->control_setup.wLength;
bool valid_interface = _wIndex == usbd_otg->interface_num; bool valid_interface = _wIndex == usbd_otg->interface_num;
bool valid_len = (_bRequest == USB_REQUEST_BULK_GET_MAX_LUN) ? 1 : 0; bool valid_val = (_bRequest >= USB_REQUEST_BULK_GET_MAX_LUN) ? (!_wValue) : true;
if (!valid_interface || _wValue != 0 || _wLength != valid_len) if (!valid_interface || !valid_val)
{ {
*ep_stall = true; *ep_stall = true;
return; return;
@@ -899,23 +903,51 @@ static void _usbd_handle_get_class_request(bool *transmit_data, u8 *descriptor,
switch (_bRequest) switch (_bRequest)
{ {
case USB_REQUEST_INTR_GET_REPORT:
if (usbd_otg->hid_rpt_size != _wLength)
break;
// _wValue unused as there's only one report type and id.
*transmit_data = true;
*size = usbd_otg->hid_rpt_size;
memcpy(desc, usbd_otg->hid_rpt_buffer, usbd_otg->hid_rpt_size);
return;
case USB_REQUEST_INTR_SET_IDLE:
if (_wLength)
break;
usbd_otg->intr_idle_rate = (_wValue & 0xFF) * 4 * 1000; // Only one interface so upper byte ignored.
usbd_otg->intr_idle_req = true;
_usbd_ep_ack(USB_EP_CTRL_IN);
return; // DELAYED_STATUS;
case USB_REQUEST_BULK_RESET: case USB_REQUEST_BULK_RESET:
if (_wLength)
break;
_usbd_ep_ack(USB_EP_CTRL_IN); _usbd_ep_ack(USB_EP_CTRL_IN);
usbd_otg->bulk_reset_req = true; usbd_otg->bulk_reset_req = true;
break; // DELAYED_STATUS; return; // DELAYED_STATUS;
case USB_REQUEST_BULK_GET_MAX_LUN: case USB_REQUEST_BULK_GET_MAX_LUN:
if (_wLength != 1)
break;
*transmit_data = true; *transmit_data = true;
*size = 1; *size = 1;
descriptor[0] = usbd_otg->max_lun; // Set 0 LUN for 1 drive supported. desc[0] = usbd_otg->max_lun; // Set 0 LUN for 1 drive supported.
usbd_otg->max_lun_set = true; usbd_otg->max_lun_set = true;
break; return;
default: default:
*ep_stall = true;
break; break;
} }
*ep_stall = true;
} }
static void _usbd_handle_get_descriptor(bool *transmit_data, void **descriptor, int *size, bool *ep_stall) static void _usbd_handle_get_descriptor(bool *transmit_data, void **desc, int *size, bool *ep_stall)
{ {
u8 descriptor_type = usbd_otg->control_setup.wValue >> 8; u8 descriptor_type = usbd_otg->control_setup.wValue >> 8;
u8 descriptor_subtype = usbd_otg->control_setup.wValue & 0xFF; u8 descriptor_subtype = usbd_otg->control_setup.wValue & 0xFF;
@@ -931,7 +963,7 @@ static void _usbd_handle_get_descriptor(bool *transmit_data, void **descriptor,
usb_device_descriptor.bcdDevice = (soc_rev >> 16) & 0xF; // MINORREV. usb_device_descriptor.bcdDevice = (soc_rev >> 16) & 0xF; // MINORREV.
usb_device_descriptor.bcdDevice |= ((soc_rev >> 4) & 0xF) << 8; // MAJORREV. usb_device_descriptor.bcdDevice |= ((soc_rev >> 4) & 0xF) << 8; // MAJORREV.
*/ */
*descriptor = usbd_otg->desc->dev; *desc = usbd_otg->desc->dev;
*size = usbd_otg->desc->dev->bLength; *size = usbd_otg->desc->dev->bLength;
*transmit_data = true; *transmit_data = true;
return; return;
@@ -941,13 +973,13 @@ static void _usbd_handle_get_descriptor(bool *transmit_data, void **descriptor,
{ {
if (usbd_otg->port_speed == USB_HIGH_SPEED) // High speed. 512 bytes. if (usbd_otg->port_speed == USB_HIGH_SPEED) // High speed. 512 bytes.
{ {
usbd_otg->desc->cfg->endpoint[0].wMaxPacketSize = 0x200; for (u32 i = 0; i < usbd_otg->desc->cfg->interface.bNumEndpoints; i++)
usbd_otg->desc->cfg->endpoint[1].wMaxPacketSize = 0x200; usbd_otg->desc->cfg->endpoint[i].wMaxPacketSize = 0x200; // No burst.
} }
else // Full speed. 64 bytes. else // Full speed. 64 bytes.
{ {
usbd_otg->desc->cfg->endpoint[0].wMaxPacketSize = 0x40; for (u32 i = 0; i < usbd_otg->desc->cfg->interface.bNumEndpoints; i++)
usbd_otg->desc->cfg->endpoint[1].wMaxPacketSize = 0x40; usbd_otg->desc->cfg->endpoint[i].wMaxPacketSize = 0x40;
} }
} }
else else
@@ -955,20 +987,22 @@ static void _usbd_handle_get_descriptor(bool *transmit_data, void **descriptor,
usb_cfg_hid_descr_t *tmp = (usb_cfg_hid_descr_t *)usbd_otg->desc->cfg; usb_cfg_hid_descr_t *tmp = (usb_cfg_hid_descr_t *)usbd_otg->desc->cfg;
if (usbd_otg->port_speed == USB_HIGH_SPEED) // High speed. 512 bytes. if (usbd_otg->port_speed == USB_HIGH_SPEED) // High speed. 512 bytes.
{ {
tmp->endpoint[0].wMaxPacketSize = 0x200; for (u32 i = 0; i < tmp->interface.bNumEndpoints; i++)
tmp->endpoint[1].wMaxPacketSize = 0x200; {
tmp->endpoint[0].bInterval = usbd_otg->gadget == USB_GADGET_HID_GAMEPAD ? 4 : 3; // 8ms : 4ms. tmp->endpoint[i].wMaxPacketSize = 0x200;
tmp->endpoint[1].bInterval = usbd_otg->gadget == USB_GADGET_HID_GAMEPAD ? 4 : 3; // 8ms : 4ms. tmp->endpoint[i].bInterval = usbd_otg->gadget == USB_GADGET_HID_GAMEPAD ? 4 : 3; // 8ms : 4ms.
}
} }
else // Full speed. 64 bytes. else // Full speed. 64 bytes.
{ {
tmp->endpoint[0].wMaxPacketSize = 0x40; for (u32 i = 0; i < tmp->interface.bNumEndpoints; i++)
tmp->endpoint[1].wMaxPacketSize = 0x40; {
tmp->endpoint[0].bInterval = usbd_otg->gadget == USB_GADGET_HID_GAMEPAD ? 8 : 4; // 8ms : 4ms. tmp->endpoint[i].wMaxPacketSize = 0x40;
tmp->endpoint[1].bInterval = usbd_otg->gadget == USB_GADGET_HID_GAMEPAD ? 8 : 4; // 8ms : 4ms. tmp->endpoint[i].bInterval = usbd_otg->gadget == USB_GADGET_HID_GAMEPAD ? 8 : 4; // 8ms : 4ms.
}
} }
} }
*descriptor = usbd_otg->desc->cfg; *desc = usbd_otg->desc->cfg;
*size = usbd_otg->desc->cfg->config.wTotalLength; *size = usbd_otg->desc->cfg->config.wTotalLength;
*transmit_data = true; *transmit_data = true;
return; return;
@@ -976,23 +1010,23 @@ static void _usbd_handle_get_descriptor(bool *transmit_data, void **descriptor,
switch (descriptor_subtype) switch (descriptor_subtype)
{ {
case 1: case 1:
*descriptor = usbd_otg->desc->vendor; *desc = usbd_otg->desc->vendor;
*size = usbd_otg->desc->vendor[0]; *size = usbd_otg->desc->vendor[0];
break; break;
case 2: case 2:
*descriptor = usbd_otg->desc->product; *desc = usbd_otg->desc->product;
*size = usbd_otg->desc->product[0]; *size = usbd_otg->desc->product[0];
break; break;
case 3: case 3:
*descriptor = usbd_otg->desc->serial; *desc = usbd_otg->desc->serial;
*size = usbd_otg->desc->serial[0]; *size = usbd_otg->desc->serial[0];
break; break;
case 0xEE: case 0xEE:
*descriptor = usbd_otg->desc->ms_os; *desc = usbd_otg->desc->ms_os;
*size = usbd_otg->desc->ms_os->bLength; *size = usbd_otg->desc->ms_os->bLength;
break; break;
default: default:
*descriptor = usbd_otg->desc->lang_id; *desc = usbd_otg->desc->lang_id;
*size = 4; *size = 4;
break; break;
} }
@@ -1002,7 +1036,7 @@ static void _usbd_handle_get_descriptor(bool *transmit_data, void **descriptor,
if (!usbd_otg->desc->dev_qual) if (!usbd_otg->desc->dev_qual)
goto exit; goto exit;
usbd_otg->desc->dev_qual->bNumOtherConfigs = 1; usbd_otg->desc->dev_qual->bNumOtherConfigs = 1;
*descriptor = usbd_otg->desc->dev_qual; *desc = usbd_otg->desc->dev_qual;
*size = usbd_otg->desc->dev_qual->bLength; *size = usbd_otg->desc->dev_qual->bLength;
*transmit_data = true; *transmit_data = true;
return; return;
@@ -1011,22 +1045,22 @@ static void _usbd_handle_get_descriptor(bool *transmit_data, void **descriptor,
goto exit; goto exit;
if (usbd_otg->port_speed == USB_HIGH_SPEED) if (usbd_otg->port_speed == USB_HIGH_SPEED)
{ {
usbd_otg->desc->cfg_other->endpoint[0].wMaxPacketSize = 0x40; for (u32 i = 0; i < usbd_otg->desc->cfg_other->interface.bNumEndpoints; i++)
usbd_otg->desc->cfg_other->endpoint[1].wMaxPacketSize = 0x40; usbd_otg->desc->cfg_other->endpoint[i].wMaxPacketSize = 0x40;
} }
else else
{ {
usbd_otg->desc->cfg_other->endpoint[0].wMaxPacketSize = 0x200; for (u32 i = 0; i < usbd_otg->desc->cfg_other->interface.bNumEndpoints; i++)
usbd_otg->desc->cfg_other->endpoint[1].wMaxPacketSize = 0x200; usbd_otg->desc->cfg_other->endpoint[i].wMaxPacketSize = 0x200;
} }
if ((usbd_otg->charger_detect & 1) && (usbd_otg->charger_detect & 2)) if ((usbd_otg->charger_detect & 1) && (usbd_otg->charger_detect & 2))
usbd_otg->desc->cfg_other->config.bMaxPower = 500 / 2; usbd_otg->desc->cfg_other->config.bMaxPower = 500 / 2;
*descriptor = usbd_otg->desc->cfg_other; *desc = usbd_otg->desc->cfg_other;
*size = usbd_otg->desc->cfg_other->config.wTotalLength; *size = usbd_otg->desc->cfg_other->config.wTotalLength;
*transmit_data = true; *transmit_data = true;
return; return;
case USB_DESCRIPTOR_DEVICE_BINARY_OBJECT: case USB_DESCRIPTOR_DEVICE_BINARY_OBJECT:
*descriptor = usbd_otg->desc->dev_bot; *desc = usbd_otg->desc->dev_bot;
*size = usbd_otg->desc->dev_bot->wTotalLength; *size = usbd_otg->desc->dev_bot->wTotalLength;
*transmit_data = true; *transmit_data = true;
return; return;
@@ -1086,7 +1120,7 @@ static int _usbd_handle_ep0_control_transfer()
bool ep_stall = false; bool ep_stall = false;
bool transmit_data = false; bool transmit_data = false;
u8 *descriptor = (u8 *)USB_DESCRIPTOR_ADDR; u8 *desc = (u8 *)USB_DESCRIPTOR_ADDR;
int size = 0; int size = 0;
u8 _bmRequestType = usbd_otg->control_setup.bmRequestType; u8 _bmRequestType = usbd_otg->control_setup.bmRequestType;
@@ -1099,17 +1133,17 @@ static int _usbd_handle_ep0_control_transfer()
switch (_bmRequestType) switch (_bmRequestType)
{ {
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_DEVICE): case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_DEVICE): // 0x00.
res = _usbd_handle_set_request(&ep_stall); res = _usbd_handle_set_request(&ep_stall);
break; break;
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_INTERFACE): case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_INTERFACE): // 0x01.
res = _usbd_ep_ack(USB_EP_CTRL_IN); res = _usbd_ep_ack(USB_EP_CTRL_IN);
if (!res) if (!res)
usbd_otg->interface_num = _wValue; usbd_otg->interface_num = _wValue;
break; break;
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT): case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT): // 0x02.
switch (_bRequest) switch (_bRequest)
{ {
case USB_REQUEST_CLEAR_FEATURE: case USB_REQUEST_CLEAR_FEATURE:
@@ -1153,25 +1187,25 @@ static int _usbd_handle_ep0_control_transfer()
} }
break; break;
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE): case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE): // 0x21.
memset(descriptor, 0, _wLength); memset(desc, 0, _wLength);
_usbd_handle_get_class_request(&transmit_data, descriptor, &size, &ep_stall); _usbd_handle_get_class_request(&transmit_data, desc, &size, &ep_stall);
break; break;
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_DEVICE): case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_DEVICE): // 0x80.
switch (_bRequest) switch (_bRequest)
{ {
case USB_REQUEST_GET_STATUS: case USB_REQUEST_GET_STATUS:
descriptor[0] = USB_STATUS_DEV_SELF_POWERED; desc[0] = USB_STATUS_DEV_SELF_POWERED;
descriptor[1] = 0; // No support for remove wake up. desc[1] = 0; // No support for remove wake up.
transmit_data = true; transmit_data = true;
size = 2; size = 2;
break; break;
case USB_REQUEST_GET_DESCRIPTOR: case USB_REQUEST_GET_DESCRIPTOR:
_usbd_handle_get_descriptor(&transmit_data, (void **)&descriptor, &size, &ep_stall); _usbd_handle_get_descriptor(&transmit_data, (void **)&desc, &size, &ep_stall);
break; break;
case USB_REQUEST_GET_CONFIGURATION: case USB_REQUEST_GET_CONFIGURATION:
descriptor = (u8 *)&usbd_otg->config_num; desc = (u8 *)&usbd_otg->config_num;
size = _wLength; size = _wLength;
transmit_data = true; transmit_data = true;
break; break;
@@ -1181,28 +1215,28 @@ static int _usbd_handle_ep0_control_transfer()
} }
break; break;
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_INTERFACE): case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_INTERFACE): // 0x81.
if (_bRequest == USB_REQUEST_GET_INTERFACE) if (_bRequest == USB_REQUEST_GET_INTERFACE)
{ {
memset(descriptor, 0, _wLength); memset(desc, 0, _wLength);
descriptor[0] = usbd_otg->interface_num; desc[0] = usbd_otg->interface_num;
size = _wLength; size = _wLength;
} }
else if (_bRequest == USB_REQUEST_GET_STATUS) else if (_bRequest == USB_REQUEST_GET_STATUS)
{ {
memset(descriptor, 0, _wLength); memset(desc, 0, _wLength);
size = _wLength; size = _wLength;
} }
else if (_bRequest == USB_REQUEST_GET_DESCRIPTOR && (_wValue >> 8) == USB_DESCRIPTOR_HID_REPORT && usbd_otg->gadget > USB_GADGET_UMS) else if (_bRequest == USB_REQUEST_GET_DESCRIPTOR && (_wValue >> 8) == USB_DESCRIPTOR_HID_REPORT && usbd_otg->gadget >= USB_GADGET_HID_GAMEPAD)
{ {
if (usbd_otg->gadget == USB_GADGET_HID_GAMEPAD) if (usbd_otg->gadget == USB_GADGET_HID_GAMEPAD)
{ {
descriptor = (u8 *)&hid_report_descriptor_jc; desc = (u8 *)&hid_report_descriptor_jc;
size = hid_report_descriptor_jc_size; size = hid_report_descriptor_jc_size;
} }
else // USB_GADGET_HID_TOUCHPAD else // USB_GADGET_HID_TOUCHPAD
{ {
descriptor = (u8 *)&hid_report_descriptor_touch; desc = (u8 *)&hid_report_descriptor_touch;
size = hid_report_descriptor_touch_size; size = hid_report_descriptor_touch_size;
} }
@@ -1219,7 +1253,7 @@ static int _usbd_handle_ep0_control_transfer()
transmit_data = true; transmit_data = true;
break; break;
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT): case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT): // 0x82.
if (_bRequest == USB_REQUEST_GET_STATUS) if (_bRequest == USB_REQUEST_GET_STATUS)
{ {
int ep_req; int ep_req;
@@ -1243,12 +1277,12 @@ static int _usbd_handle_ep0_control_transfer()
} }
size = _wLength; size = _wLength;
memset(descriptor, 0, size); memset(desc, 0, size);
if (_usbd_get_ep_status(ep_req) == USB_EP_STATUS_STALLED) if (_usbd_get_ep_status(ep_req) == USB_EP_STATUS_STALLED)
descriptor[0] = USB_STATUS_EP_HALTED; desc[0] = USB_STATUS_EP_HALTED;
else else
descriptor[0] = USB_STATUS_EP_OK; desc[0] = USB_STATUS_EP_OK;
transmit_data = true; transmit_data = true;
} }
@@ -1256,24 +1290,24 @@ static int _usbd_handle_ep0_control_transfer()
_usbd_stall_reset_ep1(3, USB_EP_CFG_STALL); _usbd_stall_reset_ep1(3, USB_EP_CFG_STALL);
break; break;
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE): case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE): // 0xA1.
memset(descriptor, 0, _wLength); memset(desc, 0, _wLength);
_usbd_handle_get_class_request(&transmit_data, descriptor, &size, &ep_stall); _usbd_handle_get_class_request(&transmit_data, desc, &size, &ep_stall);
break; break;
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_VENDOR | USB_SETUP_RECIPIENT_INTERFACE): case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_VENDOR | USB_SETUP_RECIPIENT_DEVICE): // 0xC0.
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_VENDOR | USB_SETUP_RECIPIENT_DEVICE): case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_VENDOR | USB_SETUP_RECIPIENT_INTERFACE): // 0xC1.
if (_bRequest == USB_REQUEST_GET_MS_DESCRIPTOR) if (_bRequest == USB_REQUEST_GET_MS_DESCRIPTOR)
{ {
switch (_wIndex) switch (_wIndex)
{ {
case USB_DESCRIPTOR_MS_COMPAT_ID: case USB_DESCRIPTOR_MS_COMPAT_ID:
descriptor = (u8 *)usbd_otg->desc->ms_cid; desc = (u8 *)usbd_otg->desc->ms_cid;
size = usbd_otg->desc->ms_cid->dLength; size = usbd_otg->desc->ms_cid->dLength;
transmit_data = true; transmit_data = true;
break; break;
case USB_DESCRIPTOR_MS_EXTENDED_PROPERTIES: case USB_DESCRIPTOR_MS_EXTENDED_PROPERTIES:
descriptor = (u8 *)usbd_otg->desc->mx_ext; desc = (u8 *)usbd_otg->desc->mx_ext;
size = usbd_otg->desc->mx_ext->dLength; size = usbd_otg->desc->mx_ext->dLength;
transmit_data = true; transmit_data = true;
break; break;
@@ -1294,7 +1328,7 @@ static int _usbd_handle_ep0_control_transfer()
// Transmit data to HOST if any. // Transmit data to HOST if any.
if (transmit_data) if (transmit_data)
{ {
memcpy(usb_ep0_ctrl_buf, descriptor, size); memcpy(usb_ep0_ctrl_buf, desc, size);
if (_wLength < size) if (_wLength < size)
size = _wLength; size = _wLength;
@@ -1393,7 +1427,7 @@ int usb_device_enumerate(usb_gadget_type gadget)
return _usbd_ep0_initialize(); return _usbd_ep0_initialize();
} }
int usbd_handle_ep0_ctrl_setup() int usbd_handle_ep0_ctrl_setup(u32 *data)
{ {
// Acknowledge setup request for EP0 and copy its configuration. // Acknowledge setup request for EP0 and copy its configuration.
u32 ep0_setup_req = usbd_otg->regs->endptsetupstat; u32 ep0_setup_req = usbd_otg->regs->endptsetupstat;
@@ -1405,6 +1439,15 @@ int usbd_handle_ep0_ctrl_setup()
memset(usb_ep0_ctrl_buf, 0, USB_TD_BUFFER_PAGE_SIZE); memset(usb_ep0_ctrl_buf, 0, USB_TD_BUFFER_PAGE_SIZE);
} }
if (usbd_otg->intr_idle_req)
{
if (data)
*data = usbd_otg->intr_idle_rate;
usbd_otg->intr_idle_req = false;
return USB_RES_OK;
}
// Only return error if bulk reset was requested. // Only return error if bulk reset was requested.
if (usbd_otg->bulk_reset_req) if (usbd_otg->bulk_reset_req)
{ {
@@ -1487,7 +1530,7 @@ int usb_device_ep1_out_reading_finish(u32 *pending_bytes, u32 sync_timeout)
if ((ep_status == USB_EP_STATUS_IDLE) || (ep_status == USB_EP_STATUS_DISABLED)) if ((ep_status == USB_EP_STATUS_IDLE) || (ep_status == USB_EP_STATUS_DISABLED))
break; break;
usbd_handle_ep0_ctrl_setup(); usbd_handle_ep0_ctrl_setup(NULL);
} }
while ((ep_status == USB_EP_STATUS_ACTIVE) || (ep_status == USB_EP_STATUS_STALLED)); while ((ep_status == USB_EP_STATUS_ACTIVE) || (ep_status == USB_EP_STATUS_STALLED));
@@ -1536,7 +1579,7 @@ int usb_device_ep1_in_writing_finish(u32 *pending_bytes, u32 sync_timeout)
if ((ep_status == USB_EP_STATUS_IDLE) || (ep_status == USB_EP_STATUS_DISABLED)) if ((ep_status == USB_EP_STATUS_IDLE) || (ep_status == USB_EP_STATUS_DISABLED))
break; break;
usbd_handle_ep0_ctrl_setup(); usbd_handle_ep0_ctrl_setup(NULL);
} }
while ((ep_status == USB_EP_STATUS_ACTIVE) || (ep_status == USB_EP_STATUS_STALLED)); while ((ep_status == USB_EP_STATUS_ACTIVE) || (ep_status == USB_EP_STATUS_STALLED));
@@ -1572,7 +1615,7 @@ int usb_device_class_send_max_lun(u8 max_lun)
while (!usbd_otg->max_lun_set) while (!usbd_otg->max_lun_set)
{ {
usbd_handle_ep0_ctrl_setup(); usbd_handle_ep0_ctrl_setup(NULL);
if (timer < get_tmr_ms() || btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN)) if (timer < get_tmr_ms() || btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
return USB_ERROR_USER_ABORT; return USB_ERROR_USER_ABORT;
} }
@@ -1580,15 +1623,19 @@ int usb_device_class_send_max_lun(u8 max_lun)
return USB_RES_OK; return USB_RES_OK;
} }
int usb_device_class_send_hid_report() int usb_device_class_send_hid_report(void *rpt_buffer, u32 rpt_size)
{ {
// Set buffers.
usbd_otg->hid_rpt_buffer = rpt_buffer;
usbd_otg->hid_rpt_size = rpt_size;
// Timeout if get GET_HID_REPORT request doesn't happen in 10s. // Timeout if get GET_HID_REPORT request doesn't happen in 10s.
u32 timer = get_tmr_ms() + 10000; u32 timer = get_tmr_ms() + 10000;
// Wait for request and transfer start. // Wait for request and transfer start.
while (!usbd_otg->hid_report_sent) while (!usbd_otg->hid_report_sent)
{ {
usbd_handle_ep0_ctrl_setup(); usbd_handle_ep0_ctrl_setup(NULL);
if (timer < get_tmr_ms() || btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN)) if (timer < get_tmr_ms() || btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
return USB_ERROR_USER_ABORT; return USB_ERROR_USER_ABORT;
} }

View File

@@ -1,7 +1,7 @@
/* /*
* Enhanced & eXtensible USB Device (EDCI & XDCI) driver for Tegra X1 * Enhanced & eXtensible USB Device (EDCI & XDCI) driver for Tegra X1
* *
* Copyright (c) 2019-2021 CTCaer * Copyright (c) 2019-2025 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,
@@ -31,11 +31,11 @@
#define USB_EP_BUFFER_ALIGN (USB_TD_BUFFER_PAGE_SIZE) #define USB_EP_BUFFER_ALIGN (USB_TD_BUFFER_PAGE_SIZE)
#define USB_XFER_START 0 #define USB_XFER_START 0
#define USB_XFER_SYNCED_ENUM 1000000 #define USB_XFER_SYNCED_ENUM 1000000 // ~2s.
#define USB_XFER_SYNCED_CMD 1000000 #define USB_XFER_SYNCED_CMD 1000000 // ~2s.
#define USB_XFER_SYNCED_DATA 2000000 #define USB_XFER_SYNCED_DATA 2000000 // ~4s.
#define USB_XFER_SYNCED_CLASS 5000000 #define USB_XFER_SYNCED_CLASS 5000000 // ~10s.
#define USB_XFER_SYNCED -1 #define USB_XFER_SYNCED -1 // Max.
typedef enum _usb_hid_type typedef enum _usb_hid_type
{ {
@@ -122,6 +122,9 @@ typedef enum {
USB_REQUEST_GET_MS_DESCRIPTOR = 0x99, USB_REQUEST_GET_MS_DESCRIPTOR = 0x99,
USB_REQUEST_INTR_GET_REPORT = 1,
USB_REQUEST_INTR_SET_IDLE = 10,
USB_REQUEST_BULK_GET_MAX_LUN = 0xFE, USB_REQUEST_BULK_GET_MAX_LUN = 0xFE,
USB_REQUEST_BULK_RESET = 0xFF USB_REQUEST_BULK_RESET = 0xFF
} usb_standard_req_t; } usb_standard_req_t;
@@ -167,12 +170,13 @@ typedef struct _usb_ops_t
{ {
int (*usbd_flush_endpoint)(u32); int (*usbd_flush_endpoint)(u32);
int (*usbd_set_ep_stall)(u32, int); int (*usbd_set_ep_stall)(u32, int);
int (*usbd_handle_ep0_ctrl_setup)(); int (*usbd_handle_ep0_ctrl_setup)(u32 *);
void (*usbd_end)(bool, bool); void (*usbd_end)(bool, bool);
int (*usb_device_init)(); int (*usb_device_init)();
int (*usb_device_enumerate)(usb_gadget_type gadget); int (*usb_device_enumerate)(usb_gadget_type);
int (*usb_device_class_send_max_lun)(u8); int (*usb_device_class_send_max_lun)(u8);
int (*usb_device_class_send_hid_report)(); int (*usb_device_class_send_hid_report)(void *, u32);
int (*usb_device_ep1_out_read)(u8 *, u32, u32 *, u32); int (*usb_device_ep1_out_read)(u8 *, u32, u32 *, u32);
int (*usb_device_ep1_out_read_big)(u8 *, u32, u32 *); int (*usb_device_ep1_out_read_big)(u8 *, u32, u32 *);
@@ -186,10 +190,17 @@ typedef struct _usb_ops_t
typedef struct _usb_ctxt_t typedef struct _usb_ctxt_t
{ {
u32 type; u32 type;
// UMS.
u32 partition; u32 partition;
u32 offset; u32 offset;
u32 sectors; u32 sectors;
u32 ro; u32 ro;
// HID.
u32 idle;
// System.
void (*system_maintenance)(bool); void (*system_maintenance)(bool);
void *label; void *label;
void (*set_text)(void *, const char *); void (*set_text)(void *, const char *);
@@ -201,4 +212,4 @@ void xusb_device_get_ops(usb_ops_t *ops);
int usb_device_gadget_ums(usb_ctxt_t *usbs); int usb_device_gadget_ums(usb_ctxt_t *usbs);
int usb_device_gadget_hid(usb_ctxt_t *usbs); int usb_device_gadget_hid(usb_ctxt_t *usbs);
#endif #endif

View File

@@ -1,7 +1,7 @@
/* /*
* eXtensible USB Device driver (XDCI) for Tegra X1 * eXtensible USB Device driver (XDCI) for Tegra X1
* *
* Copyright (c) 2020-2024 CTCaer * Copyright (c) 2020-2025 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,
@@ -381,6 +381,10 @@ typedef struct _xusbd_controller_t
u8 max_lun; u8 max_lun;
bool max_lun_set; bool max_lun_set;
void *hid_rpt_buffer;
u32 hid_rpt_size;
u32 intr_idle_rate;
bool intr_idle_req;
bool bulk_reset_req; bool bulk_reset_req;
} xusbd_controller_t; } xusbd_controller_t;
@@ -1469,20 +1473,39 @@ static int _xusb_handle_get_class_request(const usb_ctrl_setup_t *ctrl_setup)
u16 _wLength = ctrl_setup->wLength; u16 _wLength = ctrl_setup->wLength;
bool valid_interface = _wIndex == usbd_xotg->interface_num; bool valid_interface = _wIndex == usbd_xotg->interface_num;
bool valid_len = (_bRequest == USB_REQUEST_BULK_GET_MAX_LUN) ? 1 : 0; bool valid_val = (_bRequest >= USB_REQUEST_BULK_GET_MAX_LUN) ? (!_wValue) : true;
if (!valid_interface || _wValue != 0 || _wLength != valid_len) if (!valid_interface || !valid_val)
goto stall; goto stall;
switch (_bRequest) switch (_bRequest)
{ {
case USB_REQUEST_INTR_GET_REPORT:
if (usbd_xotg->hid_rpt_size != _wLength)
goto stall;
// _wValue unused as there's only one report type and id.
return _xusb_issue_data_trb(usbd_xotg->hid_rpt_buffer, usbd_xotg->hid_rpt_size, USB_DIR_IN);
case USB_REQUEST_INTR_SET_IDLE:
if (_wLength)
goto stall;
usbd_xotg->intr_idle_rate = (_wValue & 0xFF) * 4 * 1000; // Only one interface so upper byte ignored.
usbd_xotg->intr_idle_req = true;
return _xusb_issue_status_trb(USB_DIR_IN); // DELAYED_STATUS;
case USB_REQUEST_BULK_RESET: case USB_REQUEST_BULK_RESET:
if (_wLength)
goto stall;
usbd_xotg->bulk_reset_req = true; usbd_xotg->bulk_reset_req = true;
return _xusb_issue_status_trb(USB_DIR_IN); // DELAYED_STATUS; return _xusb_issue_status_trb(USB_DIR_IN); // DELAYED_STATUS;
case USB_REQUEST_BULK_GET_MAX_LUN: case USB_REQUEST_BULK_GET_MAX_LUN:
if (!usbd_xotg->max_lun_set) if (_wLength != 1 || !usbd_xotg->max_lun_set)
goto stall; goto stall;
usbd_xotg->device_state = XUSB_LUN_CONFIGURED_STS_WAIT; usbd_xotg->device_state = XUSB_LUN_CONFIGURED_STS_WAIT;
return _xusb_issue_data_trb(&usbd_xotg->max_lun, 1, USB_DIR_IN); return _xusb_issue_data_trb(&usbd_xotg->max_lun, 1, USB_DIR_IN);
} }
@@ -1495,7 +1518,7 @@ stall:
static int _xusb_handle_get_descriptor(const usb_ctrl_setup_t *ctrl_setup) static int _xusb_handle_get_descriptor(const usb_ctrl_setup_t *ctrl_setup)
{ {
u32 size; u32 size;
void *descriptor; void *desc;
u32 wLength = ctrl_setup->wLength; u32 wLength = ctrl_setup->wLength;
@@ -1513,7 +1536,7 @@ static int _xusb_handle_get_descriptor(const usb_ctrl_setup_t *ctrl_setup)
usb_device_descriptor.bcdDevice = (soc_rev >> 16) & 0xF; // MINORREV. usb_device_descriptor.bcdDevice = (soc_rev >> 16) & 0xF; // MINORREV.
usb_device_descriptor.bcdDevice |= ((soc_rev >> 4) & 0xF) << 8; // MAJORREV. usb_device_descriptor.bcdDevice |= ((soc_rev >> 4) & 0xF) << 8; // MAJORREV.
*/ */
descriptor = usbd_xotg->desc->dev; desc = usbd_xotg->desc->dev;
size = usbd_xotg->desc->dev->bLength; size = usbd_xotg->desc->dev->bLength;
break; break;
case USB_DESCRIPTOR_CONFIGURATION: case USB_DESCRIPTOR_CONFIGURATION:
@@ -1522,13 +1545,13 @@ static int _xusb_handle_get_descriptor(const usb_ctrl_setup_t *ctrl_setup)
{ {
if (usbd_xotg->port_speed == XUSB_HIGH_SPEED) // High speed. 512 bytes. if (usbd_xotg->port_speed == XUSB_HIGH_SPEED) // High speed. 512 bytes.
{ {
usbd_xotg->desc->cfg->endpoint[0].wMaxPacketSize = 0x200; // No burst. for (u32 i = 0; i < usbd_xotg->desc->cfg->interface.bNumEndpoints; i++)
usbd_xotg->desc->cfg->endpoint[1].wMaxPacketSize = 0x200; // No burst. usbd_xotg->desc->cfg->endpoint[i].wMaxPacketSize = 0x200; // No burst.
} }
else // Full speed. 64 bytes. else // Full speed. 64 bytes.
{ {
usbd_xotg->desc->cfg->endpoint[0].wMaxPacketSize = 0x40; for (u32 i = 0; i < usbd_xotg->desc->cfg->interface.bNumEndpoints; i++)
usbd_xotg->desc->cfg->endpoint[1].wMaxPacketSize = 0x40; usbd_xotg->desc->cfg->endpoint[i].wMaxPacketSize = 0x40;
} }
} }
else else
@@ -1536,43 +1559,45 @@ static int _xusb_handle_get_descriptor(const usb_ctrl_setup_t *ctrl_setup)
usb_cfg_hid_descr_t *tmp = (usb_cfg_hid_descr_t *)usbd_xotg->desc->cfg; usb_cfg_hid_descr_t *tmp = (usb_cfg_hid_descr_t *)usbd_xotg->desc->cfg;
if (usbd_xotg->port_speed == XUSB_HIGH_SPEED) // High speed. 512 bytes. if (usbd_xotg->port_speed == XUSB_HIGH_SPEED) // High speed. 512 bytes.
{ {
tmp->endpoint[0].wMaxPacketSize = 0x200; for (u32 i = 0; i < tmp->interface.bNumEndpoints; i++)
tmp->endpoint[1].wMaxPacketSize = 0x200; {
tmp->endpoint[0].bInterval = usbd_xotg->gadget == USB_GADGET_HID_GAMEPAD ? 4 : 3; // 8ms : 4ms. tmp->endpoint[i].wMaxPacketSize = 0x200;
tmp->endpoint[1].bInterval = usbd_xotg->gadget == USB_GADGET_HID_GAMEPAD ? 4 : 3; // 8ms : 4ms. tmp->endpoint[i].bInterval = usbd_xotg->gadget == USB_GADGET_HID_GAMEPAD ? 4 : 3; // 8ms : 4ms.
}
} }
else // Full speed. 64 bytes. else // Full speed. 64 bytes.
{ {
tmp->endpoint[0].wMaxPacketSize = 0x40; for (u32 i = 0; i < tmp->interface.bNumEndpoints; i++)
tmp->endpoint[1].wMaxPacketSize = 0x40; {
tmp->endpoint[0].bInterval = usbd_xotg->gadget == USB_GADGET_HID_GAMEPAD ? 8 : 4; // 8ms : 4ms. tmp->endpoint[i].wMaxPacketSize = 0x40;
tmp->endpoint[1].bInterval = usbd_xotg->gadget == USB_GADGET_HID_GAMEPAD ? 8 : 4; // 8ms : 4ms. tmp->endpoint[i].bInterval = usbd_xotg->gadget == USB_GADGET_HID_GAMEPAD ? 8 : 4; // 8ms : 4ms.
}
} }
} }
descriptor = usbd_xotg->desc->cfg; desc = usbd_xotg->desc->cfg;
size = usbd_xotg->desc->cfg->config.wTotalLength; size = usbd_xotg->desc->cfg->config.wTotalLength;
break; break;
case USB_DESCRIPTOR_STRING: case USB_DESCRIPTOR_STRING:
switch (descriptor_subtype) switch (descriptor_subtype)
{ {
case 1: case 1:
descriptor = usbd_xotg->desc->vendor; desc = usbd_xotg->desc->vendor;
size = usbd_xotg->desc->vendor[0]; size = usbd_xotg->desc->vendor[0];
break; break;
case 2: case 2:
descriptor = usbd_xotg->desc->product; desc = usbd_xotg->desc->product;
size = usbd_xotg->desc->product[0]; size = usbd_xotg->desc->product[0];
break; break;
case 3: case 3:
descriptor = usbd_xotg->desc->serial; desc = usbd_xotg->desc->serial;
size = usbd_xotg->desc->serial[0]; size = usbd_xotg->desc->serial[0];
break; break;
case 0xEE: case 0xEE:
descriptor = usbd_xotg->desc->ms_os; desc = usbd_xotg->desc->ms_os;
size = usbd_xotg->desc->ms_os->bLength; size = usbd_xotg->desc->ms_os->bLength;
break; break;
default: default:
descriptor = usbd_xotg->desc->lang_id; desc = usbd_xotg->desc->lang_id;
size = 4; size = 4;
break; break;
} }
@@ -1584,7 +1609,7 @@ static int _xusb_handle_get_descriptor(const usb_ctrl_setup_t *ctrl_setup)
return USB_RES_OK; return USB_RES_OK;
} }
usbd_xotg->desc->dev_qual->bNumOtherConfigs = 0; usbd_xotg->desc->dev_qual->bNumOtherConfigs = 0;
descriptor = usbd_xotg->desc->dev_qual; desc = usbd_xotg->desc->dev_qual;
size = usbd_xotg->desc->dev_qual->bLength; size = usbd_xotg->desc->dev_qual->bLength;
break; break;
case USB_DESCRIPTOR_OTHER_SPEED_CONFIGURATION: case USB_DESCRIPTOR_OTHER_SPEED_CONFIGURATION:
@@ -1595,19 +1620,19 @@ static int _xusb_handle_get_descriptor(const usb_ctrl_setup_t *ctrl_setup)
} }
if (usbd_xotg->port_speed == XUSB_HIGH_SPEED) if (usbd_xotg->port_speed == XUSB_HIGH_SPEED)
{ {
usbd_xotg->desc->cfg_other->endpoint[0].wMaxPacketSize = 0x40; for (u32 i = 0; i < usbd_xotg->desc->cfg_other->interface.bNumEndpoints; i++)
usbd_xotg->desc->cfg_other->endpoint[1].wMaxPacketSize = 0x40; usbd_xotg->desc->cfg_other->endpoint[i].wMaxPacketSize = 0x40;
} }
else else
{ {
usbd_xotg->desc->cfg_other->endpoint[0].wMaxPacketSize = 0x200; for (u32 i = 0; i < usbd_xotg->desc->cfg_other->interface.bNumEndpoints; i++)
usbd_xotg->desc->cfg_other->endpoint[1].wMaxPacketSize = 0x200; usbd_xotg->desc->cfg_other->endpoint[i].wMaxPacketSize = 0x200;
} }
descriptor = usbd_xotg->desc->cfg_other; desc = usbd_xotg->desc->cfg_other;
size = usbd_xotg->desc->cfg_other->config.wTotalLength; size = usbd_xotg->desc->cfg_other->config.wTotalLength;
break; break;
case USB_DESCRIPTOR_DEVICE_BINARY_OBJECT: case USB_DESCRIPTOR_DEVICE_BINARY_OBJECT:
descriptor = usbd_xotg->desc->dev_bot; desc = usbd_xotg->desc->dev_bot;
size = usbd_xotg->desc->dev_bot->wTotalLength; size = usbd_xotg->desc->dev_bot->wTotalLength;
break; break;
default: default:
@@ -1618,7 +1643,7 @@ static int _xusb_handle_get_descriptor(const usb_ctrl_setup_t *ctrl_setup)
if (wLength < size) if (wLength < size)
size = wLength; size = wLength;
return _xusb_issue_data_trb(descriptor, size, USB_DIR_IN); return _xusb_issue_data_trb(desc, size, USB_DIR_IN);
} }
static void _xusb_handle_set_request_dev_address(const usb_ctrl_setup_t *ctrl_setup) static void _xusb_handle_set_request_dev_address(const usb_ctrl_setup_t *ctrl_setup)
@@ -1688,18 +1713,18 @@ static int _xusbd_handle_ep0_control_transfer(usb_ctrl_setup_t *ctrl_setup)
switch (_bmRequestType) switch (_bmRequestType)
{ {
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_DEVICE): case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_DEVICE): // 0x00.
if (_bRequest == USB_REQUEST_SET_ADDRESS) if (_bRequest == USB_REQUEST_SET_ADDRESS)
_xusb_handle_set_request_dev_address(ctrl_setup); _xusb_handle_set_request_dev_address(ctrl_setup);
else if (_bRequest == USB_REQUEST_SET_CONFIGURATION) else if (_bRequest == USB_REQUEST_SET_CONFIGURATION)
_xusb_handle_set_request_configuration(ctrl_setup); _xusb_handle_set_request_configuration(ctrl_setup);
return USB_RES_OK; // What about others. return USB_RES_OK; // What about others.
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_INTERFACE): case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_INTERFACE): // 0x01.
usbd_xotg->interface_num = _wValue; usbd_xotg->interface_num = _wValue;
return _xusb_issue_status_trb(USB_DIR_IN); return _xusb_issue_status_trb(USB_DIR_IN);
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT): case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT): // 0x02.
if ((_wValue & 0xFF) == USB_FEATURE_ENDPOINT_HALT) if ((_wValue & 0xFF) == USB_FEATURE_ENDPOINT_HALT)
{ {
if (_bRequest == USB_REQUEST_CLEAR_FEATURE || _bRequest == USB_REQUEST_SET_FEATURE) if (_bRequest == USB_REQUEST_CLEAR_FEATURE || _bRequest == USB_REQUEST_SET_FEATURE)
@@ -1735,10 +1760,10 @@ static int _xusbd_handle_ep0_control_transfer(usb_ctrl_setup_t *ctrl_setup)
ep_stall = true; ep_stall = true;
break; break;
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE): case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE): // 0x21.
return _xusb_handle_get_class_request(ctrl_setup); return _xusb_handle_get_class_request(ctrl_setup);
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_DEVICE): case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_DEVICE): // 0x80.
switch (_bRequest) switch (_bRequest)
{ {
case USB_REQUEST_GET_STATUS: case USB_REQUEST_GET_STATUS:
@@ -1760,7 +1785,7 @@ static int _xusbd_handle_ep0_control_transfer(usb_ctrl_setup_t *ctrl_setup)
} }
break; break;
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_INTERFACE): case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_INTERFACE): // 0x81.
if (_bRequest == USB_REQUEST_GET_INTERFACE) if (_bRequest == USB_REQUEST_GET_INTERFACE)
{ {
desc = xusb_interface_descriptor; desc = xusb_interface_descriptor;
@@ -1774,7 +1799,7 @@ static int _xusbd_handle_ep0_control_transfer(usb_ctrl_setup_t *ctrl_setup)
size = sizeof(xusb_status_descriptor); size = sizeof(xusb_status_descriptor);
transmit_data = true; transmit_data = true;
} }
else if (_bRequest == USB_REQUEST_GET_DESCRIPTOR && (_wValue >> 8) == USB_DESCRIPTOR_HID_REPORT && usbd_xotg->gadget > USB_GADGET_UMS) else if (_bRequest == USB_REQUEST_GET_DESCRIPTOR && (_wValue >> 8) == USB_DESCRIPTOR_HID_REPORT && usbd_xotg->gadget >= USB_GADGET_HID_GAMEPAD)
{ {
if (usbd_xotg->gadget == USB_GADGET_HID_GAMEPAD) if (usbd_xotg->gadget == USB_GADGET_HID_GAMEPAD)
{ {
@@ -1793,7 +1818,7 @@ static int _xusbd_handle_ep0_control_transfer(usb_ctrl_setup_t *ctrl_setup)
ep_stall = true; ep_stall = true;
break; break;
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT): case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT): // 0x82.
if (_bRequest == USB_REQUEST_GET_STATUS) if (_bRequest == USB_REQUEST_GET_STATUS)
{ {
u32 ep = 0; u32 ep = 0;
@@ -1821,11 +1846,11 @@ static int _xusbd_handle_ep0_control_transfer(usb_ctrl_setup_t *ctrl_setup)
ep_stall = true; ep_stall = true;
break; break;
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE): case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE): // 0xA1.
return _xusb_handle_get_class_request(ctrl_setup); return _xusb_handle_get_class_request(ctrl_setup);
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_VENDOR | USB_SETUP_RECIPIENT_INTERFACE): case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_VENDOR | USB_SETUP_RECIPIENT_DEVICE): // 0xC0.
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_VENDOR | USB_SETUP_RECIPIENT_DEVICE): case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_VENDOR | USB_SETUP_RECIPIENT_INTERFACE): // 0xC1.
if (_bRequest == USB_REQUEST_GET_MS_DESCRIPTOR) if (_bRequest == USB_REQUEST_GET_MS_DESCRIPTOR)
{ {
switch (_wIndex) switch (_wIndex)
@@ -2017,12 +2042,24 @@ void xusb_end(bool reset_ep, bool only_controller)
_xusb_device_power_down(); _xusb_device_power_down();
} }
int xusb_handle_ep0_ctrl_setup() int xusb_handle_ep0_ctrl_setup(u32 *data)
{ {
/* /*
* EP0 Control handling is done by normal ep operation in XUSB. * EP0 Control handling is done by normal ep operation in XUSB.
* Here we handle the bulk reset only. * Here we handle the interface only, except if HID.
*/ */
if (usbd_xotg->gadget >= USB_GADGET_HID_GAMEPAD)
_xusb_ep_operation(1);
if (usbd_xotg->intr_idle_req)
{
if (data)
*data = usbd_xotg->intr_idle_rate;
usbd_xotg->intr_idle_req = false;
return USB_RES_OK;
}
if (usbd_xotg->bulk_reset_req) if (usbd_xotg->bulk_reset_req)
{ {
usbd_xotg->bulk_reset_req = false; usbd_xotg->bulk_reset_req = false;
@@ -2176,8 +2213,12 @@ bool xusb_device_class_send_max_lun(u8 max_lun)
return false; return false;
} }
bool xusb_device_class_send_hid_report() bool xusb_device_class_send_hid_report(void *rpt_buffer, u32 rpt_size)
{ {
// Set buffers.
usbd_xotg->hid_rpt_buffer = rpt_buffer;
usbd_xotg->hid_rpt_size = rpt_size;
// Timeout if get GET_HID_REPORT request doesn't happen in 10s. // Timeout if get GET_HID_REPORT request doesn't happen in 10s.
u32 timer = get_tmr_ms() + 10000; u32 timer = get_tmr_ms() + 10000;

View File

@@ -22,12 +22,15 @@
#include <mem/heap.h> #include <mem/heap.h>
#include <utils/types.h> #include <utils/types.h>
dirlist_t *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles, bool parse_dirs) dirlist_t *dirlist(const char *directory, const char *pattern, u32 flags)
{ {
int res = 0; int res = 0;
u32 k = 0; u32 k = 0;
DIR dir; DIR dir;
FILINFO fno; FILINFO fno;
bool show_hidden = !!(flags & DIR_SHOW_HIDDEN);
bool show_dirs = !!(flags & DIR_SHOW_DIRS);
bool ascii_order = !!(flags & DIR_ASCII_ORDER);
dirlist_t *dir_entries = (dirlist_t *)malloc(sizeof(dirlist_t)); dirlist_t *dir_entries = (dirlist_t *)malloc(sizeof(dirlist_t));
@@ -43,11 +46,11 @@ dirlist_t *dirlist(const char *directory, const char *pattern, bool includeHidde
if (res || !fno.fname[0]) if (res || !fno.fname[0])
break; break;
bool curr_parse = parse_dirs ? (fno.fattrib & AM_DIR) : !(fno.fattrib & AM_DIR); bool curr_parse = show_dirs ? (fno.fattrib & AM_DIR) : !(fno.fattrib & AM_DIR);
if (curr_parse) if (curr_parse)
{ {
if ((fno.fname[0] != '.') && (includeHiddenFiles || !(fno.fattrib & AM_HID))) if ((fno.fname[0] != '.') && (show_hidden || !(fno.fattrib & AM_HID)))
{ {
strcpy(&dir_entries->data[k * 256], fno.fname); strcpy(&dir_entries->data[k * 256], fno.fname);
if (++k >= DIR_MAX_ENTRIES) if (++k >= DIR_MAX_ENTRIES)
@@ -61,7 +64,7 @@ dirlist_t *dirlist(const char *directory, const char *pattern, bool includeHidde
{ {
do do
{ {
if (!(fno.fattrib & AM_DIR) && (fno.fname[0] != '.') && (includeHiddenFiles || !(fno.fattrib & AM_HID))) if (!(fno.fattrib & AM_DIR) && (fno.fname[0] != '.') && (show_hidden || !(fno.fattrib & AM_HID)))
{ {
strcpy(&dir_entries->data[k * 256], fno.fname); strcpy(&dir_entries->data[k * 256], fno.fname);
if (++k >= DIR_MAX_ENTRIES) if (++k >= DIR_MAX_ENTRIES)
@@ -82,12 +85,15 @@ dirlist_t *dirlist(const char *directory, const char *pattern, bool includeHidde
// Terminate name list. // Terminate name list.
dir_entries->name[k] = NULL; dir_entries->name[k] = NULL;
// Choose list ordering.
int (*strcmpex)(const char* str1, const char* str2) = ascii_order ? strcmp : strcasecmp;
// Reorder ini files Alphabetically. // Reorder ini files Alphabetically.
for (u32 i = 0; i < k - 1 ; i++) for (u32 i = 0; i < k - 1 ; i++)
{ {
for (u32 j = i + 1; j < k; j++) for (u32 j = i + 1; j < k; j++)
{ {
if (strcasecmp(dir_entries->name[i], dir_entries->name[j]) > 0) if (strcmpex(dir_entries->name[i], dir_entries->name[j]) > 0)
{ {
char *tmp = dir_entries->name[i]; char *tmp = dir_entries->name[i];
dir_entries->name[i] = dir_entries->name[j]; dir_entries->name[i] = dir_entries->name[j];

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018-2024 CTCaer * Copyright (c) 2018-2025 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 +18,14 @@
#define DIR_MAX_ENTRIES 64 #define DIR_MAX_ENTRIES 64
#define DIR_SHOW_HIDDEN BIT(0)
#define DIR_SHOW_DIRS BIT(1)
#define DIR_ASCII_ORDER BIT(2)
typedef struct _dirlist_t typedef struct _dirlist_t
{ {
char *name[DIR_MAX_ENTRIES]; char *name[DIR_MAX_ENTRIES];
char data[DIR_MAX_ENTRIES * 256]; char data[DIR_MAX_ENTRIES * 256];
} dirlist_t; } dirlist_t;
dirlist_t *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles, bool parse_dirs); dirlist_t *dirlist(const char *directory, const char *pattern, u32 flags);

View File

@@ -70,7 +70,7 @@ int ini_parse(link_t *dst, const char *ini_path, bool is_dir)
// Get all ini filenames. // Get all ini filenames.
if (is_dir) if (is_dir)
{ {
filelist = dirlist(filename, "*.ini", false, false); filelist = dirlist(filename, "*.ini", DIR_ASCII_ORDER);
if (!filelist) if (!filelist)
{ {
free(filename); free(filename);

256
bdk/utils/tegra_bct.h Normal file
View File

@@ -0,0 +1,256 @@
/*
* Copyright (c) 2018-2022 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* 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 TEGRA_BCT_H
#define TEGRA_BCT_H
#include <utils/types.h>
#include <mem/sdram_param_t210.h>
#include <mem/sdram_param_t210b01.h>
#define BCT_IRAM_ADDRESS 0x40000100
#define BCT_IRAM_ADDRESS_B01 0x40000464
#define BCT_BOOT_DEV_NONE 0
#define BCT_BOOT_DEV_SPI 3
#define BCT_BOOT_DEV_SDMMC 4
#define BCT_BOOT_DEV_USB3 9
#define BCT_BOOT_DEV_UART 11
// ECID is checked for the following.
#define BCT_SEC_DBG_JTAG BIT(0)
#define BCT_SEC_DBG_DEV BIT(1)
#define BCT_SEC_DBG_SPNID BIT(2)
#define BCT_SEC_DBG_SPID BIT(3)
#define BCT_SEC_DBG_NID BIT(4) // ECID not checked for T210B01.
#define BCT_SEC_DBG_DBG BIT(5) // ECID not checked for T210B01.
#define BCT_SDMMC_CFG_SDR25_SINGLE_PAGE 0
#define BCT_SDMMC_CFG_SDR52_MULTI_PAGE 1
#define BCT_SDMMC_CFG_SDR25_MULTI_PAGE 2
#define BCT_SDMMC_CFG_DDR52_MULTI_PAGE 3
#define BCT_SDMMC_CFG_DDR25_MULTI_PAGE 4
#define BCT_SPI_CFG_PIO_X1_20_4MHZ_SREAD 0
#define BCT_SPI_CFG_PIO_X1_19_2MHZ_SREAD 1
#define BCT_SPI_CFG_PIO_X4_51_0MHZ_QREAD 2
typedef struct _bct_bad_blocks_t
{
u32 used_entries; // For block table.
u8 virtual_block_size_log2;
u8 block_size_log2;
u8 block_table[512]; // Each bit is a block (4096 blocks).
u8 padding[10];
} bct_bad_blocks_t;
typedef struct _bct_sdmmc_dev_t210_t
{
u32 clk_div;
u32 bus_width;
u8 power_class_max;
u8 multi_block_max;
} bct_sdmmc_dev_t210_t;
typedef struct _bct_sdmmc_dev_t210b01_t
{
u8 sdmmc_config;
u8 power_class_max;
} bct_sdmmc_dev_t210b01_t;
typedef struct _bct_spi_dev_t210_t
{
u32 clk_src;
u8 clk_div;
u8 cmd_read_fast;
u8 page_size; // 0: 2KB, 1: 16KB.
} bct_spi_dev_t210_t;
typedef struct _bct_spi_dev_t210b01_t
{
u8 spi_config;
} bct_spi_dev_t210b01_t;
typedef struct _bct_usb3_dev_t
{
u8 clk_div;
u8 root_port;
u8 page_size; // 0: 2KB, 1: 16KB.
u8 oc_pin;
u8 vbus_en;
} bct_usb3_dev_t;
typedef union
{
bct_sdmmc_dev_t210_t sdmmc_params;
bct_spi_dev_t210_t spi_params;
bct_usb3_dev_t usb3_params;
u8 padding[64];
} bct_boot_dev_t210_t;
typedef union
{
bct_sdmmc_dev_t210b01_t sdmmc_params;
bct_spi_dev_t210b01_t spi_params;
u8 padding[64];
} bct_boot_dev_t210b01_t;
typedef struct _bct_bootloader_t210_t
{
u32 version;
u32 start_block;
u32 start_page;
u32 length; // Should be bl size + 16 and aligned to 16.
u32 load_addr;
u32 entrypoint;
u32 attributes; // ODM.
u8 aes_cmac_hash[16];
u8 rsa_pss_signature[256];
} bct_bootloader_t210_t;
typedef struct _bct_bootloader_t210b01_t
{
u32 start_block;
u32 start_page;
u32 version;
u32 padding;
} bct_bootloader_t210b01_t;
typedef struct _tegra_bct_t210_t
{
/* Unsigned section */
bct_bad_blocks_t bad_block_table;
u8 rsa_modulus[256];
u8 aes_cmac_hash[16];
u8 rsa_pss_signature[256];
u32 secprov_aes_key_num_insecure;
u8 secprov_aes_key[32];
u8 customer_data[204];
/* Signed section */
u8 random_aes_block[16];
u32 ecid[4];
u32 data_version; // 0x210001.
u32 block_size_log2;
u32 page_size_log2;
u32 partition_size;
u32 boot_dev_params_num;
u32 boot_dev_type;
bct_boot_dev_t210_t boot_dev_params;
u32 dram_params_num;
sdram_params_t210_t dram_params[4];
u32 bootloader_num;
bct_bootloader_t210_t bootLoader[4];
u32 bootloader_failback_en;
u32 sec_dbg_ctrl; // Copied to APBDEV_PMC_DEBUG_AUTHENTICATION. ECID checked.
u32 secprov_aes_key_num_secure;
u8 padding[20];
} tegra_bct_t210_t;
typedef struct _tegra_bct_t210b01_t
{
/* Unsigned section */
u32 rsa_key_size;
u32 padding0[3];
u8 rsa_modulus[256];
u8 rsa_exponent[256];
u8 aes_cmac_hash[16];
u8 rsa_pss_signature[256];
u8 secprov_aes_key[32];
u32 secprov_aes_key_num_insecure;
u8 padding_unsigned[12];
u8 customer_data0[208];
/* Signed section */
u8 random_aes_block0[16];
u32 boot_config0[4]; // Customer controlled features.
/// Unused space allocated for customer usage.
u32 customer_data1_signed[16];
/* Encrypted section (optionally) */
u8 random_aes_block1[16];
u32 ecid[4];
u32 data_version; // 0x210001.
u32 block_size_log2;
u32 page_size_log2;
u32 partition_size;
u32 boot_dev_params_num;
u32 boot_dev_type;
bct_boot_dev_t210b01_t boot_dev_params;
u32 dram_params_num;
sdram_params_t210b01_t dram_params[4];
u32 bootloader_num;
bct_bootloader_t210b01_t bootLoader[4];
u32 sec_dbg_ctrl; // Copied to APBDEV_PMC_DEBUG_AUTHENTICATION. ECID not checked.
u32 sec_dbg_ctrl_ecid; // Copied to APBDEV_PMC_DEBUG_AUTHENTICATION. ECID checked.
u32 boot_config1[4]; // Customer controlled features. bit0 AON TZRAM powergating enable
u32 customer_data2_signed[16]; // u32[0]: bl attributes.
u32 secprov_aes_key_num_secure;
u8 padding_signed[388];
} tegra_bct_t210b01_t;
typedef struct _bootLoader_hdr_t210b01_t
{
/* Unsigned section */
u8 aes_cmac_hash[16];
u8 rsa_pss_signature[256];
/* Signed section */
u8 salt[16]; // random_aes_block.
u8 bootLoader_sha256[16];
u32 version;
u32 length;
u32 load_addr;
u32 entrypoint;
u8 padding[16];
} bootLoader_hdr_t210b01_t;
#endif

362
bdk/utils/tegra_bit.h Normal file
View File

@@ -0,0 +1,362 @@
/*
* Copyright (c) 2018-2022 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* 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 TEGRA_BIT_H
#define TEGRA_BIT_H
#include <utils/types.h>
#define BIT_ADDRESS 0x40000000
#define BIT_BOOT_TYPE_NONE 0
#define BIT_BOOT_TYPE_COLD 1
#define BIT_BOOT_TYPE_RCM 2
#define BIT_BOOT_TYPE_UART 3
#define BIT_BOOT_TYPE_EXIT_RCM 4
#define BIT_READ_STATUS_NONE 0
#define BIT_READ_STATUS_SUCCESS 1
#define BIT_READ_STATUS_VALIDATION_ERROR 2
#define BIT_READ_STATUS_HW_READ_ERROR 3
#define BIT_USB_CHARGE_DETECT_EN BIT(0)
#define BIT_USB_CHARGE_LOW_BATT BIT(1)
#define BIT_USB_CHARGE_CONNECTED BIT(2)
#define BIT_USB_CHARGE_HI_CURRENT BIT(8)
// From T186 with some additions.
enum
{
BIT_FLOW_STATUS_NONE = 0,
BIT_FLOW_STATUS_IPATCHUNCORRECTED_ERROR = 1,
BIT_FLOW_STATUS_IPATCHSUCCESS = 2,
BIT_FLOW_STATUS_SETUPOSCCLK = 3,
BIT_FLOW_STATUS_LOWBAT_NOTCHARGED = 4,
BIT_FLOW_STATUS_LOWBAT_CHARGED = 5,
BIT_FLOW_STATUS_PLLPENABLED = 6,
BIT_FLOW_STATUS_MSSINITIALIZED = 7,
BIT_FLOW_STATUS_FABRICINITIALIZED = 8,
BIT_FLOW_STATUS_NONSECUREDISPATCHERENTRY = 9,
BIT_FLOW_STATUS_NONSECUREDISPATCHEREXIT = 10,
BIT_FLOW_STATUS_FAMODE = 11,
BIT_FLOW_STATUS_PREPRODUCTIONMODEUART = 12,
BIT_FLOW_STATUS_PRODUCTIONMODE = 13,
BIT_FLOW_STATUS_ODMPRODUCTIONMODE = 14,
BIT_FLOW_STATUS_DBGRCMMODE = 15,
BIT_FLOW_STATUS_RECOVERYMODE = 16,
BIT_FLOW_STATUS_SECUREDISPATCHERENTRY = 17,
BIT_FLOW_STATUS_SECUREDISPATCHEREXIT = 18,
BIT_FLOW_STATUS_RAMDUMPINIT = 19,
BIT_FLOW_STATUS_RAMDUMPEXIT = 20,
BIT_FLOW_STATUS_COLDBOOTENTRY = 21,
BIT_FLOW_STATUS_COLDBOOTEXIT = 22,
BIT_FLOW_STATUS_CBSETUPBOOTDEVICE = 23,
BIT_FLOW_STATUS_CBBCTDONE = 24,
BIT_FLOW_STATUS_MSSREGIONUNINITIALIZED = 25,
BIT_FLOW_STATUS_MSSREGIONENABLEINITIALIZED = 26,
BIT_FLOW_STATUS_CBMTSPREBOOTINIT = 27,
BIT_FLOW_STATUS_CBREINITSUCCESS = 28,
BIT_FLOW_STATUS_CBSDRAMINITSUCCESS = 29,
BIT_FLOW_STATUS_CBPAYLOADSUCCESS = 30,
BIT_FLOW_STATUS_RCMENTRY = 31,
BIT_FLOW_STATUS_RCMEXIT = 32,
BIT_FLOW_STATUS_SC7ENTRY = 33,
BIT_FLOW_STATUS_SC7ACKWAYPOINT = 34,
BIT_FLOW_STATUS_SC7DBELLERROR = 35,
BIT_FLOW_STATUS_SC7EXIT = 36,
BIT_FLOW_STATUS_SECUREBOOTENTRY = 37,
BIT_FLOW_STATUS_SECUREBOOTEXIT = 38,
BIT_FLOW_STATUS_DETECTEDWDTRESET = 39,
BIT_FLOW_STATUS_DETECTEDAOTAG_SENSORRESET = 40,
BIT_FLOW_STATUS_DETECTEDVFSENSORRESET = 41,
BIT_FLOW_STATUS_DETECTEDSWMAINRESET = 42,
BIT_FLOW_STATUS_DETECTEDHSMRESET = 43,
BIT_FLOW_STATUS_DETECTEDCSITEDBGRESET = 44,
BIT_FLOW_STATUS_DETECTEDSC7SPEWDT_0_RESET = 45,
BIT_FLOW_STATUS_DETECTEDSC7SPEWDT_1_RESET = 46,
BIT_FLOW_STATUS_DETECTEDSYSRESETN = 47,
BIT_FLOW_STATUS_CRYPTOINITENTRY = 48,
BIT_FLOW_STATUS_CRYPTOINITEXIT = 49,
BIT_FLOW_STATUS_SECUREEXITSTART = 50
};
typedef struct _bit_flow_log_t
{
u32 Init_time;
u32 exit_time;
u32 func_id;
u32 func_status;
} bit_flow_log_t;
typedef struct _bit_boot_sdmmc_status_t210_t
{
u8 fuses_bus_width;
u8 fuses_voltage_range;
u8 fuses_boo_mode_disable;
u8 fuses_drd_mode;
u32 card_type;
u32 voltage_range;
u8 bus_width;
u8 power_class;
u8 auto_cal_status;
u8 padding;
u32 cid[4];
u32 pages_read;
u32 crc_errors;
u8 boot_from_boot_partition;
u8 boot_mode_read_success;
} bit_boot_sdmmc_status_t210_t;
typedef struct _bit_boot_sdmmc_status_t210b01_t
{
u8 clk_src;
u8 clk_div;
u8 clk_en;
u8 clk_rst_status;
u8 clk_div_internal;
u8 data_mode;
u8 fuses_bus_width;
u8 fuses_drd_mode;
u8 fuses_config;
u8 fuses_read_mode;
u8 card_type;
u32 voltage_range;
u8 bus_width;
u8 power_class;
u8 auto_cal_status;
u32 cid[4];
u32 pages_read;
u32 crc_errors;
u8 boot_from_boot_partition;
u32 time_init;
u32 time_controller_init;
u32 time_card_enumeration;
u32 time_cmd1_op_cond;
u32 time_cmd2_cid;
u32 time_cmd9_csd;
u32 time_transfer_mode;
u32 time_cmd8_ext_csd;
u32 time_power_class;
u32 time_bus_width_and_partition;
u32 time_read;
u32 payload_size;
} bit_boot_sdmmc_status_t210b01_t;
typedef struct _bit_boot_spi_status_t210_t
{
u32 clk_src;
u32 clk_div;
u32 fast_read;
u32 pages_read;
u32 last_block_read;
u32 last_page_read;
u32 boot_status;
u32 init_status;
u32 read_status;
u32 params_validated;
} bit_boot_spi_status_t210_t;
typedef struct _bit_boot_spi_status_t210b01_t
{
u32 clk_en;
u32 clk_rst_status;
u32 mode;
u32 bus_width;
u32 clk_src;
u32 clk_div;
u32 fast_read;
u32 pages_read;
u32 last_block_read;
u32 last_page_read;
u32 boot_status;
u32 init_status;
u32 read_status;
u32 params_validated;
u32 time_qspi_init;
u32 time_read_time;
u32 payload_size;
} bit_boot_spi_status_t210b01_t;
typedef struct _bit_boot_usb3_status_t
{
u8 port;
u8 sense_key;
u8 padding[2];
u32 cur_csw_tag;
u32 curr_cmd_csw_status;
u32 curr_ep_xfer_failed_bytes;
u32 periph_dev_type;
u32 block_num;
u32 last_logical_block_addr;
u32 block_length;
u32 usb3_ctxt;
u32 init_res;
u32 read_page_res;
u32 xusb_driver_status;
u32 dev_status;
u32 ep_status;
} bit_boot_usb3_status_t;
typedef union _bit_boot_secondary_dev_status_t210_t
{
bit_boot_sdmmc_status_t210_t sdmmc_status;
bit_boot_spi_status_t210_t spi_status;
bit_boot_usb3_status_t usb3_status;
u8 padding[60];
} bit_boot_secondary_dev_status_t210_t;
typedef union _bit_boot_secondary_dev_status_t210b01_t
{
bit_boot_sdmmc_status_t210b01_t sdmmc_status;
bit_boot_spi_status_t210b01_t spi_status;
u8 padding[256];
} bit_boot_secondary_dev_status_t210b01_t;
typedef struct _bit_bl_state_t
{
u32 read_status;
u32 first_ecc_block;
u32 first_ecc_page;
u32 first_corrected_ecc_block;
u32 first_corrected_ecc_page;
u8 had_ecc_error;
u8 had_crc_error;
u8 had_corrected_ecc_error;
u8 used_for_ecc_recovery;
} bit_bl_state_t;
typedef struct _tegra_bit_t210_t
{
u32 brom_version;
u32 data_version;
u32 rcm_version;
u32 boot_type;
u32 primary_dev_type;
u32 secondary_dev_type;
u32 boot_time_log_init;
u32 boot_time_log_exit;
u32 bct_read_tick_cnt;
u32 bl_read_tick_cnt;
u32 osc_frequency;
u8 dev_initialized;
u8 dram_initialized;
u8 force_recovery_bit_cleared; // APBDEV_PMC_SCRATCH0.
u8 failback_bit_cleared; // APBDEV_PMC_SCRATCH0.
u8 failback_invoked;
u8 irom_patch_status; // bit0-3: hamming status, bit7: patches exist.
u8 bct_valid;
u8 bct_status[9]; // Each bit is a block (72 blocks).
u32 bct_last_journal_read;
u32 bct_block;
u32 bct_page;
u32 bct_size;
u32 bct_ptr;
bit_bl_state_t bl_state[4];
bit_boot_secondary_dev_status_t210_t secondary_dev_status;
u32 usb_charging_status;
u32 safe_start_addr; // Init: 0x400000F4 / UART: 0x40000100 / BL: 0x40002900.
u8 padding[12];
} tegra_bit_t210_t;
typedef struct _tegra_bit_t210b01_t
{
u32 brom_version;
u32 data_version;
u32 rcm_version;
u32 boot_type;
u32 primary_dev_type;
u32 secondary_dev_type;
u32 authentication_scheme;
u32 encryption_enabled;
u32 brom_flow_tracker;
u32 reserved;
u32 boot_time_log_exit;
u32 setup_tick_cnt;
u32 bct_read_tick_cnt;
u32 bl_read_tick_cnt;
bit_flow_log_t boot_flow_log[40];
u32 osc_frequency;
u8 dev_initialized;
u8 dram_initialized;
u8 force_recovery_bit_cleared;
u8 failback_bit_cleared;
u8 failback_invoked;
u8 irom_patch_status; // bit0-3: hamming status, bit7: patches exist.
u8 bct_size_valid;
u8 bct_size_status[9];
u32 bct_size_last_journal_read;
u32 bct_size_block;
u32 bct_size_page;
u8 bct_valid;
u8 bct_status[9];
u8 padding[2];
u32 bct_last_journal_read;
u32 bct_block;
u32 bct_page;
u32 bct_size;
u32 bct_ptr;
bit_bl_state_t bl_state[4];
bit_boot_secondary_dev_status_t210b01_t secondary_dev_status;
u32 usb_charging_status;
u8 pmu_boot_sel_read_error;
u32 safe_start_addr; // Init: 0x40000464 / UART: 0x40000464 / BL: 0x40002C64.
} tegra_bit_t210b01_t;
#endif

View File

@@ -110,7 +110,6 @@ typedef unsigned long uptr;
#define BOOT_CFG_FROM_LAUNCH BIT(1) #define BOOT_CFG_FROM_LAUNCH BIT(1)
#define BOOT_CFG_FROM_ID BIT(2) #define BOOT_CFG_FROM_ID BIT(2)
#define BOOT_CFG_TO_EMUMMC BIT(3) #define BOOT_CFG_TO_EMUMMC BIT(3)
#define BOOT_CFG_SEPT_RUN BIT(7)
#define EXTRA_CFG_KEYS BIT(0) #define EXTRA_CFG_KEYS BIT(0)
#define EXTRA_CFG_PAYLOAD BIT(1) #define EXTRA_CFG_PAYLOAD BIT(1)

View File

@@ -202,27 +202,6 @@ void reg_write_array(u32 *base, const reg_cfg_t *cfg, u32 num_cfg)
base[cfg[i].idx] = cfg[i].val; base[cfg[i].idx] = cfg[i].val;
} }
u16 crc16_calc(const u8 *buf, u32 len)
{
const u8 *p, *q;
u16 crc = 0x55aa;
static u16 table[16] = {
0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401,
0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400
};
q = buf + len;
for (p = buf; p < q; p++)
{
u8 oct = *p;
crc = (crc >> 4) ^ table[crc & 0xf] ^ table[(oct >> 0) & 0xf];
crc = (crc >> 4) ^ table[crc & 0xf] ^ table[(oct >> 4) & 0xf];
}
return crc;
}
u32 crc32_calc(u32 crc, const u8 *buf, u32 len) u32 crc32_calc(u32 crc, const u8 *buf, u32 len)
{ {
const u8 *p, *q; const u8 *p, *q;
@@ -308,7 +287,7 @@ void power_set_state(power_state_t state)
break; break;
case REBOOT_BYPASS_FUSES: case REBOOT_BYPASS_FUSES:
panic(0x21); // Bypass fuse programming in package1. panic(PMC_NX_PANIC_BYPASS_FUSES); // Bypass fuse programming in package1.
break; break;
case POWER_OFF: case POWER_OFF:

View File

@@ -51,12 +51,6 @@ typedef enum
ERR_EXCEPTION = BIT(31), ERR_EXCEPTION = BIT(31),
} hekate_errors_t; } hekate_errors_t;
typedef struct _cfg_op_t
{
u32 off;
u32 val;
} cfg_op_t;
typedef struct _reg_cfg_t typedef struct _reg_cfg_t
{ {
u32 idx; u32 idx;
@@ -93,8 +87,6 @@ long strtol(const char *nptr, char **endptr, register int base);
int atoi(const char *nptr); int atoi(const char *nptr);
void reg_write_array(u32 *base, const reg_cfg_t *cfg, u32 num_cfg); void reg_write_array(u32 *base, const reg_cfg_t *cfg, u32 num_cfg);
void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops);
u16 crc16_calc(const u8 *buf, u32 len);
u32 crc32_calc(u32 crc, const u8 *buf, u32 len); u32 crc32_calc(u32 crc, const u8 *buf, u32 len);
int qsort_compare_int(const void *a, const void *b); int qsort_compare_int(const void *a, const void *b);

View File

@@ -30,6 +30,8 @@
#include <utils/list.h> #include <utils/list.h>
#include <utils/util.h> #include <utils/util.h>
#define EMC_SEPT_RUN BIT(31)
extern hekate_config h_cfg; extern hekate_config h_cfg;
void set_default_configuration() void set_default_configuration()

View File

@@ -37,6 +37,8 @@
#include <gfx_utils.h> #include <gfx_utils.h>
#define BOOT_CFG_SEPT_RUN BIT(7)
#define PATCHED_RELOC_SZ 0x94 #define PATCHED_RELOC_SZ 0x94
#define WB_RST_ADDR 0x40010ED0 #define WB_RST_ADDR 0x40010ED0

View File

@@ -56,6 +56,8 @@
#include "fs/fstypes.h" #include "fs/fstypes.h"
#include "fs/menus/filemenu.h" #include "fs/menus/filemenu.h"
#define CBFS_DRAM_EN_ADDR 0x4003e000 // u32.
#define IPL_STACK_TOP 0x83100000
hekate_config h_cfg; hekate_config h_cfg;
boot_cfg_t __attribute__((section ("._boot_cfg"))) b_cfg; boot_cfg_t __attribute__((section ("._boot_cfg"))) b_cfg;

View File

@@ -121,6 +121,120 @@ void DumpSysFw(){
extern sdmmc_storage_t sd_storage; extern sdmmc_storage_t sd_storage;
#include <string.h>
#include <stdlib.h>
#include "../config.h"
#include <libs/fatfs/diskio.h>
#include <storage/emmc.h>
#include "../storage/emummc.h"
#include <storage/sd.h>
#include <storage/nx_emmc_bis.h>
#define MBR_Table 446 /* MBR: Offset of partition table in the MBR */
#define SZ_PTE 16 /* MBR: Size of a partition table entry */
#define LEAVE_MKFS(res) { if (!work) ff_memfree(buf); return res; }
/* Fill memory block */
static void mem_set (void* dst, int val, UINT cnt)
{
BYTE *d = (BYTE*)dst;
do {
*d++ = (BYTE)val;
} while (--cnt);
}
static void st_word (BYTE* ptr, WORD val) /* Store a 2-byte word in little-endian */
{
*ptr++ = (BYTE)val; val >>= 8;
*ptr++ = (BYTE)val;
}
static void st_dword (BYTE* ptr, DWORD val) /* Store a 4-byte word in little-endian */
{
*ptr++ = (BYTE)val; val >>= 8;
*ptr++ = (BYTE)val; val >>= 8;
*ptr++ = (BYTE)val; val >>= 8;
*ptr++ = (BYTE)val;
}
FRESULT f_fdisk_mod (
BYTE pdrv, /* Physical drive number */
const DWORD* szt, /* Pointer to the size table for each partitions */
void* work
)
{
UINT i, n, sz_cyl, tot_cyl, e_cyl;
BYTE s_hd, e_hd, *p, *buf = (BYTE*)work;
DSTATUS stat;
DWORD sz_disk, p_sect, b_cyl, b_sect;
FRESULT res;
stat = disk_initialize(pdrv);
if (stat & STA_NOINIT) return FR_NOT_READY;
if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
sz_disk = sd_storage.csd.capacity;
if (!buf) return FR_NOT_ENOUGH_CORE;
/* Determine the CHS without any consideration of the drive geometry */
for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ;
if (n == 256) n--;
e_hd = (BYTE)(n - 1);
sz_cyl = 63 * n;
tot_cyl = sz_disk / sz_cyl;
/* Create partition table */
mem_set(buf, 0, 0x10000);
p = buf + MBR_Table; b_cyl = 0, b_sect = 0;
for (i = 0; i < 4; i++, p += SZ_PTE) {
p_sect = szt[i]; /* Number of sectors */
if (p_sect == 0)
continue;
if (i == 0) { /* Exclude first 16MiB of sd */
s_hd = 1;
b_sect += 32768; p_sect -= 32768;
}
else
s_hd = 0;
b_cyl = b_sect / sz_cyl;
e_cyl = ((b_sect + p_sect) / sz_cyl) - 1; /* End cylinder */
if (e_cyl >= tot_cyl)
LEAVE_MKFS(FR_INVALID_PARAMETER);
/* Set partition table */
p[1] = s_hd; /* Start head */
p[2] = (BYTE)(((b_cyl >> 2) & 0xC0) | 1); /* Start sector */
p[3] = (BYTE)b_cyl; /* Start cylinder */
p[4] = 0x07; /* System type (temporary setting) */
p[5] = e_hd; /* End head */
p[6] = (BYTE)(((e_cyl >> 2) & 0xC0) | 63); /* End sector */
p[7] = (BYTE)e_cyl; /* End cylinder */
st_dword(p + 8, b_sect); /* Start sector in LBA */
st_dword(p + 12, p_sect); /* Number of sectors */
/* Next partition */
for (u32 cursect = 0; cursect < 512; cursect++){
disk_write(pdrv, buf + 0x4000, b_sect + (64 * cursect), 64);
}
b_sect += p_sect;
}
st_word(p, 0xAA55); /* MBR signature (always at offset 510) */
/* Write it to the MBR */
res = (disk_write(pdrv, buf, 0, 1) == RES_OK && disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR;
LEAVE_MKFS(res);
}
MenuEntry_t FatAndEmu[] = { MenuEntry_t FatAndEmu[] = {
{.optionUnion = COLORTORGB(COLOR_ORANGE), .name = "Back to main menu"}, {.optionUnion = COLORTORGB(COLOR_ORANGE), .name = "Back to main menu"},
{.optionUnion = COLORTORGB(COLOR_GREEN), .name = "Fat32 + EmuMMC"}, {.optionUnion = COLORTORGB(COLOR_GREEN), .name = "Fat32 + EmuMMC"},