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