Update to hekate bdk 5.5.6

This commit is contained in:
shchmue 2021-05-12 15:38:34 -06:00
parent 93909f149e
commit a7712b173c
95 changed files with 2720 additions and 1684 deletions

View File

@ -45,8 +45,11 @@ CUSTOMDEFINES += -DGFX_INC=$(GFX_INC) -DFFCFG_INC=$(FFCFG_INC)
#CUSTOMDEFINES += -DDEBUG #CUSTOMDEFINES += -DDEBUG
#TODO: Considering reinstating some of these when pointer warnings have been fixed.
WARNINGS := -Wall -Wno-array-bounds -Wno-stringop-overread -Wno-stringop-overflow
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork
CFLAGS = $(ARCH) -Os -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -std=gnu11 -Wall $(CUSTOMDEFINES) CFLAGS = $(ARCH) -Os -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -std=gnu11 $(WARNINGS) $(CUSTOMDEFINES)
LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defsym=IPL_LOAD_ADDR=$(IPL_LOAD_ADDR) LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defsym=IPL_LOAD_ADDR=$(IPL_LOAD_ADDR)
################################################################################ ################################################################################

View File

@ -20,6 +20,7 @@
#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/gpio.h> #include <soc/gpio.h>
#include <soc/hw_init.h> #include <soc/hw_init.h>
@ -170,9 +171,9 @@ int display_dsi_read(u8 cmd, u32 len, void *data, bool video_enabled)
void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled) void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled)
{ {
u8 *fifo8;
u32 *fifo32;
u32 host_control; u32 host_control;
u32 fifo32[DSI_STATUS_RX_FIFO_SIZE] = {0};
u8 *fifo8 = (u8 *)fifo32;
// Enable host cmd packets during video and save host control. // Enable host cmd packets during video and save host control.
if (video_enabled) if (video_enabled)
@ -193,6 +194,8 @@ void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled)
break; break;
default: default:
fifo32 = calloc(DSI_STATUS_RX_FIFO_SIZE * 8, 4);
fifo8 = (u8 *)fifo32;
fifo32[0] = (len << 8) | MIPI_DSI_DCS_LONG_WRITE; fifo32[0] = (len << 8) | MIPI_DSI_DCS_LONG_WRITE;
fifo8[4] = cmd; fifo8[4] = cmd;
memcpy(&fifo8[5], data, len); memcpy(&fifo8[5], data, len);
@ -200,6 +203,7 @@ void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled)
for (u32 i = 0; i < (ALIGN(len, 4) / 4); i++) for (u32 i = 0; i < (ALIGN(len, 4) / 4); i++)
DSI(_DSIREG(DSI_WR_DATA)) = fifo32[i]; DSI(_DSIREG(DSI_WR_DATA)) = fifo32[i];
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST; DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
free(fifo32);
break; break;
} }
@ -215,29 +219,30 @@ void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled)
void display_init() void display_init()
{ {
// Check if display is already initialized. // Check if display is already initialized.
if (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) & BIT(CLK_L_DISP1)) if (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & BIT(CLK_L_DISP1))
_display_panel_and_hw_end(true); _display_panel_and_hw_end(true);
// Get Chip ID. // Get Chip ID.
bool tegra_t210 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210; bool tegra_t210 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210;
// T210B01: Power on SD2 regulator for supplying LD0. // T210B01: Power on SD2 regulator for supplying LDO0.
if (!tegra_t210) if (!tegra_t210)
{ {
// Set SD2 regulator voltage. // Set SD2 regulator voltage.
max77620_regulator_set_voltage(REGULATOR_SD2, 1325000); max7762x_regulator_set_voltage(REGULATOR_SD2, 1325000);
// Set slew rate and enable SD2 regulator. // Set slew rate and enable SD2 regulator.
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD2_CFG, (1 << MAX77620_SD_SR_SHIFT) | MAX77620_SD_CFG1_FSRADE_SD_ENABLE); i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD2_CFG, (1 << MAX77620_SD_SR_SHIFT) | MAX77620_SD_CFG1_FSRADE_SD_ENABLE);
max77620_regulator_enable(REGULATOR_SD2, 1); max7762x_regulator_enable(REGULATOR_SD2, true);
} }
// Enable power to display panel controller. // Enable power to display panel controller.
max77620_regulator_set_volt_and_flags(REGULATOR_LDO0, 1200000, MAX77620_POWER_MODE_NORMAL); // Configure to 1.2V. max7762x_regulator_set_voltage(REGULATOR_LDO0, 1200000);
max7762x_regulator_enable(REGULATOR_LDO0, true);
if (tegra_t210) if (tegra_t210)
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO7, max77620_config_gpio(7, MAX77620_GPIO_OUTPUT_ENABLE); // T210: LD0 -> GPIO7 -> Display panel.
MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH | MAX77620_CNFG_GPIO_DRV_PUSHPULL); // T210: LD0 -> GPIO7 -> Display panel.
// Enable Display Interface specific clocks. // Enable Display Interface specific clocks.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_MIPI_CAL) | BIT(CLK_H_DSI); CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_MIPI_CAL) | BIT(CLK_H_DSI);
@ -293,7 +298,7 @@ void display_init()
// Set DISP1 clock source and parent clock. // Set DISP1 clock source and parent clock.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DISP1) = 0x40000000; // PLLD_OUT. CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DISP1) = 0x40000000; // PLLD_OUT.
u32 plld_div = (3 << 20) | (20 << 11) | 1; // DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 96 MHz. u32 plld_div = (3 << 20) | (20 << 11) | 1; // DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 97.5 MHz (offset).
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div; CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div;
if (tegra_t210) if (tegra_t210)
@ -335,9 +340,12 @@ void display_init()
#if 0 #if 0
// Get Display ID. // Get Display ID.
_display_id = 0xCCCCCC; _display_id = 0xCCCCCC; // Set initial value. 4th byte cleared.
display_dsi_read(MIPI_DCS_GET_DISPLAY_ID, 3, &_display_id, DSI_VIDEO_DISABLED); display_dsi_read(MIPI_DCS_GET_DISPLAY_ID, 3, &_display_id, DSI_VIDEO_DISABLED);
#else #else
// Drain RX FIFO.
_display_dsi_read_rx_fifo(NULL);
// Set reply size. // Set reply size.
_display_dsi_send_cmd(MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, 3, 0); _display_dsi_send_cmd(MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, 3, 0);
_display_dsi_wait(250000, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO); _display_dsi_wait(250000, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO);
@ -407,11 +415,11 @@ void display_init()
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_SET_DISPLAY_ON, 20000); _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_SET_DISPLAY_ON, 20000);
// Configure PLLD for DISP1. // Configure PLLD for DISP1.
plld_div = (1 << 20) | (24 << 11) | 1; // DIVM: 1, DIVN: 24, DIVP: 1. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 230.4 MHz. plld_div = (1 << 20) | (24 << 11) | 1; // DIVM: 1, DIVN: 24, DIVP: 1. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 234 MHz (offset).
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div; CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div;
if (tegra_t210) if (tegra_t210)
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0x20; // PLLD_SETUP CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0x20; // PLLD_SETUP.
else else
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0; CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0;
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC) = 0x2DFC00; // Use new PLLD_SDM_DIN. CLOCK(CLK_RST_CONTROLLER_PLLD_MISC) = 0x2DFC00; // Use new PLLD_SDM_DIN.
@ -420,7 +428,7 @@ void display_init()
DSI(_DSIREG(DSI_PAD_CONTROL_1)) = 0; DSI(_DSIREG(DSI_PAD_CONTROL_1)) = 0;
DSI(_DSIREG(DSI_PHY_TIMING_0)) = tegra_t210 ? 0x6070601 : 0x6070603; DSI(_DSIREG(DSI_PHY_TIMING_0)) = tegra_t210 ? 0x6070601 : 0x6070603;
exec_cfg((u32 *)DSI_BASE, _display_dsi_packet_config, 19); exec_cfg((u32 *)DSI_BASE, _display_dsi_packet_config, 19);
// Set pixel clock dividers: 230.4 / 3 / 1 = 76.8 MHz. 60 Hz. // Set pixel clock dividers: 234 / 3 / 1 = 78 MHz (offset) for 60 Hz.
DISPLAY_A(_DIREG(DC_DISP_DISP_CLOCK_CONTROL)) = PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(4); // 4: div3. DISPLAY_A(_DIREG(DC_DISP_DISP_CLOCK_CONTROL)) = PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(4); // 4: div3.
exec_cfg((u32 *)DSI_BASE, _display_dsi_mode_config, 10); exec_cfg((u32 *)DSI_BASE, _display_dsi_mode_config, 10);
usleep(10000); usleep(10000);
@ -499,6 +507,11 @@ void display_backlight_brightness(u32 brightness, u32 step_delay)
PWM(PWM_CONTROLLER_PWM_CSR_0) = 0; PWM(PWM_CONTROLLER_PWM_CSR_0) = 0;
} }
u32 display_get_backlight_brightness()
{
return ((PWM(PWM_CONTROLLER_PWM_CSR_0) >> 16) & 0xFF);
}
static void _display_panel_and_hw_end(bool no_panel_deinit) static void _display_panel_and_hw_end(bool no_panel_deinit)
{ {
if (no_panel_deinit) if (no_panel_deinit)
@ -600,11 +613,20 @@ skip_panel_deinit:
void display_end() { _display_panel_and_hw_end(false); }; void display_end() { _display_panel_and_hw_end(false); };
u16 display_get_decoded_lcd_id() u16 display_get_decoded_panel_id()
{ {
return _display_id; return _display_id;
} }
void display_set_decoded_panel_id(u32 id)
{
// Decode Display ID.
_display_id = ((id >> 8) & 0xFF00) | (id & 0xFF);
if ((_display_id & 0xFF) == PANEL_JDI_XXX062M)
_display_id = PANEL_JDI_XXX062M;
}
void display_color_screen(u32 color) void display_color_screen(u32 color)
{ {
exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_one_color, 8); exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_one_color, 8);

View File

@ -650,7 +650,9 @@
* [10] 81 [26]: JDI LPM062M326A * [10] 81 [26]: JDI LPM062M326A
* [10] 96 [09]: JDI LAM062M109A * [10] 96 [09]: JDI LAM062M109A
* [20] 93 [0F]: InnoLux P062CCA-AZ1 (Rev A1) * [20] 93 [0F]: InnoLux P062CCA-AZ1 (Rev A1)
* [20] 95 [0F]: InnoLux P062CCA-AZ2 * [20] 95 [0F]: InnoLux P062CCA-AZ2 (Rev B1)
* [20] 96 [0F]: InnoLux P062CCA-AZ3 [UNCONFIRMED MODEL REV]
* [20] 98 [0F]: InnoLux P062CCA-??? [UNCONFIRMED MODEL REV]
* [30] 94 [0F]: AUO A062TAN01 (59.06A33.001) * [30] 94 [0F]: AUO A062TAN01 (59.06A33.001)
* [30] 95 [0F]: AUO A062TAN02 (59.06A33.002) * [30] 95 [0F]: AUO A062TAN02 (59.06A33.002)
* *
@ -671,10 +673,12 @@
* 20h: InnoLux Corporation * 20h: InnoLux Corporation
* 30h: AU Optronics * 30h: AU Optronics
* 40h: Unknown1 * 40h: Unknown1
* 50h: Unknown2 (OLED? Samsung? LG?)
* *
* Boards, Panel Size: * Boards, Panel Size:
* 0Fh: Icosa/Iowa, 6.2" * 0Fh: Icosa/Iowa, 6.2"
* 10h: Hoag, 5.5" * 10h: Hoag, 5.5"
* 20h: Unknown, x.x"
*/ */
enum enum
@ -693,8 +697,9 @@ void display_init();
void display_backlight_pwm_init(); void display_backlight_pwm_init();
void display_end(); void display_end();
/*! Get Display panel ID. */ /*! Get/Set Display panel ID. */
u16 display_get_decoded_lcd_id(); u16 display_get_decoded_panel_id();
void display_set_decoded_panel_id(u32 id);
/*! Show one single color on the display. */ /*! Show one single color on the display. */
void display_color_screen(u32 color); void display_color_screen(u32 color);
@ -702,6 +707,7 @@ void display_color_screen(u32 color);
/*! Switches screen backlight ON/OFF. */ /*! Switches screen backlight ON/OFF. */
void display_backlight(bool enable); void display_backlight(bool enable);
void display_backlight_brightness(u32 brightness, u32 step_delay); void display_backlight_brightness(u32 brightness, u32 step_delay);
u32 display_get_backlight_brightness();
/*! Init display in full 1280x720 resolution (B8G8R8A8, line stride 768, framebuffer size = 1280*768*4 bytes). */ /*! Init display in full 1280x720 resolution (B8G8R8A8, line stride 768, framebuffer size = 1280*768*4 bytes). */
u32 *display_init_framebuffer_pitch(); u32 *display_init_framebuffer_pitch();

View File

@ -21,6 +21,7 @@
#include "elfload/elfload.h" #include "elfload/elfload.h"
#include <module.h> #include <module.h>
#include <mem/heap.h> #include <mem/heap.h>
#include <power/max7762x.h>
#include <storage/nx_sd.h> #include <storage/nx_sd.h>
#include <utils/types.h> #include <utils/types.h>
@ -43,6 +44,10 @@ static void _ianos_call_ep(moduleEntrypoint_t entrypoint, void *moduleConfig)
bdkParameters->memset = (memset_t)&memset; bdkParameters->memset = (memset_t)&memset;
bdkParameters->sharedHeap = &_heap; bdkParameters->sharedHeap = &_heap;
// Extra functions.
bdkParameters->extension_magic = IANOS_EXT0;
bdkParameters->reg_voltage_set = (reg_voltage_set_t)&max7762x_regulator_set_voltage;
entrypoint(moduleConfig, bdkParameters); entrypoint(moduleConfig, bdkParameters);
} }

View File

@ -17,7 +17,6 @@
*/ */
#include "als.h" #include "als.h"
#include <power/max77620.h>
#include <power/max7762x.h> #include <power/max7762x.h>
#include <soc/clock.h> #include <soc/clock.h>
#include <soc/i2c.h> #include <soc/i2c.h>
@ -98,14 +97,16 @@ void get_als_lux(als_table_t *als_val)
u8 als_init(als_table_t *als_val) u8 als_init(als_table_t *als_val)
{ {
// Enable power to ALS IC.
max7762x_regulator_set_voltage(REGULATOR_LDO6, 2900000);
max7762x_regulator_enable(REGULATOR_LDO6, true);
// Init I2C2.
pinmux_config_i2c(I2C_2); pinmux_config_i2c(I2C_2);
clock_enable_i2c(I2C_2); clock_enable_i2c(I2C_2);
i2c_init(I2C_2); i2c_init(I2C_2);
max77620_regulator_set_volt_and_flags(REGULATOR_LDO6, 2900000, MAX77620_POWER_MODE_NORMAL); // Initialize ALS.
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_LDO6_CFG2,
(MAX77620_POWER_MODE_NORMAL << MAX77620_LDO_POWER_MODE_SHIFT | (3 << 3) | MAX77620_LDO_CFG2_ADE_ENABLE));
u8 id = i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(0x12)); u8 id = i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(0x12));
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_SPEC(BH1730_SPECCMD_RESET), 0); i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_SPEC(BH1730_SPECCMD_RESET), 0);
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_GAIN_REG), HOS_GAIN); i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_GAIN_REG), HOS_GAIN);

View File

@ -1,7 +1,7 @@
/* /*
* Joy-Con UART driver for Nintendo Switch * Joy-Con UART driver for Nintendo Switch
* *
* Copyright (c) 2019 CTCaer * Copyright (c) 2019-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -39,6 +39,9 @@
#define JC_WIRED_INIT_REPLY 0x94 #define JC_WIRED_INIT_REPLY 0x94
#define JC_INIT_HANDSHAKE 0xA5 #define JC_INIT_HANDSHAKE 0xA5
#define JC_HORI_INPUT_RPT_CMD 0x9A
#define JC_HORI_INPUT_RPT 0x00
#define JC_WIRED_CMD_MAC 0x01 #define JC_WIRED_CMD_MAC 0x01
#define JC_WIRED_CMD_10 0x10 #define JC_WIRED_CMD_10 0x10
@ -61,8 +64,12 @@
#define JC_BTN_MASK_L 0xFF2900 // 0xFFE900: with charge status. #define JC_BTN_MASK_L 0xFF2900 // 0xFFE900: with charge status.
#define JC_BTN_MASK_R 0x0056FF #define JC_BTN_MASK_R 0x0056FF
#define JC_ID_L 1 #define JC_ID_L 0x01
#define JC_ID_R 2 #define JC_ID_R 0x02
#define JC_ID_HORI 0x20
#define JC_CRC8_INIT 0x00
#define JC_CRC8_POLY 0x8D
enum enum
{ {
@ -80,25 +87,31 @@ static const u8 init_jc[] = {
static const u8 init_handshake[] = { static const u8 init_handshake[] = {
0x19, 0x01, 0x03, 0x07, 0x00, // Uart header. 0x19, 0x01, 0x03, 0x07, 0x00, // Uart header.
JC_INIT_HANDSHAKE, 0x02, // Wired cmd and wired subcmd. JC_INIT_HANDSHAKE, 0x02, // Wired cmd and wired subcmd.
0x01, 0x7E, 0x00, 0x00, 0x00 // Wired subcmd data. 0x01, 0x7E, 0x00, 0x00, 0x00 // Wired subcmd data and crc.
}; };
static const u8 init_get_info[] = { static const u8 init_get_info[] = {
0x19, 0x01, 0x03, 0x07, 0x00, // Uart header. 0x19, 0x01, 0x03, 0x07, 0x00, // Uart header.
JC_WIRED_CMD, JC_WIRED_CMD_MAC, // Wired cmd and subcmd. JC_WIRED_CMD, JC_WIRED_CMD_MAC, // Wired cmd and subcmd.
0x00, 0x00, 0x00, 0x00, 0x24 // Wired subcmd data. 0x00, 0x00, 0x00, 0x00, 0x24 // Wired subcmd data and crc.
}; };
static const u8 init_finilize[] = { static const u8 init_finalize[] = {
0x19, 0x01, 0x03, 0x07, 0x00, // Uart header. 0x19, 0x01, 0x03, 0x07, 0x00, // Uart header.
JC_WIRED_CMD, JC_WIRED_CMD_10, // Wired cmd and subcmd. JC_WIRED_CMD, JC_WIRED_CMD_10, // Wired cmd and subcmd.
0x00, 0x00, 0x00, 0x00, 0x3D // Wired subcmd data. 0x00, 0x00, 0x00, 0x00, 0x3D // Wired subcmd data and crc.
}; };
static const u8 nx_pad_status[] = { static const u8 nx_pad_status[] = {
0x19, 0x01, 0x03, 0x08, 0x00, // Uart header. 0x19, 0x01, 0x03, 0x08, 0x00, // Uart header.
JC_WIRED_HID, 0x00, // Wired cmd and hid cmd. JC_WIRED_HID, 0x00, // Wired cmd and hid cmd.
0x01, 0x00, 0x00, 0x69, 0x2D, 0x1F // hid data. 0x01, 0x00, 0x00, 0x69, 0x2D, 0x1F // hid data and crc.
};
static const u8 hori_pad_status[] = {
0x19, 0x01, 0x03, 0x07, 0x00, // Uart header.
JC_HORI_INPUT_RPT_CMD, 0x01, // Hori cmd and hori subcmd.
0x00, 0x00, 0x00, 0x00, 0x48 // Hori cmd data and crc.
}; };
typedef struct _jc_uart_hdr_t typedef struct _jc_uart_hdr_t
@ -185,8 +198,8 @@ typedef struct _joycon_ctxt_t
u8 connected; u8 connected;
} joycon_ctxt_t; } joycon_ctxt_t;
static joycon_ctxt_t jc_l; static joycon_ctxt_t jc_l = {0};
static joycon_ctxt_t jc_r; static joycon_ctxt_t jc_r = {0};
static bool jc_init_done = false; static bool jc_init_done = false;
static u32 hid_pkt_inc = 0; static u32 hid_pkt_inc = 0;
@ -195,13 +208,29 @@ static jc_gamepad_rpt_t jc_gamepad;
void jc_power_supply(u8 uart, bool enable); void jc_power_supply(u8 uart, bool enable);
static u8 jc_crc(u8 *data, u16 len)
{
u8 crc = JC_CRC8_INIT;
u16 i, j;
for (i = 0; i < len; i++) {
crc ^= data[i];
for (j = 0; j < 8; j++) {
if ((crc & 0x80) != 0)
crc = (u8)((crc << 1) ^ JC_CRC8_POLY);
else
crc <<= 1;
}
}
return crc;
}
void joycon_send_raw(u8 uart_port, const u8 *buf, u16 size) void joycon_send_raw(u8 uart_port, const u8 *buf, u16 size)
{ {
uart_send(uart_port, buf, size); uart_send(uart_port, buf, size);
uart_wait_idle(uart_port, UART_TX_IDLE); uart_wait_idle(uart_port, UART_TX_IDLE);
} }
static u16 jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, u8 *data, u16 size) static u16 jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, u8 *data, u16 size, bool crc)
{ {
out->uart_hdr.magic[0] = 0x19; out->uart_hdr.magic[0] = 0x19;
out->uart_hdr.magic[1] = 0x01; out->uart_hdr.magic[1] = 0x01;
@ -214,14 +243,14 @@ static u16 jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, u8 *data, u
if (data) if (data)
memcpy(out->data, data, size); memcpy(out->data, data, size);
out->crc = 0; // wired crc8ccit can be skipped. out->crc = crc ? jc_crc(&out->uart_hdr.total_size_msb, sizeof(out->uart_hdr.total_size_msb) + sizeof(out->cmd) + sizeof(out->data)) : 0;
return sizeof(jc_wired_hdr_t); return sizeof(jc_wired_hdr_t);
} }
static u16 jc_hid_output_rpt_craft(jc_wired_hdr_t *rpt, u8 *payload, u16 size) static u16 jc_hid_output_rpt_craft(jc_wired_hdr_t *rpt, u8 *payload, u16 size, bool crc)
{ {
u16 pkt_size = jc_packet_add_uart_hdr(rpt, JC_WIRED_HID, NULL, 0); u16 pkt_size = jc_packet_add_uart_hdr(rpt, JC_WIRED_HID, NULL, 0, crc);
pkt_size += size; pkt_size += size;
rpt->uart_hdr.total_size_lsb += size; rpt->uart_hdr.total_size_lsb += size;
@ -234,12 +263,12 @@ static u16 jc_hid_output_rpt_craft(jc_wired_hdr_t *rpt, u8 *payload, u16 size)
return pkt_size; return pkt_size;
} }
void jc_send_hid_output_rpt(u8 uart, u8 *payload, u16 size) void jc_send_hid_output_rpt(u8 uart, u8 *payload, u16 size, bool crc)
{ {
u8 rpt[0x50]; u8 rpt[0x50];
memset(rpt, 0, sizeof(rpt)); memset(rpt, 0, sizeof(rpt));
u32 rpt_size = jc_hid_output_rpt_craft((jc_wired_hdr_t *)rpt, payload, size); u32 rpt_size = jc_hid_output_rpt_craft((jc_wired_hdr_t *)rpt, payload, size, crc);
joycon_send_raw(uart, rpt, rpt_size); joycon_send_raw(uart, rpt, rpt_size);
} }
@ -275,18 +304,18 @@ void jc_send_hid_cmd(u8 uart, u8 subcmd, u8 *data, u16 size)
hid_pkt->subcmd = JC_HID_SUBCMD_RUMBLE_CTL; hid_pkt->subcmd = JC_HID_SUBCMD_RUMBLE_CTL;
hid_pkt->subcmd_data[0] = 1; hid_pkt->subcmd_data[0] = 1;
if (send_r_rumble) if (send_r_rumble)
jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 0x10); jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 0x10, false);
if (send_l_rumble) if (send_l_rumble)
jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 0x10); jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 0x10, false);
// Send rumble. // Send rumble.
hid_pkt->cmd = JC_HID_RUMBLE_RPT; hid_pkt->cmd = JC_HID_RUMBLE_RPT;
hid_pkt->pkt_id = jc_hid_pkt_id_incr(); hid_pkt->pkt_id = jc_hid_pkt_id_incr();
memcpy(hid_pkt->rumble, rumble_init, sizeof(rumble_init)); memcpy(hid_pkt->rumble, rumble_init, sizeof(rumble_init));
if (send_r_rumble) if (send_r_rumble)
jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 10); jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 10, false);
if (send_l_rumble) if (send_l_rumble)
jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 10); jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 10, false);
msleep(15); msleep(15);
@ -297,21 +326,21 @@ void jc_send_hid_cmd(u8 uart, u8 subcmd, u8 *data, u16 size)
hid_pkt->subcmd_data[0] = 0; hid_pkt->subcmd_data[0] = 0;
memcpy(hid_pkt->rumble, rumble_neutral, sizeof(rumble_neutral)); memcpy(hid_pkt->rumble, rumble_neutral, sizeof(rumble_neutral));
if (send_r_rumble) if (send_r_rumble)
jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 0x10); jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 0x10, false);
if (send_l_rumble) if (send_l_rumble)
jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 0x10); jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 0x10, false);
} }
else else
{ {
bool crc_needed = (jc_l.uart == uart) ? (jc_l.type & JC_ID_HORI) : (jc_r.type & JC_ID_HORI);
hid_pkt->cmd = JC_HID_OUTPUT_RPT; hid_pkt->cmd = JC_HID_OUTPUT_RPT;
hid_pkt->pkt_id = jc_hid_pkt_id_incr(); hid_pkt->pkt_id = jc_hid_pkt_id_incr();
hid_pkt->subcmd = subcmd; hid_pkt->subcmd = subcmd;
if (data) if (data)
memcpy(hid_pkt->subcmd_data, data, size); memcpy(hid_pkt->subcmd_data, data, size);
u8 pkt_size = sizeof(jc_hid_out_rpt_t) + size; jc_send_hid_output_rpt(uart, (u8 *)hid_pkt, sizeof(jc_hid_out_rpt_t) + size, crc_needed);
jc_send_hid_output_rpt(uart, (u8 *)hid_pkt, pkt_size);
} }
} }
@ -333,6 +362,7 @@ static void jc_parse_wired_hid(joycon_ctxt_t *jc, const u8* packet, u32 size)
switch (hid_pkt->cmd) switch (hid_pkt->cmd)
{ {
case JC_HORI_INPUT_RPT:
case JC_HID_INPUT_RPT: case JC_HID_INPUT_RPT:
btn_tmp = hid_pkt->btn_right | hid_pkt->btn_shared << 8 | hid_pkt->btn_left << 16; btn_tmp = hid_pkt->btn_right | hid_pkt->btn_shared << 8 | hid_pkt->btn_left << 16;
@ -412,6 +442,7 @@ static void jc_uart_pkt_parse(joycon_ctxt_t *jc, const u8* packet, size_t size)
jc_wired_hdr_t *pkt = (jc_wired_hdr_t *)packet; jc_wired_hdr_t *pkt = (jc_wired_hdr_t *)packet;
switch (pkt->cmd) switch (pkt->cmd)
{ {
case JC_HORI_INPUT_RPT_CMD:
case JC_WIRED_HID: case JC_WIRED_HID:
jc_parse_wired_hid(jc, pkt->payload, (pkt->data[0] << 8) | pkt->data[1]); jc_parse_wired_hid(jc, pkt->payload, (pkt->data[0] << 8) | pkt->data[1]);
break; break;
@ -432,7 +463,7 @@ static void jc_rcv_pkt(joycon_ctxt_t *jc)
// Check if device stopped sending data. // Check if device stopped sending data.
u32 uart_irq = uart_get_IIR(jc->uart); u32 uart_irq = uart_get_IIR(jc->uart);
if ((uart_irq & 0x8) != 0x8) if (uart_irq != UART_IIR_REDI)
return; return;
u32 len = uart_recv(jc->uart, (u8 *)jc->buf, 0x100); u32 len = uart_recv(jc->uart, (u8 *)jc->buf, 0x100);
@ -474,10 +505,15 @@ static bool jc_send_init_rumble(joycon_ctxt_t *jc)
static void jc_req_nx_pad_status(joycon_ctxt_t *jc) static void jc_req_nx_pad_status(joycon_ctxt_t *jc)
{ {
bool sent_rumble = jc_send_init_rumble(jc); bool is_nxpad = !(jc->type & JC_ID_HORI);
if (sent_rumble) if (is_nxpad)
return; {
bool sent_rumble = jc_send_init_rumble(jc);
if (sent_rumble)
return;
}
if (jc->last_status_req_time > get_tmr_ms() || !jc->connected) if (jc->last_status_req_time > get_tmr_ms() || !jc->connected)
return; return;
@ -488,7 +524,10 @@ static void jc_req_nx_pad_status(joycon_ctxt_t *jc)
else else
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO); gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO);
joycon_send_raw(jc->uart, nx_pad_status, sizeof(nx_pad_status)); if (is_nxpad)
joycon_send_raw(jc->uart, nx_pad_status, sizeof(nx_pad_status));
else
joycon_send_raw(jc->uart, hori_pad_status, sizeof(hori_pad_status));
// Turn Joy-Con detect on. // Turn Joy-Con detect on.
if (jc->uart == UART_B) if (jc->uart == UART_B)
@ -655,24 +694,31 @@ retry:
void jc_deinit() void jc_deinit()
{ {
// Disable power.
jc_power_supply(UART_B, false);
jc_power_supply(UART_C, false);
// Turn off Joy-Con detect.
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO); gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO);
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO); gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO);
// Send sleep command.
u8 data = HCI_STATE_SLEEP; u8 data = HCI_STATE_SLEEP;
if (jc_r.connected) if (jc_r.connected && !(jc_r.type & JC_ID_HORI))
{ {
jc_send_hid_cmd(UART_B, JC_HID_SUBCMD_HCI_STATE, &data, 1); jc_send_hid_cmd(UART_B, JC_HID_SUBCMD_HCI_STATE, &data, 1);
jc_rcv_pkt(&jc_r); jc_rcv_pkt(&jc_r);
} }
if (jc_l.connected) if (jc_l.connected && !(jc_l.type & JC_ID_HORI))
{ {
jc_send_hid_cmd(UART_C, JC_HID_SUBCMD_HCI_STATE, &data, 1); jc_send_hid_cmd(UART_C, JC_HID_SUBCMD_HCI_STATE, &data, 1);
jc_rcv_pkt(&jc_l); jc_rcv_pkt(&jc_l);
} }
jc_power_supply(UART_B, false); // Disable UART B and C clocks.
jc_power_supply(UART_C, false); clock_disable_uart(UART_B);
clock_disable_uart(UART_C);
} }
static void jc_init_conn(joycon_ctxt_t *jc) static void jc_init_conn(joycon_ctxt_t *jc)
@ -709,9 +755,12 @@ static void jc_init_conn(joycon_ctxt_t *jc)
msleep(5); msleep(5);
jc_rcv_pkt(jc); jc_rcv_pkt(jc);
joycon_send_raw(jc->uart, init_finilize, sizeof(init_finilize)); if (!(jc->type & JC_ID_HORI))
msleep(5); {
jc_rcv_pkt(jc); joycon_send_raw(jc->uart, init_finalize, sizeof(init_finalize));
msleep(5);
jc_rcv_pkt(jc);
}
// Turn Joy-Con detect on. // Turn Joy-Con detect on.
if (jc->uart == UART_B) if (jc->uart == UART_B)
@ -766,10 +815,10 @@ void jc_power_supply(u8 uart, bool enable)
{ {
if (enable) if (enable)
{ {
if (regulator_get_5v_dev_enabled(1 << uart)) if (regulator_5v_get_dev_enabled(1 << uart))
return; return;
regulator_enable_5v(1 << uart); regulator_5v_enable(1 << uart);
if (jc_init_done) if (jc_init_done)
{ {
@ -799,10 +848,10 @@ void jc_power_supply(u8 uart, bool enable)
} }
else else
{ {
if (!regulator_get_5v_dev_enabled(1 << uart)) if (!regulator_5v_get_dev_enabled(1 << uart))
return; return;
regulator_disable_5v(1 << uart); regulator_5v_disable(1 << uart);
if (uart == UART_C) if (uart == UART_C)
gpio_write(GPIO_PORT_CC, GPIO_PIN_3, GPIO_LOW); gpio_write(GPIO_PORT_CC, GPIO_PIN_3, GPIO_LOW);
@ -816,10 +865,10 @@ void jc_init_hw()
jc_l.uart = UART_C; jc_l.uart = UART_C;
jc_r.uart = UART_B; jc_r.uart = UART_B;
#if !defined(DEBUG_UART_PORT) || !(DEBUG_UART_PORT)
if (fuse_read_hw_type() == FUSE_NX_HW_TYPE_HOAG) if (fuse_read_hw_type() == FUSE_NX_HW_TYPE_HOAG)
return; return;
#ifndef DEBUG_UART_PORT
jc_power_supply(UART_C, true); jc_power_supply(UART_C, true);
jc_power_supply(UART_B, true); jc_power_supply(UART_B, true);
@ -836,14 +885,14 @@ void jc_init_hw()
pinmux_config_uart(UART_C); pinmux_config_uart(UART_C);
// Ease the stress to APB. // Ease the stress to APB.
bpmp_clk_rate_set(BPMP_CLK_NORMAL); bpmp_freq_t prev_fid = bpmp_clk_rate_set(BPMP_CLK_NORMAL);
// Enable UART B and C clocks. // Enable UART B and C clocks.
clock_enable_uart(UART_B); clock_enable_uart(UART_B);
clock_enable_uart(UART_C); clock_enable_uart(UART_C);
// Restore OC. // Restore OC.
bpmp_clk_rate_set(BPMP_CLK_DEFAULT_BOOST); bpmp_clk_rate_set(prev_fid);
// Turn Joy-Con detect on. // Turn Joy-Con detect on.
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_GPIO); gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_GPIO);

View File

@ -23,7 +23,6 @@
#include <soc/i2c.h> #include <soc/i2c.h>
#include <soc/pinmux.h> #include <soc/pinmux.h>
#include <power/max7762x.h> #include <power/max7762x.h>
#include <power/max77620.h>
#include <soc/gpio.h> #include <soc/gpio.h>
#include <soc/t210.h> #include <soc/t210.h>
#include <utils/btn.h> #include <utils/btn.h>
@ -34,6 +33,16 @@
#include <gfx_utils.h> #include <gfx_utils.h>
#define DPRINTF(...) gfx_printf(__VA_ARGS__) #define DPRINTF(...) gfx_printf(__VA_ARGS__)
static touch_panel_info_t _panels[] =
{
{ 0, 1, 1, 1, "NISSHA NFT-K12D" },
{ 1, 0, 1, 1, "GiS GGM6 B2X" },
{ 2, 0, 0, 0, "NISSHA NBF-K9A" },
{ 3, 1, 0, 0, "GiS 5.5\"" },
{ 4, 0, 0, 1, "Unknown" },
{ -1, 1, 0, 1, "GiS VA 6.2\"" }
};
static int touch_command(u8 cmd, u8 *buf, u8 size) static int touch_command(u8 cmd, u8 *buf, u8 size)
{ {
int res = i2c_send_buf_small(I2C_3, STMFTS_I2C_ADDR, cmd, buf, size); int res = i2c_send_buf_small(I2C_3, STMFTS_I2C_ADDR, cmd, buf, size);
@ -53,7 +62,7 @@ static int touch_read_reg(u8 *cmd, u32 csize, u8 *buf, u32 size)
return 0; return 0;
} }
static int touch_wait_event(u8 event, u8 status, u32 timeout) static int touch_wait_event(u8 event, u8 status, u32 timeout, u8 *buf)
{ {
u32 timer = get_tmr_ms() + timeout; u32 timer = get_tmr_ms() + timeout;
while (true) while (true)
@ -61,7 +70,11 @@ static int touch_wait_event(u8 event, u8 status, u32 timeout)
u8 tmp[8] = {0}; u8 tmp[8] = {0};
i2c_recv_buf_small(tmp, 8, I2C_3, STMFTS_I2C_ADDR, STMFTS_READ_ONE_EVENT); i2c_recv_buf_small(tmp, 8, I2C_3, STMFTS_I2C_ADDR, STMFTS_READ_ONE_EVENT);
if (tmp[1] == event && tmp[2] == status) if (tmp[1] == event && tmp[2] == status)
{
if (buf)
memcpy(buf, &tmp[3], 5);
return 0; return 0;
}
if (get_tmr_ms() > timer) if (get_tmr_ms() > timer)
return 1; return 1;
@ -147,10 +160,10 @@ static void _touch_parse_event(touch_event *event)
event->type = STMFTS_EV_MULTI_TOUCH_LEAVE; event->type = STMFTS_EV_MULTI_TOUCH_LEAVE;
} }
// gfx_con_setpos(&gfx_con, 0, 300); // gfx_con_setpos(0, 300);
// DPRINTF("x = %d \ny = %d \nz = %d \n", event->x, event->y, event->z); // DPRINTF("x = %d \ny = %d \nz = %d \n", event->x, event->y, event->z);
// DPRINTF("0 = %02X\n1 = %02x\n2 = %02x\n3 = %02x\n", event->raw[0], event->raw[1], event->raw[2], event->raw[3]); // DPRINTF("0 = %02X\n1 = %02X\n2 = %02X\n3 = %02X\n", event->raw[0], event->raw[1], event->raw[2], event->raw[3]);
// DPRINTF("4 = %02X\n5 = %02x\n6 = %02x\n7 = %02x\n", event->raw[4], event->raw[5], event->raw[6], event->raw[7]); // DPRINTF("4 = %02X\n5 = %02X\n6 = %02X\n7 = %02X\n", event->raw[4], event->raw[5], event->raw[6], event->raw[7]);
} }
void touch_poll(touch_event *event) void touch_poll(touch_event *event)
@ -183,16 +196,45 @@ touch_info touch_get_info()
info.config_id = buf[4]; info.config_id = buf[4];
info.config_ver = buf[5]; info.config_ver = buf[5];
//DPRINTF("ID: %04X, FW Ver: %d.%02d\nCfg ID: %02x, Cfg Ver: %d\n", //DPRINTF("ID: %04X, FW Ver: %d.%02d\nCfg ID: %02X, Cfg Ver: %d\n",
// info.chip_id, info.fw_ver >> 8, info.fw_ver & 0xFF, info.config_id, info.config_ver); // info.chip_id, info.fw_ver >> 8, info.fw_ver & 0xFF, info.config_id, info.config_ver);
return info; return info;
} }
touch_panel_info_t *touch_get_panel_vendor()
{
u8 buf[5] = {0};
u8 cmd = STMFTS_VENDOR_GPIO_STATE;
static touch_panel_info_t panel_info = { -2, 0, 0, 0, ""};
if (touch_command(STMFTS_VENDOR, &cmd, 1))
return NULL;
if (touch_wait_event(STMFTS_EV_VENDOR, STMFTS_VENDOR_GPIO_STATE, 2000, buf))
return NULL;
for (u32 i = 0; i < ARRAY_SIZE(_panels); i++)
{
touch_panel_info_t *panel = &_panels[i];
if (buf[0] == panel->gpio0 && buf[1] == panel->gpio1 && buf[2] == panel->gpio2)
return panel;
}
// Touch panel not found, return current gpios.
panel_info.gpio0 = buf[0];
panel_info.gpio1 = buf[1];
panel_info.gpio2 = buf[2];
return &panel_info;
}
int touch_get_fw_info(touch_fw_info_t *fw) int touch_get_fw_info(touch_fw_info_t *fw)
{ {
u8 buf[8] = {0}; u8 buf[8] = {0};
memset(fw, 0, sizeof(touch_fw_info_t));
// Get fw address info. // Get fw address info.
u8 cmd[3] = { STMFTS_RW_FRAMEBUFFER_REG, 0, 0x60 }; u8 cmd[3] = { STMFTS_RW_FRAMEBUFFER_REG, 0, 0x60 };
int res = touch_read_reg(cmd, 3, buf, 3); int res = touch_read_reg(cmd, 3, buf, 3);
@ -227,7 +269,7 @@ int touch_sys_reset()
continue; continue;
} }
msleep(10); msleep(10);
if (touch_wait_event(STMFTS_EV_CONTROLLER_READY, 0, 20)) if (touch_wait_event(STMFTS_EV_CONTROLLER_READY, 0, 20, NULL))
continue; continue;
else else
return 0; return 0;
@ -284,7 +326,7 @@ int touch_get_fb_info(u8 *buf)
int res = 0; int res = 0;
for (u32 i = 0; i < 0x10000; i+=4) for (u32 i = 0; i < 0x10000; i += 4)
{ {
if (!res) if (!res)
{ {
@ -301,9 +343,9 @@ int touch_get_fb_info(u8 *buf)
int touch_sense_enable() int touch_sense_enable()
{ {
// Enable auto tuning calibration and multi-touch sensing. // Switch sense mode and enable multi-touch sensing.
u8 cmd = 1; u8 cmd = STMFTS_FINGER_MODE;
if (touch_command(STMFTS_AUTO_CALIBRATION, &cmd, 1)) if (touch_command(STMFTS_SWITCH_SENSE_MODE, &cmd, 1))
return 0; return 0;
if (touch_command(STMFTS_MS_MT_SENSE_ON, NULL, 0)) if (touch_command(STMFTS_MS_MT_SENSE_ON, NULL, 0))
@ -329,19 +371,19 @@ int touch_execute_autotune()
// Apply Mutual Sense Compensation tuning. // Apply Mutual Sense Compensation tuning.
if (touch_command(STMFTS_MS_CX_TUNING, NULL, 0)) if (touch_command(STMFTS_MS_CX_TUNING, NULL, 0))
return 0; return 0;
if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_MS_CX_TUNING_DONE, 2000)) if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_MS_CX_TUNING_DONE, 2000, NULL))
return 0; return 0;
// Apply Self Sense Compensation tuning. // Apply Self Sense Compensation tuning.
if (touch_command(STMFTS_SS_CX_TUNING, NULL, 0)) if (touch_command(STMFTS_SS_CX_TUNING, NULL, 0))
return 0; return 0;
if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_SS_CX_TUNING_DONE, 2000)) if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_SS_CX_TUNING_DONE, 2000, NULL))
return 0; return 0;
// Save Compensation data to EEPROM. // Save Compensation data to EEPROM.
if (touch_command(STMFTS_SAVE_CX_TUNING, NULL, 0)) if (touch_command(STMFTS_SAVE_CX_TUNING, NULL, 0))
return 0; return 0;
if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_WRITE_CX_TUNE_DONE, 2000)) if (touch_wait_event(STMFTS_EV_STATUS, STMFTS_EV_STATUS_WRITE_CX_TUNE_DONE, 2000, NULL))
return 0; return 0;
return touch_sense_enable(); return touch_sense_enable();
@ -358,12 +400,11 @@ static int touch_init()
int touch_power_on() int touch_power_on()
{ {
// Enables LDO6 for touchscreen VDD/AVDD supply // Enable LDO6 for touchscreen AVDD supply.
max77620_regulator_set_volt_and_flags(REGULATOR_LDO6, 2900000, MAX77620_POWER_MODE_NORMAL); max7762x_regulator_set_voltage(REGULATOR_LDO6, 2900000);
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_LDO6_CFG2, max7762x_regulator_enable(REGULATOR_LDO6, true);
(MAX77620_POWER_MODE_NORMAL << MAX77620_LDO_POWER_MODE_SHIFT | (3 << 3) | MAX77620_LDO_CFG2_ADE_ENABLE));
// Configure touchscreen GPIO. // Configure touchscreen VDD GPIO.
PINMUX_AUX(PINMUX_AUX_DAP4_SCLK) = PINMUX_PULL_DOWN | 1; PINMUX_AUX(PINMUX_AUX_DAP4_SCLK) = PINMUX_PULL_DOWN | 1;
gpio_config(GPIO_PORT_J, GPIO_PIN_7, GPIO_MODE_GPIO); gpio_config(GPIO_PORT_J, GPIO_PIN_7, GPIO_MODE_GPIO);
gpio_output_enable(GPIO_PORT_J, GPIO_PIN_7, GPIO_OUTPUT_ENABLE); gpio_output_enable(GPIO_PORT_J, GPIO_PIN_7, GPIO_OUTPUT_ENABLE);
@ -377,7 +418,7 @@ int touch_power_on()
// Configure Touscreen and GCAsic shared GPIO. // Configure Touscreen and GCAsic shared GPIO.
PINMUX_AUX(PINMUX_AUX_CAM_I2C_SDA) = PINMUX_LPDR | PINMUX_INPUT_ENABLE | PINMUX_TRISTATE | PINMUX_PULL_UP | 2; PINMUX_AUX(PINMUX_AUX_CAM_I2C_SDA) = PINMUX_LPDR | PINMUX_INPUT_ENABLE | PINMUX_TRISTATE | PINMUX_PULL_UP | 2;
PINMUX_AUX(PINMUX_AUX_CAM_I2C_SCL) = PINMUX_IO_HV | PINMUX_LPDR | PINMUX_TRISTATE | PINMUX_PULL_DOWN | 2; PINMUX_AUX(PINMUX_AUX_CAM_I2C_SCL) = PINMUX_IO_HV | PINMUX_LPDR | PINMUX_TRISTATE | PINMUX_PULL_DOWN | 2;
gpio_config(GPIO_PORT_S, GPIO_PIN_3, GPIO_MODE_GPIO); gpio_config(GPIO_PORT_S, GPIO_PIN_3, GPIO_MODE_GPIO); // GC detect.
// Initialize I2C3. // Initialize I2C3.
pinmux_config_i2c(I2C_3); pinmux_config_i2c(I2C_3);
@ -385,7 +426,7 @@ int touch_power_on()
i2c_init(I2C_3); i2c_init(I2C_3);
// Wait for the touchscreen module to get ready. // Wait for the touchscreen module to get ready.
touch_wait_event(STMFTS_EV_CONTROLLER_READY, 0, 20); touch_wait_event(STMFTS_EV_CONTROLLER_READY, 0, 20, NULL);
// Check for forced boot time calibration. // Check for forced boot time calibration.
if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN)) if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
@ -414,9 +455,7 @@ void touch_power_off()
gpio_write(GPIO_PORT_J, GPIO_PIN_7, GPIO_LOW); gpio_write(GPIO_PORT_J, GPIO_PIN_7, GPIO_LOW);
// Disables LDO6 for touchscreen VDD, AVDD supply // Disables LDO6 for touchscreen VDD, AVDD supply
max77620_regulator_enable(REGULATOR_LDO6, 0); max7762x_regulator_enable(REGULATOR_LDO6, false);
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_LDO6_CFG2,
MAX77620_LDO_CFG2_ADE_ENABLE | (2 << 3) | (MAX77620_POWER_MODE_NORMAL << MAX77620_LDO_POWER_MODE_SHIFT));
clock_disable_i2c(I2C_3); clock_disable_i2c(I2C_3);
} }

View File

@ -47,19 +47,26 @@
#define STMFTS_ITO_CHECK 0xA7 #define STMFTS_ITO_CHECK 0xA7
#define STMFTS_RELEASEINFO 0xAA #define STMFTS_RELEASEINFO 0xAA
#define STMFTS_WRITE_REG 0xB6 #define STMFTS_WRITE_REG 0xB6
#define STMFTS_AUTO_CALIBRATION 0xC3 #define STMFTS_SWITCH_SENSE_MODE 0xC3
#define STMFTS_NOISE_WRITE 0xC7 #define STMFTS_NOISE_WRITE 0xC7
#define STMFTS_NOISE_READ 0xC8 #define STMFTS_NOISE_READ 0xC8
#define STMFTS_RW_FRAMEBUFFER_REG 0xD0 #define STMFTS_RW_FRAMEBUFFER_REG 0xD0
#define STMFTS_SAVE_CX_TUNING 0xFC #define STMFTS_SAVE_CX_TUNING 0xFC
#define STMFTS_UNK0 0xB8 //Request compensation #define STMFTS_REQU_COMP_DATA 0xB8
#define STMFTS_UNK1 0xCF #define STMFTS_VENDOR 0xCF
#define STMFTS_UNK2 0xF7 #define STMFTS_FLASH_UNLOCK 0xF7
#define STMFTS_UNK3 0xFA #define STMFTS_FLASH_WRITE_64K 0xF8
#define STMFTS_UNK4 0xF9 #define STMFTS_FLASH_STATUS 0xF9
#define STMFTS_FLASH_OP 0xFA
#define STMFTS_UNK5 0x62 #define STMFTS_UNK5 0x62
/* cmd parameters */
#define STMFTS_VENDOR_GPIO_STATE 0x01
#define STMFTS_VENDOR_SENSE_MODE 0x02
#define STMFTS_STYLUS_MODE 0x00
#define STMFTS_FINGER_MODE 0x01
#define STMFTS_HOVER_MODE 0x02
/* events */ /* events */
#define STMFTS_EV_NO_EVENT 0x00 #define STMFTS_EV_NO_EVENT 0x00
@ -74,6 +81,7 @@
#define STMFTS_EV_ERROR 0x0f #define STMFTS_EV_ERROR 0x0f
#define STMFTS_EV_NOISE_READ 0x17 #define STMFTS_EV_NOISE_READ 0x17
#define STMFTS_EV_NOISE_WRITE 0x18 #define STMFTS_EV_NOISE_WRITE 0x18
#define STMFTS_EV_VENDOR 0x20
#define STMFTS_EV_CONTROLLER_READY 0x10 #define STMFTS_EV_CONTROLLER_READY 0x10
#define STMFTS_EV_STATUS 0x16 #define STMFTS_EV_STATUS 0x16
@ -131,6 +139,15 @@ typedef struct _touch_event {
bool touch; bool touch;
} touch_event; } touch_event;
typedef struct _touch_panel_info_t
{
u8 idx;
u8 gpio0;
u8 gpio1;
u8 gpio2;
char *vendor;
} touch_panel_info_t;
typedef struct _touch_info { typedef struct _touch_info {
u16 chip_id; u16 chip_id;
u16 fw_ver; u16 fw_ver;
@ -146,6 +163,7 @@ typedef struct _touch_fw_info_t {
void touch_poll(touch_event *event); void touch_poll(touch_event *event);
touch_event touch_poll_wait(); touch_event touch_poll_wait();
touch_panel_info_t *touch_get_panel_vendor();
int touch_get_fw_info(touch_fw_info_t *fw); int touch_get_fw_info(touch_fw_info_t *fw);
touch_info touch_get_info(); touch_info touch_get_info();
int touch_panel_ito_test(u8 *err); int touch_panel_ito_test(u8 *err);

View File

@ -839,10 +839,12 @@ int LZ4_compress_fast_extState_fastReset(void* state, const char* src, char* dst
int LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) int LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
{ {
int result; int result;
LZ4_stream_t ctx; LZ4_stream_t* ctx = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t));
LZ4_stream_t* const ctxPtr = &ctx; LZ4_stream_t* const ctxPtr = ctx;
result = LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration); result = LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration);
FREEMEM(ctx);
return result; return result;
} }
@ -857,13 +859,18 @@ int LZ4_compress_default(const char* source, char* dest, int inputSize, int maxO
/* strangely enough, gcc generates faster code when this function is uncommented, even if unused */ /* strangely enough, gcc generates faster code when this function is uncommented, even if unused */
int LZ4_compress_fast_force(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) int LZ4_compress_fast_force(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
{ {
LZ4_stream_t ctx; int result;
LZ4_resetStream(&ctx); LZ4_stream_t* ctx = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t));
LZ4_resetStream(ctx);
if (inputSize < LZ4_64Klimit) if (inputSize < LZ4_64Klimit)
return LZ4_compress_generic(&ctx.internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration); result = LZ4_compress_generic(&ctx->internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration);
else else
return LZ4_compress_generic(&ctx.internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, sizeof(void*)==8 ? byU32 : byPtr, noDict, noDictIssue, acceleration); result = LZ4_compress_generic(&ctx->internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, sizeof(void*)==8 ? byU32 : byPtr, noDict, noDictIssue, acceleration);
FREEMEM(ctx);
return result;
} }
@ -1045,11 +1052,13 @@ static int LZ4_compress_destSize_extState (LZ4_stream_t* state, const char* src,
int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize) int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize)
{ {
LZ4_stream_t ctxBody; LZ4_stream_t* ctxBody = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t));;
LZ4_stream_t* ctx = &ctxBody; LZ4_stream_t* ctx = ctxBody;
int result = LZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize); int result = LZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize);
FREEMEM(ctxBody);
return result; return result;
} }

View File

@ -27,7 +27,8 @@ typedef enum {
DRIVE_SD = 0, DRIVE_SD = 0,
DRIVE_RAM = 1, DRIVE_RAM = 1,
DRIVE_EMMC = 2, DRIVE_EMMC = 2,
DRIVE_BIS = 3 DRIVE_BIS = 3,
DRIVE_EMU = 4
} DDRIVE; } DDRIVE;
@ -59,6 +60,7 @@ DRESULT disk_set_info (BYTE pdrv, BYTE cmd, void *buff);
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */ #define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */
#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 */
/* Generic command (Not used by FatFs) */ /* Generic command (Not used by FatFs) */
#define CTRL_POWER 5 /* Get/Set power status */ #define CTRL_POWER 5 /* Get/Set power status */

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2019 CTCaer * Copyright (c) 2018-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -38,6 +38,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 <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);
@ -3284,6 +3285,7 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
/* Following code attempts to mount the volume. (analyze BPB and initialize the filesystem object) */ /* Following code attempts to mount the volume. (analyze BPB and initialize the filesystem object) */
fs->fs_type = 0; /* Clear the filesystem object */ fs->fs_type = 0; /* Clear the filesystem object */
fs->part_type = 0; /* Clear the Partition object */
fs->pdrv = LD2PD(vol); /* Bind the logical drive and a physical drive */ fs->pdrv = LD2PD(vol); /* Bind the logical drive and a physical drive */
stat = disk_initialize(fs->pdrv); /* Initialize the physical drive */ stat = disk_initialize(fs->pdrv); /* Initialize the physical drive */
if (stat & STA_NOINIT) { /* Check if the initialization succeeded */ if (stat & STA_NOINIT) { /* Check if the initialization succeeded */
@ -3318,6 +3320,20 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
EFSPRINTF("BRNL"); EFSPRINTF("BRNL");
return FR_DISK_ERR; /* An error occured in the disk I/O layer */ return FR_DISK_ERR; /* An error occured in the disk I/O layer */
} }
#if FF_SIMPLE_GPT
if (fmt >= 2) {
/* If GPT Check the first partition */
gpt_header_t *gpt_header = (gpt_header_t *)fs->win;
if (move_window(fs, 1) != FR_OK) return FR_DISK_ERR;
if (!mem_cmp(&gpt_header->signature, "EFI PART", 8)) {
if (move_window(fs, gpt_header->part_ent_lba) != FR_OK) return FR_DISK_ERR;
gpt_entry_t *gpt_entry = (gpt_entry_t *)fs->win;
fs->part_type = 1;
bsect = gpt_entry->lba_start;
fmt = bsect ? check_fs(fs, bsect) : 3; /* Check the partition */
}
}
#endif
if (fmt >= 2) { if (fmt >= 2) {
EFSPRINTF("NOFAT"); EFSPRINTF("NOFAT");
return FR_NO_FILESYSTEM; /* No FAT volume is found */ return FR_NO_FILESYSTEM; /* No FAT volume is found */
@ -6169,7 +6185,9 @@ FRESULT f_mkfs (
#endif #endif
/* Create FAT VBR */ /* Create FAT VBR */
mem_set(buf, 0, ss); mem_set(buf, 0, ss);
mem_cpy(buf + BS_JmpBoot, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code (x86), OEM name */ /* Boot jump code (x86), OEM name */
if (!(opt & FM_PRF2)) mem_cpy(buf + BS_JmpBoot, "\xEB\xFE\x90" "NYX1.0.0", 11);
else mem_cpy(buf + BS_JmpBoot, "\xEB\xE9\x90\x00\x00\x00\x00\x00\x00\x00\x00", 11);
st_word(buf + BPB_BytsPerSec, ss); /* Sector size [byte] */ st_word(buf + BPB_BytsPerSec, ss); /* Sector size [byte] */
buf[BPB_SecPerClus] = (BYTE)pau; /* Cluster size [sector] */ buf[BPB_SecPerClus] = (BYTE)pau; /* Cluster size [sector] */
st_word(buf + BPB_RsvdSecCnt, (WORD)sz_rsv); /* Size of reserved area */ st_word(buf + BPB_RsvdSecCnt, (WORD)sz_rsv); /* Size of reserved area */
@ -6182,23 +6200,27 @@ FRESULT f_mkfs (
} }
buf[BPB_Media] = 0xF8; /* Media descriptor byte */ buf[BPB_Media] = 0xF8; /* Media descriptor byte */
st_word(buf + BPB_SecPerTrk, 63); /* Number of sectors per track (for int13) */ st_word(buf + BPB_SecPerTrk, 63); /* Number of sectors per track (for int13) */
st_word(buf + BPB_NumHeads, 255); /* Number of heads (for int13) */ st_word(buf + BPB_NumHeads, (opt & FM_PRF2) ? 16 : 255); /* Number of heads (for int13) */
st_dword(buf + BPB_HiddSec, b_vol); /* Volume offset in the physical drive [sector] */ st_dword(buf + BPB_HiddSec, b_vol); /* Volume offset in the physical drive [sector] */
if (fmt == FS_FAT32) { if (fmt == FS_FAT32) {
st_dword(buf + BS_VolID32, GET_FATTIME()); /* VSN */ st_dword(buf + BS_VolID32, (opt & FM_PRF2) ? 0 : GET_FATTIME()); /* VSN */
st_dword(buf + BPB_FATSz32, sz_fat); /* FAT size [sector] */ st_dword(buf + BPB_FATSz32, sz_fat); /* FAT size [sector] */
st_dword(buf + BPB_RootClus32, 2); /* Root directory cluster # (2) */ st_dword(buf + BPB_RootClus32, 2); /* Root directory cluster # (2) */
st_word(buf + BPB_FSInfo32, 1); /* Offset of FSINFO sector (VBR + 1) */ st_word(buf + BPB_FSInfo32, 1); /* Offset of FSINFO sector (VBR + 1) */
st_word(buf + BPB_BkBootSec32, 6); /* Offset of backup VBR (VBR + 6) */ st_word(buf + BPB_BkBootSec32, 6); /* Offset of backup VBR (VBR + 6) */
buf[BS_DrvNum32] = 0x80; /* Drive number (for int13) */ buf[BS_DrvNum32] = 0x80; /* Drive number (for int13) */
buf[BS_BootSig32] = 0x29; /* Extended boot signature */ buf[BS_BootSig32] = 0x29; /* Extended boot signature */
mem_cpy(buf + BS_VolLab32, "SWITCH SD " "FAT32 ", 19); /* Volume label, FAT signature */ /* Volume label, FAT signature */
if (!(opt & FM_PRF2)) mem_cpy(buf + BS_VolLab32, FF_MKFS_LABEL "FAT32 ", 19);
else mem_cpy(buf + BS_VolLab32, "NO NAME " "FAT32 ", 19);
} else { } else {
st_dword(buf + BS_VolID, GET_FATTIME()); /* VSN */ st_dword(buf + BS_VolID, GET_FATTIME()); /* VSN */
st_word(buf + BPB_FATSz16, (WORD)sz_fat); /* FAT size [sector] */ st_word(buf + BPB_FATSz16, (WORD)sz_fat); /* FAT size [sector] */
buf[BS_DrvNum] = 0x80; /* Drive number (for int13) */ buf[BS_DrvNum] = 0x80; /* Drive number (for int13) */
buf[BS_BootSig] = 0x29; /* Extended boot signature */ buf[BS_BootSig] = 0x29; /* Extended boot signature */
mem_cpy(buf + BS_VolLab, "SWITCH SD " "FAT ", 19); /* Volume label, FAT signature */ /* Volume label, FAT signature */
if (!(opt & FM_PRF2)) mem_cpy(buf + BS_VolLab, FF_MKFS_LABEL "FAT ", 19);
else mem_cpy(buf + BS_VolLab, "NO NAME " "FAT ", 19);
} }
st_word(buf + BS_55AA, 0xAA55); /* Signature (offset is fixed here regardless of sector size) */ st_word(buf + BS_55AA, 0xAA55); /* Signature (offset is fixed here regardless of sector size) */
if (disk_write(pdrv, buf, b_vol, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it to the VBR sector */ if (disk_write(pdrv, buf, b_vol, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it to the VBR sector */
@ -6216,6 +6238,16 @@ FRESULT f_mkfs (
disk_write(pdrv, buf, b_vol + 1, 1); /* Write original FSINFO (VBR + 1) */ disk_write(pdrv, buf, b_vol + 1, 1); /* Write original FSINFO (VBR + 1) */
} }
/* Create PRF2SAFE info */
if (fmt == FS_FAT32 && opt & FM_PRF2) {
mem_set(buf, 0, ss);
buf[16] = 0x64; /* Record type */
st_dword(buf + 32, 0x03); /* Unknown. SYSTEM: 0x3F00. USER: 0x03. Volatile. */
st_dword(buf + 36, 25); /* Entries. SYSTEM: 22. USER: 25.Static? */
st_dword(buf + 508, 0x517BBFE0); /* Custom CRC32. SYSTEM: 0x6B673904. USER: 0x517BBFE0. */
disk_write(pdrv, buf, b_vol + 3, 1); /* Write PRF2SAFE info (VBR + 3) */
}
/* Initialize FAT area */ /* Initialize FAT area */
mem_set(buf, 0, (UINT)szb_buf); mem_set(buf, 0, (UINT)szb_buf);
sect = b_fat; /* FAT start sector */ sect = b_fat; /* FAT start sector */

View File

@ -97,6 +97,7 @@ typedef DWORD FSIZE_t;
typedef struct { typedef struct {
BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */ BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
BYTE fs_type; /* Filesystem type (0:not mounted) */ BYTE fs_type; /* Filesystem type (0:not mounted) */
BYTE part_type; /* Partition type (0:MBR, 1:GPT) */
BYTE pdrv; /* Associated physical drive */ BYTE pdrv; /* Associated physical drive */
BYTE n_fats; /* Number of FATs (1 or 2) */ BYTE n_fats; /* Number of FATs (1 or 2) */
BYTE wflag; /* win[] flag (b0:dirty) */ BYTE wflag; /* win[] flag (b0:dirty) */
@ -168,9 +169,6 @@ typedef struct {
/* File object structure (FIL) */ /* File object structure (FIL) */
typedef struct { typedef struct {
#if !FF_FS_TINY
BYTE buf[FF_MAX_SS]; /* File private data read/write window */
#endif
FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */ FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */
BYTE flag; /* File status flags */ BYTE flag; /* File status flags */
BYTE err; /* Abort flag (error code) */ BYTE err; /* Abort flag (error code) */
@ -184,6 +182,9 @@ typedef struct {
#if FF_USE_FASTSEEK #if FF_USE_FASTSEEK
DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */ DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */
#endif #endif
#if !FF_FS_TINY
BYTE buf[FF_MAX_SS] __attribute__((aligned(8))); /* File private data read/write window. DMA aligned. */
#endif
} FIL; } FIL;
@ -365,6 +366,7 @@ int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */
#define FM_EXFAT 0x04 #define FM_EXFAT 0x04
#define FM_ANY 0x07 #define FM_ANY 0x07
#define FM_SFD 0x08 #define FM_SFD 0x08
#define FM_PRF2 0x10
/* Filesystem type (FATFS.fs_type) */ /* Filesystem type (FATFS.fs_type) */
#define FS_FAT12 1 #define FS_FAT12 1

View File

@ -155,7 +155,7 @@
/*Log settings*/ /*Log settings*/
#ifdef DEBUG_UART_PORT #ifdef DEBUG_UART_LV_LOG
# define USE_LV_LOG 1 /*Enable/disable the log module*/ # define USE_LV_LOG 1 /*Enable/disable the log module*/
#else #else
# define USE_LV_LOG 0 /*Enable/disable the log module*/ # define USE_LV_LOG 0 /*Enable/disable the log module*/

View File

@ -63,7 +63,7 @@ void lv_log_add(lv_log_level_t level, const char * file, int line, const char *
if(level >= LV_LOG_LEVEL) { if(level >= LV_LOG_LEVEL) {
#if LV_LOG_PRINTF #if LV_LOG_PRINTF && defined(DEBUG_UART_PORT)
static const char * lvl_prefix[] = {"Trace", "Info", "Warn", "Error"}; static const char * lvl_prefix[] = {"Trace", "Info", "Warn", "Error"};
char *log = (char *)malloc(0x1000); char *log = (char *)malloc(0x1000);
s_printf(log, "%s: %s \t(%s #%d)\r\n", lvl_prefix[level], dsc, file, line); s_printf(log, "%s: %s \t(%s #%d)\r\n", lvl_prefix[level], dsc, file, line);

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer * Copyright (c) 2018-2020 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,
@ -20,6 +20,8 @@
#include <soc/clock.h> #include <soc/clock.h>
#include <utils/util.h> #include <utils/util.h>
#define CONFIG_ENABLE_AHB_REDIRECT
void mc_config_tsec_carveout(u32 bom, u32 size1mb, bool lock) void mc_config_tsec_carveout(u32 bom, u32 size1mb, bool lock)
{ {
MC(MC_SEC_CARVEOUT_BOM) = bom; MC(MC_SEC_CARVEOUT_BOM) = bom;
@ -143,17 +145,19 @@ void mc_disable_ahb_redirect()
void mc_enable() void mc_enable()
{ {
// Reset EMC source to PLLP.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) & 0x1FFFFFFF) | 0x40000000; CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) & 0x1FFFFFFF) | 0x40000000;
// Enable memory clocks. // Enable memory clocks.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & ~BIT(CLK_H_EMC)) | BIT(CLK_H_EMC); CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_EMC);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & ~BIT(CLK_H_MEM)) | BIT(CLK_H_MEM); CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_MEM);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) & ~BIT(CLK_X_EMC_DLL)) | BIT(CLK_X_EMC_DLL); CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = BIT(CLK_X_EMC_DLL);
// Clear clock resets for memory. // Clear clock resets for memory.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_EMC) | BIT(CLK_H_MEM); CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_EMC) | BIT(CLK_H_MEM);
usleep(5); usleep(5);
//#ifdef CONFIG_ENABLE_AHB_REDIRECT #ifdef CONFIG_ENABLE_AHB_REDIRECT
mc_enable_ahb_redirect();
#else
mc_disable_ahb_redirect(); mc_disable_ahb_redirect();
//mc_enable_ahb_redirect(); #endif
//#endif
} }

View File

@ -60,7 +60,7 @@ u32 minerva_init()
mtc_config_t mtc_tmp; mtc_config_t mtc_tmp;
mtc_tmp.mtc_table = mtc_cfg->mtc_table; mtc_tmp.mtc_table = mtc_cfg->mtc_table;
mtc_tmp.sdram_id = (fuse_read_odm(4) >> 3) & 0x1F; mtc_tmp.sdram_id = fuse_read_dramid(false);
mtc_tmp.init_done = MTC_NEW_MAGIC; mtc_tmp.init_done = MTC_NEW_MAGIC;
u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)&mtc_tmp); u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)&mtc_tmp);
@ -81,7 +81,7 @@ u32 minerva_init()
// Set table to nyx storage. // Set table to nyx storage.
mtc_cfg->mtc_table = (emc_table_t *)nyx_str->mtc_table; mtc_cfg->mtc_table = (emc_table_t *)nyx_str->mtc_table;
mtc_cfg->sdram_id = (fuse_read_odm(4) >> 3) & 0x1F; mtc_cfg->sdram_id = fuse_read_dramid(false);
mtc_cfg->init_done = MTC_NEW_MAGIC; // Initialize mtc table. mtc_cfg->init_done = MTC_NEW_MAGIC; // Initialize mtc table.
u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)mtc_cfg); u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)mtc_cfg);
@ -104,21 +104,21 @@ u32 minerva_init()
} }
mtc_cfg->rate_from = mtc_cfg->mtc_table[curr_ram_idx].rate_khz; mtc_cfg->rate_from = mtc_cfg->mtc_table[curr_ram_idx].rate_khz;
mtc_cfg->rate_to = 204000; mtc_cfg->rate_to = FREQ_204;
mtc_cfg->train_mode = OP_TRAIN; mtc_cfg->train_mode = OP_TRAIN;
minerva_cfg(mtc_cfg, NULL); minerva_cfg(mtc_cfg, NULL);
mtc_cfg->rate_to = 800000; mtc_cfg->rate_to = FREQ_800;
minerva_cfg(mtc_cfg, NULL); minerva_cfg(mtc_cfg, NULL);
mtc_cfg->rate_to = 1600000; mtc_cfg->rate_to = FREQ_1600;
minerva_cfg(mtc_cfg, NULL); minerva_cfg(mtc_cfg, NULL);
// FSP WAR. // FSP WAR.
mtc_cfg->train_mode = OP_SWITCH; mtc_cfg->train_mode = OP_SWITCH;
mtc_cfg->rate_to = 800000; mtc_cfg->rate_to = FREQ_800;
minerva_cfg(mtc_cfg, NULL); minerva_cfg(mtc_cfg, NULL);
// Switch to max. // Switch to max.
mtc_cfg->rate_to = 1600000; mtc_cfg->rate_to = FREQ_1600;
minerva_cfg(mtc_cfg, NULL); minerva_cfg(mtc_cfg, NULL);
return 0; return 0;
@ -129,6 +129,7 @@ void minerva_change_freq(minerva_freq_t freq)
if (!minerva_cfg) if (!minerva_cfg)
return; return;
// Check if requested frequency is different. Do not allow otherwise because it will hang.
mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg; mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
if (mtc_cfg->rate_from != freq) if (mtc_cfg->rate_from != freq)
{ {
@ -138,6 +139,23 @@ void minerva_change_freq(minerva_freq_t freq)
} }
} }
void minerva_prep_boot_freq()
{
if (!minerva_cfg)
return;
mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
// Check if there's RAM OC. If not exit.
if (mtc_cfg->mtc_table[mtc_cfg->table_entries - 1].rate_khz == FREQ_1600)
return;
// FSP WAR.
minerva_change_freq(FREQ_204);
// Scale down to 800 MHz boot freq.
minerva_change_freq(FREQ_800);
}
void minerva_periodic_training() void minerva_periodic_training()
{ {
if (!minerva_cfg) if (!minerva_cfg)

View File

@ -60,6 +60,7 @@ typedef enum
extern void (*minerva_cfg)(mtc_config_t *mtc_cfg, void *); extern void (*minerva_cfg)(mtc_config_t *mtc_cfg, void *);
u32 minerva_init(); u32 minerva_init();
void minerva_change_freq(minerva_freq_t freq); void minerva_change_freq(minerva_freq_t freq);
void minerva_prep_boot_freq();
void minerva_periodic_training(); void minerva_periodic_training();
#endif #endif

View File

@ -54,11 +54,6 @@ typedef struct _sdram_vendor_patch_t
#include "sdram_config_t210b01.inl" #include "sdram_config_t210b01.inl"
static u32 _sdram_get_id()
{
return ((fuse_read_odm(4) & 0xF8) >> 3);
}
static bool _sdram_wait_emc_status(u32 reg_offset, u32 bit_mask, bool updated_state, s32 emc_channel) static bool _sdram_wait_emc_status(u32 reg_offset, u32 bit_mask, bool updated_state, s32 emc_channel)
{ {
bool err = true; bool err = true;
@ -1374,9 +1369,7 @@ static void _sdram_patch_model_params_t210b01(u32 dramid, u32 *params)
static void *_sdram_get_params_t210() static void *_sdram_get_params_t210()
{ {
// Check if id is proper. // Check if id is proper.
u32 dramid = _sdram_get_id(); u32 dramid = fuse_read_dramid(false);
if (dramid > 6)
dramid = 0;
#ifdef CONFIG_SDRAM_COMPRESS_CFG #ifdef CONFIG_SDRAM_COMPRESS_CFG
@ -1413,9 +1406,7 @@ static void *_sdram_get_params_t210()
void *sdram_get_params_t210b01() void *sdram_get_params_t210b01()
{ {
// Check if id is proper. // Check if id is proper.
u32 dramid = _sdram_get_id(); u32 dramid = fuse_read_dramid(false);
if (dramid > 27)
dramid = 8;
u32 *buf = (u32 *)SDRAM_PARAMS_ADDR; u32 *buf = (u32 *)SDRAM_PARAMS_ADDR;
memcpy(buf, &_dram_cfg_08_10_12_14_samsung_hynix_4gb, sizeof(sdram_params_t210b01_t)); memcpy(buf, &_dram_cfg_08_10_12_14_samsung_hynix_4gb, sizeof(sdram_params_t210b01_t));
@ -1439,12 +1430,12 @@ void *sdram_get_params_t210b01()
case LPDDR4X_HOAG_4GB_SAMSUNG_1Y_X: case LPDDR4X_HOAG_4GB_SAMSUNG_1Y_X:
case LPDDR4X_IOWA_4GB_SAMSUNG_1Y_Y: case LPDDR4X_IOWA_4GB_SAMSUNG_1Y_Y:
case LPDDR4X_IOWA_8GB_SAMSUNG_1Y_Y: case LPDDR4X_IOWA_8GB_SAMSUNG_1Y_Y:
case LPDDR4X_SDS_4GB_SAMSUNG_1Y_A: case LPDDR4X_AULA_4GB_SAMSUNG_1Y_A:
case LPDDR4X_SDS_8GB_SAMSUNG_1Y_X: case LPDDR4X_AULA_8GB_SAMSUNG_1Y_X:
case LPDDR4X_SDS_4GB_SAMSUNG_1Y_X: case LPDDR4X_AULA_4GB_SAMSUNG_1Y_X:
case LPDDR4X_IOWA_4GB_MICRON_1Y_A: case LPDDR4X_IOWA_4GB_MICRON_1Y_A:
case LPDDR4X_HOAG_4GB_MICRON_1Y_A: case LPDDR4X_HOAG_4GB_MICRON_1Y_A:
case LPDDR4X_SDS_4GB_MICRON_1Y_A: case LPDDR4X_AULA_4GB_MICRON_1Y_A:
_sdram_patch_model_params_t210b01(dramid, (u32 *)buf); _sdram_patch_model_params_t210b01(dramid, (u32 *)buf);
break; break;
} }
@ -1494,7 +1485,7 @@ static void _sdram_init_t210()
const sdram_params_t210_t *params = (const sdram_params_t210_t *)_sdram_get_params_t210(); const sdram_params_t210_t *params = (const sdram_params_t210_t *)_sdram_get_params_t210();
// Set DRAM voltage. // Set DRAM voltage.
max77620_regulator_set_voltage(REGULATOR_SD1, 1100000); max7762x_regulator_set_voltage(REGULATOR_SD1, 1100000);
// VDDP Select. // VDDP Select.
PMC(APBDEV_PMC_VDDP_SEL) = params->pmc_vddp_sel; PMC(APBDEV_PMC_VDDP_SEL) = params->pmc_vddp_sel;
@ -1539,8 +1530,8 @@ static void _sdram_init_t210b01()
void sdram_init() void sdram_init()
{ {
// Configure SD regulator for DRAM. // Disable remote sense for SD1.
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, 0x05); i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, MAX77620_SD_CNF2_ROVS_EN_SD0 | MAX77620_SD_CNF2_RSVD);
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210) if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210)
_sdram_init_t210(); _sdram_init_t210();

View File

@ -45,7 +45,7 @@ enum sdram_ids_erista
LPDDR4_ICOSA_4GB_SAMSUNG_K4F6E304HB_MGCH = 0, LPDDR4_ICOSA_4GB_SAMSUNG_K4F6E304HB_MGCH = 0,
LPDDR4_ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 1, LPDDR4_ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 1,
LPDDR4_ICOSA_4GB_MICRON_MT53B512M32D2NP_062_WT = 2, LPDDR4_ICOSA_4GB_MICRON_MT53B512M32D2NP_062_WT = 2,
LPDDR4_COPPER_4GB_SAMSUNG_K4F6E304HB_MGCH = 3, LPDDR4_COPPER_4GB_SAMSUNG_K4F6E304HB_MGCH = 3, // Changed to AULA Hynix 4GB 1Y-A.
LPDDR4_ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH = 4, LPDDR4_ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH = 4,
LPDDR4_COPPER_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 5, LPDDR4_COPPER_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 5,
LPDDR4_COPPER_4GB_MICRON_MT53B512M32D2NP_062_WT = 6, LPDDR4_COPPER_4GB_MICRON_MT53B512M32D2NP_062_WT = 6,
@ -76,14 +76,14 @@ enum sdram_ids_mariko
LPDDR4X_IOWA_4GB_SAMSUNG_1Y_Y = 20, LPDDR4X_IOWA_4GB_SAMSUNG_1Y_Y = 20,
LPDDR4X_IOWA_8GB_SAMSUNG_1Y_Y = 21, LPDDR4X_IOWA_8GB_SAMSUNG_1Y_Y = 21,
LPDDR4X_SDS_4GB_SAMSUNG_1Y_A = 22, LPDDR4X_AULA_4GB_SAMSUNG_1Y_A = 22,
LPDDR4X_SDS_8GB_SAMSUNG_1Y_X = 23, LPDDR4X_AULA_8GB_SAMSUNG_1Y_X = 23,
LPDDR4X_SDS_4GB_SAMSUNG_1Y_X = 24, LPDDR4X_AULA_4GB_SAMSUNG_1Y_X = 24,
LPDDR4X_IOWA_4GB_MICRON_1Y_A = 25, LPDDR4X_IOWA_4GB_MICRON_1Y_A = 25,
LPDDR4X_HOAG_4GB_MICRON_1Y_A = 26, LPDDR4X_HOAG_4GB_MICRON_1Y_A = 26,
LPDDR4X_SDS_4GB_MICRON_1Y_A = 27 LPDDR4X_AULA_4GB_MICRON_1Y_A = 27
}; };
void sdram_init(); void sdram_init();

View File

@ -97,7 +97,7 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = {
* DRAM size information * DRAM size information
* Specifies the value for EMC_ADR_CFG * Specifies the value for EMC_ADR_CFG
*/ */
.emc_adr_cfg = 0x00000001, // 2 populated DRAM Devices. .emc_adr_cfg = 0x00000001, // 2 Ranks.
/* /*
* Specifies the time to wait after asserting pin * Specifies the time to wait after asserting pin
@ -243,7 +243,7 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = {
.emc_cfg_dig_dll = 0x002C00A0, .emc_cfg_dig_dll = 0x002C00A0,
.emc_cfg_dig_dll_1 = 0x00003701, .emc_cfg_dig_dll_1 = 0x00003701,
.emc_cfg_dig_dll_period = 0x00008000, .emc_cfg_dig_dll_period = 0x00008000,
.emc_dev_select = 0x00000000, // Both devices. .emc_dev_select = 0x00000000, // Both Ranks.
.emc_sel_dpd_ctrl = 0x00040008, .emc_sel_dpd_ctrl = 0x00040008,
/* Pads trimmer delays */ /* Pads trimmer delays */
@ -406,7 +406,7 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = {
.pmc_ddr_ctrl = 0x0007FF8B, .pmc_ddr_ctrl = 0x0007FF8B,
.emc_acpd_control = 0x00000000, .emc_acpd_control = 0x00000000,
.emc_swizzle_rank0_byte0 = 0x76543201, .emc_swizzle_rank0_byte0 = 0x76543201, // Overridden to 0x76543201 by spare6/7.
.emc_swizzle_rank0_byte1 = 0x65324710, .emc_swizzle_rank0_byte1 = 0x65324710,
.emc_swizzle_rank0_byte2 = 0x25763410, .emc_swizzle_rank0_byte2 = 0x25763410,
.emc_swizzle_rank0_byte3 = 0x25673401, .emc_swizzle_rank0_byte3 = 0x25673401,
@ -454,7 +454,7 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = {
.emc_pmacro_data_rx_term_mode = 0x00000010, .emc_pmacro_data_rx_term_mode = 0x00000010,
.emc_pmacro_cmd_rx_term_mode = 0x00003000, .emc_pmacro_cmd_rx_term_mode = 0x00003000,
.emc_pmacro_data_pad_tx_ctrl = 0x02000111, .emc_pmacro_data_pad_tx_ctrl = 0x02000111,
.emc_pmacro_common_pad_tx_ctrl = 0x00000008, .emc_pmacro_common_pad_tx_ctrl = 0x00000008, // Overridden to 0x0000000A by spare4/5.
.emc_pmacro_cmd_pad_tx_ctrl = 0x0A000000, .emc_pmacro_cmd_pad_tx_ctrl = 0x0A000000,
.emc_cfg3 = 0x00000040, .emc_cfg3 = 0x00000040,
@ -490,9 +490,9 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = {
.emc_pmacro_cmd_ctrl2 = 0x0A0A0A0A, .emc_pmacro_cmd_ctrl2 = 0x0A0A0A0A,
/* DRAM size information */ /* DRAM size information */
.mc_emem_adr_cfg = 0x00000001, // 2 populated DRAM Devices. .mc_emem_adr_cfg = 0x00000001, // 2 Ranks.
.mc_emem_adr_cfg_dev0 = 0x00070302, // Density 512MB. .mc_emem_adr_cfg_dev0 = 0x00070302, // Rank 0 Density 512MB.
.mc_emem_adr_cfg_dev1 = 0x00070302, // Density 512MB. .mc_emem_adr_cfg_dev1 = 0x00070302, // Rank 1 Density 512MB.
.mc_emem_adr_cfg_channel_mask = 0xFFFF2400, .mc_emem_adr_cfg_channel_mask = 0xFFFF2400,
.mc_emem_adr_cfg_bank_mask0 = 0x6E574400, .mc_emem_adr_cfg_bank_mask0 = 0x6E574400,
.mc_emem_adr_cfg_bank_mask1 = 0x39722800, .mc_emem_adr_cfg_bank_mask1 = 0x39722800,
@ -653,8 +653,8 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210[] = {
{ 0x00000005, 368, DRAM_ID(1) | DRAM_ID(5) }, // mc_emem_arb_timing_r2w. { 0x00000005, 368, DRAM_ID(1) | DRAM_ID(5) }, // mc_emem_arb_timing_r2w.
// Samsung 6GB density config. // Samsung 6GB density config.
{ 0x000C0302, 347, DRAM_ID(4) }, // mc_emem_adr_cfg_dev0. 768MB sub-partition density. { 0x000C0302, 347, DRAM_ID(4) }, // mc_emem_adr_cfg_dev0. 768MB Rank 0 density.
{ 0x000C0302, 348, DRAM_ID(4) }, // mc_emem_adr_cfg_dev1. 768MB sub-partition density. { 0x000C0302, 348, DRAM_ID(4) }, // mc_emem_adr_cfg_dev1. 768MB Rank 1 density.
{ 0x00001800, 353, DRAM_ID(4) }, // mc_emem_cfg. 6GB total density. { 0x00001800, 353, DRAM_ID(4) }, // mc_emem_cfg. 6GB total density.
#ifdef CONFIG_SDRAM_COPPER_SUPPORT #ifdef CONFIG_SDRAM_COPPER_SUPPORT

View File

@ -122,7 +122,7 @@ static const sdram_params_t210b01_t _dram_cfg_08_10_12_14_samsung_hynix_4gb = {
* DRAM size information * DRAM size information
* Specifies the value for EMC_ADR_CFG * Specifies the value for EMC_ADR_CFG
*/ */
.emc_adr_cfg = 0x00000000, // 1 populated DRAM Device. .emc_adr_cfg = 0x00000000, // 1 Rank.
/* /*
* Specifies the time to wait after asserting pin * Specifies the time to wait after asserting pin
@ -273,7 +273,7 @@ static const sdram_params_t210b01_t _dram_cfg_08_10_12_14_samsung_hynix_4gb = {
.emc_cfg_dig_dll = 0x002C00A0, .emc_cfg_dig_dll = 0x002C00A0,
.emc_cfg_dig_dll_1 = 0x000F3701, .emc_cfg_dig_dll_1 = 0x000F3701,
.emc_cfg_dig_dll_period = 0x00008000, .emc_cfg_dig_dll_period = 0x00008000,
.emc_dev_select = 0x00000002, // Dev0 only. .emc_dev_select = 0x00000002, // Rank 0 only.
.emc_sel_dpd_ctrl = 0x0004000C, .emc_sel_dpd_ctrl = 0x0004000C,
/* Pads trimmer delays */ /* Pads trimmer delays */
@ -543,9 +543,9 @@ static const sdram_params_t210b01_t _dram_cfg_08_10_12_14_samsung_hynix_4gb = {
.emc_pmacro_cmd_ctrl2 = 0x00000000, .emc_pmacro_cmd_ctrl2 = 0x00000000,
/* DRAM size information */ /* DRAM size information */
.mc_emem_adr_cfg = 0x00000000, // 1 populated DRAM Device. .mc_emem_adr_cfg = 0x00000000, // 1 Rank.
.mc_emem_adr_cfg_dev0 = 0x00080302, // Density 1024MB. .mc_emem_adr_cfg_dev0 = 0x00080302, // Rank 0 Density 1024MB.
.mc_emem_adr_cfg_dev1 = 0x00080302, // Density 1024MB. .mc_emem_adr_cfg_dev1 = 0x00080302, // Rank 1 Density 1024MB.
.mc_emem_adr_cfg_channel_mask = 0xFFFF2400, .mc_emem_adr_cfg_channel_mask = 0xFFFF2400,
.mc_emem_adr_cfg_bank_mask0 = 0x6E574400, .mc_emem_adr_cfg_bank_mask0 = 0x6E574400,
.mc_emem_adr_cfg_bank_mask1 = 0x39722800, .mc_emem_adr_cfg_bank_mask1 = 0x39722800,
@ -733,7 +733,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = {
// Samsung LPDDR4X 8GB K4UBE3D4AM-MGCJ for SDEV Iowa and Hoag. // Samsung LPDDR4X 8GB K4UBE3D4AM-MGCJ for SDEV Iowa and Hoag.
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_auto_cal_config2. { 0x05500000, 0x0D4 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_auto_cal_config2.
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_auto_cal_vref_sel0. { 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_auto_cal_vref_sel0.
{ 0x00000001, 0x134 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_adr_cfg. 2 populated DRAM Devices. { 0x00000001, 0x134 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_adr_cfg. 2 Ranks.
{ 0x00000006, 0x1CC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_quse. { 0x00000006, 0x1CC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_quse.
{ 0x00000005, 0x1D0 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_quse_width. { 0x00000005, 0x1D0 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_quse_width.
{ 0x00000003, 0x1DC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_einput. { 0x00000003, 0x1DC / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_einput.
@ -764,7 +764,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = {
{ 0x40000001, 0x45C / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_zcal_init_dev1. { 0x40000001, 0x45C / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_zcal_init_dev1.
{ 0x00000000, 0x594 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_tx_pwrd4. { 0x00000000, 0x594 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_tx_pwrd4.
{ 0x00001000, 0x598 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_tx_pwrd5. { 0x00001000, 0x598 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // emc_pmacro_tx_pwrd5.
{ 0x00000001, 0x630 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_adr_cfg. 2 populated DRAM Devices. { 0x00000001, 0x630 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_adr_cfg. 2 Ranks.
{ 0x00002000, 0x64C / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_cfg. 8GB total density. { 0x00002000, 0x64C / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_cfg. 8GB total density.
{ 0x00000002, 0x680 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_arb_timing_r2r. { 0x00000002, 0x680 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_arb_timing_r2r.
{ 0x02020001, 0x694 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_arb_da_turns. { 0x02020001, 0x694 / 4, DRAM_ID2(9) | DRAM_ID2(13) }, // mc_emem_arb_da_turns.
@ -810,7 +810,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = {
{ 0x2A800000, 0x6DC / 4, DRAM_ID2(16) }, // mc_video_protect_gpu_override0. { 0x2A800000, 0x6DC / 4, DRAM_ID2(16) }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, DRAM_ID2(16) }, // mc_video_protect_gpu_override1. { 0x00000002, 0x6E0 / 4, DRAM_ID2(16) }, // mc_video_protect_gpu_override1.
// Samsung LPDDR4X 4GB 10nm-class (1y) Die-X for Iowa, Hoag and SDS. // Samsung LPDDR4X 4GB 10nm-class (1y) Die-X for Iowa, Hoag and Aula.
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_auto_cal_config2. { 0x05500000, 0x0D4 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_auto_cal_config2.
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_auto_cal_vref_sel0. { 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_auto_cal_vref_sel0.
{ 0x00000006, 0x1CC / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_quse. { 0x00000006, 0x1CC / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // emc_quse.
@ -822,10 +822,10 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = {
{ 0x2A800000, 0x6DC / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // mc_video_protect_gpu_override0. { 0x2A800000, 0x6DC / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // mc_video_protect_gpu_override1. { 0x00000002, 0x6E0 / 4, DRAM_ID2(17) | DRAM_ID2(19) | DRAM_ID2(24) }, // mc_video_protect_gpu_override1.
// Samsung LPDDR4X 8GB 10nm-class (1y) Die-X for SDEV Iowa and SDS. // Samsung LPDDR4X 8GB 10nm-class (1y) Die-X for SDEV Iowa and Aula.
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_auto_cal_config2. { 0x05500000, 0x0D4 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_auto_cal_config2.
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_auto_cal_vref_sel0. { 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_auto_cal_vref_sel0.
{ 0x00000001, 0x134 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_adr_cfg. 2 populated DRAM Devices. { 0x00000001, 0x134 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_adr_cfg. 2 Ranks.
{ 0x00000006, 0x1CC / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_quse. { 0x00000006, 0x1CC / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_quse.
{ 0x00000005, 0x1D0 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_quse_width. { 0x00000005, 0x1D0 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_quse_width.
{ 0x00000003, 0x1DC / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_einput. { 0x00000003, 0x1DC / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_einput.
@ -847,7 +847,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = {
{ 0x40000001, 0x45C / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_zcal_init_dev1. { 0x40000001, 0x45C / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_zcal_init_dev1.
{ 0x00000000, 0x594 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_pmacro_tx_pwrd4. { 0x00000000, 0x594 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_pmacro_tx_pwrd4.
{ 0x00001000, 0x598 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_pmacro_tx_pwrd5. { 0x00001000, 0x598 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // emc_pmacro_tx_pwrd5.
{ 0x00000001, 0x630 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_adr_cfg. 2 populated DRAM Devices. { 0x00000001, 0x630 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_adr_cfg. 2 Ranks.
{ 0x00002000, 0x64C / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_cfg. 8GB total density. { 0x00002000, 0x64C / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_cfg. 8GB total density.
{ 0x00000001, 0x670 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_arb_timing_faw. { 0x00000001, 0x670 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_arb_timing_faw.
{ 0x00000002, 0x680 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_arb_timing_r2r. { 0x00000002, 0x680 / 4, DRAM_ID2(18) | DRAM_ID2(23) }, // mc_emem_arb_timing_r2r.
@ -881,7 +881,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = {
// Samsung LPDDR4X 8GB 10nm-class (1y) Die-Y for SDEV Iowa. // Samsung LPDDR4X 8GB 10nm-class (1y) Die-Y for SDEV Iowa.
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(21) }, // emc_auto_cal_config2. { 0x05500000, 0x0D4 / 4, DRAM_ID2(21) }, // emc_auto_cal_config2.
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(21) }, // emc_auto_cal_vref_sel0. { 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(21) }, // emc_auto_cal_vref_sel0.
{ 0x00000001, 0x134 / 4, DRAM_ID2(21) }, // emc_adr_cfg. 2 populated DRAM Devices. { 0x00000001, 0x134 / 4, DRAM_ID2(21) }, // emc_adr_cfg. 2 Ranks.
{ 0x00000008, 0x24C / 4, DRAM_ID2(21) }, // emc_tfaw. { 0x00000008, 0x24C / 4, DRAM_ID2(21) }, // emc_tfaw.
{ 0x08010004, 0x2B8 / 4, DRAM_ID2(21) }, // emc_mrw1. { 0x08010004, 0x2B8 / 4, DRAM_ID2(21) }, // emc_mrw1.
{ 0x08020000, 0x2BC / 4, DRAM_ID2(21) }, // emc_mrw2. { 0x08020000, 0x2BC / 4, DRAM_ID2(21) }, // emc_mrw2.
@ -914,7 +914,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = {
{ 0x40000001, 0x45C / 4, DRAM_ID2(21) }, // emc_zcal_init_dev1. { 0x40000001, 0x45C / 4, DRAM_ID2(21) }, // emc_zcal_init_dev1.
{ 0x00000000, 0x594 / 4, DRAM_ID2(21) }, // emc_pmacro_tx_pwrd4. { 0x00000000, 0x594 / 4, DRAM_ID2(21) }, // emc_pmacro_tx_pwrd4.
{ 0x00001000, 0x598 / 4, DRAM_ID2(21) }, // emc_pmacro_tx_pwrd5. { 0x00001000, 0x598 / 4, DRAM_ID2(21) }, // emc_pmacro_tx_pwrd5.
{ 0x00000001, 0x630 / 4, DRAM_ID2(21) }, // mc_emem_adr_cfg. 2 populated DRAM Devices. { 0x00000001, 0x630 / 4, DRAM_ID2(21) }, // mc_emem_adr_cfg. 2 Ranks.
{ 0x00002000, 0x64C / 4, DRAM_ID2(21) }, // mc_emem_cfg. 8GB total density. { 0x00002000, 0x64C / 4, DRAM_ID2(21) }, // mc_emem_cfg. 8GB total density.
{ 0x00000001, 0x670 / 4, DRAM_ID2(21) }, // mc_emem_arb_timing_faw. { 0x00000001, 0x670 / 4, DRAM_ID2(21) }, // mc_emem_arb_timing_faw.
{ 0x00000002, 0x680 / 4, DRAM_ID2(21) }, // mc_emem_arb_timing_r2r. { 0x00000002, 0x680 / 4, DRAM_ID2(21) }, // mc_emem_arb_timing_r2r.
@ -922,7 +922,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = {
{ 0x2A800000, 0x6DC / 4, DRAM_ID2(21) }, // mc_video_protect_gpu_override0. { 0x2A800000, 0x6DC / 4, DRAM_ID2(21) }, // mc_video_protect_gpu_override0.
{ 0x00000002, 0x6E0 / 4, DRAM_ID2(21) }, // mc_video_protect_gpu_override1. { 0x00000002, 0x6E0 / 4, DRAM_ID2(21) }, // mc_video_protect_gpu_override1.
// Samsung LPDDR4X 4GB 10nm-class (1y) Die-A for Unknown SDS. // Samsung LPDDR4X 4GB 10nm-class (1y) Die-A for Unknown Aula.
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(22) }, // emc_auto_cal_config2. { 0x05500000, 0x0D4 / 4, DRAM_ID2(22) }, // emc_auto_cal_config2.
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(22) }, // emc_auto_cal_vref_sel0. { 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(22) }, // emc_auto_cal_vref_sel0.
{ 0x00000008, 0x24C / 4, DRAM_ID2(22) }, // emc_tfaw. { 0x00000008, 0x24C / 4, DRAM_ID2(22) }, // emc_tfaw.
@ -986,7 +986,7 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = {
{ 0x00000002, 0x6E0 / 4, DRAM_ID2(22) }, // mc_video_protect_gpu_override1. { 0x00000002, 0x6E0 / 4, DRAM_ID2(22) }, // mc_video_protect_gpu_override1.
{ 0x0000009C, 0x814 / 4, DRAM_ID2(22) }, // swizzle_rank_byte_encode. { 0x0000009C, 0x814 / 4, DRAM_ID2(22) }, // swizzle_rank_byte_encode.
// Micron LPDDR4X 4GB 10nm-class (1y) Die-A for Unknown Iowa/Hoag/SDS. // Micron LPDDR4X 4GB 10nm-class (1y) Die-A for Unknown Iowa/Hoag/Aula.
{ 0x05500000, 0x0D4 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_auto_cal_config2. { 0x05500000, 0x0D4 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_auto_cal_config2.
{ 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_auto_cal_vref_sel0. { 0xC9AFBCBC, 0x0F4 / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_auto_cal_vref_sel0.
{ 0x00000006, 0x1CC / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_quse. { 0x00000006, 0x1CC / 4, DRAM_ID2(25) | DRAM_ID2(26) | DRAM_ID2(27) }, // emc_quse.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019 CTCaer * Copyright (c) 2019-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -49,8 +49,14 @@
// Virtual disk / Chainloader buffers. // Virtual disk / Chainloader buffers.
#define RAM_DISK_ADDR 0xA4000000 #define RAM_DISK_ADDR 0xA4000000
#define NX_BIS_CACHE_ADDR RAM_DISK_ADDR
#define RAM_DISK_SZ 0x41000000 // 1040MB. #define RAM_DISK_SZ 0x41000000 // 1040MB.
#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
@ -91,15 +97,10 @@
#define NYX_FB_SZ 0x384000 // 1280 x 720 x 4. #define NYX_FB_SZ 0x384000 // 1280 x 720 x 4.
#define DRAM_MEM_HOLE_ADR 0xF6A00000 #define DRAM_MEM_HOLE_ADR 0xF6A00000
#define NX_BIS_LOOKUP_ADR DRAM_MEM_HOLE_ADR
#define DRAM_MEM_HOLE_SZ 0x8140000 #define DRAM_MEM_HOLE_SZ 0x8140000
/* --- Hole: 129MB 0xF6A00000 - 0xFEB3FFFF --- */ /* --- Hole: 129MB 0xF6A00000 - 0xFEB3FFFF --- */
#define DRAM_START2 0xFEB40000 #define DRAM_START2 0xFEB40000
// NX BIS driver sector cache.
// #define NX_BIS_CACHE_ADDR 0xFEE00000
// #define NX_BIS_CACHE_SZ 0x100000
// USB buffers. // USB buffers.
#define USBD_ADDR 0xFEF00000 #define USBD_ADDR 0xFEF00000
#define USB_DESCRIPTOR_ADDR 0xFEF40000 #define USB_DESCRIPTOR_ADDR 0xFEF40000

View File

@ -21,10 +21,13 @@
#include <stddef.h> #include <stddef.h>
#include <mem/heap.h> #include <mem/heap.h>
#define IANOS_EXT0 0x304E4149
// Module Callback // Module Callback
typedef void (*cbMainModule_t)(const char *s); typedef void (*cbMainModule_t)(const char *s);
typedef void (*memcpy_t)(void *, void *, size_t); typedef void (*memcpy_t)(void *, void *, size_t);
typedef void (*memset_t)(void *, int, size_t); typedef void (*memset_t)(void *, int, size_t);
typedef int (*reg_voltage_set_t)(u32, u32);
typedef struct _bdkParams_t typedef struct _bdkParams_t
{ {
@ -33,6 +36,8 @@ typedef struct _bdkParams_t
heap_t *sharedHeap; heap_t *sharedHeap;
memcpy_t memcpy; memcpy_t memcpy;
memset_t memset; memset_t memset;
u32 extension_magic;
reg_voltage_set_t reg_voltage_set;
} *bdkParams_t; } *bdkParams_t;
// Module Entrypoint // Module Entrypoint

View File

@ -1,8 +1,7 @@
/* /*
* Defining registers address and its bit definitions of MAX77620 and MAX20024 * Defining registers address and its bit definitions of MAX77620 and MAX20024
* *
* Copyright (c) 2016 NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2019-2020 CTCaer
* Copyright (c) 2019 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,
@ -30,24 +29,33 @@
#define MAX77620_CNFGGLBL1_LBHYST_200 (1 << 4) #define MAX77620_CNFGGLBL1_LBHYST_200 (1 << 4)
#define MAX77620_CNFGGLBL1_LBHYST_300 (2 << 4) #define MAX77620_CNFGGLBL1_LBHYST_300 (2 << 4)
#define MAX77620_CNFGGLBL1_LBHYST_400 (3 << 4) #define MAX77620_CNFGGLBL1_LBHYST_400 (3 << 4)
#define MAX77620_CNFGGLBL1_LBHYST (BIT(5) | BIT(4))
#define MAX77620_CNFGGLBL1_MPPLD BIT(6) #define MAX77620_CNFGGLBL1_MPPLD BIT(6)
#define MAX77620_CNFGGLBL1_LBDAC_EN BIT(7) #define MAX77620_CNFGGLBL1_LBDAC_EN BIT(7)
#define MAX77620_REG_CNFGGLBL2 0x01 #define MAX77620_REG_CNFGGLBL2 0x01
#define MAX77620_REG_CNFGGLBL3 0x02
#define MAX77620_WDTC_MASK 0x3
#define MAX77620_WDTEN BIT(2)
#define MAX77620_WDTSLPC BIT(3)
#define MAX77620_WDTOFFC BIT(4)
#define MAX77620_TWD_MASK 0x3 #define MAX77620_TWD_MASK 0x3
#define MAX77620_TWD_2s 0x0 #define MAX77620_TWD_2s 0x0
#define MAX77620_TWD_16s 0x1 #define MAX77620_TWD_16s 0x1
#define MAX77620_TWD_64s 0x2 #define MAX77620_TWD_64s 0x2
#define MAX77620_TWD_128s 0x3 #define MAX77620_TWD_128s 0x3
#define MAX77620_WDTEN BIT(2)
#define MAX77620_WDTSLPC BIT(3)
#define MAX77620_WDTOFFC BIT(4)
#define MAX77620_GLBL_LPM BIT(5)
#define MAX77620_I2CTWD_MASK 0xC0
#define MAX77620_I2CTWD_DISABLED 0x00
#define MAX77620_I2CTWD_1_33ms 0x40
#define MAX77620_I2CTWD_35_7ms 0x80
#define MAX77620_I2CTWD_41_7ms 0xC0
#define MAX77620_REG_CNFGGLBL3 0x02
#define MAX77620_WDTC_MASK 0x3
#define MAX77620_REG_CNFG1_32K 0x03 #define MAX77620_REG_CNFG1_32K 0x03
#define MAX77620_CNFG1_PWR_MD_32K_MASK 0x3
#define MAX77620_CNFG1_32K_OUT0_EN BIT(2) #define MAX77620_CNFG1_32K_OUT0_EN BIT(2)
#define MAX77620_CNFG1_32KLOAD_MASK 0x30
#define MAX77620_CNFG1_32K_OK BIT(7)
#define MAX77620_REG_CNFGBBC 0x04 #define MAX77620_REG_CNFGBBC 0x04
#define MAX77620_CNFGBBC_ENABLE BIT(0) #define MAX77620_CNFGBBC_ENABLE BIT(0)
@ -64,6 +72,7 @@
#define MAX77620_CNFGBBC_RESISTOR_6K (3 << MAX77620_CNFGBBC_RESISTOR_SHIFT) #define MAX77620_CNFGBBC_RESISTOR_6K (3 << MAX77620_CNFGBBC_RESISTOR_SHIFT)
#define MAX77620_REG_IRQTOP 0x05 #define MAX77620_REG_IRQTOP 0x05
#define MAX77620_REG_IRQTOPM 0x0D
#define MAX77620_IRQ_TOP_ONOFF_MASK BIT(1) #define MAX77620_IRQ_TOP_ONOFF_MASK BIT(1)
#define MAX77620_IRQ_TOP_32K_MASK BIT(2) #define MAX77620_IRQ_TOP_32K_MASK BIT(2)
#define MAX77620_IRQ_TOP_RTC_MASK BIT(3) #define MAX77620_IRQ_TOP_RTC_MASK BIT(3)
@ -73,28 +82,53 @@
#define MAX77620_IRQ_TOP_GLBL_MASK BIT(7) #define MAX77620_IRQ_TOP_GLBL_MASK BIT(7)
#define MAX77620_REG_INTLBT 0x06 #define MAX77620_REG_INTLBT 0x06
#define MAX77620_REG_IRQTOPM 0x0D #define MAX77620_REG_INTENLBT 0x0E
#define MAX77620_IRQ_GLBLM_MASK BIT(0)
#define MAX77620_IRQ_TJALRM2_MASK BIT(1) #define MAX77620_IRQ_TJALRM2_MASK BIT(1)
#define MAX77620_IRQ_TJALRM1_MASK BIT(2) #define MAX77620_IRQ_TJALRM1_MASK BIT(2)
#define MAX77620_IRQ_LBM_MASK BIT(3) #define MAX77620_IRQ_LBM_MASK BIT(3)
#define MAX77620_REG_IRQSD 0x07 #define MAX77620_REG_IRQSD 0x07
#define MAX77620_REG_IRQ_LVL2_L0_7 0x08
#define MAX77620_REG_IRQ_LVL2_L8 0x09
#define MAX77620_REG_IRQ_LVL2_GPIO 0x0A
#define MAX77620_REG_ONOFFIRQ 0x0B
#define MAX77620_REG_NVERC 0x0C
#define MAX77620_REG_INTENLBT 0x0E
#define MAX77620_GLBLM_MASK BIT(0)
#define MAX77620_REG_IRQMASKSD 0x0F #define MAX77620_REG_IRQMASKSD 0x0F
#define MAX77620_IRQSD_PFI_SD3 BIT(4)
#define MAX77620_IRQSD_PFI_SD2 BIT(5)
#define MAX77620_IRQSD_PFI_SD1 BIT(6)
#define MAX77620_IRQSD_PFI_SD0 BIT(7)
#define MAX77620_REG_IRQ_LVL2_L0_7 0x08 // LDO number that irq occured.
#define MAX77620_REG_IRQ_MSK_L0_7 0x10 #define MAX77620_REG_IRQ_MSK_L0_7 0x10
#define MAX77620_REG_IRQ_LVL2_L8 0x09 // LDO number that irq occured. Only bit0: LDO8 is valid.
#define MAX77620_REG_IRQ_MSK_L8 0x11 #define MAX77620_REG_IRQ_MSK_L8 0x11
#define MAX77620_REG_IRQ_LVL2_GPIO 0x0A // Edge detection interrupt.
#define MAX77620_REG_ONOFFIRQ 0x0B
#define MAX77620_REG_ONOFFIRQM 0x12 #define MAX77620_REG_ONOFFIRQM 0x12
#define MAX77620_ONOFFIRQ_MRWRN BIT(0)
#define MAX77620_ONOFFIRQ_EN0_1SEC BIT(1)
#define MAX77620_ONOFFIRQ_EN0_F BIT(2)
#define MAX77620_ONOFFIRQ_EN0_R BIT(3)
#define MAX77620_ONOFFIRQ_LID_F BIT(4)
#define MAX77620_ONOFFIRQ_LID_R BIT(5)
#define MAX77620_ONOFFIRQ_ACOK_F BIT(6)
#define MAX77620_ONOFFIRQ_ACOK_R BIT(7)
#define MAX77620_REG_NVERC 0x0C // Shutdown reason (non-volatile).
#define MAX77620_NVERC_SHDN BIT(0)
#define MAX77620_NVERC_WTCHDG BIT(1)
#define MAX77620_NVERC_HDRST BIT(2)
#define MAX77620_NVERC_TOVLD BIT(3)
#define MAX77620_NVERC_MBLSD BIT(4)
#define MAX77620_NVERC_MBO BIT(5)
#define MAX77620_NVERC_MBU BIT(6)
#define MAX77620_NVERC_RSTIN BIT(7)
#define MAX77620_REG_STATLBT 0x13 #define MAX77620_REG_STATLBT 0x13
#define MAX77620_REG_STATSD 0x14 #define MAX77620_REG_STATSD 0x14
#define MAX77620_REG_ONOFFSTAT 0x15 #define MAX77620_REG_ONOFFSTAT 0x15
#define MAX77620_ONOFFSTAT_LID BIT(0)
#define MAX77620_ONOFFSTAT_ACOK BIT(1)
#define MAX77620_ONOFFSTAT_EN0 BIT(2)
/* SD and LDO Registers */ /* SD and LDO Registers */
#define MAX77620_REG_SD0 0x16 #define MAX77620_REG_SD0 0x16
@ -102,18 +136,42 @@
#define MAX77620_REG_SD2 0x18 #define MAX77620_REG_SD2 0x18
#define MAX77620_REG_SD3 0x19 #define MAX77620_REG_SD3 0x19
#define MAX77620_REG_SD4 0x1A #define MAX77620_REG_SD4 0x1A
#define MAX77620_REG_DVSSD0 0x1B
#define MAX77620_REG_DVSSD1 0x1C
#define MAX77620_SDX_VOLT_MASK 0xFF #define MAX77620_SDX_VOLT_MASK 0xFF
#define MAX77620_SD0_VOLT_MASK 0x3F #define MAX77620_SD0_VOLT_MASK 0x3F
#define MAX77620_SD1_VOLT_MASK 0x7F #define MAX77620_SD1_VOLT_MASK 0x7F
#define MAX77620_LDO_VOLT_MASK 0x3F #define MAX77620_LDO_VOLT_MASK 0x3F
#define MAX77620_REG_DVSSD0 0x1B
#define MAX77620_REG_DVSSD1 0x1C #define MAX77620_REG_SD0_CFG 0x1D
#define MAX77620_REG_SD0_CFG 0x1D // SD CNFG1. #define MAX77620_REG_SD1_CFG 0x1E
#define MAX77620_REG_SD1_CFG 0x1E // SD CNFG1. #define MAX77620_REG_SD2_CFG 0x1F
#define MAX77620_REG_SD2_CFG 0x1F // SD CNFG1. #define MAX77620_REG_SD3_CFG 0x20
#define MAX77620_REG_SD3_CFG 0x20 // SD CNFG1. #define MAX77620_REG_SD4_CFG 0x21
#define MAX77620_REG_SD4_CFG 0x21 // SD CNFG1. #define MAX77620_SD_SR_MASK 0xC0
#define MAX77620_SD_SR_SHIFT 6
#define MAX77620_SD_POWER_MODE_MASK 0x30
#define MAX77620_SD_POWER_MODE_SHIFT 4
#define MAX77620_SD_CFG1_ADE_MASK BIT(3)
#define MAX77620_SD_CFG1_ADE_DISABLE 0
#define MAX77620_SD_CFG1_ADE_ENABLE BIT(3)
#define MAX77620_SD_FPWM_MASK 0x04
#define MAX77620_SD_FPWM_SHIFT 2
#define MAX77620_SD_FSRADE_MASK 0x01
#define MAX77620_SD_FSRADE_SHIFT 0
#define MAX77620_SD_CFG1_FPWM_SD_MASK BIT(2)
#define MAX77620_SD_CFG1_FPWM_SD_SKIP 0
#define MAX77620_SD_CFG1_FPWM_SD_FPWM BIT(2)
#define MAX77620_SD_CFG1_MPOK_MASK BIT(1)
#define MAX77620_SD_CFG1_FSRADE_SD_MASK BIT(0)
#define MAX77620_SD_CFG1_FSRADE_SD_DISABLE 0
#define MAX77620_SD_CFG1_FSRADE_SD_ENABLE BIT(0)
#define MAX77620_REG_SD_CFG2 0x22 #define MAX77620_REG_SD_CFG2 0x22
#define MAX77620_SD_CNF2_RSVD BIT(0)
#define MAX77620_SD_CNF2_ROVS_EN_SD1 BIT(1)
#define MAX77620_SD_CNF2_ROVS_EN_SD0 BIT(2)
#define MAX77620_REG_LDO0_CFG 0x23 #define MAX77620_REG_LDO0_CFG 0x23
#define MAX77620_REG_LDO0_CFG2 0x24 #define MAX77620_REG_LDO0_CFG2 0x24
#define MAX77620_REG_LDO1_CFG 0x25 #define MAX77620_REG_LDO1_CFG 0x25
@ -132,26 +190,36 @@
#define MAX77620_REG_LDO7_CFG2 0x32 #define MAX77620_REG_LDO7_CFG2 0x32
#define MAX77620_REG_LDO8_CFG 0x33 #define MAX77620_REG_LDO8_CFG 0x33
#define MAX77620_REG_LDO8_CFG2 0x34 #define MAX77620_REG_LDO8_CFG2 0x34
#define MAX77620_LDO_CFG2_SS_MASK (1 << 0) /*! LDO CFG */
#define MAX77620_LDO_CFG2_SS_FAST (1 << 0)
#define MAX77620_LDO_CFG2_SS_SLOW 0
#define MAX77620_LDO_CFG2_ADE_MASK (1 << 1)
#define MAX77620_LDO_CFG2_ADE_DISABLE (0 << 1)
#define MAX77620_LDO_CFG2_ADE_ENABLE (1 << 1)
#define MAX20024_LDO_CFG2_MPOK_MASK BIT(2)
#define MAX77620_LDO_POWER_MODE_MASK 0xC0
#define MAX77620_LDO_POWER_MODE_SHIFT 6 #define MAX77620_LDO_POWER_MODE_SHIFT 6
#define MAX77620_LDO_POWER_MODE_MASK (3 << MAX77620_LDO_POWER_MODE_SHIFT)
#define MAX77620_POWER_MODE_NORMAL 3 #define MAX77620_POWER_MODE_NORMAL 3
#define MAX77620_POWER_MODE_LPM 2 #define MAX77620_POWER_MODE_LPM 2
#define MAX77620_POWER_MODE_GLPM 1 #define MAX77620_POWER_MODE_GLPM 1
#define MAX77620_POWER_MODE_DISABLE 0 #define MAX77620_POWER_MODE_DISABLE 0
/*! LDO CFG2 */
#define MAX77620_LDO_CFG2_SS_MASK (1 << 0)
#define MAX77620_LDO_CFG2_SS_FAST (0 << 0)
#define MAX77620_LDO_CFG2_SS_SLOW (1 << 0)
#define MAX77620_LDO_CFG2_ADE_MASK (1 << 1)
#define MAX77620_LDO_CFG2_ADE_DISABLE (0 << 1)
#define MAX77620_LDO_CFG2_ADE_ENABLE (1 << 1)
#define MAX77620_LDO_CFG2_MPOK_MASK BIT(2)
#define MAX77620_LDO_CFG2_POK_MASK BIT(3)
#define MAX77620_LDO_CFG2_COMP_SHIFT 4
#define MAX77620_LDO_CFG2_COMP_MASK (3 << MAX77620_LDO_COMP_SHIFT)
#define MAX77620_LDO_CFG2_COMP_SLOW 3
#define MAX77620_LDO_CFG2_COMP_MID_SLOW 2
#define MAX77620_LDO_CFG2_COMP_MID_FAST 1
#define MAX77620_LDO_CFG2_COMP_FAST 0
#define MAX77620_LDO_CFG2_ALPM_EN_MASK BIT(6)
#define MAX77620_LDO_CFG2_OVCLMP_MASK BIT(7)
#define MAX77620_REG_LDO_CFG3 0x35 #define MAX77620_REG_LDO_CFG3 0x35
#define MAX77620_LDO_BIAS_EN BIT(0)
#define MAX77620_TRACK4_SHIFT 5 #define MAX77620_TRACK4_SHIFT 5
#define MAX77620_TRACK4_MASK (1 << MAX77620_TRACK4_SHIFT) #define MAX77620_TRACK4_MASK (1 << MAX77620_TRACK4_SHIFT)
#define MAX77620_LDO_SLEW_RATE_MASK 0x1
#define MAX77620_REG_GPIO0 0x36 #define MAX77620_REG_GPIO0 0x36
#define MAX77620_REG_GPIO1 0x37 #define MAX77620_REG_GPIO1 0x37
#define MAX77620_REG_GPIO2 0x38 #define MAX77620_REG_GPIO2 0x38
@ -160,9 +228,6 @@
#define MAX77620_REG_GPIO5 0x3B #define MAX77620_REG_GPIO5 0x3B
#define MAX77620_REG_GPIO6 0x3C #define MAX77620_REG_GPIO6 0x3C
#define MAX77620_REG_GPIO7 0x3D #define MAX77620_REG_GPIO7 0x3D
#define MAX77620_REG_PUE_GPIO 0x3E
#define MAX77620_REG_PDE_GPIO 0x3F
#define MAX77620_REG_AME_GPIO 0x40
#define MAX77620_CNFG_GPIO_DRV_MASK (1 << 0) #define MAX77620_CNFG_GPIO_DRV_MASK (1 << 0)
#define MAX77620_CNFG_GPIO_DRV_PUSHPULL (1 << 0) #define MAX77620_CNFG_GPIO_DRV_PUSHPULL (1 << 0)
#define MAX77620_CNFG_GPIO_DRV_OPENDRAIN (0 << 0) #define MAX77620_CNFG_GPIO_DRV_OPENDRAIN (0 << 0)
@ -181,6 +246,13 @@
#define MAX77620_CNFG_GPIO_DBNC_8ms (0x1 << 6) #define MAX77620_CNFG_GPIO_DBNC_8ms (0x1 << 6)
#define MAX77620_CNFG_GPIO_DBNC_16ms (0x2 << 6) #define MAX77620_CNFG_GPIO_DBNC_16ms (0x2 << 6)
#define MAX77620_CNFG_GPIO_DBNC_32ms (0x3 << 6) #define MAX77620_CNFG_GPIO_DBNC_32ms (0x3 << 6)
#define MAX77620_GPIO_OUTPUT_DISABLE 0
#define MAX77620_GPIO_OUTPUT_ENABLE 1
#define MAX77620_REG_PUE_GPIO 0x3E // Gpio Pullup resistor enable.
#define MAX77620_REG_PDE_GPIO 0x3F // Gpio Pulldown resistor enable.
#define MAX77620_REG_AME_GPIO 0x40 // Gpio pinmuxing. Clear bits are Standard GPIO.
#define MAX77620_REG_ONOFFCNFG1 0x41 #define MAX77620_REG_ONOFFCNFG1 0x41
#define MAX20024_ONOFFCNFG1_CLRSE 0x18 #define MAX20024_ONOFFCNFG1_CLRSE 0x18
@ -188,19 +260,30 @@
#define MAX77620_ONOFFCNFG1_SLPEN BIT(2) #define MAX77620_ONOFFCNFG1_SLPEN BIT(2)
#define MAX77620_ONOFFCNFG1_MRT_SHIFT 0x3 #define MAX77620_ONOFFCNFG1_MRT_SHIFT 0x3
#define MAX77620_ONOFFCNFG1_MRT_MASK 0x38 #define MAX77620_ONOFFCNFG1_MRT_MASK 0x38
#define MAX77620_ONOFFCNFG1_RSVD BIT(6)
#define MAX77620_ONOFFCNFG1_SFT_RST BIT(7) #define MAX77620_ONOFFCNFG1_SFT_RST BIT(7)
#define MAX77620_REG_ONOFFCNFG2 0x42 #define MAX77620_REG_ONOFFCNFG2 0x42
#define MAX77620_ONOFFCNFG2_WK_EN0 BIT(0) #define MAX77620_ONOFFCNFG2_WK_EN0 BIT(0)
#define MAX77620_ONOFFCNFG2_WK_ALARM2 BIT(1)
#define MAX77620_ONOFFCNFG2_WK_ALARM1 BIT(2) #define MAX77620_ONOFFCNFG2_WK_ALARM1 BIT(2)
#define MAX77620_ONOFFCNFG2_WK_MBATT BIT(3) // MBATT event generates a wakeup signal. use it in android/l4t?
#define MAX77620_ONOFFCNFG2_WK_ACOK BIT(4)
#define MAX77620_ONOFFCNFG2_SLP_LPM_MSK BIT(5) #define MAX77620_ONOFFCNFG2_SLP_LPM_MSK BIT(5)
#define MAX77620_ONOFFCNFG2_WD_RST_WK BIT(6) #define MAX77620_ONOFFCNFG2_WD_RST_WK BIT(6)
#define MAX77620_ONOFFCNFG2_SFT_RST_WK BIT(7) #define MAX77620_ONOFFCNFG2_SFT_RST_WK BIT(7)
/* FPS Registers */ /* FPS Registers */
#define MAX77620_REG_FPS_CFG0 0x43 #define MAX77620_REG_FPS_CFG0 0x43 // FPS0.
#define MAX77620_REG_FPS_CFG1 0x44 #define MAX77620_REG_FPS_CFG1 0x44 // FPS1.
#define MAX77620_REG_FPS_CFG2 0x45 #define MAX77620_REG_FPS_CFG2 0x45 // FPS2.
#define MAX77620_FPS_ENFPS_SW_MASK 0x01
#define MAX77620_FPS_ENFPS_SW 0x01
#define MAX77620_FPS_EN_SRC_SHIFT 1
#define MAX77620_FPS_EN_SRC_MASK 0x06
#define MAX77620_FPS_TIME_PERIOD_SHIFT 3
#define MAX77620_FPS_TIME_PERIOD_MASK 0x38
#define MAX77620_REG_FPS_LDO0 0x46 #define MAX77620_REG_FPS_LDO0 0x46
#define MAX77620_REG_FPS_LDO1 0x47 #define MAX77620_REG_FPS_LDO1 0x47
#define MAX77620_REG_FPS_LDO2 0x48 #define MAX77620_REG_FPS_LDO2 0x48
@ -215,77 +298,39 @@
#define MAX77620_REG_FPS_SD2 0x51 #define MAX77620_REG_FPS_SD2 0x51
#define MAX77620_REG_FPS_SD3 0x52 #define MAX77620_REG_FPS_SD3 0x52
#define MAX77620_REG_FPS_SD4 0x53 #define MAX77620_REG_FPS_SD4 0x53
#define MAX77620_REG_FPS_NONE 0
#define MAX77620_FPS_SRC_MASK 0xC0
#define MAX77620_FPS_SRC_SHIFT 6
#define MAX77620_FPS_PU_PERIOD_MASK 0x38
#define MAX77620_FPS_PU_PERIOD_SHIFT 3
#define MAX77620_FPS_PD_PERIOD_MASK 0x07
#define MAX77620_FPS_PD_PERIOD_SHIFT 0
/* Minimum and maximum FPS period time (in microseconds) are
* different for MAX77620 and Max20024.
*/
#define MAX77620_FPS_COUNT 3
#define MAX77620_FPS_PERIOD_MIN_US 40
#define MAX20024_FPS_PERIOD_MIN_US 20
#define MAX77620_FPS_PERIOD_MAX_US 2560
#define MAX20024_FPS_PERIOD_MAX_US 5120
#define MAX77620_REG_FPS_GPIO1 0x54 #define MAX77620_REG_FPS_GPIO1 0x54
#define MAX77620_REG_FPS_GPIO2 0x55 #define MAX77620_REG_FPS_GPIO2 0x55
#define MAX77620_REG_FPS_GPIO3 0x56 #define MAX77620_REG_FPS_GPIO3 0x56
#define MAX77620_FPS_TIME_PERIOD_MASK 0x38
#define MAX77620_FPS_TIME_PERIOD_SHIFT 3
#define MAX77620_FPS_EN_SRC_MASK 0x06
#define MAX77620_FPS_EN_SRC_SHIFT 1
#define MAX77620_FPS_ENFPS_SW_MASK 0x01
#define MAX77620_FPS_ENFPS_SW 0x01
#define MAX77620_REG_FPS_RSO 0x57 #define MAX77620_REG_FPS_RSO 0x57
#define MAX77620_FPS_PD_PERIOD_SHIFT 0
#define MAX77620_FPS_PD_PERIOD_MASK 0x07
#define MAX77620_FPS_PU_PERIOD_SHIFT 3
#define MAX77620_FPS_PU_PERIOD_MASK 0x38
#define MAX77620_FPS_SRC_SHIFT 6
#define MAX77620_FPS_SRC_MASK 0xC0
#define MAX77620_FPS_COUNT 3
#define MAX77620_FPS_PERIOD_MIN_US 40
#define MAX77620_FPS_PERIOD_MAX_US 2560
#define MAX77620_REG_CID0 0x58 #define MAX77620_REG_CID0 0x58
#define MAX77620_REG_CID1 0x59 #define MAX77620_REG_CID1 0x59
#define MAX77620_REG_CID2 0x5A #define MAX77620_REG_CID2 0x5A
#define MAX77620_REG_CID3 0x5B #define MAX77620_REG_CID3 0x5B
#define MAX77620_REG_CID4 0x5C #define MAX77620_REG_CID4 0x5C // OTP version.
#define MAX77620_REG_CID5 0x5D #define MAX77620_REG_CID5 0x5D
#define MAX77620_CID_DIDO_MASK 0xF
#define MAX77620_REG_DVSSD4 0x5E #define MAX77620_CID_DIDO_SHIFT 0
#define MAX20024_REG_MAX_ADD 0x70 #define MAX77620_CID_DIDM_MASK 0xF0
#define MAX77620_CID_DIDM_SHIFT 4
#define MAX77620_CID_DIDM_MASK 0xF0
#define MAX77620_CID_DIDM_SHIFT 4
/* CNCG2SD */
#define MAX77620_SD_CNF2_ROVS_EN_SD1 BIT(1)
#define MAX77620_SD_CNF2_ROVS_EN_SD0 BIT(2)
/* Device Identification Metal */ /* Device Identification Metal */
#define MAX77620_CID5_DIDM(n) (((n) >> 4) & 0xF) #define MAX77620_CID5_DIDM(n) (((n) >> 4) & 0xF)
/* Device Indentification OTP */ /* Device Indentification OTP */
#define MAX77620_CID5_DIDO(n) ((n) & 0xF) #define MAX77620_CID5_DIDO(n) ((n) & 0xF)
/* SD CNFG1 */ #define MAX77620_REG_DVSSD4 0x5E
#define MAX77620_SD_SR_MASK 0xC0 #define MAX20024_REG_MAX_ADD 0x70
#define MAX77620_SD_SR_SHIFT 6
#define MAX77620_SD_POWER_MODE_MASK 0x30
#define MAX77620_SD_POWER_MODE_SHIFT 4
#define MAX77620_SD_CFG1_ADE_MASK BIT(3)
#define MAX77620_SD_CFG1_ADE_DISABLE 0
#define MAX77620_SD_CFG1_ADE_ENABLE BIT(3)
#define MAX77620_SD_FPWM_MASK 0x04
#define MAX77620_SD_FPWM_SHIFT 2
#define MAX77620_SD_FSRADE_MASK 0x01
#define MAX77620_SD_FSRADE_SHIFT 0
#define MAX77620_SD_CFG1_FPWM_SD_MASK BIT(2)
#define MAX77620_SD_CFG1_FPWM_SD_SKIP 0
#define MAX77620_SD_CFG1_FPWM_SD_FPWM BIT(2)
#define MAX20024_SD_CFG1_MPOK_MASK BIT(1)
#define MAX77620_SD_CFG1_FSRADE_SD_MASK BIT(0)
#define MAX77620_SD_CFG1_FSRADE_SD_DISABLE 0
#define MAX77620_SD_CFG1_FSRADE_SD_ENABLE BIT(0)
#define MAX77620_IRQ_LVL2_GPIO_EDGE0 BIT(0) #define MAX77620_IRQ_LVL2_GPIO_EDGE0 BIT(0)
#define MAX77620_IRQ_LVL2_GPIO_EDGE1 BIT(1) #define MAX77620_IRQ_LVL2_GPIO_EDGE1 BIT(1)
@ -332,9 +377,4 @@ enum max77620_fps_src {
MAX77620_FPS_SRC_DEF, MAX77620_FPS_SRC_DEF,
}; };
enum max77620_chip_id {
MAX77620,
MAX20024,
};
#endif /* _MFD_MAX77620_H_ */ #endif /* _MFD_MAX77620_H_ */

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2019 CTCaer * Copyright (c) 2019-2020 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * 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,163 +17,323 @@
#include <power/max7762x.h> #include <power/max7762x.h>
#include <power/max77620.h> #include <power/max77620.h>
#include <power/max77812.h>
#include <soc/fuse.h>
#include <soc/i2c.h> #include <soc/i2c.h>
#include <soc/t210.h>
#include <utils/util.h> #include <utils/util.h>
#define REGULATOR_SD 0 #define REGULATOR_SD 0
#define REGULATOR_LDO 1 #define REGULATOR_LDO 1
#define REGULATOR_BC0 2
#define REGULATOR_BC1 3
typedef struct _max77620_regulator_t typedef struct _max77620_fps_t
{ {
u8 type;
const char *name;
u8 reg_sd;
u32 mv_step;
u32 mv_min;
u32 mv_default;
u32 mv_max;
u8 volt_addr;
u8 cfg_addr;
u8 volt_mask;
u8 enable_mask;
u8 enable_shift;
u8 status_mask;
u8 fps_addr; u8 fps_addr;
u8 fps_src; u8 fps_src;
u8 pd_period; u8 pd_period;
u8 pu_period; u8 pu_period;
} max77620_fps_t;
typedef struct _max77621_ctrl_t
{
u8 ctrl1_por;
u8 ctrl1_hos;
u8 ctrl2_por;
u8 ctrl2_hos;
} max77621_ctrl_t;
typedef struct _max77812_ctrl_t
{
u8 mask;
u8 shift;
u8 rsvd0;
u8 rsvd1;
} max77812_en_t;
typedef struct _max77620_regulator_t
{
const char *name;
u32 uv_step;
u32 uv_min;
u32 uv_default;
u32 uv_max;
u8 type;
u8 volt_addr;
u8 cfg_addr;
u8 volt_mask;
union {
max77620_fps_t fps;
max77621_ctrl_t ctrl;
max77812_en_t enable;
};
} max77620_regulator_t; } max77620_regulator_t;
static const max77620_regulator_t _pmic_regulators[] = { static const max77620_regulator_t _pmic_regulators[] = {
{ REGULATOR_SD, "sd0", 0x16, 12500, 600000, 625000, 1400000, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, MAX77620_SD0_VOLT_MASK, MAX77620_SD_POWER_MODE_MASK, MAX77620_SD_POWER_MODE_SHIFT, 0x80, MAX77620_REG_FPS_SD0, 1, 7, 1 }, { "sd0", 12500, 600000, 625000, 1400000, REGULATOR_SD, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, MAX77620_SD0_VOLT_MASK, {{ MAX77620_REG_FPS_SD0, 1, 7, 1 }} },
{ REGULATOR_SD, "sd1", 0x17, 12500, 600000, 1125000, 1125000, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, MAX77620_SD1_VOLT_MASK, MAX77620_SD_POWER_MODE_MASK, MAX77620_SD_POWER_MODE_SHIFT, 0x40, MAX77620_REG_FPS_SD1, 0, 1, 5 }, { "sd1", 12500, 600000, 1125000, 1250000, REGULATOR_SD, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, MAX77620_SD1_VOLT_MASK, {{ MAX77620_REG_FPS_SD1, 0, 1, 5 }} },
{ REGULATOR_SD, "sd2", 0x18, 12500, 600000, 1325000, 1350000, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, MAX77620_SDX_VOLT_MASK, MAX77620_SD_POWER_MODE_MASK, MAX77620_SD_POWER_MODE_SHIFT, 0x20, MAX77620_REG_FPS_SD2, 1, 5, 2 }, { "sd2", 12500, 600000, 1325000, 1350000, REGULATOR_SD, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD2, 1, 5, 2 }} },
{ REGULATOR_SD, "sd3", 0x19, 12500, 600000, 1800000, 1800000, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, MAX77620_SDX_VOLT_MASK, MAX77620_SD_POWER_MODE_MASK, MAX77620_SD_POWER_MODE_SHIFT, 0x10, MAX77620_REG_FPS_SD3, 0, 3, 3 }, { "sd3", 12500, 600000, 1800000, 1800000, REGULATOR_SD, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD3, 0, 3, 3 }} },
{ REGULATOR_LDO, "ldo0", 0x00, 25000, 800000, 1200000, 1200000, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO0, 3, 7, 0 }, { "ldo0", 25000, 800000, 1200000, 1200000, REGULATOR_LDO, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO0, 3, 7, 0 }} },
{ REGULATOR_LDO, "ldo1", 0x00, 25000, 800000, 1050000, 1050000, MAX77620_REG_LDO1_CFG, MAX77620_REG_LDO1_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO1, 3, 7, 0 }, { "ldo1", 25000, 800000, 1050000, 1050000, REGULATOR_LDO, MAX77620_REG_LDO1_CFG, MAX77620_REG_LDO1_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO1, 3, 7, 0 }} },
{ REGULATOR_LDO, "ldo2", 0x00, 50000, 800000, 1800000, 3300000, MAX77620_REG_LDO2_CFG, MAX77620_REG_LDO2_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO2, 3, 7, 0 }, { "ldo2", 50000, 800000, 1800000, 3300000, REGULATOR_LDO, MAX77620_REG_LDO2_CFG, MAX77620_REG_LDO2_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO2, 3, 7, 0 }} },
{ REGULATOR_LDO, "ldo3", 0x00, 50000, 800000, 3100000, 3100000, MAX77620_REG_LDO3_CFG, MAX77620_REG_LDO3_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO3, 3, 7, 0 }, { "ldo3", 50000, 800000, 3100000, 3100000, REGULATOR_LDO, MAX77620_REG_LDO3_CFG, MAX77620_REG_LDO3_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO3, 3, 7, 0 }} },
{ REGULATOR_LDO, "ldo4", 0x00, 12500, 800000, 850000, 850000, MAX77620_REG_LDO4_CFG, MAX77620_REG_LDO4_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO4, 0, 7, 1 }, { "ldo4", 12500, 800000, 850000, 1000000, REGULATOR_LDO, MAX77620_REG_LDO4_CFG, MAX77620_REG_LDO4_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO4, 0, 7, 1 }} },
{ REGULATOR_LDO, "ldo5", 0x00, 50000, 800000, 1800000, 1800000, MAX77620_REG_LDO5_CFG, MAX77620_REG_LDO5_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO5, 3, 7, 0 }, { "ldo5", 50000, 800000, 1800000, 1800000, REGULATOR_LDO, MAX77620_REG_LDO5_CFG, MAX77620_REG_LDO5_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO5, 3, 7, 0 }} },
{ REGULATOR_LDO, "ldo6", 0x00, 50000, 800000, 2900000, 2900000, MAX77620_REG_LDO6_CFG, MAX77620_REG_LDO6_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO6, 3, 7, 0 }, { "ldo6", 50000, 800000, 2900000, 2900000, REGULATOR_LDO, MAX77620_REG_LDO6_CFG, MAX77620_REG_LDO6_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO6, 3, 7, 0 }} },
{ REGULATOR_LDO, "ldo7", 0x00, 50000, 800000, 1050000, 1050000, MAX77620_REG_LDO7_CFG, MAX77620_REG_LDO7_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO7, 1, 4, 3 }, { "ldo7", 50000, 800000, 1050000, 1050000, REGULATOR_LDO, MAX77620_REG_LDO7_CFG, MAX77620_REG_LDO7_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO7, 1, 4, 3 }} },
{ REGULATOR_LDO, "ldo8", 0x00, 50000, 800000, 1050000, 2800000, MAX77620_REG_LDO8_CFG, MAX77620_REG_LDO8_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO8, 3, 7, 0 } { "ldo8", 50000, 800000, 1050000, 2800000, REGULATOR_LDO, MAX77620_REG_LDO8_CFG, MAX77620_REG_LDO8_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO8, 3, 7, 0 }} },
{ "max77621_CPU", 6250, 606250, 1000000, 1400000, REGULATOR_BC0, MAX77621_VOUT_REG, MAX77621_VOUT_DVS_REG, MAX77621_DVC_DVS_VOLT_MASK, {{ MAX77621_CPU_CTRL1_POR_DEFAULT, MAX77621_CPU_CTRL1_HOS_DEFAULT, MAX77621_CPU_CTRL2_POR_DEFAULT, MAX77621_CPU_CTRL2_HOS_DEFAULT }} },
{ "max77621_GPU", 6250, 606250, 1200000, 1400000, REGULATOR_BC0, MAX77621_VOUT_REG, MAX77621_VOUT_DVS_REG, MAX77621_DVC_DVS_VOLT_MASK, {{ MAX77621_CPU_CTRL1_POR_DEFAULT, MAX77621_CPU_CTRL1_HOS_DEFAULT, MAX77621_CPU_CTRL2_POR_DEFAULT, MAX77621_CPU_CTRL2_HOS_DEFAULT }} },
{ "max77812_CPU", 5000, 250000, 600000, 1525000, REGULATOR_BC1, MAX77812_REG_M4_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M4_MASK, MAX77812_EN_CTRL_EN_M4_SHIFT, 0, 0 }} },
//{ "max77812_GPU", 5000, 250000, 600000, 1525000, REGULATOR_BC1, MAX77812_REG_M1_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M1_MASK, MAX77812_EN_CTRL_EN_M1_SHIFT, 0, 0 }} },
//{ "max77812_RAM", 5000, 250000, 600000, 1525000, REGULATOR_BC1, MAX77812_REG_M3_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M3_MASK, MAX77812_EN_CTRL_EN_M3_SHIFT, 0, 0 }} } // Only on PHASE211 configuration.
}; };
static void _max77620_set_reg(u8 reg, u8 val) static u8 _max77812_get_address()
{
static u8 max77812_i2c_addr = 0;
if (max77812_i2c_addr)
return max77812_i2c_addr;
max77812_i2c_addr =
!(FUSE(FUSE_RESERVED_ODM28_T210B01) & 1) ? MAX77812_PHASE31_CPU_I2C_ADDR : MAX77812_PHASE211_CPU_I2C_ADDR;
return max77812_i2c_addr;
}
static u8 _max7762x_get_i2c_address(u32 id)
{
const max77620_regulator_t *reg = &_pmic_regulators[id];
// Choose the correct i2c address.
switch (reg->type)
{
case REGULATOR_SD:
case REGULATOR_LDO:
return MAX77620_I2C_ADDR;
case REGULATOR_BC0:
return (id == REGULATOR_CPU0 ? MAX77621_CPU_I2C_ADDR : MAX77621_GPU_I2C_ADDR);
case REGULATOR_BC1:
return _max77812_get_address();
default:
return 0;
}
}
static void _max7762x_set_reg(u8 addr, u8 reg, u8 val)
{ {
u32 retries = 100; u32 retries = 100;
while (retries) while (retries)
{ {
if (i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, reg, val)) if (i2c_send_byte(I2C_5, addr, reg, val))
break; break;
usleep(100);
usleep(50);
retries--; retries--;
} }
} }
int max77620_regulator_get_status(u32 id) int max77620_regulator_get_status(u32 id)
{ {
if (id > REGULATOR_MAX) if (id > REGULATOR_LDO8)
return 0; return 0;
const max77620_regulator_t *reg = &_pmic_regulators[id]; const max77620_regulator_t *reg = &_pmic_regulators[id];
// SD power OK status.
if (reg->type == REGULATOR_SD) if (reg->type == REGULATOR_SD)
return (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_STATSD) & reg->status_mask) ? 0 : 1; {
return (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, reg->cfg_addr) & 8) ? 1 : 0; u8 mask = 1u << (7 - id);
return (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_STATSD) & mask) ? 0 : 1;
}
// LDO power OK status.
return (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, reg->cfg_addr) & MAX77620_LDO_CFG2_POK_MASK) ? 1 : 0;
} }
int max77620_regulator_config_fps(u32 id) int max77620_regulator_config_fps(u32 id)
{ {
if (id > REGULATOR_MAX) if (id > REGULATOR_LDO8)
return 0; return 0;
const max77620_regulator_t *reg = &_pmic_regulators[id]; const max77620_regulator_t *reg = &_pmic_regulators[id];
_max77620_set_reg(reg->fps_addr, // Set FPS configuration.
(reg->fps_src << MAX77620_FPS_SRC_SHIFT) | (reg->pu_period << MAX77620_FPS_PU_PERIOD_SHIFT) | (reg->pd_period)); _max7762x_set_reg(MAX77620_I2C_ADDR,
reg->fps.fps_addr,
(reg->fps.fps_src << MAX77620_FPS_SRC_SHIFT) |
(reg->fps.pu_period << MAX77620_FPS_PU_PERIOD_SHIFT) |
(reg->fps.pd_period << MAX77620_FPS_PD_PERIOD_SHIFT));
return 1; return 1;
} }
int max77620_regulator_set_voltage(u32 id, u32 mv) int max7762x_regulator_set_voltage(u32 id, u32 mv)
{ {
if (id > REGULATOR_MAX) if (id > REGULATOR_MAX)
return 0; return 0;
const max77620_regulator_t *reg = &_pmic_regulators[id]; const max77620_regulator_t *reg = &_pmic_regulators[id];
if (mv < reg->mv_min || mv > reg->mv_max) if (mv < reg->uv_min || mv > reg->uv_max)
return 0; return 0;
u32 mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step; u8 addr = _max7762x_get_i2c_address(id);
u8 val = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, reg->volt_addr);
// Calculate voltage multiplier.
u32 mult = (mv + reg->uv_step - 1 - reg->uv_min) / reg->uv_step;
u8 val = i2c_recv_byte(I2C_5, addr, reg->volt_addr);
val = (val & ~reg->volt_mask) | (mult & reg->volt_mask); val = (val & ~reg->volt_mask) | (mult & reg->volt_mask);
_max77620_set_reg(reg->volt_addr, val);
// Set voltage.
_max7762x_set_reg(addr, reg->volt_addr, val);
// If max77621 set DVS voltage also.
if (reg->type == REGULATOR_BC0)
_max7762x_set_reg(addr, reg->cfg_addr, MAX77621_VOUT_ENABLE_MASK | val);
// Wait for ramp up/down delay.
usleep(1000); usleep(1000);
return 1; return 1;
} }
int max77620_regulator_enable(u32 id, int enable) int max7762x_regulator_enable(u32 id, bool enable)
{ {
u8 reg_addr;
u8 enable_val;
u8 enable_mask;
u8 enable_shift;
if (id > REGULATOR_MAX) if (id > REGULATOR_MAX)
return 0; return 0;
const max77620_regulator_t *reg = &_pmic_regulators[id]; const max77620_regulator_t *reg = &_pmic_regulators[id];
u32 addr = reg->type == REGULATOR_SD ? reg->cfg_addr : reg->volt_addr; // Choose the correct i2c and register addresses and mask/shift for each type.
u8 val = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, addr); switch (reg->type)
{
case REGULATOR_SD:
reg_addr = reg->cfg_addr;
enable_val = MAX77620_POWER_MODE_NORMAL;
enable_mask = MAX77620_SD_POWER_MODE_MASK;
enable_shift = MAX77620_SD_POWER_MODE_SHIFT;
break;
case REGULATOR_LDO:
reg_addr = reg->volt_addr;
enable_val = MAX77620_POWER_MODE_NORMAL;
enable_mask = MAX77620_LDO_POWER_MODE_MASK;
enable_shift = MAX77620_LDO_POWER_MODE_SHIFT;
break;
case REGULATOR_BC0:
reg_addr = reg->volt_addr;
enable_val = MAX77621_VOUT_ENABLE;
enable_mask = MAX77621_DVC_DVS_ENABLE_MASK;
enable_shift = MAX77621_DVC_DVS_ENABLE_SHIFT;
break;
case REGULATOR_BC1:
reg_addr = reg->cfg_addr;
enable_val = MAX77812_EN_CTRL_ENABLE;
enable_mask = reg->enable.mask;
enable_shift = reg->enable.shift;
break;
default:
return 0;
}
u8 addr = _max7762x_get_i2c_address(id);
// Read and enable/disable.
u8 val = i2c_recv_byte(I2C_5, addr, reg_addr);
val &= ~enable_mask;
if (enable) if (enable)
val = (val & ~reg->enable_mask) | ((MAX77620_POWER_MODE_NORMAL << reg->enable_shift) & reg->enable_mask); val |= (enable_val << enable_shift);
else
val &= ~reg->enable_mask; // Set enable.
_max77620_set_reg(addr, val); _max7762x_set_reg(addr, reg_addr, val);
// Wait for enable/disable ramp delay.
usleep(1000); usleep(1000);
return 1; return 1;
} }
// LDO only. void max77620_config_gpio(u32 gpio_id, bool enable)
int max77620_regulator_set_volt_and_flags(u32 id, u32 mv, u8 flags)
{ {
if (id > REGULATOR_MAX) if (gpio_id > 7)
return 0; return;
// Configure as standard GPIO.
u8 val = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO);
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO, val & ~BIT(gpio_id));
// Set GPIO configuration.
if (enable)
val = MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH | MAX77620_CNFG_GPIO_DIR_OUTPUT | MAX77620_CNFG_GPIO_DRV_PUSHPULL;
else
val = MAX77620_CNFG_GPIO_DIR_INPUT | MAX77620_CNFG_GPIO_DRV_OPENDRAIN;
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO0 + gpio_id, val);
}
void max77621_config_default(u32 id, bool por)
{
const max77620_regulator_t *reg = &_pmic_regulators[id]; const max77620_regulator_t *reg = &_pmic_regulators[id];
if (mv < reg->mv_min || mv > reg->mv_max) if (reg->type != REGULATOR_BC0)
return 0; return;
u32 mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step; u8 addr = _max7762x_get_i2c_address(id);
u8 val = ((flags << reg->enable_shift) & ~reg->volt_mask) | (mult & reg->volt_mask);
_max77620_set_reg(reg->volt_addr, val);
usleep(1000);
return 1; if (por)
{
// Set voltage and disable power before changing the inductor.
max7762x_regulator_set_voltage(id, 1000000);
max7762x_regulator_enable(id, false);
// Configure to default.
i2c_send_byte(I2C_5, addr, MAX77621_CONTROL1_REG, reg->ctrl.ctrl1_por);
i2c_send_byte(I2C_5, addr, MAX77621_CONTROL2_REG, reg->ctrl.ctrl2_por);
}
else
{
i2c_send_byte(I2C_5, addr, MAX77621_CONTROL1_REG, reg->ctrl.ctrl1_hos);
i2c_send_byte(I2C_5, addr, MAX77621_CONTROL2_REG, reg->ctrl.ctrl2_hos);
}
} }
void max77620_config_default() void max77620_config_default()
{ {
for (u32 i = 1; i <= REGULATOR_MAX; i++) // Check if Erista OTP.
if (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CID4) != 0x35)
return;
// Set default voltages and enable regulators.
for (u32 i = 1; i <= REGULATOR_LDO8; i++)
{ {
i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CID4);
max77620_regulator_config_fps(i); max77620_regulator_config_fps(i);
max77620_regulator_set_voltage(i, _pmic_regulators[i].mv_default); max7762x_regulator_set_voltage(i, _pmic_regulators[i].uv_default);
if (_pmic_regulators[i].fps_src != MAX77620_FPS_SRC_NONE) if (_pmic_regulators[i].fps.fps_src != MAX77620_FPS_SRC_NONE)
max77620_regulator_enable(i, 1); max7762x_regulator_enable(i, true);
} }
_max77620_set_reg(MAX77620_REG_SD_CFG2, 4);
// Enable SD0 output voltage sense and disable for SD1. Additionally disable the reserved bit.
_max7762x_set_reg(MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, MAX77620_SD_CNF2_ROVS_EN_SD0);
} }
// Stock HOS: disabled.
void max77620_low_battery_monitor_config(bool enable) void max77620_low_battery_monitor_config(bool enable)
{ {
_max77620_set_reg(MAX77620_REG_CNFGGLBL1, _max7762x_set_reg(MAX77620_I2C_ADDR, MAX77620_REG_CNFGGLBL1,
MAX77620_CNFGGLBL1_LBDAC_EN | (enable ? MAX77620_CNFGGLBL1_MPPLD : 0) | MAX77620_CNFGGLBL1_LBDAC_EN |
MAX77620_CNFGGLBL1_LBHYST_200 | MAX77620_CNFGGLBL1_LBDAC_2800); (enable ? MAX77620_CNFGGLBL1_MPPLD : 0) |
MAX77620_CNFGGLBL1_LBHYST_200 |
MAX77620_CNFGGLBL1_LBDAC_2800);
} }

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2019 CTCaer * Copyright (c) 2019-2020 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,11 +32,11 @@
* ldo1 | XUSB, PCIE | 25000 | 800000 | 1050000 | 1050000 | 1.05V (pcv) * ldo1 | XUSB, PCIE | 25000 | 800000 | 1050000 | 1050000 | 1.05V (pcv)
* ldo2 | SDMMC1 | 50000 | 800000 | 1800000 | 3300000 | * ldo2 | SDMMC1 | 50000 | 800000 | 1800000 | 3300000 |
* ldo3 | GC ASIC | 50000 | 800000 | 3100000 | 3100000 | 3.1V (pcv) * ldo3 | GC ASIC | 50000 | 800000 | 3100000 | 3100000 | 3.1V (pcv)
* ldo4 | RTC | 12500 | 800000 | 850000 | 850000 | * ldo4 | RTC | 12500 | 800000 | 850000 | 850000 | 0.85V (AO, pcv)
* ldo5 | GC Card | 50000 | 800000 | 1800000 | 1800000 | 1.8V (pcv) * ldo5 | GC Card | 50000 | 800000 | 1800000 | 1800000 | 1.8V (pcv)
* ldo6 | Touch, ALS | 50000 | 800000 | 2900000 | 2900000 | 2.9V * ldo6 | Touch, ALS | 50000 | 800000 | 2900000 | 2900000 | 2.9V (pcv)
* ldo7 | XUSB | 50000 | 800000 | 1050000 | 1050000 | * ldo7 | XUSB | 50000 | 800000 | 1050000 | 1050000 | 1.05V (pcv)
* ldo8 | XUSB, DC | 50000 | 800000 | 1050000 | 1050000 | * ldo8 | XUSB, DP, MCU | 50000 | 800000 | 1050000 | 2800000 | 1.05V/2.8V (pcv)
*/ */
/* /*
@ -45,10 +45,10 @@
*/ */
/*! MAX77620 partitions. */ /*! MAX77620 partitions. */
#define REGULATOR_SD0 0 #define REGULATOR_SD0 0
#define REGULATOR_SD1 1 #define REGULATOR_SD1 1
#define REGULATOR_SD2 2 #define REGULATOR_SD2 2
#define REGULATOR_SD3 3 #define REGULATOR_SD3 3
#define REGULATOR_LDO0 4 #define REGULATOR_LDO0 4
#define REGULATOR_LDO1 5 #define REGULATOR_LDO1 5
#define REGULATOR_LDO2 6 #define REGULATOR_LDO2 6
@ -58,26 +58,40 @@
#define REGULATOR_LDO6 10 #define REGULATOR_LDO6 10
#define REGULATOR_LDO7 11 #define REGULATOR_LDO7 11
#define REGULATOR_LDO8 12 #define REGULATOR_LDO8 12
#define REGULATOR_MAX 12 #define REGULATOR_CPU0 13
#define REGULATOR_GPU0 14
#define REGULATOR_CPU1 15
//#define REGULATOR_GPU1 16
//#define REGULATOR_GPU1 17
#define REGULATOR_MAX 15
#define MAX77621_CPU_I2C_ADDR 0x1B #define MAX77621_CPU_I2C_ADDR 0x1B
#define MAX77621_GPU_I2C_ADDR 0x1C #define MAX77621_GPU_I2C_ADDR 0x1C
#define MAX77621_VOUT_REG 0 #define MAX77621_VOUT_REG 0x00
#define MAX77621_VOUT_DVS_REG 1 #define MAX77621_VOUT_DVS_REG 0x01
#define MAX77621_CONTROL1_REG 2 #define MAX77621_CONTROL1_REG 0x02
#define MAX77621_CONTROL2_REG 3 #define MAX77621_CONTROL2_REG 0x03
#define MAX77621_CHIPID1_REG 0x04
/* MAX77621_VOUT */ #define MAX77621_CHIPID2_REG 0x05
#define MAX77621_VOUT_ENABLE BIT(7)
#define MAX77621_VOUT_MASK 0x7F
#define MAX77621_VOUT_0_95V 0x37
#define MAX77621_VOUT_1_09V 0x4F
/* MAX77621_VOUT_DVC_DVS */ /* MAX77621_VOUT_DVC_DVS */
#define MAX77621_DVS_VOUT_MASK 0x7F #define MAX77621_DVC_DVS_VOLT_MASK 0x7F
#define MAX77621_DVC_DVS_ENABLE_SHIFT 7
#define MAX77621_DVC_DVS_ENABLE_MASK (1 << MAX77621_DVC_DVS_ENABLE_SHIFT)
/* MAX77621_VOUT */
#define MAX77621_VOUT_DISABLE 0
#define MAX77621_VOUT_ENABLE 1
#define MAX77621_VOUT_ENABLE_MASK (MAX77621_VOUT_ENABLE << MAX77621_DVC_DVS_ENABLE_SHIFT)
/* MAX77621_CONTROL1 */ /* MAX77621_CONTROL1 */
#define MAX77621_RAMP_12mV_PER_US 0x0
#define MAX77621_RAMP_25mV_PER_US 0x1
#define MAX77621_RAMP_50mV_PER_US 0x2
#define MAX77621_RAMP_200mV_PER_US 0x3
#define MAX77621_RAMP_MASK 0x3
#define MAX77621_FREQSHIFT_9PER BIT(2) #define MAX77621_FREQSHIFT_9PER BIT(2)
#define MAX77621_BIAS_ENABLE BIT(3) #define MAX77621_BIAS_ENABLE BIT(3)
#define MAX77621_AD_ENABLE BIT(4) #define MAX77621_AD_ENABLE BIT(4)
@ -85,34 +99,50 @@
#define MAX77621_FPWM_EN_M BIT(6) #define MAX77621_FPWM_EN_M BIT(6)
#define MAX77621_SNS_ENABLE BIT(7) #define MAX77621_SNS_ENABLE BIT(7)
#define MAX77621_RAMP_12mV_PER_US 0x0
#define MAX77621_RAMP_25mV_PER_US 0x1
#define MAX77621_RAMP_50mV_PER_US 0x2
#define MAX77621_RAMP_200mV_PER_US 0x3
#define MAX77621_RAMP_MASK 0x3
/* MAX77621_CONTROL2 */ /* MAX77621_CONTROL2 */
#define MAX77621_FT_ENABLE BIT(4) #define MAX77621_INDUCTOR_MIN_30_PER 0
#define MAX77621_DISCH_ENBABLE BIT(5) #define MAX77621_INDUCTOR_NOMINAL 1
#define MAX77621_WDTMR_ENABLE BIT(6) #define MAX77621_INDUCTOR_PLUS_30_PER 2
#define MAX77621_T_JUNCTION_120 BIT(7) #define MAX77621_INDUCTOR_PLUS_60_PER 3
#define MAX77621_INDUCTOR_MASK 3
#define MAX77621_CKKADV_TRIP_DISABLE 0xC
#define MAX77621_CKKADV_TRIP_75mV_PER_US 0x0 #define MAX77621_CKKADV_TRIP_75mV_PER_US 0x0
#define MAX77621_CKKADV_TRIP_150mV_PER_US 0x4 #define MAX77621_CKKADV_TRIP_150mV_PER_US BIT(2)
#define MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS 0x8 #define MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS BIT(3)
#define MAX77621_CKKADV_TRIP_DISABLE (BIT(2) | BIT(3))
#define MAX77621_CKKADV_TRIP_MASK (BIT(2) | BIT(3))
#define MAX77621_INDUCTOR_MIN_30_PER 0x0 #define MAX77621_FT_ENABLE BIT(4)
#define MAX77621_INDUCTOR_NOMINAL 0x1 #define MAX77621_DISCH_ENABLE BIT(5)
#define MAX77621_INDUCTOR_PLUS_30_PER 0x2 #define MAX77621_WDTMR_ENABLE BIT(6)
#define MAX77621_INDUCTOR_PLUS_60_PER 0x3 #define MAX77621_T_JUNCTION_120 BIT(7)
int max77620_regulator_get_status(u32 id); #define MAX77621_CPU_CTRL1_POR_DEFAULT (MAX77621_RAMP_50mV_PER_US)
int max77620_regulator_config_fps(u32 id); #define MAX77621_CPU_CTRL1_HOS_DEFAULT (MAX77621_AD_ENABLE | \
int max77620_regulator_set_voltage(u32 id, u32 mv); MAX77621_NFSR_ENABLE | \
int max77620_regulator_enable(u32 id, int enable); MAX77621_SNS_ENABLE | \
int max77620_regulator_set_volt_and_flags(u32 id, u32 mv, u8 flags); MAX77621_RAMP_12mV_PER_US)
#define MAX77621_CPU_CTRL2_POR_DEFAULT (MAX77621_T_JUNCTION_120 | \
MAX77621_FT_ENABLE | \
MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS | \
MAX77621_CKKADV_TRIP_150mV_PER_US | \
MAX77621_INDUCTOR_NOMINAL)
#define MAX77621_CPU_CTRL2_HOS_DEFAULT (MAX77621_T_JUNCTION_120 | \
MAX77621_WDTMR_ENABLE | \
MAX77621_CKKADV_TRIP_75mV_PER_US | \
MAX77621_INDUCTOR_NOMINAL)
#define MAX77621_CTRL_HOS_CFG 0
#define MAX77621_CTRL_POR_CFG 1
int max77620_regulator_get_status(u32 id);
int max77620_regulator_config_fps(u32 id);
int max7762x_regulator_set_voltage(u32 id, u32 mv);
int max7762x_regulator_enable(u32 id, bool enable);
void max77620_config_gpio(u32 id, bool enable);
void max77620_config_default(); void max77620_config_default();
void max77620_low_battery_monitor_config(bool enable); void max77620_low_battery_monitor_config(bool enable);
void max77621_config_default(u32 id, bool por);
#endif #endif

View File

@ -17,8 +17,8 @@
#ifndef _MAX77812_H_ #ifndef _MAX77812_H_
#define _MAX77812_H_ #define _MAX77812_H_
#define MAX77812_PHASE31_CPU_I2C_ADDR 0x31 #define MAX77812_PHASE31_CPU_I2C_ADDR 0x31 // 2 Outputs: 3-phase M1 + 1-phase M4.
#define MAX77812_PHASE211_CPU_I2C_ADDR 0x33 #define MAX77812_PHASE211_CPU_I2C_ADDR 0x33 // 3 Outputs: 2-phase M1 + 1-phase M3 + 1-phase M4.
#define MAX77812_REG_RSET 0x00 #define MAX77812_REG_RSET 0x00
#define MAX77812_REG_INT_SRC 0x01 #define MAX77812_REG_INT_SRC 0x01
@ -27,7 +27,15 @@
#define MAX77812_REG_TOPSYS_INT_M 0x04 #define MAX77812_REG_TOPSYS_INT_M 0x04
#define MAX77812_REG_TOPSYS_STAT 0x05 #define MAX77812_REG_TOPSYS_STAT 0x05
#define MAX77812_REG_EN_CTRL 0x06 #define MAX77812_REG_EN_CTRL 0x06
#define MAX77812_EN_CTRL_EN_M4 BIT(6) #define MAX77812_EN_CTRL_ENABLE 1
#define MAX77812_EN_CTRL_EN_M1_SHIFT 0
#define MAX77812_EN_CTRL_EN_M1_MASK (1 << MAX77812_EN_CTRL_EN_M1_SHIFT)
#define MAX77812_EN_CTRL_EN_M2_SHIFT 2
#define MAX77812_EN_CTRL_EN_M2_MASK (1 << MAX77812_EN_CTRL_EN_M2_SHIFT)
#define MAX77812_EN_CTRL_EN_M3_SHIFT 4
#define MAX77812_EN_CTRL_EN_M3_MASK (1 << MAX77812_EN_CTRL_EN_M3_SHIFT)
#define MAX77812_EN_CTRL_EN_M4_SHIFT 6
#define MAX77812_EN_CTRL_EN_M4_MASK (1 << MAX77812_EN_CTRL_EN_M4_SHIFT)
#define MAX77812_REG_STUP_DLY2 0x07 #define MAX77812_REG_STUP_DLY2 0x07
#define MAX77812_REG_STUP_DLY3 0x08 #define MAX77812_REG_STUP_DLY3 0x08
#define MAX77812_REG_STUP_DLY4 0x09 #define MAX77812_REG_STUP_DLY4 0x09
@ -46,11 +54,10 @@
#define MAX77812_REG_BUCK_INT 0x20 #define MAX77812_REG_BUCK_INT 0x20
#define MAX77812_REG_BUCK_INT_M 0x21 #define MAX77812_REG_BUCK_INT_M 0x21
#define MAX77812_REG_BUCK_STAT 0x22 #define MAX77812_REG_BUCK_STAT 0x22
#define MAX77812_REG_M1_VOUT 0x23 #define MAX77812_REG_M1_VOUT 0x23 // GPU.
#define MAX77812_REG_M2_VOUT 0x24 #define MAX77812_REG_M2_VOUT 0x24
#define MAX77812_REG_M3_VOUT 0x25 #define MAX77812_REG_M3_VOUT 0x25 // DRAM on PHASE211.
#define MAX77812_REG_M4_VOUT 0x26 #define MAX77812_REG_M4_VOUT 0x26 // CPU.
#define MAX77812_M4_VOUT_0_80V 0x6E
#define MAX77812_REG_M1_VOUT_D 0x27 #define MAX77812_REG_M1_VOUT_D 0x27
#define MAX77812_REG_M2_VOUT_D 0x28 #define MAX77812_REG_M2_VOUT_D 0x28
#define MAX77812_REG_M3_VOUT_D 0x29 #define MAX77812_REG_M3_VOUT_D 0x29
@ -66,6 +73,8 @@
#define MAX77812_REG_GLB_CFG1 0x33 #define MAX77812_REG_GLB_CFG1 0x33
#define MAX77812_REG_GLB_CFG2 0x34 #define MAX77812_REG_GLB_CFG2 0x34
#define MAX77812_REG_GLB_CFG3 0x35 #define MAX77812_REG_GLB_CFG3 0x35
/*! Protected area and settings only for MAX77812_REG_VERSION 4 */
#define MAX77812_REG_GLB_CFG4 0x36 #define MAX77812_REG_GLB_CFG4 0x36
#define MAX77812_REG_GLB_CFG5 0x37 #define MAX77812_REG_GLB_CFG5 0x37
#define MAX77812_REG_GLB_CFG6 0x38 #define MAX77812_REG_GLB_CFG6 0x38
@ -91,10 +100,6 @@
#define MAX77812_ES2_VERSION 0x04 #define MAX77812_ES2_VERSION 0x04
#define MAX77812_QS_VERSION 0x05 #define MAX77812_QS_VERSION 0x05
#define MAX77812_VOUT_MASK 0xFF #define MAX77812_BUCK_VOLT_MASK 0xFF
#define MAX77812_VOUT_N_VOLTAGE 0xFF
#define MAX77812_VOUT_VMIN 250000
#define MAX77812_VOUT_VMAX 1525000
#define MAX77812_VOUT_STEP 5000
#endif #endif

View File

@ -21,8 +21,9 @@
#include <utils/types.h> #include <utils/types.h>
static u8 reg_5v_dev = 0; static u8 reg_5v_dev = 0;
static bool batt_src = false;
void regulator_enable_5v(u8 dev) void regulator_5v_enable(u8 dev)
{ {
// The power supply selection from battery or USB is automatic. // The power supply selection from battery or USB is automatic.
if (!reg_5v_dev) if (!reg_5v_dev)
@ -32,6 +33,7 @@ void regulator_enable_5v(u8 dev)
gpio_config(GPIO_PORT_A, GPIO_PIN_5, GPIO_MODE_GPIO); gpio_config(GPIO_PORT_A, GPIO_PIN_5, GPIO_MODE_GPIO);
gpio_output_enable(GPIO_PORT_A, GPIO_PIN_5, GPIO_OUTPUT_ENABLE); gpio_output_enable(GPIO_PORT_A, GPIO_PIN_5, GPIO_OUTPUT_ENABLE);
gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_HIGH); gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_HIGH);
batt_src = true;
// Fan and Rail power from USB 5V VDD. // Fan and Rail power from USB 5V VDD.
PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN0) = PINMUX_LPDR | 1; PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN0) = PINMUX_LPDR | 1;
@ -47,7 +49,7 @@ void regulator_enable_5v(u8 dev)
reg_5v_dev |= dev; reg_5v_dev |= dev;
} }
void regulator_disable_5v(u8 dev) void regulator_5v_disable(u8 dev)
{ {
reg_5v_dev &= ~dev; reg_5v_dev &= ~dev;
@ -58,6 +60,7 @@ void regulator_disable_5v(u8 dev)
gpio_output_enable(GPIO_PORT_A, GPIO_PIN_5, GPIO_OUTPUT_DISABLE); gpio_output_enable(GPIO_PORT_A, GPIO_PIN_5, GPIO_OUTPUT_DISABLE);
gpio_config(GPIO_PORT_A, GPIO_PIN_5, GPIO_MODE_SPIO); gpio_config(GPIO_PORT_A, GPIO_PIN_5, GPIO_MODE_SPIO);
PINMUX_AUX(PINMUX_AUX_SATA_LED_ACTIVE) = PINMUX_PARKED | PINMUX_INPUT_ENABLE; PINMUX_AUX(PINMUX_AUX_SATA_LED_ACTIVE) = PINMUX_PARKED | PINMUX_INPUT_ENABLE;
batt_src = false;
// Rail power from USB 5V VDD. // Rail power from USB 5V VDD.
gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW); gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW);
@ -70,7 +73,21 @@ void regulator_disable_5v(u8 dev)
} }
} }
bool regulator_get_5v_dev_enabled(u8 dev) bool regulator_5v_get_dev_enabled(u8 dev)
{ {
return (reg_5v_dev & dev); return (reg_5v_dev & dev);
} }
void regulator_5v_batt_src_enable(bool enable)
{
if (enable && !batt_src)
{
gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_HIGH);
batt_src = true;
}
else if (!enable && batt_src)
{
gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_LOW);
batt_src = false;
}
}

View File

@ -27,8 +27,9 @@ enum
REGULATOR_5V_ALL = 0xFF REGULATOR_5V_ALL = 0xFF
}; };
void regulator_enable_5v(u8 dev); void regulator_5v_enable(u8 dev);
void regulator_disable_5v(u8 dev); void regulator_5v_disable(u8 dev);
bool regulator_get_5v_dev_enabled(u8 dev); bool regulator_5v_get_dev_enabled(u8 dev);
void regulator_5v_batt_src_enable(bool enable);
#endif #endif

View File

@ -1,8 +1,8 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer * Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2018 Atmosphère-NX * Copyright (c) 2018 Atmosphère-NX
* Copyright (c) 2019-2020 shchmue * Copyright (c) 2019-2021 shchmue
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -35,8 +35,8 @@ typedef struct _se_ll_t
vu32 size; vu32 size;
} se_ll_t; } se_ll_t;
static u32 _se_rsa_mod_sizes[TEGRA_SE_RSA_KEYSLOT_COUNT]; static u32 _se_rsa_mod_sizes[SE_RSA_KEYSLOT_COUNT];
static u32 _se_rsa_exp_sizes[TEGRA_SE_RSA_KEYSLOT_COUNT]; static u32 _se_rsa_exp_sizes[SE_RSA_KEYSLOT_COUNT];
static void _gf256_mul_x(void *block) static void _gf256_mul_x(void *block)
{ {
@ -79,17 +79,17 @@ static void _se_ll_init(se_ll_t *ll, u32 addr, u32 size)
static void _se_ll_set(se_ll_t *dst, se_ll_t *src) static void _se_ll_set(se_ll_t *dst, se_ll_t *src)
{ {
SE(SE_IN_LL_ADDR_REG_OFFSET) = (u32)src; SE(SE_IN_LL_ADDR_REG) = (u32)src;
SE(SE_OUT_LL_ADDR_REG_OFFSET) = (u32)dst; SE(SE_OUT_LL_ADDR_REG) = (u32)dst;
} }
static int _se_wait() static int _se_wait()
{ {
while (!(SE(SE_INT_STATUS_REG_OFFSET) & SE_INT_OP_DONE(INT_SET))) while (!(SE(SE_INT_STATUS_REG) & SE_INT_OP_DONE))
; ;
if (SE(SE_INT_STATUS_REG_OFFSET) & SE_INT_ERROR(INT_SET) || if (SE(SE_INT_STATUS_REG) & SE_INT_ERR_STAT ||
SE(SE_STATUS_0) & SE_STATUS_0_STATE_WAIT_IN || (SE(SE_STATUS_REG) & SE_STATUS_STATE_MASK) != SE_STATUS_STATE_IDLE ||
SE(SE_ERR_STATUS_0) != SE_ERR_STATUS_0_SE_NS_ACCESS_CLEAR) SE(SE_ERR_STATUS_REG) != 0)
return 0; return 0;
return 1; return 1;
} }
@ -114,12 +114,12 @@ static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src
_se_ll_set(ll_dst, ll_src); _se_ll_set(ll_dst, ll_src);
SE(SE_ERR_STATUS_0) = SE(SE_ERR_STATUS_0); SE(SE_ERR_STATUS_REG) = SE(SE_ERR_STATUS_REG);
SE(SE_INT_STATUS_REG_OFFSET) = SE(SE_INT_STATUS_REG_OFFSET); SE(SE_INT_STATUS_REG) = SE(SE_INT_STATUS_REG);
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
SE(SE_OPERATION_REG_OFFSET) = SE_OPERATION(op); SE(SE_OPERATION_REG) = op;
if (is_oneshot) if (is_oneshot)
{ {
@ -168,13 +168,13 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr
if (!src || !dst) if (!src || !dst)
return 0; return 0;
u8 *block = (u8 *)malloc(0x10); u8 *block = (u8 *)malloc(SE_AES_BLOCK_SIZE);
memset(block, 0, 0x10); memset(block, 0, SE_AES_BLOCK_SIZE);
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
memcpy(block, src, src_size); memcpy(block, src, src_size);
int res = _se_execute_oneshot(op, block, 0x10, block, 0x10); int res = _se_execute_oneshot(op, block, SE_AES_BLOCK_SIZE, block, SE_AES_BLOCK_SIZE);
memcpy(dst, block, dst_size); memcpy(dst, block, dst_size);
free(block); free(block);
@ -183,21 +183,21 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr
static void _se_aes_ctr_set(void *ctr) static void _se_aes_ctr_set(void *ctr)
{ {
u32 data[TEGRA_SE_AES_BLOCK_SIZE / 4]; u32 data[SE_AES_IV_SIZE / 4];
memcpy(data, ctr, TEGRA_SE_AES_BLOCK_SIZE); memcpy(data, ctr, SE_AES_IV_SIZE);
for (u32 i = 0; i < (TEGRA_SE_AES_BLOCK_SIZE / 4); i++) for (u32 i = 0; i < SE_CRYPTO_LINEAR_CTR_REG_COUNT; i++)
SE(SE_CRYPTO_CTR_REG_OFFSET + (4 * i)) = data[i]; SE(SE_CRYPTO_LINEAR_CTR_REG + (4 * i)) = data[i];
} }
void se_rsa_acc_ctrl(u32 rs, u32 flags) void se_rsa_acc_ctrl(u32 rs, u32 flags)
{ {
if (flags & SE_RSA_KEY_TBL_DIS_KEY_ALL_FLAG) if (flags & SE_RSA_KEY_TBL_DIS_KEY_ACCESS_FLAG)
SE(SE_RSA_KEYTABLE_ACCESS_REG_OFFSET + 4 * rs) = SE(SE_RSA_KEYTABLE_ACCESS_REG + 4 * rs) =
((flags >> SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG_SHIFT) & SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG) | (((flags >> 4) & SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG) |(flags & SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG)) ^
((flags & SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG) ^ SE_RSA_KEY_TBL_DIS_KEY_ALL_COMMON_FLAG); SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_USE_FLAG;
if (flags & SE_RSA_KEY_TBL_DIS_KEY_LOCK_FLAG) if (flags & SE_RSA_KEY_LOCK_FLAG)
SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) &= ~BIT(rs); SE(SE_RSA_SECURITY_PERKEY_REG) &= ~BIT(rs);
} }
// se_rsa_key_set() was derived from Atmosphère's set_rsa_keyslot // se_rsa_key_set() was derived from Atmosphère's set_rsa_keyslot
@ -206,15 +206,15 @@ void se_rsa_key_set(u32 ks, const void *mod, u32 mod_size, const void *exp, u32
u32 *data = (u32 *)mod; u32 *data = (u32 *)mod;
for (u32 i = 0; i < mod_size / 4; i++) for (u32 i = 0; i < mod_size / 4; i++)
{ {
SE(SE_RSA_KEYTABLE_ADDR) = RSA_KEY_NUM(ks) | RSA_KEY_TYPE(RSA_KEY_TYPE_MOD) | 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) = byte_swap_32(data[mod_size / 4 - i - 1]); SE(SE_RSA_KEYTABLE_DATA_REG) = byte_swap_32(data[mod_size / 4 - i - 1]);
} }
data = (u32 *)exp; data = (u32 *)exp;
for (u32 i = 0; i < exp_size / 4; i++) for (u32 i = 0; i < exp_size / 4; i++)
{ {
SE(SE_RSA_KEYTABLE_ADDR) = RSA_KEY_NUM(ks) | RSA_KEY_TYPE(RSA_KEY_TYPE_EXP) | 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) = byte_swap_32(data[exp_size / 4 - i - 1]); SE(SE_RSA_KEYTABLE_DATA_REG) = byte_swap_32(data[exp_size / 4 - i - 1]);
} }
_se_rsa_mod_sizes[ks] = mod_size; _se_rsa_mod_sizes[ks] = mod_size;
@ -224,15 +224,15 @@ void se_rsa_key_set(u32 ks, const void *mod, u32 mod_size, const void *exp, u32
// se_rsa_key_clear() was derived from Atmosphère's clear_rsa_keyslot // se_rsa_key_clear() was derived from Atmosphère's clear_rsa_keyslot
void se_rsa_key_clear(u32 ks) void se_rsa_key_clear(u32 ks)
{ {
for (u32 i = 0; i < TEGRA_SE_RSA2048_DIGEST_SIZE / 4; i++) for (u32 i = 0; i < SE_RSA2048_DIGEST_SIZE / 4; i++)
{ {
SE(SE_RSA_KEYTABLE_ADDR) = RSA_KEY_NUM(ks) | RSA_KEY_TYPE(RSA_KEY_TYPE_MOD) | 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) = 0; SE(SE_RSA_KEYTABLE_DATA_REG) = 0;
} }
for (u32 i = 0; i < TEGRA_SE_RSA2048_DIGEST_SIZE / 4; i++) for (u32 i = 0; i < SE_RSA2048_DIGEST_SIZE / 4; i++)
{ {
SE(SE_RSA_KEYTABLE_ADDR) = RSA_KEY_NUM(ks) | RSA_KEY_TYPE(RSA_KEY_TYPE_EXP) | 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) = 0; SE(SE_RSA_KEYTABLE_DATA_REG) = 0;
} }
} }
@ -240,22 +240,22 @@ 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) int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size)
{ {
int res; int res;
u8 stack_buf[TEGRA_SE_RSA2048_DIGEST_SIZE]; u8 stack_buf[SE_RSA2048_DIGEST_SIZE];
for (u32 i = 0; i < src_size; i++) for (u32 i = 0; i < src_size; i++)
stack_buf[i] = *((u8 *)src + src_size - i - 1); stack_buf[i] = *((u8 *)src + src_size - i - 1);
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_RSA) | SE_CONFIG_DST(DST_RSAREG); 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_CONFIG) = RSA_KEY_SLOT(ks);
SE(SE_RSA_KEY_SIZE_REG_OFFSET) = (_se_rsa_mod_sizes[ks] >> 6) - 1; SE(SE_RSA_KEY_SIZE_REG) = (_se_rsa_mod_sizes[ks] >> 6) - 1;
SE(SE_RSA_EXP_SIZE_REG_OFFSET) = _se_rsa_exp_sizes[ks] >> 2; SE(SE_RSA_EXP_SIZE_REG) = _se_rsa_exp_sizes[ks] >> 2;
res = _se_execute_oneshot(OP_START, NULL, 0, stack_buf, src_size); res = _se_execute_oneshot(SE_OP_START, NULL, 0, stack_buf, src_size);
// Copy output hash. // Copy output hash.
u32 *dst32 = (u32 *)dst; u32 *dst32 = (u32 *)dst;
for (u32 i = 0; i < dst_size / 4; i++) for (u32 i = 0; i < dst_size / 4; i++)
dst32[dst_size / 4 - i - 1] = byte_swap_32(SE(SE_RSA_OUTPUT + (i << 2))); dst32[dst_size / 4 - i - 1] = byte_swap_32(SE(SE_RSA_OUTPUT_REG + (i << 2)));
return res; return res;
} }
@ -263,54 +263,54 @@ int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_siz
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)
SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 4 * ks) = ~flags; SE(SE_CRYPTO_KEYTABLE_ACCESS_REG + 4 * ks) = ~flags;
if (flags & SE_KEY_TBL_DIS_KEY_LOCK_FLAG) if (flags & SE_KEY_LOCK_FLAG)
SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) &= ~BIT(ks); SE(SE_CRYPTO_SECURITY_PERKEY_REG) &= ~BIT(ks);
} }
u32 se_key_acc_ctrl_get(u32 ks) u32 se_key_acc_ctrl_get(u32 ks)
{ {
return SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 4 * ks); return SE(SE_CRYPTO_KEYTABLE_ACCESS_REG + 4 * ks);
} }
void se_aes_key_set(u32 ks, const void *key, u32 size) void se_aes_key_set(u32 ks, const void *key, u32 size)
{ {
u32 data[TEGRA_SE_AES_MAX_KEY_SIZE / 4]; u32 data[SE_AES_MAX_KEY_SIZE / 4];
memcpy(data, key, size); memcpy(data, key, size);
for (u32 i = 0; i < (size / 4); i++) for (u32 i = 0; i < (size / 4); i++)
{ {
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i; SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_PKT(i); // QUAD is automatically set by PKT.
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data[i]; SE(SE_CRYPTO_KEYTABLE_DATA_REG) = data[i];
} }
} }
void se_aes_key_partial_set(u32 ks, u32 index, u32 data) void se_aes_key_partial_set(u32 ks, u32 index, u32 data)
{ {
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | index; SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | index;
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data; 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[TEGRA_SE_AES_BLOCK_SIZE / 4]; u32 data[SE_AES_IV_SIZE / 4];
memcpy(data, iv, TEGRA_SE_AES_BLOCK_SIZE); memcpy(data, iv, SE_AES_IV_SIZE);
for (u32 i = 0; i < (TEGRA_SE_AES_BLOCK_SIZE / 4); i++) for (u32 i = 0; i < (SE_AES_IV_SIZE / 4); i++)
{ {
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(QUAD_ORG_IV) | i; SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(ORIGINAL_IV) | SE_KEYTABLE_PKT(i);
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data[i]; SE(SE_CRYPTO_KEYTABLE_DATA_REG) = data[i];
} }
} }
void se_aes_key_get(u32 ks, void *key, u32 size) void se_aes_key_get(u32 ks, void *key, u32 size)
{ {
u32 data[TEGRA_SE_AES_MAX_KEY_SIZE / 4]; u32 data[SE_AES_MAX_KEY_SIZE / 4];
for (u32 i = 0; i < (size / 4); i++) for (u32 i = 0; i < (size / 4); i++)
{ {
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i; SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_PKT(i); // QUAD is automatically set by PKT.
data[i] = SE(SE_KEYTABLE_DATA0_REG_OFFSET); data[i] = SE(SE_CRYPTO_KEYTABLE_DATA_REG);
} }
memcpy(key, data, size); memcpy(key, data, size);
@ -318,77 +318,77 @@ 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)
{ {
for (u32 i = 0; i < (TEGRA_SE_AES_MAX_KEY_SIZE / 4); i++) for (u32 i = 0; i < (SE_AES_MAX_KEY_SIZE / 4); i++)
{ {
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i; SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_PKT(i); // QUAD is automatically set by PKT.
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = 0; SE(SE_CRYPTO_KEYTABLE_DATA_REG) = 0;
} }
} }
void se_aes_iv_clear(u32 ks) void se_aes_iv_clear(u32 ks)
{ {
for (u32 i = 0; i < (TEGRA_SE_AES_BLOCK_SIZE / 4); i++) for (u32 i = 0; i < (SE_AES_IV_SIZE / 4); i++)
{ {
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(QUAD_ORG_IV) | i; SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(ORIGINAL_IV) | SE_KEYTABLE_PKT(i);
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = 0; SE(SE_CRYPTO_KEYTABLE_DATA_REG) = 0;
} }
} }
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input) int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input)
{ {
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_KEYTAB); SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_KEYTABLE);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT); SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst); SE(SE_CRYPTO_KEYTABLE_DST_REG) = SE_KEYTABLE_DST_KEY_INDEX(ks_dst) | SE_KEYTABLE_DST_WORD_QUAD(KEYS_0_3);
return _se_execute_oneshot(OP_START, NULL, 0, input, 0x10); return _se_execute_oneshot(SE_OP_START, NULL, 0, input, SE_KEY_128_SIZE);
} }
int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size) int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size)
{ {
if (enc) if (enc)
{ {
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT); SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT);
} }
else else
{ {
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY); SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT); SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
} }
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1; SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1;
return _se_execute_oneshot(OP_START, dst, dst_size, src, src_size); return _se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size);
} }
int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size) int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size)
{ {
if (enc) if (enc)
{ {
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) | SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) |
SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_XOR_POS(XOR_TOP); SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_XOR_POS(XOR_TOP);
} }
else else
{ {
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY); SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVAHB) | SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVMEM) |
SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM); SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM);
} }
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1; SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1;
return _se_execute_oneshot(OP_START, dst, dst_size, src, src_size); return _se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size);
} }
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src) int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src)
{ {
return se_aes_crypt_ecb(ks, enc, dst, 0x10, src, 0x10); return se_aes_crypt_ecb(ks, enc, dst, SE_AES_BLOCK_SIZE, src, SE_AES_BLOCK_SIZE);
} }
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr) int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr)
{ {
SE(SE_SPARE_0_REG_OFFSET) = 1; SE(SE_SPARE_REG) = SE_ECO(SE_ERRATA_FIX_ENABLE);
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) |
SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_LNR_CTR) | SE_CRYPTO_CTR_VAL(1); SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_LNR_CTR) | SE_CRYPTO_CTR_CNTN(1);
_se_aes_ctr_set(ctr); _se_aes_ctr_set(ctr);
u32 src_size_aligned = src_size & 0xFFFFFFF0; u32 src_size_aligned = src_size & 0xFFFFFFF0;
@ -396,13 +396,13 @@ int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_s
if (src_size_aligned) if (src_size_aligned)
{ {
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1; SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1;
if (!_se_execute_oneshot(OP_START, dst, dst_size, src, src_size_aligned)) if (!_se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size_aligned))
return 0; return 0;
} }
if (src_size - src_size_aligned && src_size_aligned < dst_size) if (src_size - src_size_aligned && src_size_aligned < dst_size)
return _se_execute_one_block(OP_START, dst + src_size_aligned, return _se_execute_one_block(SE_OP_START, dst + src_size_aligned,
MIN(src_size_delta, dst_size - src_size_aligned), MIN(src_size_delta, dst_size - src_size_aligned),
src + src_size_aligned, src_size_delta); src + src_size_aligned, src_size_delta);
@ -419,15 +419,15 @@ int se_initialize_rng()
u8 *output_buf = (u8 *)malloc(0x10); u8 *output_buf = (u8 *)malloc(0x10);
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY); SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM); SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_MODE(RNG_MODE_FORCE_INSTANTION) | SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY); SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_MODE(MODE_FORCE_INSTANTION) | SE_RNG_CONFIG_SRC(SRC_ENTROPY);
SE(SE_RNG_RESEED_INTERVAL_REG_OFFSET) = 70001; SE(SE_RNG_RESEED_INTERVAL_REG) = 70001;
SE(SE_RNG_SRC_CONFIG_REG_OFFSET) = SE_RNG_SRC_CONFIG_ENT_SRC(RNG_SRC_RO_ENT_ENABLE) | SE(SE_RNG_SRC_CONFIG_REG) = SE_RNG_SRC_CONFIG_ENTR_SRC(RO_ENTR_ENABLE) |
SE_RNG_SRC_CONFIG_ENT_SRC_LOCK(RNG_SRC_RO_ENT_LOCK_ENABLE); SE_RNG_SRC_CONFIG_ENTR_SRC_LOCK(RO_ENTR_LOCK_ENABLE);
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; SE(SE_CRYPTO_BLOCK_COUNT_REG) = 0;
int res =_se_execute_oneshot(OP_START, output_buf, 0x10, NULL, 0); int res =_se_execute_oneshot(SE_OP_START, output_buf, 0x10, NULL, 0);
free(output_buf); free(output_buf);
if (res) if (res)
@ -437,35 +437,35 @@ int se_initialize_rng()
int se_generate_random(void *dst, u32 size) int se_generate_random(void *dst, u32 size)
{ {
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY); SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM); SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_MODE(RNG_MODE_NORMAL) | SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY); SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_MODE(MODE_NORMAL) | SE_RNG_CONFIG_SRC(SRC_ENTROPY);
u32 num_blocks = size >> 4; u32 num_blocks = size >> 4;
u32 aligned_size = num_blocks << 4; u32 aligned_size = num_blocks << 4;
if (num_blocks) if (num_blocks)
{ {
SE(SE_BLOCK_COUNT_REG_OFFSET) = num_blocks - 1; SE(SE_CRYPTO_BLOCK_COUNT_REG) = num_blocks - 1;
if (!_se_execute_oneshot(OP_START, dst, aligned_size, NULL, 0)) if (!_se_execute_oneshot(SE_OP_START, dst, aligned_size, NULL, 0))
return 0; return 0;
} }
if (size > aligned_size) if (size > aligned_size)
return _se_execute_one_block(OP_START, dst + aligned_size, size - aligned_size, NULL, 0); return _se_execute_one_block(SE_OP_START, dst + aligned_size, size - aligned_size, NULL, 0);
return 1; return 1;
} }
int se_generate_random_key(u32 ks_dst, u32 ks_src) int se_generate_random_key(u32 ks_dst, u32 ks_src)
{ {
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY); SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) |
SE_CRYPTO_INPUT_SEL(INPUT_RANDOM); SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_MODE(RNG_MODE_NORMAL) | SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY); SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_MODE(MODE_NORMAL) | SE_RNG_CONFIG_SRC(SRC_ENTROPY);
SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst); SE(SE_CRYPTO_KEYTABLE_DST_REG) = SE_KEYTABLE_DST_KEY_INDEX(ks_dst);
if (!_se_execute_oneshot(OP_START, NULL, 0, NULL, 0)) if (!_se_execute_oneshot(SE_OP_START, NULL, 0, NULL, 0))
return 0; return 0;
SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst) | 1; SE(SE_CRYPTO_KEYTABLE_DST_REG) = SE_KEYTABLE_DST_KEY_INDEX(ks_dst) | 1;
if (!_se_execute_oneshot(OP_START, NULL, 0, NULL, 0)) if (!_se_execute_oneshot(SE_OP_START, NULL, 0, NULL, 0))
return 0; return 0;
return 1; return 1;
@ -544,8 +544,8 @@ int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size)
if (src_size & 0xF) if (src_size & 0xF)
_gf256_mul_x(key); _gf256_mul_x(key);
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_HASHREG); SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_HASHREG);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_INPUT_SEL(INPUT_AHB) | SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_INPUT_SEL(INPUT_MEMORY) |
SE_CRYPTO_XOR_POS(XOR_TOP) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) | SE_CRYPTO_HASH(HASH_ENABLE) | SE_CRYPTO_XOR_POS(XOR_TOP) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) | SE_CRYPTO_HASH(HASH_ENABLE) |
SE_CRYPTO_CORE_SEL(CORE_ENCRYPT); SE_CRYPTO_CORE_SEL(CORE_ENCRYPT);
se_aes_iv_clear(ks); se_aes_iv_clear(ks);
@ -553,10 +553,10 @@ int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size)
u32 num_blocks = (src_size + 0xf) >> 4; u32 num_blocks = (src_size + 0xf) >> 4;
if (num_blocks > 1) if (num_blocks > 1)
{ {
SE(SE_BLOCK_COUNT_REG_OFFSET) = num_blocks - 2; SE(SE_CRYPTO_BLOCK_COUNT_REG) = num_blocks - 2;
if (!_se_execute_oneshot(OP_START, NULL, 0, src, src_size)) if (!_se_execute_oneshot(SE_OP_START, NULL, 0, src, src_size))
goto out; goto out;
SE(SE_CRYPTO_REG_OFFSET) |= SE_CRYPTO_IV_SEL(IV_UPDATED); SE(SE_CRYPTO_CONFIG_REG) |= SE_CRYPTO_IV_SEL(IV_UPDATED);
} }
if (src_size & 0xf) if (src_size & 0xf)
@ -572,12 +572,12 @@ int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size)
for (u32 i = 0; i < 0x10; i++) for (u32 i = 0; i < 0x10; i++)
last_block[i] ^= key[i]; last_block[i] ^= key[i];
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; SE(SE_CRYPTO_BLOCK_COUNT_REG) = 0;
res = _se_execute_oneshot(OP_START, NULL, 0, last_block, 0x10); res = _se_execute_oneshot(SE_OP_START, NULL, 0, last_block, 0x10);
u32 *dst32 = (u32 *)dst; u32 *dst32 = (u32 *)dst;
for (u32 i = 0; i < (dst_size >> 2); i++) for (u32 i = 0; i < (dst_size >> 2); i++)
dst32[i] = SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)); dst32[i] = SE(SE_HASH_RESULT_REG + (i << 2));
out:; out:;
free(key); free(key);
@ -588,62 +588,62 @@ out:;
int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot) int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot)
{ {
int res; int res;
u32 hash32[TEGRA_SE_SHA_256_SIZE / 4]; u32 hash32[SE_SHA_256_SIZE / 4];
//! TODO: src_size must be 512 bit aligned if continuing and not last block for SHA256. //! TODO: src_size must be 512 bit aligned if continuing and not last block for SHA256.
if (src_size > 0xFFFFFF || !hash) // Max 16MB - 1 chunks and aligned x4 hash buffer. if (src_size > 0xFFFFFF || !hash) // Max 16MB - 1 chunks and aligned x4 hash buffer.
return 0; return 0;
// Setup config for SHA256. // Setup config for SHA256.
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_SHA256) | SE_CONFIG_ENC_ALG(ALG_SHA) | SE_CONFIG_DST(DST_HASHREG); SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_SHA256) | SE_CONFIG_ENC_ALG(ALG_SHA) | SE_CONFIG_DST(DST_HASHREG);
SE(SE_SHA_CONFIG_REG_OFFSET) = sha_cfg; SE(SE_SHA_CONFIG_REG) = sha_cfg;
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
// Set total size to current buffer size if empty. // Set total size to current buffer size if empty.
if (!total_size) if (!total_size)
total_size = src_size; total_size = src_size;
// Set total size: BITS(src_size), up to 2 EB. // Set total size: BITS(src_size), up to 2 EB.
SE(SE_SHA_MSG_LENGTH_0_REG_OFFSET) = (u32)(total_size << 3); SE(SE_SHA_MSG_LENGTH_0_REG) = (u32)(total_size << 3);
SE(SE_SHA_MSG_LENGTH_1_REG_OFFSET) = (u32)(total_size >> 29); SE(SE_SHA_MSG_LENGTH_1_REG) = (u32)(total_size >> 29);
SE(SE_SHA_MSG_LENGTH_2_REG_OFFSET) = 0; SE(SE_SHA_MSG_LENGTH_2_REG) = 0;
SE(SE_SHA_MSG_LENGTH_3_REG_OFFSET) = 0; SE(SE_SHA_MSG_LENGTH_3_REG) = 0;
// Set size left to hash. // Set size left to hash.
SE(SE_SHA_MSG_LEFT_0_REG_OFFSET) = (u32)(total_size << 3); SE(SE_SHA_MSG_LEFT_0_REG) = (u32)(total_size << 3);
SE(SE_SHA_MSG_LEFT_1_REG_OFFSET) = (u32)(total_size >> 29); SE(SE_SHA_MSG_LEFT_1_REG) = (u32)(total_size >> 29);
SE(SE_SHA_MSG_LEFT_2_REG_OFFSET) = 0; SE(SE_SHA_MSG_LEFT_2_REG) = 0;
SE(SE_SHA_MSG_LEFT_3_REG_OFFSET) = 0; SE(SE_SHA_MSG_LEFT_3_REG) = 0;
// If we hash in chunks, copy over the intermediate. // If we hash in chunks, copy over the intermediate.
if (sha_cfg == SHA_CONTINUE && msg_left) if (sha_cfg == SHA_CONTINUE && msg_left)
{ {
// Restore message left to process. // Restore message left to process.
SE(SE_SHA_MSG_LEFT_0_REG_OFFSET) = msg_left[0]; SE(SE_SHA_MSG_LEFT_0_REG) = msg_left[0];
SE(SE_SHA_MSG_LEFT_1_REG_OFFSET) = msg_left[1]; SE(SE_SHA_MSG_LEFT_1_REG) = msg_left[1];
// Restore hash reg. // Restore hash reg.
memcpy(hash32, hash, TEGRA_SE_SHA_256_SIZE); memcpy(hash32, hash, SE_SHA_256_SIZE);
for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++) for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++)
SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)) = byte_swap_32(hash32[i]); SE(SE_HASH_RESULT_REG + (i * 4)) = byte_swap_32(hash32[i]);
} }
// Trigger the operation. // Trigger the operation.
res = _se_execute(OP_START, NULL, 0, src, src_size, is_oneshot); res = _se_execute(SE_OP_START, NULL, 0, src, src_size, is_oneshot);
if (is_oneshot) if (is_oneshot)
{ {
// Backup message left. // Backup message left.
if (msg_left) if (msg_left)
{ {
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG_OFFSET); msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG);
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG_OFFSET); msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG);
} }
// Copy output hash. // Copy output hash.
for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++) for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++)
hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG_OFFSET + (i << 2))); hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG + (i * 4)));
memcpy(hash, hash32, TEGRA_SE_SHA_256_SIZE); memcpy(hash, hash32, SE_SHA_256_SIZE);
} }
return res; return res;
@ -656,20 +656,20 @@ 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)
{ {
u32 hash32[TEGRA_SE_SHA_256_SIZE / 4]; u32 hash32[SE_SHA_256_SIZE / 4];
int res = _se_execute_finalize(); int res = _se_execute_finalize();
// Backup message left. // Backup message left.
if (msg_left) if (msg_left)
{ {
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG_OFFSET); msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG);
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG_OFFSET); msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG);
} }
// Copy output hash. // Copy output hash.
for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++) for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++)
hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG_OFFSET + (i << 2))); hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG + (i << 2)));
memcpy(hash, hash32, TEGRA_SE_SHA_256_SIZE); memcpy(hash, hash32, SE_SHA_256_SIZE);
return res; return res;
} }
@ -793,43 +793,43 @@ void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize)
u8 *aligned_buf = (u8 *)ALIGN((u32)buf, 0x40); u8 *aligned_buf = (u8 *)ALIGN((u32)buf, 0x40);
// Set Secure Random Key. // Set Secure Random Key.
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_SRK); SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_SRK);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(0) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM); SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(0) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY) | SE_RNG_CONFIG_MODE(RNG_MODE_FORCE_RESEED); SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_SRC(SRC_ENTROPY) | SE_RNG_CONFIG_MODE(MODE_FORCE_RESEED);
SE(SE_CRYPTO_LAST_BLOCK) = 0; SE(SE_CRYPTO_LAST_BLOCK) = 0;
_se_execute_oneshot(OP_START, NULL, 0, NULL, 0); _se_execute_oneshot(SE_OP_START, NULL, 0, NULL, 0);
// Save AES keys. // Save AES keys.
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
for (u32 i = 0; i < TEGRA_SE_KEYSLOT_COUNT; i++) for (u32 i = 0; i < SE_AES_KEYSLOT_COUNT; i++)
{ {
SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(AES_KEYTABLE) | SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(AES_KEYTABLE) | SE_KEYTABLE_DST_KEY_INDEX(i) |
(i << SE_KEY_INDEX_SHIFT) | SE_CONTEXT_SAVE_WORD_QUAD(KEYS_0_3); SE_CONTEXT_AES_KEY_INDEX(0) | SE_CONTEXT_AES_WORD_QUAD(KEYS_0_3);
SE(SE_CRYPTO_LAST_BLOCK) = 0; SE(SE_CRYPTO_LAST_BLOCK) = 0;
_se_execute_oneshot(OP_CTX_SAVE, aligned_buf, 0x10, NULL, 0); _se_execute_oneshot(SE_OP_CTX_SAVE, aligned_buf, SE_AES_BLOCK_SIZE, NULL, 0);
memcpy(keys + i * keysize, aligned_buf, 0x10); memcpy(keys + i * keysize, aligned_buf, SE_AES_BLOCK_SIZE);
if (keysize > 0x10) if (keysize > SE_KEY_128_SIZE)
{ {
SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(AES_KEYTABLE) | SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(AES_KEYTABLE) | SE_KEYTABLE_DST_KEY_INDEX(i) |
(i << SE_KEY_INDEX_SHIFT) | SE_CONTEXT_SAVE_WORD_QUAD(KEYS_4_7); SE_CONTEXT_AES_KEY_INDEX(0) | SE_CONTEXT_AES_WORD_QUAD(KEYS_4_7);
SE(SE_CRYPTO_LAST_BLOCK) = 0; SE(SE_CRYPTO_LAST_BLOCK) = 0;
_se_execute_oneshot(OP_CTX_SAVE, aligned_buf, 0x10, NULL, 0); _se_execute_oneshot(SE_OP_CTX_SAVE, aligned_buf, SE_AES_BLOCK_SIZE, NULL, 0);
memcpy(keys + i * keysize + 0x10, aligned_buf, 0x10); memcpy(keys + i * keysize + SE_AES_BLOCK_SIZE, aligned_buf, SE_AES_BLOCK_SIZE);
} }
} }
// Save SRK to PMC secure scratches. // Save SRK to PMC secure scratches.
SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(SRK); SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(SRK);
SE(SE_CRYPTO_LAST_BLOCK) = 0; SE(SE_CRYPTO_LAST_BLOCK) = 0;
_se_execute_oneshot(OP_CTX_SAVE, NULL, 0, NULL, 0); _se_execute_oneshot(SE_OP_CTX_SAVE, NULL, 0, NULL, 0);
// End context save. // End context save.
SE(SE_CONFIG_REG_OFFSET) = 0; SE(SE_CONFIG_REG) = 0;
_se_execute_oneshot(OP_CTX_SAVE, NULL, 0, NULL, 0); _se_execute_oneshot(SE_OP_CTX_SAVE, NULL, 0, NULL, 0);
// Get SRK. // Get SRK.
u32 srk[4]; u32 srk[4];
@ -840,7 +840,7 @@ void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize)
// Decrypt context. // Decrypt context.
se_aes_key_clear(3); se_aes_key_clear(3);
se_aes_key_set(3, srk, 0x10); se_aes_key_set(3, srk, SE_KEY_128_SIZE);
se_aes_crypt_cbc(3, 0, keys, TEGRA_SE_KEYSLOT_COUNT * keysize, keys, TEGRA_SE_KEYSLOT_COUNT * keysize); se_aes_crypt_cbc(3, 0, keys, SE_AES_KEYSLOT_COUNT * keysize, keys, SE_AES_KEYSLOT_COUNT * keysize);
se_aes_key_clear(3); se_aes_key_clear(3);
} }

View File

@ -1,5 +1,7 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2019-2021 CTCaer
* Copyright (c) 2019-2021 shchmue
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -25,6 +27,7 @@ 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); 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_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_partial_set(u32 ks, u32 index, u32 data);
@ -35,10 +38,10 @@ int se_initialize_rng();
int se_generate_random(void *dst, u32 size); int se_generate_random(void *dst, u32 size);
int se_generate_random_key(u32 ks_dst, u32 ks_src); int se_generate_random_key(u32 ks_dst, u32 ks_src);
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input); int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input);
int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size);
int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size); int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size);
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src); int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src);
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr); int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr);
int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size);
int se_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, const void *src, u32 sec_size); int se_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, const void *src, u32 sec_size);
int se_aes_xts_crypt(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, const void *src, u32 sec_size, u32 num_secs); int se_aes_xts_crypt(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, const void *src, u32 sec_size, u32 num_secs);
int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size); int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size);
@ -47,6 +50,5 @@ 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_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size);
u32 se_rsa_oaep_decode(void *dst, u32 dst_size, const void *label_digest, u32 label_digest_size, u8 *buf, u32 buf_size); u32 se_rsa_oaep_decode(void *dst, u32 dst_size, const void *label_digest, u32 label_digest_size, u8 *buf, u32 buf_size);
void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize);
#endif #endif

View File

@ -1,400 +1,323 @@
/* /*
* Driver for Tegra Security Engine * Copyright (c) 2018 naehrwert
* * Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2011-2013, NVIDIA Corporation. All Rights Reserved. *
* * 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 * under the terms and conditions of the GNU General Public License,
* it under the terms of the GNU General Public License as published by * version 2, as published by the Free Software Foundation.
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. * This program is distributed in the hope it will be useful, but WITHOUT
* * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* This program is distributed in the hope that it will be useful, but WITHOUT * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * more details.
* 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/>.
* You should have received a copy of the GNU General Public License along */
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef _CRYPTO_TEGRA_SE_H #ifndef _SE_T210_H
#define _CRYPTO_TEGRA_SE_H #define _SE_T210_H
#include <utils/types.h> #include <utils/types.h>
#define TEGRA_SE_CRA_PRIORITY 300 #define SE_CRYPTO_QUEUE_LENGTH 50
#define TEGRA_SE_COMPOSITE_PRIORITY 400 #define SE_MAX_SRC_SG_COUNT 50
#define TEGRA_SE_CRYPTO_QUEUE_LENGTH 50 #define SE_MAX_DST_SG_COUNT 50
#define SE_MAX_SRC_SG_COUNT 50
#define SE_MAX_DST_SG_COUNT 50
#define TEGRA_SE_KEYSLOT_COUNT 16 #define SE_AES_KEYSLOT_COUNT 16
#define SE_MAX_LAST_BLOCK_SIZE 0xFFFFF #define SE_RSA_KEYSLOT_COUNT 2
#define SE_MAX_LAST_BLOCK_SIZE 0xFFFFF
#define SE_AES_BLOCK_SIZE 16
#define SE_AES_IV_SIZE 16
#define SE_AES_MIN_KEY_SIZE 16
#define SE_AES_MAX_KEY_SIZE 32
#define SE_KEY_128_SIZE 16
#define SE_KEY_192_SIZE 24
#define SE_KEY_256_SIZE 32
#define SE_SHA_192_SIZE 24
#define SE_SHA_256_SIZE 32
#define SE_SHA_384_SIZE 48
#define SE_SHA_512_SIZE 64
#define SE_RNG_IV_SIZE 16
#define SE_RNG_DT_SIZE 16
#define SE_RNG_KEY_SIZE 16
#define SE_RNG_SEED_SIZE (SE_RNG_IV_SIZE + SE_RNG_KEY_SIZE + SE_RNG_DT_SIZE)
#define SE_AES_CMAC_DIGEST_SIZE 16
#define SE_RSA512_DIGEST_SIZE 64
#define SE_RSA1024_DIGEST_SIZE 128
#define SE_RSA1536_DIGEST_SIZE 192
#define SE_RSA2048_DIGEST_SIZE 256
/* SE register definitions */ /* SE register definitions */
#define SE_SECURITY_0 0x000 #define SE_SE_SECURITY_REG 0x000
#define SE_KEY_SCHED_READ_SHIFT 3 #define SE_HARD_SETTING BIT(0)
#define SE_ENG_DIS BIT(1)
#define SE_PERKEY_SETTING BIT(2)
#define SE_SOFT_SETTING BIT(16)
#define SE_TZRAM_SECURITY_0 0x004 #define SE_TZRAM_SECURITY_REG 0x004
#define SE_TZRAM_HARD_SETTING BIT(0)
#define SE_TZRAM_ENG_DIS BIT(1)
#define SE_CONFIG_REG_OFFSET 0x014 #define SE_OPERATION_REG 0x008
#define SE_CONFIG_ENC_ALG_SHIFT 12 #define SE_OP_ABORT 0
#define SE_CONFIG_DEC_ALG_SHIFT 8 #define SE_OP_START 1
#define ALG_AES_ENC 1 #define SE_OP_RESTART_OUT 2
#define ALG_RNG 2 #define SE_OP_CTX_SAVE 3
#define ALG_SHA 3 #define SE_OP_RESTART_IN 4
#define ALG_RSA 4
#define ALG_NOP 0
#define ALG_AES_DEC 1
#define SE_CONFIG_ENC_ALG(x) ((x) << SE_CONFIG_ENC_ALG_SHIFT)
#define SE_CONFIG_DEC_ALG(x) ((x) << SE_CONFIG_DEC_ALG_SHIFT)
#define SE_CONFIG_DST_SHIFT 2
#define DST_MEMORY 0
#define DST_HASHREG 1
#define DST_KEYTAB 2
#define DST_SRK 3
#define DST_RSAREG 4
#define SE_CONFIG_DST(x) ((x) << SE_CONFIG_DST_SHIFT)
#define SE_CONFIG_ENC_MODE_SHIFT 24
#define SE_CONFIG_DEC_MODE_SHIFT 16
#define MODE_KEY128 0
#define MODE_KEY192 1
#define MODE_KEY256 2
#define MODE_SHA1 0
#define MODE_SHA224 4
#define MODE_SHA256 5
#define MODE_SHA384 6
#define MODE_SHA512 7
#define SE_CONFIG_ENC_MODE(x) ((x) << SE_CONFIG_ENC_MODE_SHIFT)
#define SE_CONFIG_DEC_MODE(x) ((x) << SE_CONFIG_DEC_MODE_SHIFT)
#define SE_RNG_CONFIG_REG_OFFSET 0x340 #define SE_INT_ENABLE_REG 0x00C
#define RNG_MODE_SHIFT 0 #define SE_INT_STATUS_REG 0x010
#define RNG_MODE_NORMAL 0 #define SE_INT_IN_LL_BUF_RD BIT(0)
#define RNG_MODE_FORCE_INSTANTION 1 #define SE_INT_IN_DONE BIT(1)
#define RNG_MODE_FORCE_RESEED 2 #define SE_INT_OUT_LL_BUF_WR BIT(2)
#define SE_RNG_CONFIG_MODE(x) ((x) << RNG_MODE_SHIFT) #define SE_INT_OUT_DONE BIT(3)
#define RNG_SRC_SHIFT 2 #define SE_INT_OP_DONE BIT(4)
#define RNG_SRC_NONE 0 #define SE_INT_RESEED_NEEDED BIT(5)
#define RNG_SRC_ENTROPY 1 #define SE_INT_ERR_STAT BIT(16)
#define RNG_SRC_LFSR 2
#define SE_RNG_CONFIG_SRC(x) ((x) << RNG_SRC_SHIFT)
#define SE_RNG_SRC_CONFIG_REG_OFFSET 0x344 #define SE_CONFIG_REG 0x014
#define RNG_SRC_RO_ENT_SHIFT 1 #define DST_MEMORY 0
#define RNG_SRC_RO_ENT_ENABLE 1 #define DST_HASHREG 1
#define RNG_SRC_RO_ENT_DISABLE 0 #define DST_KEYTABLE 2
#define SE_RNG_SRC_CONFIG_ENT_SRC(x) ((x) << RNG_SRC_RO_ENT_SHIFT) #define DST_SRK 3
#define RNG_SRC_RO_ENT_LOCK_SHIFT 0 #define DST_RSAREG 4
#define RNG_SRC_RO_ENT_LOCK_ENABLE 1 #define SE_CONFIG_DST(x) ((x) << 2)
#define RNG_SRC_RO_ENT_LOCK_DISABLE 0 #define ALG_NOP 0
#define SE_RNG_SRC_CONFIG_ENT_SRC_LOCK(x) ((x) << RNG_SRC_RO_ENT_LOCK_SHIFT) #define ALG_AES_DEC 1
#define SE_CONFIG_DEC_ALG(x) ((x) << 8)
#define ALG_NOP 0
#define ALG_AES_ENC 1
#define ALG_RNG 2
#define ALG_SHA 3
#define ALG_RSA 4
#define SE_CONFIG_ENC_ALG(x) ((x) << 12)
#define MODE_KEY128 0
#define MODE_KEY192 1
#define MODE_KEY256 2
#define MODE_SHA1 0
#define MODE_SHA224 4
#define MODE_SHA256 5
#define MODE_SHA384 6
#define MODE_SHA512 7
#define SE_CONFIG_DEC_MODE(x) ((x) << 16)
#define SE_CONFIG_ENC_MODE(x) ((x) << 24)
#define SE_RNG_RESEED_INTERVAL_REG_OFFSET 0x348 #define SE_IN_LL_ADDR_REG 0x018
#define SE_IN_CUR_BYTE_ADDR_REG 0x01C
#define SE_IN_CUR_LL_ID_REG 0x020
#define SE_OUT_LL_ADDR_REG 0x024
#define SE_OUT_CUR_BYTE_ADDR_REG 0x028
#define SE_OUT_CUR_LL_ID_REG 0x02C
#define SE_KEYTABLE_REG_OFFSET 0x31c #define SE_HASH_RESULT_REG 0x030
#define SE_KEYTABLE_SLOT_SHIFT 4 #define SE_HASH_RESULT_REG_COUNT 16
#define SE_KEYTABLE_SLOT(x) ((x) << SE_KEYTABLE_SLOT_SHIFT)
#define SE_KEYTABLE_QUAD_SHIFT 2
#define QUAD_KEYS_128 0
#define QUAD_KEYS_192 1
#define QUAD_KEYS_256 1
#define QUAD_ORG_IV 2
#define QUAD_UPDTD_IV 3
#define SE_KEYTABLE_QUAD(x) ((x) << SE_KEYTABLE_QUAD_SHIFT)
#define SE_KEYTABLE_OP_TYPE_SHIFT 9
#define OP_READ 0
#define OP_WRITE 1
#define SE_KEYTABLE_OP_TYPE(x) ((x) << SE_KEYTABLE_OP_TYPE_SHIFT)
#define SE_KEYTABLE_TABLE_SEL_SHIFT 8
#define TABLE_KEYIV 0
#define TABLE_SCHEDULE 1
#define SE_KEYTABLE_TABLE_SEL(x) ((x) << SE_KEYTABLE_TABLE_SEL_SHIFT)
#define SE_KEYTABLE_PKT_SHIFT 0
#define SE_KEYTABLE_PKT(x) ((x) << SE_KEYTABLE_PKT_SHIFT)
#define SE_OP_DONE_SHIFT 4 #define SE_CONTEXT_SAVE_CONFIG_REG 0x070
#define OP_DONE 1 #define KEYS_0_3 0
#define SE_OP_DONE(x, y) ((x) && ((y) << SE_OP_DONE_SHIFT)) #define KEYS_4_7 1
#define ORIGINAL_IV 2
#define UPDATED_IV 3
#define SE_CONTEXT_AES_WORD_QUAD(x) ((x) << 0)
#define SE_CONTEXT_AES_KEY_INDEX(x) ((x) << 8)
#define KEYS_0_3 0
#define KEYS_4_7 1
#define KEYS_8_11 2
#define KEYS_12_15 3
#define SE_CONTEXT_RSA_WORD_QUAD(x) ((x) << 12)
#define SLOT0_EXPONENT 0
#define SLOT0_MODULUS 1
#define SLOT1_EXPONENT 2
#define SLOT1_MODULUS 3
#define SE_CONTEXT_RSA_KEY_INDEX(x) ((x) << 16)
#define STICKY_0_3 0
#define STICKY_4_7 1
#define SE_CONTEXT_STICKY_WORD_QUAD(x) ((x) << 24)
#define STICKY_BITS 0
#define RSA_KEYTABLE 1
#define AES_KEYTABLE 2
#define MEM 4
#define SRK 6
#define SE_CONTEXT_SRC(x) ((x) << 29)
#define SE_CRYPTO_LAST_BLOCK 0x080 #define SE_CTX_SAVE_AUTO_T210B01_REG 0x074
#define SE_CTX_SAVE_AUTO_ENABLE BIT(0)
#define SE_CTX_SAVE_AUTO_LOCK BIT(8)
#define SE_CTX_SAVE_AUTO_CURR_CNT_MASK (0x3FF << 16)
#define SE_CRYPTO_REG_OFFSET 0x304 #define SE_CRYPTO_LAST_BLOCK 0x080
#define SE_CRYPTO_HASH_SHIFT 0
#define HASH_DISABLE 0
#define HASH_ENABLE 1
#define SE_CRYPTO_HASH(x) ((x) << SE_CRYPTO_HASH_SHIFT)
#define SE_CRYPTO_XOR_POS_SHIFT 1
#define XOR_BYPASS 0
#define XOR_TOP 2
#define XOR_BOTTOM 3
#define SE_CRYPTO_XOR_POS(x) ((x) << SE_CRYPTO_XOR_POS_SHIFT)
#define SE_CRYPTO_INPUT_SEL_SHIFT 3
#define INPUT_AHB 0
#define INPUT_RANDOM 1
#define INPUT_AESOUT 2
#define INPUT_LNR_CTR 3
#define SE_CRYPTO_INPUT_SEL(x) ((x) << SE_CRYPTO_INPUT_SEL_SHIFT)
#define SE_CRYPTO_VCTRAM_SEL_SHIFT 5
#define VCTRAM_AHB 0
#define VCTRAM_AESOUT 2
#define VCTRAM_PREVAHB 3
#define SE_CRYPTO_VCTRAM_SEL(x) ((x) << SE_CRYPTO_VCTRAM_SEL_SHIFT)
#define SE_CRYPTO_IV_SEL_SHIFT 7
#define IV_ORIGINAL 0
#define IV_UPDATED 1
#define SE_CRYPTO_IV_SEL(x) ((x) << SE_CRYPTO_IV_SEL_SHIFT)
#define SE_CRYPTO_CORE_SEL_SHIFT 8
#define CORE_DECRYPT 0
#define CORE_ENCRYPT 1
#define SE_CRYPTO_CORE_SEL(x) ((x) << SE_CRYPTO_CORE_SEL_SHIFT)
#define SE_CRYPTO_CTR_VAL_SHIFT 11
#define SE_CRYPTO_CTR_VAL(x) ((x) << SE_CRYPTO_CTR_VAL_SHIFT)
#define SE_CRYPTO_KEY_INDEX_SHIFT 24
#define SE_CRYPTO_KEY_INDEX(x) ((x) << SE_CRYPTO_KEY_INDEX_SHIFT)
#define SE_CRYPTO_CTR_CNTN_SHIFT 11
#define SE_CRYPTO_CTR_CNTN(x) ((x) << SE_CRYPTO_CTR_CNTN_SHIFT)
#define SE_CRYPTO_CTR_REG_COUNT 4 #define SE_SHA_CONFIG_REG 0x200
#define SE_CRYPTO_CTR_REG_OFFSET 0x308
#define SE_OPERATION_REG_OFFSET 0x008
#define SE_OPERATION_SHIFT 0
#define OP_ABORT 0
#define OP_START 1
#define OP_RESTART 2
#define OP_CTX_SAVE 3
#define OP_RESTART_IN 4
#define SE_OPERATION(x) ((x) << SE_OPERATION_SHIFT)
#define SE_CONTEXT_SAVE_CONFIG_REG_OFFSET 0x070
#define SE_CONTEXT_SAVE_WORD_QUAD_SHIFT 0
#define KEYS_0_3 0
#define KEYS_4_7 1
#define ORIG_IV 2
#define UPD_IV 3
#define SE_CONTEXT_SAVE_WORD_QUAD(x) ((x) << SE_CONTEXT_SAVE_WORD_QUAD_SHIFT)
#define SE_CONTEXT_SAVE_KEY_INDEX_SHIFT 8
#define SE_CONTEXT_SAVE_KEY_INDEX(x) ((x) << SE_CONTEXT_SAVE_KEY_INDEX_SHIFT)
#define SE_CONTEXT_SAVE_STICKY_WORD_QUAD_SHIFT 24
#define STICKY_0_3 0
#define STICKY_4_7 1
#define SE_CONTEXT_SAVE_STICKY_WORD_QUAD(x) \
((x) << SE_CONTEXT_SAVE_STICKY_WORD_QUAD_SHIFT)
#define SE_CONTEXT_SAVE_SRC_SHIFT 29
#define STICKY_BITS 0
#define KEYTABLE 2
#define MEM 4
#define SRK 6
#define RSA_KEYTABLE 1
#define AES_KEYTABLE 2
#define SE_CONTEXT_SAVE_SRC(x) ((x) << SE_CONTEXT_SAVE_SRC_SHIFT)
#define SE_CONTEXT_SAVE_RSA_KEY_INDEX_SHIFT 16
#define SE_CONTEXT_SAVE_RSA_KEY_INDEX(x) \
((x) << SE_CONTEXT_SAVE_RSA_KEY_INDEX_SHIFT)
#define SE_CONTEXT_RSA_WORD_QUAD_SHIFT 12
#define SE_CONTEXT_RSA_WORD_QUAD(x) \
((x) << SE_CONTEXT_RSA_WORD_QUAD_SHIFT)
#define SE_CTX_SAVE_AUTO 0x074
#define CTX_SAVE_AUTO_ENABLE BIT(0)
#define CTX_SAVE_AUTO_LOCK BIT(8)
#define CTX_SAVE_AUTO_CURR_CNT_MASK (0x3FF << 16)
#define SE_INT_ENABLE_REG_OFFSET 0x00c
#define SE_INT_STATUS_REG_OFFSET 0x010
#define INT_DISABLE 0
#define INT_ENABLE 1
#define INT_UNSET 0
#define INT_SET 1
#define SE_INT_OP_DONE_SHIFT 4
#define SE_INT_OP_DONE(x) ((x) << SE_INT_OP_DONE_SHIFT)
#define SE_INT_ERROR_SHIFT 16
#define SE_INT_ERROR(x) ((x) << SE_INT_ERROR_SHIFT)
#define SE_STATUS_0 0x800
#define SE_STATUS_0_STATE_WAIT_IN 3
#define SE_ERR_STATUS_0 0x804
#define SE_ERR_STATUS_0_SE_NS_ACCESS_CLEAR 0
#define SE_CRYPTO_KEYTABLE_DST_REG_OFFSET 0X330
#define SE_CRYPTO_KEYTABLE_DST_WORD_QUAD_SHIFT 0
#define SE_CRYPTO_KEYTABLE_DST_WORD_QUAD(x) \
((x) << SE_CRYPTO_KEYTABLE_DST_WORD_QUAD_SHIFT)
#define SE_KEY_INDEX_SHIFT 8
#define SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(x) ((x) << SE_KEY_INDEX_SHIFT)
#define SE_IN_LL_ADDR_REG_OFFSET 0x018
#define SE_OUT_LL_ADDR_REG_OFFSET 0x024
#define SE_KEYTABLE_DATA0_REG_OFFSET 0x320
#define SE_KEYTABLE_REG_MAX_DATA 16
#define SE_BLOCK_COUNT_REG_OFFSET 0x318
#define SE_SPARE_0_REG_OFFSET 0x80c
#define SE_SHA_CONFIG_REG_OFFSET 0x200
#define SHA_CONTINUE 0 #define SHA_CONTINUE 0
#define SHA_INIT_HASH 1 #define SHA_INIT_HASH 1
#define SE_SHA_MSG_LENGTH_0_REG_OFFSET 0x204 #define SE_SHA_MSG_LENGTH_0_REG 0x204
#define SE_SHA_MSG_LENGTH_1_REG_OFFSET 0x208 #define SE_SHA_MSG_LENGTH_1_REG 0x208
#define SE_SHA_MSG_LENGTH_2_REG_OFFSET 0x20C #define SE_SHA_MSG_LENGTH_2_REG 0x20C
#define SE_SHA_MSG_LENGTH_3_REG_OFFSET 0x210 #define SE_SHA_MSG_LENGTH_3_REG 0x210
#define SE_SHA_MSG_LEFT_0_REG_OFFSET 0x214 #define SE_SHA_MSG_LEFT_0_REG 0x214
#define SE_SHA_MSG_LEFT_1_REG_OFFSET 0x218 #define SE_SHA_MSG_LEFT_1_REG 0x218
#define SE_SHA_MSG_LEFT_2_REG_OFFSET 0x21C #define SE_SHA_MSG_LEFT_2_REG 0x21C
#define SE_SHA_MSG_LEFT_3_REG_OFFSET 0x220 #define SE_SHA_MSG_LEFT_3_REG 0x220
#define SE_HASH_RESULT_REG_COUNT 16 #define SE_CRYPTO_SECURITY_PERKEY_REG 0x280
#define SE_HASH_RESULT_REG_OFFSET 0x030 #define SE_KEY_LOCK_FLAG 0x80
#define TEGRA_SE_KEY_256_SIZE 32 #define SE_CRYPTO_KEYTABLE_ACCESS_REG 0x284
#define TEGRA_SE_KEY_192_SIZE 24 #define SE_CRYPTO_KEYTABLE_ACCESS_REG_COUNT 16
#define TEGRA_SE_KEY_128_SIZE 16 #define SE_KEY_TBL_DIS_KEYREAD_FLAG BIT(0)
#define TEGRA_SE_AES_BLOCK_SIZE 16 #define SE_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1)
#define TEGRA_SE_AES_MIN_KEY_SIZE 16 #define SE_KEY_TBL_DIS_OIVREAD_FLAG BIT(2)
#define TEGRA_SE_AES_MAX_KEY_SIZE 32 #define SE_KEY_TBL_DIS_OIVUPDATE_FLAG BIT(3)
#define TEGRA_SE_AES_IV_SIZE 16 #define SE_KEY_TBL_DIS_UIVREAD_FLAG BIT(4)
#define TEGRA_SE_SHA_512_SIZE 64 #define SE_KEY_TBL_DIS_UIVUPDATE_FLAG BIT(5)
#define TEGRA_SE_SHA_384_SIZE 48 #define SE_KEY_TBL_DIS_KEYUSE_FLAG BIT(6)
#define TEGRA_SE_SHA_256_SIZE 32 #define SE_KEY_TBL_DIS_KEY_ACCESS_FLAG 0x7F
#define TEGRA_SE_SHA_192_SIZE 24
#define TEGRA_SE_RNG_IV_SIZE 16
#define TEGRA_SE_RNG_DT_SIZE 16
#define TEGRA_SE_RNG_KEY_SIZE 16
#define TEGRA_SE_RNG_SEED_SIZE (TEGRA_SE_RNG_IV_SIZE + \
TEGRA_SE_RNG_KEY_SIZE + \
TEGRA_SE_RNG_DT_SIZE)
#define TEGRA_SE_AES_CMAC_DIGEST_SIZE 16 #define SE_CRYPTO_CONFIG_REG 0x304
#define TEGRA_SE_RSA512_DIGEST_SIZE 64 #define HASH_DISABLE 0
#define TEGRA_SE_RSA1024_DIGEST_SIZE 128 #define HASH_ENABLE 1
#define TEGRA_SE_RSA1536_DIGEST_SIZE 192 #define SE_CRYPTO_HASH(x) ((x) << 0)
#define TEGRA_SE_RSA2048_DIGEST_SIZE 256 #define XOR_BYPASS 0
#define XOR_TOP 2
#define XOR_BOTTOM 3
#define SE_CRYPTO_XOR_POS(x) ((x) << 1)
#define INPUT_MEMORY 0
#define INPUT_RANDOM 1
#define INPUT_AESOUT 2
#define INPUT_LNR_CTR 3
#define SE_CRYPTO_INPUT_SEL(x) ((x) << 3)
#define VCTRAM_MEM 0
#define VCTRAM_AESOUT 2
#define VCTRAM_PREVMEM 3
#define SE_CRYPTO_VCTRAM_SEL(x) ((x) << 5)
#define IV_ORIGINAL 0
#define IV_UPDATED 1
#define SE_CRYPTO_IV_SEL(x) ((x) << 7)
#define CORE_DECRYPT 0
#define CORE_ENCRYPT 1
#define SE_CRYPTO_CORE_SEL(x) ((x) << 8)
#define SE_CRYPTO_KEYSCH_BYPASS BIT(10)
#define SE_CRYPTO_CTR_CNTN(x) ((x) << 11)
#define SE_CRYPTO_KEY_INDEX(x) ((x) << 24)
#define MEMIF_AHB 0
#define MEMIF_MCCIF 1
#define SE_CRYPTO_MEMIF(x) ((x) << 31)
#define SE_KEY_TABLE_ACCESS_LOCK_OFFSET 0x280 #define SE_CRYPTO_LINEAR_CTR_REG 0x308
#define SE_KEY_TBL_DIS_KEY_LOCK_FLAG 0x80 #define SE_CRYPTO_LINEAR_CTR_REG_COUNT 4
#define SE_KEY_TABLE_ACCESS_REG_OFFSET 0x284 #define SE_CRYPTO_BLOCK_COUNT_REG 0x318
#define SE_KEY_TBL_DIS_KEYREAD_FLAG BIT(0)
#define SE_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1)
#define SE_KEY_TBL_DIS_OIVREAD_FLAG BIT(2)
#define SE_KEY_TBL_DIS_OIVUPDATE_FLAG BIT(3)
#define SE_KEY_TBL_DIS_UIVREAD_FLAG BIT(4)
#define SE_KEY_TBL_DIS_UIVUPDATE_FLAG BIT(5)
#define SE_KEY_TBL_DIS_KEYUSE_FLAG BIT(6)
#define SE_KEY_TBL_DIS_KEY_ACCESS_FLAG 0x7F
#define SE_KEY_READ_DISABLE_SHIFT 0 #define SE_CRYPTO_KEYTABLE_ADDR_REG 0x31C
#define SE_KEY_UPDATE_DISABLE_SHIFT 1 #define SE_KEYTABLE_PKT(x) ((x) << 0)
#define KEYS_0_3 0
#define KEYS_4_7 1
#define ORIGINAL_IV 2
#define UPDATED_IV 3
#define SE_KEYTABLE_QUAD(x) ((x) << 2)
#define SE_KEYTABLE_SLOT(x) ((x) << 4)
#define SE_CONTEXT_BUFER_SIZE 1072 #define SE_CRYPTO_KEYTABLE_DATA_REG 0x320
#define SE_CONTEXT_DRBG_BUFER_SIZE 2112
#define SE_CONTEXT_SAVE_RANDOM_DATA_OFFSET 0 #define SE_CRYPTO_KEYTABLE_DST_REG 0x330
#define SE_CONTEXT_SAVE_RANDOM_DATA_SIZE 16 #define KEYS_0_3 0
#define SE_CONTEXT_SAVE_STICKY_BITS_OFFSET \ #define KEYS_4_7 1
(SE_CONTEXT_SAVE_RANDOM_DATA_OFFSET + SE_CONTEXT_SAVE_RANDOM_DATA_SIZE) #define ORIGINAL_IV 2
#define SE_CONTEXT_SAVE_STICKY_BITS_SIZE 16 #define UPDATED_IV 3
#define SE_KEYTABLE_DST_WORD_QUAD(x) ((x) << 0)
#define SE_KEYTABLE_DST_KEY_INDEX(x) ((x) << 8)
#define SE_CONTEXT_SAVE_KEYS_OFFSET (SE_CONTEXT_SAVE_STICKY_BITS_OFFSET + \ #define SE_RNG_CONFIG_REG 0x340
SE_CONTEXT_SAVE_STICKY_BITS_SIZE) #define MODE_NORMAL 0
#define SE11_CONTEXT_SAVE_KEYS_OFFSET (SE_CONTEXT_SAVE_STICKY_BITS_OFFSET + \ #define MODE_FORCE_INSTANTION 1
SE_CONTEXT_SAVE_STICKY_BITS_SIZE + \ #define MODE_FORCE_RESEED 2
SE_CONTEXT_SAVE_STICKY_BITS_SIZE) #define SE_RNG_CONFIG_MODE(x) ((x) << 0)
#define SRC_NONE 0
#define SRC_ENTROPY 1
#define SRC_LFSR 2
#define SE_RNG_CONFIG_SRC(x) ((x) << 2)
#define SE_CONTEXT_SAVE_KEY_LENGTH 512 #define SE_RNG_SRC_CONFIG_REG 0x344
#define SE_CONTEXT_ORIGINAL_IV_OFFSET (SE_CONTEXT_SAVE_KEYS_OFFSET + \ #define RO_ENTR_LOCK_DISABLE 0
SE_CONTEXT_SAVE_KEY_LENGTH) #define RO_ENTR_LOCK_ENABLE 1
#define SE11_CONTEXT_ORIGINAL_IV_OFFSET (SE11_CONTEXT_SAVE_KEYS_OFFSET + \ #define SE_RNG_SRC_CONFIG_ENTR_SRC_LOCK(x) ((x) << 0)
SE_CONTEXT_SAVE_KEY_LENGTH) #define RO_ENTR_DISABLE 0
#define RO_ENTR_ENABLE 1
#define SE_RNG_SRC_CONFIG_ENTR_SRC(x) ((x) << 1)
#define RO_HW_DIS_CYA_DISABLE 0
#define RO_HW_DIS_CYA_ENABLE 1
#define SE_RNG_SRC_CONFIG_HW_DIS_CYA(x) ((x) << 2)
#define SE_RNG_SRC_CONFIG_ENTR_SUBSMPL(x) ((x) << 4)
#define SE_RNG_SRC_CONFIG_ENTR_DATA_FLUSH BIT(8)
#define SE_CONTEXT_ORIGINAL_IV_LENGTH 256 #define SE_RNG_RESEED_INTERVAL_REG 0x348
#define SE_CONTEXT_UPDATED_IV_OFFSET (SE_CONTEXT_ORIGINAL_IV_OFFSET + \ #define SE_RSA_CONFIG 0x400
SE_CONTEXT_ORIGINAL_IV_LENGTH) #define RSA_KEY_SLOT_ONE 0
#define SE11_CONTEXT_UPDATED_IV_OFFSET (SE11_CONTEXT_ORIGINAL_IV_OFFSET + \ #define RSA_KEY_SLOT_TW0 1
SE_CONTEXT_ORIGINAL_IV_LENGTH) #define RSA_KEY_SLOT(x) ((x) << 24)
#define SE_CONTEXT_UPDATED_IV_LENGTH 256 #define SE_RSA_KEY_SIZE_REG 0x404
#define RSA_KEY_WIDTH_512 0
#define RSA_KEY_WIDTH_1024 1
#define RSA_KEY_WIDTH_1536 2
#define RSA_KEY_WIDTH_2048 3
#define SE_CONTEXT_SAVE_KNOWN_PATTERN_OFFSET (SE_CONTEXT_UPDATED_IV_OFFSET + \ #define SE_RSA_EXP_SIZE_REG 0x408
SE_CONTEXT_UPDATED_IV_LENGTH)
#define SE11_CONTEXT_SAVE_KNOWN_PATTERN_OFFSET \
(SE11_CONTEXT_UPDATED_IV_OFFSET + \
SE_CONTEXT_UPDATED_IV_LENGTH)
#define SE_CONTEXT_SAVE_RSA_KEYS_OFFSET SE11_CONTEXT_SAVE_KNOWN_PATTERN_OFFSET #define SE_RSA_SECURITY_PERKEY_REG 0x40C
#define SE_RSA_KEY_LOCK_FLAG 0x80
#define SE_RSA_KEYTABLE_ACCESS_REG 0x410
#define SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG BIT(0)
#define SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1)
#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG BIT(2)
#define SE_RSA_KEY_TBL_DIS_KEY_ACCESS_FLAG 0x7F
#define SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG (SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG | SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG)
#define SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_USE_FLAG (SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG | SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG | SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG)
#define SE_CONTEXT_SAVE_RSA_KEY_LENGTH 1024 #define SE_RSA_KEYTABLE_ADDR_REG 0x420
#define SE_RSA_KEYTABLE_PKT(x) ((x) << 0)
#define RSA_KEY_TYPE_EXP 0
#define RSA_KEY_TYPE_MOD 1
#define SE_RSA_KEYTABLE_TYPE(x) ((x) << 6)
#define RSA_KEY_NUM(x) ((x) << 7)
#define RSA_KEY_INPUT_MODE_REG 0
#define RSA_KEY_INPUT_MODE_DMA 1
#define SE_RSA_KEYTABLE_INPUT_MODE(x) ((x) << 8)
#define RSA_KEY_READ 0
#define RSA_KEY_WRITE 1
#define SE_RSA_KEY_OP(x) ((x) << 10)
#define SE_CONTEXT_SAVE_RSA_KNOWN_PATTERN_OFFSET \ #define SE_RSA_KEYTABLE_DATA_REG 0x424
(SE_CONTEXT_SAVE_RSA_KEYS_OFFSET + SE_CONTEXT_SAVE_RSA_KEY_LENGTH)
#define SE_CONTEXT_KNOWN_PATTERN_SIZE 16 #define SE_RSA_OUTPUT_REG 0x428
#define SE_RSA_OUTPUT_REG_COUNT 64
#define TEGRA_SE_RSA_KEYSLOT_COUNT 2 #define SE_STATUS_REG 0x800
#define SE_STATUS_STATE_IDLE 0
#define SE_STATUS_STATE_BUSY 1
#define SE_STATUS_STATE_WAIT_OUT 2
#define SE_STATUS_STATE_WAIT_IN 3
#define SE_STATUS_STATE_MASK 3
#define SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET 0x40C #define SE_ERR_STATUS_REG 0x804
#define SE_RSA_KEY_TBL_DIS_KEY_LOCK_FLAG 0x80 #define SE_ERR_STATUS_SE_NS_ACCESS BIT(0)
#define SE_ERR_STATUS_BUSY_REG_WR BIT(1)
#define SE_ERR_STATUS_DST BIT(2)
#define SE_ERR_STATUS_SRK_USAGE_LIMIT BIT(3)
#define SE_ERR_STATUS_TZRAM_NS_ACCESS BIT(24)
#define SE_ERR_STATUS_TZRAM_ADDRESS BIT(25)
#define SE_RSA_KEYTABLE_ACCESS_REG_OFFSET 0x410 #define SE_MISC_REG 0x808
#define SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG BIT(0) #define SE_ENTROPY_NEXT_192BIT BIT(0)
#define SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1) #define SE_ENTROPY_VN_BYPASS BIT(1)
#define SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG (SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG | SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG) #define SE_CLK_OVR_ON BIT(2)
#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG BIT(2)
#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG_SHIFT BIT(2)
#define SE_RSA_KEY_TBL_DIS_KEY_ALL_COMMON_FLAG 7
#define SE_RSA_KEY_TBL_DIS_KEY_ALL_FLAG 0x7F
#define SE_RSA_KEYTABLE_ADDR 0x420 #define SE_SPARE_REG 0x80C
#define SE_RSA_KEYTABLE_DATA 0x424 #define SE_ERRATA_FIX_DISABLE 0
#define SE_RSA_OUTPUT 0x428 #define SE_ERRATA_FIX_ENABLE 1
#define SE_ECO(x) ((x) << 0)
#define RSA_KEY_READ 0 #endif
#define RSA_KEY_WRITE 1
#define SE_RSA_KEY_OP_SHIFT 10
#define SE_RSA_KEY_OP(x) ((x) << SE_RSA_KEY_OP_SHIFT)
#define RSA_KEY_INPUT_MODE_REG 0
#define RSA_KEY_INPUT_MODE_DMA 1
#define RSA_KEY_INPUT_MODE_SHIFT 8
#define RSA_KEY_INPUT_MODE(x) ((x) << RSA_KEY_INPUT_MODE_SHIFT)
#define RSA_KEY_SLOT_ONE 0
#define RSA_KEY_SLOT_TW0 1
#define RSA_KEY_NUM_SHIFT 7
#define RSA_KEY_NUM(x) ((x) << RSA_KEY_NUM_SHIFT)
#define RSA_KEY_TYPE_EXP 0
#define RSA_KEY_TYPE_MOD 1
#define RSA_KEY_TYPE_SHIFT 6
#define RSA_KEY_TYPE(x) ((x) << RSA_KEY_TYPE_SHIFT)
#define SE_RSA_KEY_SIZE_REG_OFFSET 0x404
#define SE_RSA_EXP_SIZE_REG_OFFSET 0x408
#define RSA_KEY_SLOT_SHIFT 24
#define RSA_KEY_SLOT(x) ((x) << RSA_KEY_SLOT_SHIFT)
#define SE_RSA_CONFIG 0x400
#define RSA_KEY_PKT_WORD_ADDR_SHIFT 0
#define RSA_KEY_PKT_WORD_ADDR(x) ((x) << RSA_KEY_PKT_WORD_ADDR_SHIFT)
#define RSA_KEY_WORD_ADDR_SHIFT 0
#define RSA_KEY_WORD_ADDR(x) ((x) << RSA_KEY_WORD_ADDR_SHIFT)
#define SE_RSA_KEYTABLE_PKT_SHIFT 0
#define SE_RSA_KEYTABLE_PKT(x) ((x) << SE_RSA_KEYTABLE_PKT_SHIFT)
#endif /* _CRYPTO_TEGRA_SE_H */

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2019 CTCaer * Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2018 balika011 * Copyright (c) 2018 balika011
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
@ -70,7 +70,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
u32 *pkg11_magic_off; u32 *pkg11_magic_off;
bpmp_mmu_disable(); bpmp_mmu_disable();
bpmp_clk_rate_set(BPMP_CLK_NORMAL); bpmp_freq_t prev_fid = bpmp_clk_rate_set(BPMP_CLK_NORMAL);
// Enable clocks. // Enable clocks.
clock_enable_host1x(); clock_enable_host1x();
@ -190,7 +190,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
if (kb == KB_TSEC_FW_EMU_COMPAT) if (kb == KB_TSEC_FW_EMU_COMPAT)
{ {
u32 start = get_tmr_us(); u32 start = get_tmr_us();
u32 k = se[SE_KEYTABLE_DATA0_REG_OFFSET / 4]; u32 k = se[SE_CRYPTO_KEYTABLE_DATA_REG / 4];
u32 key[16] = {0}; u32 key[16] = {0};
u32 kidx = 0; u32 kidx = 0;
@ -198,9 +198,9 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
{ {
smmu_flush_all(); smmu_flush_all();
if (k != se[SE_KEYTABLE_DATA0_REG_OFFSET / 4]) if (k != se[SE_CRYPTO_KEYTABLE_DATA_REG / 4])
{ {
k = se[SE_KEYTABLE_DATA0_REG_OFFSET / 4]; k = se[SE_CRYPTO_KEYTABLE_DATA_REG / 4];
key[kidx++] = k; key[kidx++] = k;
} }
@ -269,7 +269,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_MSB) = 0; SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_MSB) = 0;
SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_LSB) = 0; SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_LSB) = 0;
memcpy(tsec_keys, &buf, 0x10); memcpy(tsec_keys, &buf, SE_KEY_128_SIZE);
} }
out_free:; out_free:;
@ -284,7 +284,7 @@ out:;
clock_disable_sor_safe(); clock_disable_sor_safe();
clock_disable_tsec(); clock_disable_tsec();
bpmp_mmu_enable(); bpmp_mmu_enable();
bpmp_clk_rate_set(BPMP_CLK_DEFAULT_BOOST); bpmp_clk_rate_set(prev_fid);
return res; return res;
} }

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-2020 CTCaer * Copyright (c) 2019-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -212,43 +212,45 @@ const u8 pll_divn[] = {
//95 // BPMP_CLK_DEV_BOOST: 608MHz 49% - 152MHz APB. //95 // BPMP_CLK_DEV_BOOST: 608MHz 49% - 152MHz APB.
}; };
bpmp_freq_t bpmp_clock_set = BPMP_CLK_NORMAL; bpmp_freq_t bpmp_fid_current = BPMP_CLK_NORMAL;
void bpmp_clk_rate_get() void bpmp_clk_rate_get()
{ {
bool clk_src_is_pllp = ((CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) >> 4) & 7) == 3; bool clk_src_is_pllp = ((CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) >> 4) & 7) == 3;
if (clk_src_is_pllp) if (clk_src_is_pllp)
bpmp_clock_set = BPMP_CLK_NORMAL; bpmp_fid_current = BPMP_CLK_NORMAL;
else else
{ {
bpmp_clock_set = BPMP_CLK_HIGH_BOOST; bpmp_fid_current = BPMP_CLK_HIGH_BOOST;
u8 pll_divn_curr = (CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) >> 10) & 0xFF; u8 pll_divn_curr = (CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) >> 10) & 0xFF;
for (u32 i = 1; i < sizeof(pll_divn); i++) for (u32 i = 1; i < sizeof(pll_divn); i++)
{ {
if (pll_divn[i] == pll_divn_curr) if (pll_divn[i] == pll_divn_curr)
{ {
bpmp_clock_set = i; bpmp_fid_current = i;
break; break;
} }
} }
} }
} }
void bpmp_clk_rate_set(bpmp_freq_t fid) bpmp_freq_t bpmp_clk_rate_set(bpmp_freq_t fid)
{ {
bpmp_freq_t prev_fid = bpmp_fid_current;
if (fid > (BPMP_CLK_MAX - 1)) if (fid > (BPMP_CLK_MAX - 1))
fid = BPMP_CLK_MAX - 1; fid = BPMP_CLK_MAX - 1;
if (bpmp_clock_set == fid) if (prev_fid == fid)
return; return prev_fid;
if (fid) if (fid)
{ {
if (bpmp_clock_set) if (prev_fid)
{ {
// Restore to PLLP source during PLLC4 configuration. // Restore to PLLP source during PLLC configuration.
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003333; // PLLP_OUT. CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003333; // PLLP_OUT.
msleep(1); // Wait a bit for clock source change. msleep(1); // Wait a bit for clock source change.
} }
@ -269,7 +271,10 @@ void bpmp_clk_rate_set(bpmp_freq_t fid)
// Disable PLLC to save power. // Disable PLLC to save power.
clock_disable_pllc(); clock_disable_pllc();
} }
bpmp_clock_set = fid; bpmp_fid_current = fid;
// Return old fid in case of temporary swap.
return prev_fid;
} }
// The following functions halt BPMP to reduce power while sleeping. // The following functions halt BPMP to reduce power while sleeping.

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-2020 CTCaer * Copyright (c) 2019-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -53,6 +53,7 @@ typedef enum
BPMP_CLK_MAX BPMP_CLK_MAX
} bpmp_freq_t; } bpmp_freq_t;
#define BPMP_CLK_LOWER_BOOST BPMP_CLK_SUPER_BOOST
#define BPMP_CLK_DEFAULT_BOOST BPMP_CLK_HYPER_BOOST #define BPMP_CLK_DEFAULT_BOOST BPMP_CLK_HYPER_BOOST
void bpmp_mmu_maintenance(u32 op, bool force); void bpmp_mmu_maintenance(u32 op, bool force);
@ -60,7 +61,7 @@ void bpmp_mmu_set_entry(int idx, bpmp_mmu_entry_t *entry, bool apply);
void bpmp_mmu_enable(); void bpmp_mmu_enable();
void bpmp_mmu_disable(); void bpmp_mmu_disable();
void bpmp_clk_rate_get(); void bpmp_clk_rate_get();
void bpmp_clk_rate_set(bpmp_freq_t fid); bpmp_freq_t bpmp_clk_rate_set(bpmp_freq_t fid);
void bpmp_usleep(u32 us); void bpmp_usleep(u32 us);
void bpmp_msleep(u32 ms); void bpmp_msleep(u32 ms);
void bpmp_halt(); void bpmp_halt();

View File

@ -16,7 +16,6 @@
*/ */
#include <soc/ccplex.h> #include <soc/ccplex.h>
#include <soc/fuse.h>
#include <soc/hw_init.h> #include <soc/hw_init.h>
#include <soc/i2c.h> #include <soc/i2c.h>
#include <soc/clock.h> #include <soc/clock.h>
@ -29,27 +28,24 @@
void _ccplex_enable_power_t210() void _ccplex_enable_power_t210()
{ {
u8 tmp = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO); // Get current pinmuxing // Configure GPIO5 and enable output in order to power CPU pmic.
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO, tmp & ~BIT(5)); // Disable GPIO5 pinmuxing. max77620_config_gpio(5, MAX77620_GPIO_OUTPUT_ENABLE);
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO5, MAX77620_CNFG_GPIO_DRV_PUSHPULL | MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH);
// Enable cores power. // Configure CPU pmic.
// 1-3.x: MAX77621_NFSR_ENABLE. // 1-3.x: MAX77621_NFSR_ENABLE.
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL1_REG,
MAX77621_AD_ENABLE | MAX77621_NFSR_ENABLE | MAX77621_SNS_ENABLE | MAX77621_RAMP_12mV_PER_US);
// 1.0.0-3.x: MAX77621_T_JUNCTION_120 | MAX77621_CKKADV_TRIP_DISABLE | MAX77621_INDUCTOR_NOMINAL. // 1.0.0-3.x: MAX77621_T_JUNCTION_120 | MAX77621_CKKADV_TRIP_DISABLE | MAX77621_INDUCTOR_NOMINAL.
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL2_REG, max77621_config_default(REGULATOR_CPU0, MAX77621_CTRL_HOS_CFG);
MAX77621_T_JUNCTION_120 | MAX77621_WDTMR_ENABLE | MAX77621_CKKADV_TRIP_75mV_PER_US| MAX77621_INDUCTOR_NOMINAL);
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_0_95V); // Set voltage and enable cores power.
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_DVS_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_0_95V); max7762x_regulator_set_voltage(REGULATOR_CPU0, 950000);
max7762x_regulator_enable(REGULATOR_CPU0, true);
} }
void _ccplex_enable_power_t210b01() void _ccplex_enable_power_t210b01()
{ {
u8 pmic_cpu_addr = !(FUSE(FUSE_RESERVED_ODM28) & 1) ? MAX77812_PHASE31_CPU_I2C_ADDR : MAX77812_PHASE211_CPU_I2C_ADDR; // Set voltage and enable cores power.
u8 tmp = i2c_recv_byte(I2C_5, pmic_cpu_addr, MAX77812_REG_EN_CTRL); max7762x_regulator_set_voltage(REGULATOR_CPU1, 800000);
i2c_send_byte(I2C_5, pmic_cpu_addr, MAX77812_REG_EN_CTRL, tmp | MAX77812_EN_CTRL_EN_M4); max7762x_regulator_enable(REGULATOR_CPU1, true);
i2c_send_byte(I2C_5, pmic_cpu_addr, MAX77812_REG_M4_VOUT, MAX77812_M4_VOUT_0_80V);
} }
void ccplex_boot_cpu0(u32 entry) void ccplex_boot_cpu0(u32 entry)
@ -62,24 +58,31 @@ void ccplex_boot_cpu0(u32 entry)
else else
_ccplex_enable_power_t210b01(); _ccplex_enable_power_t210b01();
if (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & 0x40000000)) // PLLX_ENABLE. // Enable PLLX and set it to 300 MHz.
if (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & PLLX_BASE_ENABLE)) // PLLX_ENABLE.
{ {
CLOCK(CLK_RST_CONTROLLER_PLLX_MISC_3) &= 0xFFFFFFF7; // Disable IDDQ. CLOCK(CLK_RST_CONTROLLER_PLLX_MISC_3) &= 0xFFFFFFF7; // Disable IDDQ.
usleep(2); usleep(2);
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x80404E02;
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x404E02; // Bypass dividers.
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = PLLX_BASE_BYPASS | (4 << 20) | (78 << 8) | 2; // P div: 4 (5), N div: 78, M div: 2.
// Disable bypass
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = (4 << 20) | (78 << 8) | 2;
// Set PLLX_LOCK_ENABLE.
CLOCK(CLK_RST_CONTROLLER_PLLX_MISC) = (CLOCK(CLK_RST_CONTROLLER_PLLX_MISC) & 0xFFFBFFFF) | 0x40000; CLOCK(CLK_RST_CONTROLLER_PLLX_MISC) = (CLOCK(CLK_RST_CONTROLLER_PLLX_MISC) & 0xFFFBFFFF) | 0x40000;
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x40404E02; // Enable PLLX.
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = PLLX_BASE_ENABLE | (4 << 20) | (78 << 8) | 2;
} }
while (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & 0x8000000)) // Wait for PLL to stabilize.
while (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & PLLX_BASE_LOCK))
; ;
// Configure MSELECT source and enable clock. // Configure MSELECT source and enable clock to 102MHz.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) & 0x1FFFFF00) | 6; CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) & 0x1FFFFF00) | 6;
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) = (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) & ~BIT(CLK_V_MSELECT)) | BIT(CLK_V_MSELECT); CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = BIT(CLK_V_MSELECT);
// Configure initial CPU clock frequency and enable clock. // Configure initial CPU clock frequency and enable clock.
CLOCK(CLK_RST_CONTROLLER_CCLK_BURST_POLICY) = 0x20008888; CLOCK(CLK_RST_CONTROLLER_CCLK_BURST_POLICY) = 0x20008888; // PLLX_OUT0_LJ.
CLOCK(CLK_RST_CONTROLLER_SUPER_CCLK_DIVIDER) = 0x80000000; CLOCK(CLK_RST_CONTROLLER_SUPER_CCLK_DIVIDER) = 0x80000000;
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = BIT(CLK_V_CPUG); CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = BIT(CLK_V_CPUG);
@ -88,12 +91,12 @@ void ccplex_boot_cpu0(u32 entry)
// CAR2PMC_CPU_ACK_WIDTH should be set to 0. // CAR2PMC_CPU_ACK_WIDTH should be set to 0.
CLOCK(CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2) &= 0xFFFFF000; CLOCK(CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2) &= 0xFFFFF000;
// Enable CPU rail. // Enable CPU main rail.
pmc_enable_partition(0, 1); pmc_enable_partition(POWER_RAIL_CRAIL, ENABLE);
// Enable cluster 0 non-CPU rail. // Enable cluster 0 non-CPU rail.
pmc_enable_partition(15, 1); pmc_enable_partition(POWER_RAIL_C0NC, ENABLE);
// Enable CE0 rail. // Enable CPU0 rail.
pmc_enable_partition(14, 1); pmc_enable_partition(POWER_RAIL_CE0, ENABLE);
// Request and wait for RAM repair. // Request and wait for RAM repair.
FLOW_CTLR(FLOW_CTLR_RAM_REPAIR) = 1; FLOW_CTLR(FLOW_CTLR_RAM_REPAIR) = 1;
@ -113,7 +116,7 @@ void ccplex_boot_cpu0(u32 entry)
// MC(MC_TZ_SECURITY_CTRL) = 1; // MC(MC_TZ_SECURITY_CTRL) = 1;
// Clear MSELECT reset. // Clear MSELECT reset.
CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_V) &= ~BIT(CLK_V_MSELECT); CLOCK(CLK_RST_CONTROLLER_RST_DEV_V_CLR) = BIT(CLK_V_MSELECT);
// Clear NONCPU reset. // Clear NONCPU reset.
CLOCK(CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR) = 0x20000000; CLOCK(CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR) = 0x20000000;
// Clear CPU0 reset. // Clear CPU0 reset.

View File

@ -21,6 +21,23 @@
#include <storage/sdmmc.h> #include <storage/sdmmc.h>
#include <utils/util.h> #include <utils/util.h>
typedef struct _clock_osc_t
{
u32 freq;
u16 min;
u16 max;
} clock_osc_t;
static const clock_osc_t _clock_osc_cnt[] = {
{ 12000, 706, 757 },
{ 13000, 766, 820 },
{ 16800, 991, 1059 },
{ 19200, 1133, 1210 },
{ 26000, 1535, 1638 },
{ 38400, 2268, 2418 },
{ 48000, 2836, 3023 }
};
/* clock_t: reset, enable, source, index, clk_src, clk_div */ /* clock_t: reset, enable, source, index, clk_src, clk_div */
static const clock_t _clock_uart[] = { static const clock_t _clock_uart[] = {
@ -42,7 +59,7 @@ static const clock_t _clock_i2c[] = {
}; };
static clock_t _clock_se = { static clock_t _clock_se = {
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_SE, CLK_V_SE, 0, 0 CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_SE, CLK_V_SE, 0, 0 // 408MHz.
}; };
static clock_t _clock_tzram = { static clock_t _clock_tzram = {
@ -50,19 +67,19 @@ static clock_t _clock_tzram = {
}; };
static clock_t _clock_host1x = { static clock_t _clock_host1x = {
CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X, CLK_L_HOST1X, 4, 3 CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X, CLK_L_HOST1X, 4, 3 // 163.2MHz.
}; };
static clock_t _clock_tsec = { static clock_t _clock_tsec = {
CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_TSEC, CLK_U_TSEC, 0, 2 CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_TSEC, CLK_U_TSEC, 0, 2 // 204MHz.
}; };
static clock_t _clock_sor_safe = { static clock_t _clock_sor_safe = {
CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_NO_SOURCE, CLK_Y_SOR_SAFE, 0, 0 CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_NO_SOURCE, CLK_Y_SOR_SAFE, 0, 0
}; };
static clock_t _clock_sor0 = { static clock_t _clock_sor0 = {
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_NO_SOURCE, CLK_X_SOR0, 0, 0 CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_NOT_USED, CLK_X_SOR0, 0, 0
}; };
static clock_t _clock_sor1 = { static clock_t _clock_sor1 = {
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_SOR1, CLK_X_SOR1, 0, 2 CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_SOR1, CLK_X_SOR1, 0, 2 //204MHz.
}; };
static clock_t _clock_kfuse = { static clock_t _clock_kfuse = {
CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_KFUSE, 0, 0 CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_KFUSE, 0, 0
@ -72,11 +89,11 @@ static clock_t _clock_cl_dvfs = {
CLK_RST_CONTROLLER_RST_DEVICES_W, CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_NO_SOURCE, CLK_W_DVFS, 0, 0 CLK_RST_CONTROLLER_RST_DEVICES_W, CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_NO_SOURCE, CLK_W_DVFS, 0, 0
}; };
static clock_t _clock_coresight = { static clock_t _clock_coresight = {
CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_CSITE, CLK_U_CSITE, 0, 4 CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_CSITE, CLK_U_CSITE, 0, 4 // 136MHz.
}; };
static clock_t _clock_pwm = { static clock_t _clock_pwm = {
CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, CLK_L_PWM, 6, 4 // Fref: 6.4MHz. Stock PLLP / 54: 7.55MHz. CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, CLK_L_PWM, 6, 4 // Fref: 6.4MHz. HOS: PLLP / 54 = 7.55MHz.
}; };
static clock_t _clock_sdmmc_legacy_tm = { static clock_t _clock_sdmmc_legacy_tm = {
@ -218,13 +235,13 @@ void clock_disable_sor1()
void clock_enable_kfuse() void clock_enable_kfuse()
{ {
u32 kfuse_clk_unmask = ~BIT(CLK_H_KFUSE); CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = BIT(CLK_H_KFUSE);
CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) = (CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) & kfuse_clk_unmask) | BIT(CLK_H_KFUSE); CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_CLR) = BIT(CLK_H_KFUSE);
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) &= kfuse_clk_unmask; CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_KFUSE);
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) = (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) & kfuse_clk_unmask) | BIT(CLK_H_KFUSE); usleep(10); // Wait 10s to prevent glitching.
usleep(10);
CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) &= kfuse_clk_unmask; CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_KFUSE);
usleep(20); usleep(20); // Wait 20s fo kfuse hw to init.
} }
void clock_disable_kfuse() void clock_disable_kfuse()
@ -721,3 +738,44 @@ void clock_sdmmc_disable(u32 id)
_clock_sdmmc_is_reset(id); _clock_sdmmc_is_reset(id);
_clock_disable_pllc4(BIT(id)); _clock_disable_pllc4(BIT(id));
} }
u32 clock_get_osc_freq()
{
CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET) = OSC_FREQ_DET_TRIG | (2 - 1); // 2 periods of 32.76KHz window.
while (CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_BUSY)
;
u32 cnt = (CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_CNT);
CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET) = 0;
// Return frequency in KHz.
for (u32 i = 0; i < ARRAY_SIZE(_clock_osc_cnt); i++)
if (cnt >= _clock_osc_cnt[i].min && cnt <= _clock_osc_cnt[i].max)
return _clock_osc_cnt[i].freq;
return 0;
}
u32 clock_get_dev_freq(clock_pto_id_t id)
{
u32 val = ((id & PTO_SRC_SEL_MASK) << PTO_SRC_SEL_SHIFT) | PTO_DIV_SEL_DIV1 | PTO_CLK_ENABLE | (16 - 1); // 16 periods of 32.76KHz window.
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val;
usleep(2);
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val | PTO_CNT_RST;
usleep(2);
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val;
usleep(2);
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val | PTO_CNT_EN;
usleep(502);
while (CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_STATUS) & PTO_CLK_CNT_BUSY)
;
u32 cnt = CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_STATUS) & PTO_CLK_CNT;
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = 0;
u32 freq = ((cnt << 8) | 0x3E) / 125;
return freq;
}

View File

@ -35,6 +35,10 @@
#define CLK_RST_CONTROLLER_CLK_SYSTEM_RATE 0x30 #define CLK_RST_CONTROLLER_CLK_SYSTEM_RATE 0x30
#define CLK_RST_CONTROLLER_MISC_CLK_ENB 0x48 #define CLK_RST_CONTROLLER_MISC_CLK_ENB 0x48
#define CLK_RST_CONTROLLER_OSC_CTRL 0x50 #define CLK_RST_CONTROLLER_OSC_CTRL 0x50
#define CLK_RST_CONTROLLER_OSC_FREQ_DET 0x58
#define CLK_RST_CONTROLLER_OSC_FREQ_DET_STATUS 0x5C
#define CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL 0x60
#define CLK_RST_CONTROLLER_PTO_CLK_CNT_STATUS 0x64
#define CLK_RST_CONTROLLER_PLLC_BASE 0x80 #define CLK_RST_CONTROLLER_PLLC_BASE 0x80
#define CLK_RST_CONTROLLER_PLLC_OUT 0x84 #define CLK_RST_CONTROLLER_PLLC_OUT 0x84
#define CLK_RST_CONTROLLER_PLLC_MISC 0x88 #define CLK_RST_CONTROLLER_PLLC_MISC 0x88
@ -156,11 +160,18 @@
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTAPE 0x710 #define CLK_RST_CONTROLLER_CLK_SOURCE_UARTAPE 0x710
#define CLK_NO_SOURCE 0x0 #define CLK_NO_SOURCE 0x0
#define CLK_NOT_USED 0x0
/*! PLL control and status bits */ /*! PLL control and status bits */
#define PLLX_BASE_LOCK BIT(27)
#define PLLX_BASE_REF_DIS BIT(29)
#define PLLX_BASE_ENABLE BIT(30)
#define PLLX_BASE_BYPASS BIT(31)
#define PLLCX_BASE_LOCK BIT(27) #define PLLCX_BASE_LOCK BIT(27)
#define PLLCX_BASE_REF_DIS BIT(29) #define PLLCX_BASE_REF_DIS BIT(29)
#define PLLCX_BASE_ENABLE BIT(30) #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)
@ -178,6 +189,140 @@
#define UTMIPLL_LOCK BIT(31) #define UTMIPLL_LOCK BIT(31)
/*! PTO_CLK_CNT */
#define PTO_REF_CLK_WIN_CFG_MASK 0xF
#define PTO_REF_CLK_WIN_CFG_16P 0xF
#define PTO_CNT_EN BIT(9)
#define PTO_CNT_RST BIT(10)
#define PTO_CLK_ENABLE BIT(13)
#define PTO_SRC_SEL_SHIFT 14
#define PTO_SRC_SEL_MASK 0x1FF
#define PTO_DIV_SEL_MASK (3 << 23)
#define PTO_DIV_SEL_GATED (0 << 23)
#define PTO_DIV_SEL_DIV1 (1 << 23)
#define PTO_DIV_SEL_DIV2_RISING (2 << 23)
#define PTO_DIV_SEL_DIV2_FALLING (3 << 23)
#define PTO_DIV_SEL_CPU_EARLY (0 << 23)
#define PTO_DIV_SEL_CPU_LATE (1 << 23)
#define PTO_CLK_CNT_BUSY BIT(31)
#define PTO_CLK_CNT 0xFFFFFF
/*! OSC_FREQ_DET */
#define OSC_REF_CLK_WIN_CFG_MASK 0xF
#define OSC_FREQ_DET_TRIG BIT(31)
#define OSC_FREQ_DET_BUSY BIT(31)
#define OSC_FREQ_DET_CNT 0xFFFF
/*! PLLs omitted as they need PTO enabled in MISC registers. Norm div is 2. */
typedef enum _clock_pto_id_t
{
CLK_PTO_PCLK_SYS = 0x06,
CLK_PTO_HCLK_SYS = 0x07,
CLK_PTO_UTMIP_240 = 0x0C,
CLK_PTO_CCLK_G = 0x12,
CLK_PTO_CCLK_G_DIV2 = 0x13,
CLK_PTO_SPI1 = 0x17,
CLK_PTO_SPI2 = 0x18,
CLK_PTO_SPI3 = 0x19,
CLK_PTO_SPI4 = 0x1A,
CLK_PTO_MAUD = 0x1B,
CLK_PTO_SCLK = 0x1C,
CLK_PTO_SDMMC1 = 0x20,
CLK_PTO_SDMMC2 = 0x21,
CLK_PTO_SDMMC3 = 0x22,
CLK_PTO_SDMMC4 = 0x23,
CLK_PTO_EMC = 0x24,
CLK_PTO_MSELECT = 0x2F,
CLK_PTO_VIC = 0x36,
CLK_PTO_NVDEC = 0x39,
CLK_PTO_NVENC = 0x3A,
CLK_PTO_NVJPG = 0x3B,
CLK_PTO_TSEC = 0x3C,
CLK_PTO_TSECB = 0x3D,
CLK_PTO_SE = 0x3E,
CLK_PTO_DSIA_LP = 0x62,
CLK_PTO_ISP = 0x64,
CLK_PTO_MC = 0x6A,
CLK_PTO_ACTMON = 0x6B,
CLK_PTO_CSITE = 0x6C,
CLK_PTO_HOST1X = 0x6F,
CLK_PTO_SE_2 = 0x74, // Same as CLK_PTO_SE.
CLK_PTO_SOC_THERM = 0x75,
CLK_PTO_TSEC_2 = 0x77, // Same as CLK_PTO_TSEC.
CLK_PTO_ACLK = 0x7C,
CLK_PTO_QSPI = 0x7D,
CLK_PTO_I2S1 = 0x80,
CLK_PTO_I2S2 = 0x81,
CLK_PTO_I2S3 = 0x82,
CLK_PTO_I2S4 = 0x83,
CLK_PTO_I2S5 = 0x84,
CLK_PTO_AHUB = 0x85,
CLK_PTO_APE = 0x86,
CLK_PTO_DVFS_SOC = 0x88,
CLK_PTO_DVFS_REF = 0x89,
CLK_PTO_SPDIF = 0x8F,
CLK_PTO_SPDIF_IN = 0x90,
CLK_PTO_UART_FST_MIPI_CAL = 0x91,
CLK_PTO_PWM = 0x93,
CLK_PTO_I2C1 = 0x94,
CLK_PTO_I2C2 = 0x95,
CLK_PTO_I2C3 = 0x96,
CLK_PTO_I2C4 = 0x97,
CLK_PTO_I2C5 = 0x98,
CLK_PTO_I2C6 = 0x99,
CLK_PTO_I2C_SLOW = 0x9A,
CLK_PTO_UARTAPE = 0x9B,
CLK_PTO_EXTPERIPH1 = 0x9D,
CLK_PTO_EXTPERIPH2 = 0x9E,
CLK_PTO_ENTROPY = 0xA0,
CLK_PTO_UARTA = 0xA1,
CLK_PTO_UARTB = 0xA2,
CLK_PTO_UARTC = 0xA3,
CLK_PTO_UARTD = 0xA4,
CLK_PTO_OWR = 0xA5,
CLK_PTO_HDA2CODEC_2X = 0xA7,
CLK_PTO_HDA = 0xA8,
CLK_PTO_SDMMC_LEGACY_TM = 0xAB,
CLK_PTO_SOR0 = 0xC0,
CLK_PTO_SOR1 = 0xC1,
CLK_PTO_DISP2 = 0xC4,
CLK_PTO_DISP1 = 0xC5,
CLK_PTO_XUSB_FALCON = 0x110,
CLK_PTO_XUSB_FS = 0x136,
CLK_PTO_XUSB_SS_HOST_DEV = 0x137,
CLK_PTO_XUSB_CORE_HOST = 0x138,
CLK_PTO_XUSB_CORE_DEV = 0x139,
} clock_pto_id_t;
/* /*
* CLOCK Peripherals: * CLOCK Peripherals:
* L 0 - 31 * L 0 - 31
@ -216,7 +361,7 @@ enum CLK_L_DEV
CLK_L_USBD = 22, CLK_L_USBD = 22,
CLK_L_ISP = 23, CLK_L_ISP = 23,
CLK_L_3D = 24, // HIDDEN. CLK_L_3D = 24, // HIDDEN.
//CLK_L_ = 25, CLK_L_IDE = 25, // RESERVED.
CLK_L_DISP2 = 26, CLK_L_DISP2 = 26,
CLK_L_DISP1 = 27, CLK_L_DISP1 = 27,
CLK_L_HOST1X = 28, CLK_L_HOST1X = 28,
@ -244,11 +389,11 @@ enum CLK_H_DEV
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_ = 17, CLK_H_TVO = 17, // RESERVED.
CLK_H_HSI = 18, // HIDDEN. CLK_H_HSI = 18, // HIDDEN.
CLK_H_HDMI = 19, // HIDDEN. CLK_H_HDMI = 19, // HIDDEN.
CLK_H_CSI = 20, CLK_H_CSI = 20,
//CLK_H_ = 21, 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,
@ -263,14 +408,14 @@ enum CLK_H_DEV
enum CLK_U_DEV enum CLK_U_DEV
{ {
//CLK_U_ = 0, CLK_U_SPEEDO = 0, // RESERVED.
CLK_U_UARTD = 1, CLK_U_UARTD = 1,
CLK_U_UARTE = 2, // HIDDEN. 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_UNUSED = 7, // RESERVED 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.
@ -444,9 +589,9 @@ enum CLK_Y_DEV
/*! Generic clock descriptor. */ /*! Generic clock descriptor. */
typedef struct _clock_t typedef struct _clock_t
{ {
u32 reset; u16 reset;
u32 enable; u16 enable;
u32 source; u16 source;
u8 index; u8 index;
u8 clk_src; u8 clk_src;
u8 clk_div; u8 clk_div;
@ -494,4 +639,7 @@ int clock_sdmmc_is_not_reset_and_enabled(u32 id);
void clock_sdmmc_enable(u32 id, u32 val); void clock_sdmmc_enable(u32 id, u32 val);
void clock_sdmmc_disable(u32 id); void clock_sdmmc_disable(u32 id);
u32 clock_get_osc_freq();
u32 clock_get_dev_freq(clock_pto_id_t id);
#endif #endif

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 CTCaer * Copyright (c) 2019-2020 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,
@ -76,6 +76,35 @@ u32 fuse_read_odm_keygen_rev()
return 0; return 0;
} }
u32 fuse_read_dramid(bool raw_id)
{
u32 dramid = (fuse_read_odm(4) & 0xF8) >> 3;
if (raw_id)
return dramid;
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210)
{
if (dramid > 6)
dramid = 0;
}
else
{
if (dramid > 27)
dramid = 8;
}
return dramid;
}
u32 fuse_read_hw_state()
{
if ((fuse_read_odm(4) & 3) != 3)
return FUSE_NX_HW_STATE_PROD;
else
return FUSE_NX_HW_STATE_DEV;
}
u32 fuse_read_hw_type() u32 fuse_read_hw_type()
{ {
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01) if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01)
@ -118,6 +147,7 @@ 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_ADDR) & ~FUSE_CMD_MASK) | FUSE_READ;
fuse_wait_idle(); fuse_wait_idle();
return FUSE(FUSE_RDATA); return FUSE(FUSE_RDATA);
} }

View File

@ -2,6 +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-2020 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 +65,10 @@
#define FUSE_OPT_X_COORDINATE 0x214 #define FUSE_OPT_X_COORDINATE 0x214
#define FUSE_OPT_Y_COORDINATE 0x218 #define FUSE_OPT_Y_COORDINATE 0x218
#define FUSE_GPU_IDDQ_CALIB 0x228 #define FUSE_GPU_IDDQ_CALIB 0x228
#define FUSE_RESERVED_ODM28 0x240
#define FUSE_USB_CALIB_EXT 0x350 #define FUSE_USB_CALIB_EXT 0x350
#define FUSE_RESERVED_ODM28_T210B01 0x240
/*! Fuse commands. */ /*! Fuse commands. */
#define FUSE_READ 0x1 #define FUSE_READ 0x1
#define FUSE_WRITE 0x2 #define FUSE_WRITE 0x2
@ -83,9 +85,17 @@ enum
FUSE_NX_HW_TYPE_HOAG FUSE_NX_HW_TYPE_HOAG
}; };
enum
{
FUSE_NX_HW_STATE_PROD,
FUSE_NX_HW_STATE_DEV
};
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_dramid(bool raw_id);
u32 fuse_read_hw_state();
u32 fuse_read_hw_type(); u32 fuse_read_hw_type();
u8 fuse_count_burnt(u32 val); u8 fuse_count_burnt(u32 val);
void fuse_wait_idle(); void fuse_wait_idle();

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer * Copyright (c) 2018-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -18,7 +18,7 @@
#include <string.h> #include <string.h>
#include <soc/hw_init.h> #include <soc/hw_init.h>
#include <gfx/di.h> #include <display/di.h>
#include <input/joycon.h> #include <input/joycon.h>
#include <input/touch.h> #include <input/touch.h>
#include <sec/se.h> #include <sec/se.h>
@ -42,6 +42,7 @@
#include <storage/nx_sd.h> #include <storage/nx_sd.h>
#include <storage/sdmmc.h> #include <storage/sdmmc.h>
#include <thermal/fan.h> #include <thermal/fan.h>
#include <thermal/tmp451.h>
#include <utils/util.h> #include <utils/util.h>
extern boot_cfg_t b_cfg; extern boot_cfg_t b_cfg;
@ -87,6 +88,7 @@ static void _config_oscillators()
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // Set HCLK div to 1 and PCLK div to 3. CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // Set HCLK div to 1 and PCLK div to 3.
} }
// The uart is skipped for Copper, Hoag and Calcio. Used in Icosa, Iowa and Aula.
static void _config_gpios(bool nx_hoag) static void _config_gpios(bool nx_hoag)
{ {
// Clamp inputs when tristated. // Clamp inputs when tristated.
@ -263,7 +265,7 @@ static void _config_se_brom()
FUSE(FUSE_PRIVATE_KEY3) FUSE(FUSE_PRIVATE_KEY3)
}; };
// Set SBK to slot 14. // Set SBK to slot 14.
se_aes_key_set(14, sbk, 0x10); se_aes_key_set(14, sbk, SE_KEY_128_SIZE);
// Lock SBK from being read. // Lock SBK from being read.
se_key_acc_ctrl(14, SE_KEY_TBL_DIS_KEYREAD_FLAG); se_key_acc_ctrl(14, SE_KEY_TBL_DIS_KEYREAD_FLAG);
@ -275,7 +277,7 @@ static void _config_se_brom()
// This memset needs to happen here, else TZRAM will behave weirdly later on. // This memset needs to happen here, else TZRAM will behave weirdly later on.
memset((void *)TZRAM_BASE, 0, 0x10000); memset((void *)TZRAM_BASE, 0, 0x10000);
PMC(APBDEV_PMC_CRYPTO_OP) = PMC_CRYPTO_OP_SE_ENABLE; PMC(APBDEV_PMC_CRYPTO_OP) = PMC_CRYPTO_OP_SE_ENABLE;
SE(SE_INT_STATUS_REG_OFFSET) = 0x1F; SE(SE_INT_STATUS_REG) = 0x1F; // Clear all SE interrupts.
// Clear the boot reason to avoid problems later // Clear the boot reason to avoid problems later
PMC(APBDEV_PMC_SCRATCH200) = 0x0; PMC(APBDEV_PMC_SCRATCH200) = 0x0;
@ -285,17 +287,21 @@ static void _config_se_brom()
static void _config_regulators(bool tegra_t210) static void _config_regulators(bool tegra_t210)
{ {
// Set RTC/AO domain to POR voltage.
if (tegra_t210)
max7762x_regulator_set_voltage(REGULATOR_LDO4, 1000000);
// Disable low battery shutdown monitor. // Disable low battery shutdown monitor.
max77620_low_battery_monitor_config(false); max77620_low_battery_monitor_config(false);
// Disable SDMMC1 IO power. // Disable SDMMC1 IO power.
gpio_write(GPIO_PORT_E, GPIO_PIN_4, GPIO_LOW); gpio_write(GPIO_PORT_E, GPIO_PIN_4, GPIO_LOW);
max77620_regulator_enable(REGULATOR_LDO2, 0); max7762x_regulator_enable(REGULATOR_LDO2, false);
sd_power_cycle_time_start = get_tmr_ms(); sd_power_cycle_time_start = get_tmr_ms();
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CNFGBBC, MAX77620_CNFGBBC_RESISTOR_1K); i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CNFGBBC, MAX77620_CNFGBBC_RESISTOR_1K);
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1,
BIT(6) | (3 << MAX77620_ONOFFCNFG1_MRT_SHIFT)); // PWR delay for forced shutdown off. MAX77620_ONOFFCNFG1_RSVD | (3 << MAX77620_ONOFFCNFG1_MRT_SHIFT)); // PWR delay for forced shutdown off.
if (tegra_t210) if (tegra_t210)
{ {
@ -313,28 +319,18 @@ static void _config_regulators(bool tegra_t210)
(4 << MAX77620_FPS_TIME_PERIOD_SHIFT) | (2 << MAX77620_FPS_PD_PERIOD_SHIFT)); // 3.x+ (4 << MAX77620_FPS_TIME_PERIOD_SHIFT) | (2 << MAX77620_FPS_PD_PERIOD_SHIFT)); // 3.x+
// Set vdd_core voltage to 1.125V. // Set vdd_core voltage to 1.125V.
max77620_regulator_set_voltage(REGULATOR_SD0, 1125000); max7762x_regulator_set_voltage(REGULATOR_SD0, 1125000);
// Fix CPU/GPU after a L4T warmboot. // Fix CPU/GPU after L4T warmboot.
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO5, 2); max77620_config_gpio(5, MAX77620_GPIO_OUTPUT_DISABLE);
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO6, 2); max77620_config_gpio(6, MAX77620_GPIO_OUTPUT_DISABLE);
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_REG, MAX77621_VOUT_0_95V); // Disable power. // Set POR configuration.
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_DVS_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_1_09V); // Enable DVS power. max77621_config_default(REGULATOR_CPU0, MAX77621_CTRL_POR_CFG);
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL1_REG, MAX77621_RAMP_50mV_PER_US); max77621_config_default(REGULATOR_GPU0, MAX77621_CTRL_POR_CFG);
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL2_REG,
MAX77621_T_JUNCTION_120 | MAX77621_FT_ENABLE | MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS |
MAX77621_CKKADV_TRIP_150mV_PER_US | MAX77621_INDUCTOR_NOMINAL);
i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_VOUT_REG, MAX77621_VOUT_0_95V); // Disable power.
i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_VOUT_DVS_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_1_09V); // Enable DVS power.
i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_CONTROL1_REG, MAX77621_RAMP_50mV_PER_US);
i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_CONTROL2_REG,
MAX77621_T_JUNCTION_120 | MAX77621_FT_ENABLE | MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS |
MAX77621_CKKADV_TRIP_150mV_PER_US | MAX77621_INDUCTOR_NOMINAL);
} }
else // Tegra X1+ set vdd_core voltage to 1.05V. else // Tegra X1+ set vdd_core voltage to 1.05V.
max77620_regulator_set_voltage(REGULATOR_SD0, 1050000); max7762x_regulator_set_voltage(REGULATOR_SD0, 1050000);
} }
void hw_init() void hw_init()
@ -373,7 +369,8 @@ void hw_init()
#ifdef DEBUG_UART_PORT #ifdef DEBUG_UART_PORT
clock_enable_uart(DEBUG_UART_PORT); clock_enable_uart(DEBUG_UART_PORT);
uart_init(DEBUG_UART_PORT, 115200); uart_init(DEBUG_UART_PORT, DEBUG_UART_BAUDRATE);
uart_invert(DEBUG_UART_PORT, DEBUG_UART_INVERT, UART_INVERT_TXD);
#endif #endif
// Enable Dynamic Voltage and Frequency Scaling device clock. // Enable Dynamic Voltage and Frequency Scaling device clock.
@ -391,17 +388,20 @@ void hw_init()
//! TODO: Why? Device is NFC MCU on Lite. //! TODO: Why? Device is NFC MCU on Lite.
if (nx_hoag) if (nx_hoag)
max77620_regulator_set_volt_and_flags(REGULATOR_LDO8, 2800000, MAX77620_POWER_MODE_NORMAL); {
max7762x_regulator_set_voltage(REGULATOR_LDO8, 2800000);
max7762x_regulator_enable(REGULATOR_LDO8, true);
}
// Initialize I2C1 for various power related devices. // Initialize I2C1 for various power related devices.
i2c_init(I2C_1); i2c_init(I2C_1);
// Enable charger in case it's disabled.
bq24193_enable_charger();
// Initialize various regulators based on Erista/Mariko platform. // Initialize various regulators based on Erista/Mariko platform.
_config_regulators(tegra_t210); _config_regulators(tegra_t210);
// Enable charger in case it's disabled.
bq24193_enable_charger();
_config_pmc_scratch(); // Missing from 4.x+ _config_pmc_scratch(); // Missing from 4.x+
// Set BPMP/SCLK to PLLP_OUT (408MHz). // Set BPMP/SCLK to PLLP_OUT (408MHz).
@ -421,19 +421,18 @@ void hw_init()
bpmp_mmu_enable(); bpmp_mmu_enable();
} }
void hw_reinit_workaround(bool extra_reconfig, u32 magic) void hw_reinit_workaround(bool coreboot, u32 bl_magic)
{ {
// Disable BPMP max clock. // Disable BPMP max clock.
bpmp_clk_rate_set(BPMP_CLK_NORMAL); bpmp_clk_rate_set(BPMP_CLK_NORMAL);
#ifdef NYX #ifdef NYX
// Deinit touchscreen, 5V regulators and Joy-Con. // Disable temperature sensor, touchscreen, 5V regulators and Joy-Con.
touch_power_off(); tmp451_end();
set_fan_duty(0); set_fan_duty(0);
touch_power_off();
jc_deinit(); jc_deinit();
regulator_disable_5v(REGULATOR_5V_ALL); regulator_5v_disable(REGULATOR_5V_ALL);
clock_disable_uart(UART_B);
clock_disable_uart(UART_C);
#endif #endif
// Flush/disable MMU cache and set DRAM clock to 204MHz. // Flush/disable MMU cache and set DRAM clock to 204MHz.
@ -445,10 +444,10 @@ void hw_reinit_workaround(bool extra_reconfig, u32 magic)
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= BIT(CLK_V_AHUB); CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= BIT(CLK_V_AHUB);
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= BIT(CLK_Y_APE); CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= BIT(CLK_Y_APE);
if (extra_reconfig) // Do coreboot mitigations.
if (coreboot)
{ {
msleep(10); msleep(10);
PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_SDMMC1_IO_EN;
clock_disable_cl_dvfs(); clock_disable_cl_dvfs();
@ -457,13 +456,27 @@ void hw_reinit_workaround(bool extra_reconfig, u32 magic)
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO); gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO);
gpio_config(GPIO_PORT_E, GPIO_PIN_6, GPIO_MODE_SPIO); gpio_config(GPIO_PORT_E, GPIO_PIN_6, GPIO_MODE_SPIO);
gpio_config(GPIO_PORT_H, GPIO_PIN_6, GPIO_MODE_SPIO); gpio_config(GPIO_PORT_H, GPIO_PIN_6, GPIO_MODE_SPIO);
// Reinstate SD controller power.
PMC(APBDEV_PMC_NO_IOPOWER) &= ~(PMC_NO_IOPOWER_SDMMC1_IO_EN);
} }
// Power off display. // Seamless display or display power off.
display_end(); switch (bl_magic)
{
case BL_MAGIC_CRBOOT_SLD:;
// Set pwm to 0%, switch to gpio mode and restore pwm duty.
u32 brightness = display_get_backlight_brightness();
display_backlight_brightness(0, 1000);
gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_GPIO);
display_backlight_brightness(brightness, 0);
break;
default:
display_end();
}
// Enable clock to USBD and init SDMMC1 to avoid hangs with bad hw inits. // Enable clock to USBD and init SDMMC1 to avoid hangs with bad hw inits.
if (magic == 0xBAADF00D) if (bl_magic == BL_MAGIC_BROKEN_HWI)
{ {
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_USBD); CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_USBD);
sdmmc_init(&sd_sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID, 0); sdmmc_init(&sd_sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID, 0);

View File

@ -20,8 +20,11 @@
#include <utils/types.h> #include <utils/types.h>
#define BL_MAGIC_CRBOOT_SLD 0x30444C53 // SLD0, seamless display type 0.
#define BL_MAGIC_BROKEN_HWI 0xBAADF00D // Broken hwinit.
void hw_init(); void hw_init();
void hw_reinit_workaround(bool extra_reconfig, u32 magic); void hw_reinit_workaround(bool coreboot, u32 magic);
u32 hw_get_chip_id(); u32 hw_get_chip_id();
#endif #endif

View File

@ -136,10 +136,10 @@ static int _i2c_send_single(u32 i2c_idx, u32 dev_addr, u8 *buf, u32 size)
// Initiate transaction on normal mode. // Initiate transaction on normal mode.
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | NORMAL_MODE_GO; base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | NORMAL_MODE_GO;
u32 timeout = get_tmr_ms() + 400; // Actual for max 8 bytes at 100KHz is 0.74ms. u32 timeout = get_tmr_us() + 200000; // Actual for max 8 bytes at 100KHz is 0.74ms.
while (base[I2C_STATUS] & I2C_STATUS_BUSY) while (base[I2C_STATUS] & I2C_STATUS_BUSY)
{ {
if (get_tmr_ms() > timeout) if (get_tmr_us() > timeout)
return 0; return 0;
} }
@ -168,10 +168,10 @@ static int _i2c_recv_single(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr)
// Initiate transaction on normal mode. // Initiate transaction on normal mode.
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | NORMAL_MODE_GO; base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | NORMAL_MODE_GO;
u32 timeout = get_tmr_ms() + 400; // Actual for max 8 bytes at 100KHz is 0.74ms. u32 timeout = get_tmr_us() + 200000; // Actual for max 8 bytes at 100KHz is 0.74ms.
while (base[I2C_STATUS] & I2C_STATUS_BUSY) while (base[I2C_STATUS] & I2C_STATUS_BUSY)
{ {
if (get_tmr_ms() > timeout) if (get_tmr_us() > timeout)
return 0; return 0;
} }

View File

@ -133,6 +133,10 @@ static irq_status_t _irq_handle_source(u32 irq)
} }
} }
// Do not re-enable if not handled.
if (status == IRQ_NONE)
return status;
if (irqs[idx].flags & IRQ_FLAG_ONE_OFF) if (irqs[idx].flags & IRQ_FLAG_ONE_OFF)
irq_free(irq); irq_free(irq);
else else
@ -148,7 +152,9 @@ void irq_handler()
if (!irq_init_done) if (!irq_init_done)
{ {
_irq_disable_source(irq);
_irq_ack_source(irq); _irq_ack_source(irq);
return; return;
} }
@ -156,9 +162,10 @@ void irq_handler()
int err = _irq_handle_source(irq); int err = _irq_handle_source(irq);
//TODO: disable if unhandhled.
if (err == IRQ_NONE) if (err == IRQ_NONE)
gfx_printf("Unhandled IRQ: %d\n", irq); {
DPRINTF("Unhandled IRQ got disabled: %d!\n", irq);
}
} }
static void _irq_init() static void _irq_init()
@ -170,6 +177,9 @@ static void _irq_init()
void irq_end() void irq_end()
{ {
if (!irq_init_done)
return;
_irq_free_all(); _irq_free_all();
irq_disable_cpu_irq_exceptions(); irq_disable_cpu_irq_exceptions();
irq_init_done = false; irq_init_done = false;

View File

@ -14,11 +14,69 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <soc/hw_init.h>
#include <soc/pmc.h> #include <soc/pmc.h>
#include <soc/t210.h> #include <soc/t210.h>
#include <utils/util.h> #include <utils/util.h>
int pmc_enable_partition(u32 part, int enable) void pmc_scratch_lock(pmc_sec_lock_t lock_mask)
{
// Lock Private key disable, Fuse write enable, MC carveout, Warmboot PA id and Warmboot address.
if (lock_mask & PMC_SEC_LOCK_MISC)
{
PMC(APBDEV_PMC_SEC_DISABLE) |= 0x700FF0; // RW lock: 0-3.
PMC(APBDEV_PMC_SEC_DISABLE2) |= 0xFC000000; // RW lock: 21-23.
PMC(APBDEV_PMC_SEC_DISABLE3) |= 0x3F0FFF00; // RW lock: 28-33, 36-38.
PMC(APBDEV_PMC_SEC_DISABLE6) |= 0xC000000; // RW lock: 85.
PMC(APBDEV_PMC_SEC_DISABLE8) |= 0xFF00FF00; // RW lock: 108-111, 116-119.
// SE2 context.
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01)
{
PMC(APBDEV_PMC_SEC_DISABLE9) |= 0x3FF; // RW lock: 120-124. (0xB38)
PMC(APBDEV_PMC_SEC_DISABLE10) = 0xFFFFFFFF; // RW lock: 135-150.
}
}
if (lock_mask & PMC_SEC_LOCK_LP0_PARAMS)
{
PMC(APBDEV_PMC_SEC_DISABLE2) |= 0x3FCFFFF; // RW lock: 8-15, 17-20.
PMC(APBDEV_PMC_SEC_DISABLE4) |= 0x3F3FFFFF; // RW lock: 40-50, 52-54.
PMC(APBDEV_PMC_SEC_DISABLE5) = 0xFFFFFFFF; // RW lock: 56-71.
PMC(APBDEV_PMC_SEC_DISABLE6) |= 0xF3FFC00F; // RW lock: 72-73, 79-84, 86-87.
PMC(APBDEV_PMC_SEC_DISABLE7) |= 0x3FFFFF; // RW lock: 88-98.
PMC(APBDEV_PMC_SEC_DISABLE8) |= 0xFF; // RW lock: 104-107.
}
if (lock_mask & PMC_SEC_LOCK_RST_VECTOR)
PMC(APBDEV_PMC_SEC_DISABLE3) |= 0xF00000; // RW lock: 34-35.
if (lock_mask & PMC_SEC_LOCK_CARVEOUTS)
{
PMC(APBDEV_PMC_SEC_DISABLE2) |= 0x30000; // RW lock: 16.
PMC(APBDEV_PMC_SEC_DISABLE3) |= 0xC0000000; // RW lock: 39.
PMC(APBDEV_PMC_SEC_DISABLE4) |= 0xC0C00000; // RW lock: 51, 55.
PMC(APBDEV_PMC_SEC_DISABLE6) |= 0x3FF0; // RW lock: 74-78.
PMC(APBDEV_PMC_SEC_DISABLE7) |= 0xFFC00000; // RW lock: 99-103.
}
if (lock_mask & PMC_SEC_LOCK_TZ_CMAC_W)
PMC(APBDEV_PMC_SEC_DISABLE8) |= 0x550000; // W lock: 112-115.
if (lock_mask & PMC_SEC_LOCK_TZ_CMAC_R)
PMC(APBDEV_PMC_SEC_DISABLE8) |= 0xAA0000; // R lock: 112-115.
if (lock_mask & PMC_SEC_LOCK_TZ_KEK_W)
PMC(APBDEV_PMC_SEC_DISABLE3) |= 0x55; // W lock: 24-27.
if (lock_mask & PMC_SEC_LOCK_TZ_KEK_R)
PMC(APBDEV_PMC_SEC_DISABLE3) |= 0xAA; // R lock: 24-27.
if (lock_mask & PMC_SEC_LOCK_SE_SRK)
PMC(APBDEV_PMC_SEC_DISABLE) |= 0xFF000; // RW lock: 4-7
}
int pmc_enable_partition(pmc_power_rail_t part, u32 enable)
{ {
u32 part_mask = BIT(part); u32 part_mask = BIT(part);
u32 desired_state = enable << part; u32 desired_state = enable << part;

View File

@ -91,6 +91,8 @@
#define APBDEV_PMC_SEC_DISABLE6 0x5B8 #define APBDEV_PMC_SEC_DISABLE6 0x5B8
#define APBDEV_PMC_SEC_DISABLE7 0x5BC #define APBDEV_PMC_SEC_DISABLE7 0x5BC
#define APBDEV_PMC_SEC_DISABLE8 0x5C0 #define APBDEV_PMC_SEC_DISABLE8 0x5C0
#define APBDEV_PMC_SEC_DISABLE9 0x5C4
#define APBDEV_PMC_SEC_DISABLE10 0x5C8
#define APBDEV_PMC_SCRATCH188 0x810 #define APBDEV_PMC_SCRATCH188 0x810
#define APBDEV_PMC_SCRATCH190 0x818 #define APBDEV_PMC_SCRATCH190 0x818
#define APBDEV_PMC_SCRATCH200 0x840 #define APBDEV_PMC_SCRATCH200 0x840
@ -98,6 +100,54 @@
#define APBDEV_PMC_TZRAM_SEC_DISABLE 0xBEC #define APBDEV_PMC_TZRAM_SEC_DISABLE 0xBEC
#define APBDEV_PMC_TZRAM_NON_SEC_DISABLE 0xBF0 #define APBDEV_PMC_TZRAM_NON_SEC_DISABLE 0xBF0
int pmc_enable_partition(u32 part, int enable); typedef enum _pmc_sec_lock_t
{
PMC_SEC_LOCK_MISC = BIT(0),
PMC_SEC_LOCK_LP0_PARAMS = BIT(1),
PMC_SEC_LOCK_RST_VECTOR = BIT(2),
PMC_SEC_LOCK_CARVEOUTS = BIT(3),
PMC_SEC_LOCK_TZ_CMAC_W = BIT(4),
PMC_SEC_LOCK_TZ_CMAC_R = BIT(5),
PMC_SEC_LOCK_TZ_KEK_W = BIT(6),
PMC_SEC_LOCK_TZ_KEK_R = BIT(7),
PMC_SEC_LOCK_SE_SRK = BIT(8),
} pmc_sec_lock_t;
typedef enum _pmc_power_rail_t
{
POWER_RAIL_CRAIL = 0,
POWER_RAIL_3D0 = 1,
POWER_RAIL_VENC = 2,
POWER_RAIL_PCIE = 3,
POWER_RAIL_VDEC = 4,
POWER_RAIL_L2C = 5,
POWER_RAIL_MPE = 6,
POWER_RAIL_HEG = 7,
POWER_RAIL_SATA = 8,
POWER_RAIL_CE1 = 9,
POWER_RAIL_CE2 = 10,
POWER_RAIL_CE3 = 11,
POWER_RAIL_CELP = 12,
POWER_RAIL_3D1 = 13,
POWER_RAIL_CE0 = 14,
POWER_RAIL_C0NC = 15,
POWER_RAIL_C1NC = 16,
POWER_RAIL_SOR = 17,
POWER_RAIL_DIS = 18,
POWER_RAIL_DISB = 19,
POWER_RAIL_XUSBA = 20,
POWER_RAIL_XUSBB = 21,
POWER_RAIL_XUSBC = 22,
POWER_RAIL_VIC = 23,
POWER_RAIL_IRAM = 24,
POWER_RAIL_NVDEC = 25,
POWER_RAIL_NVJPG = 26,
POWER_RAIL_AUD = 27,
POWER_RAIL_DFD = 28,
POWER_RAIL_VE2 = 29
} pmc_power_rail_t;
void pmc_scratch_lock(pmc_sec_lock_t lock_mask);
int pmc_enable_partition(pmc_power_rail_t part, u32 enable);
#endif #endif

View File

@ -122,7 +122,12 @@ u32 uart_get_IIR(u32 idx)
{ {
uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]); uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]);
return uart->UART_IIR_FCR; u32 iir = uart->UART_IIR_FCR & UART_IIR_INT_MASK;
if (iir & UART_IIR_NO_INT)
return 0;
else
return ((iir >> 1) + 1); // Return encoded interrupt.
} }
void uart_set_IIR(u32 idx) void uart_set_IIR(u32 idx)

View File

@ -54,6 +54,17 @@
#define UART_IIR_FCR_RX_CLR 0x2 #define UART_IIR_FCR_RX_CLR 0x2
#define UART_IIR_FCR_EN_FIFO 0x1 #define UART_IIR_FCR_EN_FIFO 0x1
#define UART_IIR_NO_INT BIT(0)
#define UART_IIR_INT_MASK 0xF
/* Custom returned interrupt results. Actual interrupts are -1 */
#define UART_IIR_NOI 0 // No interrupt.
#define UART_IIR_MSI 1 // Modem status interrupt.
#define UART_IIR_THRI 2 // Transmitter holding register empty.
#define UART_IIR_RDI 3 // Receiver data interrupt.
#define UART_IIR_ERROR 4 // Overrun Error, Parity Error, Framing Error, Break.
#define UART_IIR_REDI 5 // Receiver end of data interrupt.
#define UART_IIR_RDTI 7 // Receiver data timeout interrupt.
#define UART_MCR_RTS 0x2 #define UART_MCR_RTS 0x2
#define UART_MCR_DTR 0x1 #define UART_MCR_DTR 0x1

View File

@ -84,6 +84,11 @@
#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */ #define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */
#define MMC_GEN_CMD 56 /* adtc [0] RD/WR 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 */ /* class 11 */
#define MMC_QUE_TASK_PARAMS 44 /* ac [20:16] task id R1 */ #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_QUE_TASK_ADDR 45 /* ac [31:0] data addr R1 */
@ -142,7 +147,10 @@ c : clear by read
#define R1_SWITCH_ERROR (1 << 7) /* sx, c */ #define R1_SWITCH_ERROR (1 << 7) /* sx, c */
#define R1_EXCEPTION_EVENT (1 << 6) /* sr, a */ #define R1_EXCEPTION_EVENT (1 << 6) /* sr, a */
#define R1_APP_CMD (1 << 5) /* sr, c */ #define R1_APP_CMD (1 << 5) /* sr, c */
#define R1_SKIP_STATE_CHECK (1 << 4) /* Custom state to skip expected state check */
#define R1_AKE_SEQ_ERROR (1 << 3)
/* R1_CURRENT_STATE 12:9 */
#define R1_STATE_IDLE 0 #define R1_STATE_IDLE 0
#define R1_STATE_READY 1 #define R1_STATE_READY 1
#define R1_STATE_IDENT 2 #define R1_STATE_IDENT 2
@ -179,7 +187,10 @@ c : clear by read
/* /*
* OCR bits are mostly in host.h * OCR bits are mostly in host.h
*/ */
#define MMC_CARD_BUSY 0x80000000 /* Card Power up status bit */ #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) * Card Command Classes (CCC)
@ -241,6 +252,7 @@ c : clear by read
#define EXT_CSD_GP_SIZE_MULT 143 /* R/W */ #define EXT_CSD_GP_SIZE_MULT 143 /* R/W */
#define EXT_CSD_PARTITION_SETTING_COMPLETED 155 /* R/W */ #define EXT_CSD_PARTITION_SETTING_COMPLETED 155 /* R/W */
#define EXT_CSD_PARTITION_ATTRIBUTE 156 /* 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_PARTITION_SUPPORT 160 /* RO */
#define EXT_CSD_HPI_MGMT 161 /* R/W */ #define EXT_CSD_HPI_MGMT 161 /* R/W */
#define EXT_CSD_RST_N_FUNCTION 162 /* R/W */ #define EXT_CSD_RST_N_FUNCTION 162 /* R/W */

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2019 CTCaer * Copyright (c) 2018-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -45,12 +45,15 @@ extern FATFS sd_fs;
void sd_error_count_increment(u8 type); void sd_error_count_increment(u8 type);
u16 *sd_get_error_count(); u16 *sd_get_error_count();
bool sd_get_card_removed(); bool sd_get_card_removed();
bool sd_get_card_initialized();
bool sd_get_card_mounted();
u32 sd_get_mode(); u32 sd_get_mode();
int sd_init_retry(bool power_cycle); int sd_init_retry(bool power_cycle);
bool sd_initialize(bool power_cycle); bool sd_initialize(bool power_cycle);
bool sd_mount(); bool sd_mount();
void sd_unmount(); void sd_unmount();
void sd_end(); void sd_end();
bool sd_is_gpt();
void *sd_file_read(const char *path, u32 *fsize); void *sd_file_read(const char *path, u32 *fsize);
int sd_save_to_file(void *buf, u32 size, const char *filename); int sd_save_to_file(void *buf, u32 size, const char *filename);

View File

@ -1,7 +1,7 @@
/* /*
* Ramdisk driver for Tegra X1 * Ramdisk driver for Tegra X1
* *
* Copyright (c) 2019 CTCaer * Copyright (c) 2019-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -19,23 +19,40 @@
#include <string.h> #include <string.h>
#include "ramdisk.h" #include "ramdisk.h"
#include <libs/fatfs/diskio.h>
#include <mem/heap.h> #include <mem/heap.h>
#include <utils/types.h> #include <utils/types.h>
#include <memory_map.h> #include <memory_map.h>
int ram_disk_init(FATFS *ram_fs) static u32 disk_size = 0;
int ram_disk_init(FATFS *ram_fs, u32 ramdisk_size)
{ {
int res; int res = 0;
u8 *buf = malloc(0x400000); disk_size = ramdisk_size;
f_mount(NULL, "ram:", 1); // Unmount ramdisk. // If ramdisk is not raw, format it.
if (ram_fs)
{
u8 *buf = malloc(0x400000);
res = f_mkfs("ram:", FM_EXFAT, RAMDISK_CLUSTER_SZ, buf, 0x400000); // Format as exFAT w/ 32KB cluster. // Set ramdisk size.
if (!res) ramdisk_size >>= 9;
res = f_mount(ram_fs, "ram:", 1); // Mount ramdisk. disk_set_info(DRIVE_RAM, SET_SECTOR_COUNT, &ramdisk_size);
free(buf); // Unmount ramdisk.
f_mount(NULL, "ram:", 1);
// Format as exFAT w/ 32KB cluster with no MBR.
res = f_mkfs("ram:", FM_EXFAT | FM_SFD, RAMDISK_CLUSTER_SZ, buf, 0x400000);
// Mount ramdisk.
if (!res)
res = f_mount(ram_fs, "ram:", 1);
free(buf);
}
return res; return res;
} }
@ -45,7 +62,7 @@ int ram_disk_read(u32 sector, u32 sector_count, void *buf)
u32 sector_off = RAM_DISK_ADDR + (sector << 9); u32 sector_off = RAM_DISK_ADDR + (sector << 9);
u32 bytes_count = sector_count << 9; u32 bytes_count = sector_count << 9;
if ((sector_off - RAM_DISK_ADDR) > RAM_DISK_SZ) if ((sector_off - RAM_DISK_ADDR) > disk_size)
return 1; return 1;
memcpy(buf, (void *)sector_off, bytes_count); memcpy(buf, (void *)sector_off, bytes_count);
@ -58,7 +75,7 @@ int ram_disk_write(u32 sector, u32 sector_count, const void *buf)
u32 sector_off = RAM_DISK_ADDR + (sector << 9); u32 sector_off = RAM_DISK_ADDR + (sector << 9);
u32 bytes_count = sector_count << 9; u32 bytes_count = sector_count << 9;
if ((sector_off - RAM_DISK_ADDR) > RAM_DISK_SZ) if ((sector_off - RAM_DISK_ADDR) > disk_size)
return 1; return 1;
memcpy((void *)sector_off, buf, bytes_count); memcpy((void *)sector_off, buf, bytes_count);

View File

@ -1,7 +1,7 @@
/* /*
* Ramdisk driver for Tegra X1 * Ramdisk driver for Tegra X1
* *
* Copyright (c) 2019 CTCaer * Copyright (c) 2019-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -23,7 +23,7 @@
#define RAMDISK_CLUSTER_SZ 32768 #define RAMDISK_CLUSTER_SZ 32768
int ram_disk_init(FATFS *ram_fs); int ram_disk_init(FATFS *ram_fs, u32 ramdisk_size);
int ram_disk_read(u32 sector, u32 sector_count, void *buf); int ram_disk_read(u32 sector, u32 sector_count, void *buf);
int ram_disk_write(u32 sector, u32 sector_count, const void *buf); int ram_disk_write(u32 sector, u32 sector_count, const void *buf);

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2005-2007 Pierre Ossman, All Rights Reserved. * Copyright (c) 2005-2007 Pierre Ossman, All Rights Reserved.
* Copyright (c) 2018 CTCaer * Copyright (c) 2018-2021 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
@ -14,58 +14,79 @@
/* SD commands type argument response */ /* SD commands type argument response */
/* class 0 */ /* class 0 */
/* This is basically the same command as for MMC with some quirks. */ /* This is basically the same command as for MMC with some quirks. */
#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */ #define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */
#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */ #define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */
#define SD_SWITCH_VOLTAGE 11 /* ac R1 */ #define SD_SWITCH_VOLTAGE 11 /* ac R1 */
/* class 10 */ /* class 10 */
#define SD_SWITCH 6 /* adtc [31:0] See below R1 */ #define SD_SWITCH 6 /* adtc [31:0] See below R1 */
/* class 5 */ /* class 5 */
#define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */ #define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */
#define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */ #define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */
/* Application commands */ /* Application commands */
#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */ #define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */
#define SD_APP_SD_STATUS 13 /* adtc R1 */ #define SD_APP_SD_STATUS 13 /* adtc R1 */
#define SD_APP_SEND_NUM_WR_BLKS 22 /* adtc R1 */ #define SD_APP_SEND_NUM_WR_BLKS 22 /* adtc R1 */
#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */ #define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */
#define SD_APP_SET_CLR_CARD_DETECT 42 #define SD_APP_SET_CLR_CARD_DETECT 42 /* adtc R1 */
#define SD_APP_SEND_SCR 51 /* adtc R1 */ #define SD_APP_SEND_SCR 51 /* adtc R1 */
/* Application secure commands */
#define SD_APP_SECURE_READ_MULTI_BLOCK 18 /* adtc R1 */
#define SD_APP_SECURE_WRITE_MULTI_BLOCK 25 /* adtc R1 */
#define SD_APP_SECURE_WRITE_MKB 26 /* adtc R1 */
#define SD_APP_SECURE_ERASE 38 /* adtc R1b */
#define SD_APP_GET_MKB 43 /* adtc [31:0] See below R1 */
#define SD_APP_GET_MID 44 /* adtc R1 */
#define SD_APP_SET_CER_RN1 45 /* adtc R1 */
#define SD_APP_GET_CER_RN2 46 /* adtc R1 */
#define SD_APP_SET_CER_RES2 47 /* adtc R1 */
#define SD_APP_GET_CER_RES1 48 /* adtc R1 */
#define SD_APP_CHANGE_SECURE_AREA 49 /* adtc R1b */
/* OCR bit definitions */ /* OCR bit definitions */
#define SD_OCR_VDD_18 (1 << 7) /* VDD voltage 1.8 */
#define SD_VHD_27_36 (1 << 8) /* VDD voltage 2.7 ~ 3.6 */
#define SD_OCR_VDD_27_34 (0x7F << 15) /* VDD voltage 2.7 ~ 3.4 */
#define SD_OCR_VDD_32_33 (1 << 20) /* VDD voltage 3.2 ~ 3.3 */
#define SD_OCR_S18R (1 << 24) /* 1.8V switching request */ #define SD_OCR_S18R (1 << 24) /* 1.8V switching request */
#define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */ #define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */
#define SD_OCR_XPC (1 << 28) /* SDXC power control */ #define SD_OCR_XPC (1 << 28) /* SDXC power control */
#define SD_OCR_CCS (1 << 30) /* Card Capacity Status */ #define SD_OCR_CCS (1 << 30) /* Card Capacity Status */
#define SD_OCR_VDD_27_34 (0x7F << 15) /* VDD voltage 2.7 ~ 3.4 */ #define SD_OCR_BUSY (1 << 31) /* Card Power up Status */
#define SD_OCR_VDD_32_33 (1 << 20) /* VDD voltage 3.2 ~ 3.3 */
#define SD_OCR_VDD_18 (1 << 7) /* VDD voltage 1.8 */
/* /*
* SD_SWITCH argument format: * SD_SWITCH argument format:
* *
* [31] Check (0) or switch (1) * [31] Check (0) or switch (1)
* [30:24] Reserved (0) * [30:24] Reserved (0)
* [23:20] Function group 6 * [23:20] Function group 6
* [19:16] Function group 5 * [19:16] Function group 5
* [15:12] Function group 4 * [15:12] Function group 4
* [11:8] Function group 3 * [11:8] Function group 3
* [7:4] Function group 2 * [7:4] Function group 2
* [3:0] Function group 1 * [3:0] Function group 1
*/ */
/* /*
* SD_SEND_IF_COND argument format: * SD_SEND_IF_COND argument format:
* *
* [31:12] Reserved (0) * [31:12] Reserved (0)
* [11:8] Host Voltage Supply Flags * [11:8] Host Voltage Supply Flags
* [7:0] Check Pattern (0xAA) * [7:0] Check Pattern (0xAA)
*/ */
/* /*
* SCR field definitions * SD_APP_GET_MKB argument format:
*/ *
* [31:24] Number of blocks to read (512 block size)
* [23:16] MKB ID
* [15:0] Block offset
*/
/*
* SCR field definitions
*/
#define SCR_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.01 */ #define SCR_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.01 */
#define SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */ #define SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */
#define SCR_SPEC_VER_2 2 /* Implements system specification 2.00-3.0X */ #define SCR_SPEC_VER_2 2 /* Implements system specification 2.00-3.0X */
@ -73,14 +94,14 @@
#define SD_SCR_BUS_WIDTH_4 (1<<2) #define SD_SCR_BUS_WIDTH_4 (1<<2)
/* /*
* SD bus widths * SD bus widths
*/ */
#define SD_BUS_WIDTH_1 0 #define SD_BUS_WIDTH_1 0
#define SD_BUS_WIDTH_4 2 #define SD_BUS_WIDTH_4 2
/* /*
* SD bus speeds * SD bus speeds
*/ */
#define UHS_SDR12_BUS_SPEED 0 #define UHS_SDR12_BUS_SPEED 0
#define HIGH_SPEED_BUS_SPEED 1 #define HIGH_SPEED_BUS_SPEED 1
#define UHS_SDR25_BUS_SPEED 1 #define UHS_SDR25_BUS_SPEED 1
@ -110,19 +131,19 @@
#define SD_MAX_CURRENT_800 (1 << SD_SET_CURRENT_LIMIT_800) #define SD_MAX_CURRENT_800 (1 << SD_SET_CURRENT_LIMIT_800)
/* /*
* SD_SWITCH mode * SD_SWITCH mode
*/ */
#define SD_SWITCH_CHECK 0 #define SD_SWITCH_CHECK 0
#define SD_SWITCH_SET 1 #define SD_SWITCH_SET 1
/* /*
* SD_SWITCH function groups * SD_SWITCH function groups
*/ */
#define SD_SWITCH_GRP_ACCESS 0 #define SD_SWITCH_GRP_ACCESS 0
/* /*
* SD_SWITCH access modes * SD_SWITCH access modes
*/ */
#define SD_SWITCH_ACCESS_DEF 0 #define SD_SWITCH_ACCESS_DEF 0
#define SD_SWITCH_ACCESS_HS 1 #define SD_SWITCH_ACCESS_HS 1

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer * Copyright (c) 2018-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -42,10 +42,10 @@ static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size)
} }
/* /*
* Common functions for SD and MMC. * Common functions for SD and MMC.
*/ */
static int _sdmmc_storage_check_result(u32 res) static int _sdmmc_storage_check_card_status(u32 res)
{ {
//Error mask: //Error mask:
//TODO: R1_SWITCH_ERROR can be skipped for certain card types. //TODO: R1_SWITCH_ERROR can be skipped for certain card types.
@ -66,15 +66,15 @@ static int _sdmmc_storage_execute_cmd_type1_ex(sdmmc_storage_t *storage, u32 *re
{ {
sdmmc_cmd_t cmdbuf; sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmdbuf, cmd, arg, SDMMC_RSP_TYPE_1, check_busy); sdmmc_init_cmd(&cmdbuf, cmd, arg, SDMMC_RSP_TYPE_1, check_busy);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0; return 0;
sdmmc_get_rsp(storage->sdmmc, resp, 4, SDMMC_RSP_TYPE_1); sdmmc_get_rsp(storage->sdmmc, resp, 4, SDMMC_RSP_TYPE_1);
if (mask) if (mask)
*resp &= ~mask; *resp &= ~mask;
if (_sdmmc_storage_check_result(*resp)) if (_sdmmc_storage_check_card_status(*resp))
if (expected_state == 0x10 || R1_CURRENT_STATE(*resp) == expected_state) if (expected_state == R1_SKIP_STATE_CHECK || R1_CURRENT_STATE(*resp) == expected_state)
return 1; return 1;
return 0; return 0;
@ -88,37 +88,37 @@ static int _sdmmc_storage_execute_cmd_type1(sdmmc_storage_t *storage, u32 cmd, u
static int _sdmmc_storage_go_idle_state(sdmmc_storage_t *storage) static int _sdmmc_storage_go_idle_state(sdmmc_storage_t *storage)
{ {
sdmmc_cmd_t cmd; sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmd, MMC_GO_IDLE_STATE, 0, SDMMC_RSP_TYPE_0, 0); sdmmc_init_cmd(&cmdbuf, MMC_GO_IDLE_STATE, 0, SDMMC_RSP_TYPE_0, 0);
return sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0); return sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL);
} }
static int _sdmmc_storage_get_cid(sdmmc_storage_t *storage, void *buf) static int _sdmmc_storage_get_cid(sdmmc_storage_t *storage)
{ {
sdmmc_cmd_t cmd; sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmd, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0); sdmmc_init_cmd(&cmdbuf, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0; return 0;
sdmmc_get_rsp(storage->sdmmc, buf, 0x10, SDMMC_RSP_TYPE_2); sdmmc_get_rsp(storage->sdmmc, (u32 *)storage->raw_cid, 16, SDMMC_RSP_TYPE_2);
return 1; return 1;
} }
static int _sdmmc_storage_select_card(sdmmc_storage_t *storage) static int _sdmmc_storage_select_card(sdmmc_storage_t *storage)
{ {
return _sdmmc_storage_execute_cmd_type1(storage, MMC_SELECT_CARD, storage->rca << 16, 1, 0x10); return _sdmmc_storage_execute_cmd_type1(storage, MMC_SELECT_CARD, storage->rca << 16, 1, R1_SKIP_STATE_CHECK);
} }
static int _sdmmc_storage_get_csd(sdmmc_storage_t *storage, void *buf) static int _sdmmc_storage_get_csd(sdmmc_storage_t *storage)
{ {
sdmmc_cmd_t cmdbuf; sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmdbuf, MMC_SEND_CSD, storage->rca << 16, SDMMC_RSP_TYPE_2, 0); sdmmc_init_cmd(&cmdbuf, MMC_SEND_CSD, storage->rca << 16, SDMMC_RSP_TYPE_2, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0; return 0;
sdmmc_get_rsp(storage->sdmmc, buf, 0x10, SDMMC_RSP_TYPE_2); sdmmc_get_rsp(storage->sdmmc, (u32 *)storage->raw_csd, 16, SDMMC_RSP_TYPE_2);
return 1; return 1;
} }
@ -145,6 +145,10 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out
sdmmc_cmd_t cmdbuf; sdmmc_cmd_t cmdbuf;
sdmmc_req_t reqbuf; sdmmc_req_t reqbuf;
// If SDSC convert block address to byte address.
if (!storage->has_sector_access)
sector <<= 9;
sdmmc_init_cmd(&cmdbuf, is_write ? MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK, sector, SDMMC_RSP_TYPE_1, 0); sdmmc_init_cmd(&cmdbuf, is_write ? MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK, sector, SDMMC_RSP_TYPE_1, 0);
reqbuf.buf = buf; reqbuf.buf = buf;
@ -152,7 +156,7 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out
reqbuf.blksize = 512; reqbuf.blksize = 512;
reqbuf.is_write = is_write; reqbuf.is_write = is_write;
reqbuf.is_multi_block = 1; reqbuf.is_multi_block = 1;
reqbuf.is_auto_cmd12 = 1; reqbuf.is_auto_stop_trn = 1;
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, blkcnt_out)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, blkcnt_out))
{ {
@ -288,25 +292,25 @@ int sdmmc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, v
static int _mmc_storage_get_op_cond_inner(sdmmc_storage_t *storage, u32 *pout, u32 power) static int _mmc_storage_get_op_cond_inner(sdmmc_storage_t *storage, u32 *pout, u32 power)
{ {
sdmmc_cmd_t cmd; sdmmc_cmd_t cmdbuf;
u32 arg = 0; u32 arg = 0;
switch (power) switch (power)
{ {
case SDMMC_POWER_1_8: case SDMMC_POWER_1_8:
arg = SD_OCR_CCS | SD_OCR_VDD_18; arg = MMC_CARD_CCS | MMC_CARD_VDD_18;
break; break;
case SDMMC_POWER_3_3: case SDMMC_POWER_3_3:
arg = SD_OCR_CCS | SD_OCR_VDD_27_34; arg = MMC_CARD_CCS | MMC_CARD_VDD_27_34;
break; break;
default: default:
return 0; return 0;
} }
sdmmc_init_cmd(&cmd, MMC_SEND_OP_COND, arg, SDMMC_RSP_TYPE_3, 0); sdmmc_init_cmd(&cmdbuf, MMC_SEND_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0; return 0;
return sdmmc_get_rsp(storage->sdmmc, pout, 4, SDMMC_RSP_TYPE_3); return sdmmc_get_rsp(storage->sdmmc, pout, 4, SDMMC_RSP_TYPE_3);
@ -316,15 +320,17 @@ static int _mmc_storage_get_op_cond(sdmmc_storage_t *storage, u32 power)
{ {
u32 timeout = get_tmr_ms() + 1500; u32 timeout = get_tmr_ms() + 1500;
while (1) while (true)
{ {
u32 cond = 0; u32 cond = 0;
if (!_mmc_storage_get_op_cond_inner(storage, &cond, power)) if (!_mmc_storage_get_op_cond_inner(storage, &cond, power))
break; break;
// Check if power up is done.
if (cond & MMC_CARD_BUSY) if (cond & MMC_CARD_BUSY)
{ {
if (cond & SD_OCR_CCS) // Check if card is high capacity.
if (cond & MMC_CARD_CCS)
storage->has_sector_access = 1; storage->has_sector_access = 1;
return 1; return 1;
@ -340,7 +346,7 @@ static int _mmc_storage_get_op_cond(sdmmc_storage_t *storage, u32 power)
static int _mmc_storage_set_relative_addr(sdmmc_storage_t *storage) static int _mmc_storage_set_relative_addr(sdmmc_storage_t *storage)
{ {
return _sdmmc_storage_execute_cmd_type1(storage, MMC_SET_RELATIVE_ADDR, storage->rca << 16, 0, 0x10); return _sdmmc_storage_execute_cmd_type1(storage, MMC_SET_RELATIVE_ADDR, storage->rca << 16, 0, R1_SKIP_STATE_CHECK);
} }
static void _mmc_storage_parse_cid(sdmmc_storage_t *storage) static void _mmc_storage_parse_cid(sdmmc_storage_t *storage)
@ -362,7 +368,6 @@ static void _mmc_storage_parse_cid(sdmmc_storage_t *storage)
case 3: /* MMC v3.1 - v3.3 */ case 3: /* MMC v3.1 - v3.3 */
case 4: /* MMC v4 */ case 4: /* MMC v4 */
storage->cid.manfid = unstuff_bits(raw_cid, 120, 8); storage->cid.manfid = unstuff_bits(raw_cid, 120, 8);
storage->cid.card_bga = unstuff_bits(raw_cid, 112, 2);
storage->cid.oemid = unstuff_bits(raw_cid, 104, 8); storage->cid.oemid = unstuff_bits(raw_cid, 104, 8);
storage->cid.prv = unstuff_bits(raw_cid, 48, 8); storage->cid.prv = unstuff_bits(raw_cid, 48, 8);
storage->cid.serial = unstuff_bits(raw_cid, 16, 32); storage->cid.serial = unstuff_bits(raw_cid, 16, 32);
@ -390,13 +395,14 @@ static void _mmc_storage_parse_cid(sdmmc_storage_t *storage)
static void _mmc_storage_parse_csd(sdmmc_storage_t *storage) static void _mmc_storage_parse_csd(sdmmc_storage_t *storage)
{ {
u32 *raw_csd = (u32 *)&(storage->raw_csd); u32 *raw_csd = (u32 *)storage->raw_csd;
storage->csd.mmca_vsn = unstuff_bits(raw_csd, 122, 4); storage->csd.mmca_vsn = unstuff_bits(raw_csd, 122, 4);
storage->csd.structure = unstuff_bits(raw_csd, 126, 2); storage->csd.structure = unstuff_bits(raw_csd, 126, 2);
storage->csd.cmdclass = unstuff_bits(raw_csd, 84, 12); storage->csd.cmdclass = unstuff_bits(raw_csd, 84, 12);
storage->csd.read_blkbits = unstuff_bits(raw_csd, 80, 4); storage->csd.read_blkbits = unstuff_bits(raw_csd, 80, 4);
storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2); storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2);
storage->sec_cnt = storage->csd.capacity;
} }
static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf) static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf)
@ -407,16 +413,26 @@ static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf)
storage->ext_csd.dev_version = *(u16 *)&buf[EXT_CSD_DEVICE_VERSION]; storage->ext_csd.dev_version = *(u16 *)&buf[EXT_CSD_DEVICE_VERSION];
storage->ext_csd.boot_mult = buf[EXT_CSD_BOOT_MULT]; storage->ext_csd.boot_mult = buf[EXT_CSD_BOOT_MULT];
storage->ext_csd.rpmb_mult = buf[EXT_CSD_RPMB_MULT]; storage->ext_csd.rpmb_mult = buf[EXT_CSD_RPMB_MULT];
storage->ext_csd.sectors = *(u32 *)&buf[EXT_CSD_SEC_CNT]; //storage->ext_csd.bkops = buf[EXT_CSD_BKOPS_SUPPORT];
storage->ext_csd.bkops = buf[EXT_CSD_BKOPS_SUPPORT]; //storage->ext_csd.bkops_en = buf[EXT_CSD_BKOPS_EN];
storage->ext_csd.bkops_en = buf[EXT_CSD_BKOPS_EN]; //storage->ext_csd.bkops_status = buf[EXT_CSD_BKOPS_STATUS];
storage->ext_csd.bkops_status = buf[EXT_CSD_BKOPS_STATUS];
storage->ext_csd.pre_eol_info = buf[EXT_CSD_PRE_EOL_INFO]; storage->ext_csd.pre_eol_info = buf[EXT_CSD_PRE_EOL_INFO];
storage->ext_csd.dev_life_est_a = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A]; storage->ext_csd.dev_life_est_a = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A];
storage->ext_csd.dev_life_est_b = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B]; storage->ext_csd.dev_life_est_b = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B];
storage->sec_cnt = *(u32 *)&buf[EXT_CSD_SEC_CNT]; storage->ext_csd.cache_size =
buf[EXT_CSD_CACHE_SIZE] |
(buf[EXT_CSD_CACHE_SIZE + 1] << 8) |
(buf[EXT_CSD_CACHE_SIZE + 2] << 16) |
(buf[EXT_CSD_CACHE_SIZE + 3] << 24);
storage->ext_csd.max_enh_mult =
(buf[EXT_CSD_MAX_ENH_SIZE_MULT] |
(buf[EXT_CSD_MAX_ENH_SIZE_MULT + 1] << 8) |
(buf[EXT_CSD_MAX_ENH_SIZE_MULT + 2] << 16)) *
buf[EXT_CSD_HC_WP_GRP_SIZE] * buf[EXT_CSD_HC_ERASE_GRP_SIZE];
storage->sec_cnt = *(u32 *)&buf[EXT_CSD_SEC_CNT];
} }
static int _mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf) static int _mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf)
@ -430,21 +446,21 @@ static int _mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf)
reqbuf.num_sectors = 1; reqbuf.num_sectors = 1;
reqbuf.is_write = 0; reqbuf.is_write = 0;
reqbuf.is_multi_block = 0; reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0; reqbuf.is_auto_stop_trn = 0;
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, 0)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
return 0; return 0;
u32 tmp = 0; u32 tmp = 0;
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1); sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
_mmc_storage_parse_ext_csd(storage, buf); _mmc_storage_parse_ext_csd(storage, buf);
return _sdmmc_storage_check_result(tmp); return _sdmmc_storage_check_card_status(tmp);
} }
static int _mmc_storage_switch(sdmmc_storage_t *storage, u32 arg) static int _mmc_storage_switch(sdmmc_storage_t *storage, u32 arg)
{ {
return _sdmmc_storage_execute_cmd_type1(storage, MMC_SWITCH, arg, 1, 0x10); return _sdmmc_storage_execute_cmd_type1(storage, MMC_SWITCH, arg, 1, R1_SKIP_STATE_CHECK);
} }
static int _mmc_storage_switch_buswidth(sdmmc_storage_t *storage, u32 bus_width) static int _mmc_storage_switch_buswidth(sdmmc_storage_t *storage, u32 bus_width)
@ -559,19 +575,21 @@ out:
return 1; return 1;
} }
/*
static int _mmc_storage_enable_bkops(sdmmc_storage_t *storage) static int _mmc_storage_enable_bkops(sdmmc_storage_t *storage)
{ {
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_SET_BITS, EXT_CSD_BKOPS_EN, EXT_CSD_BKOPS_LEVEL_2))) if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_SET_BITS, EXT_CSD_BKOPS_EN, EXT_CSD_AUTO_BKOPS_MASK)))
return 0; return 0;
return _sdmmc_storage_check_status(storage); return _sdmmc_storage_check_status(storage);
} }
*/
int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type) int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type)
{ {
memset(storage, 0, sizeof(sdmmc_storage_t)); memset(storage, 0, sizeof(sdmmc_storage_t));
storage->sdmmc = sdmmc; storage->sdmmc = sdmmc;
storage->rca = 2; //TODO: this could be a config item. storage->rca = 2; // Set default device address. This could be a config item.
if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_MMC_ID, SDMMC_POWER_SAVE_DISABLE)) if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_MMC_ID, SDMMC_POWER_SAVE_DISABLE))
return 0; return 0;
@ -587,7 +605,7 @@ DPRINTF("[MMC] went to idle state\n");
return 0; return 0;
DPRINTF("[MMC] got op cond\n"); DPRINTF("[MMC] got op cond\n");
if (!_sdmmc_storage_get_cid(storage, storage->raw_cid)) if (!_sdmmc_storage_get_cid(storage))
return 0; return 0;
DPRINTF("[MMC] got cid\n"); DPRINTF("[MMC] got cid\n");
@ -595,7 +613,7 @@ DPRINTF("[MMC] got cid\n");
return 0; return 0;
DPRINTF("[MMC] set relative addr\n"); DPRINTF("[MMC] set relative addr\n");
if (!_sdmmc_storage_get_csd(storage, storage->raw_csd)) if (!_sdmmc_storage_get_csd(storage))
return 0; return 0;
DPRINTF("[MMC] got csd\n"); DPRINTF("[MMC] got csd\n");
_mmc_storage_parse_csd(storage); _mmc_storage_parse_csd(storage);
@ -612,13 +630,9 @@ DPRINTF("[MMC] card selected\n");
return 0; return 0;
DPRINTF("[MMC] set blocklen to 512\n"); DPRINTF("[MMC] set blocklen to 512\n");
u32 *csd = (u32 *)storage->raw_csd; // Check system specification version, only version 4.0 and later support below features.
//Check system specification version, only version 4.0 and later support below features. if (storage->csd.mmca_vsn < CSD_SPEC_VER_4)
if (unstuff_bits(csd, 122, 4) < CSD_SPEC_VER_4)
{
storage->sec_cnt = (1 + unstuff_bits(csd, 62, 12)) << (unstuff_bits(csd, 47, 3) + 2);
return 1; return 1;
}
if (!_mmc_storage_switch_buswidth(storage, bus_width)) if (!_mmc_storage_switch_buswidth(storage, bus_width))
return 0; return 0;
@ -628,21 +642,20 @@ DPRINTF("[MMC] switched buswidth\n");
return 0; return 0;
DPRINTF("[MMC] got ext_csd\n"); DPRINTF("[MMC] got ext_csd\n");
_mmc_storage_parse_cid(storage); //This needs to be after csd and ext_csd _mmc_storage_parse_cid(storage); // This needs to be after csd and ext_csd.
//gfx_hexdump(0, ext_csd, 512); //gfx_hexdump(0, ext_csd, 512);
/* When auto BKOPS is enabled the mmc device should be powered all the time until we disable this and check status. /*
Disable it for now until BKOPS disable added to power down sequence at sdmmc_storage_end(). if (storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_AUTO_BKOPS_MASK))
Additionally this works only when we put the device in idle mode which we don't after enabling it. */
if (0 && storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_BKOPS_LEVEL_2))
{ {
_mmc_storage_enable_bkops(storage); _mmc_storage_enable_bkops(storage);
DPRINTF("[MMC] BKOPS enabled\n"); DPRINTF("[MMC] BKOPS enabled\n");
} }
*/
if (!_mmc_storage_enable_highspeed(storage, storage->ext_csd.card_type, type)) if (!_mmc_storage_enable_highspeed(storage, storage->ext_csd.card_type, type))
return 0; return 0;
DPRINTF("[MMC] succesfully switched to HS mode\n"); DPRINTF("[MMC] successfully switched to HS mode\n");
sdmmc_card_clock_powersave(storage->sdmmc, SDMMC_POWER_SAVE_ENABLE); sdmmc_card_clock_powersave(storage->sdmmc, SDMMC_POWER_SAVE_ENABLE);
@ -665,16 +678,16 @@ int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition)
} }
/* /*
* SD specific functions. * SD specific functions.
*/ */
static int _sd_storage_execute_app_cmd(sdmmc_storage_t *storage, u32 expected_state, u32 mask, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *blkcnt_out) static int _sd_storage_execute_app_cmd(sdmmc_storage_t *storage, u32 expected_state, u32 mask, sdmmc_cmd_t *cmdbuf, sdmmc_req_t *req, u32 *blkcnt_out)
{ {
u32 tmp; u32 tmp;
if (!_sdmmc_storage_execute_cmd_type1_ex(storage, &tmp, MMC_APP_CMD, storage->rca << 16, 0, expected_state, mask)) if (!_sdmmc_storage_execute_cmd_type1_ex(storage, &tmp, MMC_APP_CMD, storage->rca << 16, 0, expected_state, mask))
return 0; return 0;
return sdmmc_execute_cmd(storage->sdmmc, cmd, req, blkcnt_out); return sdmmc_execute_cmd(storage->sdmmc, cmdbuf, req, blkcnt_out);
} }
static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp, u32 cmd, u32 arg, u32 check_busy, u32 expected_state) static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp, u32 cmd, u32 arg, u32 check_busy, u32 expected_state)
@ -685,60 +698,70 @@ static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp
return _sdmmc_storage_execute_cmd_type1_ex(storage, resp, cmd, arg, check_busy, expected_state, 0); return _sdmmc_storage_execute_cmd_type1_ex(storage, resp, cmd, arg, check_busy, expected_state, 0);
} }
static int _sd_storage_send_if_cond(sdmmc_storage_t *storage) static int _sd_storage_send_if_cond(sdmmc_storage_t *storage, bool *is_sdsc)
{ {
sdmmc_cmd_t cmdbuf; sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmdbuf, SD_SEND_IF_COND, 0x1AA, SDMMC_RSP_TYPE_5, 0); u16 vhd_pattern = SD_VHD_27_36 | 0xAA;
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0)) sdmmc_init_cmd(&cmdbuf, SD_SEND_IF_COND, vhd_pattern, SDMMC_RSP_TYPE_5, 0);
return 1; // The SD Card is version 1.X if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
{
*is_sdsc = 1; // The SD Card is version 1.X
return 1;
}
// For Card version >= 2.0, parse results.
u32 resp = 0; u32 resp = 0;
if (!sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_5)) sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_5);
return 2;
return (resp & 0xFF) == 0xAA ? 0 : 2; // Check if VHD was accepted and pattern was properly returned.
if ((resp & 0xFFF) == vhd_pattern)
return 1;
return 0;
} }
static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, int is_version_1, int bus_low_voltage_support) static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, bool is_sdsc, int bus_uhs_support)
{ {
sdmmc_cmd_t cmdbuf; sdmmc_cmd_t cmdbuf;
// Support for Current > 150mA // Support for Current > 150mA
u32 arg = (~is_version_1 & 1) ? SD_OCR_XPC : 0; u32 arg = !is_sdsc ? SD_OCR_XPC : 0;
// Support for handling block-addressed SDHC cards // Support for handling block-addressed SDHC cards
arg |= (~is_version_1 & 1) ? SD_OCR_CCS : 0; arg |= !is_sdsc ? SD_OCR_CCS : 0;
// Support for 1.8V // Support for 1.8V
arg |= (bus_low_voltage_support & ~is_version_1 & 1) ? SD_OCR_S18R : 0; arg |= (bus_uhs_support && !is_sdsc) ? SD_OCR_S18R : 0;
// This is needed for most cards. Do not set bit7 even if 1.8V is supported. // This is needed for most cards. Do not set bit7 even if 1.8V is supported.
arg |= SD_OCR_VDD_32_33; arg |= SD_OCR_VDD_32_33;
sdmmc_init_cmd(&cmdbuf, SD_APP_OP_COND, arg, SDMMC_RSP_TYPE_3, 0); sdmmc_init_cmd(&cmdbuf, SD_APP_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
if (!_sd_storage_execute_app_cmd(storage, 0x10, is_version_1 ? 0x400000 : 0, &cmdbuf, 0, 0)) if (!_sd_storage_execute_app_cmd(storage, R1_SKIP_STATE_CHECK, is_sdsc ? R1_ILLEGAL_COMMAND : 0, &cmdbuf, NULL, NULL))
return 0; return 0;
return sdmmc_get_rsp(storage->sdmmc, cond, 4, SDMMC_RSP_TYPE_3); return sdmmc_get_rsp(storage->sdmmc, cond, 4, SDMMC_RSP_TYPE_3);
} }
static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, int is_version_1, int bus_low_voltage_support) static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, bool is_sdsc, int bus_uhs_support)
{ {
u32 timeout = get_tmr_ms() + 1500; u32 timeout = get_tmr_ms() + 1500;
while (1) while (true)
{ {
u32 cond = 0; u32 cond = 0;
if (!_sd_storage_get_op_cond_once(storage, &cond, is_version_1, bus_low_voltage_support)) if (!_sd_storage_get_op_cond_once(storage, &cond, is_sdsc, bus_uhs_support))
break; break;
if (cond & MMC_CARD_BUSY)
{
DPRINTF("[SD] cond: %08X, lv: %d\n", cond, bus_low_voltage_support);
// Check if power up is done.
if (cond & SD_OCR_BUSY)
{
DPRINTF("[SD] op cond: %08X, lv: %d\n", cond, bus_uhs_support);
// Check if card is high capacity.
if (cond & SD_OCR_CCS) if (cond & SD_OCR_CCS)
storage->has_sector_access = 1; storage->has_sector_access = 1;
// Check if card supports 1.8V signaling. // Check if card supports 1.8V signaling.
if (cond & SD_ROCR_S18A && bus_low_voltage_support) if (cond & SD_ROCR_S18A && bus_uhs_support)
{ {
//The low voltage regulator configuration is valid for SDMMC1 only. // Switch to 1.8V signaling.
if (storage->sdmmc->id == SDMMC_1 && if (_sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY))
_sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY))
{ {
if (!sdmmc_enable_low_voltage(storage->sdmmc)) if (!sdmmc_enable_low_voltage(storage->sdmmc))
return 0; return 0;
@ -769,9 +792,9 @@ static int _sd_storage_get_rca(sdmmc_storage_t *storage)
u32 timeout = get_tmr_ms() + 1500; u32 timeout = get_tmr_ms() + 1500;
while (1) while (true)
{ {
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
break; break;
u32 resp = 0; u32 resp = 0;
@ -802,8 +825,9 @@ static void _sd_storage_parse_scr(sdmmc_storage_t *storage)
storage->scr.sda_vsn = unstuff_bits(resp, 56, 4); storage->scr.sda_vsn = unstuff_bits(resp, 56, 4);
storage->scr.bus_widths = unstuff_bits(resp, 48, 4); storage->scr.bus_widths = unstuff_bits(resp, 48, 4);
/* If v2.0 is supported, check if Physical Layer Spec v3.0 is supported */
if (storage->scr.sda_vsn == SCR_SPEC_VER_2) if (storage->scr.sda_vsn == SCR_SPEC_VER_2)
/* Check if Physical Layer Spec v3.0 is supported */
storage->scr.sda_spec3 = unstuff_bits(resp, 47, 1); storage->scr.sda_spec3 = unstuff_bits(resp, 47, 1);
if (storage->scr.sda_spec3) if (storage->scr.sda_spec3)
storage->scr.cmds = unstuff_bits(resp, 32, 2); storage->scr.cmds = unstuff_bits(resp, 32, 2);
@ -820,9 +844,9 @@ int _sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf)
reqbuf.num_sectors = 1; reqbuf.num_sectors = 1;
reqbuf.is_write = 0; reqbuf.is_write = 0;
reqbuf.is_multi_block = 0; reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0; reqbuf.is_auto_stop_trn = 0;
if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, 0)) if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, NULL))
return 0; return 0;
u32 tmp = 0; u32 tmp = 0;
@ -838,7 +862,7 @@ int _sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf)
_sd_storage_parse_scr(storage); _sd_storage_parse_scr(storage);
//gfx_hexdump(0, storage->raw_scr, 8); //gfx_hexdump(0, storage->raw_scr, 8);
return _sdmmc_storage_check_result(tmp); return _sdmmc_storage_check_card_status(tmp);
} }
int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf) int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf)
@ -852,14 +876,14 @@ int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf)
reqbuf.num_sectors = 1; reqbuf.num_sectors = 1;
reqbuf.is_write = 0; reqbuf.is_write = 0;
reqbuf.is_multi_block = 0; reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0; reqbuf.is_auto_stop_trn = 0;
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, 0)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
return 0; return 0;
u32 tmp = 0; u32 tmp = 0;
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1); sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
return _sdmmc_storage_check_result(tmp); return _sdmmc_storage_check_card_status(tmp);
} }
int _sd_storage_switch(sdmmc_storage_t *storage, void *buf, int mode, int group, u32 arg) int _sd_storage_switch(sdmmc_storage_t *storage, void *buf, int mode, int group, u32 arg)
@ -876,14 +900,14 @@ int _sd_storage_switch(sdmmc_storage_t *storage, void *buf, int mode, int group,
reqbuf.num_sectors = 1; reqbuf.num_sectors = 1;
reqbuf.is_write = 0; reqbuf.is_write = 0;
reqbuf.is_multi_block = 0; reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0; reqbuf.is_auto_stop_trn = 0;
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, 0)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
return 0; return 0;
u32 tmp = 0; u32 tmp = 0;
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1); sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
return _sdmmc_storage_check_result(tmp); return _sdmmc_storage_check_card_status(tmp);
} }
void _sd_storage_set_current_limit(sdmmc_storage_t *storage, u16 current_limit, u8 *buf) void _sd_storage_set_current_limit(sdmmc_storage_t *storage, u16 current_limit, u8 *buf)
@ -1057,41 +1081,64 @@ int _sd_storage_enable_hs_high_volt(sdmmc_storage_t *storage, u8 *buf)
return sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_HS25); return sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_HS25);
} }
u32 sd_storage_get_ssr_au(sdmmc_storage_t *storage)
{
u32 au_size = storage->ssr.uhs_au_size;
if (!au_size)
au_size = storage->ssr.au_size;
if (au_size <= 10)
{
u32 shift = au_size;
au_size = shift ? 8 : 0;
au_size <<= shift;
}
else
{
switch (au_size)
{
case 11:
au_size = 12288;
break;
case 12:
au_size = 16384;
break;
case 13:
au_size = 24576;
break;
case 14:
au_size = 32768;
break;
case 15:
au_size = 65536;
break;
}
}
return au_size;
}
static void _sd_storage_parse_ssr(sdmmc_storage_t *storage) static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
{ {
// unstuff_bits supports only 4 u32 so break into 2 x 16byte groups // unstuff_bits supports only 4 u32 so break into 2 x u32x4 groups.
u32 raw_ssr1[4]; u32 raw_ssr1[4];
u32 raw_ssr2[4]; u32 raw_ssr2[4];
raw_ssr1[3] = *(u32 *)&storage->raw_ssr[12]; memcpy(raw_ssr1, &storage->raw_ssr[0], 16);
raw_ssr1[2] = *(u32 *)&storage->raw_ssr[8]; memcpy(raw_ssr2, &storage->raw_ssr[16], 16);
raw_ssr1[1] = *(u32 *)&storage->raw_ssr[4];
raw_ssr1[0] = *(u32 *)&storage->raw_ssr[0];
raw_ssr2[3] = *(u32 *)&storage->raw_ssr[28];
raw_ssr2[2] = *(u32 *)&storage->raw_ssr[24];
raw_ssr2[1] = *(u32 *)&storage->raw_ssr[20];
raw_ssr2[0] = *(u32 *)&storage->raw_ssr[16];
storage->ssr.bus_width = (unstuff_bits(raw_ssr1, 510 - 384, 2) & SD_BUS_WIDTH_4) ? 4 : 1; storage->ssr.bus_width = (unstuff_bits(raw_ssr1, 510 - 384, 2) & SD_BUS_WIDTH_4) ? 4 : 1;
storage->ssr.protected_size = unstuff_bits(raw_ssr1, 448 - 384, 32); storage->ssr.protected_size = unstuff_bits(raw_ssr1, 448 - 384, 32);
switch(unstuff_bits(raw_ssr1, 440 - 384, 8)) u32 speed_class = unstuff_bits(raw_ssr1, 440 - 384, 8);
switch(speed_class)
{ {
case 0: case 0:
storage->ssr.speed_class = 0;
break;
case 1: case 1:
storage->ssr.speed_class = 2;
break;
case 2: case 2:
storage->ssr.speed_class = 4;
break;
case 3: case 3:
storage->ssr.speed_class = 6; storage->ssr.speed_class = speed_class << 1;
break; break;
case 4: case 4:
@ -1099,16 +1146,18 @@ static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
break; break;
default: default:
storage->ssr.speed_class = unstuff_bits(raw_ssr1, 440 - 384, 8); storage->ssr.speed_class = speed_class;
break; break;
} }
storage->ssr.uhs_grade = unstuff_bits(raw_ssr1, 396 - 384, 4); storage->ssr.uhs_grade = unstuff_bits(raw_ssr1, 396 - 384, 4);
storage->ssr.video_class = unstuff_bits(raw_ssr1, 384 - 384, 8); storage->ssr.video_class = unstuff_bits(raw_ssr1, 384 - 384, 8);
storage->ssr.app_class = unstuff_bits(raw_ssr2, 336 - 256, 4);
storage->ssr.app_class = unstuff_bits(raw_ssr2, 336 - 256, 4); storage->ssr.au_size = unstuff_bits(raw_ssr1, 428 - 384, 4);
storage->ssr.uhs_au_size = unstuff_bits(raw_ssr1, 392 - 384, 4);
} }
static int _sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf) int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
{ {
sdmmc_cmd_t cmdbuf; sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmdbuf, SD_APP_SD_STATUS, 0, SDMMC_RSP_TYPE_1, 0); sdmmc_init_cmd(&cmdbuf, SD_APP_SD_STATUS, 0, SDMMC_RSP_TYPE_1, 0);
@ -1119,49 +1168,51 @@ static int _sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
reqbuf.num_sectors = 1; reqbuf.num_sectors = 1;
reqbuf.is_write = 0; reqbuf.is_write = 0;
reqbuf.is_multi_block = 0; reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0; reqbuf.is_auto_stop_trn = 0;
if (!(storage->csd.cmdclass & CCC_APP_SPEC)) if (!(storage->csd.cmdclass & CCC_APP_SPEC))
{ {
DPRINTF("[SD] ssr: Card lacks mandatory SD Status function\n"); DPRINTF("[SD] ssr: Not supported\n");
return 0; return 0;
} }
if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, 0)) if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, NULL))
return 0; return 0;
u32 tmp = 0; u32 tmp = 0;
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1); sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
//Prepare buffer for unstuff_bits
for (int i = 0; i < 64; i+=4) // Convert buffer to LE.
for (int i = 0; i < 64; i += 4)
{ {
storage->raw_ssr[i + 3] = buf[i]; storage->raw_ssr[i + 3] = buf[i];
storage->raw_ssr[i + 2] = buf[i + 1]; storage->raw_ssr[i + 2] = buf[i + 1];
storage->raw_ssr[i + 1] = buf[i + 2]; storage->raw_ssr[i + 1] = buf[i + 2];
storage->raw_ssr[i] = buf[i + 3]; storage->raw_ssr[i] = buf[i + 3];
} }
_sd_storage_parse_ssr(storage); _sd_storage_parse_ssr(storage);
//gfx_hexdump(0, storage->raw_ssr, 64); //gfx_hexdump(0, storage->raw_ssr, 64);
return _sdmmc_storage_check_result(tmp); return _sdmmc_storage_check_card_status(tmp);
} }
static void _sd_storage_parse_cid(sdmmc_storage_t *storage) static void _sd_storage_parse_cid(sdmmc_storage_t *storage)
{ {
u32 *raw_cid = (u32 *)&(storage->raw_cid); u32 *raw_cid = (u32 *)&(storage->raw_cid);
storage->cid.manfid = unstuff_bits(raw_cid, 120, 8); storage->cid.manfid = unstuff_bits(raw_cid, 120, 8);
storage->cid.oemid = unstuff_bits(raw_cid, 104, 16); storage->cid.oemid = unstuff_bits(raw_cid, 104, 16);
storage->cid.prod_name[0] = unstuff_bits(raw_cid, 96, 8); storage->cid.prod_name[0] = unstuff_bits(raw_cid, 96, 8);
storage->cid.prod_name[1] = unstuff_bits(raw_cid, 88, 8); storage->cid.prod_name[1] = unstuff_bits(raw_cid, 88, 8);
storage->cid.prod_name[2] = unstuff_bits(raw_cid, 80, 8); storage->cid.prod_name[2] = unstuff_bits(raw_cid, 80, 8);
storage->cid.prod_name[3] = unstuff_bits(raw_cid, 72, 8); storage->cid.prod_name[3] = unstuff_bits(raw_cid, 72, 8);
storage->cid.prod_name[4] = unstuff_bits(raw_cid, 64, 8); storage->cid.prod_name[4] = unstuff_bits(raw_cid, 64, 8);
storage->cid.hwrev = unstuff_bits(raw_cid, 60, 4); storage->cid.hwrev = unstuff_bits(raw_cid, 60, 4);
storage->cid.fwrev = unstuff_bits(raw_cid, 56, 4); storage->cid.fwrev = unstuff_bits(raw_cid, 56, 4);
storage->cid.serial = unstuff_bits(raw_cid, 24, 32); storage->cid.serial = unstuff_bits(raw_cid, 24, 32);
storage->cid.month = unstuff_bits(raw_cid, 8, 4); storage->cid.year = unstuff_bits(raw_cid, 12, 8) + 2000;
storage->cid.year = unstuff_bits(raw_cid, 12, 8) + 2000; storage->cid.month = unstuff_bits(raw_cid, 8, 4);
} }
static void _sd_storage_parse_csd(sdmmc_storage_t *storage) static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
@ -1176,6 +1227,7 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
{ {
case 0: case 0:
storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2); storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2);
storage->csd.capacity <<= unstuff_bits(raw_csd, 80, 4) - 9; // Convert native block size to LBA 512B.
break; break;
case 1: case 1:
@ -1183,10 +1235,16 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
storage->csd.capacity = storage->csd.c_size << 10; storage->csd.capacity = storage->csd.c_size << 10;
storage->csd.read_blkbits = 9; storage->csd.read_blkbits = 9;
break; break;
default:
DPRINTF("[SD] unknown CSD structure %d\n", storage->csd.structure);
break;
} }
storage->sec_cnt = storage->csd.capacity;
} }
static bool _sdmmc_storage_get_low_voltage_support(u32 bus_width, u32 type) static bool _sdmmc_storage_get_bus_uhs_support(u32 bus_width, u32 type)
{ {
switch (type) switch (type)
{ {
@ -1213,8 +1271,10 @@ void sdmmc_storage_init_wait_sd()
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type) int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type)
{ {
int is_version_1 = 0; u32 tmp = 0;
u8 *buf = (u8 *)SDMMC_UPPER_BUFFER; int is_sdsc = 0;
u8 *buf = (u8 *)SDMMC_UPPER_BUFFER;
bool bus_uhs_support = _sdmmc_storage_get_bus_uhs_support(bus_width, type);
DPRINTF("[SD] init: bus: %d, type: %d\n", bus_width, type); DPRINTF("[SD] init: bus: %d, type: %d\n", bus_width, type);
@ -1234,18 +1294,15 @@ DPRINTF("[SD] after init\n");
return 0; return 0;
DPRINTF("[SD] went to idle state\n"); DPRINTF("[SD] went to idle state\n");
is_version_1 = _sd_storage_send_if_cond(storage); if (!_sd_storage_send_if_cond(storage, &is_sdsc))
if (is_version_1 == 2)
return 0; return 0;
DPRINTF("[SD] after send if cond\n"); DPRINTF("[SD] after send if cond\n");
bool bus_low_voltage_support = _sdmmc_storage_get_low_voltage_support(bus_width, type); if (!_sd_storage_get_op_cond(storage, is_sdsc, bus_uhs_support))
if (!_sd_storage_get_op_cond(storage, is_version_1, bus_low_voltage_support))
return 0; return 0;
DPRINTF("[SD] got op cond\n"); DPRINTF("[SD] got op cond\n");
if (!_sdmmc_storage_get_cid(storage, storage->raw_cid)) if (!_sdmmc_storage_get_cid(storage))
return 0; return 0;
DPRINTF("[SD] got cid\n"); DPRINTF("[SD] got cid\n");
_sd_storage_parse_cid(storage); _sd_storage_parse_cid(storage);
@ -1254,30 +1311,16 @@ DPRINTF("[SD] got cid\n");
return 0; return 0;
DPRINTF("[SD] got rca (= %04X)\n", storage->rca); DPRINTF("[SD] got rca (= %04X)\n", storage->rca);
if (!_sdmmc_storage_get_csd(storage, storage->raw_csd)) if (!_sdmmc_storage_get_csd(storage))
return 0; return 0;
DPRINTF("[SD] got csd\n"); DPRINTF("[SD] got csd\n");
//Parse CSD.
_sd_storage_parse_csd(storage); _sd_storage_parse_csd(storage);
switch (storage->csd.structure)
{
case 0:
storage->sec_cnt = storage->csd.capacity;
break;
case 1:
storage->sec_cnt = storage->csd.c_size << 10;
break;
default:
DPRINTF("[SD] unknown CSD structure %d\n", storage->csd.structure);
break;
}
if (!storage->is_low_voltage) if (!storage->is_low_voltage)
{ {
if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_DS12)) if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_DS12))
return 0; return 0;
DPRINTF("[SD] after setup clock\n"); DPRINTF("[SD] after setup default clock\n");
} }
if (!_sdmmc_storage_select_card(storage)) if (!_sdmmc_storage_select_card(storage))
@ -1288,19 +1331,17 @@ DPRINTF("[SD] card selected\n");
return 0; return 0;
DPRINTF("[SD] set blocklen to 512\n"); DPRINTF("[SD] set blocklen to 512\n");
u32 tmp = 0; // Disconnect Card Detect resistor from DAT3.
if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_CLR_CARD_DETECT, 0, 0, R1_STATE_TRAN)) if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_CLR_CARD_DETECT, 0, 0, R1_STATE_TRAN))
return 0; return 0;
DPRINTF("[SD] cleared card detect\n"); DPRINTF("[SD] cleared card detect\n");
if (!_sd_storage_get_scr(storage, buf)) if (!_sd_storage_get_scr(storage, buf))
return 0; return 0;
//gfx_hexdump(0, storage->raw_scr, 8);
DPRINTF("[SD] got scr\n"); DPRINTF("[SD] got scr\n");
// Check if card supports a wider bus and if it's not SD Version 1.X // If card supports a wider bus and if it's not SD Version 1.0 switch bus width.
if (bus_width == SDMMC_BUS_WIDTH_4 && (storage->scr.bus_widths & 4) && (storage->scr.sda_vsn & 0xF)) if (bus_width == SDMMC_BUS_WIDTH_4 && (storage->scr.bus_widths & BIT(SD_BUS_WIDTH_4)) && storage->scr.sda_vsn)
{ {
if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_BUS_WIDTH, SD_BUS_WIDTH_4, 0, R1_STATE_TRAN)) if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_BUS_WIDTH, SD_BUS_WIDTH_4, 0, R1_STATE_TRAN))
return 0; return 0;
@ -1310,6 +1351,7 @@ DPRINTF("[SD] switched to wide bus width\n");
} }
else else
{ {
bus_width = SDMMC_BUS_WIDTH_1;
DPRINTF("[SD] SD does not support wide bus width\n"); DPRINTF("[SD] SD does not support wide bus width\n");
} }
@ -1321,7 +1363,7 @@ DPRINTF("[SD] enabled UHS\n");
sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE); sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE);
} }
else if (type != SDHCI_TIMING_SD_DS12 && (storage->scr.sda_vsn & 0xF) != 0) else if (type != SDHCI_TIMING_SD_DS12 && storage->scr.sda_vsn) // Not default speed and not SD Version 1.0.
{ {
if (!_sd_storage_enable_hs_high_volt(storage, buf)) if (!_sd_storage_enable_hs_high_volt(storage, buf))
return 0; return 0;
@ -1340,7 +1382,7 @@ DPRINTF("[SD] enabled HS\n");
} }
// Parse additional card info from sd status. // Parse additional card info from sd status.
if (_sd_storage_get_ssr(storage, buf)) if (sd_storage_get_ssr(storage, buf))
{ {
DPRINTF("[SD] got sd status\n"); DPRINTF("[SD] got sd status\n");
} }
@ -1351,14 +1393,14 @@ DPRINTF("[SD] got sd status\n");
} }
/* /*
* Gamecard specific functions. * Gamecard specific functions.
*/ */
int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf) int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf)
{ {
u32 resp; u32 resp;
sdmmc_cmd_t cmdbuf; sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmdbuf, 60, 0, SDMMC_RSP_TYPE_1, 1); sdmmc_init_cmd(&cmdbuf, MMC_VENDOR_60_CMD, 0, SDMMC_RSP_TYPE_1, 1);
sdmmc_req_t reqbuf; sdmmc_req_t reqbuf;
reqbuf.buf = buf; reqbuf.buf = buf;
@ -1366,9 +1408,9 @@ int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf)
reqbuf.num_sectors = 1; reqbuf.num_sectors = 1;
reqbuf.is_write = 1; reqbuf.is_write = 1;
reqbuf.is_multi_block = 0; reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0; reqbuf.is_auto_stop_trn = 0;
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, 0)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
{ {
sdmmc_stop_transmission(storage->sdmmc, &resp); sdmmc_stop_transmission(storage->sdmmc, &resp);
return 0; return 0;
@ -1376,7 +1418,7 @@ int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf)
if (!sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_1)) if (!sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_1))
return 0; return 0;
if (!_sdmmc_storage_check_result(resp)) if (!_sdmmc_storage_check_card_status(resp))
return 0; return 0;
return _sdmmc_storage_check_status(storage); return _sdmmc_storage_check_status(storage);
} }

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer * Copyright (c) 2018-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -30,18 +30,18 @@ typedef enum _sdmmc_type
EMMC_GPP = 0, EMMC_GPP = 0,
EMMC_BOOT0 = 1, EMMC_BOOT0 = 1,
EMMC_BOOT1 = 2 EMMC_BOOT1 = 2,
EMMC_RPMB = 3
} sdmmc_type; } sdmmc_type;
typedef struct _mmc_cid typedef struct _mmc_cid
{ {
u32 manfid; u32 manfid;
u8 prod_name[8]; u8 prod_name[8];
u8 card_bga;
u8 prv;
u32 serial; u32 serial;
u16 oemid; u16 oemid;
u16 year; u16 year;
u8 prv;
u8 hwrev; u8 hwrev;
u8 fwrev; u8 fwrev;
u8 month; u8 month;
@ -65,19 +65,20 @@ typedef struct _mmc_csd
typedef struct _mmc_ext_csd typedef struct _mmc_ext_csd
{ {
u32 sectors; //u8 bkops; /* background support bit */
int bkops; /* background support bit */ //u8 bkops_en; /* manual bkops enable bit */
int bkops_en; /* manual bkops enable bit */ //u8 bkops_status; /* 246 */
u8 rev; u8 rev;
u8 ext_struct; /* 194 */ u8 ext_struct; /* 194 */
u8 card_type; /* 196 */ u8 card_type; /* 196 */
u8 bkops_status; /* 246 */
u8 pre_eol_info; u8 pre_eol_info;
u8 dev_life_est_a; u8 dev_life_est_a;
u8 dev_life_est_b; u8 dev_life_est_b;
u8 boot_mult; u8 boot_mult;
u8 rpmb_mult; u8 rpmb_mult;
u16 dev_version; u16 dev_version;
u32 cache_size;
u32 max_enh_mult;
} mmc_ext_csd_t; } mmc_ext_csd_t;
typedef struct _sd_scr typedef struct _sd_scr
@ -90,11 +91,13 @@ typedef struct _sd_scr
typedef struct _sd_ssr typedef struct _sd_ssr
{ {
u8 bus_width; u8 bus_width;
u8 speed_class; u8 speed_class;
u8 uhs_grade; u8 uhs_grade;
u8 video_class; u8 video_class;
u8 app_class; u8 app_class;
u8 au_size;
u8 uhs_au_size;
u32 protected_size; u32 protected_size;
} sd_ssr_t; } sd_ssr_t;
@ -107,6 +110,7 @@ typedef struct _sdmmc_storage_t
u32 sec_cnt; u32 sec_cnt;
int is_low_voltage; int is_low_voltage;
u32 partition; u32 partition;
int initialized;
u8 raw_cid[0x10]; u8 raw_cid[0x10];
u8 raw_csd[0x10]; u8 raw_csd[0x10];
u8 raw_scr[8]; u8 raw_scr[8];
@ -116,16 +120,18 @@ typedef struct _sdmmc_storage_t
mmc_ext_csd_t ext_csd; mmc_ext_csd_t ext_csd;
sd_scr_t scr; sd_scr_t scr;
sd_ssr_t ssr; sd_ssr_t ssr;
int initialized;
} sdmmc_storage_t; } sdmmc_storage_t;
int sdmmc_storage_end(sdmmc_storage_t *storage); int sdmmc_storage_end(sdmmc_storage_t *storage);
int sdmmc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf); int sdmmc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf);
int sdmmc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf); int sdmmc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf);
int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type); int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type);
int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition); int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition);
void sdmmc_storage_init_wait_sd(); void sdmmc_storage_init_wait_sd();
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type); int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type);
int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc); int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc);
int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf);
u32 sd_storage_get_ssr_au(sdmmc_storage_t *storage);
#endif #endif

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer * Copyright (c) 2018-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -501,7 +501,7 @@ int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type)
break; break;
case SDMMC_RSP_TYPE_2: case SDMMC_RSP_TYPE_2:
if (size < 0x10) if (size < 16)
return 0; return 0;
rsp[0] = sdmmc->rsp[0]; rsp[0] = sdmmc->rsp[0];
rsp[1] = sdmmc->rsp[1]; rsp[1] = sdmmc->rsp[1];
@ -934,12 +934,20 @@ static int _sdmmc_config_dma(sdmmc_t *sdmmc, u32 *blkcnt_out, sdmmc_req_t *req)
*blkcnt_out = blkcnt; *blkcnt_out = blkcnt;
u32 trnmode = SDHCI_TRNS_DMA; u32 trnmode = SDHCI_TRNS_DMA;
// Set mulitblock request.
if (req->is_multi_block) if (req->is_multi_block)
trnmode = SDHCI_TRNS_MULTI | SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_DMA; trnmode = SDHCI_TRNS_MULTI | SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_DMA;
// Set request direction.
if (!req->is_write) if (!req->is_write)
trnmode |= SDHCI_TRNS_READ; trnmode |= SDHCI_TRNS_READ;
if (req->is_auto_cmd12)
trnmode = (trnmode & ~(SDHCI_TRNS_AUTO_CMD12 | SDHCI_TRNS_AUTO_CMD23)) | SDHCI_TRNS_AUTO_CMD12; // Automatic send of stop transmission or set block count cmd.
if (req->is_auto_stop_trn)
trnmode |= SDHCI_TRNS_AUTO_CMD12;
//else if (req->is_auto_set_blkcnt)
// trnmode |= SDHCI_TRNS_AUTO_CMD23;
sdmmc->regs->trnmod = trnmode; sdmmc->regs->trnmod = trnmode;
@ -1052,7 +1060,7 @@ DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result,
if (!result) if (!result)
{ {
#ifdef ERROR_EXTRA_PRINTING #ifdef ERROR_EXTRA_PRINTING
EPRINTFARGS("SDMMC: DMA Update failed (%08X)!", result); EPRINTF("SDMMC: DMA Update failed!");
#endif #endif
} }
} }
@ -1070,7 +1078,7 @@ DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result,
if (blkcnt_out) if (blkcnt_out)
*blkcnt_out = blkcnt; *blkcnt_out = blkcnt;
if (req->is_auto_cmd12) if (req->is_auto_stop_trn)
sdmmc->rsp3 = sdmmc->regs->rspreg3; sdmmc->rsp3 = sdmmc->regs->rspreg3;
} }
@ -1200,8 +1208,8 @@ static int _sdmmc_config_sdmmc1(bool t210b01)
usleep(10000); usleep(10000);
// Enable SD card IO power. // Enable SD card IO power.
max77620_regulator_set_voltage(REGULATOR_LDO2, 3300000); max7762x_regulator_set_voltage(REGULATOR_LDO2, 3300000);
max77620_regulator_enable(REGULATOR_LDO2, 1); max7762x_regulator_enable(REGULATOR_LDO2, true);
usleep(1000); usleep(1000);
// Set pad slew codes to get good quality clock. // Set pad slew codes to get good quality clock.
@ -1332,18 +1340,6 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int p
void sdmmc1_disable_power() void sdmmc1_disable_power()
{ {
// Ensure regulator is into default voltage.
if (PMC(APBDEV_PMC_PWR_DET_VAL) & PMC_PWR_DET_SDMMC1_IO_EN)
{
// Switch to 1.8V and wait for regulator to stabilize.
max77620_regulator_set_voltage(REGULATOR_LDO2, 1800000);
usleep(150);
// Inform IO pads that we switched to 1.8V.
PMC(APBDEV_PMC_PWR_DET_VAL) &= ~(PMC_PWR_DET_SDMMC1_IO_EN);
(void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write.
}
// T210B01 WAR: Clear pull down from CLK pad. // T210B01 WAR: Clear pull down from CLK pad.
PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) &= ~PINMUX_PULL_MASK; PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) &= ~PINMUX_PULL_MASK;
@ -1351,7 +1347,7 @@ void sdmmc1_disable_power()
_sdmmc_config_sdmmc1_pads(true); _sdmmc_config_sdmmc1_pads(true);
// Disable SD card IO power regulator. // Disable SD card IO power regulator.
max77620_regulator_enable(REGULATOR_LDO2, 0); max7762x_regulator_enable(REGULATOR_LDO2, false);
usleep(4000); usleep(4000);
// Disable SD card IO power pin. // Disable SD card IO power pin.
@ -1383,12 +1379,12 @@ void sdmmc_end(sdmmc_t *sdmmc)
_sdmmc_sd_clock_disable(sdmmc); _sdmmc_sd_clock_disable(sdmmc);
// Disable SDMMC power. // Disable SDMMC power.
_sdmmc_set_io_power(sdmmc, SDMMC_POWER_OFF); _sdmmc_set_io_power(sdmmc, SDMMC_POWER_OFF);
_sdmmc_commit_changes(sdmmc);
// Disable SD card power. // Disable SD card power.
if (sdmmc->id == SDMMC_1) if (sdmmc->id == SDMMC_1)
sdmmc1_disable_power(); sdmmc1_disable_power();
_sdmmc_commit_changes(sdmmc);
clock_sdmmc_disable(sdmmc->id); clock_sdmmc_disable(sdmmc->id);
sdmmc->clock_stopped = 1; sdmmc->clock_stopped = 1;
} }
@ -1440,7 +1436,7 @@ int sdmmc_enable_low_voltage(sdmmc_t *sdmmc)
_sdmmc_commit_changes(sdmmc); _sdmmc_commit_changes(sdmmc);
// Switch to 1.8V and wait for regulator to stabilize. Assume max possible wait needed. // Switch to 1.8V and wait for regulator to stabilize. Assume max possible wait needed.
max77620_regulator_set_voltage(REGULATOR_LDO2, 1800000); max7762x_regulator_set_voltage(REGULATOR_LDO2, 1800000);
usleep(150); usleep(150);
// Inform IO pads that we switched to 1.8V. // Inform IO pads that we switched to 1.8V.

View File

@ -242,7 +242,7 @@ typedef struct _sdmmc_req_t
u32 num_sectors; u32 num_sectors;
int is_write; int is_write;
int is_multi_block; int is_multi_block;
int is_auto_cmd12; int is_auto_stop_trn;
} sdmmc_req_t; } sdmmc_req_t;
int sdmmc_get_io_power(sdmmc_t *sdmmc); int sdmmc_get_io_power(sdmmc_t *sdmmc);

View File

@ -26,7 +26,7 @@
void set_fan_duty(u32 duty) void set_fan_duty(u32 duty)
{ {
static bool fan_init = false; static bool fan_init = false;
static u16 curr_duty = -1; static u16 curr_duty = -1;
if (curr_duty == duty) if (curr_duty == duty)
return; return;
@ -56,7 +56,7 @@ void set_fan_duty(u32 duty)
if (inv_duty == 236) if (inv_duty == 236)
{ {
PWM(PWM_CONTROLLER_PWM_CSR_1) = PWM_CSR_EN | (0x100 << 16); // Bit 24 is absolute 0%. PWM(PWM_CONTROLLER_PWM_CSR_1) = PWM_CSR_EN | (0x100 << 16); // Bit 24 is absolute 0%.
regulator_disable_5v(REGULATOR_5V_FAN); regulator_5v_disable(REGULATOR_5V_FAN);
// Disable fan. // Disable fan.
PINMUX_AUX(PINMUX_AUX_LCD_GPIO2) = PINMUX_AUX(PINMUX_AUX_LCD_GPIO2) =
@ -65,7 +65,7 @@ void set_fan_duty(u32 duty)
else // Set PWM duty. else // Set PWM duty.
{ {
// Fan power supply. // Fan power supply.
regulator_enable_5v(REGULATOR_5V_FAN); regulator_5v_enable(REGULATOR_5V_FAN);
PWM(PWM_CONTROLLER_PWM_CSR_1) = PWM_CSR_EN | (inv_duty << 16); PWM(PWM_CONTROLLER_PWM_CSR_1) = PWM_CSR_EN | (inv_duty << 16);
// Enable fan. // Enable fan.
@ -79,15 +79,14 @@ void get_fan_speed(u32 *duty, u32 *rpm)
{ {
if (rpm) if (rpm)
{ {
u32 irq_count = 1; u32 irq_count = 0;
bool should_read = true; bool should_read = true;
bool irq_val = 0;
// Poll irqs for 2 seconds. // Poll irqs for 2 seconds. (5 seconds for accurate count).
int timer = get_tmr_us() + 1000000; int timer = get_tmr_us() + 2000000;
while (timer - get_tmr_us()) while ((timer - get_tmr_us()) > 0)
{ {
irq_val = gpio_read(GPIO_PORT_S, GPIO_PIN_7); bool irq_val = gpio_read(GPIO_PORT_S, GPIO_PIN_7);
if (irq_val && should_read) if (irq_val && should_read)
{ {
irq_count++; irq_count++;
@ -97,8 +96,11 @@ void get_fan_speed(u32 *duty, u32 *rpm)
should_read = true; should_read = true;
} }
// Halve the irq count.
irq_count /= 2;
// Calculate rpm based on triggered interrupts. // Calculate rpm based on triggered interrupts.
*rpm = 60000000 / ((1000000 * 2) / irq_count); *rpm = irq_count * (60 / 2);
} }
if (duty) if (duty)

View File

@ -1,7 +1,7 @@
/* /*
* SOC/PCB Temperature driver for Nintendo Switch's TI TMP451 * SOC/PCB Temperature driver for Nintendo Switch's TI TMP451
* *
* Copyright (c) 2018 CTCaer * Copyright (c) 2018-2020 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,
@ -16,7 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <soc/hw_init.h>
#include <soc/i2c.h> #include <soc/i2c.h>
#include <soc/t210.h>
#include <thermal/tmp451.h> #include <thermal/tmp451.h>
u16 tmp451_get_soc_temp(bool intenger) u16 tmp451_get_soc_temp(bool intenger)
@ -56,6 +58,20 @@ void tmp451_init()
// Disable ALARM and Range to 0 - 127 oC. // Disable ALARM and Range to 0 - 127 oC.
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CONFIG_REG, 0x80); i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CONFIG_REG, 0x80);
// Set remote sensor offsets based on SoC.
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210)
{
// Set offset to 0 oC for Erista.
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TMP_OFH_REG, 0);
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TMP_OFL_REG, 0);
}
else
{
// Set offset to -12.5 oC for Mariko.
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TMP_OFH_REG, 0xF3); // - 13 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 32/s 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);
@ -63,3 +79,9 @@ void tmp451_init()
// Set rate to every 4 seconds. // Set rate to every 4 seconds.
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CNV_RATE_REG, 2); i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CNV_RATE_REG, 2);
} }
void tmp451_end()
{
// Place into shutdown mode to conserve power.
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CONFIG_REG, 0xC0);
}

View File

@ -32,11 +32,15 @@
#define TMP451_SOC_TMP_DEC_REG 0x10 #define TMP451_SOC_TMP_DEC_REG 0x10
#define TMP451_PCB_TMP_DEC_REG 0x15 #define TMP451_PCB_TMP_DEC_REG 0x15
#define TMP451_SOC_TMP_OFH_REG 0x11
#define TMP451_SOC_TMP_OFL_REG 0x12
// If input is false, the return value is packed. MSByte is the integer in oC // If input is false, the return value is packed. MSByte is the integer in oC
// and the LSByte is the decimal point truncated to 2 decimal places. // and the LSByte is the decimal point truncated to 2 decimal places.
// Otherwise it's an integer oC. // Otherwise it's an integer oC.
u16 tmp451_get_soc_temp(bool integer); u16 tmp451_get_soc_temp(bool integer);
u16 tmp451_get_pcb_temp(bool integer); u16 tmp451_get_pcb_temp(bool integer);
void tmp451_init(); void tmp451_init();
void tmp451_end();
#endif /* __TMP451_H_ */ #endif /* __TMP451_H_ */

View File

@ -309,7 +309,7 @@ static bool _fts_touch_read(touchpad_report_t *rpt)
static u8 _hid_transfer_start(usb_ctxt_t *usbs, u32 len) static u8 _hid_transfer_start(usb_ctxt_t *usbs, u32 len)
{ {
u8 status = usb_ops.usb_device_ep1_in_write((u8 *)USB_EP_BULK_IN_BUF_ADDR, len, NULL, USB_XFER_SYNCED); u8 status = usb_ops.usb_device_ep1_in_write((u8 *)USB_EP_BULK_IN_BUF_ADDR, len, NULL, USB_XFER_SYNCED_CMD);
if (status == USB_ERROR_XFER_ERROR) if (status == USB_ERROR_XFER_ERROR)
{ {
usbs->set_text(usbs->label, "#FFDD00 Error:# EP IN transfer!"); usbs->set_text(usbs->label, "#FFDD00 Error:# EP IN transfer!");

View File

@ -58,7 +58,7 @@
#define UMS_SCSI_TRANSFER_512K (0x80000 >> UMS_DISK_LBA_SHIFT) #define UMS_SCSI_TRANSFER_512K (0x80000 >> UMS_DISK_LBA_SHIFT)
#define UMS_EP_OUT_MAX_XFER (USB_EP_BULK_OUT_MAX_XFER >> UMS_DISK_LBA_SHIFT) #define UMS_EP_OUT_MAX_XFER (USB_EP_BULK_OUT_MAX_XFER)
// Length of a SCSI Command Data Block. // Length of a SCSI Command Data Block.
#define SCSI_MAX_CMD_SZ 16 #define SCSI_MAX_CMD_SZ 16
@ -121,6 +121,15 @@ enum ums_state {
UMS_STATE_TERMINATED UMS_STATE_TERMINATED
}; };
enum ums_result {
UMS_RES_OK = 0,
UMS_RES_IO_ERROR = -5,
UMS_RES_TIMEOUT = -3,
UMS_RES_PROT_FATAL = -4,
UMS_RES_INVALID_ARG = -22
};
enum data_direction { enum data_direction {
DATA_DIR_UNKNOWN = 0, DATA_DIR_UNKNOWN = 0,
DATA_DIR_FROM_HOST, DATA_DIR_FROM_HOST,
@ -194,7 +203,7 @@ typedef struct _bulk_ctxt_t {
typedef struct _usbd_gadget_ums_t { typedef struct _usbd_gadget_ums_t {
bulk_ctxt_t bulk_ctxt; bulk_ctxt_t bulk_ctxt;
int cmnd_size; u32 cmnd_size;
u8 cmnd[SCSI_MAX_CMD_SZ]; u8 cmnd[SCSI_MAX_CMD_SZ];
u32 lun_idx; // lun index u32 lun_idx; // lun index
@ -283,21 +292,21 @@ static int ums_wedge_bulk_in_endpoint(usbd_gadget_ums_t *ums)
{ {
/* usbd_set_ep_wedge(bulk_ctxt->bulk_in); */ /* usbd_set_ep_wedge(bulk_ctxt->bulk_in); */
return 0; return UMS_RES_OK;
} }
static int ums_set_stall(u32 ep) static int ums_set_stall(u32 ep)
{ {
usb_ops.usbd_set_ep_stall(ep, USB_EP_CFG_STALL); usb_ops.usbd_set_ep_stall(ep, USB_EP_CFG_STALL);
return 0; return UMS_RES_OK;
} }
static int ums_clear_stall(u32 ep) static int ums_clear_stall(u32 ep)
{ {
usb_ops.usbd_set_ep_stall(ep, USB_EP_CFG_CLEAR); usb_ops.usbd_set_ep_stall(ep, USB_EP_CFG_CLEAR);
return 0; return UMS_RES_OK;
} }
static void ums_flush_endpoint(u32 ep) static void ums_flush_endpoint(u32 ep)
@ -306,13 +315,13 @@ static void ums_flush_endpoint(u32 ep)
usb_ops.usbd_flush_endpoint(ep); usb_ops.usbd_flush_endpoint(ep);
} }
static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32 ep, bool sync) static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32 ep, u32 sync_timeout)
{ {
if (ep == bulk_ctxt->bulk_in) if (ep == bulk_ctxt->bulk_in)
{ {
bulk_ctxt->bulk_in_status = usb_ops.usb_device_ep1_in_write( bulk_ctxt->bulk_in_status = usb_ops.usb_device_ep1_in_write(
bulk_ctxt->bulk_in_buf, bulk_ctxt->bulk_in_length, bulk_ctxt->bulk_in_buf, bulk_ctxt->bulk_in_length,
&bulk_ctxt->bulk_in_length_actual, sync); &bulk_ctxt->bulk_in_length_actual, sync_timeout);
if (bulk_ctxt->bulk_in_status == USB_ERROR_XFER_ERROR) if (bulk_ctxt->bulk_in_status == USB_ERROR_XFER_ERROR)
{ {
@ -322,14 +331,14 @@ static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt,
else if (bulk_ctxt->bulk_in_status == USB2_ERROR_XFER_NOT_ALIGNED) else if (bulk_ctxt->bulk_in_status == USB2_ERROR_XFER_NOT_ALIGNED)
ums->set_text(ums->label, "#FFDD00 Error:# EP IN Buffer not aligned!"); ums->set_text(ums->label, "#FFDD00 Error:# EP IN Buffer not aligned!");
if (sync) if (sync_timeout)
bulk_ctxt->bulk_in_buf_state = BUF_STATE_EMPTY; bulk_ctxt->bulk_in_buf_state = BUF_STATE_EMPTY;
} }
else else
{ {
bulk_ctxt->bulk_out_status = usb_ops.usb_device_ep1_out_read( bulk_ctxt->bulk_out_status = usb_ops.usb_device_ep1_out_read(
bulk_ctxt->bulk_out_buf, bulk_ctxt->bulk_out_length, bulk_ctxt->bulk_out_buf, bulk_ctxt->bulk_out_length,
&bulk_ctxt->bulk_out_length_actual, sync); &bulk_ctxt->bulk_out_length_actual, sync_timeout);
if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR) if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR)
{ {
@ -339,7 +348,7 @@ static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt,
else if (bulk_ctxt->bulk_out_status == USB2_ERROR_XFER_NOT_ALIGNED) else if (bulk_ctxt->bulk_out_status == USB2_ERROR_XFER_NOT_ALIGNED)
ums->set_text(ums->label, "#FFDD00 Error:# EP OUT Buffer not aligned!"); ums->set_text(ums->label, "#FFDD00 Error:# EP OUT Buffer not aligned!");
if (sync) if (sync_timeout)
bulk_ctxt->bulk_out_buf_state = BUF_STATE_FULL; bulk_ctxt->bulk_out_buf_state = BUF_STATE_FULL;
} }
} }
@ -377,7 +386,7 @@ static void _ums_transfer_finish(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt,
else else
{ {
bulk_ctxt->bulk_out_status = usb_ops.usb_device_ep1_out_reading_finish( bulk_ctxt->bulk_out_status = usb_ops.usb_device_ep1_out_reading_finish(
&bulk_ctxt->bulk_out_length_actual, 1000000); &bulk_ctxt->bulk_out_length_actual);
if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR) if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR)
{ {
@ -446,20 +455,20 @@ static int _scsi_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{ {
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
return -22; // Invalid argument. return UMS_RES_INVALID_ARG;
} }
} }
if (lba_offset >= ums->lun.num_sectors) if (lba_offset >= ums->lun.num_sectors)
{ {
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
return -22; // Invalid argument. return UMS_RES_INVALID_ARG;
} }
// Check that request data size is not 0. // Check that request data size is not 0.
u32 amount_left = ums->data_size_from_cmnd >> UMS_DISK_LBA_SHIFT; u32 amount_left = ums->data_size_from_cmnd >> UMS_DISK_LBA_SHIFT;
if (!amount_left) if (!amount_left)
return -5; // I/O error. /* No default reply */ return UMS_RES_IO_ERROR; // No default reply.
// Limit IO transfers based on request for faster concurrent reads. // Limit IO transfers based on request for faster concurrent reads.
u32 max_io_transfer = (amount_left >= UMS_SCSI_TRANSFER_512K) ? u32 max_io_transfer = (amount_left >= UMS_SCSI_TRANSFER_512K) ?
@ -520,7 +529,7 @@ static int _scsi_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
sdmmc_buf += amount << UMS_DISK_LBA_SHIFT; sdmmc_buf += amount << UMS_DISK_LBA_SHIFT;
} }
return -5; // I/O error no default reply here. /* No default reply */ return UMS_RES_IO_ERROR; // No default reply.
} }
/* /*
@ -541,7 +550,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{ {
ums->lun.sense_data = SS_WRITE_PROTECTED; ums->lun.sense_data = SS_WRITE_PROTECTED;
return -22; // Invalid argument. return UMS_RES_INVALID_ARG;
} }
if (ums->cmnd[0] == SC_WRITE_6) if (ums->cmnd[0] == SC_WRITE_6)
@ -555,7 +564,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{ {
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
return -22; // Invalid argument. return UMS_RES_INVALID_ARG;
} }
} }
@ -564,7 +573,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{ {
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
return -22; // Invalid argument. return UMS_RES_INVALID_ARG;
} }
/* Carry out the file writes */ /* Carry out the file writes */
@ -574,22 +583,20 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
while (amount_left_to_write > 0) while (amount_left_to_write > 0)
{ {
/* Queue a request for more data from the host */ /* Queue a request for more data from the host */
if (amount_left_to_req) if (amount_left_to_req > 0)
{ {
// Limit write to max supported read from EP OUT. // Limit write to max supported read from EP OUT.
amount = MIN(amount_left_to_req, UMS_EP_OUT_MAX_XFER << UMS_DISK_LBA_SHIFT); amount = MIN(amount_left_to_req, UMS_EP_OUT_MAX_XFER);
if (usb_lba_offset >= ums->lun.num_sectors) //////////Check if it works with concurrency if (usb_lba_offset >= ums->lun.num_sectors)
{ {
ums->set_text(ums->label, "#FFDD00 Error:# Write - Past last sector!"); ums->set_text(ums->label, "#FFDD00 Error:# Write - Past last sector!");
amount_left_to_req = 0;
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;
continue; break;
} }
// Get the next buffer. // Get the next buffer.
@ -612,7 +619,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
ums->lun.sense_data = SS_COMMUNICATION_FAILURE; ums->lun.sense_data = SS_COMMUNICATION_FAILURE;
ums->lun.sense_data_info = lba_offset; ums->lun.sense_data_info = lba_offset;
ums->lun.info_valid = 1; ums->lun.info_valid = 1;
sprintf(txt_buf, "#FFDD00 Error:# Write - Comm failure %d!", bulk_ctxt->bulk_out_status); s_printf(txt_buf, "#FFDD00 Error:# Write - Comm failure %d!", bulk_ctxt->bulk_out_status);
ums->set_text(ums->label, txt_buf); ums->set_text(ums->label, txt_buf);
break; break;
} }
@ -668,7 +675,7 @@ DPRINTF("file write %X @ %X\n", amount, lba_offset);
} }
} }
return -5; // I/O error. /* No default reply */ return UMS_RES_IO_ERROR; // No default reply.
} }
static int _scsi_verify(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) static int _scsi_verify(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
@ -679,7 +686,7 @@ static int _scsi_verify(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{ {
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
return -22; // Invalid argument. return UMS_RES_INVALID_ARG;
} }
// We allow DPO but we don't implement it. Check that nothing else is enabled. // We allow DPO but we don't implement it. Check that nothing else is enabled.
@ -687,12 +694,12 @@ static int _scsi_verify(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{ {
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
return -22; // Invalid argument. return UMS_RES_INVALID_ARG;
} }
u32 verification_length = get_array_be_to_le16(&ums->cmnd[7]); u32 verification_length = get_array_be_to_le16(&ums->cmnd[7]);
if (verification_length == 0) if (verification_length == 0)
return -5; // I/O error. /* No default reply */ return UMS_RES_IO_ERROR; // No default reply.
u32 amount; u32 amount;
while (verification_length > 0) while (verification_length > 0)
@ -724,7 +731,7 @@ DPRINTF("File read %X @ %X\n", amount, lba_offset);
lba_offset += amount; lba_offset += amount;
verification_length -= amount; verification_length -= amount;
} }
return 0; return UMS_RES_OK;
} }
static int _scsi_inquiry(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) static int _scsi_inquiry(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
@ -742,7 +749,7 @@ static int _scsi_inquiry(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
buf[3] = 20; // Additional length. buf[3] = 20; // Additional length.
buf += 4; buf += 4;
sprintf((char *)buf, "%04X%s", s_printf((char *)buf, "%04X%s",
ums->lun.storage->cid.serial, ums->lun.type == MMC_SD ? " SD " : " eMMC "); ums->lun.storage->cid.serial, ums->lun.type == MMC_SD ? " SD " : " eMMC ");
switch (ums->lun.partition) switch (ums->lun.partition)
@ -751,13 +758,13 @@ static int _scsi_inquiry(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
strcpy((char *)buf + strlen((char *)buf), "RAW"); strcpy((char *)buf + strlen((char *)buf), "RAW");
break; break;
case EMMC_GPP + 1: case EMMC_GPP + 1:
sprintf((char *)buf + strlen((char *)buf), "GPP"); s_printf((char *)buf + strlen((char *)buf), "GPP");
break; break;
case EMMC_BOOT0 + 1: case EMMC_BOOT0 + 1:
sprintf((char *)buf + strlen((char *)buf), "BOOT0"); s_printf((char *)buf + strlen((char *)buf), "BOOT0");
break; break;
case EMMC_BOOT1 + 1: case EMMC_BOOT1 + 1:
sprintf((char *)buf + strlen((char *)buf), "BOOT1"); s_printf((char *)buf + strlen((char *)buf), "BOOT1");
break; break;
} }
@ -784,18 +791,18 @@ 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:
sprintf((char *)buf, "%s", "SD RAW"); s_printf((char *)buf, "%s", "SD RAW");
break; break;
case EMMC_GPP + 1: case EMMC_GPP + 1:
sprintf((char *)buf, "%s%s", s_printf((char *)buf, "%s%s",
ums->lun.type == MMC_SD ? "SD " : "eMMC ", "GPP"); ums->lun.type == MMC_SD ? "SD " : "eMMC ", "GPP");
break; break;
case EMMC_BOOT0 + 1: case EMMC_BOOT0 + 1:
sprintf((char *)buf, "%s%s", s_printf((char *)buf, "%s%s",
ums->lun.type == MMC_SD ? "SD " : "eMMC ", "BOOT0"); ums->lun.type == MMC_SD ? "SD " : "eMMC ", "BOOT0");
break; break;
case EMMC_BOOT1 + 1: case EMMC_BOOT1 + 1:
sprintf((char *)buf, "%s%s", s_printf((char *)buf, "%s%s",
ums->lun.type == MMC_SD ? "SD " : "eMMC ", "BOOT1"); ums->lun.type == MMC_SD ? "SD " : "eMMC ", "BOOT1");
break; break;
} }
@ -843,7 +850,7 @@ static int _scsi_read_capacity(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{ {
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
return -22; // Invalid argument. return UMS_RES_INVALID_ARG;
} }
put_array_le_to_be32(ums->lun.num_sectors - 1, &buf[0]); // Max logical block. put_array_le_to_be32(ums->lun.num_sectors - 1, &buf[0]); // Max logical block.
@ -866,14 +873,14 @@ static int _scsi_log_sense(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{ {
ums->lun.sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED; ums->lun.sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED;
return -22; // Invalid argument. return UMS_RES_INVALID_ARG;
} }
if (pc != 1) // Current cumulative values. if (pc != 1) // Current cumulative values.
{ {
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
return -22; // Invalid argument. return UMS_RES_INVALID_ARG;
} }
memset(buf, 0, 8); memset(buf, 0, 8);
@ -915,7 +922,7 @@ static int _scsi_log_sense(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{ {
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
return -22; // Invalid argument. return UMS_RES_INVALID_ARG;
} }
put_array_le_to_be16(len - 4, &buf0[2]); put_array_le_to_be16(len - 4, &buf0[2]);
@ -938,14 +945,14 @@ static int _scsi_mode_sense(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{ {
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
return -22; // Invalid argument. return UMS_RES_INVALID_ARG;
} }
if (pc == 3) if (pc == 3)
{ {
ums->lun.sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED; ums->lun.sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED;
return -22; // Invalid argument. return UMS_RES_INVALID_ARG;
} }
/* Write the mode parameter header. Fixed values are: default /* Write the mode parameter header. Fixed values are: default
@ -995,7 +1002,7 @@ static int _scsi_mode_sense(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{ {
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
return -22; // Invalid argument. return UMS_RES_INVALID_ARG;
} }
/* Store the mode data length */ /* Store the mode data length */
@ -1015,14 +1022,14 @@ static int _scsi_start_stop(usbd_gadget_ums_t *ums)
{ {
ums->lun.sense_data = SS_INVALID_COMMAND; ums->lun.sense_data = SS_INVALID_COMMAND;
return -22; // Invalid argument. return UMS_RES_INVALID_ARG;
} }
else if ((ums->cmnd[1] & ~0x01) != 0 || // Mask away Immed. else if ((ums->cmnd[1] & ~0x01) != 0 || // Mask away Immed.
(ums->cmnd[4] & ~0x03) != 0) // Mask LoEj, Start. (ums->cmnd[4] & ~0x03) != 0) // Mask LoEj, Start.
{ {
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
return -22; return UMS_RES_INVALID_ARG;
} }
loej = ums->cmnd[4] & 0x02; loej = ums->cmnd[4] & 0x02;
@ -1035,10 +1042,10 @@ static int _scsi_start_stop(usbd_gadget_ums_t *ums)
{ {
ums->lun.sense_data = SS_MEDIUM_NOT_PRESENT; ums->lun.sense_data = SS_MEDIUM_NOT_PRESENT;
return -22; return UMS_RES_INVALID_ARG;
} }
return 0; return UMS_RES_OK;
} }
// Check if we are allowed to unload the media. // Check if we are allowed to unload the media.
@ -1047,16 +1054,16 @@ static int _scsi_start_stop(usbd_gadget_ums_t *ums)
ums->set_text(ums->label, "#C7EA46 Status:# Unload attempt prevented"); ums->set_text(ums->label, "#C7EA46 Status:# Unload attempt prevented");
ums->lun.sense_data = SS_MEDIUM_REMOVAL_PREVENTED; ums->lun.sense_data = SS_MEDIUM_REMOVAL_PREVENTED;
return -22; return UMS_RES_INVALID_ARG;
} }
if (!loej) if (!loej)
return 0; return UMS_RES_OK;
// Unmount means we exit UMS because of ejection. // Unmount means we exit UMS because of ejection.
ums->lun.unmounted = 1; ums->lun.unmounted = 1;
return 0; return UMS_RES_OK;
} }
static int _scsi_prevent_allow_removal(usbd_gadget_ums_t *ums) static int _scsi_prevent_allow_removal(usbd_gadget_ums_t *ums)
@ -1067,7 +1074,7 @@ static int _scsi_prevent_allow_removal(usbd_gadget_ums_t *ums)
{ {
ums->lun.sense_data = SS_INVALID_COMMAND; ums->lun.sense_data = SS_INVALID_COMMAND;
return -22; // Invalid argument. return UMS_RES_INVALID_ARG;
} }
prevent = ums->cmnd[4] & 0x01; prevent = ums->cmnd[4] & 0x01;
@ -1075,7 +1082,7 @@ static int _scsi_prevent_allow_removal(usbd_gadget_ums_t *ums)
{ {
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
return -22; // Invalid argument. return UMS_RES_INVALID_ARG;
} }
// Notify for possible unmounting? // Notify for possible unmounting?
@ -1085,7 +1092,7 @@ static int _scsi_prevent_allow_removal(usbd_gadget_ums_t *ums)
ums->lun.prevent_medium_removal = prevent; ums->lun.prevent_medium_removal = prevent;
return 0; return UMS_RES_OK;
} }
static int _scsi_read_format_capacities(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) static int _scsi_read_format_capacities(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
@ -1105,7 +1112,7 @@ static int _scsi_read_format_capacities(usbd_gadget_ums_t *ums, bulk_ctxt_t *bul
// Check whether the command is properly formed and whether its data size // Check whether the command is properly formed and whether its data size
// and direction agree with the values we already have. // and direction agree with the values we already have.
static int _ums_check_scsi_cmd(usbd_gadget_ums_t *ums, int cmnd_size, static int _ums_check_scsi_cmd(usbd_gadget_ums_t *ums, u32 cmnd_size,
enum data_direction data_dir, u32 mask, int needs_medium) enum data_direction data_dir, u32 mask, int needs_medium)
{ {
//const char dirletter[4] = {'u', 'o', 'i', 'n'}; //const char dirletter[4] = {'u', 'o', 'i', 'n'};
@ -1132,7 +1139,7 @@ DPRINTF("SCSI command: %X; Dc=%d, D%c=%X; Hc=%d, H%c=%X\n",
{ {
ums->phase_error = 1; ums->phase_error = 1;
return -22; // Invalid argument. return UMS_RES_INVALID_ARG;
} }
// Cmd length verification. // Cmd length verification.
@ -1146,7 +1153,7 @@ DPRINTF("SCSI command: %X; Dc=%d, D%c=%X; Hc=%d, H%c=%X\n",
{ {
ums->phase_error = 1; ums->phase_error = 1;
return -22; // Invalid argument. return UMS_RES_INVALID_ARG;
} }
} }
@ -1167,7 +1174,7 @@ DPRINTF("SCSI command: %X; Dc=%d, D%c=%X; Hc=%d, H%c=%X\n",
ums->lun.sense_data = ums->lun.unit_attention_data; ums->lun.sense_data = ums->lun.unit_attention_data;
ums->lun.unit_attention_data = SS_NO_SENSE; ums->lun.unit_attention_data = SS_NO_SENSE;
return -22; return UMS_RES_INVALID_ARG;
} }
// Check that only command bytes listed in the mask are set. // Check that only command bytes listed in the mask are set.
@ -1178,7 +1185,7 @@ DPRINTF("SCSI command: %X; Dc=%d, D%c=%X; Hc=%d, H%c=%X\n",
{ {
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB; ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
return -22; // Invalid argument. return UMS_RES_INVALID_ARG;
} }
} }
@ -1187,16 +1194,16 @@ DPRINTF("SCSI command: %X; Dc=%d, D%c=%X; Hc=%d, H%c=%X\n",
{ {
ums->lun.sense_data = SS_MEDIUM_NOT_PRESENT; ums->lun.sense_data = SS_MEDIUM_NOT_PRESENT;
return -22; return UMS_RES_INVALID_ARG;
} }
return 0; return UMS_RES_OK;
} }
static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{ {
u32 len; u32 len;
int reply = -22; // Invalid argument. int reply = UMS_RES_INVALID_ARG;
ums->phase_error = 0; ums->phase_error = 0;
ums->short_packet_received = 0; ums->short_packet_received = 0;
@ -1227,7 +1234,7 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{ {
// We don't support MODE SELECT. // We don't support MODE SELECT.
ums->lun.sense_data = SS_INVALID_COMMAND; ums->lun.sense_data = SS_INVALID_COMMAND;
reply = -22; reply = UMS_RES_INVALID_ARG;
} }
break; break;
@ -1238,7 +1245,7 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{ {
// We don't support MODE SELECT. // We don't support MODE SELECT.
ums->lun.sense_data = SS_INVALID_COMMAND; ums->lun.sense_data = SS_INVALID_COMMAND;
reply = -22; reply = UMS_RES_INVALID_ARG;
} }
break; break;
@ -1367,12 +1374,12 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
if (reply == 0) if (reply == 0)
{ {
ums->lun.sense_data = SS_INVALID_COMMAND; ums->lun.sense_data = SS_INVALID_COMMAND;
reply = -22; // Invalid argument. reply = UMS_RES_INVALID_ARG;
} }
break; break;
} }
if (reply == -22) // Invalid argument. if (reply == UMS_RES_INVALID_ARG)
reply = 0; // Error reply length. reply = 0; // Error reply length.
// Set up reply buffer for finish_reply(). Otherwise it's already set. // Set up reply buffer for finish_reply(). Otherwise it's already set.
@ -1384,7 +1391,7 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
ums->residue -= reply; ums->residue -= reply;
} }
return 0; return UMS_RES_OK;
} }
static int pad_with_zeros(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) static int pad_with_zeros(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
@ -1398,12 +1405,12 @@ static int pad_with_zeros(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
u32 nsend = MIN(ums->usb_amount_left, USB_EP_BUFFER_MAX_SIZE); u32 nsend = MIN(ums->usb_amount_left, USB_EP_BUFFER_MAX_SIZE);
memset(bulk_ctxt->bulk_in_buf + current_len_to_keep, 0, nsend - current_len_to_keep); memset(bulk_ctxt->bulk_in_buf + current_len_to_keep, 0, nsend - current_len_to_keep);
bulk_ctxt->bulk_in_length = nsend; bulk_ctxt->bulk_in_length = nsend;
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED); _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_DATA);
ums->usb_amount_left -= nsend; ums->usb_amount_left -= nsend;
current_len_to_keep = 0; current_len_to_keep = 0;
} }
return 0; return UMS_RES_OK;
} }
static int throw_away_data(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) static int throw_away_data(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
@ -1416,10 +1423,10 @@ static int throw_away_data(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
u32 amount = MIN(ums->usb_amount_left, USB_EP_BUFFER_MAX_SIZE); u32 amount = MIN(ums->usb_amount_left, USB_EP_BUFFER_MAX_SIZE);
bulk_ctxt->bulk_out_length = amount; bulk_ctxt->bulk_out_length = amount;
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED); _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED_DATA);
ums->usb_amount_left -= amount; ums->usb_amount_left -= amount;
return 0; return UMS_RES_OK;
} }
// Throw away the data in a filled buffer. // Throw away the data in a filled buffer.
@ -1431,15 +1438,15 @@ static int throw_away_data(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
bulk_ctxt->bulk_out_status != USB_RES_OK) bulk_ctxt->bulk_out_status != USB_RES_OK)
{ {
raise_exception(ums, UMS_STATE_ABORT_BULK_OUT); raise_exception(ums, UMS_STATE_ABORT_BULK_OUT);
return -4; // Interrupted system call return UMS_RES_PROT_FATAL;
} }
} }
return 0; return UMS_RES_OK;
} }
static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{ {
int rc = 0; int rc = UMS_RES_OK;
switch (ums->data_dir) { switch (ums->data_dir) {
case DATA_DIR_NONE: case DATA_DIR_NONE:
@ -1463,7 +1470,7 @@ static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
// If there's no residue, simply send the last buffer. // If there's no residue, simply send the last buffer.
if (!ums->residue) if (!ums->residue)
{ {
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED); _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_DATA);
/* For Bulk-only, if we're allowed to stall then send the /* For Bulk-only, if we're allowed to stall then send the
* short packet and halt the bulk-in endpoint. If we can't * short packet and halt the bulk-in endpoint. If we can't
@ -1471,7 +1478,7 @@ static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
} }
else if (ums->can_stall) else if (ums->can_stall)
{ {
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED); _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_DATA);
rc = ums_set_stall(bulk_ctxt->bulk_in); rc = ums_set_stall(bulk_ctxt->bulk_in);
ums->set_text(ums->label, "#FFDD00 Error:# Residue. Stalled EP IN!"); ums->set_text(ums->label, "#FFDD00 Error:# Residue. Stalled EP IN!");
} }
@ -1491,7 +1498,7 @@ static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
if (ums->short_packet_received) // Did the host stop sending unexpectedly early? if (ums->short_packet_received) // Did the host stop sending unexpectedly early?
{ {
raise_exception(ums, UMS_STATE_ABORT_BULK_OUT); raise_exception(ums, UMS_STATE_ABORT_BULK_OUT);
rc = -4; // Interrupted system call rc = UMS_RES_PROT_FATAL;
} }
else // We can't stall. Read in the excess data and throw it away. else // We can't stall. Read in the excess data and throw it away.
rc = throw_away_data(ums, bulk_ctxt); rc = throw_away_data(ums, bulk_ctxt);
@ -1574,7 +1581,7 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
} }
if (bulk_ctxt->bulk_out_status || bulk_ctxt->bulk_out_ignore) if (bulk_ctxt->bulk_out_status || bulk_ctxt->bulk_out_ignore)
return -22; // Invalid argument. return UMS_RES_INVALID_ARG;
} }
/* Is the CBW valid? */ /* Is the CBW valid? */
@ -1594,12 +1601,12 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
// until the next reset. // until the next reset.
ums_wedge_bulk_in_endpoint(ums); ums_wedge_bulk_in_endpoint(ums);
bulk_ctxt->bulk_out_ignore = 1; bulk_ctxt->bulk_out_ignore = 1;
return -22; // Invalid argument. return UMS_RES_INVALID_ARG;
} }
/* Is the CBW meaningful? */ /* Is the CBW meaningful? */
if (cbw->Lun >= UMS_MAX_LUN || cbw->Flags & ~USB_BULK_IN_FLAG || if (cbw->Lun >= UMS_MAX_LUN || cbw->Flags & ~USB_BULK_IN_FLAG ||
cbw->Length <= 0 || cbw->Length > SCSI_MAX_CMD_SZ) cbw->Length == 0 || cbw->Length > SCSI_MAX_CMD_SZ)
{ {
gfx_printf("USB: non-meaningful CBW: lun = %X, flags = 0x%X, cmdlen %X\n", gfx_printf("USB: non-meaningful CBW: lun = %X, flags = 0x%X, cmdlen %X\n",
cbw->Lun, cbw->Flags, cbw->Length); cbw->Lun, cbw->Flags, cbw->Length);
@ -1613,7 +1620,7 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
ums->set_text(ums->label, "#FFDD00 Error:# CBW unknown - Stalled both EP!"); ums->set_text(ums->label, "#FFDD00 Error:# CBW unknown - Stalled both EP!");
} }
return -22; // Invalid argument. return UMS_RES_INVALID_ARG;
} }
/* Save the command for later */ /* Save the command for later */
@ -1636,12 +1643,12 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
if (!ums->lun.unmounted) if (!ums->lun.unmounted)
ums->timeouts = 0; ums->timeouts = 0;
return 0; return UMS_RES_OK;
} }
static int get_next_command(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) static int get_next_command(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{ {
int rc = 0; int rc = UMS_RES_OK;
/* Wait for the next buffer to become available */ /* Wait for the next buffer to become available */
// while (bulk_ctxt->bulk_out_buf_state != BUF_STATE_EMPTY) // while (bulk_ctxt->bulk_out_buf_state != BUF_STATE_EMPTY)
@ -1652,7 +1659,7 @@ static int get_next_command(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
bulk_ctxt->bulk_out_length = USB_BULK_CB_WRAP_LEN; bulk_ctxt->bulk_out_length = USB_BULK_CB_WRAP_LEN;
/* Queue a request to read a Bulk-only CBW */ /* Queue a request to read a Bulk-only CBW */
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED); _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED_CMD);
/* We will drain the buffer in software, which means we /* We will drain the buffer in software, which means we
* can reuse it for the next filling. No need to advance * can reuse it for the next filling. No need to advance
@ -1698,7 +1705,7 @@ static void send_status(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
csw->Status = status; csw->Status = status;
bulk_ctxt->bulk_in_length = USB_BULK_CS_WRAP_LEN; bulk_ctxt->bulk_in_length = USB_BULK_CS_WRAP_LEN;
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED); _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_CMD);
} }
static void handle_exception(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) static void handle_exception(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
@ -1765,16 +1772,16 @@ static inline void _system_maintainance(usbd_gadget_ums_t *ums)
u32 time = get_tmr_ms(); u32 time = get_tmr_ms();
if (timer_dram < time) if (timer_status_bar < time)
{
minerva_periodic_training();
timer_dram = get_tmr_ms() + 100;
}
else if (timer_status_bar < time)
{ {
ums->system_maintenance(true); ums->system_maintenance(true);
timer_status_bar = get_tmr_ms() + 30000; timer_status_bar = get_tmr_ms() + 30000;
} }
else if (timer_dram < time)
{
minerva_periodic_training();
timer_dram = get_tmr_ms() + EMC_PERIODIC_TRAIN_MS;
}
} }
int usb_device_gadget_ums(usb_ctxt_t *usbs) int usb_device_gadget_ums(usb_ctxt_t *usbs)
@ -1828,6 +1835,7 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
// Initialize sdmmc. // Initialize sdmmc.
if (usbs->type == MMC_SD) if (usbs->type == MMC_SD)
{ {
sd_end();
sd_mount(); sd_mount();
sd_unmount(); sd_unmount();
ums.lun.sdmmc = &sd_sdmmc; ums.lun.sdmmc = &sd_sdmmc;
@ -1898,7 +1906,10 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
send_status(&ums, &ums.bulk_ctxt); send_status(&ums, &ums.bulk_ctxt);
} while (ums.state != UMS_STATE_TERMINATED); } while (ums.state != UMS_STATE_TERMINATED);
ums.set_text(ums.label, "#C7EA46 Status:# Disk ejected"); if (ums.lun.prevent_medium_removal)
ums.set_text(ums.label, "#FFDD00 Error:# Disk unsafely ejected");
else
ums.set_text(ums.label, "#C7EA46 Status:# Disk ejected");
goto exit; goto exit;
error: error:

View File

@ -198,6 +198,7 @@ typedef struct _t210_usb2d_t
#define XUSB_DEV_XHCI_ST 0x34 #define XUSB_DEV_XHCI_ST 0x34
#define XHCI_ST_RC BIT(0) #define XHCI_ST_RC BIT(0)
#define XHCI_ST_IP BIT(4) #define XHCI_ST_IP BIT(4)
#define XUSB_DEV_XHCI_RT_IMOD 0x38
#define XUSB_DEV_XHCI_PORTSC 0x3C #define XUSB_DEV_XHCI_PORTSC 0x3C
#define XHCI_PORTSC_PR BIT(4) #define XHCI_PORTSC_PR BIT(4)
#define XHCI_PORTSC_PLS_MASK (0xF << 5) #define XHCI_PORTSC_PLS_MASK (0xF << 5)

View File

@ -724,7 +724,7 @@ static usb_ep_status_t _usbd_get_ep_status(usb_ep_t endpoint)
return USB_EP_STATUS_IDLE; return USB_EP_STATUS_IDLE;
} }
static int _usbd_ep_operation(usb_ep_t endpoint, u8 *buf, u32 len, bool sync) static int _usbd_ep_operation(usb_ep_t endpoint, u8 *buf, u32 len, u32 sync_timeout)
{ {
if (!buf) if (!buf)
len = 0; len = 0;
@ -797,12 +797,12 @@ static int _usbd_ep_operation(usb_ep_t endpoint, u8 *buf, u32 len, bool sync)
int res = USB_RES_OK; int res = USB_RES_OK;
usb_ep_status_t ep_status; usb_ep_status_t ep_status;
if (sync) if (sync_timeout)
{ {
ep_status = _usbd_get_ep_status(endpoint); ep_status = _usbd_get_ep_status(endpoint);
if (ep_status == USB_EP_STATUS_ACTIVE) if (ep_status == USB_EP_STATUS_ACTIVE)
{ {
u32 retries = 1000000; // Timeout 2s. u32 retries = sync_timeout;
while (retries) while (retries)
{ {
ep_status = _usbd_get_ep_status(endpoint); ep_status = _usbd_get_ep_status(endpoint);
@ -834,7 +834,7 @@ out:
static int _usbd_ep_ack(usb_ep_t ep) static int _usbd_ep_ack(usb_ep_t ep)
{ {
return _usbd_ep_operation(ep, NULL, 0, true); return _usbd_ep_operation(ep, NULL, 0, USB_XFER_SYNCED_ENUM);
} }
static void _usbd_set_ep0_stall() static void _usbd_set_ep0_stall()
@ -1275,7 +1275,7 @@ static int _usbd_handle_ep0_control_transfer()
if (_wLength < size) if (_wLength < size)
size = _wLength; size = _wLength;
res = _usbd_ep_operation(USB_EP_CTRL_IN, usb_ep0_ctrl_buf, size, true); res = _usbd_ep_operation(USB_EP_CTRL_IN, usb_ep0_ctrl_buf, size, USB_XFER_SYNCED_ENUM);
if (!res) if (!res)
res = _usbd_ep_ack(USB_EP_CTRL_OUT); res = _usbd_ep_ack(USB_EP_CTRL_OUT);
} }
@ -1402,7 +1402,7 @@ static usb_ep_status_t _usbd_get_ep1_status(usb_dir_t dir)
return _usbd_get_ep_status(ep); return _usbd_get_ep_status(ep);
} }
int usb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, bool sync) int usb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, u32 sync_timeout)
{ {
if ((u32)buf % USB_EP_BUFFER_ALIGN) if ((u32)buf % USB_EP_BUFFER_ALIGN)
return USB2_ERROR_XFER_NOT_ALIGNED; return USB2_ERROR_XFER_NOT_ALIGNED;
@ -1410,9 +1410,9 @@ int usb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, bool sync)
if (len > USB_EP_BUFFER_MAX_SIZE) if (len > USB_EP_BUFFER_MAX_SIZE)
len = USB_EP_BUFFER_MAX_SIZE; len = USB_EP_BUFFER_MAX_SIZE;
int res = _usbd_ep_operation(USB_EP_BULK_OUT, buf, len, sync); int res = _usbd_ep_operation(USB_EP_BULK_OUT, buf, len, sync_timeout);
if (sync && bytes_read) if (sync_timeout && bytes_read)
*bytes_read = res ? 0 : len; *bytes_read = res ? 0 : len;
return res; return res;
@ -1435,7 +1435,7 @@ int usb_device_ep1_out_read_big(u8 *buf, u32 len, u32 *bytes_read)
{ {
u32 len_ep = MIN(len, USB_EP_BUFFER_MAX_SIZE); u32 len_ep = MIN(len, USB_EP_BUFFER_MAX_SIZE);
res = usb_device_ep1_out_read(buf_curr, len_ep, &bytes, USB_XFER_SYNCED); res = usb_device_ep1_out_read(buf_curr, len_ep, &bytes, USB_XFER_SYNCED_DATA);
if (res) if (res)
return res; return res;
@ -1455,7 +1455,7 @@ static int _usbd_get_ep1_out_bytes_read()
return (usbdaemon->ep_bytes_requested[USB_EP_BULK_OUT] - (usbdaemon->qhs[USB_EP_BULK_OUT].token >> 16)); return (usbdaemon->ep_bytes_requested[USB_EP_BULK_OUT] - (usbdaemon->qhs[USB_EP_BULK_OUT].token >> 16));
} }
int usb_device_ep1_out_reading_finish(u32 *pending_bytes, int tries) int usb_device_ep1_out_reading_finish(u32 *pending_bytes)
{ {
usb_ep_status_t ep_status; usb_ep_status_t ep_status;
do do
@ -1480,7 +1480,7 @@ int usb_device_ep1_out_reading_finish(u32 *pending_bytes, int tries)
return USB_ERROR_XFER_ERROR; return USB_ERROR_XFER_ERROR;
} }
int usb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, bool sync) int usb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, u32 sync_timeout)
{ {
if ((u32)buf % USB_EP_BUFFER_ALIGN) if ((u32)buf % USB_EP_BUFFER_ALIGN)
return USB2_ERROR_XFER_NOT_ALIGNED; return USB2_ERROR_XFER_NOT_ALIGNED;
@ -1488,9 +1488,9 @@ int usb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, bool sync)
if (len > USB_EP_BUFFER_MAX_SIZE) if (len > USB_EP_BUFFER_MAX_SIZE)
len = USB_EP_BUFFER_MAX_SIZE; len = USB_EP_BUFFER_MAX_SIZE;
int res = _usbd_ep_operation(USB_EP_BULK_IN, buf, len, sync); int res = _usbd_ep_operation(USB_EP_BULK_IN, buf, len, sync_timeout);
if (sync && bytes_written) if (sync_timeout && bytes_written)
*bytes_written = res ? 0 : len; *bytes_written = res ? 0 : len;
return res; return res;

View File

@ -30,8 +30,12 @@
#define USB_EP_BUFFER_MAX_SIZE (USB_EP_BUFFER_4_TD) #define USB_EP_BUFFER_MAX_SIZE (USB_EP_BUFFER_4_TD)
#define USB_EP_BUFFER_ALIGN (USB_TD_BUFFER_PAGE_SIZE) #define USB_EP_BUFFER_ALIGN (USB_TD_BUFFER_PAGE_SIZE)
#define USB_XFER_START false #define USB_XFER_START 0
#define USB_XFER_SYNCED true #define USB_XFER_SYNCED_ENUM 1000000
#define USB_XFER_SYNCED_CMD 1000000
#define USB_XFER_SYNCED_DATA 2000000
#define USB_XFER_SYNCED_CLASS 5000000
#define USB_XFER_SYNCED -1
typedef enum _usb_hid_type typedef enum _usb_hid_type
{ {
@ -169,10 +173,10 @@ typedef struct _usb_ops_t
int (*usb_device_class_send_max_lun)(u8); int (*usb_device_class_send_max_lun)(u8);
int (*usb_device_class_send_hid_report)(); int (*usb_device_class_send_hid_report)();
int (*usb_device_ep1_out_read)(u8 *, u32, u32 *, bool); int (*usb_device_ep1_out_read)(u8 *, u32, u32 *, u32);
int (*usb_device_ep1_out_read_big)(u8 *, u32, u32 *); int (*usb_device_ep1_out_read_big)(u8 *, u32, u32 *);
int (*usb_device_ep1_out_reading_finish)(u32 *, int); int (*usb_device_ep1_out_reading_finish)(u32 *);
int (*usb_device_ep1_in_write)(u8 *, u32, u32 *, bool); int (*usb_device_ep1_in_write)(u8 *, u32, u32 *, u32);
int (*usb_device_ep1_in_writing_finish)(u32 *); int (*usb_device_ep1_in_writing_finish)(u32 *);
bool (*usb_device_get_suspended)(); bool (*usb_device_get_suspended)();
bool (*usb_device_get_port_in_sleep)(); bool (*usb_device_get_port_in_sleep)();

View File

@ -881,7 +881,7 @@ int xusb_device_init()
_xusbd_init_device_clocks(); _xusbd_init_device_clocks();
// Enable AHB redirect for access to IRAM for Event/EP ring buffers. // Enable AHB redirect for access to IRAM for Event/EP ring buffers.
mc_enable_ahb_redirect(); // can be skipped if IRAM is not used///////////////// mc_enable_ahb_redirect(); // Can be skipped if IRAM is not used.
// Enable XUSB device IPFS. // Enable XUSB device IPFS.
XUSB_DEV_DEV(XUSB_DEV_CONFIGURATION) |= DEV_CONFIGURATION_EN_FPCI; XUSB_DEV_DEV(XUSB_DEV_CONFIGURATION) |= DEV_CONFIGURATION_EN_FPCI;
@ -895,14 +895,11 @@ int xusb_device_init()
XUSB_DEV_DEV(XUSB_DEV_INTR_MASK) |= DEV_INTR_MASK_IP_INT_MASK; XUSB_DEV_DEV(XUSB_DEV_INTR_MASK) |= DEV_INTR_MASK_IP_INT_MASK;
// AHB USB performance cfg. // AHB USB performance cfg.
//TODO: Doesn't help..
/*
AHB_GIZMO(AHB_GIZMO_AHB_MEM) |= AHB_MEM_DONT_SPLIT_AHB_WR | AHB_MEM_ENB_FAST_REARBITRATE; AHB_GIZMO(AHB_GIZMO_AHB_MEM) |= AHB_MEM_DONT_SPLIT_AHB_WR | AHB_MEM_ENB_FAST_REARBITRATE;
AHB_GIZMO(AHB_GIZMO_USB3) |= AHB_GIZMO_IMMEDIATE; AHB_GIZMO(AHB_GIZMO_USB3) |= AHB_GIZMO_IMMEDIATE;
AHB_GIZMO(AHB_ARBITRATION_PRIORITY_CTRL) = PRIORITY_CTRL_WEIGHT(7) | PRIORITY_SELECT_USB3; AHB_GIZMO(AHB_ARBITRATION_PRIORITY_CTRL) = PRIORITY_CTRL_WEIGHT(7) | PRIORITY_SELECT_USB3;
AHB_GIZMO(AHB_AHB_MEM_PREFETCH_CFG1) = AHB_GIZMO(AHB_AHB_MEM_PREFETCH_CFG1) =
MEM_PREFETCH_ENABLE | MEM_PREFETCH_USB3_MST_ID | MEM_PREFETCH_ADDR_BNDRY(12) | 0x1000; // Addr boundary 64KB, Inactivity 4096 cycles. MEM_PREFETCH_ENABLE | MEM_PREFETCH_USB3_MST_ID | MEM_PREFETCH_ADDR_BNDRY(12) | 0x1000; // Addr boundary 64KB, Inactivity 4096 cycles.
*/
// Initialize context. // Initialize context.
usbd_xotg = &usbd_xotg_controller_ctxt; usbd_xotg = &usbd_xotg_controller_ctxt;
@ -1771,6 +1768,13 @@ int xusb_device_enumerate(usb_gadget_type gadget)
usbd_xotg->gadget = gadget; usbd_xotg->gadget = gadget;
/*
* Set interrupt moderation to 0us.
* This is important because default value creates a 4.62ms latency.
* Effectively hurting transfers by having 15% to 96% performance loss.
*/
XUSB_DEV_XHCI(XUSB_DEV_XHCI_RT_IMOD) = 0;
// Disable Wake events. // Disable Wake events.
XUSB_PADCTL(XUSB_PADCTL_ELPG_PROGRAM_0) = 0; XUSB_PADCTL(XUSB_PADCTL_ELPG_PROGRAM_0) = 0;
XUSB_PADCTL(XUSB_PADCTL_ELPG_PROGRAM_1) = 0; XUSB_PADCTL(XUSB_PADCTL_ELPG_PROGRAM_1) = 0;
@ -1803,7 +1807,7 @@ int xusb_device_enumerate(usb_gadget_type gadget)
u32 timer = get_tmr_ms() + 90000; u32 timer = get_tmr_ms() + 90000;
while (true) while (true)
{ {
int res = _xusb_ep_operation(1000000); // 2s timeout. int res = _xusb_ep_operation(USB_XFER_SYNCED_ENUM); // 2s timeout.
if (res && res != USB_ERROR_TIMEOUT) if (res && res != USB_ERROR_TIMEOUT)
return res; return res;
@ -1826,7 +1830,7 @@ void xusb_end(bool reset_ep, bool only_controller)
CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB_PADCTL); CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB_PADCTL);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_CLR) = BIT(CLK_W_XUSB); CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_CLR) = BIT(CLK_W_XUSB);
CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB); CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB);
mc_disable_ahb_redirect();/////////////////// mc_disable_ahb_redirect(); // Can be skipped if IRAM is not used.
} }
int xusb_handle_ep0_ctrl_setup() int xusb_handle_ep0_ctrl_setup()
@ -1844,7 +1848,7 @@ int xusb_handle_ep0_ctrl_setup()
return USB_RES_OK; return USB_RES_OK;
} }
int xusb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, bool sync) int xusb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, u32 sync_tries)
{ {
if (len > USB_EP_BUFFER_MAX_SIZE) if (len > USB_EP_BUFFER_MAX_SIZE)
len = USB_EP_BUFFER_MAX_SIZE; len = USB_EP_BUFFER_MAX_SIZE;
@ -1855,10 +1859,10 @@ int xusb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, bool sync)
_xusb_issue_normal_trb(buf, len, USB_DIR_OUT); _xusb_issue_normal_trb(buf, len, USB_DIR_OUT);
usbd_xotg->tx_count[USB_DIR_OUT]++; usbd_xotg->tx_count[USB_DIR_OUT]++;
if (sync) if (sync_tries)
{ {
while (!res && usbd_xotg->tx_count[USB_DIR_OUT]) while (!res && usbd_xotg->tx_count[USB_DIR_OUT])
res = _xusb_ep_operation(1000000); // 2s timeout. res = _xusb_ep_operation(sync_tries);
if (bytes_read) if (bytes_read)
*bytes_read = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_OUT]; *bytes_read = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_OUT];
@ -1882,7 +1886,7 @@ int xusb_device_ep1_out_read_big(u8 *buf, u32 len, u32 *bytes_read)
{ {
u32 len_ep = MIN(len, USB_EP_BUFFER_MAX_SIZE); u32 len_ep = MIN(len, USB_EP_BUFFER_MAX_SIZE);
int res = xusb_device_ep1_out_read(buf_curr, len_ep, &bytes, USB_XFER_SYNCED); int res = xusb_device_ep1_out_read(buf_curr, len_ep, &bytes, USB_XFER_SYNCED_DATA);
if (res) if (res)
return res; return res;
@ -1894,11 +1898,11 @@ int xusb_device_ep1_out_read_big(u8 *buf, u32 len, u32 *bytes_read)
return USB_RES_OK; return USB_RES_OK;
} }
int xusb_device_ep1_out_reading_finish(u32 *pending_bytes, int tries) int xusb_device_ep1_out_reading_finish(u32 *pending_bytes)
{ {
int res = USB_RES_OK; int res = USB_RES_OK;
while (!res && usbd_xotg->tx_count[USB_DIR_OUT]) while (!res && usbd_xotg->tx_count[USB_DIR_OUT])
res = _xusb_ep_operation(tries); res = _xusb_ep_operation(USB_XFER_SYNCED); // Infinite retries.
if (pending_bytes) if (pending_bytes)
*pending_bytes = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_OUT]; *pending_bytes = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_OUT];
@ -1908,7 +1912,7 @@ int xusb_device_ep1_out_reading_finish(u32 *pending_bytes, int tries)
return res; return res;
} }
int xusb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, bool sync) int xusb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, u32 sync_tries)
{ {
if (len > USB_EP_BUFFER_MAX_SIZE) if (len > USB_EP_BUFFER_MAX_SIZE)
len = USB_EP_BUFFER_MAX_SIZE; len = USB_EP_BUFFER_MAX_SIZE;
@ -1921,10 +1925,10 @@ int xusb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, bool sync)
_xusb_issue_normal_trb(buf, len, USB_DIR_IN); _xusb_issue_normal_trb(buf, len, USB_DIR_IN);
usbd_xotg->tx_count[USB_DIR_IN]++; usbd_xotg->tx_count[USB_DIR_IN]++;
if (sync) if (sync_tries)
{ {
while (!res && usbd_xotg->tx_count[USB_DIR_IN]) while (!res && usbd_xotg->tx_count[USB_DIR_IN])
res = _xusb_ep_operation(1000000); // 2s timeout. res = _xusb_ep_operation(sync_tries);
if (bytes_written) if (bytes_written)
*bytes_written = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_IN]; *bytes_written = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_IN];
@ -1947,7 +1951,7 @@ int xusb_device_ep1_in_writing_finish(u32 *pending_bytes)
{ {
int res = USB_RES_OK; int res = USB_RES_OK;
while (!res && usbd_xotg->tx_count[USB_DIR_IN]) while (!res && usbd_xotg->tx_count[USB_DIR_IN])
res = _xusb_ep_operation(1000000); // 2s timeout. res = _xusb_ep_operation(USB_XFER_SYNCED); // Infinite retries.
if (pending_bytes) if (pending_bytes)
*pending_bytes = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_IN]; *pending_bytes = res ? 0 : usbd_xotg->bytes_remaining[USB_DIR_IN];
@ -1973,7 +1977,7 @@ bool xusb_device_class_send_max_lun(u8 max_lun)
// Wait for request and transfer start. // Wait for request and transfer start.
while (usbd_xotg->device_state != XUSB_LUN_CONFIGURED) while (usbd_xotg->device_state != XUSB_LUN_CONFIGURED)
{ {
_xusb_ep_operation(500000); _xusb_ep_operation(USB_XFER_SYNCED_CLASS);
if (timer < get_tmr_ms() || btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN)) if (timer < get_tmr_ms() || btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
return true; return true;
} }
@ -1991,7 +1995,7 @@ bool xusb_device_class_send_hid_report()
// Wait for request and transfer start. // Wait for request and transfer start.
while (usbd_xotg->device_state != XUSB_HID_CONFIGURED) while (usbd_xotg->device_state != XUSB_HID_CONFIGURED)
{ {
_xusb_ep_operation(500000); _xusb_ep_operation(USB_XFER_SYNCED_CLASS);
if (timer < get_tmr_ms() || btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN)) if (timer < get_tmr_ms() || btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
return true; return true;
} }

View File

@ -29,7 +29,7 @@ u8 btn_read()
res |= BTN_VOL_DOWN; res |= BTN_VOL_DOWN;
if (!gpio_read(GPIO_PORT_X, GPIO_PIN_6)) if (!gpio_read(GPIO_PORT_X, GPIO_PIN_6))
res |= BTN_VOL_UP; res |= BTN_VOL_UP;
if (i2c_recv_byte(4, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFSTAT) & 0x4) if (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFSTAT) & MAX77620_ONOFFSTAT_EN0)
res |= BTN_POWER; res |= BTN_POWER;
return res; return res;
} }

View File

@ -21,16 +21,16 @@
#include <mem/heap.h> #include <mem/heap.h>
#include <utils/types.h> #include <utils/types.h>
#define MAX_ENTRIES 64
char *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles, bool parse_dirs) char *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles, bool parse_dirs)
{ {
u8 max_entries = 61;
int res = 0; int res = 0;
u32 i = 0, j = 0, k = 0; u32 i = 0, j = 0, k = 0;
DIR dir; DIR dir;
FILINFO fno; FILINFO fno;
char *dir_entries = (char *)calloc(max_entries, 256); char *dir_entries = (char *)calloc(MAX_ENTRIES, 256);
char *temp = (char *)calloc(1, 256); char *temp = (char *)calloc(1, 256);
if (!pattern && !f_opendir(&dir, directory)) if (!pattern && !f_opendir(&dir, directory))
@ -49,7 +49,7 @@ char *dirlist(const char *directory, const char *pattern, bool includeHiddenFile
{ {
strcpy(dir_entries + (k * 256), fno.fname); strcpy(dir_entries + (k * 256), fno.fname);
k++; k++;
if (k > (max_entries - 1)) if (k > (MAX_ENTRIES - 1))
break; break;
} }
} }
@ -64,7 +64,7 @@ char *dirlist(const char *directory, const char *pattern, bool includeHiddenFile
{ {
strcpy(dir_entries + (k * 256), fno.fname); strcpy(dir_entries + (k * 256), fno.fname);
k++; k++;
if (k > (max_entries - 1)) if (k > (MAX_ENTRIES - 1))
break; break;
} }
res = f_findnext(&dir, &fno); res = f_findnext(&dir, &fno);

View File

@ -66,14 +66,14 @@ ini_sec_t *_ini_create_section(link_t *dst, ini_sec_t *csec, char *name, u8 type
int ini_parse(link_t *dst, char *ini_path, bool is_dir) int ini_parse(link_t *dst, char *ini_path, bool is_dir)
{ {
FIL fp;
u32 lblen; u32 lblen;
u32 pathlen = strlen(ini_path); u32 pathlen = strlen(ini_path);
u32 k = 0; u32 k = 0;
char lbuf[512];
char *filelist = NULL;
FIL fp;
ini_sec_t *csec = NULL; ini_sec_t *csec = NULL;
char *lbuf = NULL;
char *filelist = NULL;
char *filename = (char *)malloc(256); char *filename = (char *)malloc(256);
strcpy(filename, ini_path); strcpy(filename, ini_path);
@ -114,6 +114,8 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir)
return 0; return 0;
} }
lbuf = malloc(512);
do do
{ {
// Fetch one line. // Fetch one line.
@ -168,6 +170,7 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir)
} }
} while (is_dir); } while (is_dir);
free(lbuf);
free(filename); free(filename);
free(filelist); free(filelist);

View File

@ -56,7 +56,7 @@ static u32 _putn(char *buffer, u32 v, int base, char fill, int fcnt) {
return _puts(buffer, p); return _puts(buffer, p);
} }
u32 sprintf(char *buffer, const char *fmt, ...) { u32 s_printf(char *buffer, const char *fmt, ...) {
va_list ap; va_list ap;
int fill, fcnt; int fill, fcnt;
u32 count = 0; u32 count = 0;

View File

@ -19,6 +19,6 @@
#include "types.h" #include "types.h"
u32 sprintf(char *buffer, const char *fmt, ...); u32 s_printf(char *buffer, const char *fmt, ...);
#endif #endif

View File

@ -22,7 +22,7 @@
#define ALWAYS_INLINE inline __attribute__((always_inline)) #define ALWAYS_INLINE inline __attribute__((always_inline))
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
#define ALIGN_DOWN(x, a) (((x) - ((a) - 1)) & ~((a) - 1)) #define ALIGN_DOWN(x, a) ((x) & ~((a) - 1))
#define BIT(n) (1U << (n)) #define BIT(n) (1U << (n))
#define MAX(a, b) ((a) > (b) ? (a) : (b)) #define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MIN(a, b) ((a) < (b) ? (a) : (b))
@ -74,6 +74,9 @@ typedef int bool;
#define true 1 #define true 1
#define false 0 #define false 0
#define DISABLE 0
#define ENABLE 1
#define BOOT_CFG_AUTOBOOT_EN BIT(0) #define BOOT_CFG_AUTOBOOT_EN BIT(0)
#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)

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer * Copyright (c) 2018-2020 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * 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,
@ -44,7 +44,7 @@ u32 get_tmr_ms()
u32 get_tmr_us() u32 get_tmr_us()
{ {
return TMR(TIMERUS_CNTR_1US); //TIMERUS_CNTR_1US return TMR(TIMERUS_CNTR_1US);
} }
void msleep(u32 ms) void msleep(u32 ms)
@ -132,53 +132,58 @@ void panic(u32 val)
usleep(1); usleep(1);
} }
void reboot_normal() void power_set_state(power_state_t state)
{ {
u8 reg;
// Unmount and power down sd card.
sd_end(); sd_end();
hw_reinit_workaround(false, 0);
panic(0x21); // Bypass fuse programming in package1. // De-initialize and power down various hardware.
}
void reboot_rcm()
{
sd_end();
hw_reinit_workaround(false, 0);
PMC(APBDEV_PMC_SCRATCH0) = PMC_SCRATCH0_MODE_RCM;
PMC(APBDEV_PMC_CNTRL) |= PMC_CNTRL_MAIN_RST;
while (true)
bpmp_halt();
}
void reboot_full()
{
sd_end();
hw_reinit_workaround(false, 0);
// Enable soft reset wake event.
u8 reg = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2);
reg |= MAX77620_ONOFFCNFG2_SFT_RST_WK;
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2, reg);
// Do a soft reset.
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_SFT_RST);
while (true)
bpmp_halt();
}
void power_off()
{
sd_end();
hw_reinit_workaround(false, 0); hw_reinit_workaround(false, 0);
// Stop the alarm, in case we injected and powered off too fast. // Stop the alarm, in case we injected and powered off too fast.
max77620_rtc_stop_alarm(); max77620_rtc_stop_alarm();
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_PWR_OFF); // Set power state.
switch (state)
{
case REBOOT_RCM:
PMC(APBDEV_PMC_SCRATCH0) = PMC_SCRATCH0_MODE_RCM; // Enable RCM path.
PMC(APBDEV_PMC_CNTRL) |= PMC_CNTRL_MAIN_RST; // PMC reset.
break;
case REBOOT_BYPASS_FUSES:
panic(0x21); // Bypass fuse programming in package1.
break;
case POWER_OFF:
// Initiate power down sequence and do not generate a reset (regulators retain state).
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_PWR_OFF);
break;
case POWER_OFF_RESET:
case POWER_OFF_REBOOT:
default:
// Enable/Disable soft reset wake event.
reg = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2);
if (state == POWER_OFF_RESET) // Do not wake up after power off.
reg &= ~(MAX77620_ONOFFCNFG2_SFT_RST_WK | MAX77620_ONOFFCNFG2_WK_ALARM1 | MAX77620_ONOFFCNFG2_WK_ALARM2);
else // POWER_OFF_REBOOT. Wake up after power off.
reg |= MAX77620_ONOFFCNFG2_SFT_RST_WK;
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2, reg);
// Initiate power down sequence and generate a reset (regulators' state resets).
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_SFT_RST);
break;
}
while (true) while (true)
bpmp_halt(); bpmp_halt();
} }
void power_set_state_ex(void *param)
{
power_state_t *state = (power_state_t *)param;
power_set_state(*state);
}

View File

@ -21,6 +21,16 @@
#include <utils/types.h> #include <utils/types.h>
#include <mem/minerva.h> #include <mem/minerva.h>
typedef enum
{
REBOOT_RCM, // PMC reset. Enter RCM mode.
REBOOT_BYPASS_FUSES, // PMC reset via watchdog. Enter Normal mode. Bypass fuse programming in package1.
POWER_OFF, // Power off PMIC. Do not reset regulators.
POWER_OFF_RESET, // Power off PMIC. Reset regulators.
POWER_OFF_REBOOT, // Power off PMIC. Reset regulators. Power on.
} power_state_t;
typedef enum typedef enum
{ {
NYX_CFG_BIS = BIT(5), NYX_CFG_BIS = BIT(5),
@ -41,6 +51,8 @@ typedef enum
#define byte_swap_32(num) ((((num) >> 24) & 0xff) | (((num) << 8) & 0xff0000) | \ #define byte_swap_32(num) ((((num) >> 24) & 0xff) | (((num) << 8) & 0xff0000) | \
(((num) >> 8 )& 0xff00) | (((num) << 24) & 0xff000000)) (((num) >> 8 )& 0xff00) | (((num) << 24) & 0xff000000))
#define byte_swap_16(num) ((((num) >> 8) & 0xff) | (((num) << 8) & 0xff00))
typedef struct _cfg_op_t typedef struct _cfg_op_t
{ {
u32 off; u32 off;
@ -49,6 +61,10 @@ typedef struct _cfg_op_t
typedef struct _nyx_info_t typedef struct _nyx_info_t
{ {
u32 magic;
u32 sd_init;
u32 sd_errors[3];
u8 rsvd[0x1000];
u32 disp_id; u32 disp_id;
u32 errors; u32 errors;
} nyx_info_t; } nyx_info_t;
@ -65,17 +81,18 @@ typedef struct _nyx_storage_t
emc_table_t mtc_table[10]; emc_table_t mtc_table[10];
} nyx_storage_t; } nyx_storage_t;
void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops);
u32 crc32_calc(u32 crc, const u8 *buf, u32 len);
u32 get_tmr_us(); u32 get_tmr_us();
u32 get_tmr_ms(); u32 get_tmr_ms();
u32 get_tmr_s(); u32 get_tmr_s();
void usleep(u32 us); void usleep(u32 us);
void msleep(u32 ms); void msleep(u32 ms);
void panic(u32 val); void panic(u32 val);
void reboot_normal(); void power_set_state(power_state_t state);
void reboot_rcm(); void power_set_state_ex(void *param);
void reboot_full();
void power_off();
void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops);
u32 crc32_calc(u32 crc, const u8 *buf, u32 len);
#endif #endif

View File

@ -49,6 +49,7 @@ void set_default_configuration()
h_cfg.sept_run = EMC(EMC_SCRATCH0) & EMC_SEPT_RUN; h_cfg.sept_run = EMC(EMC_SCRATCH0) & EMC_SEPT_RUN;
h_cfg.aes_slots_new = false; h_cfg.aes_slots_new = false;
h_cfg.rcm_patched = fuse_check_patched_rcm(); h_cfg.rcm_patched = fuse_check_patched_rcm();
h_cfg.sbk_set = FUSE(FUSE_PRIVATE_KEY0) == 0xFFFFFFFF;
h_cfg.emummc_force_disable = false; h_cfg.emummc_force_disable = false;
h_cfg.t210b01 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01; h_cfg.t210b01 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01;

View File

@ -38,6 +38,7 @@ typedef struct _hekate_config
bool aes_slots_new; bool aes_slots_new;
bool emummc_force_disable; bool emummc_force_disable;
bool rcm_patched; bool rcm_patched;
bool sbk_set;
u32 errors; u32 errors;
hos_eks_mbr_t *eks; hos_eks_mbr_t *eks;
} hekate_config; } hekate_config;

View File

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer * Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2019-2020 shchmue * Copyright (c) 2019-2021 shchmue
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -24,6 +24,8 @@
gfx_ctxt_t gfx_ctxt; gfx_ctxt_t gfx_ctxt;
gfx_con_t gfx_con; gfx_con_t gfx_con;
static bool gfx_con_init_done = false;
static const u8 _gfx_font[] = { static const u8 _gfx_font[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Char 032 ( ) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Char 032 ( )
0x00, 0x30, 0x30, 0x18, 0x18, 0x00, 0x0C, 0x00, // Char 033 (!) 0x00, 0x30, 0x30, 0x18, 0x18, 0x00, 0x0C, 0x00, // Char 033 (!)
@ -158,6 +160,8 @@ void gfx_con_init()
gfx_con.fillbg = 1; gfx_con.fillbg = 1;
gfx_con.bgcol = 0xFF1B1B1B; gfx_con.bgcol = 0xFF1B1B1B;
gfx_con.mute = 0; gfx_con.mute = 0;
gfx_con_init_done = true;
} }
void gfx_con_setcol(u32 fgcol, int fillbg, u32 bgcol) void gfx_con_setcol(u32 fgcol, int fillbg, u32 bgcol)
@ -274,7 +278,7 @@ void gfx_putc(char c)
void gfx_puts(const char *s) void gfx_puts(const char *s)
{ {
if (!s || gfx_con.mute) if (!s || !gfx_con_init_done || gfx_con.mute)
return; return;
for (; *s; s++) for (; *s; s++)
@ -330,7 +334,7 @@ void gfx_put_big_sep()
void gfx_printf(const char *fmt, ...) void gfx_printf(const char *fmt, ...)
{ {
if (gfx_con.mute) if (!gfx_con_init_done || gfx_con.mute)
return; return;
va_list ap; va_list ap;
@ -404,11 +408,13 @@ void gfx_printf(const char *fmt, ...)
va_end(ap); va_end(ap);
} }
void gfx_hexdump(u32 base, const u8 *buf, u32 len) void gfx_hexdump(u32 base, const void *buf, u32 len)
{ {
if (gfx_con.mute) if (!gfx_con_init_done || gfx_con.mute)
return; return;
u8 *buff = (u8 *)buf;
u8 prevFontSize = gfx_con.fntsz; u8 prevFontSize = gfx_con.fntsz;
gfx_con.fntsz = 8; gfx_con.fntsz = 8;
for(u32 i = 0; i < len; i++) for(u32 i = 0; i < len; i++)
@ -420,7 +426,7 @@ void gfx_hexdump(u32 base, const u8 *buf, u32 len)
gfx_puts("| "); gfx_puts("| ");
for(u32 j = 0; j < 0x10; j++) for(u32 j = 0; j < 0x10; j++)
{ {
u8 c = buf[i - 0x10 + j]; u8 c = buff[i - 0x10 + j];
if(c >= 32 && c <= 126) if(c >= 32 && c <= 126)
gfx_putc(c); gfx_putc(c);
else else
@ -430,7 +436,7 @@ void gfx_hexdump(u32 base, const u8 *buf, u32 len)
} }
gfx_printf("%08x: ", base + i); gfx_printf("%08x: ", base + i);
} }
gfx_printf("%02x ", buf[i]); gfx_printf("%02x ", buff[i]);
if (i == len - 1) if (i == len - 1)
{ {
int ln = len % 0x10 != 0; int ln = len % 0x10 != 0;
@ -444,7 +450,7 @@ void gfx_hexdump(u32 base, const u8 *buf, u32 len)
gfx_puts("| "); gfx_puts("| ");
for(u32 j = 0; j < (ln ? k : k + 1); j++) for(u32 j = 0; j < (ln ? k : k + 1); j++)
{ {
u8 c = buf[i - k + j]; u8 c = buff[i - k + j];
if(c >= 32 && c <= 126) if(c >= 32 && c <= 126)
gfx_putc(c); gfx_putc(c);
else else
@ -457,12 +463,15 @@ void gfx_hexdump(u32 base, const u8 *buf, u32 len)
gfx_con.fntsz = prevFontSize; gfx_con.fntsz = prevFontSize;
} }
void gfx_hexdiff(u32 base, const u8 *buf1, const u8 *buf2, u32 len) void gfx_hexdiff(u32 base, const void *buf1, const void *buf2, u32 len)
{ {
if (gfx_con.mute) if (!gfx_con_init_done || gfx_con.mute)
return; return;
if (memcmp(buf1, buf2, len) == 0) u8 *buff1 = (u8 *)buf1;
u8 *buff2 = (u8 *)buf2;
if (memcmp(buff1, buff2, len) == 0)
{ {
gfx_printf("Diff: No differences found.\n"); gfx_printf("Diff: No differences found.\n");
return; return;
@ -473,14 +482,14 @@ void gfx_hexdiff(u32 base, const u8 *buf1, const u8 *buf2, u32 len)
for(u32 i = 0; i < len; i+=0x10) for(u32 i = 0; i < len; i+=0x10)
{ {
u32 bytes_left = len - i < 0x10 ? len - i : 0x10; u32 bytes_left = len - i < 0x10 ? len - i : 0x10;
if (memcmp(buf1 + i, buf2 + i, bytes_left) == 0) if (memcmp(buff1 + i, buff2 + i, bytes_left) == 0)
continue; continue;
gfx_printf("Diff 1: %08x: ", base + i); gfx_printf("Diff 1: %08x: ", base + i);
for (u32 j = 0; j < bytes_left; j++) for (u32 j = 0; j < bytes_left; j++)
{ {
if (buf1[i+j] != buf2[i+j]) if (buff1[i+j] != buff2[i+j])
gfx_con.fgcol = COLOR_ORANGE; gfx_con.fgcol = COLOR_ORANGE;
gfx_printf("%02x ", buf1[i+j]); gfx_printf("%02x ", buff1[i+j]);
gfx_con.fgcol = 0xFFCCCCCC; gfx_con.fgcol = 0xFFCCCCCC;
} }
gfx_puts("| "); gfx_puts("| ");
@ -488,9 +497,9 @@ void gfx_hexdiff(u32 base, const u8 *buf1, const u8 *buf2, u32 len)
gfx_printf("Diff 2: %08x: ", base + i); gfx_printf("Diff 2: %08x: ", base + i);
for (u32 j = 0; j < bytes_left; j++) for (u32 j = 0; j < bytes_left; j++)
{ {
if (buf1[i+j] != buf2[i+j]) if (buff1[i+j] != buff2[i+j])
gfx_con.fgcol = COLOR_ORANGE; gfx_con.fgcol = COLOR_ORANGE;
gfx_printf("%02x ", buf2[i+j]); gfx_printf("%02x ", buff2[i+j]);
gfx_con.fgcol = 0xFFCCCCCC; gfx_con.fgcol = 0xFFCCCCCC;
} }
gfx_puts("| "); gfx_puts("| ");

View File

@ -1,6 +1,7 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer * Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2019-2021 shchmue
* Copyright (c) 2018 M4xw * Copyright (c) 2018 M4xw
* *
* 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
@ -63,8 +64,8 @@ void gfx_con_setpos(u32 x, u32 y);
void gfx_putc(char c); void gfx_putc(char c);
void gfx_puts(const char *s); void gfx_puts(const char *s);
void gfx_printf(const char *fmt, ...); void gfx_printf(const char *fmt, ...);
void gfx_hexdump(u32 base, const u8 *buf, u32 len); void gfx_hexdump(u32 base, const void *buf, u32 len);
void gfx_hexdiff(u32 base, const u8 *buf1, const u8 *buf2, u32 len); void gfx_hexdiff(u32 base, const void *buf1, const void *buf2, u32 len);
void gfx_set_pixel(u32 x, u32 y, u32 color); void gfx_set_pixel(u32 x, u32 y, u32 color);
void gfx_line(int x0, int y0, int x1, int y1, u32 color); void gfx_line(int x0, int y0, int x1, int y1, u32 color);

View File

@ -15,7 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <gfx/di.h> #include <display/di.h>
#include "tui.h" #include "tui.h"
#include "../config.h" #include "../config.h"
#include <power/max17050.h> #include <power/max17050.h>
@ -77,7 +77,7 @@ void tui_pbar(int x, int y, u32 val, u32 fgcol, u32 bgcol)
x += 7 * gfx_con.fntsz; x += 7 * gfx_con.fntsz;
for (int i = 0; i < (gfx_con.fntsz >> 3) * 6; i++) for (u32 i = 0; i < (gfx_con.fntsz >> 3) * 6; i++)
{ {
gfx_line(x, y + i + 1, x + 3 * val, y + i + 1, fgcol); gfx_line(x, y + i + 1, x + 3 * val, y + i + 1, fgcol);
gfx_line(x + 3 * val, y + i + 1, x + 3 * 100, y + i + 1, bgcol); gfx_line(x + 3 * val, y + i + 1, x + 3 * 100, y + i + 1, bgcol);

View File

@ -139,7 +139,7 @@ int parse_fss(launch_ctxt_t *ctxt, const char *path, fss0_sept_t *sept_ctxt)
if (mariko_not_supported) if (mariko_not_supported)
{ {
EPRINTF("Mariko not supported on < 0.17.0!"); EPRINTF("\nMariko not supported on < 0.17.0!");
goto fail; goto fail;
} }

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer * Copyright (c) 2018-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -20,6 +20,7 @@
#include "pkg1.h" #include "pkg1.h"
#include "pkg2.h" #include "pkg2.h"
#include <sec/se_t210.h>
#include <utils/types.h> #include <utils/types.h>
#include <utils/ini.h> #include <utils/ini.h>
#include <sec/tsec.h> #include <sec/tsec.h>
@ -50,20 +51,21 @@ typedef struct _exo_ctxt_t
bool fs_is_510; bool fs_is_510;
bool no_user_exceptions; bool no_user_exceptions;
bool user_pmu; bool user_pmu;
bool *usb3_force;
bool *cal0_blank; bool *cal0_blank;
bool *cal0_allow_writes_sys; bool *cal0_allow_writes_sys;
} exo_ctxt_t; } exo_ctxt_t;
typedef struct _hos_eks_keys_t typedef struct _hos_eks_keys_t
{ {
u8 mkk[0x10]; u8 mkk[SE_KEY_128_SIZE];
u8 fdk[0x10]; u8 fdk[SE_KEY_128_SIZE];
} hos_eks_keys_t; } hos_eks_keys_t;
typedef struct _hos_eks_bis_keys_t typedef struct _hos_eks_bis_keys_t
{ {
u8 crypt[0x10]; u8 crypt[SE_KEY_128_SIZE];
u8 tweak[0x10]; u8 tweak[SE_KEY_128_SIZE];
} hos_eks_bis_keys_t; } hos_eks_bis_keys_t;
typedef struct _hos_eks_mbr_t typedef struct _hos_eks_mbr_t
@ -73,8 +75,8 @@ typedef struct _hos_eks_mbr_t
u8 enabled_bis; u8 enabled_bis;
u8 rsvd[2]; u8 rsvd[2];
u32 lot0; u32 lot0;
u8 dkg[0x10]; u8 dkg[SE_KEY_128_SIZE];
u8 dkk[0x10]; u8 dkk[SE_KEY_128_SIZE];
hos_eks_keys_t keys[5]; hos_eks_keys_t keys[5];
hos_eks_bis_keys_t bis_keys[3]; hos_eks_bis_keys_t bis_keys[3];
} hos_eks_mbr_t; } hos_eks_mbr_t;
@ -106,14 +108,16 @@ typedef struct _launch_ctxt_t
link_t kip1_list; link_t kip1_list;
char* kip1_patches; char* kip1_patches;
u32 fss0_hosver;
bool svcperm; bool svcperm;
bool debugmode; bool debugmode;
bool stock; bool stock;
bool atmosphere;
bool fss0_experimental;
bool emummc_forced; bool emummc_forced;
char *fss0_main_path;
u32 fss0_hosver;
bool fss0_experimental;
bool atmosphere;
exo_ctxt_t exo_ctx; exo_ctxt_t exo_ctx;
ini_sec_t *cfg; ini_sec_t *cfg;
@ -129,6 +133,6 @@ void hos_eks_get();
void hos_eks_save(u32 kb); void hos_eks_save(u32 kb);
void hos_eks_clear(u32 kb); void hos_eks_clear(u32 kb);
int hos_launch(ini_sec_t *cfg); int hos_launch(ini_sec_t *cfg);
int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt); int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt);
#endif #endif

View File

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018 st4rk * Copyright (c) 2018 st4rk
* Copyright (c) 2018-2019 CTCaer * Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2018 balika011 * Copyright (c) 2018 balika011
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
@ -46,7 +46,7 @@ static const pkg1_id_t _pkg1_ids[] = {
const pkg1_id_t *pkg1_identify(u8 *pkg1) const pkg1_id_t *pkg1_identify(u8 *pkg1)
{ {
for (u32 i = 0; _pkg1_ids[i].id; i++) for (u32 i = 0; i < ARRAY_SIZE(_pkg1_ids); i++)
if (!memcmp(pkg1 + 0x10, _pkg1_ids[i].id, 8)) if (!memcmp(pkg1 + 0x10, _pkg1_ids[i].id, 8))
return &_pkg1_ids[i]; return &_pkg1_ids[i];
return NULL; return NULL;

View File

@ -21,7 +21,7 @@
#include "sept.h" #include "sept.h"
#include "../config.h" #include "../config.h"
#include <utils/ini.h> #include <utils/ini.h>
#include <gfx/di.h> #include <display/di.h>
#include <libs/fatfs/ff.h> #include <libs/fatfs/ff.h>
#include <mem/heap.h> #include <mem/heap.h>
#include <soc/hw_init.h> #include <soc/hw_init.h>

View File

@ -17,7 +17,7 @@
#include "keys.h" #include "keys.h"
#include "../config.h" #include "../config.h"
#include <gfx/di.h> #include <display/di.h>
#include <gfx_utils.h> #include <gfx_utils.h>
#include "../gfx/tui.h" #include "../gfx/tui.h"
#include "../hos/pkg1.h" #include "../hos/pkg1.h"
@ -93,8 +93,8 @@ static ALWAYS_INLINE u32 _get_tsec_fw_size(tsec_key_data_t *key_data) {
return key_data->blob0_size + sizeof(tsec_key_data_t) + key_data->blob1_size + key_data->blob2_size + key_data->blob3_size + key_data->blob4_size; return key_data->blob0_size + sizeof(tsec_key_data_t) + key_data->blob1_size + key_data->blob2_size + key_data->blob3_size + key_data->blob4_size;
} }
static u8 *_read_pkg1(sdmmc_t *sdmmc, const pkg1_id_t **pkg1_id) { static u8 *_read_pkg1(const pkg1_id_t **pkg1_id) {
if (emummc_storage_init_mmc(&emmc_storage, sdmmc)) { if (emummc_storage_init_mmc()) {
EPRINTF("Unable to init MMC."); EPRINTF("Unable to init MMC.");
return NULL; return NULL;
} }
@ -102,11 +102,11 @@ static u8 *_read_pkg1(sdmmc_t *sdmmc, const pkg1_id_t **pkg1_id) {
// Read package1. // Read package1.
u8 *pkg1 = (u8 *)malloc(PKG1_MAX_SIZE); u8 *pkg1 = (u8 *)malloc(PKG1_MAX_SIZE);
if (!emummc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0)) { if (!emummc_storage_set_mmc_partition(EMMC_BOOT0)) {
EPRINTF("Unable to set partition."); EPRINTF("Unable to set partition.");
return NULL; return NULL;
} }
if (!emummc_storage_read(&emmc_storage, PKG1_OFFSET / NX_EMMC_BLOCKSIZE, PKG1_MAX_SIZE / NX_EMMC_BLOCKSIZE, pkg1)) { if (!emummc_storage_read(PKG1_OFFSET / NX_EMMC_BLOCKSIZE, PKG1_MAX_SIZE / NX_EMMC_BLOCKSIZE, pkg1)) {
EPRINTF("Unable to read pkg1."); EPRINTF("Unable to read pkg1.");
return NULL; return NULL;
} }
@ -283,7 +283,7 @@ static void _derive_master_keys_from_keyblobs(key_derivation_ctx_t *keys) {
se_aes_key_set(8, keys->tsec_keys, sizeof(keys->tsec_keys) / 2); se_aes_key_set(8, keys->tsec_keys, sizeof(keys->tsec_keys) / 2);
if (!emummc_storage_read(&emmc_storage, KEYBLOB_OFFSET / NX_EMMC_BLOCKSIZE, KB_FIRMWARE_VERSION_600 + 1, keyblob_block)) { if (!emummc_storage_read(KEYBLOB_OFFSET / NX_EMMC_BLOCKSIZE, KB_FIRMWARE_VERSION_600 + 1, keyblob_block)) {
EPRINTF("Unable to read keyblobs."); EPRINTF("Unable to read keyblobs.");
} }
@ -577,7 +577,7 @@ static bool _derive_titlekeys(key_derivation_ctx_t *keys, titlekey_buffer_t *tit
rsa_keypair_t rsa_keypair = {0}; rsa_keypair_t rsa_keypair = {0};
if (!emummc_storage_read(&emmc_storage, NX_EMMC_CALIBRATION_OFFSET / NX_EMMC_BLOCKSIZE, NX_EMMC_CALIBRATION_SIZE / NX_EMMC_BLOCKSIZE, titlekey_buffer->read_buffer)) { if (!emummc_storage_read(NX_EMMC_CALIBRATION_OFFSET / NX_EMMC_BLOCKSIZE, NX_EMMC_CALIBRATION_SIZE / NX_EMMC_BLOCKSIZE, titlekey_buffer->read_buffer)) {
EPRINTF("Unable to read PRODINFO."); EPRINTF("Unable to read PRODINFO.");
return false; return false;
} }
@ -643,7 +643,7 @@ static bool _derive_emmc_keys(key_derivation_ctx_t *keys, titlekey_buffer_t *tit
se_aes_key_set(4, keys->bis_key[2] + 0x00, AES_128_KEY_SIZE); se_aes_key_set(4, keys->bis_key[2] + 0x00, AES_128_KEY_SIZE);
se_aes_key_set(5, keys->bis_key[2] + 0x10, AES_128_KEY_SIZE); se_aes_key_set(5, keys->bis_key[2] + 0x10, AES_128_KEY_SIZE);
if (!emummc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP)) { if (!emummc_storage_set_mmc_partition(EMMC_GPP)) {
EPRINTF("Unable to set partition."); EPRINTF("Unable to set partition.");
return false; return false;
} }
@ -690,7 +690,7 @@ static void _save_mariko_partial_keys(char *text_buffer) {
for (u32 ks = 12; ks < 16; ks++) { for (u32 ks = 12; ks < 16; ks++) {
// First, encrypt zeros with complete key // First, encrypt zeros with complete key
se_aes_crypt_block_ecb(ks, 1, &data[3 * AES_128_KEY_SIZE], zeros); se_aes_crypt_block_ecb(ks, 1, &data[3 * AES_128_KEY_SIZE], zeros);
pos += sprintf(&text_buffer[pos], "%d\n", ks); pos += s_printf(&text_buffer[pos], "%d\n", ks);
// We only need to overwrite 3 of the dwords of the key // We only need to overwrite 3 of the dwords of the key
for (u32 i = 0; i < 3; i++) { for (u32 i = 0; i < 3; i++) {
@ -701,8 +701,8 @@ static void _save_mariko_partial_keys(char *text_buffer) {
} }
for (u32 i = 0; i < 4; i++) { for (u32 i = 0; i < 4; i++) {
for (u32 j = 0; j < AES_128_KEY_SIZE; j++) for (u32 j = 0; j < AES_128_KEY_SIZE; j++)
pos += sprintf(&text_buffer[pos], "%02x", data[i * AES_128_KEY_SIZE + j]); pos += s_printf(&text_buffer[pos], "%02x", data[i * AES_128_KEY_SIZE + j]);
pos += sprintf(&text_buffer[pos], "\n"); pos += s_printf(&text_buffer[pos], "\n");
} }
} }
free(data); free(data);
@ -788,7 +788,7 @@ static void _save_keys_to_sd(key_derivation_ctx_t *keys, titlekey_buffer_t *titl
f_mkdir("sd:/switch"); f_mkdir("sd:/switch");
char keyfile_path[30] = "sd:/switch/prod.keys"; char keyfile_path[30] = "sd:/switch/prod.keys";
if (fuse_read_odm(4) & 3) if (fuse_read_odm(4) & 3)
sprintf(&keyfile_path[11], "dev.keys"); s_printf(&keyfile_path[11], "dev.keys");
FILINFO fno; FILINFO fno;
if (!sd_save_to_file(text_buffer, strlen(text_buffer), keyfile_path) && !f_stat(keyfile_path, &fno)) { if (!sd_save_to_file(text_buffer, strlen(text_buffer), keyfile_path) && !f_stat(keyfile_path, &fno)) {
@ -811,13 +811,13 @@ static void _save_keys_to_sd(key_derivation_ctx_t *keys, titlekey_buffer_t *titl
for (u32 i = 0; i < _titlekey_count; i++) { for (u32 i = 0; i < _titlekey_count; i++) {
for (u32 j = 0; j < AES_128_KEY_SIZE; j++) for (u32 j = 0; j < AES_128_KEY_SIZE; j++)
sprintf(&titlekey_text[i].rights_id[j * 2], "%02x", titlekey_buffer->rights_ids[i][j]); s_printf(&titlekey_text[i].rights_id[j * 2], "%02x", titlekey_buffer->rights_ids[i][j]);
sprintf(titlekey_text[i].equals, " = "); s_printf(titlekey_text[i].equals, " = ");
for (u32 j = 0; j < AES_128_KEY_SIZE; j++) for (u32 j = 0; j < AES_128_KEY_SIZE; j++)
sprintf(&titlekey_text[i].titlekey[j * 2], "%02x", titlekey_buffer->titlekeys[i][j]); s_printf(&titlekey_text[i].titlekey[j * 2], "%02x", titlekey_buffer->titlekeys[i][j]);
sprintf(titlekey_text[i].newline, "\n"); s_printf(titlekey_text[i].newline, "\n");
} }
sprintf(&keyfile_path[11], "title.keys"); s_printf(&keyfile_path[11], "title.keys");
if (!sd_save_to_file(text_buffer, strlen(text_buffer), keyfile_path) && !f_stat(keyfile_path, &fno)) { if (!sd_save_to_file(text_buffer, strlen(text_buffer), keyfile_path) && !f_stat(keyfile_path, &fno)) {
gfx_printf("%kWrote %d bytes to %s\n", colors[(color_idx++) % 6], (u32)fno.fsize, keyfile_path); gfx_printf("%kWrote %d bytes to %s\n", colors[(color_idx++) % 6], (u32)fno.fsize, keyfile_path);
} else } else
@ -828,10 +828,9 @@ static void _save_keys_to_sd(key_derivation_ctx_t *keys, titlekey_buffer_t *titl
static void _derive_keys() { static void _derive_keys() {
u32 start_whole_operation_time = get_tmr_us(); u32 start_whole_operation_time = get_tmr_us();
sdmmc_t sdmmc;
const pkg1_id_t *pkg1_id; const pkg1_id_t *pkg1_id;
u8 *pkg1 = _read_pkg1(&sdmmc, &pkg1_id); u8 *pkg1 = _read_pkg1(&pkg1_id);
if (!pkg1) { if (!pkg1) {
return; return;
} }
@ -909,17 +908,17 @@ static void _save_key(const char *name, const void *data, u32 len, char *outbuf)
if (!_key_exists(data)) if (!_key_exists(data))
return; return;
u32 pos = strlen(outbuf); u32 pos = strlen(outbuf);
pos += sprintf(&outbuf[pos], "%s = ", name); pos += s_printf(&outbuf[pos], "%s = ", name);
for (u32 i = 0; i < len; i++) for (u32 i = 0; i < len; i++)
pos += sprintf(&outbuf[pos], "%02x", *(u8*)(data + i)); pos += s_printf(&outbuf[pos], "%02x", *(u8*)(data + i));
sprintf(&outbuf[pos], "\n"); s_printf(&outbuf[pos], "\n");
_key_count++; _key_count++;
} }
static void _save_key_family(const char *name, const void *data, u32 start_key, u32 num_keys, u32 len, char *outbuf) { static void _save_key_family(const char *name, const void *data, u32 start_key, u32 num_keys, u32 len, char *outbuf) {
char *temp_name = calloc(1, 0x40); char *temp_name = calloc(1, 0x40);
for (u32 i = 0; i < num_keys; i++) { for (u32 i = 0; i < num_keys; i++) {
sprintf(temp_name, "%s_%02x", name, i + start_key); s_printf(temp_name, "%s_%02x", name, i + start_key);
_save_key(temp_name, data + i * len, len, outbuf); _save_key(temp_name, data + i * len, len, outbuf);
} }
free(temp_name); free(temp_name);

View File

@ -245,7 +245,7 @@
#define FF_FS_NORTC 1 #define FF_FS_NORTC 1
#define FF_NORTC_MON 1 #define FF_NORTC_MON 1
#define FF_NORTC_MDAY 1 #define FF_NORTC_MDAY 1
#define FF_NORTC_YEAR 2020 #define FF_NORTC_YEAR 2021
/* The option FF_FS_NORTC switches timestamp function. If the system does not have /* The option FF_FS_NORTC switches timestamp function. If the system does not have
/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable / any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable
/ the timestamp function. Every object modified by FatFs will have a fixed timestamp / the timestamp function. Every object modified by FatFs will have a fixed timestamp

View File

@ -5,7 +5,8 @@ SECTIONS {
. = __ipl_start; . = __ipl_start;
.text : { .text : {
*(.text._start); *(.text._start);
*(._boot_cfg); KEEP(*(._boot_cfg));
*(.text._irq_setup);
*(.text*); *(.text*);
} }
.data : { .data : {

View File

@ -1,8 +1,8 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* *
* Copyright (c) 2018-2020 CTCaer * Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2019-2020 shchmue * Copyright (c) 2019-2021 shchmue
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -20,7 +20,7 @@
#include <string.h> #include <string.h>
#include "config.h" #include "config.h"
#include <gfx/di.h> #include <display/di.h>
#include <gfx_utils.h> #include <gfx_utils.h>
#include "gfx/tui.h" #include "gfx/tui.h"
#include <libs/fatfs/ff.h> #include <libs/fatfs/ff.h>
@ -57,6 +57,7 @@ volatile nyx_storage_t *nyx_str = (nyx_storage_t *)NYX_STORAGE_ADDR;
#define EXT_PAYLOAD_ADDR 0xC0000000 #define EXT_PAYLOAD_ADDR 0xC0000000
#define RCM_PAYLOAD_ADDR (EXT_PAYLOAD_ADDR + ALIGN(PATCHED_RELOC_SZ, 0x10)) #define RCM_PAYLOAD_ADDR (EXT_PAYLOAD_ADDR + ALIGN(PATCHED_RELOC_SZ, 0x10))
#define COREBOOT_END_ADDR 0xD0000000 #define COREBOOT_END_ADDR 0xD0000000
#define COREBOOT_VER_OFF 0x41
#define CBFS_DRAM_EN_ADDR 0x4003e000 #define CBFS_DRAM_EN_ADDR 0x4003e000
#define CBFS_DRAM_MAGIC 0x4452414D // "DRAM" #define CBFS_DRAM_MAGIC 0x4452414D // "DRAM"
@ -80,9 +81,10 @@ void reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size)
} }
} }
int launch_payload(char *path) int launch_payload(char *path, bool clear_screen)
{ {
gfx_clear_grey(0x1B); if (clear_screen)
gfx_clear_grey(0x1B);
gfx_con_setpos(0, 0); gfx_con_setpos(0, 0);
if (!path) if (!path)
return 1; return 1;
@ -92,10 +94,10 @@ int launch_payload(char *path)
FIL fp; FIL fp;
if (f_open(&fp, path, FA_READ)) if (f_open(&fp, path, FA_READ))
{ {
gfx_con.mute = false;
EPRINTFARGS("Payload file is missing!\n(%s)", path); EPRINTFARGS("Payload file is missing!\n(%s)", path);
sd_unmount();
return 1; goto out;
} }
// Read and copy the payload to our chosen address // Read and copy the payload to our chosen address
@ -108,19 +110,27 @@ int launch_payload(char *path)
{ {
coreboot_addr = (void *)(COREBOOT_END_ADDR - size); coreboot_addr = (void *)(COREBOOT_END_ADDR - size);
buf = coreboot_addr; buf = coreboot_addr;
if (h_cfg.t210b01)
{
f_close(&fp);
gfx_con.mute = false;
EPRINTF("Coreboot not allowed on Mariko!");
goto out;
}
} }
if (f_read(&fp, buf, size, NULL)) if (f_read(&fp, buf, size, NULL))
{ {
f_close(&fp); f_close(&fp);
sd_unmount();
return 1; goto out;
} }
f_close(&fp); f_close(&fp);
sd_unmount(); sd_end();
if (size < 0x30000) if (size < 0x30000)
{ {
@ -131,7 +141,12 @@ int launch_payload(char *path)
else else
{ {
reloc_patcher(PATCHED_RELOC_ENTRY, EXT_PAYLOAD_ADDR, 0x7000); reloc_patcher(PATCHED_RELOC_ENTRY, EXT_PAYLOAD_ADDR, 0x7000);
hw_reinit_workaround(true, 0);
// Get coreboot seamless display magic.
u32 magic = 0;
char *magic_ptr = buf + COREBOOT_VER_OFF;
memcpy(&magic, magic_ptr + strlen(magic_ptr) - 4, 4);
hw_reinit_workaround(true, magic);
} }
// Some cards (Sandisk U1), do not like a fast power cycle. Wait min 100ms. // Some cards (Sandisk U1), do not like a fast power cycle. Wait min 100ms.
@ -143,6 +158,8 @@ int launch_payload(char *path)
(*ext_payload_ptr)(); (*ext_payload_ptr)();
} }
out:
sd_end();
return 1; return 1;
} }
@ -221,7 +238,8 @@ void launch_tools()
free(ments); free(ments);
free(dir); free(dir);
free(filelist); free(filelist);
sd_unmount(); sd_end();
return; return;
} }
} }
@ -247,15 +265,12 @@ void launch_tools()
else else
memcpy(dir, file_sec, strlen(file_sec) + 1); memcpy(dir, file_sec, strlen(file_sec) + 1);
if (launch_payload(dir)) launch_payload(dir, true);
{ EPRINTF("Failed to launch payload.");
EPRINTF("Failed to launch payload.");
free(dir);
}
} }
out: out:
sd_unmount(); sd_end();
free(dir); free(dir);
btn_wait(); btn_wait();
@ -278,15 +293,20 @@ void dump_emunand()
dump_keys(); dump_keys();
} }
power_state_t STATE_POWER_OFF = POWER_OFF_RESET;
power_state_t STATE_REBOOT_FULL = POWER_OFF_REBOOT;
power_state_t STATE_REBOOT_RCM = REBOOT_RCM;
power_state_t STATE_REBOOT_BYPASS_FUSES = REBOOT_BYPASS_FUSES;
ment_t ment_top[] = { ment_t ment_top[] = {
MDEF_HANDLER("Dump from SysNAND | Key generation: unk", dump_sysnand, COLOR_RED), MDEF_HANDLER("Dump from SysNAND | Key generation: unk", dump_sysnand, COLOR_RED),
MDEF_HANDLER("Dump from EmuNAND | Key generation: unk", dump_emunand, COLOR_ORANGE), MDEF_HANDLER("Dump from EmuNAND | Key generation: unk", dump_emunand, COLOR_ORANGE),
MDEF_CAPTION("---------------", COLOR_YELLOW), MDEF_CAPTION("---------------", COLOR_YELLOW),
MDEF_HANDLER("Payloads...", launch_tools, COLOR_GREEN), MDEF_HANDLER("Payloads...", launch_tools, COLOR_GREEN),
MDEF_CAPTION("---------------", COLOR_BLUE), MDEF_CAPTION("---------------", COLOR_BLUE),
MDEF_HANDLER("Reboot (Normal)", reboot_normal, COLOR_VIOLET), MDEF_HANDLER_EX("Reboot (OFW)", &STATE_REBOOT_BYPASS_FUSES, power_set_state_ex, COLOR_VIOLET),
MDEF_HANDLER("Reboot (RCM)", reboot_rcm, COLOR_RED), MDEF_HANDLER_EX("Reboot (RCM)", &STATE_REBOOT_RCM, power_set_state_ex, COLOR_RED),
MDEF_HANDLER("Power off", power_off, COLOR_ORANGE), MDEF_HANDLER_EX("Power off", &STATE_POWER_OFF, power_set_state_ex, COLOR_ORANGE),
MDEF_END() MDEF_END()
}; };
@ -305,7 +325,7 @@ void _get_key_generations(char *sysnand_label, char *emunand_label)
u32 pk1_offset = h_cfg.t210b01 ? sizeof(bl_hdr_t210b01_t) : 0; // Skip T210B01 OEM header. u32 pk1_offset = h_cfg.t210b01 ? sizeof(bl_hdr_t210b01_t) : 0; // Skip T210B01 OEM header.
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1 + pk1_offset); const pkg1_id_t *pkg1_id = pkg1_identify(pkg1 + pk1_offset);
if (pkg1_id) { if (pkg1_id) {
sprintf(sysnand_label + 36, "% 3d", pkg1_id->kb); s_printf(sysnand_label + 36, "% 3d", pkg1_id->kb);
ment_top[0].caption = sysnand_label; ment_top[0].caption = sysnand_label;
if (h_cfg.emummc_force_disable) if (h_cfg.emummc_force_disable)
{ {
@ -314,15 +334,15 @@ void _get_key_generations(char *sysnand_label, char *emunand_label)
} }
} }
emummc_storage_init_mmc(&storage, &sdmmc); emummc_storage_init_mmc();
memset(pkg1, 0, PKG1_MAX_SIZE); memset(pkg1, 0, PKG1_MAX_SIZE);
emummc_storage_set_mmc_partition(&storage, EMMC_BOOT0); emummc_storage_set_mmc_partition(EMMC_BOOT0);
emummc_storage_read(&storage, PKG1_OFFSET / NX_EMMC_BLOCKSIZE, PKG1_MAX_SIZE / NX_EMMC_BLOCKSIZE, pkg1); emummc_storage_read(PKG1_OFFSET / NX_EMMC_BLOCKSIZE, PKG1_MAX_SIZE / NX_EMMC_BLOCKSIZE, pkg1);
emummc_storage_end(&storage); emummc_storage_end();
pkg1_id = pkg1_identify(pkg1 + pk1_offset); pkg1_id = pkg1_identify(pkg1 + pk1_offset);
if (pkg1_id) { if (pkg1_id) {
sprintf(emunand_label + 36, "% 3d", pkg1_id->kb); s_printf(emunand_label + 36, "% 3d", pkg1_id->kb);
free(pkg1); free(pkg1);
ment_top[1].caption = emunand_label; ment_top[1].caption = emunand_label;
} }
@ -367,8 +387,9 @@ void ipl_main()
display_backlight_pwm_init(); display_backlight_pwm_init();
// Overclock BPMP. // Overclock BPMP.
bpmp_clk_rate_set(BPMP_CLK_DEFAULT_BOOST); bpmp_clk_rate_set(h_cfg.t210b01 ? BPMP_CLK_DEFAULT_BOOST : BPMP_CLK_LOWER_BOOST);
// Load emuMMC configuration from SD.
emummc_load_cfg(); emummc_load_cfg();
// Ignore whether emummc is enabled. // Ignore whether emummc is enabled.
h_cfg.emummc_force_disable = emu_cfg.sector == 0 && !emu_cfg.path; h_cfg.emummc_force_disable = emu_cfg.sector == 0 && !emu_cfg.path;
@ -401,7 +422,7 @@ void ipl_main()
if (h_cfg.rcm_patched) if (h_cfg.rcm_patched)
{ {
ment_top[5].handler = reboot_full; ment_top[6].data = &STATE_REBOOT_FULL;
} }
// Update key generations listed in menu. // Update key generations listed in menu.

View File

@ -23,8 +23,8 @@
.extern memset .extern memset
.type memset, %function .type memset, %function
.extern ipl_main .extern _irq_setup
.type ipl_main, %function .type _irq_setup, %function
.globl _start .globl _start
.type _start, %function .type _start, %function
@ -67,7 +67,7 @@ _real_start:
LDR R2, =__bss_end LDR R2, =__bss_end
SUB R2, R2, R0 SUB R2, R2, R0
BL memset BL memset
BL ipl_main BL _irq_setup
B . B .
.globl pivot_stack .globl pivot_stack

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019 CTCaer * Copyright (c) 2019-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -131,13 +131,13 @@ static int emummc_raw_get_part_off(int part_idx)
return 2; return 2;
} }
int emummc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc) int emummc_storage_init_mmc()
{ {
FILINFO fno; FILINFO fno;
emu_cfg.active_part = 0; emu_cfg.active_part = 0;
// Always init eMMC even when in emuMMC. eMMC is needed from the emuMMC driver anyway. // Always init eMMC even when in emuMMC. eMMC is needed from the emuMMC driver anyway.
if (!sdmmc_storage_init_mmc(storage, sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400)) if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
return 2; return 2;
if (!emu_cfg.enabled || h_cfg.emummc_force_disable) if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
@ -173,21 +173,21 @@ out:
return 1; return 1;
} }
int emummc_storage_end(sdmmc_storage_t *storage) int emummc_storage_end()
{ {
if (!emu_cfg.enabled || h_cfg.emummc_force_disable) if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
sdmmc_storage_end(storage); sdmmc_storage_end(&emmc_storage);
else else
sd_end(); sd_end();
return 1; return 1;
} }
int emummc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf) int emummc_storage_read(u32 sector, u32 num_sectors, void *buf)
{ {
FIL fp; FIL fp;
if (!emu_cfg.enabled || h_cfg.emummc_force_disable) if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
return sdmmc_storage_read(storage, sector, num_sectors, buf); return sdmmc_storage_read(&emmc_storage, sector, num_sectors, buf);
else if (emu_cfg.sector) else if (emu_cfg.sector)
{ {
sector += emu_cfg.sector; sector += emu_cfg.sector;
@ -228,11 +228,11 @@ int emummc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, v
return 1; return 1;
} }
int emummc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf) int emummc_storage_write(u32 sector, u32 num_sectors, void *buf)
{ {
FIL fp; FIL fp;
if (!emu_cfg.enabled || h_cfg.emummc_force_disable) if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
return sdmmc_storage_write(storage, sector, num_sectors, buf); return sdmmc_storage_write(&emmc_storage, sector, num_sectors, buf);
else if (emu_cfg.sector) else if (emu_cfg.sector)
{ {
sector += emu_cfg.sector; sector += emu_cfg.sector;
@ -253,15 +253,13 @@ int emummc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors,
itoa(file_part, emu_cfg.emummc_file_based_path + strlen(emu_cfg.emummc_file_based_path) - 1, 10); itoa(file_part, emu_cfg.emummc_file_based_path + strlen(emu_cfg.emummc_file_based_path) - 1, 10);
} }
} }
if (f_open(&fp, emu_cfg.emummc_file_based_path, FA_WRITE)) if (f_open(&fp, emu_cfg.emummc_file_based_path, FA_WRITE))
{
gfx_printf("e5\n");
return 0; return 0;
}
f_lseek(&fp, (u64)sector << 9); f_lseek(&fp, (u64)sector << 9);
if (f_write(&fp, buf, (u64)num_sectors << 9, NULL)) if (f_write(&fp, buf, (u64)num_sectors << 9, NULL))
{ {
gfx_printf("e6\n");
f_close(&fp); f_close(&fp);
return 0; return 0;
} }
@ -271,13 +269,12 @@ int emummc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors,
} }
} }
int emummc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition) int emummc_storage_set_mmc_partition(u32 partition)
{ {
emu_cfg.active_part = partition; emu_cfg.active_part = partition;
sdmmc_storage_set_mmc_partition(&emmc_storage, partition);
if (!emu_cfg.enabled || h_cfg.emummc_force_disable) if (!emu_cfg.enabled || h_cfg.emummc_force_disable || emu_cfg.sector)
sdmmc_storage_set_mmc_partition(storage, partition);
else if (emu_cfg.sector)
return 1; return 1;
else else
{ {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019 CTCaer * Copyright (c) 2019-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -51,10 +51,10 @@ extern emummc_cfg_t emu_cfg;
void emummc_load_cfg(); void emummc_load_cfg();
bool emummc_set_path(char *path); bool emummc_set_path(char *path);
int emummc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc); int emummc_storage_init_mmc();
int emummc_storage_end(sdmmc_storage_t *storage); int emummc_storage_end();
int emummc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf); int emummc_storage_read(u32 sector, u32 num_sectors, void *buf);
int emummc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf); int emummc_storage_write(u32 sector, u32 num_sectors, void *buf);
int emummc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition); int emummc_storage_set_mmc_partition(u32 partition);
#endif #endif

View File

@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2019-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -19,6 +20,7 @@
#include "nx_emmc.h" #include "nx_emmc.h"
#include "emummc.h" #include "emummc.h"
#include <mem/heap.h> #include <mem/heap.h>
#include <soc/fuse.h>
#include <storage/mbr_gpt.h> #include <storage/mbr_gpt.h>
#include <utils/list.h> #include <utils/list.h>
@ -30,7 +32,11 @@ void nx_emmc_gpt_parse(link_t *gpt, sdmmc_storage_t *storage)
{ {
gpt_t *gpt_buf = (gpt_t *)calloc(NX_GPT_NUM_BLOCKS, NX_EMMC_BLOCKSIZE); gpt_t *gpt_buf = (gpt_t *)calloc(NX_GPT_NUM_BLOCKS, NX_EMMC_BLOCKSIZE);
emummc_storage_read(storage, NX_GPT_FIRST_LBA, NX_GPT_NUM_BLOCKS, gpt_buf); emummc_storage_read(NX_GPT_FIRST_LBA, NX_GPT_NUM_BLOCKS, gpt_buf);
// Check if no GPT or more than max allowed entries.
if (memcmp(&gpt_buf->header.signature, "EFI PART", 8) || gpt_buf->header.num_part_ents > 128)
goto out;
for (u32 i = 0; i < gpt_buf->header.num_part_ents; i++) for (u32 i = 0; i < gpt_buf->header.num_part_ents; i++)
{ {
@ -52,6 +58,7 @@ void nx_emmc_gpt_parse(link_t *gpt, sdmmc_storage_t *storage)
list_append(gpt, &part->link); list_append(gpt, &part->link);
} }
out:
free(gpt_buf); free(gpt_buf);
} }
@ -66,6 +73,7 @@ emmc_part_t *nx_emmc_part_find(link_t *gpt, const char *name)
LIST_FOREACH_ENTRY(emmc_part_t, part, gpt, link) LIST_FOREACH_ENTRY(emmc_part_t, part, gpt, link)
if (!strcmp(part->name, name)) if (!strcmp(part->name, name))
return part; return part;
return NULL; return NULL;
} }
@ -74,7 +82,8 @@ int nx_emmc_part_read(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_of
// The last LBA is inclusive. // The last LBA is inclusive.
if (part->lba_start + sector_off > part->lba_end) if (part->lba_start + sector_off > part->lba_end)
return 0; return 0;
return emummc_storage_read(storage, part->lba_start + sector_off, num_sectors, buf);
return emummc_storage_read(part->lba_start + sector_off, num_sectors, buf);
} }
int nx_emmc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf) int nx_emmc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf)
@ -82,5 +91,20 @@ int nx_emmc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_o
// The last LBA is inclusive. // The last LBA is inclusive.
if (part->lba_start + sector_off > part->lba_end) if (part->lba_start + sector_off > part->lba_end)
return 0; return 0;
return sdmmc_storage_write(storage, part->lba_start + sector_off, num_sectors, buf);
return emummc_storage_write(part->lba_start + sector_off, num_sectors, buf);
}
void nx_emmc_get_autorcm_masks(u8 *mod0, u8 *mod1)
{
if (fuse_read_hw_state() == FUSE_NX_HW_STATE_PROD)
{
*mod0 = 0xF7;
*mod1 = 0x86;
}
else
{
*mod0 = 0x37;
*mod1 = 0x84;
}
} }

View File

@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2019-2020 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -43,7 +44,9 @@ extern FATFS emmc_fs;
void nx_emmc_gpt_parse(link_t *gpt, sdmmc_storage_t *storage); void nx_emmc_gpt_parse(link_t *gpt, sdmmc_storage_t *storage);
void nx_emmc_gpt_free(link_t *gpt); void nx_emmc_gpt_free(link_t *gpt);
emmc_part_t *nx_emmc_part_find(link_t *gpt, const char *name); emmc_part_t *nx_emmc_part_find(link_t *gpt, const char *name);
int nx_emmc_part_read(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf); int nx_emmc_part_read(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf);
int nx_emmc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf); int nx_emmc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf);
void nx_emmc_get_autorcm_masks(u8 *mod0, u8 *mod1);
#endif #endif

View File

@ -23,6 +23,7 @@
#include <mem/heap.h> #include <mem/heap.h>
#include <sec/se.h> #include <sec/se.h>
#include <sec/se_t210.h>
#include "../storage/nx_emmc.h" #include "../storage/nx_emmc.h"
#include "nx_emmc_bis.h" #include "nx_emmc_bis.h"
#include <storage/sdmmc.h> #include <storage/sdmmc.h>
@ -32,7 +33,7 @@
#define CLUSTER_LOOKUP_EMPTY_ENTRY 0xFFFFFFFF #define CLUSTER_LOOKUP_EMPTY_ENTRY 0xFFFFFFFF
#define SECTORS_PER_CLUSTER 0x20 #define SECTORS_PER_CLUSTER 0x20
typedef struct typedef struct _cluster_cache_t
{ {
u32 cluster_num; // index of the cluster in the partition u32 cluster_num; // index of the cluster in the partition
u32 visit_count; // used for debugging/access analysis u32 visit_count; // used for debugging/access analysis
@ -41,7 +42,7 @@ typedef struct
u8 cluster[XTS_CLUSTER_SIZE]; // the cached cluster itself u8 cluster[XTS_CLUSTER_SIZE]; // the cached cluster itself
} cluster_cache_t; } cluster_cache_t;
typedef struct typedef struct _bis_cache_t
{ {
u8 emmc_buffer[XTS_CLUSTER_SIZE]; u8 emmc_buffer[XTS_CLUSTER_SIZE];
cluster_cache_t cluster_cache[]; cluster_cache_t cluster_cache[];
@ -313,8 +314,8 @@ void nx_emmc_bis_cluster_cache_init()
free(cluster_lookup_buf); free(cluster_lookup_buf);
// Check if carveout protected, in case of old hwinit (pre 4.0.0) chainload. // Check if carveout protected, in case of old hwinit (pre 4.0.0) chainload.
*(vu32 *)NX_BIS_LOOKUP_ADR = 0; *(vu32 *)NX_BIS_LOOKUP_ADDR = 0;
if (*(vu32 *)NX_BIS_LOOKUP_ADR != 0) if (*(vu32 *)NX_BIS_LOOKUP_ADDR != 0)
{ {
cluster_lookup_buf = (u32 *)malloc(cluster_lookup_size + 0x2000); cluster_lookup_buf = (u32 *)malloc(cluster_lookup_size + 0x2000);
cluster_lookup = (u32 *)ALIGN((u32)cluster_lookup_buf, 0x1000); cluster_lookup = (u32 *)ALIGN((u32)cluster_lookup_buf, 0x1000);
@ -322,7 +323,7 @@ void nx_emmc_bis_cluster_cache_init()
else else
{ {
cluster_lookup_buf = NULL; cluster_lookup_buf = NULL;
cluster_lookup = (u32 *)NX_BIS_LOOKUP_ADR; cluster_lookup = (u32 *)NX_BIS_LOOKUP_ADDR;
} }
// Clear cluster lookup table and reset end index. // Clear cluster lookup table and reset end index.

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2019 CTCaer * Copyright (c) 2018-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -59,6 +59,11 @@ bool sd_get_card_removed()
return false; return false;
} }
bool sd_get_card_mounted()
{
return sd_mounted;
}
u32 sd_get_mode() u32 sd_get_mode()
{ {
return sd_mode; return sd_mode;
@ -180,6 +185,11 @@ static void _sd_deinit()
void sd_unmount() { _sd_deinit(); } void sd_unmount() { _sd_deinit(); }
void sd_end() { _sd_deinit(); } void sd_end() { _sd_deinit(); }
bool sd_is_gpt()
{
return sd_fs.part_type;
}
void *sd_file_read(const char *path, u32 *fsize) void *sd_file_read(const char *path, u32 *fsize)
{ {
FIL fp; FIL fp;