mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
fusee: Implement BootConfig and Boot Reason handling.
This commit is contained in:
parent
1cbbdb43d3
commit
611e85e6ee
19 changed files with 299 additions and 109 deletions
|
@ -138,9 +138,9 @@ void bootconfig_get_package2_hash_for_recovery(uint64_t *out_hash) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bootconfig_is_recovery_boot(void) {
|
bool bootconfig_is_recovery_boot(void) {
|
||||||
return (g_boot_reason.is_recovery_boot != 0);
|
return ((g_boot_reason.bootloader_attribute & 0x01) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t bootconfig_get_boot_reason(void) {
|
uint64_t bootconfig_get_boot_reason(void) {
|
||||||
return ((uint64_t)g_boot_reason.boot_reason_high << 24) | (g_boot_reason.boot_reason_low & 0xFFFFFF);
|
return ((uint64_t)g_boot_reason.boot_reason_state << 24) | (g_boot_reason.boot_reason_value & 0xFFFFFF);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,11 +34,12 @@ static inline bootconfig_t *get_loaded_bootconfig(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint64_t _0x00;
|
uint32_t bootloader_version;
|
||||||
uint32_t _0x08;
|
uint32_t bootloader_start_block;
|
||||||
uint32_t is_recovery_boot;
|
uint32_t bootloader_start_page;
|
||||||
uint32_t boot_reason_low;
|
uint32_t bootloader_attribute;
|
||||||
uint32_t boot_reason_high;
|
uint32_t boot_reason_value;
|
||||||
|
uint32_t boot_reason_state;
|
||||||
} boot_reason_t;
|
} boot_reason_t;
|
||||||
|
|
||||||
void bootconfig_load_and_verify(const bootconfig_t *bootconfig);
|
void bootconfig_load_and_verify(const bootconfig_t *bootconfig);
|
||||||
|
|
|
@ -16,7 +16,7 @@ uint32_t btn_read()
|
||||||
res |= BTN_VOL_UP;
|
res |= BTN_VOL_UP;
|
||||||
|
|
||||||
uint32_t val = 0;
|
uint32_t val = 0;
|
||||||
if (i2c_query(4, 0x3C, 0x15, &val, 1))
|
if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, 0x15, &val, 1))
|
||||||
{
|
{
|
||||||
if (val & 0x4)
|
if (val & 0x4)
|
||||||
res |= BTN_POWER;
|
res |= BTN_POWER;
|
||||||
|
|
|
@ -36,9 +36,9 @@ void display_init()
|
||||||
|
|
||||||
/* Power on. */
|
/* Power on. */
|
||||||
uint8_t val = 0xD0;
|
uint8_t val = 0xD0;
|
||||||
i2c_send(4, 0x3C, MAX77620_REG_LDO0_CFG, &val, 1);
|
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_LDO0_CFG, &val, 1);
|
||||||
val = 0x09;
|
val = 0x09;
|
||||||
i2c_send(4, 0x3C, MAX77620_REG_GPIO7, &val, 1);
|
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_GPIO7, &val, 1);
|
||||||
|
|
||||||
/* Enable MIPI CAL, DSI, DISP1, HOST1X, UART_FST_MIPI_CAL, DSIA LP clocks. */
|
/* Enable MIPI CAL, DSI, DISP1, HOST1X, UART_FST_MIPI_CAL, DSIA LP clocks. */
|
||||||
car->rst_dev_h_clr = 0x1010000;
|
car->rst_dev_h_clr = 0x1010000;
|
||||||
|
|
|
@ -203,33 +203,33 @@ void nx_hwinit()
|
||||||
clkrst_reboot(CARDEVICE_UNK);
|
clkrst_reboot(CARDEVICE_UNK);
|
||||||
|
|
||||||
/* Initialize I2C1 and I2C5. */
|
/* Initialize I2C1 and I2C5. */
|
||||||
i2c_init(0);
|
i2c_init(I2C_1);
|
||||||
i2c_init(4);
|
i2c_init(I2C_5);
|
||||||
|
|
||||||
uint8_t val = 0x40;
|
uint8_t val = 0x40;
|
||||||
i2c_send(4, 0x3C, MAX77620_REG_CNFGBBC, &val, 1);
|
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CNFGBBC, &val, 1);
|
||||||
val = 0x78;
|
val = 0x78;
|
||||||
i2c_send(4, 0x3C, MAX77620_REG_ONOFFCNFG1, &val, 1);
|
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, &val, 1);
|
||||||
|
|
||||||
val = 0x38;
|
val = 0x38;
|
||||||
i2c_send(4, 0x3C, MAX77620_REG_FPS_CFG0, &val, 1);
|
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_CFG0, &val, 1);
|
||||||
val = 0x3A;
|
val = 0x3A;
|
||||||
i2c_send(4, 0x3C, MAX77620_REG_FPS_CFG1, &val, 1);
|
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_CFG1, &val, 1);
|
||||||
val = 0x38;
|
val = 0x38;
|
||||||
i2c_send(4, 0x3C, MAX77620_REG_FPS_CFG2, &val, 1);
|
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_CFG2, &val, 1);
|
||||||
val = 0xF;
|
val = 0xF;
|
||||||
i2c_send(4, 0x3C, MAX77620_REG_FPS_LDO4, &val, 1);
|
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_LDO4, &val, 1);
|
||||||
val = 0xC7;
|
val = 0xC7;
|
||||||
i2c_send(4, 0x3C, MAX77620_REG_FPS_LDO8, &val, 1);
|
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_LDO8, &val, 1);
|
||||||
val = 0x4F;
|
val = 0x4F;
|
||||||
i2c_send(4, 0x3C, MAX77620_REG_FPS_SD0, &val, 1);
|
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_SD0, &val, 1);
|
||||||
val = 0x29;
|
val = 0x29;
|
||||||
i2c_send(4, 0x3C, MAX77620_REG_FPS_SD1, &val, 1);
|
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_SD1, &val, 1);
|
||||||
val = 0x1B;
|
val = 0x1B;
|
||||||
i2c_send(4, 0x3C, MAX77620_REG_FPS_SD3, &val, 1);
|
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_SD3, &val, 1);
|
||||||
|
|
||||||
val = 42; /* 42 = (1125000 - 600000) / 12500 -> 1.125V */
|
val = 42; /* 42 = (1125000 - 600000) / 12500 -> 1.125V */
|
||||||
i2c_send(4, 0x3C, MAX77620_REG_SD0, &val, 1);
|
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_SD0, &val, 1);
|
||||||
|
|
||||||
/* Configure and lock PMC scratch registers. */
|
/* Configure and lock PMC scratch registers. */
|
||||||
config_pmc_scratch();
|
config_pmc_scratch();
|
||||||
|
|
|
@ -43,16 +43,16 @@ void i2c_init(unsigned int id) {
|
||||||
void i2c_send_pmic_cpu_shutdown_cmd(void) {
|
void i2c_send_pmic_cpu_shutdown_cmd(void) {
|
||||||
uint32_t val = 0;
|
uint32_t val = 0;
|
||||||
/* PMIC == Device 4:3C. */
|
/* PMIC == Device 4:3C. */
|
||||||
i2c_query(4, 0x3C, 0x41, &val, 1);
|
i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, 0x41, &val, 1);
|
||||||
val |= 4;
|
val |= 4;
|
||||||
i2c_send(4, 0x3C, 0x41, &val, 1);
|
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, 0x41, &val, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Queries the value of TI charger bit over I2C. */
|
/* Queries the value of TI charger bit over I2C. */
|
||||||
bool i2c_query_ti_charger_bit_7(void) {
|
bool i2c_query_ti_charger_bit_7(void) {
|
||||||
uint32_t val = 0;
|
uint32_t val = 0;
|
||||||
/* TI Charger = Device 0:6B. */
|
/* TI Charger = Device 0:6B. */
|
||||||
i2c_query(0, 0x6B, 0, &val, 1);
|
i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1);
|
||||||
return (val & 0x80) != 0;
|
return (val & 0x80) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,34 +60,34 @@ bool i2c_query_ti_charger_bit_7(void) {
|
||||||
void i2c_clear_ti_charger_bit_7(void) {
|
void i2c_clear_ti_charger_bit_7(void) {
|
||||||
uint32_t val = 0;
|
uint32_t val = 0;
|
||||||
/* TI Charger = Device 0:6B. */
|
/* TI Charger = Device 0:6B. */
|
||||||
i2c_query(0, 0x6B, 0, &val, 1);
|
i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1);
|
||||||
val &= 0x7F;
|
val &= 0x7F;
|
||||||
i2c_send(0, 0x6B, 0, &val, 1);
|
i2c_send(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sets TI charger bit over I2C. */
|
/* Sets TI charger bit over I2C. */
|
||||||
void i2c_set_ti_charger_bit_7(void) {
|
void i2c_set_ti_charger_bit_7(void) {
|
||||||
uint32_t val = 0;
|
uint32_t val = 0;
|
||||||
/* TI Charger = Device 0:6B. */
|
/* TI Charger = Device 0:6B. */
|
||||||
i2c_query(0, 0x6B, 0, &val, 1);
|
i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1);
|
||||||
val |= 0x80;
|
val |= 0x80;
|
||||||
i2c_send(0, 0x6B, 0, &val, 1);
|
i2c_send(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get registers pointer based on I2C ID. */
|
/* Get registers pointer based on I2C ID. */
|
||||||
volatile tegra_i2c_t *i2c_get_registers_from_id(unsigned int id) {
|
volatile tegra_i2c_t *i2c_get_registers_from_id(unsigned int id) {
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case 0:
|
case I2C_1:
|
||||||
return I2C1_REGS;
|
return I2C1_REGS;
|
||||||
case 1:
|
case I2C_2:
|
||||||
return I2C2_REGS;
|
return I2C2_REGS;
|
||||||
case 2:
|
case I2C_3:
|
||||||
return I2C3_REGS;
|
return I2C3_REGS;
|
||||||
case 3:
|
case I2C_4:
|
||||||
return I2C4_REGS;
|
return I2C4_REGS;
|
||||||
case 4:
|
case I2C_5:
|
||||||
return I2C5_REGS;
|
return I2C5_REGS;
|
||||||
case 5:
|
case I2C_6:
|
||||||
return I2C6_REGS;
|
return I2C6_REGS;
|
||||||
default:
|
default:
|
||||||
generic_panic();
|
generic_panic();
|
||||||
|
|
|
@ -8,6 +8,20 @@
|
||||||
#define I2C234_BASE 0x7000C000
|
#define I2C234_BASE 0x7000C000
|
||||||
#define I2C56_BASE 0x7000D000
|
#define I2C56_BASE 0x7000D000
|
||||||
|
|
||||||
|
#define I2C_1 0
|
||||||
|
#define I2C_2 1
|
||||||
|
#define I2C_3 2
|
||||||
|
#define I2C_4 3
|
||||||
|
#define I2C_5 4
|
||||||
|
#define I2C_6 5
|
||||||
|
|
||||||
|
#define MAX77621_CPU_I2C_ADDR 0x1B
|
||||||
|
#define MAX77621_GPU_I2C_ADDR 0x1C
|
||||||
|
#define MAX17050_I2C_ADDR 0x36
|
||||||
|
#define MAX77620_PWR_I2C_ADDR 0x3C
|
||||||
|
#define MAX77620_RTC_I2C_ADDR 0x68
|
||||||
|
#define BQ24193_I2C_ADDR 0x6B
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t I2C_I2C_CNFG_0;
|
uint32_t I2C_I2C_CNFG_0;
|
||||||
uint32_t I2C_I2C_CMD_ADDR0_0;
|
uint32_t I2C_I2C_CMD_ADDR0_0;
|
||||||
|
|
|
@ -11,6 +11,36 @@
|
||||||
#ifndef _MFD_MAX77620_H_
|
#ifndef _MFD_MAX77620_H_
|
||||||
#define _MFD_MAX77620_H_
|
#define _MFD_MAX77620_H_
|
||||||
|
|
||||||
|
/* RTC Registers */
|
||||||
|
#define MAX77620_REG_RTCINT 0x00
|
||||||
|
#define MAX77620_REG_RTCINTM 0x01
|
||||||
|
#define MAX77620_REG_RTCCNTLM 0x02
|
||||||
|
#define MAX77620_REG_RTCCNTL 0x03
|
||||||
|
#define MAX77620_REG_RTCUPDATE0 0x04
|
||||||
|
#define MAX77620_REG_RTCUPDATE1 0x05
|
||||||
|
#define MAX77620_REG_RTCSMPL 0x06
|
||||||
|
#define MAX77620_REG_RTCSEC 0x07
|
||||||
|
#define MAX77620_REG_RTCMIN 0x08
|
||||||
|
#define MAX77620_REG_RTCHOUR 0x09
|
||||||
|
#define MAX77620_REG_RTCDOW 0x0A
|
||||||
|
#define MAX77620_REG_RTCMONTH 0x0B
|
||||||
|
#define MAX77620_REG_RTCYEAR 0x0C
|
||||||
|
#define MAX77620_REG_RTCDOM 0x0D
|
||||||
|
#define MAX77620_REG_RTCSECA1 0x0E
|
||||||
|
#define MAX77620_REG_RTCMINA1 0x0F
|
||||||
|
#define MAX77620_REG_RTCHOURA1 0x10
|
||||||
|
#define MAX77620_REG_RTCDOWA1 0x11
|
||||||
|
#define MAX77620_REG_RTCMONTHA1 0x12
|
||||||
|
#define MAX77620_REG_RTCYEARA1 0x13
|
||||||
|
#define MAX77620_REG_RTCDOMA1 0x14
|
||||||
|
#define MAX77620_REG_RTCSECA2 0x15
|
||||||
|
#define MAX77620_REG_RTCMINA2 0x16
|
||||||
|
#define MAX77620_REG_RTCHOURA2 0x17
|
||||||
|
#define MAX77620_REG_RTCDOWA2 0x18
|
||||||
|
#define MAX77620_REG_RTCMONTHA2 0x19
|
||||||
|
#define MAX77620_REG_RTCYEARA2 0x1A
|
||||||
|
#define MAX77620_REG_RTCDOMA2 0x1B
|
||||||
|
|
||||||
/* GLOBAL, PMIC, GPIO, FPS, ONOFFC, CID Registers */
|
/* GLOBAL, PMIC, GPIO, FPS, ONOFFC, CID Registers */
|
||||||
#define MAX77620_REG_CNFGGLBL1 0x00
|
#define MAX77620_REG_CNFGGLBL1 0x00
|
||||||
#define MAX77620_REG_CNFGGLBL2 0x01
|
#define MAX77620_REG_CNFGGLBL2 0x01
|
||||||
|
|
|
@ -55,11 +55,11 @@ int max77620_regulator_get_status(uint32_t id)
|
||||||
uint8_t val = 0;
|
uint8_t val = 0;
|
||||||
|
|
||||||
if (reg->type == REGULATOR_SD) {
|
if (reg->type == REGULATOR_SD) {
|
||||||
if (i2c_query(4, 0x3C, MAX77620_REG_STATSD, &val, 1))
|
if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_STATSD, &val, 1))
|
||||||
return (val & reg->status_mask) ? 0 : 1;
|
return (val & reg->status_mask) ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i2c_query(4, 0x3C, reg->cfg_addr, &val, 1))
|
if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, reg->cfg_addr, &val, 1))
|
||||||
return (val & 8) ? 0 : 1;
|
return (val & 8) ? 0 : 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -73,7 +73,7 @@ int max77620_regulator_config_fps(uint32_t id)
|
||||||
const max77620_regulator_t *reg = &_pmic_regulators[id];
|
const max77620_regulator_t *reg = &_pmic_regulators[id];
|
||||||
uint8_t val = ((reg->fps_src << 6) | (reg->pu_period << 3) | (reg->pd_period));
|
uint8_t val = ((reg->fps_src << 6) | (reg->pu_period << 3) | (reg->pd_period));
|
||||||
|
|
||||||
if (i2c_send(4, 0x3C, reg->fps_addr, &val, 1)) {
|
if (i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, reg->fps_addr, &val, 1)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,11 +93,11 @@ int max77620_regulator_set_voltage(uint32_t id, uint32_t mv)
|
||||||
uint32_t mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step;
|
uint32_t mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step;
|
||||||
uint8_t val = 0;
|
uint8_t val = 0;
|
||||||
|
|
||||||
if (i2c_query(4, 0x3C, reg->volt_addr, &val, 1))
|
if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, reg->volt_addr, &val, 1))
|
||||||
{
|
{
|
||||||
val = ((val & ~reg->volt_mask) | (mult & reg->volt_mask));
|
val = ((val & ~reg->volt_mask) | (mult & reg->volt_mask));
|
||||||
|
|
||||||
if (i2c_send(4, 0x3C, reg->volt_addr, &val, 1))
|
if (i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, reg->volt_addr, &val, 1))
|
||||||
{
|
{
|
||||||
udelay(1000);
|
udelay(1000);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -117,14 +117,14 @@ int max77620_regulator_enable(uint32_t id, int enable)
|
||||||
uint32_t addr = (reg->type == REGULATOR_SD) ? reg->cfg_addr : reg->volt_addr;
|
uint32_t addr = (reg->type == REGULATOR_SD) ? reg->cfg_addr : reg->volt_addr;
|
||||||
uint8_t val = 0;
|
uint8_t val = 0;
|
||||||
|
|
||||||
if (i2c_query(4, 0x3C, addr, &val, 1))
|
if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, addr, &val, 1))
|
||||||
{
|
{
|
||||||
if (enable)
|
if (enable)
|
||||||
val = ((val & ~reg->enable_mask) | ((3 << reg->enable_shift) & reg->enable_mask));
|
val = ((val & ~reg->enable_mask) | ((3 << reg->enable_shift) & reg->enable_mask));
|
||||||
else
|
else
|
||||||
val &= ~reg->enable_mask;
|
val &= ~reg->enable_mask;
|
||||||
|
|
||||||
if (i2c_send(4, 0x3C, addr, &val, 1))
|
if (i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, addr, &val, 1))
|
||||||
{
|
{
|
||||||
udelay(1000);
|
udelay(1000);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -139,7 +139,7 @@ void max77620_config_default()
|
||||||
for (uint32_t i = 1; i <= REGULATOR_MAX; i++)
|
for (uint32_t i = 1; i <= REGULATOR_MAX; i++)
|
||||||
{
|
{
|
||||||
uint8_t val = 0;
|
uint8_t val = 0;
|
||||||
if (i2c_query(4, 0x3C, MAX77620_REG_CID4, &val, 1))
|
if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CID4, &val, 1))
|
||||||
{
|
{
|
||||||
max77620_regulator_config_fps(i);
|
max77620_regulator_config_fps(i);
|
||||||
max77620_regulator_set_voltage(i, _pmic_regulators[i].mv_default);
|
max77620_regulator_set_voltage(i, _pmic_regulators[i].mv_default);
|
||||||
|
@ -151,11 +151,11 @@ void max77620_config_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t val = 4;
|
uint8_t val = 4;
|
||||||
i2c_send(4, 0x3C, MAX77620_REG_SD_CFG2, &val, 1);
|
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_SD_CFG2, &val, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void max77620_low_battery_monitor_config()
|
void max77620_low_battery_monitor_config()
|
||||||
{
|
{
|
||||||
uint8_t val = (MAX77620_CNFGGLBL1_LBDAC_EN | MAX77620_CNFGGLBL1_LBHYST_N | MAX77620_CNFGGLBL1_LBDAC_N);
|
uint8_t val = (MAX77620_CNFGGLBL1_LBDAC_EN | MAX77620_CNFGGLBL1_LBHYST_N | MAX77620_CNFGGLBL1_LBDAC_N);
|
||||||
i2c_send(4, 0x3C, MAX77620_REG_CNFGGLBL1, &val, 1);
|
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CNFGGLBL1, &val, 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -542,9 +542,9 @@ void sdram_init()
|
||||||
const sdram_params_t *params = (const sdram_params_t *)sdram_get_params();
|
const sdram_params_t *params = (const sdram_params_t *)sdram_get_params();
|
||||||
|
|
||||||
uint8_t val = 5;
|
uint8_t val = 5;
|
||||||
i2c_send(4, 0x3C, MAX77620_REG_SD_CFG2, &val, 1);
|
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_SD_CFG2, &val, 1);
|
||||||
val = 40; /* 40 = (1000 * 1100 - 600000) / 12500 -> 1.1V */
|
val = 40; /* 40 = (1000 * 1100 - 600000) / 12500 -> 1.1V */
|
||||||
i2c_send(4, 0x3C, MAX77620_REG_SD1, &val, 1);
|
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_SD1, &val, 1);
|
||||||
|
|
||||||
pmc->vddp_sel = params->pmc_vddp_sel;
|
pmc->vddp_sel = params->pmc_vddp_sel;
|
||||||
udelay(params->pmc_vddp_sel_wait);
|
udelay(params->pmc_vddp_sel_wait);
|
||||||
|
|
|
@ -16,7 +16,7 @@ uint32_t btn_read()
|
||||||
res |= BTN_VOL_UP;
|
res |= BTN_VOL_UP;
|
||||||
|
|
||||||
uint32_t val = 0;
|
uint32_t val = 0;
|
||||||
if (i2c_query(4, 0x3C, 0x15, &val, 1))
|
if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, 0x15, &val, 1))
|
||||||
{
|
{
|
||||||
if (val & 0x4)
|
if (val & 0x4)
|
||||||
res |= BTN_POWER;
|
res |= BTN_POWER;
|
||||||
|
|
|
@ -12,22 +12,22 @@
|
||||||
void _cluster_enable_power()
|
void _cluster_enable_power()
|
||||||
{
|
{
|
||||||
uint8_t val = 0;
|
uint8_t val = 0;
|
||||||
i2c_query(4, 0x3C, MAX77620_REG_AME_GPIO, &val, 1);
|
i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_AME_GPIO, &val, 1);
|
||||||
|
|
||||||
val &= 0xDF;
|
val &= 0xDF;
|
||||||
i2c_send(4, 0x3C, MAX77620_REG_AME_GPIO, &val, 1);
|
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_AME_GPIO, &val, 1);
|
||||||
val = 0x09;
|
val = 0x09;
|
||||||
i2c_send(4, 0x3C, MAX77620_REG_GPIO5, &val, 1);
|
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_GPIO5, &val, 1);
|
||||||
|
|
||||||
/* Enable power. */
|
/* Enable power. */
|
||||||
val = 0x20;
|
val = 0x20;
|
||||||
i2c_send(4, 0x1B, MAX77620_REG_CNFGGLBL3, &val, 1);
|
i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x02, &val, 1);
|
||||||
val = 0x8D;
|
val = 0x8D;
|
||||||
i2c_send(4, 0x1B, MAX77620_REG_CNFG1_32K, &val, 1);
|
i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x03, &val, 1);
|
||||||
val = 0xB7;
|
val = 0xB7;
|
||||||
i2c_send(4, 0x1B, MAX77620_REG_CNFGGLBL1, &val, 1);
|
i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x00, &val, 1);
|
||||||
val = 0xB7;
|
val = 0xB7;
|
||||||
i2c_send(4, 0x1B, MAX77620_REG_CNFGGLBL2, &val, 1);
|
i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x01, &val, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int _cluster_pmc_enable_partition(uint32_t part, uint32_t toggle)
|
int _cluster_pmc_enable_partition(uint32_t part, uint32_t toggle)
|
||||||
|
|
|
@ -36,9 +36,9 @@ void display_init()
|
||||||
|
|
||||||
/* Power on. */
|
/* Power on. */
|
||||||
uint8_t val = 0xD0;
|
uint8_t val = 0xD0;
|
||||||
i2c_send(4, 0x3C, MAX77620_REG_LDO0_CFG, &val, 1);
|
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_LDO0_CFG, &val, 1);
|
||||||
val = 0x09;
|
val = 0x09;
|
||||||
i2c_send(4, 0x3C, MAX77620_REG_GPIO7, &val, 1);
|
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_GPIO7, &val, 1);
|
||||||
|
|
||||||
/* Enable MIPI CAL, DSI, DISP1, HOST1X, UART_FST_MIPI_CAL, DSIA LP clocks. */
|
/* Enable MIPI CAL, DSI, DISP1, HOST1X, UART_FST_MIPI_CAL, DSIA LP clocks. */
|
||||||
car->rst_dev_h_clr = 0x1010000;
|
car->rst_dev_h_clr = 0x1010000;
|
||||||
|
|
|
@ -43,16 +43,16 @@ void i2c_init(unsigned int id) {
|
||||||
void i2c_send_pmic_cpu_shutdown_cmd(void) {
|
void i2c_send_pmic_cpu_shutdown_cmd(void) {
|
||||||
uint32_t val = 0;
|
uint32_t val = 0;
|
||||||
/* PMIC == Device 4:3C. */
|
/* PMIC == Device 4:3C. */
|
||||||
i2c_query(4, 0x3C, 0x41, &val, 1);
|
i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, 0x41, &val, 1);
|
||||||
val |= 4;
|
val |= 4;
|
||||||
i2c_send(4, 0x3C, 0x41, &val, 1);
|
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, 0x41, &val, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Queries the value of TI charger bit over I2C. */
|
/* Queries the value of TI charger bit over I2C. */
|
||||||
bool i2c_query_ti_charger_bit_7(void) {
|
bool i2c_query_ti_charger_bit_7(void) {
|
||||||
uint32_t val = 0;
|
uint32_t val = 0;
|
||||||
/* TI Charger = Device 0:6B. */
|
/* TI Charger = Device 0:6B. */
|
||||||
i2c_query(0, 0x6B, 0, &val, 1);
|
i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1);
|
||||||
return (val & 0x80) != 0;
|
return (val & 0x80) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,34 +60,34 @@ bool i2c_query_ti_charger_bit_7(void) {
|
||||||
void i2c_clear_ti_charger_bit_7(void) {
|
void i2c_clear_ti_charger_bit_7(void) {
|
||||||
uint32_t val = 0;
|
uint32_t val = 0;
|
||||||
/* TI Charger = Device 0:6B. */
|
/* TI Charger = Device 0:6B. */
|
||||||
i2c_query(0, 0x6B, 0, &val, 1);
|
i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1);
|
||||||
val &= 0x7F;
|
val &= 0x7F;
|
||||||
i2c_send(0, 0x6B, 0, &val, 1);
|
i2c_send(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sets TI charger bit over I2C. */
|
/* Sets TI charger bit over I2C. */
|
||||||
void i2c_set_ti_charger_bit_7(void) {
|
void i2c_set_ti_charger_bit_7(void) {
|
||||||
uint32_t val = 0;
|
uint32_t val = 0;
|
||||||
/* TI Charger = Device 0:6B. */
|
/* TI Charger = Device 0:6B. */
|
||||||
i2c_query(0, 0x6B, 0, &val, 1);
|
i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1);
|
||||||
val |= 0x80;
|
val |= 0x80;
|
||||||
i2c_send(0, 0x6B, 0, &val, 1);
|
i2c_send(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get registers pointer based on I2C ID. */
|
/* Get registers pointer based on I2C ID. */
|
||||||
volatile tegra_i2c_t *i2c_get_registers_from_id(unsigned int id) {
|
volatile tegra_i2c_t *i2c_get_registers_from_id(unsigned int id) {
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case 0:
|
case I2C_1:
|
||||||
return I2C1_REGS;
|
return I2C1_REGS;
|
||||||
case 1:
|
case I2C_2:
|
||||||
return I2C2_REGS;
|
return I2C2_REGS;
|
||||||
case 2:
|
case I2C_3:
|
||||||
return I2C3_REGS;
|
return I2C3_REGS;
|
||||||
case 3:
|
case I2C_4:
|
||||||
return I2C4_REGS;
|
return I2C4_REGS;
|
||||||
case 4:
|
case I2C_5:
|
||||||
return I2C5_REGS;
|
return I2C5_REGS;
|
||||||
case 5:
|
case I2C_6:
|
||||||
return I2C6_REGS;
|
return I2C6_REGS;
|
||||||
default:
|
default:
|
||||||
generic_panic();
|
generic_panic();
|
||||||
|
|
|
@ -8,6 +8,20 @@
|
||||||
#define I2C234_BASE 0x7000C000
|
#define I2C234_BASE 0x7000C000
|
||||||
#define I2C56_BASE 0x7000D000
|
#define I2C56_BASE 0x7000D000
|
||||||
|
|
||||||
|
#define I2C_1 0
|
||||||
|
#define I2C_2 1
|
||||||
|
#define I2C_3 2
|
||||||
|
#define I2C_4 3
|
||||||
|
#define I2C_5 4
|
||||||
|
#define I2C_6 5
|
||||||
|
|
||||||
|
#define MAX77621_CPU_I2C_ADDR 0x1B
|
||||||
|
#define MAX77621_GPU_I2C_ADDR 0x1C
|
||||||
|
#define MAX17050_I2C_ADDR 0x36
|
||||||
|
#define MAX77620_PWR_I2C_ADDR 0x3C
|
||||||
|
#define MAX77620_RTC_I2C_ADDR 0x68
|
||||||
|
#define BQ24193_I2C_ADDR 0x6B
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t I2C_I2C_CNFG_0;
|
uint32_t I2C_I2C_CNFG_0;
|
||||||
uint32_t I2C_I2C_CMD_ADDR0_0;
|
uint32_t I2C_I2C_CMD_ADDR0_0;
|
||||||
|
|
|
@ -11,6 +11,36 @@
|
||||||
#ifndef _MFD_MAX77620_H_
|
#ifndef _MFD_MAX77620_H_
|
||||||
#define _MFD_MAX77620_H_
|
#define _MFD_MAX77620_H_
|
||||||
|
|
||||||
|
/* RTC Registers */
|
||||||
|
#define MAX77620_REG_RTCINT 0x00
|
||||||
|
#define MAX77620_REG_RTCINTM 0x01
|
||||||
|
#define MAX77620_REG_RTCCNTLM 0x02
|
||||||
|
#define MAX77620_REG_RTCCNTL 0x03
|
||||||
|
#define MAX77620_REG_RTCUPDATE0 0x04
|
||||||
|
#define MAX77620_REG_RTCUPDATE1 0x05
|
||||||
|
#define MAX77620_REG_RTCSMPL 0x06
|
||||||
|
#define MAX77620_REG_RTCSEC 0x07
|
||||||
|
#define MAX77620_REG_RTCMIN 0x08
|
||||||
|
#define MAX77620_REG_RTCHOUR 0x09
|
||||||
|
#define MAX77620_REG_RTCDOW 0x0A
|
||||||
|
#define MAX77620_REG_RTCMONTH 0x0B
|
||||||
|
#define MAX77620_REG_RTCYEAR 0x0C
|
||||||
|
#define MAX77620_REG_RTCDOM 0x0D
|
||||||
|
#define MAX77620_REG_RTCSECA1 0x0E
|
||||||
|
#define MAX77620_REG_RTCMINA1 0x0F
|
||||||
|
#define MAX77620_REG_RTCHOURA1 0x10
|
||||||
|
#define MAX77620_REG_RTCDOWA1 0x11
|
||||||
|
#define MAX77620_REG_RTCMONTHA1 0x12
|
||||||
|
#define MAX77620_REG_RTCYEARA1 0x13
|
||||||
|
#define MAX77620_REG_RTCDOMA1 0x14
|
||||||
|
#define MAX77620_REG_RTCSECA2 0x15
|
||||||
|
#define MAX77620_REG_RTCMINA2 0x16
|
||||||
|
#define MAX77620_REG_RTCHOURA2 0x17
|
||||||
|
#define MAX77620_REG_RTCDOWA2 0x18
|
||||||
|
#define MAX77620_REG_RTCMONTHA2 0x19
|
||||||
|
#define MAX77620_REG_RTCYEARA2 0x1A
|
||||||
|
#define MAX77620_REG_RTCDOMA2 0x1B
|
||||||
|
|
||||||
/* GLOBAL, PMIC, GPIO, FPS, ONOFFC, CID Registers */
|
/* GLOBAL, PMIC, GPIO, FPS, ONOFFC, CID Registers */
|
||||||
#define MAX77620_REG_CNFGGLBL1 0x00
|
#define MAX77620_REG_CNFGGLBL1 0x00
|
||||||
#define MAX77620_REG_CNFGGLBL2 0x01
|
#define MAX77620_REG_CNFGGLBL2 0x01
|
||||||
|
|
|
@ -55,11 +55,11 @@ int max77620_regulator_get_status(uint32_t id)
|
||||||
uint8_t val = 0;
|
uint8_t val = 0;
|
||||||
|
|
||||||
if (reg->type == REGULATOR_SD) {
|
if (reg->type == REGULATOR_SD) {
|
||||||
if (i2c_query(4, 0x3C, MAX77620_REG_STATSD, &val, 1))
|
if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_STATSD, &val, 1))
|
||||||
return (val & reg->status_mask) ? 0 : 1;
|
return (val & reg->status_mask) ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i2c_query(4, 0x3C, reg->cfg_addr, &val, 1))
|
if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, reg->cfg_addr, &val, 1))
|
||||||
return (val & 8) ? 0 : 1;
|
return (val & 8) ? 0 : 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -73,7 +73,7 @@ int max77620_regulator_config_fps(uint32_t id)
|
||||||
const max77620_regulator_t *reg = &_pmic_regulators[id];
|
const max77620_regulator_t *reg = &_pmic_regulators[id];
|
||||||
uint8_t val = ((reg->fps_src << 6) | (reg->pu_period << 3) | (reg->pd_period));
|
uint8_t val = ((reg->fps_src << 6) | (reg->pu_period << 3) | (reg->pd_period));
|
||||||
|
|
||||||
if (i2c_send(4, 0x3C, reg->fps_addr, &val, 1)) {
|
if (i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, reg->fps_addr, &val, 1)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,11 +93,11 @@ int max77620_regulator_set_voltage(uint32_t id, uint32_t mv)
|
||||||
uint32_t mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step;
|
uint32_t mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step;
|
||||||
uint8_t val = 0;
|
uint8_t val = 0;
|
||||||
|
|
||||||
if (i2c_query(4, 0x3C, reg->volt_addr, &val, 1))
|
if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, reg->volt_addr, &val, 1))
|
||||||
{
|
{
|
||||||
val = ((val & ~reg->volt_mask) | (mult & reg->volt_mask));
|
val = ((val & ~reg->volt_mask) | (mult & reg->volt_mask));
|
||||||
|
|
||||||
if (i2c_send(4, 0x3C, reg->volt_addr, &val, 1))
|
if (i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, reg->volt_addr, &val, 1))
|
||||||
{
|
{
|
||||||
udelay(1000);
|
udelay(1000);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -117,14 +117,14 @@ int max77620_regulator_enable(uint32_t id, int enable)
|
||||||
uint32_t addr = (reg->type == REGULATOR_SD) ? reg->cfg_addr : reg->volt_addr;
|
uint32_t addr = (reg->type == REGULATOR_SD) ? reg->cfg_addr : reg->volt_addr;
|
||||||
uint8_t val = 0;
|
uint8_t val = 0;
|
||||||
|
|
||||||
if (i2c_query(4, 0x3C, addr, &val, 1))
|
if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, addr, &val, 1))
|
||||||
{
|
{
|
||||||
if (enable)
|
if (enable)
|
||||||
val = ((val & ~reg->enable_mask) | ((3 << reg->enable_shift) & reg->enable_mask));
|
val = ((val & ~reg->enable_mask) | ((3 << reg->enable_shift) & reg->enable_mask));
|
||||||
else
|
else
|
||||||
val &= ~reg->enable_mask;
|
val &= ~reg->enable_mask;
|
||||||
|
|
||||||
if (i2c_send(4, 0x3C, addr, &val, 1))
|
if (i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, addr, &val, 1))
|
||||||
{
|
{
|
||||||
udelay(1000);
|
udelay(1000);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -139,7 +139,7 @@ void max77620_config_default()
|
||||||
for (uint32_t i = 1; i <= REGULATOR_MAX; i++)
|
for (uint32_t i = 1; i <= REGULATOR_MAX; i++)
|
||||||
{
|
{
|
||||||
uint8_t val = 0;
|
uint8_t val = 0;
|
||||||
if (i2c_query(4, 0x3C, MAX77620_REG_CID4, &val, 1))
|
if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CID4, &val, 1))
|
||||||
{
|
{
|
||||||
max77620_regulator_config_fps(i);
|
max77620_regulator_config_fps(i);
|
||||||
max77620_regulator_set_voltage(i, _pmic_regulators[i].mv_default);
|
max77620_regulator_set_voltage(i, _pmic_regulators[i].mv_default);
|
||||||
|
@ -151,11 +151,11 @@ void max77620_config_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t val = 4;
|
uint8_t val = 4;
|
||||||
i2c_send(4, 0x3C, MAX77620_REG_SD_CFG2, &val, 1);
|
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_SD_CFG2, &val, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void max77620_low_battery_monitor_config()
|
void max77620_low_battery_monitor_config()
|
||||||
{
|
{
|
||||||
uint8_t val = (MAX77620_CNFGGLBL1_LBDAC_EN | MAX77620_CNFGGLBL1_LBHYST_N | MAX77620_CNFGGLBL1_LBDAC_N);
|
uint8_t val = (MAX77620_CNFGGLBL1_LBDAC_EN | MAX77620_CNFGGLBL1_LBHYST_N | MAX77620_CNFGGLBL1_LBDAC_N);
|
||||||
i2c_send(4, 0x3C, MAX77620_REG_CNFGGLBL1, &val, 1);
|
i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CNFGGLBL1, &val, 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,13 @@
|
||||||
#include "fs_utils.h"
|
#include "fs_utils.h"
|
||||||
#include "nxboot.h"
|
#include "nxboot.h"
|
||||||
#include "nxfs.h"
|
#include "nxfs.h"
|
||||||
|
#include "bct.h"
|
||||||
#include "di.h"
|
#include "di.h"
|
||||||
#include "mc.h"
|
#include "mc.h"
|
||||||
#include "se.h"
|
#include "se.h"
|
||||||
#include "pmc.h"
|
#include "pmc.h"
|
||||||
|
#include "i2c.h"
|
||||||
|
#include "max77620.h"
|
||||||
#include "cluster.h"
|
#include "cluster.h"
|
||||||
#include "flow.h"
|
#include "flow.h"
|
||||||
#include "timers.h"
|
#include "timers.h"
|
||||||
|
@ -78,13 +81,98 @@ static void nxboot_configure_exosphere(uint32_t target_firmware) {
|
||||||
*(MAILBOX_EXOSPHERE_CONFIGURATION) = exo_cfg;
|
*(MAILBOX_EXOSPHERE_CONFIGURATION) = exo_cfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void nxboot_set_bootreason() {
|
||||||
|
boot_reason_t boot_reason = {0};
|
||||||
|
FILE *boot0;
|
||||||
|
nvboot_config_table *bct;
|
||||||
|
nv_bootloader_info *bootloader_info;
|
||||||
|
|
||||||
|
/* Allocate memory for the BCT. */
|
||||||
|
bct = malloc(sizeof(nvboot_config_table));
|
||||||
|
if (bct == NULL) {
|
||||||
|
fatal_error("[NXBOOT]: Out of memory!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open boot0. */
|
||||||
|
boot0 = fopen("boot0:/", "rb");
|
||||||
|
if (boot0 == NULL) {
|
||||||
|
fatal_error("[NXBOOT]: Failed to open boot0!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read the BCT. */
|
||||||
|
if (fread(bct, sizeof(nvboot_config_table), 1, boot0) == 0) {
|
||||||
|
fatal_error("[NXBOOT]: Failed to read the BCT!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close boot0. */
|
||||||
|
fclose(boot0);
|
||||||
|
|
||||||
|
/* Populate bootloader parameters. */
|
||||||
|
bootloader_info = &bct->bootloader[0];
|
||||||
|
boot_reason.bootloader_version = bootloader_info->version;
|
||||||
|
boot_reason.bootloader_start_block = bootloader_info->start_blk;
|
||||||
|
boot_reason.bootloader_start_page = bootloader_info->start_page;
|
||||||
|
boot_reason.bootloader_attribute = bootloader_info->attribute;
|
||||||
|
|
||||||
|
uint8_t power_key_intr = 0;
|
||||||
|
uint8_t rtc_intr = 0;
|
||||||
|
i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_ONOFFIRQ, &power_key_intr, 1);
|
||||||
|
i2c_query(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_REG_RTCINT, &rtc_intr, 1);
|
||||||
|
|
||||||
|
/* Set PMIC value. */
|
||||||
|
boot_reason.boot_reason_value = ((rtc_intr << 0x08) | power_key_intr);
|
||||||
|
|
||||||
|
/* TODO: Find out what these mean. */
|
||||||
|
if (power_key_intr & 0x80)
|
||||||
|
boot_reason.boot_reason_state = 0x01;
|
||||||
|
else if (power_key_intr & 0x08)
|
||||||
|
boot_reason.boot_reason_state = 0x02;
|
||||||
|
else if (rtc_intr & 0x02)
|
||||||
|
boot_reason.boot_reason_state = 0x03;
|
||||||
|
else if (rtc_intr & 0x04)
|
||||||
|
boot_reason.boot_reason_state = 0x04;
|
||||||
|
|
||||||
|
/* Set in memory. */
|
||||||
|
memcpy((void *)MAILBOX_NX_BOOTLOADER_BOOT_REASON, &boot_reason, sizeof(boot_reason));
|
||||||
|
|
||||||
|
/* Clean up. */
|
||||||
|
free(bct);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nxboot_move_bootconfig() {
|
||||||
|
FILE *bcfile;
|
||||||
|
void *bootconfig;
|
||||||
|
|
||||||
|
/* Allocate memory for reading BootConfig. */
|
||||||
|
bootconfig = memalign(0x1000, 0x4000);
|
||||||
|
if (bootconfig == NULL) {
|
||||||
|
fatal_error("[NXBOOT]: Out of memory!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get BootConfig from the Package2 partition. */
|
||||||
|
bcfile = fopen("bcpkg21:/", "rb");
|
||||||
|
if (bcfile == NULL) {
|
||||||
|
fatal_error("[NXBOOT]: Failed to open BootConfig from eMMC!\n");
|
||||||
|
}
|
||||||
|
if (fread(bootconfig, 0x4000, 1, bcfile) < 1) {
|
||||||
|
fatal_error("[NXBOOT]: Failed to read BootConfig!\n");
|
||||||
|
}
|
||||||
|
fclose(bcfile);
|
||||||
|
|
||||||
|
/* Copy the first 0x3000 bytes into IRAM. */
|
||||||
|
memset((void *)0x4003D000, 0, 0x3000);
|
||||||
|
memcpy((void *)0x4003D000, bootconfig, 0x3000);
|
||||||
|
|
||||||
|
/* Clean up. */
|
||||||
|
free(bootconfig);
|
||||||
|
}
|
||||||
|
|
||||||
/* This is the main function responsible for booting Horizon. */
|
/* This is the main function responsible for booting Horizon. */
|
||||||
static nx_keyblob_t __attribute__((aligned(16))) g_keyblobs[32];
|
static nx_keyblob_t __attribute__((aligned(16))) g_keyblobs[32];
|
||||||
void nxboot_main(void) {
|
void nxboot_main(void) {
|
||||||
volatile tegra_pmc_t *pmc = pmc_get_regs();
|
volatile tegra_pmc_t *pmc = pmc_get_regs();
|
||||||
volatile tegra_se_t *se = se_get_regs();
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
loader_ctx_t *loader_ctx = get_loader_ctx();
|
loader_ctx_t *loader_ctx = get_loader_ctx();
|
||||||
/* void *bootconfig; */
|
|
||||||
package2_header_t *package2;
|
package2_header_t *package2;
|
||||||
size_t package2_size;
|
size_t package2_size;
|
||||||
void *tsec_fw;
|
void *tsec_fw;
|
||||||
|
@ -101,7 +189,7 @@ void nxboot_main(void) {
|
||||||
void *exosphere_memaddr;
|
void *exosphere_memaddr;
|
||||||
|
|
||||||
/* Allocate memory for reading Package2. */
|
/* Allocate memory for reading Package2. */
|
||||||
package2 = memalign(4096, PACKAGE2_SIZE_MAX);
|
package2 = memalign(0x1000, PACKAGE2_SIZE_MAX);
|
||||||
if (package2 == NULL) {
|
if (package2 == NULL) {
|
||||||
fatal_error("[NXBOOT]: Out of memory!\n");
|
fatal_error("[NXBOOT]: Out of memory!\n");
|
||||||
}
|
}
|
||||||
|
@ -115,10 +203,12 @@ void nxboot_main(void) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pk2file = fopen("bcpkg21:/", "rb");
|
pk2file = fopen("bcpkg21:/", "rb");
|
||||||
if (pk2file == NULL || fseek(pk2file, 0x4000, SEEK_SET) != 0) {
|
if (pk2file == NULL) {
|
||||||
printf("[NXBOOT]: Failed to open Package2 from eMMC: %s!\n", strerror(errno));
|
fatal_error("[NXBOOT]: Failed to open Package2 from eMMC: %s!\n", strerror(errno));
|
||||||
|
}
|
||||||
|
if (fseek(pk2file, 0x4000, SEEK_SET) != 0) {
|
||||||
|
fatal_error("[NXBOOT]: Failed to seek Package2 in eMMC: %s!\n", strerror(errno));
|
||||||
fclose(pk2file);
|
fclose(pk2file);
|
||||||
generic_panic();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +217,7 @@ void nxboot_main(void) {
|
||||||
fatal_error("[NXBOOT]: Failed to read Package2!\n");
|
fatal_error("[NXBOOT]: Failed to read Package2!\n");
|
||||||
}
|
}
|
||||||
package2_size = package2_meta_get_size(&package2->metadata);
|
package2_size = package2_meta_get_size(&package2->metadata);
|
||||||
if (package2_size > PACKAGE2_SIZE_MAX || package2_size <= sizeof(package2_header_t)) {
|
if ((package2_size > PACKAGE2_SIZE_MAX) || (package2_size <= sizeof(package2_header_t))) {
|
||||||
fatal_error("[NXBOOT]: Package2 is too big or too small!\n");
|
fatal_error("[NXBOOT]: Package2 is too big or too small!\n");
|
||||||
}
|
}
|
||||||
if (fread(package2->data, package2_size - sizeof(package2_header_t), 1, pk2file) < 1) {
|
if (fread(package2->data, package2_size - sizeof(package2_header_t), 1, pk2file) < 1) {
|
||||||
|
@ -138,7 +228,7 @@ void nxboot_main(void) {
|
||||||
/* Read and parse boot0. */
|
/* Read and parse boot0. */
|
||||||
printf("[NXBOOT]: Reading boot0...\n");
|
printf("[NXBOOT]: Reading boot0...\n");
|
||||||
boot0 = fopen("boot0:/", "rb");
|
boot0 = fopen("boot0:/", "rb");
|
||||||
if (boot0 == NULL || package1_read_and_parse_boot0(&package1loader, &package1loader_size, g_keyblobs, &available_revision, boot0) == -1) {
|
if ((boot0 == NULL) || (package1_read_and_parse_boot0(&package1loader, &package1loader_size, g_keyblobs, &available_revision, boot0) == -1)) {
|
||||||
fatal_error("[NXBOOT]: Couldn't parse boot0: %s!\n", strerror(errno));
|
fatal_error("[NXBOOT]: Couldn't parse boot0: %s!\n", strerror(errno));
|
||||||
}
|
}
|
||||||
fclose(boot0);
|
fclose(boot0);
|
||||||
|
@ -146,13 +236,15 @@ void nxboot_main(void) {
|
||||||
/* Read the TSEC firmware from a file, otherwise from PK1L. */
|
/* Read the TSEC firmware from a file, otherwise from PK1L. */
|
||||||
if (loader_ctx->tsecfw_path[0] != '\0') {
|
if (loader_ctx->tsecfw_path[0] != '\0') {
|
||||||
tsec_fw_size = get_file_size(loader_ctx->tsecfw_path);
|
tsec_fw_size = get_file_size(loader_ctx->tsecfw_path);
|
||||||
if (tsec_fw_size != 0 && tsec_fw_size != 0xF00) {
|
if ((tsec_fw_size != 0) && (tsec_fw_size != 0xF00)) {
|
||||||
fatal_error("[NXBOOT]: TSEC firmware from %s has a wrong size!\n", loader_ctx->tsecfw_path);
|
fatal_error("[NXBOOT]: TSEC firmware from %s has a wrong size!\n", loader_ctx->tsecfw_path);
|
||||||
} else if (tsec_fw_size == 0) {
|
} else if (tsec_fw_size == 0) {
|
||||||
fatal_error("[NXBOOT]: Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path);
|
fatal_error("[NXBOOT]: Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Allocate memory for the TSEC firmware. */
|
||||||
tsec_fw = memalign(0x100, tsec_fw_size);
|
tsec_fw = memalign(0x100, tsec_fw_size);
|
||||||
|
|
||||||
if (tsec_fw == NULL) {
|
if (tsec_fw == NULL) {
|
||||||
fatal_error("[NXBOOT]: Out of memory!\n");
|
fatal_error("[NXBOOT]: Out of memory!\n");
|
||||||
}
|
}
|
||||||
|
@ -166,10 +258,6 @@ void nxboot_main(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Validate that we're capable of booting. */
|
|
||||||
|
|
||||||
/* TODO: Initialize Boot Reason. */
|
|
||||||
|
|
||||||
/* Find the system's target firmware. */
|
/* Find the system's target firmware. */
|
||||||
uint32_t target_firmware = nxboot_get_target_firmware(package1loader);
|
uint32_t target_firmware = nxboot_get_target_firmware(package1loader);
|
||||||
if (!target_firmware)
|
if (!target_firmware)
|
||||||
|
@ -180,6 +268,12 @@ void nxboot_main(void) {
|
||||||
/* Setup boot configuration for Exosphère. */
|
/* Setup boot configuration for Exosphère. */
|
||||||
nxboot_configure_exosphere(target_firmware);
|
nxboot_configure_exosphere(target_firmware);
|
||||||
|
|
||||||
|
/* Initialize Boot Reason on older firmware versions. */
|
||||||
|
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) {
|
||||||
|
printf("[NXBOOT]: Initializing Boot Reason...\n");
|
||||||
|
nxboot_set_bootreason();
|
||||||
|
}
|
||||||
|
|
||||||
/* Derive keydata. */
|
/* Derive keydata. */
|
||||||
if (derive_nx_keydata(MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware, g_keyblobs, available_revision, tsec_fw, tsec_fw_size) != 0) {
|
if (derive_nx_keydata(MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware, g_keyblobs, available_revision, tsec_fw, tsec_fw_size) != 0) {
|
||||||
fatal_error("[NXBOOT]: Key derivation failed!\n");
|
fatal_error("[NXBOOT]: Key derivation failed!\n");
|
||||||
|
@ -192,7 +286,9 @@ void nxboot_main(void) {
|
||||||
fatal_error("[NXBOOT]: Could not read the warmboot firmware from %s!\n", loader_ctx->warmboot_path);
|
fatal_error("[NXBOOT]: Could not read the warmboot firmware from %s!\n", loader_ctx->warmboot_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Allocate memory for the warmboot firmware. */
|
||||||
warmboot_fw = malloc(warmboot_fw_size);
|
warmboot_fw = malloc(warmboot_fw_size);
|
||||||
|
|
||||||
if (warmboot_fw == NULL) {
|
if (warmboot_fw == NULL) {
|
||||||
fatal_error("[NXBOOT]: Out of memory!\n");
|
fatal_error("[NXBOOT]: Out of memory!\n");
|
||||||
}
|
}
|
||||||
|
@ -236,32 +332,36 @@ void nxboot_main(void) {
|
||||||
/* Patch package2, adding Thermosphère + custom KIPs. */
|
/* Patch package2, adding Thermosphère + custom KIPs. */
|
||||||
package2_rebuild_and_copy(package2, MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware);
|
package2_rebuild_and_copy(package2, MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware);
|
||||||
|
|
||||||
printf(u8"Reading Exosphère...\n");
|
printf(u8"[NXBOOT]: Reading Exosphère...\n");
|
||||||
|
|
||||||
/* Select the right address for Exosphère. */
|
/* Select the right address for Exosphère. */
|
||||||
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware <= EXOSPHERE_TARGET_FIRMWARE_400) {
|
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware <= EXOSPHERE_TARGET_FIRMWARE_400) {
|
||||||
exosphere_memaddr = (void *)0x40020000;
|
exosphere_memaddr = (void *)0x4002D000;
|
||||||
} else {
|
} else {
|
||||||
exosphere_memaddr = (void *)0x40018000; /* 5.x has its secmon's crt0 around this region. */
|
exosphere_memaddr = (void *)0x4002B000;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy Exosphère to a good location or read it directly to it. */
|
/* Copy Exosphère to a good location or read it directly to it. */
|
||||||
if (loader_ctx->exosphere_path[0] != '\0') {
|
if (loader_ctx->exosphere_path[0] != '\0') {
|
||||||
size_t exosphere_size = get_file_size(loader_ctx->exosphere_path);
|
size_t exosphere_size = get_file_size(loader_ctx->exosphere_path);
|
||||||
if (exosphere_size == 0) {
|
if (exosphere_size == 0) {
|
||||||
fatal_error(u8"Could not read Exosphère from %s!\n", loader_ctx->exosphere_path);
|
fatal_error(u8"[NXBOOT]: Could not read Exosphère from %s!\n", loader_ctx->exosphere_path);
|
||||||
} else if (exosphere_size > 0x10000) {
|
} else if (exosphere_size > 0x10000) {
|
||||||
/* The maximum is actually a bit less than that. */
|
/* The maximum is actually a bit less than that. */
|
||||||
fatal_error(u8"Exosphère from %s is too big!\n", loader_ctx->exosphere_path);
|
fatal_error(u8"[NXBOOT]: Exosphère from %s is too big!\n", loader_ctx->exosphere_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (read_from_file(exosphere_memaddr, exosphere_size, loader_ctx->exosphere_path) != exosphere_size) {
|
if (read_from_file(exosphere_memaddr, exosphere_size, loader_ctx->exosphere_path) != exosphere_size) {
|
||||||
fatal_error(u8"Could not read Exosphère from %s!\n", loader_ctx->exosphere_path);
|
fatal_error(u8"[NXBOOT]: Could not read Exosphère from %s!\n", loader_ctx->exosphere_path);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
memcpy(exosphere_memaddr, exosphere_bin, exosphere_bin_size);
|
memcpy(exosphere_memaddr, exosphere_bin, exosphere_bin_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Move BootConfig. */
|
||||||
|
printf("[NXBOOT]: Moving BootConfig...\n");
|
||||||
|
nxboot_move_bootconfig();
|
||||||
|
|
||||||
/* Clean up. */
|
/* Clean up. */
|
||||||
free(package1loader);
|
free(package1loader);
|
||||||
if (loader_ctx->tsecfw_path[0] != '\0') {
|
if (loader_ctx->tsecfw_path[0] != '\0') {
|
||||||
|
@ -287,9 +387,6 @@ void nxboot_main(void) {
|
||||||
set_aes_keyslot_flags(KEYSLOT_SWITCH_4XOLDDEVICEKEY, 0xFF);
|
set_aes_keyslot_flags(KEYSLOT_SWITCH_4XOLDDEVICEKEY, 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Handle bootconfig. */
|
|
||||||
memset((void *)0x4003D000, 0, 0x3000);
|
|
||||||
|
|
||||||
/* Finalize the GPU UCODE carveout. */
|
/* Finalize the GPU UCODE carveout. */
|
||||||
mc_config_carveout_finalize();
|
mc_config_carveout_finalize();
|
||||||
|
|
||||||
|
|
|
@ -5,22 +5,26 @@
|
||||||
|
|
||||||
#define MAILBOX_NX_BOOTLOADER_BASE ((void *)(0x40002000))
|
#define MAILBOX_NX_BOOTLOADER_BASE ((void *)(0x40002000))
|
||||||
|
|
||||||
|
#define MAILBOX_NX_BOOTLOADER_BOOT_REASON (MAILBOX_NX_BOOTLOADER_BASE + 0xE10)
|
||||||
#define MAILBOX_NX_BOOTLOADER_SETUP_STATE MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + 0xEF8)
|
#define MAILBOX_NX_BOOTLOADER_SETUP_STATE MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + 0xEF8)
|
||||||
|
#define MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + 0xEFC)
|
||||||
|
|
||||||
#define NX_BOOTLOADER_STATE_INIT 0
|
#define NX_BOOTLOADER_STATE_INIT 0
|
||||||
#define NX_BOOTLOADER_STATE_MOVED_BOOTCONFIG 1
|
#define NX_BOOTLOADER_STATE_MOVED_BOOTCONFIG 1
|
||||||
|
|
||||||
#define NX_BOOTLOADER_STATE_LOADED_PACKAGE2 2
|
#define NX_BOOTLOADER_STATE_LOADED_PACKAGE2 2
|
||||||
#define NX_BOOTLOADER_STATE_FINISHED 3
|
#define NX_BOOTLOADER_STATE_FINISHED 3
|
||||||
|
|
||||||
#define NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X 2
|
#define NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X 2
|
||||||
#define NX_BOOTLOADER_STATE_LOADED_PACKAGE2_4X 3
|
#define NX_BOOTLOADER_STATE_LOADED_PACKAGE2_4X 3
|
||||||
#define NX_BOOTLOADER_STATE_FINISHED_4X 4
|
#define NX_BOOTLOADER_STATE_FINISHED_4X 4
|
||||||
|
|
||||||
/* Physaddr 0x40002EFC */
|
typedef struct {
|
||||||
#define MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + 0xEFC)
|
uint32_t bootloader_version;
|
||||||
|
uint32_t bootloader_start_block;
|
||||||
#define MAILBOX_NX_BOOTLOADER_BOOT_REASON (MAILBOX_NX_BOOTLOADER_BASE + 0xE10)
|
uint32_t bootloader_start_page;
|
||||||
|
uint32_t bootloader_attribute;
|
||||||
|
uint32_t boot_reason_value;
|
||||||
|
uint32_t boot_reason_state;
|
||||||
|
} boot_reason_t;
|
||||||
|
|
||||||
void nxboot_main(void);
|
void nxboot_main(void);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue