This commit is contained in:
Resaec 2018-09-05 05:56:06 +02:00
commit d8451eb804
27 changed files with 430 additions and 151 deletions

View file

@ -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);
} }

View file

@ -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);

View file

@ -9,9 +9,25 @@
#define SYSCTR0_BASE (MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_SYSCTR0)) #define SYSCTR0_BASE (MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_SYSCTR0))
#define MAKE_SYSCTR0_REG(n) MAKE_REG32(SYSCTR0_BASE + n) #define MAKE_SYSCTR0_REG(n) MAKE_REG32(SYSCTR0_BASE + n)
#define SYSCTR0_CNTCR_0 MAKE_SYSCTR0_REG(0x00)
#define SYSCTR0_CNTSR_0 MAKE_SYSCTR0_REG(0x04)
#define SYSCTR0_CNTCV0_0 MAKE_SYSCTR0_REG(0x08)
#define SYSCTR0_CNTCV1_0 MAKE_SYSCTR0_REG(0x0C)
#define SYSCTR0_CNTFID0_0 MAKE_SYSCTR0_REG(0x20)
#define SYSCTR0_CNTFID1_0 MAKE_SYSCTR0_REG(0x24)
#define SYSCTR0_COUNTERID4_0 MAKE_SYSCTR0_REG(0xFD0)
#define SYSCTR0_COUNTERID5_0 MAKE_SYSCTR0_REG(0xFD4)
#define SYSCTR0_COUNTERID6_0 MAKE_SYSCTR0_REG(0xFD8)
#define SYSCTR0_COUNTERID7_0 MAKE_SYSCTR0_REG(0xFDC)
#define SYSCTR0_COUNTERID0_0 MAKE_SYSCTR0_REG(0xFE0)
#define SYSCTR0_COUNTERID1_0 MAKE_SYSCTR0_REG(0xFE4)
#define SYSCTR0_COUNTERID2_0 MAKE_SYSCTR0_REG(0xFE8)
#define SYSCTR0_COUNTERID3_0 MAKE_SYSCTR0_REG(0xFEC)
#define SYSCTR0_COUNTERID8_0 MAKE_SYSCTR0_REG(0xFF0)
#define SYSCTR0_COUNTERID9_0 MAKE_SYSCTR0_REG(0xFF4)
#define SYSCTR0_COUNTERID10_0 MAKE_SYSCTR0_REG(0xFF8)
#define SYSCTR0_COUNTERID11_0 MAKE_SYSCTR0_REG(0xFFC)
#endif #endif

View file

@ -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;

View file

@ -224,16 +224,16 @@ typedef struct {
uint32_t clk_cpu_cmplx_clr; /* _CLK_CPU_CMPLX_SET_0, 0x34c */ uint32_t clk_cpu_cmplx_clr; /* _CLK_CPU_CMPLX_SET_0, 0x34c */
uint32_t _0x350[2]; uint32_t _0x350[2];
uint32_t rst_dev_v; /* _RST_DEVICES_V/W_0 */ uint32_t rst_dev_v; /* _RST_DEVICES_V_0, 0x358 */
uint32_t rst_dev_w; /* _RST_DEVICES_V/W_0 */ uint32_t rst_dev_w; /* _RST_DEVICES_W_0, 0x35c */
uint32_t clk_out_enb_v; /* _CLK_OUT_ENB_V/W_0 */ uint32_t clk_out_enb_v; /* _CLK_OUT_ENB_V_0, 0x360 */
uint32_t clk_out_enb_w; /* _CLK_OUT_ENB_V/W_0 */ uint32_t clk_out_enb_w; /* _CLK_OUT_ENB_W_0, 0x364 */
uint32_t cclkg_brst_pol; /* _CCLKG_BURST_POLICY_0, 0x368 */ uint32_t cclkg_brst_pol; /* _CCLKG_BURST_POLICY_0, 0x368 */
uint32_t super_cclkg_div; /* _SUPER_CCLKG_DIVIDER_0, 0x36C */ uint32_t super_cclkg_div; /* _SUPER_CCLKG_DIVIDER_0, 0x36c */
uint32_t cclklp_brst_pol; /* _CCLKLP_BURST_POLICY_0, 0x370 */ uint32_t cclklp_brst_pol; /* _CCLKLP_BURST_POLICY_0, 0x370 */
uint32_t super_cclkp_div; /* _SUPER_CCLKLP_DIVIDER_0, 0x374 */ uint32_t super_cclkp_div; /* _SUPER_CCLKLP_DIVIDER_0, 0x374 */
uint32_t clk_cpug_cmplx; /* _CLK_CPUG_CMPLX_0, 0x378 */ uint32_t clk_cpug_cmplx; /* _CLK_CPUG_CMPLX_0, 0x378 */
uint32_t clk_cpulp_cmplx; /* _CLK_CPULP_CMPLX_0, 0x37C */ uint32_t clk_cpulp_cmplx; /* _CLK_CPULP_CMPLX_0, 0x37c */
uint32_t cpu_softrst_ctrl; /* _CPU_SOFTRST_CTRL_0, 0x380 */ uint32_t cpu_softrst_ctrl; /* _CPU_SOFTRST_CTRL_0, 0x380 */
uint32_t cpu_softrst_ctrl1; /* _CPU_SOFTRST_CTRL1_0, 0x384 */ uint32_t cpu_softrst_ctrl1; /* _CPU_SOFTRST_CTRL1_0, 0x384 */
uint32_t cpu_softrst_ctrl2; /* _CPU_SOFTRST_CTRL2_0, 0x388 */ uint32_t cpu_softrst_ctrl2; /* _CPU_SOFTRST_CTRL2_0, 0x388 */
@ -456,6 +456,7 @@ typedef struct {
uint32_t tsecb_super_clk_divider; /* _TSECB_SUPER_CLK_DIVIDER_0, 0x70c */ uint32_t tsecb_super_clk_divider; /* _TSECB_SUPER_CLK_DIVIDER_0, 0x70c */
uint32_t clk_source_uartape; /* _CLK_SOURCE_UARTAPE_0, 0x710 */ uint32_t clk_source_uartape; /* _CLK_SOURCE_UARTAPE_0, 0x710 */
uint32_t clk_cpug_misc2; /* _CLK_CPUG_MISC2_0, 0x714 */
uint32_t clk_source_dbgapb; /* _CLK_SOURCE_DBGAPB_0, 0x718 */ uint32_t clk_source_dbgapb; /* _CLK_SOURCE_DBGAPB_0, 0x718 */
uint32_t clk_ccplex_cc4_ret_clk_enb; /* _CLK_CCPLEX_CC4_RET_CLK_ENB_0, 0x71c */ uint32_t clk_ccplex_cc4_ret_clk_enb; /* _CLK_CCPLEX_CC4_RET_CLK_ENB_0, 0x71c */
uint32_t actmon_cpu_clk; /* _ACTMON_CPU_CLK_0, 0x720 */ uint32_t actmon_cpu_clk; /* _ACTMON_CPU_CLK_0, 0x720 */

View file

@ -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;

View file

@ -47,6 +47,12 @@ void unmount_sd(void)
sdmmc_device_finish(&g_sd_device); sdmmc_device_finish(&g_sd_device);
g_sd_mounted = false; g_sd_mounted = false;
} }
/* Disable AHB redirection if necessary. */
if (g_ahb_redirect_enabled) {
mc_disable_ahb_redirect();
g_ahb_redirect_enabled = false;
}
} }
uint32_t get_file_size(const char *filename) uint32_t get_file_size(const char *filename)

View file

@ -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();

View file

@ -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();

View file

@ -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;

View file

@ -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

View file

@ -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);
} }

View file

@ -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);

View file

@ -3,9 +3,26 @@
#include <stdint.h> #include <stdint.h>
#define SYSCTR0_BASE 0x7000F000 #define SYSCTR0_BASE 0x700F0000
#define MAKE_SYSCTR0_REG(n) MAKE_REG32(SYSCTR0_BASE + n) #define MAKE_SYSCTR0_REG(n) MAKE_REG32(SYSCTR0_BASE + n)
#define SYSCTR0_CNTCR_0 MAKE_SYSCTR0_REG(0x00)
#define SYSCTR0_CNTSR_0 MAKE_SYSCTR0_REG(0x04)
#define SYSCTR0_CNTCV0_0 MAKE_SYSCTR0_REG(0x08)
#define SYSCTR0_CNTCV1_0 MAKE_SYSCTR0_REG(0x0C)
#define SYSCTR0_CNTFID0_0 MAKE_SYSCTR0_REG(0x20) #define SYSCTR0_CNTFID0_0 MAKE_SYSCTR0_REG(0x20)
#define SYSCTR0_CNTFID1_0 MAKE_SYSCTR0_REG(0x24)
#define SYSCTR0_COUNTERID4_0 MAKE_SYSCTR0_REG(0xFD0)
#define SYSCTR0_COUNTERID5_0 MAKE_SYSCTR0_REG(0xFD4)
#define SYSCTR0_COUNTERID6_0 MAKE_SYSCTR0_REG(0xFD8)
#define SYSCTR0_COUNTERID7_0 MAKE_SYSCTR0_REG(0xFDC)
#define SYSCTR0_COUNTERID0_0 MAKE_SYSCTR0_REG(0xFE0)
#define SYSCTR0_COUNTERID1_0 MAKE_SYSCTR0_REG(0xFE4)
#define SYSCTR0_COUNTERID2_0 MAKE_SYSCTR0_REG(0xFE8)
#define SYSCTR0_COUNTERID3_0 MAKE_SYSCTR0_REG(0xFEC)
#define SYSCTR0_COUNTERID8_0 MAKE_SYSCTR0_REG(0xFF0)
#define SYSCTR0_COUNTERID9_0 MAKE_SYSCTR0_REG(0xFF4)
#define SYSCTR0_COUNTERID10_0 MAKE_SYSCTR0_REG(0xFF8)
#define SYSCTR0_COUNTERID11_0 MAKE_SYSCTR0_REG(0xFFC)
#endif #endif

View file

@ -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;

View file

@ -224,16 +224,16 @@ typedef struct {
uint32_t clk_cpu_cmplx_clr; /* _CLK_CPU_CMPLX_SET_0, 0x34c */ uint32_t clk_cpu_cmplx_clr; /* _CLK_CPU_CMPLX_SET_0, 0x34c */
uint32_t _0x350[2]; uint32_t _0x350[2];
uint32_t rst_dev_v; /* _RST_DEVICES_V/W_0 */ uint32_t rst_dev_v; /* _RST_DEVICES_V_0, 0x358 */
uint32_t rst_dev_w; /* _RST_DEVICES_V/W_0 */ uint32_t rst_dev_w; /* _RST_DEVICES_W_0, 0x35c */
uint32_t clk_out_enb_v; /* _CLK_OUT_ENB_V/W_0 */ uint32_t clk_out_enb_v; /* _CLK_OUT_ENB_V_0, 0x360 */
uint32_t clk_out_enb_w; /* _CLK_OUT_ENB_V/W_0 */ uint32_t clk_out_enb_w; /* _CLK_OUT_ENB_W_0, 0x364 */
uint32_t cclkg_brst_pol; /* _CCLKG_BURST_POLICY_0, 0x368 */ uint32_t cclkg_brst_pol; /* _CCLKG_BURST_POLICY_0, 0x368 */
uint32_t super_cclkg_div; /* _SUPER_CCLKG_DIVIDER_0, 0x36C */ uint32_t super_cclkg_div; /* _SUPER_CCLKG_DIVIDER_0, 0x36c */
uint32_t cclklp_brst_pol; /* _CCLKLP_BURST_POLICY_0, 0x370 */ uint32_t cclklp_brst_pol; /* _CCLKLP_BURST_POLICY_0, 0x370 */
uint32_t super_cclkp_div; /* _SUPER_CCLKLP_DIVIDER_0, 0x374 */ uint32_t super_cclkp_div; /* _SUPER_CCLKLP_DIVIDER_0, 0x374 */
uint32_t clk_cpug_cmplx; /* _CLK_CPUG_CMPLX_0, 0x378 */ uint32_t clk_cpug_cmplx; /* _CLK_CPUG_CMPLX_0, 0x378 */
uint32_t clk_cpulp_cmplx; /* _CLK_CPULP_CMPLX_0, 0x37C */ uint32_t clk_cpulp_cmplx; /* _CLK_CPULP_CMPLX_0, 0x37c */
uint32_t cpu_softrst_ctrl; /* _CPU_SOFTRST_CTRL_0, 0x380 */ uint32_t cpu_softrst_ctrl; /* _CPU_SOFTRST_CTRL_0, 0x380 */
uint32_t cpu_softrst_ctrl1; /* _CPU_SOFTRST_CTRL1_0, 0x384 */ uint32_t cpu_softrst_ctrl1; /* _CPU_SOFTRST_CTRL1_0, 0x384 */
uint32_t cpu_softrst_ctrl2; /* _CPU_SOFTRST_CTRL2_0, 0x388 */ uint32_t cpu_softrst_ctrl2; /* _CPU_SOFTRST_CTRL2_0, 0x388 */
@ -456,6 +456,7 @@ typedef struct {
uint32_t tsecb_super_clk_divider; /* _TSECB_SUPER_CLK_DIVIDER_0, 0x70c */ uint32_t tsecb_super_clk_divider; /* _TSECB_SUPER_CLK_DIVIDER_0, 0x70c */
uint32_t clk_source_uartape; /* _CLK_SOURCE_UARTAPE_0, 0x710 */ uint32_t clk_source_uartape; /* _CLK_SOURCE_UARTAPE_0, 0x710 */
uint32_t clk_cpug_misc2; /* _CLK_CPUG_MISC2_0, 0x714 */
uint32_t clk_source_dbgapb; /* _CLK_SOURCE_DBGAPB_0, 0x718 */ uint32_t clk_source_dbgapb; /* _CLK_SOURCE_DBGAPB_0, 0x718 */
uint32_t clk_ccplex_cc4_ret_clk_enb; /* _CLK_CCPLEX_CC4_RET_CLK_ENB_0, 0x71c */ uint32_t clk_ccplex_cc4_ret_clk_enb; /* _CLK_CCPLEX_CC4_RET_CLK_ENB_0, 0x71c */
uint32_t actmon_cpu_clk; /* _ACTMON_CPU_CLK_0, 0x720 */ uint32_t actmon_cpu_clk; /* _ACTMON_CPU_CLK_0, 0x720 */

View file

@ -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)
@ -77,12 +77,12 @@ void cluster_boot_cpu0(uint32_t entry)
udelay(2); udelay(2);
car->pllx_base = 0x80404E02; car->pllx_base = 0x80404E02;
car->pllx_base = 0x404E02; car->pllx_base = 0x404E02;
car->pllx_misc = ((car->pllx_base & 0xFFFBFFFF) | 0x40000); car->pllx_misc = ((car->pllx_misc & 0xFFFBFFFF) | 0x40000);
car->pllx_base = 0x40404E02; car->pllx_base = 0x40404E02;
} }
while (!(car->pllx_base & 0x8000000)) { while (!(car->pllx_base & 0x8000000)) {
/* Spinlock. */ /* Wait. */
} }
/* Configure MSELECT source and enable clock. */ /* Configure MSELECT source and enable clock. */
@ -111,13 +111,13 @@ void cluster_boot_cpu0(uint32_t entry)
/* Request and wait for RAM repair. */ /* Request and wait for RAM repair. */
FLOW_CTLR_RAM_REPAIR_0 = 1; FLOW_CTLR_RAM_REPAIR_0 = 1;
while (!(FLOW_CTLR_RAM_REPAIR_0 & 2)){ while (!(FLOW_CTLR_RAM_REPAIR_0 & 2)){
/* Spinlock. */ /* Wait. */
} }
MAKE_EXCP_VEC_REG(0x100) = 0; MAKE_EXCP_VEC_REG(0x100) = 0;
/* Set reset vector. */ /* Set reset vector. */
SB_AA64_RESET_LOW_0 = entry | 1; SB_AA64_RESET_LOW_0 = (entry | 1);
SB_AA64_RESET_HIGH_0 = 0; SB_AA64_RESET_HIGH_0 = 0;
/* Non-secure reset vector write disable. */ /* Non-secure reset vector write disable. */

View file

@ -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;

View file

@ -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();

View file

@ -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;

View file

@ -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

View file

@ -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);
} }

View file

@ -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");
} }
@ -165,10 +257,6 @@ void nxboot_main(void) {
fatal_error("[NXBOOT]: Failed to read the TSEC firmware from Package1loader!\n"); fatal_error("[NXBOOT]: Failed to read the TSEC firmware from Package1loader!\n");
} }
} }
/* 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);
@ -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,45 @@ 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();
/* Set 3.0.0/3.0.1/3.0.2 warmboot security check. */
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware == EXOSPHERE_TARGET_FIRMWARE_300) {
const package1loader_header_t *package1loader_header = (const package1loader_header_t *)package1loader;
if (!strcmp(package1loader_header->build_timestamp, "20170519101410"))
pmc->secure_scratch32 = 0xE3; /* Warmboot 3.0.0 security check.*/
else if (!strcmp(package1loader_header->build_timestamp, "20170710161758"))
pmc->secure_scratch32 = 0x104; /* Warmboot 3.0.1/3.0.2 security check. */
}
/* Clean up. */ /* Clean up. */
free(package1loader); free(package1loader);
if (loader_ctx->tsecfw_path[0] != '\0') { if (loader_ctx->tsecfw_path[0] != '\0') {
@ -272,9 +381,6 @@ void nxboot_main(void) {
} }
free(package2); free(package2);
/* Unmount everything. */
nxfs_unmount_all();
/* Clear used keyslots. */ /* Clear used keyslots. */
clear_aes_keyslot(KEYSLOT_SWITCH_PACKAGE2KEY); clear_aes_keyslot(KEYSLOT_SWITCH_PACKAGE2KEY);
clear_aes_keyslot(KEYSLOT_SWITCH_RNGKEY); clear_aes_keyslot(KEYSLOT_SWITCH_RNGKEY);
@ -287,9 +393,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();
@ -320,6 +423,9 @@ void nxboot_main(void) {
/* Display splash screen. */ /* Display splash screen. */
display_splash_screen_bmp(loader_ctx->custom_splash_path); display_splash_screen_bmp(loader_ctx->custom_splash_path);
/* Unmount everything. */
nxfs_unmount_all();
/* Turn off the backlight. */ /* Turn off the backlight. */
display_backlight(false); display_backlight(false);
@ -327,7 +433,7 @@ void nxboot_main(void) {
display_end(); display_end();
/* Boot CPU0. */ /* Boot CPU0. */
cluster_boot_cpu0((uint64_t)(uintptr_t)exosphere_memaddr); cluster_boot_cpu0((uint32_t)exosphere_memaddr);
/* Wait for Exosphère to wake up. */ /* Wait for Exosphère to wake up. */
while (MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE == 0) { while (MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE == 0) {

View file

@ -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);

View file

@ -48,6 +48,7 @@ static int mmc_partition_initialize(device_partition_t *devpart) {
devpart->crypto_work_buffer_num_sectors = 0; devpart->crypto_work_buffer_num_sectors = 0;
} }
/* Enable AHB redirection if necessary. */
if (!g_ahb_redirect_enabled) { if (!g_ahb_redirect_enabled) {
mc_enable_ahb_redirect(); mc_enable_ahb_redirect();
g_ahb_redirect_enabled = true; g_ahb_redirect_enabled = true;
@ -78,6 +79,12 @@ static int mmc_partition_initialize(device_partition_t *devpart) {
static void mmc_partition_finalize(device_partition_t *devpart) { static void mmc_partition_finalize(device_partition_t *devpart) {
free(devpart->crypto_work_buffer); free(devpart->crypto_work_buffer);
/* Disable AHB redirection if necessary. */
if (g_ahb_redirect_enabled) {
mc_disable_ahb_redirect();
g_ahb_redirect_enabled = false;
}
} }
static int mmc_partition_read(device_partition_t *devpart, void *dst, uint64_t sector, uint64_t num_sectors) { static int mmc_partition_read(device_partition_t *devpart, void *dst, uint64_t sector, uint64_t num_sectors) {

View file

@ -1,5 +1,4 @@
#include <stdio.h> #include <stdio.h>
#include "utils.h"
#include "timers.h" #include "timers.h"
#include "splash_screen.h" #include "splash_screen.h"
#include "fs_utils.h" #include "fs_utils.h"
@ -7,7 +6,7 @@
void display_splash_screen_bmp(const char *custom_splash_path) { void display_splash_screen_bmp(const char *custom_splash_path) {
uint8_t *splash_screen = g_default_splash_screen; uint8_t *splash_screen = g_default_splash_screen;
if (custom_splash_path != NULL && custom_splash_path[0] != '\x00') { if ((custom_splash_path != NULL) && (custom_splash_path[0] != '\x00')) {
if (!read_from_file(splash_screen, sizeof(g_default_splash_screen), custom_splash_path)) { if (!read_from_file(splash_screen, sizeof(g_default_splash_screen), custom_splash_path)) {
fatal_error("Failed to read custom splash screen from %s!\n", custom_splash_path); fatal_error("Failed to read custom splash screen from %s!\n", custom_splash_path);
} }
@ -16,5 +15,5 @@ void display_splash_screen_bmp(const char *custom_splash_path) {
/* TODO: Display the splash screen. It should be a pointer to a BMP, at this point. */ /* TODO: Display the splash screen. It should be a pointer to a BMP, at this point. */
/* Display the splash screen for three seconds. */ /* Display the splash screen for three seconds. */
wait(3000000); /* udelay(3000000); */
} }

View file

@ -19,6 +19,11 @@
static ini1_header_t *g_stratosphere_ini1 = NULL; static ini1_header_t *g_stratosphere_ini1 = NULL;
static bool g_stratosphere_loader_enabled = true;
static bool g_stratosphere_sm_enabled = true;
static bool g_stratosphere_pm_enabled = true;
static bool g_stratosphere_boot_enabled = false;
extern const uint8_t boot_100_kip[], boot_200_kip[]; extern const uint8_t boot_100_kip[], boot_200_kip[];
extern const uint8_t loader_kip[], pm_kip[], sm_kip[]; extern const uint8_t loader_kip[], pm_kip[], sm_kip[];
extern const uint32_t boot_100_kip_size, boot_200_kip_size; extern const uint32_t boot_100_kip_size, boot_200_kip_size;
@ -27,8 +32,9 @@ extern const uint32_t loader_kip_size, pm_kip_size, sm_kip_size;
/* GCC doesn't consider the size as const... we have to write it ourselves. */ /* GCC doesn't consider the size as const... we have to write it ourselves. */
ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware) { ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware) {
/* const uint8_t *boot_kip = NULL; */ const uint8_t *boot_kip = NULL;
uint32_t boot_kip_size = 0; uint32_t boot_kip_size = 0;
uint32_t num_processes = 0;
uint8_t *data; uint8_t *data;
if (g_stratosphere_ini1 != NULL) { if (g_stratosphere_ini1 != NULL) {
@ -36,14 +42,36 @@ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware) {
} }
if (target_firmware <= EXOSPHERE_TARGET_FIRMWARE_100) { if (target_firmware <= EXOSPHERE_TARGET_FIRMWARE_100) {
/* boot_kip = boot_100_kip; */ boot_kip = boot_100_kip;
boot_kip_size = boot_100_kip_size; boot_kip_size = boot_100_kip_size;
} else { } else {
/* boot_kip = boot_200_kip; */ boot_kip = boot_200_kip;
boot_kip_size = boot_200_kip_size; boot_kip_size = boot_200_kip_size;
} }
size_t size = sizeof(ini1_header_t) + loader_kip_size + pm_kip_size + sm_kip_size + boot_kip_size; size_t size = sizeof(ini1_header_t);
/* Calculate our processes' sizes. */
if (g_stratosphere_loader_enabled) {
size += loader_kip_size;
num_processes++;
}
if (g_stratosphere_pm_enabled) {
size += pm_kip_size;
num_processes++;
}
if (g_stratosphere_sm_enabled) {
size += sm_kip_size;
num_processes++;
}
if (g_stratosphere_boot_enabled) {
size += boot_kip_size;
num_processes++;
}
g_stratosphere_ini1 = (ini1_header_t *)malloc(size); g_stratosphere_ini1 = (ini1_header_t *)malloc(size);
if (g_stratosphere_ini1 == NULL) { if (g_stratosphere_ini1 == NULL) {
@ -52,26 +80,31 @@ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware) {
g_stratosphere_ini1->magic = MAGIC_INI1; g_stratosphere_ini1->magic = MAGIC_INI1;
g_stratosphere_ini1->size = size; g_stratosphere_ini1->size = size;
g_stratosphere_ini1->num_processes = 3; /*TODO: Change to 4 when boot is supported. */ g_stratosphere_ini1->num_processes = num_processes;
g_stratosphere_ini1->_0xC = 0; g_stratosphere_ini1->_0xC = 0;
data = g_stratosphere_ini1->kip_data; data = g_stratosphere_ini1->kip_data;
/* Copy our processes. */ /* Copy our processes. */
memcpy(data, loader_kip, loader_kip_size); if (g_stratosphere_loader_enabled) {
data += loader_kip_size; memcpy(data, loader_kip, loader_kip_size);
data += loader_kip_size;
}
memcpy(data, pm_kip, pm_kip_size); if (g_stratosphere_pm_enabled) {
data += pm_kip_size; memcpy(data, pm_kip, pm_kip_size);
data += pm_kip_size;
}
memcpy(data, sm_kip, sm_kip_size); if (g_stratosphere_sm_enabled) {
data += sm_kip_size; memcpy(data, sm_kip, sm_kip_size);
data += sm_kip_size;
}
/* TODO: Uncomment when boot is supported. */ if (g_stratosphere_boot_enabled) {
/* memcpy(data, boot_kip, boot_kip_size);
memcpy(data, boot_kip, boot_kip_size); data += boot_kip_size;
data += boot_kip_size; }
*/
return g_stratosphere_ini1; return g_stratosphere_ini1;
} }