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

View file

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

View file

@ -650,7 +650,9 @@
* [10] 81 [26]: JDI LPM062M326A
* [10] 96 [09]: JDI LAM062M109A
* [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] 95 [0F]: AUO A062TAN02 (59.06A33.002)
*
@ -671,10 +673,12 @@
* 20h: InnoLux Corporation
* 30h: AU Optronics
* 40h: Unknown1
* 50h: Unknown2 (OLED? Samsung? LG?)
*
* Boards, Panel Size:
* 0Fh: Icosa/Iowa, 6.2"
* 10h: Hoag, 5.5"
* 20h: Unknown, x.x"
*/
enum
@ -693,8 +697,9 @@ void display_init();
void display_backlight_pwm_init();
void display_end();
/*! Get Display panel ID. */
u16 display_get_decoded_lcd_id();
/*! Get/Set Display panel ID. */
u16 display_get_decoded_panel_id();
void display_set_decoded_panel_id(u32 id);
/*! Show one single color on the display. */
void display_color_screen(u32 color);
@ -702,6 +707,7 @@ void display_color_screen(u32 color);
/*! Switches screen backlight ON/OFF. */
void display_backlight(bool enable);
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). */
u32 *display_init_framebuffer_pitch();

View file

@ -21,6 +21,7 @@
#include "elfload/elfload.h"
#include <module.h>
#include <mem/heap.h>
#include <power/max7762x.h>
#include <storage/nx_sd.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->sharedHeap = &_heap;
// Extra functions.
bdkParameters->extension_magic = IANOS_EXT0;
bdkParameters->reg_voltage_set = (reg_voltage_set_t)&max7762x_regulator_set_voltage;
entrypoint(moduleConfig, bdkParameters);
}

View file

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

View file

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

View file

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

View file

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

View file

@ -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 result;
LZ4_stream_t ctx;
LZ4_stream_t* const ctxPtr = &ctx;
LZ4_stream_t* ctx = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t));
LZ4_stream_t* const ctxPtr = ctx;
result = LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration);
FREEMEM(ctx);
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 */
int LZ4_compress_fast_force(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
{
LZ4_stream_t ctx;
LZ4_resetStream(&ctx);
int result;
LZ4_stream_t* ctx = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t));
LZ4_resetStream(ctx);
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
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)
{
LZ4_stream_t ctxBody;
LZ4_stream_t* ctx = &ctxBody;
LZ4_stream_t* ctxBody = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t));;
LZ4_stream_t* ctx = ctxBody;
int result = LZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize);
FREEMEM(ctxBody);
return result;
}

View file

@ -27,7 +27,8 @@ typedef enum {
DRIVE_SD = 0,
DRIVE_RAM = 1,
DRIVE_EMMC = 2,
DRIVE_BIS = 3
DRIVE_BIS = 3,
DRIVE_EMU = 4
} 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_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 SET_SECTOR_OFFSET 5 /* Set media logical offset */
/* Generic command (Not used by FatFs) */
#define CTRL_POWER 5 /* Get/Set power status */

View file

@ -1,6 +1,6 @@
/*
* 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
* under the terms and conditions of the GNU General Public License,
@ -38,6 +38,7 @@
#include "ff.h" /* Declarations of FatFs API */
#include "diskio.h" /* Declarations of device I/O functions */
#include <storage/mbr_gpt.h>
#include <gfx_utils.h>
#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) */
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 */
stat = disk_initialize(fs->pdrv); /* Initialize the physical drive */
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");
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) {
EFSPRINTF("NOFAT");
return FR_NO_FILESYSTEM; /* No FAT volume is found */
@ -6169,7 +6185,9 @@ FRESULT f_mkfs (
#endif
/* Create FAT VBR */
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] */
buf[BPB_SecPerClus] = (BYTE)pau; /* Cluster size [sector] */
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 */
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] */
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_RootClus32, 2); /* Root directory cluster # (2) */
st_word(buf + BPB_FSInfo32, 1); /* Offset of FSINFO sector (VBR + 1) */
st_word(buf + BPB_BkBootSec32, 6); /* Offset of backup VBR (VBR + 6) */
buf[BS_DrvNum32] = 0x80; /* Drive number (for int13) */
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 {
st_dword(buf + BS_VolID, GET_FATTIME()); /* VSN */
st_word(buf + BPB_FATSz16, (WORD)sz_fat); /* FAT size [sector] */
buf[BS_DrvNum] = 0x80; /* Drive number (for int13) */
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) */
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) */
}
/* 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 */
mem_set(buf, 0, (UINT)szb_buf);
sect = b_fat; /* FAT start sector */

View file

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

View file

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

View file

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

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer
* Copyright (c) 2018-2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -20,6 +20,8 @@
#include <soc/clock.h>
#include <utils/util.h>
#define CONFIG_ENABLE_AHB_REDIRECT
void mc_config_tsec_carveout(u32 bom, u32 size1mb, bool lock)
{
MC(MC_SEC_CARVEOUT_BOM) = bom;
@ -143,17 +145,19 @@ void mc_disable_ahb_redirect()
void mc_enable()
{
// Reset EMC source to PLLP.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) & 0x1FFFFFFF) | 0x40000000;
// Enable memory clocks.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & ~BIT(CLK_H_EMC)) | BIT(CLK_H_EMC);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & ~BIT(CLK_H_MEM)) | BIT(CLK_H_MEM);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) & ~BIT(CLK_X_EMC_DLL)) | BIT(CLK_X_EMC_DLL);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_EMC);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_MEM);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = BIT(CLK_X_EMC_DLL);
// Clear clock resets for memory.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_EMC) | BIT(CLK_H_MEM);
usleep(5);
//#ifdef CONFIG_ENABLE_AHB_REDIRECT
#ifdef CONFIG_ENABLE_AHB_REDIRECT
mc_enable_ahb_redirect();
#else
mc_disable_ahb_redirect();
//mc_enable_ahb_redirect();
//#endif
#endif
}

View file

@ -60,7 +60,7 @@ u32 minerva_init()
mtc_config_t mtc_tmp;
mtc_tmp.mtc_table = mtc_cfg->mtc_table;
mtc_tmp.sdram_id = (fuse_read_odm(4) >> 3) & 0x1F;
mtc_tmp.sdram_id = fuse_read_dramid(false);
mtc_tmp.init_done = MTC_NEW_MAGIC;
u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)&mtc_tmp);
@ -81,7 +81,7 @@ u32 minerva_init()
// Set table to nyx storage.
mtc_cfg->mtc_table = (emc_table_t *)nyx_str->mtc_table;
mtc_cfg->sdram_id = (fuse_read_odm(4) >> 3) & 0x1F;
mtc_cfg->sdram_id = fuse_read_dramid(false);
mtc_cfg->init_done = MTC_NEW_MAGIC; // Initialize mtc table.
u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)mtc_cfg);
@ -104,21 +104,21 @@ u32 minerva_init()
}
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;
minerva_cfg(mtc_cfg, NULL);
mtc_cfg->rate_to = 800000;
mtc_cfg->rate_to = FREQ_800;
minerva_cfg(mtc_cfg, NULL);
mtc_cfg->rate_to = 1600000;
mtc_cfg->rate_to = FREQ_1600;
minerva_cfg(mtc_cfg, NULL);
// FSP WAR.
mtc_cfg->train_mode = OP_SWITCH;
mtc_cfg->rate_to = 800000;
mtc_cfg->rate_to = FREQ_800;
minerva_cfg(mtc_cfg, NULL);
// Switch to max.
mtc_cfg->rate_to = 1600000;
mtc_cfg->rate_to = FREQ_1600;
minerva_cfg(mtc_cfg, NULL);
return 0;
@ -129,6 +129,7 @@ void minerva_change_freq(minerva_freq_t freq)
if (!minerva_cfg)
return;
// Check if requested frequency is different. Do not allow otherwise because it will hang.
mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
if (mtc_cfg->rate_from != freq)
{
@ -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()
{
if (!minerva_cfg)

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,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
* under the terms and conditions of the GNU General Public License,
@ -49,8 +49,14 @@
// Virtual disk / Chainloader buffers.
#define RAM_DISK_ADDR 0xA4000000
#define NX_BIS_CACHE_ADDR RAM_DISK_ADDR
#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).
#define PSTORE_ADDR 0xB0000000
@ -91,15 +97,10 @@
#define NYX_FB_SZ 0x384000 // 1280 x 720 x 4.
#define DRAM_MEM_HOLE_ADR 0xF6A00000
#define NX_BIS_LOOKUP_ADR DRAM_MEM_HOLE_ADR
#define DRAM_MEM_HOLE_SZ 0x8140000
/* --- Hole: 129MB 0xF6A00000 - 0xFEB3FFFF --- */
#define DRAM_START2 0xFEB40000
// NX BIS driver sector cache.
// #define NX_BIS_CACHE_ADDR 0xFEE00000
// #define NX_BIS_CACHE_SZ 0x100000
// USB buffers.
#define USBD_ADDR 0xFEF00000
#define USB_DESCRIPTOR_ADDR 0xFEF40000

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -21,8 +21,9 @@
#include <utils/types.h>
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.
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_output_enable(GPIO_PORT_A, GPIO_PIN_5, GPIO_OUTPUT_ENABLE);
gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_HIGH);
batt_src = true;
// Fan and Rail power from USB 5V VDD.
PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN0) = PINMUX_LPDR | 1;
@ -47,7 +49,7 @@ void regulator_enable_5v(u8 dev)
reg_5v_dev |= dev;
}
void regulator_disable_5v(u8 dev)
void regulator_5v_disable(u8 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_config(GPIO_PORT_A, GPIO_PIN_5, GPIO_MODE_SPIO);
PINMUX_AUX(PINMUX_AUX_SATA_LED_ACTIVE) = PINMUX_PARKED | PINMUX_INPUT_ENABLE;
batt_src = false;
// Rail power from USB 5V VDD.
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);
}
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
};
void regulator_enable_5v(u8 dev);
void regulator_disable_5v(u8 dev);
bool regulator_get_5v_dev_enabled(u8 dev);
void regulator_5v_enable(u8 dev);
void regulator_5v_disable(u8 dev);
bool regulator_5v_get_dev_enabled(u8 dev);
void regulator_5v_batt_src_enable(bool enable);
#endif

View file

@ -1,8 +1,8 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer
* Copyright (c) 2018-2021 CTCaer
* 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
* under the terms and conditions of the GNU General Public License,
@ -35,8 +35,8 @@ typedef struct _se_ll_t
vu32 size;
} se_ll_t;
static u32 _se_rsa_mod_sizes[TEGRA_SE_RSA_KEYSLOT_COUNT];
static u32 _se_rsa_exp_sizes[TEGRA_SE_RSA_KEYSLOT_COUNT];
static u32 _se_rsa_mod_sizes[SE_RSA_KEYSLOT_COUNT];
static u32 _se_rsa_exp_sizes[SE_RSA_KEYSLOT_COUNT];
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)
{
SE(SE_IN_LL_ADDR_REG_OFFSET) = (u32)src;
SE(SE_OUT_LL_ADDR_REG_OFFSET) = (u32)dst;
SE(SE_IN_LL_ADDR_REG) = (u32)src;
SE(SE_OUT_LL_ADDR_REG) = (u32)dst;
}
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) ||
SE(SE_STATUS_0) & SE_STATUS_0_STATE_WAIT_IN ||
SE(SE_ERR_STATUS_0) != SE_ERR_STATUS_0_SE_NS_ACCESS_CLEAR)
if (SE(SE_INT_STATUS_REG) & SE_INT_ERR_STAT ||
(SE(SE_STATUS_REG) & SE_STATUS_STATE_MASK) != SE_STATUS_STATE_IDLE ||
SE(SE_ERR_STATUS_REG) != 0)
return 0;
return 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(SE_ERR_STATUS_0) = SE(SE_ERR_STATUS_0);
SE(SE_INT_STATUS_REG_OFFSET) = SE(SE_INT_STATUS_REG_OFFSET);
SE(SE_ERR_STATUS_REG) = SE(SE_ERR_STATUS_REG);
SE(SE_INT_STATUS_REG) = SE(SE_INT_STATUS_REG);
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)
{
@ -168,13 +168,13 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr
if (!src || !dst)
return 0;
u8 *block = (u8 *)malloc(0x10);
memset(block, 0, 0x10);
u8 *block = (u8 *)malloc(SE_AES_BLOCK_SIZE);
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);
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);
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)
{
u32 data[TEGRA_SE_AES_BLOCK_SIZE / 4];
memcpy(data, ctr, TEGRA_SE_AES_BLOCK_SIZE);
u32 data[SE_AES_IV_SIZE / 4];
memcpy(data, ctr, SE_AES_IV_SIZE);
for (u32 i = 0; i < (TEGRA_SE_AES_BLOCK_SIZE / 4); i++)
SE(SE_CRYPTO_CTR_REG_OFFSET + (4 * i)) = data[i];
for (u32 i = 0; i < SE_CRYPTO_LINEAR_CTR_REG_COUNT; i++)
SE(SE_CRYPTO_LINEAR_CTR_REG + (4 * i)) = data[i];
}
void se_rsa_acc_ctrl(u32 rs, u32 flags)
{
if (flags & SE_RSA_KEY_TBL_DIS_KEY_ALL_FLAG)
SE(SE_RSA_KEYTABLE_ACCESS_REG_OFFSET + 4 * rs) =
((flags >> SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG_SHIFT) & SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG) |
((flags & SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG) ^ SE_RSA_KEY_TBL_DIS_KEY_ALL_COMMON_FLAG);
if (flags & SE_RSA_KEY_TBL_DIS_KEY_LOCK_FLAG)
SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) &= ~BIT(rs);
if (flags & SE_RSA_KEY_TBL_DIS_KEY_ACCESS_FLAG)
SE(SE_RSA_KEYTABLE_ACCESS_REG + 4 * rs) =
(((flags >> 4) & SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG) |(flags & SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG)) ^
SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_USE_FLAG;
if (flags & SE_RSA_KEY_LOCK_FLAG)
SE(SE_RSA_SECURITY_PERKEY_REG) &= ~BIT(rs);
}
// 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;
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_DATA) = byte_swap_32(data[mod_size / 4 - i - 1]);
SE(SE_RSA_KEYTABLE_ADDR_REG) = RSA_KEY_NUM(ks) | SE_RSA_KEYTABLE_TYPE(RSA_KEY_TYPE_MOD) | i;
SE(SE_RSA_KEYTABLE_DATA_REG) = byte_swap_32(data[mod_size / 4 - i - 1]);
}
data = (u32 *)exp;
for (u32 i = 0; i < exp_size / 4; i++)
{
SE(SE_RSA_KEYTABLE_ADDR) = RSA_KEY_NUM(ks) | RSA_KEY_TYPE(RSA_KEY_TYPE_EXP) | i;
SE(SE_RSA_KEYTABLE_DATA) = byte_swap_32(data[exp_size / 4 - i - 1]);
SE(SE_RSA_KEYTABLE_ADDR_REG) = RSA_KEY_NUM(ks) | SE_RSA_KEYTABLE_TYPE(RSA_KEY_TYPE_EXP) | i;
SE(SE_RSA_KEYTABLE_DATA_REG) = byte_swap_32(data[exp_size / 4 - i - 1]);
}
_se_rsa_mod_sizes[ks] = mod_size;
@ -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
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_DATA) = 0;
SE(SE_RSA_KEYTABLE_ADDR_REG) = RSA_KEY_NUM(ks) | SE_RSA_KEYTABLE_TYPE(RSA_KEY_TYPE_MOD) | i;
SE(SE_RSA_KEYTABLE_DATA_REG) = 0;
}
for (u32 i = 0; i < 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_DATA) = 0;
SE(SE_RSA_KEYTABLE_ADDR_REG) = RSA_KEY_NUM(ks) | SE_RSA_KEYTABLE_TYPE(RSA_KEY_TYPE_EXP) | i;
SE(SE_RSA_KEYTABLE_DATA_REG) = 0;
}
}
@ -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 res;
u8 stack_buf[TEGRA_SE_RSA2048_DIGEST_SIZE];
u8 stack_buf[SE_RSA2048_DIGEST_SIZE];
for (u32 i = 0; i < src_size; i++)
stack_buf[i] = *((u8 *)src + src_size - i - 1);
SE(SE_CONFIG_REG_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_KEY_SIZE_REG_OFFSET) = (_se_rsa_mod_sizes[ks] >> 6) - 1;
SE(SE_RSA_EXP_SIZE_REG_OFFSET) = _se_rsa_exp_sizes[ks] >> 2;
SE(SE_RSA_KEY_SIZE_REG) = (_se_rsa_mod_sizes[ks] >> 6) - 1;
SE(SE_RSA_EXP_SIZE_REG) = _se_rsa_exp_sizes[ks] >> 2;
res = _se_execute_oneshot(OP_START, NULL, 0, stack_buf, src_size);
res = _se_execute_oneshot(SE_OP_START, NULL, 0, stack_buf, src_size);
// Copy output hash.
u32 *dst32 = (u32 *)dst;
for (u32 i = 0; i < dst_size / 4; i++)
dst32[dst_size / 4 - i - 1] = byte_swap_32(SE(SE_RSA_OUTPUT + (i << 2)));
dst32[dst_size / 4 - i - 1] = byte_swap_32(SE(SE_RSA_OUTPUT_REG + (i << 2)));
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)
{
if (flags & SE_KEY_TBL_DIS_KEY_ACCESS_FLAG)
SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 4 * ks) = ~flags;
if (flags & SE_KEY_TBL_DIS_KEY_LOCK_FLAG)
SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) &= ~BIT(ks);
SE(SE_CRYPTO_KEYTABLE_ACCESS_REG + 4 * ks) = ~flags;
if (flags & SE_KEY_LOCK_FLAG)
SE(SE_CRYPTO_SECURITY_PERKEY_REG) &= ~BIT(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)
{
u32 data[TEGRA_SE_AES_MAX_KEY_SIZE / 4];
u32 data[SE_AES_MAX_KEY_SIZE / 4];
memcpy(data, key, size);
for (u32 i = 0; i < (size / 4); i++)
{
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i;
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data[i];
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_PKT(i); // QUAD is automatically set by PKT.
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = data[i];
}
}
void se_aes_key_partial_set(u32 ks, u32 index, u32 data)
{
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | index;
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data;
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | index;
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = data;
}
void se_aes_iv_set(u32 ks, const void *iv)
{
u32 data[TEGRA_SE_AES_BLOCK_SIZE / 4];
memcpy(data, iv, TEGRA_SE_AES_BLOCK_SIZE);
u32 data[SE_AES_IV_SIZE / 4];
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_KEYTABLE_DATA0_REG_OFFSET) = data[i];
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(ORIGINAL_IV) | SE_KEYTABLE_PKT(i);
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = data[i];
}
}
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++)
{
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i;
data[i] = SE(SE_KEYTABLE_DATA0_REG_OFFSET);
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_PKT(i); // QUAD is automatically set by PKT.
data[i] = SE(SE_CRYPTO_KEYTABLE_DATA_REG);
}
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)
{
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_KEYTABLE_DATA0_REG_OFFSET) = 0;
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_PKT(i); // QUAD is automatically set by PKT.
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = 0;
}
}
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_KEYTABLE_DATA0_REG_OFFSET) = 0;
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(ORIGINAL_IV) | SE_KEYTABLE_PKT(i);
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = 0;
}
}
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_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0;
SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst);
SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_KEYTABLE);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
SE(SE_CRYPTO_KEYTABLE_DST_REG) = SE_KEYTABLE_DST_KEY_INDEX(ks_dst) | SE_KEYTABLE_DST_WORD_QUAD(KEYS_0_3);
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)
{
if (enc)
{
SE(SE_CONFIG_REG_OFFSET) = 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_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT);
}
else
{
SE(SE_CONFIG_REG_OFFSET) = 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_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
}
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1;
return _se_execute_oneshot(OP_START, dst, dst_size, src, src_size);
SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1;
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)
{
if (enc)
{
SE(SE_CONFIG_REG_OFFSET) = 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_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) |
SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_XOR_POS(XOR_TOP);
}
else
{
SE(SE_CONFIG_REG_OFFSET) = 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_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVMEM) |
SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM);
}
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1;
return _se_execute_oneshot(OP_START, dst, dst_size, src, src_size);
SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1;
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)
{
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)
{
SE(SE_SPARE_0_REG_OFFSET) = 1;
SE(SE_CONFIG_REG_OFFSET) = 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_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_LNR_CTR) | SE_CRYPTO_CTR_VAL(1);
SE(SE_SPARE_REG) = SE_ECO(SE_ERRATA_FIX_ENABLE);
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) |
SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_LNR_CTR) | SE_CRYPTO_CTR_CNTN(1);
_se_aes_ctr_set(ctr);
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)
{
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1;
if (!_se_execute_oneshot(OP_START, dst, dst_size, src, src_size_aligned))
SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1;
if (!_se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size_aligned))
return 0;
}
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),
src + src_size_aligned, src_size_delta);
@ -419,15 +419,15 @@ int se_initialize_rng()
u8 *output_buf = (u8 *)malloc(0x10);
SE(SE_CONFIG_REG_OFFSET) = 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_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_MODE(RNG_MODE_FORCE_INSTANTION) | SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY);
SE(SE_RNG_RESEED_INTERVAL_REG_OFFSET) = 70001;
SE(SE_RNG_SRC_CONFIG_REG_OFFSET) = SE_RNG_SRC_CONFIG_ENT_SRC(RNG_SRC_RO_ENT_ENABLE) |
SE_RNG_SRC_CONFIG_ENT_SRC_LOCK(RNG_SRC_RO_ENT_LOCK_ENABLE);
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0;
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_MODE(MODE_FORCE_INSTANTION) | SE_RNG_CONFIG_SRC(SRC_ENTROPY);
SE(SE_RNG_RESEED_INTERVAL_REG) = 70001;
SE(SE_RNG_SRC_CONFIG_REG) = SE_RNG_SRC_CONFIG_ENTR_SRC(RO_ENTR_ENABLE) |
SE_RNG_SRC_CONFIG_ENTR_SRC_LOCK(RO_ENTR_LOCK_ENABLE);
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 0;
int res =_se_execute_oneshot(OP_START, output_buf, 0x10, NULL, 0);
int res =_se_execute_oneshot(SE_OP_START, output_buf, 0x10, NULL, 0);
free(output_buf);
if (res)
@ -437,35 +437,35 @@ int se_initialize_rng()
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_CRYPTO_REG_OFFSET) = 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_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_MODE(MODE_NORMAL) | SE_RNG_CONFIG_SRC(SRC_ENTROPY);
u32 num_blocks = size >> 4;
u32 aligned_size = num_blocks << 4;
if (num_blocks)
{
SE(SE_BLOCK_COUNT_REG_OFFSET) = num_blocks - 1;
if (!_se_execute_oneshot(OP_START, dst, aligned_size, NULL, 0))
SE(SE_CRYPTO_BLOCK_COUNT_REG) = num_blocks - 1;
if (!_se_execute_oneshot(SE_OP_START, dst, aligned_size, NULL, 0))
return 0;
}
if (size > aligned_size)
return _se_execute_one_block(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;
}
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_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) |
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) |
SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG_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);
if (!_se_execute_oneshot(OP_START, NULL, 0, NULL, 0))
SE(SE_CRYPTO_KEYTABLE_DST_REG) = SE_KEYTABLE_DST_KEY_INDEX(ks_dst);
if (!_se_execute_oneshot(SE_OP_START, NULL, 0, NULL, 0))
return 0;
SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst) | 1;
if (!_se_execute_oneshot(OP_START, NULL, 0, NULL, 0))
SE(SE_CRYPTO_KEYTABLE_DST_REG) = SE_KEYTABLE_DST_KEY_INDEX(ks_dst) | 1;
if (!_se_execute_oneshot(SE_OP_START, NULL, 0, NULL, 0))
return 0;
return 1;
@ -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)
_gf256_mul_x(key);
SE(SE_CONFIG_REG_OFFSET) = 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_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_HASHREG);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_INPUT_SEL(INPUT_MEMORY) |
SE_CRYPTO_XOR_POS(XOR_TOP) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) | SE_CRYPTO_HASH(HASH_ENABLE) |
SE_CRYPTO_CORE_SEL(CORE_ENCRYPT);
se_aes_iv_clear(ks);
@ -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;
if (num_blocks > 1)
{
SE(SE_BLOCK_COUNT_REG_OFFSET) = num_blocks - 2;
if (!_se_execute_oneshot(OP_START, NULL, 0, src, src_size))
SE(SE_CRYPTO_BLOCK_COUNT_REG) = num_blocks - 2;
if (!_se_execute_oneshot(SE_OP_START, NULL, 0, src, src_size))
goto out;
SE(SE_CRYPTO_REG_OFFSET) |= SE_CRYPTO_IV_SEL(IV_UPDATED);
SE(SE_CRYPTO_CONFIG_REG) |= SE_CRYPTO_IV_SEL(IV_UPDATED);
}
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++)
last_block[i] ^= key[i];
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0;
res = _se_execute_oneshot(OP_START, NULL, 0, last_block, 0x10);
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 0;
res = _se_execute_oneshot(SE_OP_START, NULL, 0, last_block, 0x10);
u32 *dst32 = (u32 *)dst;
for (u32 i = 0; i < (dst_size >> 2); i++)
dst32[i] = SE(SE_HASH_RESULT_REG_OFFSET + (i << 2));
dst32[i] = SE(SE_HASH_RESULT_REG + (i << 2));
out:;
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 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.
if (src_size > 0xFFFFFF || !hash) // Max 16MB - 1 chunks and aligned x4 hash buffer.
return 0;
// 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_SHA_CONFIG_REG_OFFSET) = sha_cfg;
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0;
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) = sha_cfg;
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
// Set total size to current buffer size if empty.
if (!total_size)
total_size = src_size;
// 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_1_REG_OFFSET) = (u32)(total_size >> 29);
SE(SE_SHA_MSG_LENGTH_2_REG_OFFSET) = 0;
SE(SE_SHA_MSG_LENGTH_3_REG_OFFSET) = 0;
SE(SE_SHA_MSG_LENGTH_0_REG) = (u32)(total_size << 3);
SE(SE_SHA_MSG_LENGTH_1_REG) = (u32)(total_size >> 29);
SE(SE_SHA_MSG_LENGTH_2_REG) = 0;
SE(SE_SHA_MSG_LENGTH_3_REG) = 0;
// Set size left to hash.
SE(SE_SHA_MSG_LEFT_0_REG_OFFSET) = (u32)(total_size << 3);
SE(SE_SHA_MSG_LEFT_1_REG_OFFSET) = (u32)(total_size >> 29);
SE(SE_SHA_MSG_LEFT_2_REG_OFFSET) = 0;
SE(SE_SHA_MSG_LEFT_3_REG_OFFSET) = 0;
SE(SE_SHA_MSG_LEFT_0_REG) = (u32)(total_size << 3);
SE(SE_SHA_MSG_LEFT_1_REG) = (u32)(total_size >> 29);
SE(SE_SHA_MSG_LEFT_2_REG) = 0;
SE(SE_SHA_MSG_LEFT_3_REG) = 0;
// If we hash in chunks, copy over the intermediate.
if (sha_cfg == SHA_CONTINUE && msg_left)
{
// Restore message left to process.
SE(SE_SHA_MSG_LEFT_0_REG_OFFSET) = msg_left[0];
SE(SE_SHA_MSG_LEFT_1_REG_OFFSET) = msg_left[1];
SE(SE_SHA_MSG_LEFT_0_REG) = msg_left[0];
SE(SE_SHA_MSG_LEFT_1_REG) = msg_left[1];
// Restore hash reg.
memcpy(hash32, hash, TEGRA_SE_SHA_256_SIZE);
for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++)
SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)) = byte_swap_32(hash32[i]);
memcpy(hash32, hash, SE_SHA_256_SIZE);
for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++)
SE(SE_HASH_RESULT_REG + (i * 4)) = byte_swap_32(hash32[i]);
}
// 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)
{
// Backup message left.
if (msg_left)
{
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG_OFFSET);
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG_OFFSET);
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG);
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG);
}
// Copy output hash.
for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++)
hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)));
memcpy(hash, hash32, TEGRA_SE_SHA_256_SIZE);
for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++)
hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG + (i * 4)));
memcpy(hash, hash32, SE_SHA_256_SIZE);
}
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)
{
u32 hash32[TEGRA_SE_SHA_256_SIZE / 4];
u32 hash32[SE_SHA_256_SIZE / 4];
int res = _se_execute_finalize();
// Backup message left.
if (msg_left)
{
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG_OFFSET);
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG_OFFSET);
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG);
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG);
}
// Copy output hash.
for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++)
hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)));
memcpy(hash, hash32, TEGRA_SE_SHA_256_SIZE);
for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++)
hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG + (i << 2)));
memcpy(hash, hash32, SE_SHA_256_SIZE);
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);
// 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_CRYPTO_REG_OFFSET) = 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_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_SRK);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(0) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_SRC(SRC_ENTROPY) | SE_RNG_CONFIG_MODE(MODE_FORCE_RESEED);
SE(SE_CRYPTO_LAST_BLOCK) = 0;
_se_execute_oneshot(OP_START, NULL, 0, NULL, 0);
_se_execute_oneshot(SE_OP_START, NULL, 0, NULL, 0);
// 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) |
(i << SE_KEY_INDEX_SHIFT) | SE_CONTEXT_SAVE_WORD_QUAD(KEYS_0_3);
SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(AES_KEYTABLE) | SE_KEYTABLE_DST_KEY_INDEX(i) |
SE_CONTEXT_AES_KEY_INDEX(0) | SE_CONTEXT_AES_WORD_QUAD(KEYS_0_3);
SE(SE_CRYPTO_LAST_BLOCK) = 0;
_se_execute_oneshot(OP_CTX_SAVE, aligned_buf, 0x10, NULL, 0);
memcpy(keys + i * keysize, aligned_buf, 0x10);
_se_execute_oneshot(SE_OP_CTX_SAVE, aligned_buf, SE_AES_BLOCK_SIZE, NULL, 0);
memcpy(keys + i * keysize, aligned_buf, SE_AES_BLOCK_SIZE);
if (keysize > 0x10)
if (keysize > SE_KEY_128_SIZE)
{
SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(AES_KEYTABLE) |
(i << SE_KEY_INDEX_SHIFT) | SE_CONTEXT_SAVE_WORD_QUAD(KEYS_4_7);
SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(AES_KEYTABLE) | SE_KEYTABLE_DST_KEY_INDEX(i) |
SE_CONTEXT_AES_KEY_INDEX(0) | SE_CONTEXT_AES_WORD_QUAD(KEYS_4_7);
SE(SE_CRYPTO_LAST_BLOCK) = 0;
_se_execute_oneshot(OP_CTX_SAVE, aligned_buf, 0x10, NULL, 0);
memcpy(keys + i * keysize + 0x10, aligned_buf, 0x10);
_se_execute_oneshot(SE_OP_CTX_SAVE, aligned_buf, SE_AES_BLOCK_SIZE, NULL, 0);
memcpy(keys + i * keysize + SE_AES_BLOCK_SIZE, aligned_buf, SE_AES_BLOCK_SIZE);
}
}
// Save SRK to PMC secure scratches.
SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(SRK);
SE(SE_CRYPTO_LAST_BLOCK) = 0;
_se_execute_oneshot(OP_CTX_SAVE, NULL, 0, NULL, 0);
SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(SRK);
SE(SE_CRYPTO_LAST_BLOCK) = 0;
_se_execute_oneshot(SE_OP_CTX_SAVE, NULL, 0, NULL, 0);
// End context save.
SE(SE_CONFIG_REG_OFFSET) = 0;
_se_execute_oneshot(OP_CTX_SAVE, NULL, 0, NULL, 0);
SE(SE_CONFIG_REG) = 0;
_se_execute_oneshot(SE_OP_CTX_SAVE, NULL, 0, NULL, 0);
// Get SRK.
u32 srk[4];
@ -840,7 +840,7 @@ void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize)
// Decrypt context.
se_aes_key_clear(3);
se_aes_key_set(3, srk, 0x10);
se_aes_crypt_cbc(3, 0, keys, TEGRA_SE_KEYSLOT_COUNT * keysize, keys, TEGRA_SE_KEYSLOT_COUNT * keysize);
se_aes_key_set(3, srk, SE_KEY_128_SIZE);
se_aes_crypt_cbc(3, 0, keys, SE_AES_KEYSLOT_COUNT * keysize, keys, SE_AES_KEYSLOT_COUNT * keysize);
se_aes_key_clear(3);
}

View file

@ -1,5 +1,7 @@
/*
* 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
* 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);
void se_key_acc_ctrl(u32 ks, u32 flags);
u32 se_key_acc_ctrl_get(u32 ks);
void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize);
void se_aes_key_set(u32 ks, const void *key, u32 size);
void se_aes_iv_set(u32 ks, const void *iv);
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_key(u32 ks_dst, u32 ks_src);
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_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_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(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);
@ -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_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);
void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize);
#endif

View file

@ -1,400 +1,323 @@
/*
* Driver for Tegra Security Engine
*
* Copyright (c) 2011-2013, NVIDIA Corporation. All Rights Reserved.
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _CRYPTO_TEGRA_SE_H
#define _CRYPTO_TEGRA_SE_H
#ifndef _SE_T210_H
#define _SE_T210_H
#include <utils/types.h>
#define TEGRA_SE_CRA_PRIORITY 300
#define TEGRA_SE_COMPOSITE_PRIORITY 400
#define TEGRA_SE_CRYPTO_QUEUE_LENGTH 50
#define SE_MAX_SRC_SG_COUNT 50
#define SE_MAX_DST_SG_COUNT 50
#define SE_CRYPTO_QUEUE_LENGTH 50
#define SE_MAX_SRC_SG_COUNT 50
#define SE_MAX_DST_SG_COUNT 50
#define TEGRA_SE_KEYSLOT_COUNT 16
#define SE_MAX_LAST_BLOCK_SIZE 0xFFFFF
#define SE_AES_KEYSLOT_COUNT 16
#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 */
#define SE_SECURITY_0 0x000
#define SE_KEY_SCHED_READ_SHIFT 3
#define SE_SE_SECURITY_REG 0x000
#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_CONFIG_ENC_ALG_SHIFT 12
#define SE_CONFIG_DEC_ALG_SHIFT 8
#define ALG_AES_ENC 1
#define ALG_RNG 2
#define ALG_SHA 3
#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_OPERATION_REG 0x008
#define SE_OP_ABORT 0
#define SE_OP_START 1
#define SE_OP_RESTART_OUT 2
#define SE_OP_CTX_SAVE 3
#define SE_OP_RESTART_IN 4
#define SE_RNG_CONFIG_REG_OFFSET 0x340
#define RNG_MODE_SHIFT 0
#define RNG_MODE_NORMAL 0
#define RNG_MODE_FORCE_INSTANTION 1
#define RNG_MODE_FORCE_RESEED 2
#define SE_RNG_CONFIG_MODE(x) ((x) << RNG_MODE_SHIFT)
#define RNG_SRC_SHIFT 2
#define RNG_SRC_NONE 0
#define RNG_SRC_ENTROPY 1
#define RNG_SRC_LFSR 2
#define SE_RNG_CONFIG_SRC(x) ((x) << RNG_SRC_SHIFT)
#define SE_INT_ENABLE_REG 0x00C
#define SE_INT_STATUS_REG 0x010
#define SE_INT_IN_LL_BUF_RD BIT(0)
#define SE_INT_IN_DONE BIT(1)
#define SE_INT_OUT_LL_BUF_WR BIT(2)
#define SE_INT_OUT_DONE BIT(3)
#define SE_INT_OP_DONE BIT(4)
#define SE_INT_RESEED_NEEDED BIT(5)
#define SE_INT_ERR_STAT BIT(16)
#define SE_RNG_SRC_CONFIG_REG_OFFSET 0x344
#define RNG_SRC_RO_ENT_SHIFT 1
#define RNG_SRC_RO_ENT_ENABLE 1
#define RNG_SRC_RO_ENT_DISABLE 0
#define SE_RNG_SRC_CONFIG_ENT_SRC(x) ((x) << RNG_SRC_RO_ENT_SHIFT)
#define RNG_SRC_RO_ENT_LOCK_SHIFT 0
#define RNG_SRC_RO_ENT_LOCK_ENABLE 1
#define RNG_SRC_RO_ENT_LOCK_DISABLE 0
#define SE_RNG_SRC_CONFIG_ENT_SRC_LOCK(x) ((x) << RNG_SRC_RO_ENT_LOCK_SHIFT)
#define SE_CONFIG_REG 0x014
#define DST_MEMORY 0
#define DST_HASHREG 1
#define DST_KEYTABLE 2
#define DST_SRK 3
#define DST_RSAREG 4
#define SE_CONFIG_DST(x) ((x) << 2)
#define ALG_NOP 0
#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_KEYTABLE_SLOT_SHIFT 4
#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_HASH_RESULT_REG 0x030
#define SE_HASH_RESULT_REG_COUNT 16
#define SE_OP_DONE_SHIFT 4
#define OP_DONE 1
#define SE_OP_DONE(x, y) ((x) && ((y) << SE_OP_DONE_SHIFT))
#define SE_CONTEXT_SAVE_CONFIG_REG 0x070
#define KEYS_0_3 0
#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_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_LAST_BLOCK 0x080
#define SE_CRYPTO_CTR_REG_COUNT 4
#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 SE_SHA_CONFIG_REG 0x200
#define SHA_CONTINUE 0
#define SHA_INIT_HASH 1
#define SE_SHA_MSG_LENGTH_0_REG_OFFSET 0x204
#define SE_SHA_MSG_LENGTH_1_REG_OFFSET 0x208
#define SE_SHA_MSG_LENGTH_2_REG_OFFSET 0x20C
#define SE_SHA_MSG_LENGTH_3_REG_OFFSET 0x210
#define SE_SHA_MSG_LEFT_0_REG_OFFSET 0x214
#define SE_SHA_MSG_LEFT_1_REG_OFFSET 0x218
#define SE_SHA_MSG_LEFT_2_REG_OFFSET 0x21C
#define SE_SHA_MSG_LEFT_3_REG_OFFSET 0x220
#define SE_SHA_MSG_LENGTH_0_REG 0x204
#define SE_SHA_MSG_LENGTH_1_REG 0x208
#define SE_SHA_MSG_LENGTH_2_REG 0x20C
#define SE_SHA_MSG_LENGTH_3_REG 0x210
#define SE_SHA_MSG_LEFT_0_REG 0x214
#define SE_SHA_MSG_LEFT_1_REG 0x218
#define SE_SHA_MSG_LEFT_2_REG 0x21C
#define SE_SHA_MSG_LEFT_3_REG 0x220
#define SE_HASH_RESULT_REG_COUNT 16
#define SE_HASH_RESULT_REG_OFFSET 0x030
#define TEGRA_SE_KEY_256_SIZE 32
#define TEGRA_SE_KEY_192_SIZE 24
#define TEGRA_SE_KEY_128_SIZE 16
#define TEGRA_SE_AES_BLOCK_SIZE 16
#define TEGRA_SE_AES_MIN_KEY_SIZE 16
#define TEGRA_SE_AES_MAX_KEY_SIZE 32
#define TEGRA_SE_AES_IV_SIZE 16
#define TEGRA_SE_SHA_512_SIZE 64
#define TEGRA_SE_SHA_384_SIZE 48
#define TEGRA_SE_SHA_256_SIZE 32
#define TEGRA_SE_SHA_192_SIZE 24
#define TEGRA_SE_RNG_IV_SIZE 16
#define TEGRA_SE_RNG_DT_SIZE 16
#define TEGRA_SE_RNG_KEY_SIZE 16
#define TEGRA_SE_RNG_SEED_SIZE (TEGRA_SE_RNG_IV_SIZE + \
TEGRA_SE_RNG_KEY_SIZE + \
TEGRA_SE_RNG_DT_SIZE)
#define SE_CRYPTO_SECURITY_PERKEY_REG 0x280
#define SE_KEY_LOCK_FLAG 0x80
#define SE_CRYPTO_KEYTABLE_ACCESS_REG 0x284
#define SE_CRYPTO_KEYTABLE_ACCESS_REG_COUNT 16
#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 TEGRA_SE_AES_CMAC_DIGEST_SIZE 16
#define TEGRA_SE_RSA512_DIGEST_SIZE 64
#define TEGRA_SE_RSA1024_DIGEST_SIZE 128
#define TEGRA_SE_RSA1536_DIGEST_SIZE 192
#define TEGRA_SE_RSA2048_DIGEST_SIZE 256
#define SE_CRYPTO_CONFIG_REG 0x304
#define HASH_DISABLE 0
#define HASH_ENABLE 1
#define SE_CRYPTO_HASH(x) ((x) << 0)
#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_KEY_TBL_DIS_KEY_LOCK_FLAG 0x80
#define SE_CRYPTO_LINEAR_CTR_REG 0x308
#define SE_CRYPTO_LINEAR_CTR_REG_COUNT 4
#define SE_KEY_TABLE_ACCESS_REG_OFFSET 0x284
#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_CRYPTO_BLOCK_COUNT_REG 0x318
#define SE_KEY_READ_DISABLE_SHIFT 0
#define SE_KEY_UPDATE_DISABLE_SHIFT 1
#define SE_CRYPTO_KEYTABLE_ADDR_REG 0x31C
#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_CONTEXT_DRBG_BUFER_SIZE 2112
#define SE_CRYPTO_KEYTABLE_DATA_REG 0x320
#define SE_CONTEXT_SAVE_RANDOM_DATA_OFFSET 0
#define SE_CONTEXT_SAVE_RANDOM_DATA_SIZE 16
#define SE_CONTEXT_SAVE_STICKY_BITS_OFFSET \
(SE_CONTEXT_SAVE_RANDOM_DATA_OFFSET + SE_CONTEXT_SAVE_RANDOM_DATA_SIZE)
#define SE_CONTEXT_SAVE_STICKY_BITS_SIZE 16
#define SE_CRYPTO_KEYTABLE_DST_REG 0x330
#define KEYS_0_3 0
#define KEYS_4_7 1
#define ORIGINAL_IV 2
#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 + \
SE_CONTEXT_SAVE_STICKY_BITS_SIZE)
#define SE11_CONTEXT_SAVE_KEYS_OFFSET (SE_CONTEXT_SAVE_STICKY_BITS_OFFSET + \
SE_CONTEXT_SAVE_STICKY_BITS_SIZE + \
SE_CONTEXT_SAVE_STICKY_BITS_SIZE)
#define SE_RNG_CONFIG_REG 0x340
#define MODE_NORMAL 0
#define MODE_FORCE_INSTANTION 1
#define MODE_FORCE_RESEED 2
#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_CONTEXT_ORIGINAL_IV_OFFSET (SE_CONTEXT_SAVE_KEYS_OFFSET + \
SE_CONTEXT_SAVE_KEY_LENGTH)
#define SE11_CONTEXT_ORIGINAL_IV_OFFSET (SE11_CONTEXT_SAVE_KEYS_OFFSET + \
SE_CONTEXT_SAVE_KEY_LENGTH)
#define SE_RNG_SRC_CONFIG_REG 0x344
#define RO_ENTR_LOCK_DISABLE 0
#define RO_ENTR_LOCK_ENABLE 1
#define SE_RNG_SRC_CONFIG_ENTR_SRC_LOCK(x) ((x) << 0)
#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 + \
SE_CONTEXT_ORIGINAL_IV_LENGTH)
#define SE11_CONTEXT_UPDATED_IV_OFFSET (SE11_CONTEXT_ORIGINAL_IV_OFFSET + \
SE_CONTEXT_ORIGINAL_IV_LENGTH)
#define SE_RSA_CONFIG 0x400
#define RSA_KEY_SLOT_ONE 0
#define RSA_KEY_SLOT_TW0 1
#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 + \
SE_CONTEXT_UPDATED_IV_LENGTH)
#define SE11_CONTEXT_SAVE_KNOWN_PATTERN_OFFSET \
(SE11_CONTEXT_UPDATED_IV_OFFSET + \
SE_CONTEXT_UPDATED_IV_LENGTH)
#define SE_RSA_EXP_SIZE_REG 0x408
#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 \
(SE_CONTEXT_SAVE_RSA_KEYS_OFFSET + SE_CONTEXT_SAVE_RSA_KEY_LENGTH)
#define SE_RSA_KEYTABLE_DATA_REG 0x424
#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_RSA_KEY_TBL_DIS_KEY_LOCK_FLAG 0x80
#define SE_ERR_STATUS_REG 0x804
#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_RSA_KEY_TBL_DIS_KEYREAD_FLAG BIT(0)
#define SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG 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_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_MISC_REG 0x808
#define SE_ENTROPY_NEXT_192BIT BIT(0)
#define SE_ENTROPY_VN_BYPASS BIT(1)
#define SE_CLK_OVR_ON BIT(2)
#define SE_RSA_KEYTABLE_ADDR 0x420
#define SE_RSA_KEYTABLE_DATA 0x424
#define SE_RSA_OUTPUT 0x428
#define SE_SPARE_REG 0x80C
#define SE_ERRATA_FIX_DISABLE 0
#define SE_ERRATA_FIX_ENABLE 1
#define SE_ECO(x) ((x) << 0)
#define RSA_KEY_READ 0
#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 */
#endif

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2019 CTCaer
* Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2018 balika011
*
* 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;
bpmp_mmu_disable();
bpmp_clk_rate_set(BPMP_CLK_NORMAL);
bpmp_freq_t prev_fid = bpmp_clk_rate_set(BPMP_CLK_NORMAL);
// Enable clocks.
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)
{
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 kidx = 0;
@ -198,9 +198,9 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
{
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;
}
@ -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_LSB) = 0;
memcpy(tsec_keys, &buf, 0x10);
memcpy(tsec_keys, &buf, SE_KEY_128_SIZE);
}
out_free:;
@ -284,7 +284,7 @@ out:;
clock_disable_sor_safe();
clock_disable_tsec();
bpmp_mmu_enable();
bpmp_clk_rate_set(BPMP_CLK_DEFAULT_BOOST);
bpmp_clk_rate_set(prev_fid);
return res;
}

View file

@ -1,7 +1,7 @@
/*
* 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
* 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.
};
bpmp_freq_t bpmp_clock_set = BPMP_CLK_NORMAL;
bpmp_freq_t bpmp_fid_current = BPMP_CLK_NORMAL;
void bpmp_clk_rate_get()
{
bool clk_src_is_pllp = ((CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) >> 4) & 7) == 3;
if (clk_src_is_pllp)
bpmp_clock_set = BPMP_CLK_NORMAL;
bpmp_fid_current = BPMP_CLK_NORMAL;
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;
for (u32 i = 1; i < sizeof(pll_divn); i++)
{
if (pll_divn[i] == pll_divn_curr)
{
bpmp_clock_set = i;
bpmp_fid_current = i;
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))
fid = BPMP_CLK_MAX - 1;
if (bpmp_clock_set == fid)
return;
if (prev_fid == fid)
return prev_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.
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.
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.

View file

@ -1,7 +1,7 @@
/*
* 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
* under the terms and conditions of the GNU General Public License,
@ -53,6 +53,7 @@ typedef enum
BPMP_CLK_MAX
} bpmp_freq_t;
#define BPMP_CLK_LOWER_BOOST BPMP_CLK_SUPER_BOOST
#define BPMP_CLK_DEFAULT_BOOST BPMP_CLK_HYPER_BOOST
void bpmp_mmu_maintenance(u32 op, bool force);
@ -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_disable();
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_msleep(u32 ms);
void bpmp_halt();

View file

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

View file

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

View file

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

View file

@ -2,7 +2,7 @@
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 shuffle2
* Copyright (c) 2018 balika011
* Copyright (c) 2019 CTCaer
* Copyright (c) 2019-2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -76,6 +76,35 @@ u32 fuse_read_odm_keygen_rev()
return 0;
}
u32 fuse_read_dramid(bool raw_id)
{
u32 dramid = (fuse_read_odm(4) & 0xF8) >> 3;
if (raw_id)
return dramid;
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210)
{
if (dramid > 6)
dramid = 0;
}
else
{
if (dramid > 27)
dramid = 8;
}
return dramid;
}
u32 fuse_read_hw_state()
{
if ((fuse_read_odm(4) & 3) != 3)
return FUSE_NX_HW_STATE_PROD;
else
return FUSE_NX_HW_STATE_DEV;
}
u32 fuse_read_hw_type()
{
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01)
@ -118,6 +147,7 @@ u32 fuse_read(u32 addr)
FUSE(FUSE_ADDR) = addr;
FUSE(FUSE_CTRL) = (FUSE(FUSE_ADDR) & ~FUSE_CMD_MASK) | FUSE_READ;
fuse_wait_idle();
return FUSE(FUSE_RDATA);
}

View file

@ -2,6 +2,7 @@
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 shuffle2
* Copyright (c) 2018 balika011
* Copyright (c) 2019-2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -64,9 +65,10 @@
#define FUSE_OPT_X_COORDINATE 0x214
#define FUSE_OPT_Y_COORDINATE 0x218
#define FUSE_GPU_IDDQ_CALIB 0x228
#define FUSE_RESERVED_ODM28 0x240
#define FUSE_USB_CALIB_EXT 0x350
#define FUSE_RESERVED_ODM28_T210B01 0x240
/*! Fuse commands. */
#define FUSE_READ 0x1
#define FUSE_WRITE 0x2
@ -83,9 +85,17 @@ enum
FUSE_NX_HW_TYPE_HOAG
};
enum
{
FUSE_NX_HW_STATE_PROD,
FUSE_NX_HW_STATE_DEV
};
void fuse_disable_program();
u32 fuse_read_odm(u32 idx);
u32 fuse_read_odm_keygen_rev();
u32 fuse_read_dramid(bool raw_id);
u32 fuse_read_hw_state();
u32 fuse_read_hw_type();
u8 fuse_count_burnt(u32 val);
void fuse_wait_idle();

View file

@ -1,6 +1,6 @@
/*
* 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
* under the terms and conditions of the GNU General Public License,
@ -18,7 +18,7 @@
#include <string.h>
#include <soc/hw_init.h>
#include <gfx/di.h>
#include <display/di.h>
#include <input/joycon.h>
#include <input/touch.h>
#include <sec/se.h>
@ -42,6 +42,7 @@
#include <storage/nx_sd.h>
#include <storage/sdmmc.h>
#include <thermal/fan.h>
#include <thermal/tmp451.h>
#include <utils/util.h>
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.
}
// The uart is skipped for Copper, Hoag and Calcio. Used in Icosa, Iowa and Aula.
static void _config_gpios(bool nx_hoag)
{
// Clamp inputs when tristated.
@ -263,7 +265,7 @@ static void _config_se_brom()
FUSE(FUSE_PRIVATE_KEY3)
};
// 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.
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.
memset((void *)TZRAM_BASE, 0, 0x10000);
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
PMC(APBDEV_PMC_SCRATCH200) = 0x0;
@ -285,17 +287,21 @@ static void _config_se_brom()
static void _config_regulators(bool tegra_t210)
{
// Set RTC/AO domain to POR voltage.
if (tegra_t210)
max7762x_regulator_set_voltage(REGULATOR_LDO4, 1000000);
// Disable low battery shutdown monitor.
max77620_low_battery_monitor_config(false);
// Disable SDMMC1 IO power.
gpio_write(GPIO_PORT_E, GPIO_PIN_4, GPIO_LOW);
max77620_regulator_enable(REGULATOR_LDO2, 0);
max7762x_regulator_enable(REGULATOR_LDO2, false);
sd_power_cycle_time_start = get_tmr_ms();
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CNFGBBC, MAX77620_CNFGBBC_RESISTOR_1K);
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1,
BIT(6) | (3 << MAX77620_ONOFFCNFG1_MRT_SHIFT)); // PWR delay for forced shutdown off.
MAX77620_ONOFFCNFG1_RSVD | (3 << MAX77620_ONOFFCNFG1_MRT_SHIFT)); // PWR delay for forced shutdown off.
if (tegra_t210)
{
@ -313,28 +319,18 @@ static void _config_regulators(bool tegra_t210)
(4 << MAX77620_FPS_TIME_PERIOD_SHIFT) | (2 << MAX77620_FPS_PD_PERIOD_SHIFT)); // 3.x+
// Set vdd_core voltage to 1.125V.
max77620_regulator_set_voltage(REGULATOR_SD0, 1125000);
max7762x_regulator_set_voltage(REGULATOR_SD0, 1125000);
// Fix CPU/GPU after a L4T warmboot.
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO5, 2);
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO6, 2);
// Fix CPU/GPU after L4T warmboot.
max77620_config_gpio(5, MAX77620_GPIO_OUTPUT_DISABLE);
max77620_config_gpio(6, MAX77620_GPIO_OUTPUT_DISABLE);
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_REG, MAX77621_VOUT_0_95V); // Disable power.
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_DVS_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_1_09V); // Enable DVS power.
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL1_REG, MAX77621_RAMP_50mV_PER_US);
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL2_REG,
MAX77621_T_JUNCTION_120 | MAX77621_FT_ENABLE | MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS |
MAX77621_CKKADV_TRIP_150mV_PER_US | MAX77621_INDUCTOR_NOMINAL);
i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_VOUT_REG, MAX77621_VOUT_0_95V); // Disable power.
i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_VOUT_DVS_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_1_09V); // Enable DVS power.
i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_CONTROL1_REG, MAX77621_RAMP_50mV_PER_US);
i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_CONTROL2_REG,
MAX77621_T_JUNCTION_120 | MAX77621_FT_ENABLE | MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS |
MAX77621_CKKADV_TRIP_150mV_PER_US | MAX77621_INDUCTOR_NOMINAL);
// Set POR configuration.
max77621_config_default(REGULATOR_CPU0, MAX77621_CTRL_POR_CFG);
max77621_config_default(REGULATOR_GPU0, MAX77621_CTRL_POR_CFG);
}
else // Tegra X1+ set vdd_core voltage to 1.05V.
max77620_regulator_set_voltage(REGULATOR_SD0, 1050000);
max7762x_regulator_set_voltage(REGULATOR_SD0, 1050000);
}
void hw_init()
@ -373,7 +369,8 @@ void hw_init()
#ifdef DEBUG_UART_PORT
clock_enable_uart(DEBUG_UART_PORT);
uart_init(DEBUG_UART_PORT, 115200);
uart_init(DEBUG_UART_PORT, DEBUG_UART_BAUDRATE);
uart_invert(DEBUG_UART_PORT, DEBUG_UART_INVERT, UART_INVERT_TXD);
#endif
// Enable Dynamic Voltage and Frequency Scaling device clock.
@ -391,17 +388,20 @@ void hw_init()
//! TODO: Why? Device is NFC MCU on Lite.
if (nx_hoag)
max77620_regulator_set_volt_and_flags(REGULATOR_LDO8, 2800000, MAX77620_POWER_MODE_NORMAL);
{
max7762x_regulator_set_voltage(REGULATOR_LDO8, 2800000);
max7762x_regulator_enable(REGULATOR_LDO8, true);
}
// Initialize I2C1 for various power related devices.
i2c_init(I2C_1);
// Enable charger in case it's disabled.
bq24193_enable_charger();
// Initialize various regulators based on Erista/Mariko platform.
_config_regulators(tegra_t210);
// Enable charger in case it's disabled.
bq24193_enable_charger();
_config_pmc_scratch(); // Missing from 4.x+
// Set BPMP/SCLK to PLLP_OUT (408MHz).
@ -421,19 +421,18 @@ void hw_init()
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.
bpmp_clk_rate_set(BPMP_CLK_NORMAL);
#ifdef NYX
// Deinit touchscreen, 5V regulators and Joy-Con.
touch_power_off();
// Disable temperature sensor, touchscreen, 5V regulators and Joy-Con.
tmp451_end();
set_fan_duty(0);
touch_power_off();
jc_deinit();
regulator_disable_5v(REGULATOR_5V_ALL);
clock_disable_uart(UART_B);
clock_disable_uart(UART_C);
regulator_5v_disable(REGULATOR_5V_ALL);
#endif
// 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_Y) |= BIT(CLK_Y_APE);
if (extra_reconfig)
// Do coreboot mitigations.
if (coreboot)
{
msleep(10);
PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_SDMMC1_IO_EN;
clock_disable_cl_dvfs();
@ -457,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_E, GPIO_PIN_6, GPIO_MODE_SPIO);
gpio_config(GPIO_PORT_H, GPIO_PIN_6, GPIO_MODE_SPIO);
// Reinstate SD controller power.
PMC(APBDEV_PMC_NO_IOPOWER) &= ~(PMC_NO_IOPOWER_SDMMC1_IO_EN);
}
// Power off display.
display_end();
// Seamless display or display power off.
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.
if (magic == 0xBAADF00D)
if (bl_magic == BL_MAGIC_BROKEN_HWI)
{
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_USBD);
sdmmc_init(&sd_sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID, 0);

View file

@ -20,8 +20,11 @@
#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_reinit_workaround(bool extra_reconfig, u32 magic);
void hw_reinit_workaround(bool coreboot, u32 magic);
u32 hw_get_chip_id();
#endif

View file

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

View file

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

View file

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

View file

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

View file

@ -122,7 +122,12 @@ u32 uart_get_IIR(u32 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)

View file

@ -54,6 +54,17 @@
#define UART_IIR_FCR_RX_CLR 0x2
#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_DTR 0x1

View file

@ -84,6 +84,11 @@
#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */
#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */
#define MMC_VENDOR_60_CMD 60 /* Vendor Defined */
#define MMC_VENDOR_61_CMD 61 /* Vendor Defined */
#define MMC_VENDOR_62_CMD 62 /* Vendor Defined */
#define MMC_VENDOR_63_CMD 63 /* Vendor Defined */
/* class 11 */
#define MMC_QUE_TASK_PARAMS 44 /* ac [20:16] task id R1 */
#define MMC_QUE_TASK_ADDR 45 /* ac [31:0] data addr R1 */
@ -142,7 +147,10 @@ c : clear by read
#define R1_SWITCH_ERROR (1 << 7) /* sx, c */
#define R1_EXCEPTION_EVENT (1 << 6) /* sr, a */
#define R1_APP_CMD (1 << 5) /* sr, c */
#define R1_SKIP_STATE_CHECK (1 << 4) /* Custom state to skip expected state check */
#define R1_AKE_SEQ_ERROR (1 << 3)
/* R1_CURRENT_STATE 12:9 */
#define R1_STATE_IDLE 0
#define R1_STATE_READY 1
#define R1_STATE_IDENT 2
@ -179,7 +187,10 @@ c : clear by read
/*
* 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)
@ -241,6 +252,7 @@ c : clear by read
#define EXT_CSD_GP_SIZE_MULT 143 /* R/W */
#define EXT_CSD_PARTITION_SETTING_COMPLETED 155 /* R/W */
#define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */
#define EXT_CSD_MAX_ENH_SIZE_MULT 157 /* RO, 3 bytes */
#define EXT_CSD_PARTITION_SUPPORT 160 /* RO */
#define EXT_CSD_HPI_MGMT 161 /* R/W */
#define EXT_CSD_RST_N_FUNCTION 162 /* R/W */

View file

@ -1,6 +1,6 @@
/*
* 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
* 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);
u16 *sd_get_error_count();
bool sd_get_card_removed();
bool sd_get_card_initialized();
bool sd_get_card_mounted();
u32 sd_get_mode();
int sd_init_retry(bool power_cycle);
bool sd_initialize(bool power_cycle);
bool sd_mount();
void sd_unmount();
void sd_end();
bool sd_is_gpt();
void *sd_file_read(const char *path, u32 *fsize);
int sd_save_to_file(void *buf, u32 size, const char *filename);

View file

@ -1,7 +1,7 @@
/*
* 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
* under the terms and conditions of the GNU General Public License,
@ -19,23 +19,40 @@
#include <string.h>
#include "ramdisk.h"
#include <libs/fatfs/diskio.h>
#include <mem/heap.h>
#include <utils/types.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;
u8 *buf = malloc(0x400000);
int res = 0;
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.
if (!res)
res = f_mount(ram_fs, "ram:", 1); // Mount ramdisk.
// Set ramdisk size.
ramdisk_size >>= 9;
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;
}
@ -45,7 +62,7 @@ int ram_disk_read(u32 sector, u32 sector_count, void *buf)
u32 sector_off = RAM_DISK_ADDR + (sector << 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;
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 bytes_count = sector_count << 9;
if ((sector_off - RAM_DISK_ADDR) > RAM_DISK_SZ)
if ((sector_off - RAM_DISK_ADDR) > disk_size)
return 1;
memcpy((void *)sector_off, buf, bytes_count);

View file

@ -1,7 +1,7 @@
/*
* 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
* under the terms and conditions of the GNU General Public License,
@ -23,7 +23,7 @@
#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_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) 2018 CTCaer
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -14,58 +14,79 @@
/* SD commands type argument response */
/* class 0 */
/* This is basically the same command as for MMC with some quirks. */
#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */
#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */
#define SD_SWITCH_VOLTAGE 11 /* ac R1 */
#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */
#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */
#define SD_SWITCH_VOLTAGE 11 /* ac R1 */
/* class 10 */
#define SD_SWITCH 6 /* adtc [31:0] See below R1 */
#define SD_SWITCH 6 /* adtc [31:0] See below R1 */
/* class 5 */
#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_START 32 /* ac [31:0] data addr R1 */
#define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */
/* Application commands */
#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */
#define SD_APP_SD_STATUS 13 /* 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_SET_CLR_CARD_DETECT 42
#define SD_APP_SEND_SCR 51 /* adtc 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_SEND_NUM_WR_BLKS 22 /* adtc R1 */
#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */
#define SD_APP_SET_CLR_CARD_DETECT 42 /* 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 */
#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_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */
#define SD_OCR_XPC (1 << 28) /* SDXC power control */
#define SD_OCR_CCS (1 << 30) /* Card Capacity Status */
#define SD_OCR_VDD_27_34 (0x7F << 15) /* VDD voltage 2.7 ~ 3.4 */
#define SD_OCR_VDD_32_33 (1 << 20) /* VDD voltage 3.2 ~ 3.3 */
#define SD_OCR_VDD_18 (1 << 7) /* VDD voltage 1.8 */
#define SD_OCR_BUSY (1 << 31) /* Card Power up Status */
/*
* SD_SWITCH argument format:
*
* [31] Check (0) or switch (1)
* [30:24] Reserved (0)
* [23:20] Function group 6
* [19:16] Function group 5
* [15:12] Function group 4
* [11:8] Function group 3
* [7:4] Function group 2
* [3:0] Function group 1
*/
* SD_SWITCH argument format:
*
* [31] Check (0) or switch (1)
* [30:24] Reserved (0)
* [23:20] Function group 6
* [19:16] Function group 5
* [15:12] Function group 4
* [11:8] Function group 3
* [7:4] Function group 2
* [3:0] Function group 1
*/
/*
* SD_SEND_IF_COND argument format:
*
* [31:12] Reserved (0)
* [11:8] Host Voltage Supply Flags
* [7:0] Check Pattern (0xAA)
*/
* SD_SEND_IF_COND argument format:
*
* [31:12] Reserved (0)
* [11:8] Host Voltage Supply Flags
* [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_1 1 /* Implements system specification 1.10 */
#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)
/*
* SD bus widths
*/
* SD bus widths
*/
#define SD_BUS_WIDTH_1 0
#define SD_BUS_WIDTH_4 2
/*
* SD bus speeds
*/
* SD bus speeds
*/
#define UHS_SDR12_BUS_SPEED 0
#define HIGH_SPEED_BUS_SPEED 1
#define UHS_SDR25_BUS_SPEED 1
@ -110,19 +131,19 @@
#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_SET 1
/*
* SD_SWITCH function groups
*/
* SD_SWITCH function groups
*/
#define SD_SWITCH_GRP_ACCESS 0
/*
* SD_SWITCH access modes
*/
* SD_SWITCH access modes
*/
#define SD_SWITCH_ACCESS_DEF 0
#define SD_SWITCH_ACCESS_HS 1

View file

@ -1,6 +1,6 @@
/*
* 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
* 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:
//TODO: R1_SWITCH_ERROR can be skipped for certain card types.
@ -66,15 +66,15 @@ static int _sdmmc_storage_execute_cmd_type1_ex(sdmmc_storage_t *storage, u32 *re
{
sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmdbuf, cmd, arg, SDMMC_RSP_TYPE_1, check_busy);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0))
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0;
sdmmc_get_rsp(storage->sdmmc, resp, 4, SDMMC_RSP_TYPE_1);
if (mask)
*resp &= ~mask;
if (_sdmmc_storage_check_result(*resp))
if (expected_state == 0x10 || R1_CURRENT_STATE(*resp) == expected_state)
if (_sdmmc_storage_check_card_status(*resp))
if (expected_state == R1_SKIP_STATE_CHECK || R1_CURRENT_STATE(*resp) == expected_state)
return 1;
return 0;
@ -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)
{
sdmmc_cmd_t cmd;
sdmmc_init_cmd(&cmd, MMC_GO_IDLE_STATE, 0, SDMMC_RSP_TYPE_0, 0);
sdmmc_cmd_t cmdbuf;
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_init_cmd(&cmd, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0))
sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmdbuf, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0;
sdmmc_get_rsp(storage->sdmmc, buf, 0x10, SDMMC_RSP_TYPE_2);
sdmmc_get_rsp(storage->sdmmc, (u32 *)storage->raw_cid, 16, SDMMC_RSP_TYPE_2);
return 1;
}
static int _sdmmc_storage_select_card(sdmmc_storage_t *storage)
{
return _sdmmc_storage_execute_cmd_type1(storage, MMC_SELECT_CARD, storage->rca << 16, 1, 0x10);
return _sdmmc_storage_execute_cmd_type1(storage, MMC_SELECT_CARD, storage->rca << 16, 1, R1_SKIP_STATE_CHECK);
}
static int _sdmmc_storage_get_csd(sdmmc_storage_t *storage, void *buf)
static int _sdmmc_storage_get_csd(sdmmc_storage_t *storage)
{
sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmdbuf, MMC_SEND_CSD, storage->rca << 16, SDMMC_RSP_TYPE_2, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0))
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0;
sdmmc_get_rsp(storage->sdmmc, buf, 0x10, SDMMC_RSP_TYPE_2);
sdmmc_get_rsp(storage->sdmmc, (u32 *)storage->raw_csd, 16, SDMMC_RSP_TYPE_2);
return 1;
}
@ -145,6 +145,10 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out
sdmmc_cmd_t cmdbuf;
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);
reqbuf.buf = buf;
@ -152,7 +156,7 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out
reqbuf.blksize = 512;
reqbuf.is_write = is_write;
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))
{
@ -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)
{
sdmmc_cmd_t cmd;
sdmmc_cmd_t cmdbuf;
u32 arg = 0;
switch (power)
{
case SDMMC_POWER_1_8:
arg = SD_OCR_CCS | SD_OCR_VDD_18;
arg = MMC_CARD_CCS | MMC_CARD_VDD_18;
break;
case SDMMC_POWER_3_3:
arg = SD_OCR_CCS | SD_OCR_VDD_27_34;
arg = MMC_CARD_CCS | MMC_CARD_VDD_27_34;
break;
default:
return 0;
}
sdmmc_init_cmd(&cmd, MMC_SEND_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0))
sdmmc_init_cmd(&cmdbuf, MMC_SEND_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0;
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;
while (1)
while (true)
{
u32 cond = 0;
if (!_mmc_storage_get_op_cond_inner(storage, &cond, power))
break;
// Check if power up is done.
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;
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)
{
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)
@ -362,7 +368,6 @@ static void _mmc_storage_parse_cid(sdmmc_storage_t *storage)
case 3: /* MMC v3.1 - v3.3 */
case 4: /* MMC v4 */
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.prv = unstuff_bits(raw_cid, 48, 8);
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)
{
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.structure = unstuff_bits(raw_csd, 126, 2);
storage->csd.cmdclass = unstuff_bits(raw_csd, 84, 12);
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->sec_cnt = storage->csd.capacity;
}
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.boot_mult = buf[EXT_CSD_BOOT_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_en = buf[EXT_CSD_BKOPS_EN];
storage->ext_csd.bkops_status = buf[EXT_CSD_BKOPS_STATUS];
//storage->ext_csd.bkops = buf[EXT_CSD_BKOPS_SUPPORT];
//storage->ext_csd.bkops_en = buf[EXT_CSD_BKOPS_EN];
//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.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->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)
@ -430,21 +446,21 @@ static int _mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf)
reqbuf.num_sectors = 1;
reqbuf.is_write = 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;
u32 tmp = 0;
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
_mmc_storage_parse_ext_csd(storage, buf);
return _sdmmc_storage_check_result(tmp);
return _sdmmc_storage_check_card_status(tmp);
}
static int _mmc_storage_switch(sdmmc_storage_t *storage, u32 arg)
{
return _sdmmc_storage_execute_cmd_type1(storage, MMC_SWITCH, arg, 1, 0x10);
return _sdmmc_storage_execute_cmd_type1(storage, MMC_SWITCH, arg, 1, R1_SKIP_STATE_CHECK);
}
static int _mmc_storage_switch_buswidth(sdmmc_storage_t *storage, u32 bus_width)
@ -559,19 +575,21 @@ out:
return 1;
}
/*
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 _sdmmc_storage_check_status(storage);
}
*/
int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type)
{
memset(storage, 0, sizeof(sdmmc_storage_t));
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))
return 0;
@ -587,7 +605,7 @@ DPRINTF("[MMC] went to idle state\n");
return 0;
DPRINTF("[MMC] got op cond\n");
if (!_sdmmc_storage_get_cid(storage, storage->raw_cid))
if (!_sdmmc_storage_get_cid(storage))
return 0;
DPRINTF("[MMC] got cid\n");
@ -595,7 +613,7 @@ DPRINTF("[MMC] got cid\n");
return 0;
DPRINTF("[MMC] set relative addr\n");
if (!_sdmmc_storage_get_csd(storage, storage->raw_csd))
if (!_sdmmc_storage_get_csd(storage))
return 0;
DPRINTF("[MMC] got csd\n");
_mmc_storage_parse_csd(storage);
@ -612,13 +630,9 @@ DPRINTF("[MMC] card selected\n");
return 0;
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.
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);
// Check system specification version, only version 4.0 and later support below features.
if (storage->csd.mmca_vsn < CSD_SPEC_VER_4)
return 1;
}
if (!_mmc_storage_switch_buswidth(storage, bus_width))
return 0;
@ -628,21 +642,20 @@ DPRINTF("[MMC] switched buswidth\n");
return 0;
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);
/* 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().
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))
/*
if (storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_AUTO_BKOPS_MASK))
{
_mmc_storage_enable_bkops(storage);
DPRINTF("[MMC] BKOPS enabled\n");
}
*/
if (!_mmc_storage_enable_highspeed(storage, storage->ext_csd.card_type, type))
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);
@ -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;
if (!_sdmmc_storage_execute_cmd_type1_ex(storage, &tmp, MMC_APP_CMD, storage->rca << 16, 0, expected_state, mask))
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)
@ -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);
}
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_init_cmd(&cmdbuf, SD_SEND_IF_COND, 0x1AA, SDMMC_RSP_TYPE_5, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0))
return 1; // The SD Card is version 1.X
u16 vhd_pattern = SD_VHD_27_36 | 0xAA;
sdmmc_init_cmd(&cmdbuf, SD_SEND_IF_COND, vhd_pattern, SDMMC_RSP_TYPE_5, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
{
*is_sdsc = 1; // The SD Card is version 1.X
return 1;
}
// For Card version >= 2.0, parse results.
u32 resp = 0;
if (!sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_5))
return 2;
sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_5);
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;
// 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
arg |= (~is_version_1 & 1) ? SD_OCR_CCS : 0;
arg |= !is_sdsc ? SD_OCR_CCS : 0;
// Support for 1.8V
arg |= (bus_low_voltage_support & ~is_version_1 & 1) ? SD_OCR_S18R : 0;
arg |= (bus_uhs_support && !is_sdsc) ? SD_OCR_S18R : 0;
// This is needed for most cards. Do not set bit7 even if 1.8V is supported.
arg |= SD_OCR_VDD_32_33;
sdmmc_init_cmd(&cmdbuf, SD_APP_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
if (!_sd_storage_execute_app_cmd(storage, 0x10, is_version_1 ? 0x400000 : 0, &cmdbuf, 0, 0))
if (!_sd_storage_execute_app_cmd(storage, R1_SKIP_STATE_CHECK, is_sdsc ? R1_ILLEGAL_COMMAND : 0, &cmdbuf, NULL, NULL))
return 0;
return sdmmc_get_rsp(storage->sdmmc, cond, 4, SDMMC_RSP_TYPE_3);
}
static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, int is_version_1, int bus_low_voltage_support)
static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, bool is_sdsc, int bus_uhs_support)
{
u32 timeout = get_tmr_ms() + 1500;
while (1)
while (true)
{
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;
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)
storage->has_sector_access = 1;
// Check if card supports 1.8V signaling.
if (cond & SD_ROCR_S18A && bus_low_voltage_support)
if (cond & SD_ROCR_S18A && bus_uhs_support)
{
//The low voltage regulator configuration is valid for SDMMC1 only.
if (storage->sdmmc->id == SDMMC_1 &&
_sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY))
// Switch to 1.8V signaling.
if (_sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY))
{
if (!sdmmc_enable_low_voltage(storage->sdmmc))
return 0;
@ -769,9 +792,9 @@ static int _sd_storage_get_rca(sdmmc_storage_t *storage)
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;
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.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)
/* Check if Physical Layer Spec v3.0 is supported */
storage->scr.sda_spec3 = unstuff_bits(resp, 47, 1);
if (storage->scr.sda_spec3)
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.is_write = 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;
u32 tmp = 0;
@ -838,7 +862,7 @@ int _sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf)
_sd_storage_parse_scr(storage);
//gfx_hexdump(0, storage->raw_scr, 8);
return _sdmmc_storage_check_result(tmp);
return _sdmmc_storage_check_card_status(tmp);
}
int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf)
@ -852,14 +876,14 @@ int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf)
reqbuf.num_sectors = 1;
reqbuf.is_write = 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;
u32 tmp = 0;
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
return _sdmmc_storage_check_result(tmp);
return _sdmmc_storage_check_card_status(tmp);
}
int _sd_storage_switch(sdmmc_storage_t *storage, void *buf, int mode, int group, u32 arg)
@ -876,14 +900,14 @@ int _sd_storage_switch(sdmmc_storage_t *storage, void *buf, int mode, int group,
reqbuf.num_sectors = 1;
reqbuf.is_write = 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;
u32 tmp = 0;
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
return _sdmmc_storage_check_result(tmp);
return _sdmmc_storage_check_card_status(tmp);
}
void _sd_storage_set_current_limit(sdmmc_storage_t *storage, u16 current_limit, u8 *buf)
@ -1057,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);
}
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)
{
// 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_ssr2[4];
raw_ssr1[3] = *(u32 *)&storage->raw_ssr[12];
raw_ssr1[2] = *(u32 *)&storage->raw_ssr[8];
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];
memcpy(raw_ssr1, &storage->raw_ssr[0], 16);
memcpy(raw_ssr2, &storage->raw_ssr[16], 16);
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);
switch(unstuff_bits(raw_ssr1, 440 - 384, 8))
u32 speed_class = unstuff_bits(raw_ssr1, 440 - 384, 8);
switch(speed_class)
{
case 0:
storage->ssr.speed_class = 0;
break;
case 1:
storage->ssr.speed_class = 2;
break;
case 2:
storage->ssr.speed_class = 4;
break;
case 3:
storage->ssr.speed_class = 6;
storage->ssr.speed_class = speed_class << 1;
break;
case 4:
@ -1099,16 +1146,18 @@ static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
break;
default:
storage->ssr.speed_class = unstuff_bits(raw_ssr1, 440 - 384, 8);
storage->ssr.speed_class = speed_class;
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.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_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.is_write = 0;
reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0;
reqbuf.is_auto_stop_trn = 0;
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;
}
if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, 0))
if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, NULL))
return 0;
u32 tmp = 0;
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 + 2] = buf[i + 1];
storage->raw_ssr[i + 1] = buf[i + 2];
storage->raw_ssr[i] = buf[i + 3];
}
_sd_storage_parse_ssr(storage);
//gfx_hexdump(0, storage->raw_ssr, 64);
return _sdmmc_storage_check_result(tmp);
return _sdmmc_storage_check_card_status(tmp);
}
static void _sd_storage_parse_cid(sdmmc_storage_t *storage)
{
u32 *raw_cid = (u32 *)&(storage->raw_cid);
storage->cid.manfid = unstuff_bits(raw_cid, 120, 8);
storage->cid.oemid = unstuff_bits(raw_cid, 104, 16);
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[2] = unstuff_bits(raw_cid, 80, 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.hwrev = unstuff_bits(raw_cid, 60, 4);
storage->cid.fwrev = unstuff_bits(raw_cid, 56, 4);
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.manfid = unstuff_bits(raw_cid, 120, 8);
storage->cid.oemid = unstuff_bits(raw_cid, 104, 16);
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[2] = unstuff_bits(raw_cid, 80, 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.hwrev = unstuff_bits(raw_cid, 60, 4);
storage->cid.fwrev = unstuff_bits(raw_cid, 56, 4);
storage->cid.serial = unstuff_bits(raw_cid, 24, 32);
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)
@ -1176,6 +1227,7 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
{
case 0:
storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2);
storage->csd.capacity <<= unstuff_bits(raw_csd, 80, 4) - 9; // Convert native block size to LBA 512B.
break;
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.read_blkbits = 9;
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)
{
@ -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 is_version_1 = 0;
u8 *buf = (u8 *)SDMMC_UPPER_BUFFER;
u32 tmp = 0;
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);
@ -1234,18 +1294,15 @@ DPRINTF("[SD] after init\n");
return 0;
DPRINTF("[SD] went to idle state\n");
is_version_1 = _sd_storage_send_if_cond(storage);
if (is_version_1 == 2)
if (!_sd_storage_send_if_cond(storage, &is_sdsc))
return 0;
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_version_1, bus_low_voltage_support))
if (!_sd_storage_get_op_cond(storage, is_sdsc, bus_uhs_support))
return 0;
DPRINTF("[SD] got op cond\n");
if (!_sdmmc_storage_get_cid(storage, storage->raw_cid))
if (!_sdmmc_storage_get_cid(storage))
return 0;
DPRINTF("[SD] got cid\n");
_sd_storage_parse_cid(storage);
@ -1254,30 +1311,16 @@ DPRINTF("[SD] got cid\n");
return 0;
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;
DPRINTF("[SD] got csd\n");
//Parse CSD.
_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 (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_DS12))
return 0;
DPRINTF("[SD] after setup clock\n");
DPRINTF("[SD] after setup default clock\n");
}
if (!_sdmmc_storage_select_card(storage))
@ -1288,19 +1331,17 @@ DPRINTF("[SD] card selected\n");
return 0;
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))
return 0;
DPRINTF("[SD] cleared card detect\n");
if (!_sd_storage_get_scr(storage, buf))
return 0;
//gfx_hexdump(0, storage->raw_scr, 8);
DPRINTF("[SD] got scr\n");
// Check if card supports a wider bus and if it's not SD Version 1.X
if (bus_width == SDMMC_BUS_WIDTH_4 && (storage->scr.bus_widths & 4) && (storage->scr.sda_vsn & 0xF))
// 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 & 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))
return 0;
@ -1310,6 +1351,7 @@ DPRINTF("[SD] switched to wide bus width\n");
}
else
{
bus_width = SDMMC_BUS_WIDTH_1;
DPRINTF("[SD] SD does not support wide bus width\n");
}
@ -1321,7 +1363,7 @@ DPRINTF("[SD] enabled UHS\n");
sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE);
}
else if (type != SDHCI_TIMING_SD_DS12 && (storage->scr.sda_vsn & 0xF) != 0)
else if (type != SDHCI_TIMING_SD_DS12 && storage->scr.sda_vsn) // Not default speed and not SD Version 1.0.
{
if (!_sd_storage_enable_hs_high_volt(storage, buf))
return 0;
@ -1340,7 +1382,7 @@ DPRINTF("[SD] enabled HS\n");
}
// 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");
}
@ -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)
{
u32 resp;
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;
reqbuf.buf = buf;
@ -1366,9 +1408,9 @@ int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf)
reqbuf.num_sectors = 1;
reqbuf.is_write = 1;
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);
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))
return 0;
if (!_sdmmc_storage_check_result(resp))
if (!_sdmmc_storage_check_card_status(resp))
return 0;
return _sdmmc_storage_check_status(storage);
}

View file

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

View file

@ -1,6 +1,6 @@
/*
* 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
* 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;
case SDMMC_RSP_TYPE_2:
if (size < 0x10)
if (size < 16)
return 0;
rsp[0] = sdmmc->rsp[0];
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;
u32 trnmode = SDHCI_TRNS_DMA;
// Set mulitblock request.
if (req->is_multi_block)
trnmode = SDHCI_TRNS_MULTI | SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_DMA;
// Set request direction.
if (!req->is_write)
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;
@ -1052,7 +1060,7 @@ DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result,
if (!result)
{
#ifdef ERROR_EXTRA_PRINTING
EPRINTFARGS("SDMMC: DMA Update failed (%08X)!", result);
EPRINTF("SDMMC: DMA Update failed!");
#endif
}
}
@ -1070,7 +1078,7 @@ DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result,
if (blkcnt_out)
*blkcnt_out = blkcnt;
if (req->is_auto_cmd12)
if (req->is_auto_stop_trn)
sdmmc->rsp3 = sdmmc->regs->rspreg3;
}
@ -1200,8 +1208,8 @@ static int _sdmmc_config_sdmmc1(bool t210b01)
usleep(10000);
// Enable SD card IO power.
max77620_regulator_set_voltage(REGULATOR_LDO2, 3300000);
max77620_regulator_enable(REGULATOR_LDO2, 1);
max7762x_regulator_set_voltage(REGULATOR_LDO2, 3300000);
max7762x_regulator_enable(REGULATOR_LDO2, true);
usleep(1000);
// Set pad slew codes to get good quality clock.
@ -1332,18 +1340,6 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int p
void sdmmc1_disable_power()
{
// Ensure regulator is into default voltage.
if (PMC(APBDEV_PMC_PWR_DET_VAL) & PMC_PWR_DET_SDMMC1_IO_EN)
{
// Switch to 1.8V and wait for regulator to stabilize.
max77620_regulator_set_voltage(REGULATOR_LDO2, 1800000);
usleep(150);
// Inform IO pads that we switched to 1.8V.
PMC(APBDEV_PMC_PWR_DET_VAL) &= ~(PMC_PWR_DET_SDMMC1_IO_EN);
(void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write.
}
// T210B01 WAR: Clear pull down from CLK pad.
PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) &= ~PINMUX_PULL_MASK;
@ -1351,7 +1347,7 @@ void sdmmc1_disable_power()
_sdmmc_config_sdmmc1_pads(true);
// Disable SD card IO power regulator.
max77620_regulator_enable(REGULATOR_LDO2, 0);
max7762x_regulator_enable(REGULATOR_LDO2, false);
usleep(4000);
// Disable SD card IO power pin.
@ -1383,12 +1379,12 @@ void sdmmc_end(sdmmc_t *sdmmc)
_sdmmc_sd_clock_disable(sdmmc);
// Disable SDMMC power.
_sdmmc_set_io_power(sdmmc, SDMMC_POWER_OFF);
_sdmmc_commit_changes(sdmmc);
// Disable SD card power.
if (sdmmc->id == SDMMC_1)
sdmmc1_disable_power();
_sdmmc_commit_changes(sdmmc);
clock_sdmmc_disable(sdmmc->id);
sdmmc->clock_stopped = 1;
}
@ -1440,7 +1436,7 @@ int sdmmc_enable_low_voltage(sdmmc_t *sdmmc)
_sdmmc_commit_changes(sdmmc);
// Switch to 1.8V and wait for regulator to stabilize. Assume max possible wait needed.
max77620_regulator_set_voltage(REGULATOR_LDO2, 1800000);
max7762x_regulator_set_voltage(REGULATOR_LDO2, 1800000);
usleep(150);
// Inform IO pads that we switched to 1.8V.

View file

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

View file

@ -26,7 +26,7 @@
void set_fan_duty(u32 duty)
{
static bool fan_init = false;
static u16 curr_duty = -1;
static u16 curr_duty = -1;
if (curr_duty == duty)
return;
@ -56,7 +56,7 @@ void set_fan_duty(u32 duty)
if (inv_duty == 236)
{
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.
PINMUX_AUX(PINMUX_AUX_LCD_GPIO2) =
@ -65,7 +65,7 @@ void set_fan_duty(u32 duty)
else // Set PWM duty.
{
// 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);
// Enable fan.
@ -79,15 +79,14 @@ void get_fan_speed(u32 *duty, u32 *rpm)
{
if (rpm)
{
u32 irq_count = 1;
u32 irq_count = 0;
bool should_read = true;
bool irq_val = 0;
// Poll irqs for 2 seconds.
int timer = get_tmr_us() + 1000000;
while (timer - get_tmr_us())
// Poll irqs for 2 seconds. (5 seconds for accurate count).
int timer = get_tmr_us() + 2000000;
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)
{
irq_count++;
@ -97,8 +96,11 @@ void get_fan_speed(u32 *duty, u32 *rpm)
should_read = true;
}
// Halve the irq count.
irq_count /= 2;
// Calculate rpm based on triggered interrupts.
*rpm = 60000000 / ((1000000 * 2) / irq_count);
*rpm = irq_count * (60 / 2);
}
if (duty)

View file

@ -1,7 +1,7 @@
/*
* 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
* 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/>.
*/
#include <soc/hw_init.h>
#include <soc/i2c.h>
#include <soc/t210.h>
#include <thermal/tmp451.h>
u16 tmp451_get_soc_temp(bool intenger)
@ -56,6 +58,20 @@ void tmp451_init()
// Disable ALARM and Range to 0 - 127 oC.
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.
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CNV_RATE_REG, 9);
tmp451_get_soc_temp(false);
@ -63,3 +79,9 @@ void tmp451_init()
// Set rate to every 4 seconds.
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_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
// and the LSByte is the decimal point truncated to 2 decimal places.
// Otherwise it's an integer oC.
u16 tmp451_get_soc_temp(bool integer);
u16 tmp451_get_pcb_temp(bool integer);
void tmp451_init();
void tmp451_end();
#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)
{
u8 status = usb_ops.usb_device_ep1_in_write((u8 *)USB_EP_BULK_IN_BUF_ADDR, len, NULL, USB_XFER_SYNCED);
u8 status = usb_ops.usb_device_ep1_in_write((u8 *)USB_EP_BULK_IN_BUF_ADDR, len, NULL, USB_XFER_SYNCED_CMD);
if (status == USB_ERROR_XFER_ERROR)
{
usbs->set_text(usbs->label, "#FFDD00 Error:# EP IN transfer!");

View file

@ -58,7 +58,7 @@
#define UMS_SCSI_TRANSFER_512K (0x80000 >> UMS_DISK_LBA_SHIFT)
#define UMS_EP_OUT_MAX_XFER (USB_EP_BULK_OUT_MAX_XFER >> UMS_DISK_LBA_SHIFT)
#define UMS_EP_OUT_MAX_XFER (USB_EP_BULK_OUT_MAX_XFER)
// Length of a SCSI Command Data Block.
#define SCSI_MAX_CMD_SZ 16
@ -121,6 +121,15 @@ enum ums_state {
UMS_STATE_TERMINATED
};
enum ums_result {
UMS_RES_OK = 0,
UMS_RES_IO_ERROR = -5,
UMS_RES_TIMEOUT = -3,
UMS_RES_PROT_FATAL = -4,
UMS_RES_INVALID_ARG = -22
};
enum data_direction {
DATA_DIR_UNKNOWN = 0,
DATA_DIR_FROM_HOST,
@ -194,7 +203,7 @@ typedef struct _bulk_ctxt_t {
typedef struct _usbd_gadget_ums_t {
bulk_ctxt_t bulk_ctxt;
int cmnd_size;
u32 cmnd_size;
u8 cmnd[SCSI_MAX_CMD_SZ];
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); */
return 0;
return UMS_RES_OK;
}
static int ums_set_stall(u32 ep)
{
usb_ops.usbd_set_ep_stall(ep, USB_EP_CFG_STALL);
return 0;
return UMS_RES_OK;
}
static int ums_clear_stall(u32 ep)
{
usb_ops.usbd_set_ep_stall(ep, USB_EP_CFG_CLEAR);
return 0;
return UMS_RES_OK;
}
static void ums_flush_endpoint(u32 ep)
@ -306,13 +315,13 @@ static void ums_flush_endpoint(u32 ep)
usb_ops.usbd_flush_endpoint(ep);
}
static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32 ep, bool sync)
static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32 ep, u32 sync_timeout)
{
if (ep == bulk_ctxt->bulk_in)
{
bulk_ctxt->bulk_in_status = usb_ops.usb_device_ep1_in_write(
bulk_ctxt->bulk_in_buf, bulk_ctxt->bulk_in_length,
&bulk_ctxt->bulk_in_length_actual, sync);
&bulk_ctxt->bulk_in_length_actual, sync_timeout);
if (bulk_ctxt->bulk_in_status == USB_ERROR_XFER_ERROR)
{
@ -322,14 +331,14 @@ static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt,
else if (bulk_ctxt->bulk_in_status == USB2_ERROR_XFER_NOT_ALIGNED)
ums->set_text(ums->label, "#FFDD00 Error:# EP IN Buffer not aligned!");
if (sync)
if (sync_timeout)
bulk_ctxt->bulk_in_buf_state = BUF_STATE_EMPTY;
}
else
{
bulk_ctxt->bulk_out_status = usb_ops.usb_device_ep1_out_read(
bulk_ctxt->bulk_out_buf, bulk_ctxt->bulk_out_length,
&bulk_ctxt->bulk_out_length_actual, sync);
&bulk_ctxt->bulk_out_length_actual, sync_timeout);
if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR)
{
@ -339,7 +348,7 @@ static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt,
else if (bulk_ctxt->bulk_out_status == USB2_ERROR_XFER_NOT_ALIGNED)
ums->set_text(ums->label, "#FFDD00 Error:# EP OUT Buffer not aligned!");
if (sync)
if (sync_timeout)
bulk_ctxt->bulk_out_buf_state = BUF_STATE_FULL;
}
}
@ -377,7 +386,7 @@ static void _ums_transfer_finish(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt,
else
{
bulk_ctxt->bulk_out_status = usb_ops.usb_device_ep1_out_reading_finish(
&bulk_ctxt->bulk_out_length_actual, 1000000);
&bulk_ctxt->bulk_out_length_actual);
if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR)
{
@ -446,20 +455,20 @@ static int _scsi_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
return -22; // Invalid argument.
return UMS_RES_INVALID_ARG;
}
}
if (lba_offset >= ums->lun.num_sectors)
{
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
return -22; // Invalid argument.
return UMS_RES_INVALID_ARG;
}
// Check that request data size is not 0.
u32 amount_left = ums->data_size_from_cmnd >> UMS_DISK_LBA_SHIFT;
if (!amount_left)
return -5; // I/O error. /* No default reply */
return UMS_RES_IO_ERROR; // No default reply.
// Limit IO transfers based on request for faster concurrent reads.
u32 max_io_transfer = (amount_left >= UMS_SCSI_TRANSFER_512K) ?
@ -520,7 +529,7 @@ static int _scsi_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
sdmmc_buf += amount << UMS_DISK_LBA_SHIFT;
}
return -5; // I/O error no default reply here. /* No default reply */
return UMS_RES_IO_ERROR; // No default reply.
}
/*
@ -541,7 +550,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{
ums->lun.sense_data = SS_WRITE_PROTECTED;
return -22; // Invalid argument.
return UMS_RES_INVALID_ARG;
}
if (ums->cmnd[0] == SC_WRITE_6)
@ -555,7 +564,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
return -22; // Invalid argument.
return UMS_RES_INVALID_ARG;
}
}
@ -564,7 +573,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
return -22; // Invalid argument.
return UMS_RES_INVALID_ARG;
}
/* Carry out the file writes */
@ -574,22 +583,20 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
while (amount_left_to_write > 0)
{
/* 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.
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!");
amount_left_to_req = 0;
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
ums->lun.sense_data_info = usb_lba_offset;
ums->lun.info_valid = 1;
continue;
break;
}
// 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_info = lba_offset;
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);
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)
@ -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;
return -22; // Invalid argument.
return UMS_RES_INVALID_ARG;
}
// We allow DPO but we don't implement it. Check that nothing else is enabled.
@ -687,12 +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;
return -22; // Invalid argument.
return UMS_RES_INVALID_ARG;
}
u32 verification_length = get_array_be_to_le16(&ums->cmnd[7]);
if (verification_length == 0)
return -5; // I/O error. /* No default reply */
return UMS_RES_IO_ERROR; // No default reply.
u32 amount;
while (verification_length > 0)
@ -724,7 +731,7 @@ DPRINTF("File read %X @ %X\n", amount, lba_offset);
lba_offset += amount;
verification_length -= amount;
}
return 0;
return UMS_RES_OK;
}
static int _scsi_inquiry(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
@ -742,7 +749,7 @@ static int _scsi_inquiry(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
buf[3] = 20; // Additional length.
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 ");
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");
break;
case EMMC_GPP + 1:
sprintf((char *)buf + strlen((char *)buf), "GPP");
s_printf((char *)buf + strlen((char *)buf), "GPP");
break;
case EMMC_BOOT0 + 1:
sprintf((char *)buf + strlen((char *)buf), "BOOT0");
s_printf((char *)buf + strlen((char *)buf), "BOOT0");
break;
case EMMC_BOOT1 + 1:
sprintf((char *)buf + strlen((char *)buf), "BOOT1");
s_printf((char *)buf + strlen((char *)buf), "BOOT1");
break;
}
@ -784,18 +791,18 @@ static int _scsi_inquiry(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
switch (ums->lun.partition)
{
case 0:
sprintf((char *)buf, "%s", "SD RAW");
s_printf((char *)buf, "%s", "SD RAW");
break;
case EMMC_GPP + 1:
sprintf((char *)buf, "%s%s",
s_printf((char *)buf, "%s%s",
ums->lun.type == MMC_SD ? "SD " : "eMMC ", "GPP");
break;
case EMMC_BOOT0 + 1:
sprintf((char *)buf, "%s%s",
s_printf((char *)buf, "%s%s",
ums->lun.type == MMC_SD ? "SD " : "eMMC ", "BOOT0");
break;
case EMMC_BOOT1 + 1:
sprintf((char *)buf, "%s%s",
s_printf((char *)buf, "%s%s",
ums->lun.type == MMC_SD ? "SD " : "eMMC ", "BOOT1");
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;
return -22; // Invalid argument.
return UMS_RES_INVALID_ARG;
}
put_array_le_to_be32(ums->lun.num_sectors - 1, &buf[0]); // Max logical block.
@ -866,14 +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;
return -22; // Invalid argument.
return UMS_RES_INVALID_ARG;
}
if (pc != 1) // Current cumulative values.
{
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
return -22; // Invalid argument.
return UMS_RES_INVALID_ARG;
}
memset(buf, 0, 8);
@ -915,7 +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;
return -22; // Invalid argument.
return UMS_RES_INVALID_ARG;
}
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;
return -22; // Invalid argument.
return UMS_RES_INVALID_ARG;
}
if (pc == 3)
{
ums->lun.sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED;
return -22; // Invalid argument.
return UMS_RES_INVALID_ARG;
}
/* Write the mode parameter header. Fixed values are: default
@ -995,7 +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;
return -22; // Invalid argument.
return UMS_RES_INVALID_ARG;
}
/* 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;
return -22; // Invalid argument.
return UMS_RES_INVALID_ARG;
}
else if ((ums->cmnd[1] & ~0x01) != 0 || // Mask away Immed.
(ums->cmnd[4] & ~0x03) != 0) // Mask LoEj, Start.
{
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
return -22;
return UMS_RES_INVALID_ARG;
}
loej = ums->cmnd[4] & 0x02;
@ -1035,10 +1042,10 @@ static int _scsi_start_stop(usbd_gadget_ums_t *ums)
{
ums->lun.sense_data = SS_MEDIUM_NOT_PRESENT;
return -22;
return UMS_RES_INVALID_ARG;
}
return 0;
return UMS_RES_OK;
}
// Check if we are allowed to unload the media.
@ -1047,16 +1054,16 @@ static int _scsi_start_stop(usbd_gadget_ums_t *ums)
ums->set_text(ums->label, "#C7EA46 Status:# Unload attempt prevented");
ums->lun.sense_data = SS_MEDIUM_REMOVAL_PREVENTED;
return -22;
return UMS_RES_INVALID_ARG;
}
if (!loej)
return 0;
return UMS_RES_OK;
// Unmount means we exit UMS because of ejection.
ums->lun.unmounted = 1;
return 0;
return UMS_RES_OK;
}
static int _scsi_prevent_allow_removal(usbd_gadget_ums_t *ums)
@ -1067,7 +1074,7 @@ static int _scsi_prevent_allow_removal(usbd_gadget_ums_t *ums)
{
ums->lun.sense_data = SS_INVALID_COMMAND;
return -22; // Invalid argument.
return UMS_RES_INVALID_ARG;
}
prevent = ums->cmnd[4] & 0x01;
@ -1075,7 +1082,7 @@ static int _scsi_prevent_allow_removal(usbd_gadget_ums_t *ums)
{
ums->lun.sense_data = SS_INVALID_FIELD_IN_CDB;
return -22; // Invalid argument.
return UMS_RES_INVALID_ARG;
}
// Notify for possible unmounting?
@ -1085,7 +1092,7 @@ static int _scsi_prevent_allow_removal(usbd_gadget_ums_t *ums)
ums->lun.prevent_medium_removal = prevent;
return 0;
return UMS_RES_OK;
}
static int _scsi_read_format_capacities(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
@ -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
// 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)
{
//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;
return -22; // Invalid argument.
return UMS_RES_INVALID_ARG;
}
// 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;
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.unit_attention_data = SS_NO_SENSE;
return -22;
return UMS_RES_INVALID_ARG;
}
// Check that only command bytes listed in the mask are set.
@ -1178,7 +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;
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;
return -22;
return UMS_RES_INVALID_ARG;
}
return 0;
return UMS_RES_OK;
}
static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{
u32 len;
int reply = -22; // Invalid argument.
int reply = UMS_RES_INVALID_ARG;
ums->phase_error = 0;
ums->short_packet_received = 0;
@ -1227,7 +1234,7 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{
// We don't support MODE SELECT.
ums->lun.sense_data = SS_INVALID_COMMAND;
reply = -22;
reply = UMS_RES_INVALID_ARG;
}
break;
@ -1238,7 +1245,7 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{
// We don't support MODE SELECT.
ums->lun.sense_data = SS_INVALID_COMMAND;
reply = -22;
reply = UMS_RES_INVALID_ARG;
}
break;
@ -1367,12 +1374,12 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
if (reply == 0)
{
ums->lun.sense_data = SS_INVALID_COMMAND;
reply = -22; // Invalid argument.
reply = UMS_RES_INVALID_ARG;
}
break;
}
if (reply == -22) // Invalid argument.
if (reply == UMS_RES_INVALID_ARG)
reply = 0; // Error reply length.
// Set up reply buffer for finish_reply(). Otherwise it's already set.
@ -1384,7 +1391,7 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
ums->residue -= reply;
}
return 0;
return UMS_RES_OK;
}
static int pad_with_zeros(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
@ -1398,12 +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);
memset(bulk_ctxt->bulk_in_buf + current_len_to_keep, 0, nsend - current_len_to_keep);
bulk_ctxt->bulk_in_length = nsend;
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED);
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_DATA);
ums->usb_amount_left -= nsend;
current_len_to_keep = 0;
}
return 0;
return UMS_RES_OK;
}
static int throw_away_data(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
@ -1416,10 +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);
bulk_ctxt->bulk_out_length = amount;
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED);
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED_DATA);
ums->usb_amount_left -= amount;
return 0;
return UMS_RES_OK;
}
// Throw away the data in a filled buffer.
@ -1431,15 +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)
{
raise_exception(ums, UMS_STATE_ABORT_BULK_OUT);
return -4; // Interrupted system call
return UMS_RES_PROT_FATAL;
}
}
return 0;
return UMS_RES_OK;
}
static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{
int rc = 0;
int rc = UMS_RES_OK;
switch (ums->data_dir) {
case DATA_DIR_NONE:
@ -1463,7 +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 (!ums->residue)
{
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED);
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_DATA);
/* For Bulk-only, if we're allowed to stall then send the
* short packet and halt the bulk-in endpoint. If we can't
@ -1471,7 +1478,7 @@ static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
}
else if (ums->can_stall)
{
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED);
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_DATA);
rc = ums_set_stall(bulk_ctxt->bulk_in);
ums->set_text(ums->label, "#FFDD00 Error:# Residue. Stalled EP IN!");
}
@ -1491,7 +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?
{
raise_exception(ums, UMS_STATE_ABORT_BULK_OUT);
rc = -4; // Interrupted system call
rc = UMS_RES_PROT_FATAL;
}
else // We can't stall. Read in the excess data and throw it away.
rc = throw_away_data(ums, bulk_ctxt);
@ -1574,7 +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)
return -22; // Invalid argument.
return UMS_RES_INVALID_ARG;
}
/* 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.
ums_wedge_bulk_in_endpoint(ums);
bulk_ctxt->bulk_out_ignore = 1;
return -22; // Invalid argument.
return UMS_RES_INVALID_ARG;
}
/* Is the CBW meaningful? */
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",
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!");
}
return -22; // Invalid argument.
return UMS_RES_INVALID_ARG;
}
/* 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)
ums->timeouts = 0;
return 0;
return UMS_RES_OK;
}
static int get_next_command(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{
int rc = 0;
int rc = UMS_RES_OK;
/* Wait for the next buffer to become available */
// while (bulk_ctxt->bulk_out_buf_state != BUF_STATE_EMPTY)
@ -1652,7 +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;
/* Queue a request to read a Bulk-only CBW */
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED);
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED_CMD);
/* We will drain the buffer in software, which means we
* can reuse it for the next filling. No need to advance
@ -1698,7 +1705,7 @@ static void send_status(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
csw->Status = status;
bulk_ctxt->bulk_in_length = USB_BULK_CS_WRAP_LEN;
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED);
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_CMD);
}
static void handle_exception(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
@ -1765,16 +1772,16 @@ static inline void _system_maintainance(usbd_gadget_ums_t *ums)
u32 time = get_tmr_ms();
if (timer_dram < time)
{
minerva_periodic_training();
timer_dram = get_tmr_ms() + 100;
}
else if (timer_status_bar < time)
if (timer_status_bar < time)
{
ums->system_maintenance(true);
timer_status_bar = get_tmr_ms() + 30000;
}
else if (timer_dram < time)
{
minerva_periodic_training();
timer_dram = get_tmr_ms() + EMC_PERIODIC_TRAIN_MS;
}
}
int usb_device_gadget_ums(usb_ctxt_t *usbs)
@ -1828,6 +1835,7 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
// Initialize sdmmc.
if (usbs->type == MMC_SD)
{
sd_end();
sd_mount();
sd_unmount();
ums.lun.sdmmc = &sd_sdmmc;
@ -1898,7 +1906,10 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
send_status(&ums, &ums.bulk_ctxt);
} 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;
error:

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -21,16 +21,16 @@
#include <mem/heap.h>
#include <utils/types.h>
#define MAX_ENTRIES 64
char *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles, bool parse_dirs)
{
u8 max_entries = 61;
int res = 0;
u32 i = 0, j = 0, k = 0;
DIR dir;
FILINFO fno;
char *dir_entries = (char *)calloc(max_entries, 256);
char *dir_entries = (char *)calloc(MAX_ENTRIES, 256);
char *temp = (char *)calloc(1, 256);
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);
k++;
if (k > (max_entries - 1))
if (k > (MAX_ENTRIES - 1))
break;
}
}
@ -64,7 +64,7 @@ char *dirlist(const char *directory, const char *pattern, bool includeHiddenFile
{
strcpy(dir_entries + (k * 256), fno.fname);
k++;
if (k > (max_entries - 1))
if (k > (MAX_ENTRIES - 1))
break;
}
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)
{
FIL fp;
u32 lblen;
u32 pathlen = strlen(ini_path);
u32 k = 0;
char lbuf[512];
char *filelist = NULL;
FIL fp;
ini_sec_t *csec = NULL;
char *lbuf = NULL;
char *filelist = NULL;
char *filename = (char *)malloc(256);
strcpy(filename, ini_path);
@ -114,6 +114,8 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir)
return 0;
}
lbuf = malloc(512);
do
{
// Fetch one line.
@ -168,6 +170,7 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir)
}
} while (is_dir);
free(lbuf);
free(filename);
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);
}
u32 sprintf(char *buffer, const char *fmt, ...) {
u32 s_printf(char *buffer, const char *fmt, ...) {
va_list ap;
int fill, fcnt;
u32 count = 0;

View file

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

View file

@ -22,7 +22,7 @@
#define ALWAYS_INLINE inline __attribute__((always_inline))
#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 MAX(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 false 0
#define DISABLE 0
#define ENABLE 1
#define BOOT_CFG_AUTOBOOT_EN BIT(0)
#define BOOT_CFG_FROM_LAUNCH BIT(1)
#define BOOT_CFG_FROM_ID BIT(2)

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer
* Copyright (c) 2018-2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -44,7 +44,7 @@ u32 get_tmr_ms()
u32 get_tmr_us()
{
return TMR(TIMERUS_CNTR_1US); //TIMERUS_CNTR_1US
return TMR(TIMERUS_CNTR_1US);
}
void msleep(u32 ms)
@ -132,53 +132,58 @@ void panic(u32 val)
usleep(1);
}
void reboot_normal()
void power_set_state(power_state_t state)
{
u8 reg;
// Unmount and power down sd card.
sd_end();
hw_reinit_workaround(false, 0);
panic(0x21); // Bypass fuse programming in package1.
}
void reboot_rcm()
{
sd_end();
hw_reinit_workaround(false, 0);
PMC(APBDEV_PMC_SCRATCH0) = PMC_SCRATCH0_MODE_RCM;
PMC(APBDEV_PMC_CNTRL) |= PMC_CNTRL_MAIN_RST;
while (true)
bpmp_halt();
}
void reboot_full()
{
sd_end();
hw_reinit_workaround(false, 0);
// Enable soft reset wake event.
u8 reg = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2);
reg |= MAX77620_ONOFFCNFG2_SFT_RST_WK;
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2, reg);
// Do a soft reset.
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_SFT_RST);
while (true)
bpmp_halt();
}
void power_off()
{
sd_end();
// De-initialize and power down various hardware.
hw_reinit_workaround(false, 0);
// Stop the alarm, in case we injected and powered off too fast.
max77620_rtc_stop_alarm();
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_PWR_OFF);
// Set power state.
switch (state)
{
case REBOOT_RCM:
PMC(APBDEV_PMC_SCRATCH0) = PMC_SCRATCH0_MODE_RCM; // Enable RCM path.
PMC(APBDEV_PMC_CNTRL) |= PMC_CNTRL_MAIN_RST; // PMC reset.
break;
case REBOOT_BYPASS_FUSES:
panic(0x21); // Bypass fuse programming in package1.
break;
case POWER_OFF:
// Initiate power down sequence and do not generate a reset (regulators retain state).
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_PWR_OFF);
break;
case POWER_OFF_RESET:
case POWER_OFF_REBOOT:
default:
// Enable/Disable soft reset wake event.
reg = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2);
if (state == POWER_OFF_RESET) // 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)
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 <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
{
NYX_CFG_BIS = BIT(5),
@ -41,6 +51,8 @@ typedef enum
#define byte_swap_32(num) ((((num) >> 24) & 0xff) | (((num) << 8) & 0xff0000) | \
(((num) >> 8 )& 0xff00) | (((num) << 24) & 0xff000000))
#define byte_swap_16(num) ((((num) >> 8) & 0xff) | (((num) << 8) & 0xff00))
typedef struct _cfg_op_t
{
u32 off;
@ -49,6 +61,10 @@ typedef struct _cfg_op_t
typedef struct _nyx_info_t
{
u32 magic;
u32 sd_init;
u32 sd_errors[3];
u8 rsvd[0x1000];
u32 disp_id;
u32 errors;
} nyx_info_t;
@ -65,17 +81,18 @@ typedef struct _nyx_storage_t
emc_table_t mtc_table[10];
} nyx_storage_t;
void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops);
u32 crc32_calc(u32 crc, const u8 *buf, u32 len);
u32 get_tmr_us();
u32 get_tmr_ms();
u32 get_tmr_s();
void usleep(u32 us);
void msleep(u32 ms);
void panic(u32 val);
void reboot_normal();
void reboot_rcm();
void reboot_full();
void power_off();
void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops);
u32 crc32_calc(u32 crc, const u8 *buf, u32 len);
void power_set_state(power_state_t state);
void power_set_state_ex(void *param);
#endif

View file

@ -49,6 +49,7 @@ void set_default_configuration()
h_cfg.sept_run = EMC(EMC_SCRATCH0) & EMC_SEPT_RUN;
h_cfg.aes_slots_new = false;
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.t210b01 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01;

View file

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

View file

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

View file

@ -1,6 +1,7 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2019-2021 shchmue
* Copyright (c) 2018 M4xw
*
* 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_puts(const char *s);
void gfx_printf(const char *fmt, ...);
void gfx_hexdump(u32 base, const u8 *buf, u32 len);
void gfx_hexdiff(u32 base, const u8 *buf1, const u8 *buf2, u32 len);
void gfx_hexdump(u32 base, const void *buf, 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_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/>.
*/
#include <gfx/di.h>
#include <display/di.h>
#include "tui.h"
#include "../config.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;
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 + 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)
{
EPRINTF("Mariko not supported on < 0.17.0!");
EPRINTF("\nMariko not supported on < 0.17.0!");
goto fail;
}

View file

@ -1,6 +1,6 @@
/*
* 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
* under the terms and conditions of the GNU General Public License,
@ -20,6 +20,7 @@
#include "pkg1.h"
#include "pkg2.h"
#include <sec/se_t210.h>
#include <utils/types.h>
#include <utils/ini.h>
#include <sec/tsec.h>
@ -50,20 +51,21 @@ typedef struct _exo_ctxt_t
bool fs_is_510;
bool no_user_exceptions;
bool user_pmu;
bool *usb3_force;
bool *cal0_blank;
bool *cal0_allow_writes_sys;
} exo_ctxt_t;
typedef struct _hos_eks_keys_t
{
u8 mkk[0x10];
u8 fdk[0x10];
u8 mkk[SE_KEY_128_SIZE];
u8 fdk[SE_KEY_128_SIZE];
} hos_eks_keys_t;
typedef struct _hos_eks_bis_keys_t
{
u8 crypt[0x10];
u8 tweak[0x10];
u8 crypt[SE_KEY_128_SIZE];
u8 tweak[SE_KEY_128_SIZE];
} hos_eks_bis_keys_t;
typedef struct _hos_eks_mbr_t
@ -73,8 +75,8 @@ typedef struct _hos_eks_mbr_t
u8 enabled_bis;
u8 rsvd[2];
u32 lot0;
u8 dkg[0x10];
u8 dkk[0x10];
u8 dkg[SE_KEY_128_SIZE];
u8 dkk[SE_KEY_128_SIZE];
hos_eks_keys_t keys[5];
hos_eks_bis_keys_t bis_keys[3];
} hos_eks_mbr_t;
@ -106,14 +108,16 @@ typedef struct _launch_ctxt_t
link_t kip1_list;
char* kip1_patches;
u32 fss0_hosver;
bool svcperm;
bool debugmode;
bool stock;
bool atmosphere;
bool fss0_experimental;
bool emummc_forced;
char *fss0_main_path;
u32 fss0_hosver;
bool fss0_experimental;
bool atmosphere;
exo_ctxt_t exo_ctx;
ini_sec_t *cfg;
@ -129,6 +133,6 @@ void hos_eks_get();
void hos_eks_save(u32 kb);
void hos_eks_clear(u32 kb);
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

View file

@ -1,7 +1,7 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 st4rk
* Copyright (c) 2018-2019 CTCaer
* Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2018 balika011
*
* 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)
{
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))
return &_pkg1_ids[i];
return NULL;

View file

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

View file

@ -17,7 +17,7 @@
#include "keys.h"
#include "../config.h"
#include <gfx/di.h>
#include <display/di.h>
#include <gfx_utils.h>
#include "../gfx/tui.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;
}
static u8 *_read_pkg1(sdmmc_t *sdmmc, const pkg1_id_t **pkg1_id) {
if (emummc_storage_init_mmc(&emmc_storage, sdmmc)) {
static u8 *_read_pkg1(const pkg1_id_t **pkg1_id) {
if (emummc_storage_init_mmc()) {
EPRINTF("Unable to init MMC.");
return NULL;
}
@ -102,11 +102,11 @@ static u8 *_read_pkg1(sdmmc_t *sdmmc, const pkg1_id_t **pkg1_id) {
// Read package1.
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.");
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.");
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);
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.");
}
@ -577,7 +577,7 @@ static bool _derive_titlekeys(key_derivation_ctx_t *keys, titlekey_buffer_t *tit
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.");
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(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.");
return false;
}
@ -690,7 +690,7 @@ static void _save_mariko_partial_keys(char *text_buffer) {
for (u32 ks = 12; ks < 16; ks++) {
// First, encrypt zeros with complete key
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
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 j = 0; j < AES_128_KEY_SIZE; j++)
pos += sprintf(&text_buffer[pos], "%02x", data[i * AES_128_KEY_SIZE + j]);
pos += sprintf(&text_buffer[pos], "\n");
pos += s_printf(&text_buffer[pos], "%02x", data[i * AES_128_KEY_SIZE + j]);
pos += s_printf(&text_buffer[pos], "\n");
}
}
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");
char keyfile_path[30] = "sd:/switch/prod.keys";
if (fuse_read_odm(4) & 3)
sprintf(&keyfile_path[11], "dev.keys");
s_printf(&keyfile_path[11], "dev.keys");
FILINFO 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 j = 0; j < AES_128_KEY_SIZE; j++)
sprintf(&titlekey_text[i].rights_id[j * 2], "%02x", titlekey_buffer->rights_ids[i][j]);
sprintf(titlekey_text[i].equals, " = ");
s_printf(&titlekey_text[i].rights_id[j * 2], "%02x", titlekey_buffer->rights_ids[i][j]);
s_printf(titlekey_text[i].equals, " = ");
for (u32 j = 0; j < AES_128_KEY_SIZE; j++)
sprintf(&titlekey_text[i].titlekey[j * 2], "%02x", titlekey_buffer->titlekeys[i][j]);
sprintf(titlekey_text[i].newline, "\n");
s_printf(&titlekey_text[i].titlekey[j * 2], "%02x", titlekey_buffer->titlekeys[i][j]);
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)) {
gfx_printf("%kWrote %d bytes to %s\n", colors[(color_idx++) % 6], (u32)fno.fsize, keyfile_path);
} else
@ -828,10 +828,9 @@ static void _save_keys_to_sd(key_derivation_ctx_t *keys, titlekey_buffer_t *titl
static void _derive_keys() {
u32 start_whole_operation_time = get_tmr_us();
sdmmc_t sdmmc;
const pkg1_id_t *pkg1_id;
u8 *pkg1 = _read_pkg1(&sdmmc, &pkg1_id);
u8 *pkg1 = _read_pkg1(&pkg1_id);
if (!pkg1) {
return;
}
@ -909,17 +908,17 @@ static void _save_key(const char *name, const void *data, u32 len, char *outbuf)
if (!_key_exists(data))
return;
u32 pos = strlen(outbuf);
pos += sprintf(&outbuf[pos], "%s = ", name);
pos += s_printf(&outbuf[pos], "%s = ", name);
for (u32 i = 0; i < len; i++)
pos += sprintf(&outbuf[pos], "%02x", *(u8*)(data + i));
sprintf(&outbuf[pos], "\n");
pos += s_printf(&outbuf[pos], "%02x", *(u8*)(data + i));
s_printf(&outbuf[pos], "\n");
_key_count++;
}
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);
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);
}
free(temp_name);

View file

@ -245,7 +245,7 @@
#define FF_FS_NORTC 1
#define FF_NORTC_MON 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
/ 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

View file

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

View file

@ -1,8 +1,8 @@
/*
* Copyright (c) 2018 naehrwert
*
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2019-2020 shchmue
* Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2019-2021 shchmue
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -20,7 +20,7 @@
#include <string.h>
#include "config.h"
#include <gfx/di.h>
#include <display/di.h>
#include <gfx_utils.h>
#include "gfx/tui.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 RCM_PAYLOAD_ADDR (EXT_PAYLOAD_ADDR + ALIGN(PATCHED_RELOC_SZ, 0x10))
#define COREBOOT_END_ADDR 0xD0000000
#define COREBOOT_VER_OFF 0x41
#define CBFS_DRAM_EN_ADDR 0x4003e000
#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);
if (!path)
return 1;
@ -92,10 +94,10 @@ int launch_payload(char *path)
FIL fp;
if (f_open(&fp, path, FA_READ))
{
gfx_con.mute = false;
EPRINTFARGS("Payload file is missing!\n(%s)", path);
sd_unmount();
return 1;
goto out;
}
// 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);
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))
{
f_close(&fp);
sd_unmount();
return 1;
goto out;
}
f_close(&fp);
sd_unmount();
sd_end();
if (size < 0x30000)
{
@ -131,7 +141,12 @@ int launch_payload(char *path)
else
{
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.
@ -143,6 +158,8 @@ int launch_payload(char *path)
(*ext_payload_ptr)();
}
out:
sd_end();
return 1;
}
@ -221,7 +238,8 @@ void launch_tools()
free(ments);
free(dir);
free(filelist);
sd_unmount();
sd_end();
return;
}
}
@ -247,15 +265,12 @@ void launch_tools()
else
memcpy(dir, file_sec, strlen(file_sec) + 1);
if (launch_payload(dir))
{
EPRINTF("Failed to launch payload.");
free(dir);
}
launch_payload(dir, true);
EPRINTF("Failed to launch payload.");
}
out:
sd_unmount();
sd_end();
free(dir);
btn_wait();
@ -278,15 +293,20 @@ void dump_emunand()
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[] = {
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_CAPTION("---------------", COLOR_YELLOW),
MDEF_HANDLER("Payloads...", launch_tools, COLOR_GREEN),
MDEF_CAPTION("---------------", COLOR_BLUE),
MDEF_HANDLER("Reboot (Normal)", reboot_normal, COLOR_VIOLET),
MDEF_HANDLER("Reboot (RCM)", reboot_rcm, COLOR_RED),
MDEF_HANDLER("Power off", power_off, COLOR_ORANGE),
MDEF_HANDLER_EX("Reboot (OFW)", &STATE_REBOOT_BYPASS_FUSES, power_set_state_ex, COLOR_VIOLET),
MDEF_HANDLER_EX("Reboot (RCM)", &STATE_REBOOT_RCM, power_set_state_ex, COLOR_RED),
MDEF_HANDLER_EX("Power off", &STATE_POWER_OFF, power_set_state_ex, COLOR_ORANGE),
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.
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1 + pk1_offset);
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;
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);
emummc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
emummc_storage_read(&storage, PKG1_OFFSET / NX_EMMC_BLOCKSIZE, PKG1_MAX_SIZE / NX_EMMC_BLOCKSIZE, pkg1);
emummc_storage_end(&storage);
emummc_storage_set_mmc_partition(EMMC_BOOT0);
emummc_storage_read(PKG1_OFFSET / NX_EMMC_BLOCKSIZE, PKG1_MAX_SIZE / NX_EMMC_BLOCKSIZE, pkg1);
emummc_storage_end();
pkg1_id = pkg1_identify(pkg1 + pk1_offset);
if (pkg1_id) {
sprintf(emunand_label + 36, "% 3d", pkg1_id->kb);
s_printf(emunand_label + 36, "% 3d", pkg1_id->kb);
free(pkg1);
ment_top[1].caption = emunand_label;
}
@ -367,8 +387,9 @@ void ipl_main()
display_backlight_pwm_init();
// 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();
// Ignore whether emummc is enabled.
h_cfg.emummc_force_disable = emu_cfg.sector == 0 && !emu_cfg.path;
@ -401,7 +422,7 @@ void ipl_main()
if (h_cfg.rcm_patched)
{
ment_top[5].handler = reboot_full;
ment_top[6].data = &STATE_REBOOT_FULL;
}
// Update key generations listed in menu.

View file

@ -23,8 +23,8 @@
.extern memset
.type memset, %function
.extern ipl_main
.type ipl_main, %function
.extern _irq_setup
.type _irq_setup, %function
.globl _start
.type _start, %function
@ -67,7 +67,7 @@ _real_start:
LDR R2, =__bss_end
SUB R2, R2, R0
BL memset
BL ipl_main
BL _irq_setup
B .
.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
* 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;
}
int emummc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc)
int emummc_storage_init_mmc()
{
FILINFO fno;
emu_cfg.active_part = 0;
// 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;
if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
@ -173,21 +173,21 @@ out:
return 1;
}
int emummc_storage_end(sdmmc_storage_t *storage)
int emummc_storage_end()
{
if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
sdmmc_storage_end(storage);
sdmmc_storage_end(&emmc_storage);
else
sd_end();
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;
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)
{
sector += emu_cfg.sector;
@ -228,11 +228,11 @@ int emummc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, v
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;
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)
{
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);
}
}
if (f_open(&fp, emu_cfg.emummc_file_based_path, FA_WRITE))
{
gfx_printf("e5\n");
return 0;
}
f_lseek(&fp, (u64)sector << 9);
if (f_write(&fp, buf, (u64)num_sectors << 9, NULL))
{
gfx_printf("e6\n");
f_close(&fp);
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;
sdmmc_storage_set_mmc_partition(&emmc_storage, partition);
if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
sdmmc_storage_set_mmc_partition(storage, partition);
else if (emu_cfg.sector)
if (!emu_cfg.enabled || h_cfg.emummc_force_disable || emu_cfg.sector)
return 1;
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
* 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();
bool emummc_set_path(char *path);
int emummc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc);
int emummc_storage_end(sdmmc_storage_t *storage);
int emummc_storage_read(sdmmc_storage_t *storage, 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_set_mmc_partition(sdmmc_storage_t *storage, u32 partition);
int emummc_storage_init_mmc();
int emummc_storage_end();
int emummc_storage_read(u32 sector, u32 num_sectors, void *buf);
int emummc_storage_write(u32 sector, u32 num_sectors, void *buf);
int emummc_storage_set_mmc_partition(u32 partition);
#endif

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2019-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -19,6 +20,7 @@
#include "nx_emmc.h"
#include "emummc.h"
#include <mem/heap.h>
#include <soc/fuse.h>
#include <storage/mbr_gpt.h>
#include <utils/list.h>
@ -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);
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++)
{
@ -52,6 +58,7 @@ void nx_emmc_gpt_parse(link_t *gpt, sdmmc_storage_t *storage)
list_append(gpt, &part->link);
}
out:
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)
if (!strcmp(part->name, name))
return part;
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.
if (part->lba_start + sector_off > part->lba_end)
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)
@ -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.
if (part->lba_start + sector_off > part->lba_end)
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) 2019-2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -43,7 +44,9 @@ extern FATFS emmc_fs;
void nx_emmc_gpt_parse(link_t *gpt, sdmmc_storage_t *storage);
void nx_emmc_gpt_free(link_t *gpt);
emmc_part_t *nx_emmc_part_find(link_t *gpt, const char *name);
int nx_emmc_part_read(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf);
int nx_emmc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf);
int nx_emmc_part_read(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf);
int nx_emmc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf);
void nx_emmc_get_autorcm_masks(u8 *mod0, u8 *mod1);
#endif

View file

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

View file

@ -1,6 +1,6 @@
/*
* 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
* under the terms and conditions of the GNU General Public License,
@ -59,6 +59,11 @@ bool sd_get_card_removed()
return false;
}
bool sd_get_card_mounted()
{
return sd_mounted;
}
u32 sd_get_mode()
{
return sd_mode;
@ -180,6 +185,11 @@ static void _sd_deinit()
void sd_unmount() { _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)
{
FIL fp;