From 611e85e6eee068cad226fdf58e9794a0cbfc4f02 Mon Sep 17 00:00:00 2001 From: hexkyz Date: Wed, 29 Aug 2018 18:28:21 +0100 Subject: [PATCH] fusee: Implement BootConfig and Boot Reason handling. --- exosphere/src/bootconfig.c | 4 +- exosphere/src/bootconfig.h | 11 ++- fusee/fusee-primary/src/btn.c | 2 +- fusee/fusee-primary/src/di.c | 4 +- fusee/fusee-primary/src/hwinit.c | 26 ++--- fusee/fusee-primary/src/i2c.c | 26 ++--- fusee/fusee-primary/src/i2c.h | 14 +++ fusee/fusee-primary/src/max77620.h | 30 ++++++ fusee/fusee-primary/src/max7762x.c | 20 ++-- fusee/fusee-primary/src/sdram.c | 4 +- fusee/fusee-secondary/src/btn.c | 2 +- fusee/fusee-secondary/src/cluster.c | 14 +-- fusee/fusee-secondary/src/di.c | 4 +- fusee/fusee-secondary/src/i2c.c | 26 ++--- fusee/fusee-secondary/src/i2c.h | 14 +++ fusee/fusee-secondary/src/max77620.h | 30 ++++++ fusee/fusee-secondary/src/max7762x.c | 20 ++-- fusee/fusee-secondary/src/nxboot.c | 141 ++++++++++++++++++++++----- fusee/fusee-secondary/src/nxboot.h | 16 +-- 19 files changed, 299 insertions(+), 109 deletions(-) diff --git a/exosphere/src/bootconfig.c b/exosphere/src/bootconfig.c index dd2cfd870..afa1f7e20 100644 --- a/exosphere/src/bootconfig.c +++ b/exosphere/src/bootconfig.c @@ -138,9 +138,9 @@ void bootconfig_get_package2_hash_for_recovery(uint64_t *out_hash) { } 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) { - 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); } diff --git a/exosphere/src/bootconfig.h b/exosphere/src/bootconfig.h index 823323a03..e2e410ade 100644 --- a/exosphere/src/bootconfig.h +++ b/exosphere/src/bootconfig.h @@ -34,11 +34,12 @@ static inline bootconfig_t *get_loaded_bootconfig(void) { } typedef struct { - uint64_t _0x00; - uint32_t _0x08; - uint32_t is_recovery_boot; - uint32_t boot_reason_low; - uint32_t boot_reason_high; + uint32_t bootloader_version; + uint32_t bootloader_start_block; + uint32_t bootloader_start_page; + uint32_t bootloader_attribute; + uint32_t boot_reason_value; + uint32_t boot_reason_state; } boot_reason_t; void bootconfig_load_and_verify(const bootconfig_t *bootconfig); diff --git a/fusee/fusee-primary/src/btn.c b/fusee/fusee-primary/src/btn.c index bffc8e79d..942d27be6 100644 --- a/fusee/fusee-primary/src/btn.c +++ b/fusee/fusee-primary/src/btn.c @@ -16,7 +16,7 @@ uint32_t btn_read() res |= BTN_VOL_UP; 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) res |= BTN_POWER; diff --git a/fusee/fusee-primary/src/di.c b/fusee/fusee-primary/src/di.c index e22257465..f46310eb8 100644 --- a/fusee/fusee-primary/src/di.c +++ b/fusee/fusee-primary/src/di.c @@ -36,9 +36,9 @@ void display_init() /* Power on. */ 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; - 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. */ car->rst_dev_h_clr = 0x1010000; diff --git a/fusee/fusee-primary/src/hwinit.c b/fusee/fusee-primary/src/hwinit.c index 903b750bd..929136d38 100644 --- a/fusee/fusee-primary/src/hwinit.c +++ b/fusee/fusee-primary/src/hwinit.c @@ -203,33 +203,33 @@ void nx_hwinit() clkrst_reboot(CARDEVICE_UNK); /* Initialize I2C1 and I2C5. */ - i2c_init(0); - i2c_init(4); + i2c_init(I2C_1); + i2c_init(I2C_5); 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; - i2c_send(4, 0x3C, MAX77620_REG_ONOFFCNFG1, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, &val, 1); 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; - 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; - 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; - 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; - 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; - 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; - 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; - 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 */ - 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. */ config_pmc_scratch(); diff --git a/fusee/fusee-primary/src/i2c.c b/fusee/fusee-primary/src/i2c.c index a98d7fa6e..028ba56e8 100644 --- a/fusee/fusee-primary/src/i2c.c +++ b/fusee/fusee-primary/src/i2c.c @@ -43,16 +43,16 @@ void i2c_init(unsigned int id) { void i2c_send_pmic_cpu_shutdown_cmd(void) { uint32_t val = 0; /* PMIC == Device 4:3C. */ - i2c_query(4, 0x3C, 0x41, &val, 1); + i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, 0x41, &val, 1); 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. */ bool i2c_query_ti_charger_bit_7(void) { uint32_t val = 0; /* 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; } @@ -60,34 +60,34 @@ bool i2c_query_ti_charger_bit_7(void) { void i2c_clear_ti_charger_bit_7(void) { uint32_t val = 0; /* TI Charger = Device 0:6B. */ - i2c_query(0, 0x6B, 0, &val, 1); + i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); 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. */ void i2c_set_ti_charger_bit_7(void) { uint32_t val = 0; /* TI Charger = Device 0:6B. */ - i2c_query(0, 0x6B, 0, &val, 1); + i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); 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. */ volatile tegra_i2c_t *i2c_get_registers_from_id(unsigned int id) { switch (id) { - case 0: + case I2C_1: return I2C1_REGS; - case 1: + case I2C_2: return I2C2_REGS; - case 2: + case I2C_3: return I2C3_REGS; - case 3: + case I2C_4: return I2C4_REGS; - case 4: + case I2C_5: return I2C5_REGS; - case 5: + case I2C_6: return I2C6_REGS; default: generic_panic(); diff --git a/fusee/fusee-primary/src/i2c.h b/fusee/fusee-primary/src/i2c.h index e07ed3349..8b0acbd35 100644 --- a/fusee/fusee-primary/src/i2c.h +++ b/fusee/fusee-primary/src/i2c.h @@ -8,6 +8,20 @@ #define I2C234_BASE 0x7000C000 #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 { uint32_t I2C_I2C_CNFG_0; uint32_t I2C_I2C_CMD_ADDR0_0; diff --git a/fusee/fusee-primary/src/max77620.h b/fusee/fusee-primary/src/max77620.h index ad22a06b5..ab90f2b8e 100644 --- a/fusee/fusee-primary/src/max77620.h +++ b/fusee/fusee-primary/src/max77620.h @@ -11,6 +11,36 @@ #ifndef _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 */ #define MAX77620_REG_CNFGGLBL1 0x00 #define MAX77620_REG_CNFGGLBL2 0x01 diff --git a/fusee/fusee-primary/src/max7762x.c b/fusee/fusee-primary/src/max7762x.c index 419a13bce..da20eb7b9 100644 --- a/fusee/fusee-primary/src/max7762x.c +++ b/fusee/fusee-primary/src/max7762x.c @@ -55,11 +55,11 @@ int max77620_regulator_get_status(uint32_t id) uint8_t val = 0; 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; } - 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 0; @@ -73,7 +73,7 @@ int max77620_regulator_config_fps(uint32_t id) const max77620_regulator_t *reg = &_pmic_regulators[id]; 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; } @@ -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; 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)); - 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); 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; 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) val = ((val & ~reg->enable_mask) | ((3 << reg->enable_shift) & reg->enable_mask)); else 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); return 1; @@ -139,7 +139,7 @@ void max77620_config_default() for (uint32_t i = 1; i <= REGULATOR_MAX; i++) { 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_set_voltage(i, _pmic_regulators[i].mv_default); @@ -151,11 +151,11 @@ void max77620_config_default() } 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() { 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); } diff --git a/fusee/fusee-primary/src/sdram.c b/fusee/fusee-primary/src/sdram.c index eb941f235..135833eea 100644 --- a/fusee/fusee-primary/src/sdram.c +++ b/fusee/fusee-primary/src/sdram.c @@ -542,9 +542,9 @@ void sdram_init() const sdram_params_t *params = (const sdram_params_t *)sdram_get_params(); 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 */ - 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; udelay(params->pmc_vddp_sel_wait); diff --git a/fusee/fusee-secondary/src/btn.c b/fusee/fusee-secondary/src/btn.c index bffc8e79d..942d27be6 100644 --- a/fusee/fusee-secondary/src/btn.c +++ b/fusee/fusee-secondary/src/btn.c @@ -16,7 +16,7 @@ uint32_t btn_read() res |= BTN_VOL_UP; 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) res |= BTN_POWER; diff --git a/fusee/fusee-secondary/src/cluster.c b/fusee/fusee-secondary/src/cluster.c index bceaf7d73..b0c884670 100644 --- a/fusee/fusee-secondary/src/cluster.c +++ b/fusee/fusee-secondary/src/cluster.c @@ -12,22 +12,22 @@ void _cluster_enable_power() { 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; - 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; - i2c_send(4, 0x3C, MAX77620_REG_GPIO5, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_GPIO5, &val, 1); /* Enable power. */ val = 0x20; - i2c_send(4, 0x1B, MAX77620_REG_CNFGGLBL3, &val, 1); + i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x02, &val, 1); 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; - i2c_send(4, 0x1B, MAX77620_REG_CNFGGLBL1, &val, 1); + i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x00, &val, 1); 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) diff --git a/fusee/fusee-secondary/src/di.c b/fusee/fusee-secondary/src/di.c index e22257465..f46310eb8 100644 --- a/fusee/fusee-secondary/src/di.c +++ b/fusee/fusee-secondary/src/di.c @@ -36,9 +36,9 @@ void display_init() /* Power on. */ 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; - 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. */ car->rst_dev_h_clr = 0x1010000; diff --git a/fusee/fusee-secondary/src/i2c.c b/fusee/fusee-secondary/src/i2c.c index a98d7fa6e..028ba56e8 100644 --- a/fusee/fusee-secondary/src/i2c.c +++ b/fusee/fusee-secondary/src/i2c.c @@ -43,16 +43,16 @@ void i2c_init(unsigned int id) { void i2c_send_pmic_cpu_shutdown_cmd(void) { uint32_t val = 0; /* PMIC == Device 4:3C. */ - i2c_query(4, 0x3C, 0x41, &val, 1); + i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, 0x41, &val, 1); 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. */ bool i2c_query_ti_charger_bit_7(void) { uint32_t val = 0; /* 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; } @@ -60,34 +60,34 @@ bool i2c_query_ti_charger_bit_7(void) { void i2c_clear_ti_charger_bit_7(void) { uint32_t val = 0; /* TI Charger = Device 0:6B. */ - i2c_query(0, 0x6B, 0, &val, 1); + i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); 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. */ void i2c_set_ti_charger_bit_7(void) { uint32_t val = 0; /* TI Charger = Device 0:6B. */ - i2c_query(0, 0x6B, 0, &val, 1); + i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); 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. */ volatile tegra_i2c_t *i2c_get_registers_from_id(unsigned int id) { switch (id) { - case 0: + case I2C_1: return I2C1_REGS; - case 1: + case I2C_2: return I2C2_REGS; - case 2: + case I2C_3: return I2C3_REGS; - case 3: + case I2C_4: return I2C4_REGS; - case 4: + case I2C_5: return I2C5_REGS; - case 5: + case I2C_6: return I2C6_REGS; default: generic_panic(); diff --git a/fusee/fusee-secondary/src/i2c.h b/fusee/fusee-secondary/src/i2c.h index e07ed3349..8b0acbd35 100644 --- a/fusee/fusee-secondary/src/i2c.h +++ b/fusee/fusee-secondary/src/i2c.h @@ -8,6 +8,20 @@ #define I2C234_BASE 0x7000C000 #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 { uint32_t I2C_I2C_CNFG_0; uint32_t I2C_I2C_CMD_ADDR0_0; diff --git a/fusee/fusee-secondary/src/max77620.h b/fusee/fusee-secondary/src/max77620.h index ad22a06b5..ab90f2b8e 100644 --- a/fusee/fusee-secondary/src/max77620.h +++ b/fusee/fusee-secondary/src/max77620.h @@ -11,6 +11,36 @@ #ifndef _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 */ #define MAX77620_REG_CNFGGLBL1 0x00 #define MAX77620_REG_CNFGGLBL2 0x01 diff --git a/fusee/fusee-secondary/src/max7762x.c b/fusee/fusee-secondary/src/max7762x.c index 419a13bce..da20eb7b9 100644 --- a/fusee/fusee-secondary/src/max7762x.c +++ b/fusee/fusee-secondary/src/max7762x.c @@ -55,11 +55,11 @@ int max77620_regulator_get_status(uint32_t id) uint8_t val = 0; 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; } - 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 0; @@ -73,7 +73,7 @@ int max77620_regulator_config_fps(uint32_t id) const max77620_regulator_t *reg = &_pmic_regulators[id]; 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; } @@ -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; 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)); - 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); 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; 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) val = ((val & ~reg->enable_mask) | ((3 << reg->enable_shift) & reg->enable_mask)); else 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); return 1; @@ -139,7 +139,7 @@ void max77620_config_default() for (uint32_t i = 1; i <= REGULATOR_MAX; i++) { 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_set_voltage(i, _pmic_regulators[i].mv_default); @@ -151,11 +151,11 @@ void max77620_config_default() } 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() { 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); } diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 17a9b5f0c..dbe0882b1 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -7,10 +7,13 @@ #include "fs_utils.h" #include "nxboot.h" #include "nxfs.h" +#include "bct.h" #include "di.h" #include "mc.h" #include "se.h" #include "pmc.h" +#include "i2c.h" +#include "max77620.h" #include "cluster.h" #include "flow.h" #include "timers.h" @@ -78,13 +81,98 @@ static void nxboot_configure_exosphere(uint32_t target_firmware) { *(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. */ static nx_keyblob_t __attribute__((aligned(16))) g_keyblobs[32]; void nxboot_main(void) { volatile tegra_pmc_t *pmc = pmc_get_regs(); volatile tegra_se_t *se = se_get_regs(); loader_ctx_t *loader_ctx = get_loader_ctx(); - /* void *bootconfig; */ package2_header_t *package2; size_t package2_size; void *tsec_fw; @@ -101,7 +189,7 @@ void nxboot_main(void) { void *exosphere_memaddr; /* Allocate memory for reading Package2. */ - package2 = memalign(4096, PACKAGE2_SIZE_MAX); + package2 = memalign(0x1000, PACKAGE2_SIZE_MAX); if (package2 == NULL) { fatal_error("[NXBOOT]: Out of memory!\n"); } @@ -115,10 +203,12 @@ void nxboot_main(void) { } } else { pk2file = fopen("bcpkg21:/", "rb"); - if (pk2file == NULL || fseek(pk2file, 0x4000, SEEK_SET) != 0) { - printf("[NXBOOT]: Failed to open Package2 from eMMC: %s!\n", strerror(errno)); + if (pk2file == NULL) { + 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); - generic_panic(); } } @@ -127,7 +217,7 @@ void nxboot_main(void) { fatal_error("[NXBOOT]: Failed to read Package2!\n"); } 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"); } 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. */ printf("[NXBOOT]: Reading boot0...\n"); 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)); } fclose(boot0); @@ -146,13 +236,15 @@ void nxboot_main(void) { /* Read the TSEC firmware from a file, otherwise from PK1L. */ if (loader_ctx->tsecfw_path[0] != '\0') { 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); } else if (tsec_fw_size == 0) { 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); + if (tsec_fw == NULL) { 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"); } } - - /* TODO: Validate that we're capable of booting. */ - - /* TODO: Initialize Boot Reason. */ /* Find the system's target firmware. */ uint32_t target_firmware = nxboot_get_target_firmware(package1loader); @@ -180,6 +268,12 @@ void nxboot_main(void) { /* Setup boot configuration for Exosphère. */ 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. */ 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"); @@ -192,7 +286,9 @@ void nxboot_main(void) { 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); + if (warmboot_fw == NULL) { fatal_error("[NXBOOT]: Out of memory!\n"); } @@ -236,32 +332,36 @@ void nxboot_main(void) { /* Patch package2, adding Thermosphère + custom KIPs. */ 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. */ if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware <= EXOSPHERE_TARGET_FIRMWARE_400) { - exosphere_memaddr = (void *)0x40020000; + exosphere_memaddr = (void *)0x4002D000; } 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. */ if (loader_ctx->exosphere_path[0] != '\0') { size_t exosphere_size = get_file_size(loader_ctx->exosphere_path); 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) { /* 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) { - 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 { memcpy(exosphere_memaddr, exosphere_bin, exosphere_bin_size); } + /* Move BootConfig. */ + printf("[NXBOOT]: Moving BootConfig...\n"); + nxboot_move_bootconfig(); + /* Clean up. */ free(package1loader); if (loader_ctx->tsecfw_path[0] != '\0') { @@ -287,9 +387,6 @@ void nxboot_main(void) { set_aes_keyslot_flags(KEYSLOT_SWITCH_4XOLDDEVICEKEY, 0xFF); } - /* TODO: Handle bootconfig. */ - memset((void *)0x4003D000, 0, 0x3000); - /* Finalize the GPU UCODE carveout. */ mc_config_carveout_finalize(); diff --git a/fusee/fusee-secondary/src/nxboot.h b/fusee/fusee-secondary/src/nxboot.h index 32710d7eb..5f24266d3 100644 --- a/fusee/fusee-secondary/src/nxboot.h +++ b/fusee/fusee-secondary/src/nxboot.h @@ -5,22 +5,26 @@ #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_IS_SECMON_AWAKE MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + 0xEFC) #define NX_BOOTLOADER_STATE_INIT 0 #define NX_BOOTLOADER_STATE_MOVED_BOOTCONFIG 1 - #define NX_BOOTLOADER_STATE_LOADED_PACKAGE2 2 #define NX_BOOTLOADER_STATE_FINISHED 3 - #define NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X 2 #define NX_BOOTLOADER_STATE_LOADED_PACKAGE2_4X 3 #define NX_BOOTLOADER_STATE_FINISHED_4X 4 -/* Physaddr 0x40002EFC */ -#define MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + 0xEFC) - -#define MAILBOX_NX_BOOTLOADER_BOOT_REASON (MAILBOX_NX_BOOTLOADER_BASE + 0xE10) +typedef struct { + uint32_t bootloader_version; + uint32_t bootloader_start_block; + 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);