From c356e1ab36f22f446c59b9bec1b8fd4eb66912f4 Mon Sep 17 00:00:00 2001 From: hexkyz Date: Mon, 7 Dec 2020 18:39:23 +0000 Subject: [PATCH] fusee: start fleshing out nxboot for Mariko --- fusee/fusee-mtc/src/car.c | 3 + fusee/fusee-mtc/src/car.h | 1 + fusee/fusee-mtc/src/mtc.c | 49 ++-- .../fusee-primary-main/src/car.c | 3 + .../fusee-primary-main/src/car.h | 1 + .../fusee-primary-main/src/i2c.h | 14 +- .../fusee-primary-main/src/max77812.h | 81 ++++++ fusee/fusee-secondary/src/car.c | 3 + fusee/fusee-secondary/src/car.h | 1 + fusee/fusee-secondary/src/cluster.c | 194 ++++++++++--- fusee/fusee-secondary/src/i2c.h | 14 +- fusee/fusee-secondary/src/max77812.h | 81 ++++++ fusee/fusee-secondary/src/nxboot.c | 265 ++++++++++-------- fusee/fusee-secondary/src/nxboot.h | 2 + fusee/fusee-secondary/src/nxboot_iram.c | 42 ++- sept/sept-primary/src/car.c | 5 +- sept/sept-primary/src/car.h | 1 + sept/sept-primary/src/i2c.h | 14 +- sept/sept-secondary/src/car.c | 3 + sept/sept-secondary/src/car.h | 1 + sept/sept-secondary/src/cluster.c | 239 +++++++++++----- sept/sept-secondary/src/i2c.h | 14 +- sept/sept-secondary/src/max77812.h | 81 ++++++ 23 files changed, 804 insertions(+), 308 deletions(-) create mode 100644 fusee/fusee-primary/fusee-primary-main/src/max77812.h create mode 100644 fusee/fusee-secondary/src/max77812.h create mode 100644 sept/sept-secondary/src/max77812.h diff --git a/fusee/fusee-mtc/src/car.c b/fusee/fusee-mtc/src/car.c index c185b2523..30c2d86aa 100644 --- a/fusee/fusee-mtc/src/car.c +++ b/fusee/fusee-mtc/src/car.c @@ -35,6 +35,7 @@ static inline uint32_t get_clk_source_reg(CarDevice dev) { case CARDEVICE_KFUSE: return 0; case CARDEVICE_CL_DVFS: return 0; case CARDEVICE_CORESIGHT: return 0x1D4; + case CARDEVICE_MSELECT: return 0x3B4; case CARDEVICE_ACTMON: return 0x3E8; case CARDEVICE_BPMP: return 0; default: generic_panic(); @@ -58,6 +59,7 @@ static inline uint32_t get_clk_source_val(CarDevice dev) { case CARDEVICE_KFUSE: return 0; case CARDEVICE_CL_DVFS: return 0; case CARDEVICE_CORESIGHT: return 0; + case CARDEVICE_MSELECT: return 0; case CARDEVICE_ACTMON: return 6; case CARDEVICE_BPMP: return 0; default: generic_panic(); @@ -81,6 +83,7 @@ static inline uint32_t get_clk_source_div(CarDevice dev) { case CARDEVICE_KFUSE: return 0; case CARDEVICE_CL_DVFS: return 0; case CARDEVICE_CORESIGHT: return 4; + case CARDEVICE_MSELECT: return 6; case CARDEVICE_ACTMON: return 0; case CARDEVICE_BPMP: return 0; default: generic_panic(); diff --git a/fusee/fusee-mtc/src/car.h b/fusee/fusee-mtc/src/car.h index 1f223f695..97dc3f792 100644 --- a/fusee/fusee-mtc/src/car.h +++ b/fusee/fusee-mtc/src/car.h @@ -51,6 +51,7 @@ typedef enum { CARDEVICE_USB2 = ((1 << 5) | 0x1A), CARDEVICE_CORESIGHT = ((2 << 5) | 0x9), CARDEVICE_TSEC = ((2 << 5) | 0x13), + CARDEVICE_MSELECT = ((3 << 5) | 0x8), CARDEVICE_ACTMON = ((3 << 5) | 0x17), CARDEVICE_TZRAM = ((3 << 5) | 0x1E), CARDEVICE_SE = ((3 << 5) | 0x1F), diff --git a/fusee/fusee-mtc/src/mtc.c b/fusee/fusee-mtc/src/mtc.c index 32a673ed2..453274f35 100644 --- a/fusee/fusee-mtc/src/mtc.c +++ b/fusee/fusee-mtc/src/mtc.c @@ -590,9 +590,12 @@ static const uint32_t g_ram_pattern_dmi[0x500] = { 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3 }; -/* - * Register read/write helpers. - */ +/* Determine the current SoC for Mariko specific code. */ +static bool is_soc_mariko() { + return (fuse_get_soc_type() == 1); +} + +/* Register read/write helpers. */ static inline void emc_write(uint32_t val, uint32_t offset) { MAKE_EMC_REG(offset) = val; } @@ -664,10 +667,10 @@ static void ccfifo_write(uint32_t ccfifo_addr, uint32_t ccfifo_data, uint32_t cc static void start_periodic_compensation() { uint32_t mpc_req = 0x4B; - // Write to EMC_MPC_0 + /* Write to EMC_MPC_0. */ emc_write(mpc_req, EMC_MPC); - // Dummy read + /* Dummy read. */ mpc_req = emc_read(EMC_MPC); } @@ -704,7 +707,7 @@ static uint32_t wait_for_update(uint32_t status_reg, uint32_t bit_mask, bool upd udelay(1); } - // Timeout + /* Timeout. */ return 4; } @@ -1114,9 +1117,7 @@ static uint32_t update_clock_tree_delay(tegra_emc_timing_t* current_timing, tegr bool training_update = (type == TRAINING_UPDATE); bool periodic_training_update = (type == PERIODIC_TRAINING_UPDATE); - /* - * Dev0 MSB. - */ + /* Dev0 MSB. */ if (dvfs_pt1 || training_pt1 || periodic_training_update) { mrr_req = ((2 << EMC_MRR_DEV_SEL_SHIFT) | (19 << EMC_MRR_MA_SHIFT)); emc_write(mrr_req, EMC_MRR); @@ -1136,9 +1137,7 @@ static uint32_t update_clock_tree_delay(tegra_emc_timing_t* current_timing, tegr temp1_1 = (mrr_data & 0xff00); } - /* - * Dev0 LSB. - */ + /* Dev0 LSB. */ mrr_req = ((mrr_req & ~EMC_MRR_MA_MASK) | (18 << EMC_MRR_MA_SHIFT)); emc_write(mrr_req, EMC_MRR); @@ -1249,9 +1248,7 @@ static uint32_t update_clock_tree_delay(tegra_emc_timing_t* current_timing, tegr if (dram_dev_num != TWO_RANK) return adel; - /* - * Dev1 MSB. - */ + /* Dev1 MSB. */ if (dvfs_pt1 || training_pt1 || periodic_training_update) { mrr_req = ((1 << EMC_MRR_DEV_SEL_SHIFT) | (19 << EMC_MRR_MA_SHIFT)); emc_write(mrr_req, EMC_MRR); @@ -1271,9 +1268,7 @@ static uint32_t update_clock_tree_delay(tegra_emc_timing_t* current_timing, tegr temp1_1 = (mrr_data & 0xff00); } - /* - * Dev1 LSB. - */ + /* Dev1 LSB. */ mrr_req = ((mrr_req & ~EMC_MRR_MA_MASK) | (18 << EMC_MRR_MA_SHIFT)); emc_write(mrr_req, EMC_MRR); @@ -1454,9 +1449,7 @@ static uint32_t periodic_compensation_handler(tegra_emc_timing_t *current_timing start_periodic_compensation(); udelay(delay); - /* - * Generate next sample of data. - */ + /* Generate next sample of data. */ adel = update_clock_tree_delay(current_timing, next_timing, dram_dev_num, channel_mode, DVFS_PT1); } } @@ -1477,9 +1470,7 @@ static uint32_t periodic_compensation_handler(tegra_emc_timing_t *current_timing start_periodic_compensation(); udelay(delay); - /* - * Generate next sample of data. - */ + /* Generate next sample of data. */ update_clock_tree_delay(current_timing, next_timing, dram_dev_num, channel_mode, TRAINING_PT1); } @@ -3706,7 +3697,7 @@ static int train_one(int z_val, uint32_t next_rate, uint32_t current_rate, tegra return 0; } -void train_dram(void) { +static void train_dram_erista(void) { volatile tegra_car_t *car = car_get_regs(); tegra_emc_timing_t *timing_tables; @@ -3747,4 +3738,12 @@ void train_dram(void) { do_periodic_emc_compensation((tegra_emc_timing_t*)&timing_tables[g_active_timing_table_idx]); print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Done!\n"); +} + +void train_dram(void) { + if (is_soc_mariko()) { + /* TODO */ + } else { + train_dram_erista(); + } } \ No newline at end of file diff --git a/fusee/fusee-primary/fusee-primary-main/src/car.c b/fusee/fusee-primary/fusee-primary-main/src/car.c index c185b2523..30c2d86aa 100644 --- a/fusee/fusee-primary/fusee-primary-main/src/car.c +++ b/fusee/fusee-primary/fusee-primary-main/src/car.c @@ -35,6 +35,7 @@ static inline uint32_t get_clk_source_reg(CarDevice dev) { case CARDEVICE_KFUSE: return 0; case CARDEVICE_CL_DVFS: return 0; case CARDEVICE_CORESIGHT: return 0x1D4; + case CARDEVICE_MSELECT: return 0x3B4; case CARDEVICE_ACTMON: return 0x3E8; case CARDEVICE_BPMP: return 0; default: generic_panic(); @@ -58,6 +59,7 @@ static inline uint32_t get_clk_source_val(CarDevice dev) { case CARDEVICE_KFUSE: return 0; case CARDEVICE_CL_DVFS: return 0; case CARDEVICE_CORESIGHT: return 0; + case CARDEVICE_MSELECT: return 0; case CARDEVICE_ACTMON: return 6; case CARDEVICE_BPMP: return 0; default: generic_panic(); @@ -81,6 +83,7 @@ static inline uint32_t get_clk_source_div(CarDevice dev) { case CARDEVICE_KFUSE: return 0; case CARDEVICE_CL_DVFS: return 0; case CARDEVICE_CORESIGHT: return 4; + case CARDEVICE_MSELECT: return 6; case CARDEVICE_ACTMON: return 0; case CARDEVICE_BPMP: return 0; default: generic_panic(); diff --git a/fusee/fusee-primary/fusee-primary-main/src/car.h b/fusee/fusee-primary/fusee-primary-main/src/car.h index 1f223f695..97dc3f792 100644 --- a/fusee/fusee-primary/fusee-primary-main/src/car.h +++ b/fusee/fusee-primary/fusee-primary-main/src/car.h @@ -51,6 +51,7 @@ typedef enum { CARDEVICE_USB2 = ((1 << 5) | 0x1A), CARDEVICE_CORESIGHT = ((2 << 5) | 0x9), CARDEVICE_TSEC = ((2 << 5) | 0x13), + CARDEVICE_MSELECT = ((3 << 5) | 0x8), CARDEVICE_ACTMON = ((3 << 5) | 0x17), CARDEVICE_TZRAM = ((3 << 5) | 0x1E), CARDEVICE_SE = ((3 << 5) | 0x1F), diff --git a/fusee/fusee-primary/fusee-primary-main/src/i2c.h b/fusee/fusee-primary/fusee-primary-main/src/i2c.h index 64b109b21..4d3254333 100644 --- a/fusee/fusee-primary/fusee-primary-main/src/i2c.h +++ b/fusee/fusee-primary/fusee-primary-main/src/i2c.h @@ -24,12 +24,14 @@ #define I2C1234_BASE 0x7000C000 #define I2C56_BASE 0x7000D000 -#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 +#define MAX77621_CPU_I2C_ADDR 0x1B +#define MAX77621_GPU_I2C_ADDR 0x1C +#define MAX77812_PHASE31_CPU_I2C_ADDR 0x31 +#define MAX77812_PHASE211_CPU_I2C_ADDR 0x33 +#define MAX17050_I2C_ADDR 0x36 +#define MAX77620_PWR_I2C_ADDR 0x3C +#define MAX77620_RTC_I2C_ADDR 0x68 +#define BQ24193_I2C_ADDR 0x6B typedef enum { I2C_1 = 0, diff --git a/fusee/fusee-primary/fusee-primary-main/src/max77812.h b/fusee/fusee-primary/fusee-primary-main/src/max77812.h new file mode 100644 index 000000000..bf329ff6b --- /dev/null +++ b/fusee/fusee-primary/fusee-primary-main/src/max77812.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef FUSEE_MAX77812_H_ +#define FUSEE_MAX77812_H_ + +#define MAX77812_REG_RESET 0x00 +#define MAX77812_REG_INT_SRC 0x01 +#define MAX77812_REG_INT_SRC_M 0x02 +#define MAX77812_REG_TOPSYS_INT 0x03 +#define MAX77812_REG_TOPSYS_INT_M 0x04 +#define MAX77812_REG_TOPSYS_STAT 0x05 +#define MAX77812_REG_EN_CTRL 0x06 +#define MAX77812_REG_STUP_DLY1 0x07 +#define MAX77812_REG_STUP_DLY2 0x08 +#define MAX77812_REG_STUP_DLY3 0x09 +#define MAX77812_REG_SHDN_DLY1 0x0A +#define MAX77812_REG_SHDN_DLY2 0x0B +#define MAX77812_REG_SHDN_DLY3 0x0C +#define MAX77812_REG_SHDN_DLY4 0x0D +#define MAX77812_REG_WDTRSTB_DEB 0x0E +#define MAX77812_REG_GPI_FUNC 0x0F +#define MAX77812_REG_GPI_DEB1 0x10 +#define MAX77812_REG_GPI_DEB2 0x11 +#define MAX77812_REG_GPI_PD_CTRL 0x12 +#define MAX77812_REG_PROT_CFG 0x13 +#define MAX77812_REG_I2C_CFG 0x15 +#define MAX77812_REG_BUCK_INT 0x20 +#define MAX77812_REG_BUCK_INT_M 0x21 +#define MAX77812_REG_BUCK_STAT 0x22 +#define MAX77812_REG_M1_VOUT 0x23 +#define MAX77812_REG_M2_VOUT 0x24 +#define MAX77812_REG_M3_VOUT 0x25 +#define MAX77812_REG_M4_VOUT 0x26 +#define MAX77812_REG_M1_VOUT_D 0x27 +#define MAX77812_REG_M2_VOUT_D 0x28 +#define MAX77812_REG_M3_VOUT_D 0x29 +#define MAX77812_REG_M4_VOUT_D 0x2A +#define MAX77812_REG_M1_VOUT_S 0x2B +#define MAX77812_REG_M2_VOUT_S 0x2C +#define MAX77812_REG_M3_VOUT_S 0x2D +#define MAX77812_REG_M4_VOUT_S 0x2E +#define MAX77812_REG_M1_CGF 0x2F +#define MAX77812_REG_M2_CGF 0x30 +#define MAX77812_REG_M3_CGF 0x31 +#define MAX77812_REG_M4_CGF 0x32 +#define MAX77812_REG_GLB_CFG1 0x33 +#define MAX77812_REG_GLB_CFG2 0x34 +#define MAX77812_REG_GLB_CFG3 0x35 + +#define MAX77812_REG_EN_CTRL_MASK(n) BIT(n) +#define MAX77812_START_SLEW_RATE_MASK 0x07 +#define MAX77812_SHDN_SLEW_RATE_MASK 0x70 +#define MAX77812_RAMPDOWN_SLEW_RATE_MASK 0x07 +#define MAX77812_RAMPUP_SLEW_RATE_MASK 0x70 + +#define MAX77812_VOUT_MASK 0xFF +#define MAX77812_VOUT_N_VOLTAGE 0xFF +#define MAX77812_VOUT_VMIN 250000 +#define MAX77812_VOUT_VMAX 1525000 +#define MAX77812_VOUT_STEP 5000 + +#define MAX77812_REGULATOR_ID_M1 0 +#define MAX77812_REGULATOR_ID_M2 1 +#define MAX77812_REGULATOR_ID_M3 2 +#define MAX77812_REGULATOR_ID_M4 3 + +#endif diff --git a/fusee/fusee-secondary/src/car.c b/fusee/fusee-secondary/src/car.c index c185b2523..30c2d86aa 100644 --- a/fusee/fusee-secondary/src/car.c +++ b/fusee/fusee-secondary/src/car.c @@ -35,6 +35,7 @@ static inline uint32_t get_clk_source_reg(CarDevice dev) { case CARDEVICE_KFUSE: return 0; case CARDEVICE_CL_DVFS: return 0; case CARDEVICE_CORESIGHT: return 0x1D4; + case CARDEVICE_MSELECT: return 0x3B4; case CARDEVICE_ACTMON: return 0x3E8; case CARDEVICE_BPMP: return 0; default: generic_panic(); @@ -58,6 +59,7 @@ static inline uint32_t get_clk_source_val(CarDevice dev) { case CARDEVICE_KFUSE: return 0; case CARDEVICE_CL_DVFS: return 0; case CARDEVICE_CORESIGHT: return 0; + case CARDEVICE_MSELECT: return 0; case CARDEVICE_ACTMON: return 6; case CARDEVICE_BPMP: return 0; default: generic_panic(); @@ -81,6 +83,7 @@ static inline uint32_t get_clk_source_div(CarDevice dev) { case CARDEVICE_KFUSE: return 0; case CARDEVICE_CL_DVFS: return 0; case CARDEVICE_CORESIGHT: return 4; + case CARDEVICE_MSELECT: return 6; case CARDEVICE_ACTMON: return 0; case CARDEVICE_BPMP: return 0; default: generic_panic(); diff --git a/fusee/fusee-secondary/src/car.h b/fusee/fusee-secondary/src/car.h index 1f223f695..97dc3f792 100644 --- a/fusee/fusee-secondary/src/car.h +++ b/fusee/fusee-secondary/src/car.h @@ -51,6 +51,7 @@ typedef enum { CARDEVICE_USB2 = ((1 << 5) | 0x1A), CARDEVICE_CORESIGHT = ((2 << 5) | 0x9), CARDEVICE_TSEC = ((2 << 5) | 0x13), + CARDEVICE_MSELECT = ((3 << 5) | 0x8), CARDEVICE_ACTMON = ((3 << 5) | 0x17), CARDEVICE_TZRAM = ((3 << 5) | 0x1E), CARDEVICE_SE = ((3 << 5) | 0x1F), diff --git a/fusee/fusee-secondary/src/cluster.c b/fusee/fusee-secondary/src/cluster.c index d98540cca..bd7b339b5 100644 --- a/fusee/fusee-secondary/src/cluster.c +++ b/fusee/fusee-secondary/src/cluster.c @@ -22,75 +22,101 @@ #include "sysreg.h" #include "i2c.h" #include "car.h" +#include "fuse.h" #include "mc.h" #include "timers.h" #include "pmc.h" #include "max77620.h" +#include "max77812.h" -void _cluster_enable_power() -{ - uint8_t val = 0; - i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_AME_GPIO, &val, 1); - - val &= 0xDF; - i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_AME_GPIO, &val, 1); - val = 0x09; - i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_GPIO5, &val, 1); - - /* Enable power. */ - val = 0x20; - i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x02, &val, 1); - val = 0x8D; - i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x03, &val, 1); - val = 0xB7; - i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x00, &val, 1); - val = 0xB7; - i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x01, &val, 1); +/* Determine the current SoC for Mariko specific code. */ +static bool is_soc_mariko() { + return (fuse_get_soc_type() == 1); } -int _cluster_pmc_enable_partition(uint32_t part, uint32_t toggle) -{ +static void cluster_enable_power(uint32_t regulator) { + switch (regulator) { + case 0: /* Regulator_Max77621 */ + uint8_t val = 0; + i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_AME_GPIO, &val, 1); + val &= 0xDF; + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_AME_GPIO, &val, 1); + val = 0x09; + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_GPIO5, &val, 1); + val = 0x20; + i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x02, &val, 1); + val = 0x8D; + i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x03, &val, 1); + val = 0xB7; + i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x00, &val, 1); + val = 0xB7; + i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x01, &val, 1); + break; + case 1: /* Regulator_Max77812PhaseConfiguration31 */ + uint8_t val = 0; + i2c_query(I2C_5, MAX77812_PHASE31_CPU_I2C_ADDR, MAX77812_REG_EN_CTRL, &val, 1); + if (val) { + val |= 0x40; + i2c_send(I2C_5, MAX77812_PHASE31_CPU_I2C_ADDR, MAX77812_REG_EN_CTRL, &val, 1); + } + val = 0x6E; + i2c_send(I2C_5, MAX77812_PHASE31_CPU_I2C_ADDR, MAX77812_REG_M4_VOUT, &val, 1); + break; + case 2: /* Regulator_Max77812PhaseConfiguration211 */ + uint8_t val = 0; + i2c_query(I2C_5, MAX77812_PHASE211_CPU_I2C_ADDR, MAX77812_REG_EN_CTRL, &val, 1); + if (val) { + val |= 0x40; + i2c_send(I2C_5, MAX77812_PHASE211_CPU_I2C_ADDR, MAX77812_REG_EN_CTRL, &val, 1); + } + val = 0x6E; + i2c_send(I2C_5, MAX77812_PHASE211_CPU_I2C_ADDR, MAX77812_REG_M4_VOUT, &val, 1); + break; + default: return; + } +} + +static void cluster_pmc_enable_partition(uint32_t part, uint32_t toggle) { volatile tegra_pmc_t *pmc = pmc_get_regs(); /* Check if the partition has already been turned on. */ - if (pmc->pwrgate_status & part) - return 1; - - uint32_t i = 5001; - while (pmc->pwrgate_toggle & 0x100) - { - udelay(1); - i--; - if (i < 1) - return 0; + if (pmc->pwrgate_status & part) { + return; } + uint32_t i = 5001; + while (pmc->pwrgate_toggle & 0x100) { + udelay(1); + i--; + if (i < 1) { + return; + } + } + + /* Turn the partition on. */ pmc->pwrgate_toggle = (toggle | 0x100); i = 5001; - while (i > 0) - { - if (pmc->pwrgate_status & part) + while (i > 0) { + /* Check if the partition has already been turned on. */ + if (pmc->pwrgate_status & part) { break; - + } udelay(1); i--; } - - return 1; } -void cluster_boot_cpu0(uint32_t entry) -{ +static void cluster_boot_cpu0_erista(uint32_t entry) { volatile tegra_car_t *car = car_get_regs(); /* Set ACTIVE_CLUSER to FAST. */ FLOW_CTLR_BPMP_CLUSTER_CONTROL_0 &= 0xFFFFFFFE; - _cluster_enable_power(); + /* Enable VddCpu. */ + cluster_enable_power(0); - if (!(car->pllx_base & 0x40000000)) - { + if (!(car->pllx_base & 0x40000000)) { car->pllx_misc3 &= 0xFFFFFFF7; udelay(2); car->pllx_base = 0x80404E02; @@ -118,13 +144,13 @@ void cluster_boot_cpu0(uint32_t entry) car->cpu_softrst_ctrl2 &= 0xFFFFF000; /* Enable CPU rail. */ - _cluster_pmc_enable_partition(1, 0); + cluster_pmc_enable_partition(1, 0); /* Enable cluster 0 non-CPU. */ - _cluster_pmc_enable_partition(0x8000, 15); + cluster_pmc_enable_partition(0x8000, 15); /* Enable CE0. */ - _cluster_pmc_enable_partition(0x4000, 14); + cluster_pmc_enable_partition(0x4000, 14); /* Request and wait for RAM repair. */ FLOW_CTLR_RAM_REPAIR_0 = 1; @@ -157,3 +183,81 @@ void cluster_boot_cpu0(uint32_t entry) /* car->rst_cpug_cmplx_clr = 0x411F000F; */ car->rst_cpug_cmplx_clr = 0x41010001; } + +static void cluster_boot_cpu0_mariko(uint32_t entry) { + volatile tegra_car_t *car = car_get_regs(); + + /* Set ACTIVE_CLUSER to FAST. */ + FLOW_CTLR_BPMP_CLUSTER_CONTROL_0 &= 0xFFFFFFFE; + + /* Enable VddCpu. */ + cluster_enable_power(fuse_get_regulator()); + + if (!(car->pllx_base & 0x40000000)) { + car->pllx_misc3 &= 0xFFFFFFF7; + udelay(2); + car->pllx_misc = ((car->pllx_misc & 0xFFFBFFFF) | 0x40000); + car->pllx_base = 0x40404E02; + } + + while (!(car->pllx_base & 0x8000000)) { + /* Wait. */ + } + + /* Set MSELECT clock. */ + clk_enable(CARDEVICE_MSELECT); + + /* Configure initial CPU clock frequency and enable clock. */ + car->cclk_brst_pol = 0x20008888; + car->super_cclk_div = 0x80000000; + car->clk_enb_v_set = 1; + + /* Reboot CORESIGHT. */ + clkrst_reboot(CARDEVICE_CORESIGHT); + + /* Set CAR2PMC_CPU_ACK_WIDTH to 0. */ + car->cpu_softrst_ctrl2 &= 0xFFFFF000; + + /* Enable CPU rail. */ + cluster_pmc_enable_partition(1, 0); + + /* Enable cluster 0 non-CPU. */ + cluster_pmc_enable_partition(0x8000, 15); + + /* Enable CE0. */ + cluster_pmc_enable_partition(0x4000, 14); + + /* Request and wait for RAM repair. */ + FLOW_CTLR_RAM_REPAIR_0 = 1; + while (!(FLOW_CTLR_RAM_REPAIR_0 & 2)) { + /* Wait. */ + } + + MAKE_EXCP_VEC_REG(0x100) = 0; + + /* Set reset vector. */ + SB_AA64_RESET_LOW_0 = (entry | 1); + SB_AA64_RESET_HIGH_0 = 0; + + /* Non-secure reset vector write disable. */ + SB_CSR_0 = 2; + (void)SB_CSR_0; + + /* Set CPU_STRICT_TZ_APERTURE_CHECK. */ + /* NOTE: This breaks Exosphère. */ + /* MAKE_MC_REG(MC_TZ_SECURITY_CTRL) = 1; */ + + /* Clear MSELECT reset. */ + rst_disable(CARDEVICE_MSELECT); + + /* Clear CPU{0,1,2,3} POR and CORE, CX0, L2, and DBG reset.*/ + car->rst_cpug_cmplx_clr = 0x41010001; +} + +void cluster_boot_cpu0(uint32_t entry) { + if (is_soc_mariko()) { + cluster_boot_cpu0_mariko(uint32_t entry); + } else { + cluster_boot_cpu0_erista(uint32_t entry); + } +} diff --git a/fusee/fusee-secondary/src/i2c.h b/fusee/fusee-secondary/src/i2c.h index 64b109b21..4d3254333 100644 --- a/fusee/fusee-secondary/src/i2c.h +++ b/fusee/fusee-secondary/src/i2c.h @@ -24,12 +24,14 @@ #define I2C1234_BASE 0x7000C000 #define I2C56_BASE 0x7000D000 -#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 +#define MAX77621_CPU_I2C_ADDR 0x1B +#define MAX77621_GPU_I2C_ADDR 0x1C +#define MAX77812_PHASE31_CPU_I2C_ADDR 0x31 +#define MAX77812_PHASE211_CPU_I2C_ADDR 0x33 +#define MAX17050_I2C_ADDR 0x36 +#define MAX77620_PWR_I2C_ADDR 0x3C +#define MAX77620_RTC_I2C_ADDR 0x68 +#define BQ24193_I2C_ADDR 0x6B typedef enum { I2C_1 = 0, diff --git a/fusee/fusee-secondary/src/max77812.h b/fusee/fusee-secondary/src/max77812.h new file mode 100644 index 000000000..bf329ff6b --- /dev/null +++ b/fusee/fusee-secondary/src/max77812.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef FUSEE_MAX77812_H_ +#define FUSEE_MAX77812_H_ + +#define MAX77812_REG_RESET 0x00 +#define MAX77812_REG_INT_SRC 0x01 +#define MAX77812_REG_INT_SRC_M 0x02 +#define MAX77812_REG_TOPSYS_INT 0x03 +#define MAX77812_REG_TOPSYS_INT_M 0x04 +#define MAX77812_REG_TOPSYS_STAT 0x05 +#define MAX77812_REG_EN_CTRL 0x06 +#define MAX77812_REG_STUP_DLY1 0x07 +#define MAX77812_REG_STUP_DLY2 0x08 +#define MAX77812_REG_STUP_DLY3 0x09 +#define MAX77812_REG_SHDN_DLY1 0x0A +#define MAX77812_REG_SHDN_DLY2 0x0B +#define MAX77812_REG_SHDN_DLY3 0x0C +#define MAX77812_REG_SHDN_DLY4 0x0D +#define MAX77812_REG_WDTRSTB_DEB 0x0E +#define MAX77812_REG_GPI_FUNC 0x0F +#define MAX77812_REG_GPI_DEB1 0x10 +#define MAX77812_REG_GPI_DEB2 0x11 +#define MAX77812_REG_GPI_PD_CTRL 0x12 +#define MAX77812_REG_PROT_CFG 0x13 +#define MAX77812_REG_I2C_CFG 0x15 +#define MAX77812_REG_BUCK_INT 0x20 +#define MAX77812_REG_BUCK_INT_M 0x21 +#define MAX77812_REG_BUCK_STAT 0x22 +#define MAX77812_REG_M1_VOUT 0x23 +#define MAX77812_REG_M2_VOUT 0x24 +#define MAX77812_REG_M3_VOUT 0x25 +#define MAX77812_REG_M4_VOUT 0x26 +#define MAX77812_REG_M1_VOUT_D 0x27 +#define MAX77812_REG_M2_VOUT_D 0x28 +#define MAX77812_REG_M3_VOUT_D 0x29 +#define MAX77812_REG_M4_VOUT_D 0x2A +#define MAX77812_REG_M1_VOUT_S 0x2B +#define MAX77812_REG_M2_VOUT_S 0x2C +#define MAX77812_REG_M3_VOUT_S 0x2D +#define MAX77812_REG_M4_VOUT_S 0x2E +#define MAX77812_REG_M1_CGF 0x2F +#define MAX77812_REG_M2_CGF 0x30 +#define MAX77812_REG_M3_CGF 0x31 +#define MAX77812_REG_M4_CGF 0x32 +#define MAX77812_REG_GLB_CFG1 0x33 +#define MAX77812_REG_GLB_CFG2 0x34 +#define MAX77812_REG_GLB_CFG3 0x35 + +#define MAX77812_REG_EN_CTRL_MASK(n) BIT(n) +#define MAX77812_START_SLEW_RATE_MASK 0x07 +#define MAX77812_SHDN_SLEW_RATE_MASK 0x70 +#define MAX77812_RAMPDOWN_SLEW_RATE_MASK 0x07 +#define MAX77812_RAMPUP_SLEW_RATE_MASK 0x70 + +#define MAX77812_VOUT_MASK 0xFF +#define MAX77812_VOUT_N_VOLTAGE 0xFF +#define MAX77812_VOUT_VMIN 250000 +#define MAX77812_VOUT_VMAX 1525000 +#define MAX77812_VOUT_STEP 5000 + +#define MAX77812_REGULATOR_ID_M1 0 +#define MAX77812_REGULATOR_ID_M2 1 +#define MAX77812_REGULATOR_ID_M3 2 +#define MAX77812_REGULATOR_ID_M4 3 + +#endif diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 953c77faa..a8c0de223 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -108,6 +108,11 @@ static const uint8_t dev_pkc_modulus[0x100] = { 0xD5, 0x52, 0xDA, 0xEC, 0x41, 0xA4, 0xAD, 0x7B, 0x36, 0x86, 0x18, 0xB4, 0x5B, 0xD1, 0x30, 0xBB }; +/* Determine the current SoC for Mariko specific code. */ +static bool is_soc_mariko() { + return (fuse_get_soc_type() == 1); +} + static int emummc_ini_handler(void *user, const char *section, const char *name, const char *value) { emummc_config_t *emummc_cfg = (emummc_config_t *)user; if (strcmp(section, "emummc") == 0) { @@ -602,15 +607,14 @@ static void nxboot_set_bootreason(void *bootreason_base) { /* 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; + boot_reason.boot_reason_state = 0x01; /* BootReason_AcOk */ else if (power_key_intr & 0x08) - boot_reason.boot_reason_state = 0x02; + boot_reason.boot_reason_state = 0x02; /* BootReason_OnKey */ else if (rtc_intr & 0x02) - boot_reason.boot_reason_state = 0x03; + boot_reason.boot_reason_state = 0x03; /* BootReason_RtcAlarm1 */ else if (rtc_intr & 0x04) - boot_reason.boot_reason_state = 0x04; + boot_reason.boot_reason_state = 0x04; /* BootReason_RtcAlarm2 */ /* Set in memory. */ memcpy(bootreason_base, &boot_reason, sizeof(boot_reason)); @@ -643,6 +647,7 @@ static void nxboot_move_bootconfig() { fclose(bcfile); /* Select the actual BootConfig size and destination address. */ + /* NOTE: Mariko relies on BPMP's inability to data abort and tries to copy 0x1000 bytes instead. */ bootconfig_addr = 0x4003F800; bootconfig_size = 0x800; @@ -685,7 +690,12 @@ uint32_t nxboot_main(void) { FILE *boot0, *pk2file; void *exosphere_memaddr; exo_emummc_config_t exo_emummc_cfg; - + + /* Set the start time (Mariko only). */ + if (is_soc_mariko()) { + MAILBOX_NX_BOOTLOADER_START_TIME = get_time(); + } + /* Configure emummc or mount the real NAND. */ if (!nxboot_configure_emummc(&exo_emummc_cfg)) { emummc = NULL; @@ -774,102 +784,105 @@ uint32_t nxboot_main(void) { else print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Detected target firmware %ld!\n", target_firmware); - /* 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 && tsec_fw_size != 0x2900 && tsec_fw_size != 0x3000 && tsec_fw_size != 0x3300)) { - 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"); - } - if (read_from_file(tsec_fw, tsec_fw_size, loader_ctx->tsecfw_path) != tsec_fw_size) { - fatal_error("[NXBOOT] Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path); - } - - if (tsec_fw_size == 0x3000) { - if (fuse_get_hardware_state() != 0) { - sept_secondary_enc = sept_secondary_00_enc; - sept_secondary_enc_size = sept_secondary_00_enc_size; - } else { - sept_secondary_enc = sept_secondary_dev_00_enc; - sept_secondary_enc_size = sept_secondary_dev_00_enc_size; + /* Handle TSEC and Sept (Erista only). */ + if (!is_soc_mariko()) { + /* 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 && tsec_fw_size != 0x2900 && tsec_fw_size != 0x3000 && tsec_fw_size != 0x3300)) { + 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); } - } else if (tsec_fw_size == 0x3300) { - if (fuse_get_hardware_state() != 0) { - sept_secondary_enc = sept_secondary_01_enc; - sept_secondary_enc_size = sept_secondary_01_enc_size; + + /* Allocate memory for the TSEC firmware. */ + tsec_fw = memalign(0x100, tsec_fw_size); + + if (tsec_fw == NULL) { + fatal_error("[NXBOOT] Out of memory!\n"); + } + if (read_from_file(tsec_fw, tsec_fw_size, loader_ctx->tsecfw_path) != tsec_fw_size) { + fatal_error("[NXBOOT] Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path); + } + + if (tsec_fw_size == 0x3000) { + if (fuse_get_hardware_state() != 0) { + sept_secondary_enc = sept_secondary_00_enc; + sept_secondary_enc_size = sept_secondary_00_enc_size; + } else { + sept_secondary_enc = sept_secondary_dev_00_enc; + sept_secondary_enc_size = sept_secondary_dev_00_enc_size; + } + } else if (tsec_fw_size == 0x3300) { + if (fuse_get_hardware_state() != 0) { + sept_secondary_enc = sept_secondary_01_enc; + sept_secondary_enc_size = sept_secondary_01_enc_size; + } else { + sept_secondary_enc = sept_secondary_dev_01_enc; + sept_secondary_enc_size = sept_secondary_dev_01_enc_size; + } } else { - sept_secondary_enc = sept_secondary_dev_01_enc; - sept_secondary_enc_size = sept_secondary_dev_01_enc_size; + fatal_error("[NXBOOT] Unable to identify sept revision to run."); } } else { - fatal_error("[NXBOOT] Unable to identify sept revision to run."); - } - } else { - if (!package1_get_tsec_fw(&tsec_fw, package1loader, package1loader_size)) { - fatal_error("[NXBOOT] Failed to read the TSEC firmware from Package1loader!\n"); - } - if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_8_1_0) { - if (fuse_get_hardware_state() != 0) { - sept_secondary_enc = sept_secondary_01_enc; - sept_secondary_enc_size = sept_secondary_01_enc_size; - } else { - sept_secondary_enc = sept_secondary_dev_01_enc; - sept_secondary_enc_size = sept_secondary_dev_01_enc_size; + if (!package1_get_tsec_fw(&tsec_fw, package1loader, package1loader_size)) { + fatal_error("[NXBOOT] Failed to read the TSEC firmware from Package1loader!\n"); } - tsec_fw_size = 0x3300; - } else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_7_0_0) { - if (fuse_get_hardware_state() != 0) { - sept_secondary_enc = sept_secondary_00_enc; - sept_secondary_enc_size = sept_secondary_00_enc_size; + if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_8_1_0) { + if (fuse_get_hardware_state() != 0) { + sept_secondary_enc = sept_secondary_01_enc; + sept_secondary_enc_size = sept_secondary_01_enc_size; + } else { + sept_secondary_enc = sept_secondary_dev_01_enc; + sept_secondary_enc_size = sept_secondary_dev_01_enc_size; + } + tsec_fw_size = 0x3300; + } else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_7_0_0) { + if (fuse_get_hardware_state() != 0) { + sept_secondary_enc = sept_secondary_00_enc; + sept_secondary_enc_size = sept_secondary_00_enc_size; + } else { + sept_secondary_enc = sept_secondary_dev_00_enc; + sept_secondary_enc_size = sept_secondary_dev_00_enc_size; + } + tsec_fw_size = 0x3000; + } else if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_6_2_0) { + tsec_fw_size = 0x2900; } else { - sept_secondary_enc = sept_secondary_dev_00_enc; - sept_secondary_enc_size = sept_secondary_dev_00_enc_size; + tsec_fw_size = 0xF00; } - tsec_fw_size = 0x3000; + } + + print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Loaded firmware from eMMC...\n"); + + /* Get the TSEC keys. */ + uint8_t tsec_key[0x10] = {0}; + uint8_t tsec_root_keys[0x20][0x10] = {0}; + if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_7_0_0) { + /* Detect whether we need to run sept-secondary in order to derive keys. */ + if (!get_and_clear_has_run_sept()) { + reboot_to_sept(tsec_fw, tsec_fw_size, sept_secondary_enc, sept_secondary_enc_size); + } else { + if (mkey_detect_revision(fuse_get_hardware_state() != 0) != 0) { + fatal_error("[NXBOOT] Sept derived incorrect keys!\n"); + } + } + get_and_clear_has_run_sept(); } else if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_6_2_0) { - tsec_fw_size = 0x2900; - } else { - tsec_fw_size = 0xF00; - } - } + uint8_t tsec_keys[0x20] = {0}; - print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Loaded firmware from eMMC...\n"); + /* Emulate the TSEC payload on 6.2.0+. */ + smmu_emulate_tsec((void *)tsec_keys, package1loader, package1loader_size, package1loader); - /* Get the TSEC keys. */ - uint8_t tsec_key[0x10] = {0}; - uint8_t tsec_root_keys[0x20][0x10] = {0}; - if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_7_0_0) { - /* Detect whether we need to run sept-secondary in order to derive keys. */ - if (!get_and_clear_has_run_sept()) { - reboot_to_sept(tsec_fw, tsec_fw_size, sept_secondary_enc, sept_secondary_enc_size); + /* Copy back the keys. */ + memcpy((void *)tsec_key, (void *)tsec_keys, 0x10); + memcpy((void *)tsec_root_keys, (void *)tsec_keys + 0x10, 0x10); } else { - if (mkey_detect_revision(fuse_get_hardware_state() != 0) != 0) { - fatal_error("[NXBOOT] Sept derived incorrect keys!\n"); + /* Run the TSEC payload and get the key. */ + if (tsec_get_key(tsec_key, 1, tsec_fw, tsec_fw_size) != 0) { + fatal_error("[NXBOOT] Failed to get TSEC key!\n"); } } - get_and_clear_has_run_sept(); - } else if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_6_2_0) { - uint8_t tsec_keys[0x20] = {0}; - - /* Emulate the TSEC payload on 6.2.0+. */ - smmu_emulate_tsec((void *)tsec_keys, package1loader, package1loader_size, package1loader); - - /* Copy back the keys. */ - memcpy((void *)tsec_key, (void *)tsec_keys, 0x10); - memcpy((void *)tsec_root_keys, (void *)tsec_keys + 0x10, 0x10); - } else { - /* Run the TSEC payload and get the key. */ - if (tsec_get_key(tsec_key, 1, tsec_fw, tsec_fw_size) != 0) { - fatal_error("[NXBOOT] Failed to get TSEC key!\n"); - } } /* Display splash screen. */ @@ -909,12 +922,14 @@ uint32_t nxboot_main(void) { /* Setup boot configuration for Exosphère. */ nxboot_configure_exosphere(target_firmware, keygen_type, &exo_emummc_cfg); - /* Initialize Boot Reason on older firmware versions. */ - if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) { - print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Initializing Boot Reason...\n"); - nxboot_set_bootreason((void *)MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE); - } else { - memset((void *)MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE, 0, 0x200); + /* Initialize BootReason on older firmware versions (Erista only). */ + if (!is_soc_mariko()) { + if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) { + print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Initializing BootReason...\n"); + nxboot_set_bootreason((void *)MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE); + } else { + memset((void *)MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE, 0, 0x200); + } } /* Read the warmboot firmware from a file, otherwise from Atmosphere's implementation. */ @@ -933,8 +948,8 @@ uint32_t nxboot_main(void) { if (read_from_file(warmboot_fw, warmboot_fw_size, loader_ctx->warmboot_path) != warmboot_fw_size) { fatal_error("[NXBOOT] Could not read the warmboot firmware from %s!\n", loader_ctx->warmboot_path); } - } else { - /* Use Atmosphere's warmboot firmware implementation. */ + } else if (!is_soc_mariko()) { + /* Use Atmosphere's warmboot firmware implementation (Erista only). */ warmboot_fw_size = warmboot_bin_size; warmboot_fw = malloc(warmboot_fw_size); @@ -949,8 +964,8 @@ uint32_t nxboot_main(void) { } } - /* Patch warmboot firmware for atmosphere. */ - if (warmboot_fw != NULL && warmboot_fw_size >= sizeof(warmboot_ams_header_t)) { + /* Patch warmboot firmware for atmosphere (Erista only). */ + if (!is_soc_mariko() && (warmboot_fw != NULL) && (warmboot_fw_size >= sizeof(warmboot_ams_header_t))) { warmboot_ams_header_t *ams_header = (warmboot_ams_header_t *)warmboot_fw; if (ams_header->ams_metadata.magic == WARMBOOT_MAGIC) { /* Set target firmware */ @@ -970,8 +985,24 @@ uint32_t nxboot_main(void) { /* Copy the warmboot firmware and set the address in PMC if necessary. */ if (warmboot_fw && (warmboot_fw_size > 0)) { memcpy(warmboot_memaddr, warmboot_fw, warmboot_fw_size); - if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) + if (!is_soc_mariko() && (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_4_0_0)) { pmc->scratch1 = (uint32_t)warmboot_memaddr; + } + } + + /* Handle warmboot security check. */ + if (is_soc_mariko()) { + /* TODO */ + } else { + /* Set 3.0.0/3.0.1/3.0.2 warmboot security check. */ + if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware == ATMOSPHERE_TARGET_FIRMWARE_3_0_0) { + 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. */ + } + } } /* Configure mesosphere. */ @@ -991,15 +1022,11 @@ uint32_t nxboot_main(void) { mesosphere_size = sd_meso_size; } else if (is_experimental) { mesosphere_size = mesosphere_bin_size; - - mesosphere = malloc(mesosphere_size); - + mesosphere = malloc(mesosphere_size); if (mesosphere == NULL) { fatal_error("[NXBOOT] Out of memory!\n"); } - memcpy(mesosphere, mesosphere_bin, mesosphere_size); - if (mesosphere_size == 0) { fatal_error("[NXBOOT] Could not read embedded mesosphere!\n"); } @@ -1036,7 +1063,6 @@ uint32_t nxboot_main(void) { /* The maximum is actually a bit less than that. */ 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"[NXBOOT] Could not read Exosphère from %s!\n", loader_ctx->exosphere_path); } @@ -1044,8 +1070,8 @@ uint32_t nxboot_main(void) { memcpy(exosphere_memaddr, exosphere_bin, exosphere_bin_size); } - /* Copy the exosphere mariko fatal program to a good location. */ - { + /* Copy the Mariko's Exosphère fatal program to a good location. */ + if (is_soc_mariko()) { void * const mariko_fatal_dst = (void *)0x80020000; memset(mariko_fatal_dst, 0, 0x20000); @@ -1066,15 +1092,6 @@ uint32_t nxboot_main(void) { print(SCREEN_LOG_LEVEL_INFO, "[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 == ATMOSPHERE_TARGET_FIRMWARE_3_0_0) { - 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. */ free(package1loader); if (loader_ctx->tsecfw_path[0] != '\0') { @@ -1090,12 +1107,14 @@ uint32_t nxboot_main(void) { /* Wait for the splash screen to have been displayed for as long as it should be. */ splash_screen_wait_delay(); - /* Set reset for USBD, USB2, AHBDMA, and APBDMA. */ - rst_enable(CARDEVICE_USBD); - rst_enable(CARDEVICE_USB2); - rst_enable(CARDEVICE_AHBDMA); - rst_enable(CARDEVICE_APBDMA); - + /* Set reset for USBD, USB2, AHBDMA, and APBDMA on Erista. */ + if (!is_soc_mariko()) { + rst_enable(CARDEVICE_USBD); + rst_enable(CARDEVICE_USB2); + rst_enable(CARDEVICE_AHBDMA); + rst_enable(CARDEVICE_APBDMA); + } + /* Return the memory address for booting CPU0. */ return (uint32_t)exosphere_memaddr; } diff --git a/fusee/fusee-secondary/src/nxboot.h b/fusee/fusee-secondary/src/nxboot.h index ebcc878b3..bf1f8922d 100644 --- a/fusee/fusee-secondary/src/nxboot.h +++ b/fusee/fusee-secondary/src/nxboot.h @@ -36,6 +36,8 @@ typedef struct { #define MAILBOX_NX_BOOTLOADER_BASE 0x40000000 #define MAKE_MAILBOX_NX_BOOTLOADER_REG(n) MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + n) +#define MAILBOX_NX_BOOTLOADER_START_TIME MAKE_MAILBOX_NX_BOOTLOADER_REG(0x00) +#define MAILBOX_NX_BOOTLOADER_END_TIME MAKE_MAILBOX_NX_BOOTLOADER_REG(0x04) #define MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE MAKE_MAILBOX_NX_BOOTLOADER_REG(0x10) #define MAILBOX_NX_BOOTLOADER_SETUP_STATE MAKE_MAILBOX_NX_BOOTLOADER_REG(0xF8) #define MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE MAKE_MAILBOX_NX_BOOTLOADER_REG(0xFC) diff --git a/fusee/fusee-secondary/src/nxboot_iram.c b/fusee/fusee-secondary/src/nxboot_iram.c index 3fc9ff3d0..fe28eb0e2 100644 --- a/fusee/fusee-secondary/src/nxboot_iram.c +++ b/fusee/fusee-secondary/src/nxboot_iram.c @@ -20,6 +20,7 @@ #include "di.h" #include "exocfg.h" #include "flow.h" +#include "fuse.h" #include "mc.h" #include "nxboot.h" #include "se.h" @@ -27,6 +28,11 @@ #include "timers.h" #include "sysreg.h" +/* Determine the current SoC for Mariko specific code. */ +static bool is_soc_mariko() { + return (fuse_get_soc_type() == 1); +} + void nxboot_finish(uint32_t boot_memaddr) { /* Boot up Exosphère. */ MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE = 0; @@ -34,21 +40,26 @@ void nxboot_finish(uint32_t boot_memaddr) { /* Terminate the display. */ display_end(); - - /* Check if SMMU emulation has been used. */ - uint32_t smmu_magic = *(uint32_t *)(SMMU_AARCH64_PAYLOAD_ADDR + 0xFC); - if (smmu_magic == 0xDEADC0DE) { - /* Clear the magic. */ - *(uint32_t *)(SMMU_AARCH64_PAYLOAD_ADDR + 0xFC) = 0; - - /* Pass the boot address to the already running payload. */ - *(uint32_t *)(SMMU_AARCH64_PAYLOAD_ADDR + 0xF0) = boot_memaddr; - - /* Wait a while. */ - mdelay(500); - } else { + + if (is_soc_mariko()) { /* Boot CPU0. */ cluster_boot_cpu0(boot_memaddr); + } else { + /* Check if SMMU emulation has been used. */ + uint32_t smmu_magic = *(uint32_t *)(SMMU_AARCH64_PAYLOAD_ADDR + 0xFC); + if (smmu_magic == 0xDEADC0DE) { + /* Clear the magic. */ + *(uint32_t *)(SMMU_AARCH64_PAYLOAD_ADDR + 0xFC) = 0; + + /* Pass the boot address to the already running payload. */ + *(uint32_t *)(SMMU_AARCH64_PAYLOAD_ADDR + 0xF0) = boot_memaddr; + + /* Wait a while. */ + mdelay(500); + } else { + /* Boot CPU0. */ + cluster_boot_cpu0(boot_memaddr); + } } /* Wait for Exosphère to wake up. */ @@ -59,6 +70,11 @@ void nxboot_finish(uint32_t boot_memaddr) { /* Signal Exosphère. */ MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_FINISHED_4X; + /* Set the end time (Mariko only).*/ + if (is_soc_mariko()) { + MAILBOX_NX_BOOTLOADER_END_TIME = get_time(); + } + /* Halt ourselves in waitevent state. */ while (1) { FLOW_CTLR_HALT_COP_EVENTS_0 = 0x50000000; diff --git a/sept/sept-primary/src/car.c b/sept/sept-primary/src/car.c index 29dad4bbd..30c2d86aa 100644 --- a/sept/sept-primary/src/car.c +++ b/sept/sept-primary/src/car.c @@ -15,8 +15,8 @@ */ #include "car.h" -#include "utils.h" #include "timers.h" +#include "utils.h" static inline uint32_t get_clk_source_reg(CarDevice dev) { switch (dev) { @@ -35,6 +35,7 @@ static inline uint32_t get_clk_source_reg(CarDevice dev) { case CARDEVICE_KFUSE: return 0; case CARDEVICE_CL_DVFS: return 0; case CARDEVICE_CORESIGHT: return 0x1D4; + case CARDEVICE_MSELECT: return 0x3B4; case CARDEVICE_ACTMON: return 0x3E8; case CARDEVICE_BPMP: return 0; default: generic_panic(); @@ -58,6 +59,7 @@ static inline uint32_t get_clk_source_val(CarDevice dev) { case CARDEVICE_KFUSE: return 0; case CARDEVICE_CL_DVFS: return 0; case CARDEVICE_CORESIGHT: return 0; + case CARDEVICE_MSELECT: return 0; case CARDEVICE_ACTMON: return 6; case CARDEVICE_BPMP: return 0; default: generic_panic(); @@ -81,6 +83,7 @@ static inline uint32_t get_clk_source_div(CarDevice dev) { case CARDEVICE_KFUSE: return 0; case CARDEVICE_CL_DVFS: return 0; case CARDEVICE_CORESIGHT: return 4; + case CARDEVICE_MSELECT: return 6; case CARDEVICE_ACTMON: return 0; case CARDEVICE_BPMP: return 0; default: generic_panic(); diff --git a/sept/sept-primary/src/car.h b/sept/sept-primary/src/car.h index 1f223f695..97dc3f792 100644 --- a/sept/sept-primary/src/car.h +++ b/sept/sept-primary/src/car.h @@ -51,6 +51,7 @@ typedef enum { CARDEVICE_USB2 = ((1 << 5) | 0x1A), CARDEVICE_CORESIGHT = ((2 << 5) | 0x9), CARDEVICE_TSEC = ((2 << 5) | 0x13), + CARDEVICE_MSELECT = ((3 << 5) | 0x8), CARDEVICE_ACTMON = ((3 << 5) | 0x17), CARDEVICE_TZRAM = ((3 << 5) | 0x1E), CARDEVICE_SE = ((3 << 5) | 0x1F), diff --git a/sept/sept-primary/src/i2c.h b/sept/sept-primary/src/i2c.h index 64b109b21..4d3254333 100644 --- a/sept/sept-primary/src/i2c.h +++ b/sept/sept-primary/src/i2c.h @@ -24,12 +24,14 @@ #define I2C1234_BASE 0x7000C000 #define I2C56_BASE 0x7000D000 -#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 +#define MAX77621_CPU_I2C_ADDR 0x1B +#define MAX77621_GPU_I2C_ADDR 0x1C +#define MAX77812_PHASE31_CPU_I2C_ADDR 0x31 +#define MAX77812_PHASE211_CPU_I2C_ADDR 0x33 +#define MAX17050_I2C_ADDR 0x36 +#define MAX77620_PWR_I2C_ADDR 0x3C +#define MAX77620_RTC_I2C_ADDR 0x68 +#define BQ24193_I2C_ADDR 0x6B typedef enum { I2C_1 = 0, diff --git a/sept/sept-secondary/src/car.c b/sept/sept-secondary/src/car.c index c185b2523..30c2d86aa 100644 --- a/sept/sept-secondary/src/car.c +++ b/sept/sept-secondary/src/car.c @@ -35,6 +35,7 @@ static inline uint32_t get_clk_source_reg(CarDevice dev) { case CARDEVICE_KFUSE: return 0; case CARDEVICE_CL_DVFS: return 0; case CARDEVICE_CORESIGHT: return 0x1D4; + case CARDEVICE_MSELECT: return 0x3B4; case CARDEVICE_ACTMON: return 0x3E8; case CARDEVICE_BPMP: return 0; default: generic_panic(); @@ -58,6 +59,7 @@ static inline uint32_t get_clk_source_val(CarDevice dev) { case CARDEVICE_KFUSE: return 0; case CARDEVICE_CL_DVFS: return 0; case CARDEVICE_CORESIGHT: return 0; + case CARDEVICE_MSELECT: return 0; case CARDEVICE_ACTMON: return 6; case CARDEVICE_BPMP: return 0; default: generic_panic(); @@ -81,6 +83,7 @@ static inline uint32_t get_clk_source_div(CarDevice dev) { case CARDEVICE_KFUSE: return 0; case CARDEVICE_CL_DVFS: return 0; case CARDEVICE_CORESIGHT: return 4; + case CARDEVICE_MSELECT: return 6; case CARDEVICE_ACTMON: return 0; case CARDEVICE_BPMP: return 0; default: generic_panic(); diff --git a/sept/sept-secondary/src/car.h b/sept/sept-secondary/src/car.h index 1f223f695..97dc3f792 100644 --- a/sept/sept-secondary/src/car.h +++ b/sept/sept-secondary/src/car.h @@ -51,6 +51,7 @@ typedef enum { CARDEVICE_USB2 = ((1 << 5) | 0x1A), CARDEVICE_CORESIGHT = ((2 << 5) | 0x9), CARDEVICE_TSEC = ((2 << 5) | 0x13), + CARDEVICE_MSELECT = ((3 << 5) | 0x8), CARDEVICE_ACTMON = ((3 << 5) | 0x17), CARDEVICE_TZRAM = ((3 << 5) | 0x1E), CARDEVICE_SE = ((3 << 5) | 0x1F), diff --git a/sept/sept-secondary/src/cluster.c b/sept/sept-secondary/src/cluster.c index 8a0c395df..bd7b339b5 100644 --- a/sept/sept-secondary/src/cluster.c +++ b/sept/sept-secondary/src/cluster.c @@ -14,87 +14,109 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #include - + #include "cluster.h" #include "flow.h" #include "sysreg.h" #include "i2c.h" #include "car.h" +#include "fuse.h" #include "mc.h" #include "timers.h" #include "pmc.h" #include "max77620.h" +#include "max77812.h" -void _cluster_enable_power() -{ - /* Reboot I2C5. */ - clkrst_reboot(CARDEVICE_I2C5); - i2c_init(I2C_5); - - uint8_t val = 0; - i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_AME_GPIO, &val, 1); - - val &= 0xDF; - i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_AME_GPIO, &val, 1); - val = 0x09; - i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_GPIO5, &val, 1); - - /* Enable power. */ - val = 0x20; - i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x02, &val, 1); - val = 0x8D; - i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x03, &val, 1); - val = 0xB7; - i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x00, &val, 1); - val = 0xB7; - i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x01, &val, 1); +/* Determine the current SoC for Mariko specific code. */ +static bool is_soc_mariko() { + return (fuse_get_soc_type() == 1); } -int _cluster_pmc_enable_partition(uint32_t part, uint32_t toggle) -{ +static void cluster_enable_power(uint32_t regulator) { + switch (regulator) { + case 0: /* Regulator_Max77621 */ + uint8_t val = 0; + i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_AME_GPIO, &val, 1); + val &= 0xDF; + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_AME_GPIO, &val, 1); + val = 0x09; + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_GPIO5, &val, 1); + val = 0x20; + i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x02, &val, 1); + val = 0x8D; + i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x03, &val, 1); + val = 0xB7; + i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x00, &val, 1); + val = 0xB7; + i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x01, &val, 1); + break; + case 1: /* Regulator_Max77812PhaseConfiguration31 */ + uint8_t val = 0; + i2c_query(I2C_5, MAX77812_PHASE31_CPU_I2C_ADDR, MAX77812_REG_EN_CTRL, &val, 1); + if (val) { + val |= 0x40; + i2c_send(I2C_5, MAX77812_PHASE31_CPU_I2C_ADDR, MAX77812_REG_EN_CTRL, &val, 1); + } + val = 0x6E; + i2c_send(I2C_5, MAX77812_PHASE31_CPU_I2C_ADDR, MAX77812_REG_M4_VOUT, &val, 1); + break; + case 2: /* Regulator_Max77812PhaseConfiguration211 */ + uint8_t val = 0; + i2c_query(I2C_5, MAX77812_PHASE211_CPU_I2C_ADDR, MAX77812_REG_EN_CTRL, &val, 1); + if (val) { + val |= 0x40; + i2c_send(I2C_5, MAX77812_PHASE211_CPU_I2C_ADDR, MAX77812_REG_EN_CTRL, &val, 1); + } + val = 0x6E; + i2c_send(I2C_5, MAX77812_PHASE211_CPU_I2C_ADDR, MAX77812_REG_M4_VOUT, &val, 1); + break; + default: return; + } +} + +static void cluster_pmc_enable_partition(uint32_t part, uint32_t toggle) { volatile tegra_pmc_t *pmc = pmc_get_regs(); - + /* Check if the partition has already been turned on. */ - if (pmc->pwrgate_status & part) - return 1; - - uint32_t i = 5001; - while (pmc->pwrgate_toggle & 0x100) - { - udelay(1); - i--; - if (i < 1) - return 0; + if (pmc->pwrgate_status & part) { + return; } + uint32_t i = 5001; + while (pmc->pwrgate_toggle & 0x100) { + udelay(1); + i--; + if (i < 1) { + return; + } + } + + /* Turn the partition on. */ pmc->pwrgate_toggle = (toggle | 0x100); i = 5001; - while (i > 0) - { - if (pmc->pwrgate_status & part) + while (i > 0) { + /* Check if the partition has already been turned on. */ + if (pmc->pwrgate_status & part) { break; - + } udelay(1); i--; } - - return 1; } -void cluster_boot_cpu0(uint32_t entry) -{ +static void cluster_boot_cpu0_erista(uint32_t entry) { volatile tegra_car_t *car = car_get_regs(); - + /* Set ACTIVE_CLUSER to FAST. */ FLOW_CTLR_BPMP_CLUSTER_CONTROL_0 &= 0xFFFFFFFE; - _cluster_enable_power(); - - if (!(car->pllx_base & 0x40000000)) - { + /* Enable VddCpu. */ + cluster_enable_power(0); + + if (!(car->pllx_base & 0x40000000)) { car->pllx_misc3 &= 0xFFFFFFF7; udelay(2); car->pllx_base = 0x80404E02; @@ -102,7 +124,7 @@ void cluster_boot_cpu0(uint32_t entry) car->pllx_misc = ((car->pllx_misc & 0xFFFBFFFF) | 0x40000); car->pllx_base = 0x40404E02; } - + while (!(car->pllx_base & 0x8000000)) { /* Wait. */ } @@ -115,20 +137,20 @@ void cluster_boot_cpu0(uint32_t entry) car->cclk_brst_pol = 0x20008888; car->super_cclk_div = 0x80000000; car->clk_enb_v_set = 1; - + clkrst_reboot(CARDEVICE_CORESIGHT); /* CAR2PMC_CPU_ACK_WIDTH should be set to 0. */ car->cpu_softrst_ctrl2 &= 0xFFFFF000; /* Enable CPU rail. */ - _cluster_pmc_enable_partition(1, 0); - + cluster_pmc_enable_partition(1, 0); + /* Enable cluster 0 non-CPU. */ - _cluster_pmc_enable_partition(0x8000, 15); - + cluster_pmc_enable_partition(0x8000, 15); + /* Enable CE0. */ - _cluster_pmc_enable_partition(0x4000, 14); + cluster_pmc_enable_partition(0x4000, 14); /* Request and wait for RAM repair. */ FLOW_CTLR_RAM_REPAIR_0 = 1; @@ -138,41 +160,104 @@ void cluster_boot_cpu0(uint32_t entry) MAKE_EXCP_VEC_REG(0x100) = 0; - /* Check for reset vector lock. */ - if (SB_CSR_0 & 2) { - generic_panic(); - } - /* Set reset vector. */ SB_AA64_RESET_LOW_0 = (entry | 1); SB_AA64_RESET_HIGH_0 = 0; - + /* Non-secure reset vector write disable. */ SB_CSR_0 = 2; (void)SB_CSR_0; - /* Validate reset vector lock + RESET_LOW/HIGH values. */ - if (!(SB_CSR_0 & 2)) { - generic_panic(); - } - - /* TODO: Should we even bother taking as a parameter? */ - if (SB_AA64_RESET_LOW_0 != (0x4003D000 | 1) || SB_AA64_RESET_HIGH_0 != 0) { - generic_panic(); - } - /* Set CPU_STRICT_TZ_APERTURE_CHECK. */ /* NOTE: [4.0.0+] This was added, but it breaks Exosphère. */ /* MAKE_MC_REG(MC_TZ_SECURITY_CTRL) = 1; */ - + /* Clear MSELECT reset. */ car->rst_dev_v &= 0xFFFFFFF7; - + /* Clear NONCPU reset. */ car->rst_cpug_cmplx_clr = 0x20000000; - + /* Clear CPU{0,1,2,3} POR and CORE, CX0, L2, and DBG reset.*/ /* NOTE: [5.0.0+] This was changed so only CPU0 reset is cleared. */ /* car->rst_cpug_cmplx_clr = 0x411F000F; */ car->rst_cpug_cmplx_clr = 0x41010001; } + +static void cluster_boot_cpu0_mariko(uint32_t entry) { + volatile tegra_car_t *car = car_get_regs(); + + /* Set ACTIVE_CLUSER to FAST. */ + FLOW_CTLR_BPMP_CLUSTER_CONTROL_0 &= 0xFFFFFFFE; + + /* Enable VddCpu. */ + cluster_enable_power(fuse_get_regulator()); + + if (!(car->pllx_base & 0x40000000)) { + car->pllx_misc3 &= 0xFFFFFFF7; + udelay(2); + car->pllx_misc = ((car->pllx_misc & 0xFFFBFFFF) | 0x40000); + car->pllx_base = 0x40404E02; + } + + while (!(car->pllx_base & 0x8000000)) { + /* Wait. */ + } + + /* Set MSELECT clock. */ + clk_enable(CARDEVICE_MSELECT); + + /* Configure initial CPU clock frequency and enable clock. */ + car->cclk_brst_pol = 0x20008888; + car->super_cclk_div = 0x80000000; + car->clk_enb_v_set = 1; + + /* Reboot CORESIGHT. */ + clkrst_reboot(CARDEVICE_CORESIGHT); + + /* Set CAR2PMC_CPU_ACK_WIDTH to 0. */ + car->cpu_softrst_ctrl2 &= 0xFFFFF000; + + /* Enable CPU rail. */ + cluster_pmc_enable_partition(1, 0); + + /* Enable cluster 0 non-CPU. */ + cluster_pmc_enable_partition(0x8000, 15); + + /* Enable CE0. */ + cluster_pmc_enable_partition(0x4000, 14); + + /* Request and wait for RAM repair. */ + FLOW_CTLR_RAM_REPAIR_0 = 1; + while (!(FLOW_CTLR_RAM_REPAIR_0 & 2)) { + /* Wait. */ + } + + MAKE_EXCP_VEC_REG(0x100) = 0; + + /* Set reset vector. */ + SB_AA64_RESET_LOW_0 = (entry | 1); + SB_AA64_RESET_HIGH_0 = 0; + + /* Non-secure reset vector write disable. */ + SB_CSR_0 = 2; + (void)SB_CSR_0; + + /* Set CPU_STRICT_TZ_APERTURE_CHECK. */ + /* NOTE: This breaks Exosphère. */ + /* MAKE_MC_REG(MC_TZ_SECURITY_CTRL) = 1; */ + + /* Clear MSELECT reset. */ + rst_disable(CARDEVICE_MSELECT); + + /* Clear CPU{0,1,2,3} POR and CORE, CX0, L2, and DBG reset.*/ + car->rst_cpug_cmplx_clr = 0x41010001; +} + +void cluster_boot_cpu0(uint32_t entry) { + if (is_soc_mariko()) { + cluster_boot_cpu0_mariko(uint32_t entry); + } else { + cluster_boot_cpu0_erista(uint32_t entry); + } +} diff --git a/sept/sept-secondary/src/i2c.h b/sept/sept-secondary/src/i2c.h index 64b109b21..4d3254333 100644 --- a/sept/sept-secondary/src/i2c.h +++ b/sept/sept-secondary/src/i2c.h @@ -24,12 +24,14 @@ #define I2C1234_BASE 0x7000C000 #define I2C56_BASE 0x7000D000 -#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 +#define MAX77621_CPU_I2C_ADDR 0x1B +#define MAX77621_GPU_I2C_ADDR 0x1C +#define MAX77812_PHASE31_CPU_I2C_ADDR 0x31 +#define MAX77812_PHASE211_CPU_I2C_ADDR 0x33 +#define MAX17050_I2C_ADDR 0x36 +#define MAX77620_PWR_I2C_ADDR 0x3C +#define MAX77620_RTC_I2C_ADDR 0x68 +#define BQ24193_I2C_ADDR 0x6B typedef enum { I2C_1 = 0, diff --git a/sept/sept-secondary/src/max77812.h b/sept/sept-secondary/src/max77812.h new file mode 100644 index 000000000..bf329ff6b --- /dev/null +++ b/sept/sept-secondary/src/max77812.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef FUSEE_MAX77812_H_ +#define FUSEE_MAX77812_H_ + +#define MAX77812_REG_RESET 0x00 +#define MAX77812_REG_INT_SRC 0x01 +#define MAX77812_REG_INT_SRC_M 0x02 +#define MAX77812_REG_TOPSYS_INT 0x03 +#define MAX77812_REG_TOPSYS_INT_M 0x04 +#define MAX77812_REG_TOPSYS_STAT 0x05 +#define MAX77812_REG_EN_CTRL 0x06 +#define MAX77812_REG_STUP_DLY1 0x07 +#define MAX77812_REG_STUP_DLY2 0x08 +#define MAX77812_REG_STUP_DLY3 0x09 +#define MAX77812_REG_SHDN_DLY1 0x0A +#define MAX77812_REG_SHDN_DLY2 0x0B +#define MAX77812_REG_SHDN_DLY3 0x0C +#define MAX77812_REG_SHDN_DLY4 0x0D +#define MAX77812_REG_WDTRSTB_DEB 0x0E +#define MAX77812_REG_GPI_FUNC 0x0F +#define MAX77812_REG_GPI_DEB1 0x10 +#define MAX77812_REG_GPI_DEB2 0x11 +#define MAX77812_REG_GPI_PD_CTRL 0x12 +#define MAX77812_REG_PROT_CFG 0x13 +#define MAX77812_REG_I2C_CFG 0x15 +#define MAX77812_REG_BUCK_INT 0x20 +#define MAX77812_REG_BUCK_INT_M 0x21 +#define MAX77812_REG_BUCK_STAT 0x22 +#define MAX77812_REG_M1_VOUT 0x23 +#define MAX77812_REG_M2_VOUT 0x24 +#define MAX77812_REG_M3_VOUT 0x25 +#define MAX77812_REG_M4_VOUT 0x26 +#define MAX77812_REG_M1_VOUT_D 0x27 +#define MAX77812_REG_M2_VOUT_D 0x28 +#define MAX77812_REG_M3_VOUT_D 0x29 +#define MAX77812_REG_M4_VOUT_D 0x2A +#define MAX77812_REG_M1_VOUT_S 0x2B +#define MAX77812_REG_M2_VOUT_S 0x2C +#define MAX77812_REG_M3_VOUT_S 0x2D +#define MAX77812_REG_M4_VOUT_S 0x2E +#define MAX77812_REG_M1_CGF 0x2F +#define MAX77812_REG_M2_CGF 0x30 +#define MAX77812_REG_M3_CGF 0x31 +#define MAX77812_REG_M4_CGF 0x32 +#define MAX77812_REG_GLB_CFG1 0x33 +#define MAX77812_REG_GLB_CFG2 0x34 +#define MAX77812_REG_GLB_CFG3 0x35 + +#define MAX77812_REG_EN_CTRL_MASK(n) BIT(n) +#define MAX77812_START_SLEW_RATE_MASK 0x07 +#define MAX77812_SHDN_SLEW_RATE_MASK 0x70 +#define MAX77812_RAMPDOWN_SLEW_RATE_MASK 0x07 +#define MAX77812_RAMPUP_SLEW_RATE_MASK 0x70 + +#define MAX77812_VOUT_MASK 0xFF +#define MAX77812_VOUT_N_VOLTAGE 0xFF +#define MAX77812_VOUT_VMIN 250000 +#define MAX77812_VOUT_VMAX 1525000 +#define MAX77812_VOUT_STEP 5000 + +#define MAX77812_REGULATOR_ID_M1 0 +#define MAX77812_REGULATOR_ID_M2 1 +#define MAX77812_REGULATOR_ID_M3 2 +#define MAX77812_REGULATOR_ID_M4 3 + +#endif