mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 12:21:18 +00:00
fusee: start fleshing out nxboot for Mariko
This commit is contained in:
parent
222300d03c
commit
4809ced64d
23 changed files with 804 additions and 308 deletions
|
@ -35,6 +35,7 @@ static inline uint32_t get_clk_source_reg(CarDevice dev) {
|
||||||
case CARDEVICE_KFUSE: return 0;
|
case CARDEVICE_KFUSE: return 0;
|
||||||
case CARDEVICE_CL_DVFS: return 0;
|
case CARDEVICE_CL_DVFS: return 0;
|
||||||
case CARDEVICE_CORESIGHT: return 0x1D4;
|
case CARDEVICE_CORESIGHT: return 0x1D4;
|
||||||
|
case CARDEVICE_MSELECT: return 0x3B4;
|
||||||
case CARDEVICE_ACTMON: return 0x3E8;
|
case CARDEVICE_ACTMON: return 0x3E8;
|
||||||
case CARDEVICE_BPMP: return 0;
|
case CARDEVICE_BPMP: return 0;
|
||||||
default: generic_panic();
|
default: generic_panic();
|
||||||
|
@ -58,6 +59,7 @@ static inline uint32_t get_clk_source_val(CarDevice dev) {
|
||||||
case CARDEVICE_KFUSE: return 0;
|
case CARDEVICE_KFUSE: return 0;
|
||||||
case CARDEVICE_CL_DVFS: return 0;
|
case CARDEVICE_CL_DVFS: return 0;
|
||||||
case CARDEVICE_CORESIGHT: return 0;
|
case CARDEVICE_CORESIGHT: return 0;
|
||||||
|
case CARDEVICE_MSELECT: return 0;
|
||||||
case CARDEVICE_ACTMON: return 6;
|
case CARDEVICE_ACTMON: return 6;
|
||||||
case CARDEVICE_BPMP: return 0;
|
case CARDEVICE_BPMP: return 0;
|
||||||
default: generic_panic();
|
default: generic_panic();
|
||||||
|
@ -81,6 +83,7 @@ static inline uint32_t get_clk_source_div(CarDevice dev) {
|
||||||
case CARDEVICE_KFUSE: return 0;
|
case CARDEVICE_KFUSE: return 0;
|
||||||
case CARDEVICE_CL_DVFS: return 0;
|
case CARDEVICE_CL_DVFS: return 0;
|
||||||
case CARDEVICE_CORESIGHT: return 4;
|
case CARDEVICE_CORESIGHT: return 4;
|
||||||
|
case CARDEVICE_MSELECT: return 6;
|
||||||
case CARDEVICE_ACTMON: return 0;
|
case CARDEVICE_ACTMON: return 0;
|
||||||
case CARDEVICE_BPMP: return 0;
|
case CARDEVICE_BPMP: return 0;
|
||||||
default: generic_panic();
|
default: generic_panic();
|
||||||
|
|
|
@ -51,6 +51,7 @@ typedef enum {
|
||||||
CARDEVICE_USB2 = ((1 << 5) | 0x1A),
|
CARDEVICE_USB2 = ((1 << 5) | 0x1A),
|
||||||
CARDEVICE_CORESIGHT = ((2 << 5) | 0x9),
|
CARDEVICE_CORESIGHT = ((2 << 5) | 0x9),
|
||||||
CARDEVICE_TSEC = ((2 << 5) | 0x13),
|
CARDEVICE_TSEC = ((2 << 5) | 0x13),
|
||||||
|
CARDEVICE_MSELECT = ((3 << 5) | 0x8),
|
||||||
CARDEVICE_ACTMON = ((3 << 5) | 0x17),
|
CARDEVICE_ACTMON = ((3 << 5) | 0x17),
|
||||||
CARDEVICE_TZRAM = ((3 << 5) | 0x1E),
|
CARDEVICE_TZRAM = ((3 << 5) | 0x1E),
|
||||||
CARDEVICE_SE = ((3 << 5) | 0x1F),
|
CARDEVICE_SE = ((3 << 5) | 0x1F),
|
||||||
|
|
|
@ -590,9 +590,12 @@ static const uint32_t g_ram_pattern_dmi[0x500] = {
|
||||||
0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3
|
0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/* Determine the current SoC for Mariko specific code. */
|
||||||
* Register read/write helpers.
|
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) {
|
static inline void emc_write(uint32_t val, uint32_t offset) {
|
||||||
MAKE_EMC_REG(offset) = val;
|
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() {
|
static void start_periodic_compensation() {
|
||||||
uint32_t mpc_req = 0x4B;
|
uint32_t mpc_req = 0x4B;
|
||||||
|
|
||||||
// Write to EMC_MPC_0
|
/* Write to EMC_MPC_0. */
|
||||||
emc_write(mpc_req, EMC_MPC);
|
emc_write(mpc_req, EMC_MPC);
|
||||||
|
|
||||||
// Dummy read
|
/* Dummy read. */
|
||||||
mpc_req = emc_read(EMC_MPC);
|
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);
|
udelay(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timeout
|
/* Timeout. */
|
||||||
return 4;
|
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 training_update = (type == TRAINING_UPDATE);
|
||||||
bool periodic_training_update = (type == PERIODIC_TRAINING_UPDATE);
|
bool periodic_training_update = (type == PERIODIC_TRAINING_UPDATE);
|
||||||
|
|
||||||
/*
|
/* Dev0 MSB. */
|
||||||
* Dev0 MSB.
|
|
||||||
*/
|
|
||||||
if (dvfs_pt1 || training_pt1 || periodic_training_update) {
|
if (dvfs_pt1 || training_pt1 || periodic_training_update) {
|
||||||
mrr_req = ((2 << EMC_MRR_DEV_SEL_SHIFT) | (19 << EMC_MRR_MA_SHIFT));
|
mrr_req = ((2 << EMC_MRR_DEV_SEL_SHIFT) | (19 << EMC_MRR_MA_SHIFT));
|
||||||
emc_write(mrr_req, EMC_MRR);
|
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);
|
temp1_1 = (mrr_data & 0xff00);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Dev0 LSB. */
|
||||||
* Dev0 LSB.
|
|
||||||
*/
|
|
||||||
mrr_req = ((mrr_req & ~EMC_MRR_MA_MASK) | (18 << EMC_MRR_MA_SHIFT));
|
mrr_req = ((mrr_req & ~EMC_MRR_MA_MASK) | (18 << EMC_MRR_MA_SHIFT));
|
||||||
emc_write(mrr_req, EMC_MRR);
|
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)
|
if (dram_dev_num != TWO_RANK)
|
||||||
return adel;
|
return adel;
|
||||||
|
|
||||||
/*
|
/* Dev1 MSB. */
|
||||||
* Dev1 MSB.
|
|
||||||
*/
|
|
||||||
if (dvfs_pt1 || training_pt1 || periodic_training_update) {
|
if (dvfs_pt1 || training_pt1 || periodic_training_update) {
|
||||||
mrr_req = ((1 << EMC_MRR_DEV_SEL_SHIFT) | (19 << EMC_MRR_MA_SHIFT));
|
mrr_req = ((1 << EMC_MRR_DEV_SEL_SHIFT) | (19 << EMC_MRR_MA_SHIFT));
|
||||||
emc_write(mrr_req, EMC_MRR);
|
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);
|
temp1_1 = (mrr_data & 0xff00);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Dev1 LSB. */
|
||||||
* Dev1 LSB.
|
|
||||||
*/
|
|
||||||
mrr_req = ((mrr_req & ~EMC_MRR_MA_MASK) | (18 << EMC_MRR_MA_SHIFT));
|
mrr_req = ((mrr_req & ~EMC_MRR_MA_MASK) | (18 << EMC_MRR_MA_SHIFT));
|
||||||
emc_write(mrr_req, EMC_MRR);
|
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();
|
start_periodic_compensation();
|
||||||
udelay(delay);
|
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);
|
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();
|
start_periodic_compensation();
|
||||||
udelay(delay);
|
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);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void train_dram(void) {
|
static void train_dram_erista(void) {
|
||||||
volatile tegra_car_t *car = car_get_regs();
|
volatile tegra_car_t *car = car_get_regs();
|
||||||
|
|
||||||
tegra_emc_timing_t *timing_tables;
|
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]);
|
do_periodic_emc_compensation((tegra_emc_timing_t*)&timing_tables[g_active_timing_table_idx]);
|
||||||
|
|
||||||
print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Done!\n");
|
print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Done!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void train_dram(void) {
|
||||||
|
if (is_soc_mariko()) {
|
||||||
|
/* TODO */
|
||||||
|
} else {
|
||||||
|
train_dram_erista();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -35,6 +35,7 @@ static inline uint32_t get_clk_source_reg(CarDevice dev) {
|
||||||
case CARDEVICE_KFUSE: return 0;
|
case CARDEVICE_KFUSE: return 0;
|
||||||
case CARDEVICE_CL_DVFS: return 0;
|
case CARDEVICE_CL_DVFS: return 0;
|
||||||
case CARDEVICE_CORESIGHT: return 0x1D4;
|
case CARDEVICE_CORESIGHT: return 0x1D4;
|
||||||
|
case CARDEVICE_MSELECT: return 0x3B4;
|
||||||
case CARDEVICE_ACTMON: return 0x3E8;
|
case CARDEVICE_ACTMON: return 0x3E8;
|
||||||
case CARDEVICE_BPMP: return 0;
|
case CARDEVICE_BPMP: return 0;
|
||||||
default: generic_panic();
|
default: generic_panic();
|
||||||
|
@ -58,6 +59,7 @@ static inline uint32_t get_clk_source_val(CarDevice dev) {
|
||||||
case CARDEVICE_KFUSE: return 0;
|
case CARDEVICE_KFUSE: return 0;
|
||||||
case CARDEVICE_CL_DVFS: return 0;
|
case CARDEVICE_CL_DVFS: return 0;
|
||||||
case CARDEVICE_CORESIGHT: return 0;
|
case CARDEVICE_CORESIGHT: return 0;
|
||||||
|
case CARDEVICE_MSELECT: return 0;
|
||||||
case CARDEVICE_ACTMON: return 6;
|
case CARDEVICE_ACTMON: return 6;
|
||||||
case CARDEVICE_BPMP: return 0;
|
case CARDEVICE_BPMP: return 0;
|
||||||
default: generic_panic();
|
default: generic_panic();
|
||||||
|
@ -81,6 +83,7 @@ static inline uint32_t get_clk_source_div(CarDevice dev) {
|
||||||
case CARDEVICE_KFUSE: return 0;
|
case CARDEVICE_KFUSE: return 0;
|
||||||
case CARDEVICE_CL_DVFS: return 0;
|
case CARDEVICE_CL_DVFS: return 0;
|
||||||
case CARDEVICE_CORESIGHT: return 4;
|
case CARDEVICE_CORESIGHT: return 4;
|
||||||
|
case CARDEVICE_MSELECT: return 6;
|
||||||
case CARDEVICE_ACTMON: return 0;
|
case CARDEVICE_ACTMON: return 0;
|
||||||
case CARDEVICE_BPMP: return 0;
|
case CARDEVICE_BPMP: return 0;
|
||||||
default: generic_panic();
|
default: generic_panic();
|
||||||
|
|
|
@ -51,6 +51,7 @@ typedef enum {
|
||||||
CARDEVICE_USB2 = ((1 << 5) | 0x1A),
|
CARDEVICE_USB2 = ((1 << 5) | 0x1A),
|
||||||
CARDEVICE_CORESIGHT = ((2 << 5) | 0x9),
|
CARDEVICE_CORESIGHT = ((2 << 5) | 0x9),
|
||||||
CARDEVICE_TSEC = ((2 << 5) | 0x13),
|
CARDEVICE_TSEC = ((2 << 5) | 0x13),
|
||||||
|
CARDEVICE_MSELECT = ((3 << 5) | 0x8),
|
||||||
CARDEVICE_ACTMON = ((3 << 5) | 0x17),
|
CARDEVICE_ACTMON = ((3 << 5) | 0x17),
|
||||||
CARDEVICE_TZRAM = ((3 << 5) | 0x1E),
|
CARDEVICE_TZRAM = ((3 << 5) | 0x1E),
|
||||||
CARDEVICE_SE = ((3 << 5) | 0x1F),
|
CARDEVICE_SE = ((3 << 5) | 0x1F),
|
||||||
|
|
|
@ -24,12 +24,14 @@
|
||||||
#define I2C1234_BASE 0x7000C000
|
#define I2C1234_BASE 0x7000C000
|
||||||
#define I2C56_BASE 0x7000D000
|
#define I2C56_BASE 0x7000D000
|
||||||
|
|
||||||
#define MAX77621_CPU_I2C_ADDR 0x1B
|
#define MAX77621_CPU_I2C_ADDR 0x1B
|
||||||
#define MAX77621_GPU_I2C_ADDR 0x1C
|
#define MAX77621_GPU_I2C_ADDR 0x1C
|
||||||
#define MAX17050_I2C_ADDR 0x36
|
#define MAX77812_PHASE31_CPU_I2C_ADDR 0x31
|
||||||
#define MAX77620_PWR_I2C_ADDR 0x3C
|
#define MAX77812_PHASE211_CPU_I2C_ADDR 0x33
|
||||||
#define MAX77620_RTC_I2C_ADDR 0x68
|
#define MAX17050_I2C_ADDR 0x36
|
||||||
#define BQ24193_I2C_ADDR 0x6B
|
#define MAX77620_PWR_I2C_ADDR 0x3C
|
||||||
|
#define MAX77620_RTC_I2C_ADDR 0x68
|
||||||
|
#define BQ24193_I2C_ADDR 0x6B
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
I2C_1 = 0,
|
I2C_1 = 0,
|
||||||
|
|
81
fusee/fusee-primary/fusee-primary-main/src/max77812.h
Normal file
81
fusee/fusee-primary/fusee-primary-main/src/max77812.h
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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
|
|
@ -35,6 +35,7 @@ static inline uint32_t get_clk_source_reg(CarDevice dev) {
|
||||||
case CARDEVICE_KFUSE: return 0;
|
case CARDEVICE_KFUSE: return 0;
|
||||||
case CARDEVICE_CL_DVFS: return 0;
|
case CARDEVICE_CL_DVFS: return 0;
|
||||||
case CARDEVICE_CORESIGHT: return 0x1D4;
|
case CARDEVICE_CORESIGHT: return 0x1D4;
|
||||||
|
case CARDEVICE_MSELECT: return 0x3B4;
|
||||||
case CARDEVICE_ACTMON: return 0x3E8;
|
case CARDEVICE_ACTMON: return 0x3E8;
|
||||||
case CARDEVICE_BPMP: return 0;
|
case CARDEVICE_BPMP: return 0;
|
||||||
default: generic_panic();
|
default: generic_panic();
|
||||||
|
@ -58,6 +59,7 @@ static inline uint32_t get_clk_source_val(CarDevice dev) {
|
||||||
case CARDEVICE_KFUSE: return 0;
|
case CARDEVICE_KFUSE: return 0;
|
||||||
case CARDEVICE_CL_DVFS: return 0;
|
case CARDEVICE_CL_DVFS: return 0;
|
||||||
case CARDEVICE_CORESIGHT: return 0;
|
case CARDEVICE_CORESIGHT: return 0;
|
||||||
|
case CARDEVICE_MSELECT: return 0;
|
||||||
case CARDEVICE_ACTMON: return 6;
|
case CARDEVICE_ACTMON: return 6;
|
||||||
case CARDEVICE_BPMP: return 0;
|
case CARDEVICE_BPMP: return 0;
|
||||||
default: generic_panic();
|
default: generic_panic();
|
||||||
|
@ -81,6 +83,7 @@ static inline uint32_t get_clk_source_div(CarDevice dev) {
|
||||||
case CARDEVICE_KFUSE: return 0;
|
case CARDEVICE_KFUSE: return 0;
|
||||||
case CARDEVICE_CL_DVFS: return 0;
|
case CARDEVICE_CL_DVFS: return 0;
|
||||||
case CARDEVICE_CORESIGHT: return 4;
|
case CARDEVICE_CORESIGHT: return 4;
|
||||||
|
case CARDEVICE_MSELECT: return 6;
|
||||||
case CARDEVICE_ACTMON: return 0;
|
case CARDEVICE_ACTMON: return 0;
|
||||||
case CARDEVICE_BPMP: return 0;
|
case CARDEVICE_BPMP: return 0;
|
||||||
default: generic_panic();
|
default: generic_panic();
|
||||||
|
|
|
@ -51,6 +51,7 @@ typedef enum {
|
||||||
CARDEVICE_USB2 = ((1 << 5) | 0x1A),
|
CARDEVICE_USB2 = ((1 << 5) | 0x1A),
|
||||||
CARDEVICE_CORESIGHT = ((2 << 5) | 0x9),
|
CARDEVICE_CORESIGHT = ((2 << 5) | 0x9),
|
||||||
CARDEVICE_TSEC = ((2 << 5) | 0x13),
|
CARDEVICE_TSEC = ((2 << 5) | 0x13),
|
||||||
|
CARDEVICE_MSELECT = ((3 << 5) | 0x8),
|
||||||
CARDEVICE_ACTMON = ((3 << 5) | 0x17),
|
CARDEVICE_ACTMON = ((3 << 5) | 0x17),
|
||||||
CARDEVICE_TZRAM = ((3 << 5) | 0x1E),
|
CARDEVICE_TZRAM = ((3 << 5) | 0x1E),
|
||||||
CARDEVICE_SE = ((3 << 5) | 0x1F),
|
CARDEVICE_SE = ((3 << 5) | 0x1F),
|
||||||
|
|
|
@ -22,75 +22,101 @@
|
||||||
#include "sysreg.h"
|
#include "sysreg.h"
|
||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
#include "car.h"
|
#include "car.h"
|
||||||
|
#include "fuse.h"
|
||||||
#include "mc.h"
|
#include "mc.h"
|
||||||
#include "timers.h"
|
#include "timers.h"
|
||||||
#include "pmc.h"
|
#include "pmc.h"
|
||||||
#include "max77620.h"
|
#include "max77620.h"
|
||||||
|
#include "max77812.h"
|
||||||
|
|
||||||
void _cluster_enable_power()
|
/* Determine the current SoC for Mariko specific code. */
|
||||||
{
|
static bool is_soc_mariko() {
|
||||||
uint8_t val = 0;
|
return (fuse_get_soc_type() == 1);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
volatile tegra_pmc_t *pmc = pmc_get_regs();
|
||||||
|
|
||||||
/* Check if the partition has already been turned on. */
|
/* Check if the partition has already been turned on. */
|
||||||
if (pmc->pwrgate_status & part)
|
if (pmc->pwrgate_status & part) {
|
||||||
return 1;
|
return;
|
||||||
|
|
||||||
uint32_t i = 5001;
|
|
||||||
while (pmc->pwrgate_toggle & 0x100)
|
|
||||||
{
|
|
||||||
udelay(1);
|
|
||||||
i--;
|
|
||||||
if (i < 1)
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
pmc->pwrgate_toggle = (toggle | 0x100);
|
||||||
|
|
||||||
i = 5001;
|
i = 5001;
|
||||||
while (i > 0)
|
while (i > 0) {
|
||||||
{
|
/* Check if the partition has already been turned on. */
|
||||||
if (pmc->pwrgate_status & part)
|
if (pmc->pwrgate_status & part) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
udelay(1);
|
udelay(1);
|
||||||
i--;
|
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();
|
volatile tegra_car_t *car = car_get_regs();
|
||||||
|
|
||||||
/* Set ACTIVE_CLUSER to FAST. */
|
/* Set ACTIVE_CLUSER to FAST. */
|
||||||
FLOW_CTLR_BPMP_CLUSTER_CONTROL_0 &= 0xFFFFFFFE;
|
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;
|
car->pllx_misc3 &= 0xFFFFFFF7;
|
||||||
udelay(2);
|
udelay(2);
|
||||||
car->pllx_base = 0x80404E02;
|
car->pllx_base = 0x80404E02;
|
||||||
|
@ -118,13 +144,13 @@ void cluster_boot_cpu0(uint32_t entry)
|
||||||
car->cpu_softrst_ctrl2 &= 0xFFFFF000;
|
car->cpu_softrst_ctrl2 &= 0xFFFFF000;
|
||||||
|
|
||||||
/* Enable CPU rail. */
|
/* Enable CPU rail. */
|
||||||
_cluster_pmc_enable_partition(1, 0);
|
cluster_pmc_enable_partition(1, 0);
|
||||||
|
|
||||||
/* Enable cluster 0 non-CPU. */
|
/* Enable cluster 0 non-CPU. */
|
||||||
_cluster_pmc_enable_partition(0x8000, 15);
|
cluster_pmc_enable_partition(0x8000, 15);
|
||||||
|
|
||||||
/* Enable CE0. */
|
/* Enable CE0. */
|
||||||
_cluster_pmc_enable_partition(0x4000, 14);
|
cluster_pmc_enable_partition(0x4000, 14);
|
||||||
|
|
||||||
/* Request and wait for RAM repair. */
|
/* Request and wait for RAM repair. */
|
||||||
FLOW_CTLR_RAM_REPAIR_0 = 1;
|
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 = 0x411F000F; */
|
||||||
car->rst_cpug_cmplx_clr = 0x41010001;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -24,12 +24,14 @@
|
||||||
#define I2C1234_BASE 0x7000C000
|
#define I2C1234_BASE 0x7000C000
|
||||||
#define I2C56_BASE 0x7000D000
|
#define I2C56_BASE 0x7000D000
|
||||||
|
|
||||||
#define MAX77621_CPU_I2C_ADDR 0x1B
|
#define MAX77621_CPU_I2C_ADDR 0x1B
|
||||||
#define MAX77621_GPU_I2C_ADDR 0x1C
|
#define MAX77621_GPU_I2C_ADDR 0x1C
|
||||||
#define MAX17050_I2C_ADDR 0x36
|
#define MAX77812_PHASE31_CPU_I2C_ADDR 0x31
|
||||||
#define MAX77620_PWR_I2C_ADDR 0x3C
|
#define MAX77812_PHASE211_CPU_I2C_ADDR 0x33
|
||||||
#define MAX77620_RTC_I2C_ADDR 0x68
|
#define MAX17050_I2C_ADDR 0x36
|
||||||
#define BQ24193_I2C_ADDR 0x6B
|
#define MAX77620_PWR_I2C_ADDR 0x3C
|
||||||
|
#define MAX77620_RTC_I2C_ADDR 0x68
|
||||||
|
#define BQ24193_I2C_ADDR 0x6B
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
I2C_1 = 0,
|
I2C_1 = 0,
|
||||||
|
|
81
fusee/fusee-secondary/src/max77812.h
Normal file
81
fusee/fusee-secondary/src/max77812.h
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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
|
|
@ -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
|
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) {
|
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;
|
emummc_config_t *emummc_cfg = (emummc_config_t *)user;
|
||||||
if (strcmp(section, "emummc") == 0) {
|
if (strcmp(section, "emummc") == 0) {
|
||||||
|
@ -602,15 +607,14 @@ static void nxboot_set_bootreason(void *bootreason_base) {
|
||||||
/* Set PMIC value. */
|
/* Set PMIC value. */
|
||||||
boot_reason.boot_reason_value = ((rtc_intr << 0x08) | power_key_intr);
|
boot_reason.boot_reason_value = ((rtc_intr << 0x08) | power_key_intr);
|
||||||
|
|
||||||
/* TODO: Find out what these mean. */
|
|
||||||
if (power_key_intr & 0x80)
|
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)
|
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)
|
else if (rtc_intr & 0x02)
|
||||||
boot_reason.boot_reason_state = 0x03;
|
boot_reason.boot_reason_state = 0x03; /* BootReason_RtcAlarm1 */
|
||||||
else if (rtc_intr & 0x04)
|
else if (rtc_intr & 0x04)
|
||||||
boot_reason.boot_reason_state = 0x04;
|
boot_reason.boot_reason_state = 0x04; /* BootReason_RtcAlarm2 */
|
||||||
|
|
||||||
/* Set in memory. */
|
/* Set in memory. */
|
||||||
memcpy(bootreason_base, &boot_reason, sizeof(boot_reason));
|
memcpy(bootreason_base, &boot_reason, sizeof(boot_reason));
|
||||||
|
@ -643,6 +647,7 @@ static void nxboot_move_bootconfig() {
|
||||||
fclose(bcfile);
|
fclose(bcfile);
|
||||||
|
|
||||||
/* Select the actual BootConfig size and destination address. */
|
/* 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_addr = 0x4003F800;
|
||||||
bootconfig_size = 0x800;
|
bootconfig_size = 0x800;
|
||||||
|
|
||||||
|
@ -685,7 +690,12 @@ uint32_t nxboot_main(void) {
|
||||||
FILE *boot0, *pk2file;
|
FILE *boot0, *pk2file;
|
||||||
void *exosphere_memaddr;
|
void *exosphere_memaddr;
|
||||||
exo_emummc_config_t exo_emummc_cfg;
|
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. */
|
/* Configure emummc or mount the real NAND. */
|
||||||
if (!nxboot_configure_emummc(&exo_emummc_cfg)) {
|
if (!nxboot_configure_emummc(&exo_emummc_cfg)) {
|
||||||
emummc = NULL;
|
emummc = NULL;
|
||||||
|
@ -774,102 +784,105 @@ uint32_t nxboot_main(void) {
|
||||||
else
|
else
|
||||||
print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Detected target firmware %ld!\n", target_firmware);
|
print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Detected target firmware %ld!\n", target_firmware);
|
||||||
|
|
||||||
/* Read the TSEC firmware from a file, otherwise from PK1L. */
|
/* Handle TSEC and Sept (Erista only). */
|
||||||
if (loader_ctx->tsecfw_path[0] != '\0') {
|
if (!is_soc_mariko()) {
|
||||||
tsec_fw_size = get_file_size(loader_ctx->tsecfw_path);
|
/* Read the TSEC firmware from a file, otherwise from PK1L. */
|
||||||
if ((tsec_fw_size != 0) && (tsec_fw_size != 0xF00 && tsec_fw_size != 0x2900 && tsec_fw_size != 0x3000 && tsec_fw_size != 0x3300)) {
|
if (loader_ctx->tsecfw_path[0] != '\0') {
|
||||||
fatal_error("[NXBOOT] TSEC firmware from %s has a wrong size!\n", loader_ctx->tsecfw_path);
|
tsec_fw_size = get_file_size(loader_ctx->tsecfw_path);
|
||||||
} else if (tsec_fw_size == 0) {
|
if ((tsec_fw_size != 0) && (tsec_fw_size != 0xF00 && tsec_fw_size != 0x2900 && tsec_fw_size != 0x3000 && tsec_fw_size != 0x3300)) {
|
||||||
fatal_error("[NXBOOT] Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path);
|
fatal_error("[NXBOOT] TSEC firmware from %s has a wrong size!\n", loader_ctx->tsecfw_path);
|
||||||
}
|
} else if (tsec_fw_size == 0) {
|
||||||
|
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;
|
|
||||||
}
|
}
|
||||||
} else if (tsec_fw_size == 0x3300) {
|
|
||||||
if (fuse_get_hardware_state() != 0) {
|
/* Allocate memory for the TSEC firmware. */
|
||||||
sept_secondary_enc = sept_secondary_01_enc;
|
tsec_fw = memalign(0x100, tsec_fw_size);
|
||||||
sept_secondary_enc_size = sept_secondary_01_enc_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 {
|
} else {
|
||||||
sept_secondary_enc = sept_secondary_dev_01_enc;
|
fatal_error("[NXBOOT] Unable to identify sept revision to run.");
|
||||||
sept_secondary_enc_size = sept_secondary_dev_01_enc_size;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fatal_error("[NXBOOT] Unable to identify sept revision to run.");
|
if (!package1_get_tsec_fw(&tsec_fw, package1loader, package1loader_size)) {
|
||||||
}
|
fatal_error("[NXBOOT] Failed to read the TSEC firmware from Package1loader!\n");
|
||||||
} 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;
|
|
||||||
}
|
}
|
||||||
tsec_fw_size = 0x3300;
|
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_8_1_0) {
|
||||||
} else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_7_0_0) {
|
if (fuse_get_hardware_state() != 0) {
|
||||||
if (fuse_get_hardware_state() != 0) {
|
sept_secondary_enc = sept_secondary_01_enc;
|
||||||
sept_secondary_enc = sept_secondary_00_enc;
|
sept_secondary_enc_size = sept_secondary_01_enc_size;
|
||||||
sept_secondary_enc_size = sept_secondary_00_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 {
|
} else {
|
||||||
sept_secondary_enc = sept_secondary_dev_00_enc;
|
tsec_fw_size = 0xF00;
|
||||||
sept_secondary_enc_size = sept_secondary_dev_00_enc_size;
|
|
||||||
}
|
}
|
||||||
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) {
|
} else if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_6_2_0) {
|
||||||
tsec_fw_size = 0x2900;
|
uint8_t tsec_keys[0x20] = {0};
|
||||||
} else {
|
|
||||||
tsec_fw_size = 0xF00;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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. */
|
/* Copy back the keys. */
|
||||||
uint8_t tsec_key[0x10] = {0};
|
memcpy((void *)tsec_key, (void *)tsec_keys, 0x10);
|
||||||
uint8_t tsec_root_keys[0x20][0x10] = {0};
|
memcpy((void *)tsec_root_keys, (void *)tsec_keys + 0x10, 0x10);
|
||||||
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 {
|
} else {
|
||||||
if (mkey_detect_revision(fuse_get_hardware_state() != 0) != 0) {
|
/* Run the TSEC payload and get the key. */
|
||||||
fatal_error("[NXBOOT] Sept derived incorrect keys!\n");
|
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. */
|
/* Display splash screen. */
|
||||||
|
@ -909,12 +922,14 @@ uint32_t nxboot_main(void) {
|
||||||
/* Setup boot configuration for Exosphère. */
|
/* Setup boot configuration for Exosphère. */
|
||||||
nxboot_configure_exosphere(target_firmware, keygen_type, &exo_emummc_cfg);
|
nxboot_configure_exosphere(target_firmware, keygen_type, &exo_emummc_cfg);
|
||||||
|
|
||||||
/* Initialize Boot Reason on older firmware versions. */
|
/* Initialize BootReason on older firmware versions (Erista only). */
|
||||||
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
|
if (!is_soc_mariko()) {
|
||||||
print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Initializing Boot Reason...\n");
|
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_4_0_0) {
|
||||||
nxboot_set_bootreason((void *)MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE);
|
print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Initializing BootReason...\n");
|
||||||
} else {
|
nxboot_set_bootreason((void *)MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE);
|
||||||
memset((void *)MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE, 0, 0x200);
|
} else {
|
||||||
|
memset((void *)MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE, 0, 0x200);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read the warmboot firmware from a file, otherwise from Atmosphere's implementation. */
|
/* 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) {
|
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);
|
fatal_error("[NXBOOT] Could not read the warmboot firmware from %s!\n", loader_ctx->warmboot_path);
|
||||||
}
|
}
|
||||||
} else {
|
} else if (!is_soc_mariko()) {
|
||||||
/* Use Atmosphere's warmboot firmware implementation. */
|
/* Use Atmosphere's warmboot firmware implementation (Erista only). */
|
||||||
warmboot_fw_size = warmboot_bin_size;
|
warmboot_fw_size = warmboot_bin_size;
|
||||||
warmboot_fw = malloc(warmboot_fw_size);
|
warmboot_fw = malloc(warmboot_fw_size);
|
||||||
|
|
||||||
|
@ -949,8 +964,8 @@ uint32_t nxboot_main(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Patch warmboot firmware for atmosphere. */
|
/* Patch warmboot firmware for atmosphere (Erista only). */
|
||||||
if (warmboot_fw != NULL && warmboot_fw_size >= sizeof(warmboot_ams_header_t)) {
|
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;
|
warmboot_ams_header_t *ams_header = (warmboot_ams_header_t *)warmboot_fw;
|
||||||
if (ams_header->ams_metadata.magic == WARMBOOT_MAGIC) {
|
if (ams_header->ams_metadata.magic == WARMBOOT_MAGIC) {
|
||||||
/* Set target firmware */
|
/* Set target firmware */
|
||||||
|
@ -970,8 +985,24 @@ uint32_t nxboot_main(void) {
|
||||||
/* Copy the warmboot firmware and set the address in PMC if necessary. */
|
/* Copy the warmboot firmware and set the address in PMC if necessary. */
|
||||||
if (warmboot_fw && (warmboot_fw_size > 0)) {
|
if (warmboot_fw && (warmboot_fw_size > 0)) {
|
||||||
memcpy(warmboot_memaddr, warmboot_fw, warmboot_fw_size);
|
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;
|
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. */
|
/* Configure mesosphere. */
|
||||||
|
@ -991,15 +1022,11 @@ uint32_t nxboot_main(void) {
|
||||||
mesosphere_size = sd_meso_size;
|
mesosphere_size = sd_meso_size;
|
||||||
} else if (is_experimental) {
|
} else if (is_experimental) {
|
||||||
mesosphere_size = mesosphere_bin_size;
|
mesosphere_size = mesosphere_bin_size;
|
||||||
|
mesosphere = malloc(mesosphere_size);
|
||||||
mesosphere = malloc(mesosphere_size);
|
|
||||||
|
|
||||||
if (mesosphere == NULL) {
|
if (mesosphere == NULL) {
|
||||||
fatal_error("[NXBOOT] Out of memory!\n");
|
fatal_error("[NXBOOT] Out of memory!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(mesosphere, mesosphere_bin, mesosphere_size);
|
memcpy(mesosphere, mesosphere_bin, mesosphere_size);
|
||||||
|
|
||||||
if (mesosphere_size == 0) {
|
if (mesosphere_size == 0) {
|
||||||
fatal_error("[NXBOOT] Could not read embedded mesosphere!\n");
|
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. */
|
/* 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);
|
fatal_error(u8"[NXBOOT] Exosphère from %s is too big!\n", loader_ctx->exosphere_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (read_from_file(exosphere_memaddr, exosphere_size, loader_ctx->exosphere_path) != exosphere_size) {
|
if (read_from_file(exosphere_memaddr, exosphere_size, loader_ctx->exosphere_path) != exosphere_size) {
|
||||||
fatal_error(u8"[NXBOOT] Could not read Exosphère from %s!\n", loader_ctx->exosphere_path);
|
fatal_error(u8"[NXBOOT] Could not read Exosphère from %s!\n", loader_ctx->exosphere_path);
|
||||||
}
|
}
|
||||||
|
@ -1044,8 +1070,8 @@ uint32_t nxboot_main(void) {
|
||||||
memcpy(exosphere_memaddr, exosphere_bin, exosphere_bin_size);
|
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;
|
void * const mariko_fatal_dst = (void *)0x80020000;
|
||||||
memset(mariko_fatal_dst, 0, 0x20000);
|
memset(mariko_fatal_dst, 0, 0x20000);
|
||||||
|
|
||||||
|
@ -1066,15 +1092,6 @@ uint32_t nxboot_main(void) {
|
||||||
print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Moving BootConfig...\n");
|
print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Moving BootConfig...\n");
|
||||||
nxboot_move_bootconfig();
|
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. */
|
/* Clean up. */
|
||||||
free(package1loader);
|
free(package1loader);
|
||||||
if (loader_ctx->tsecfw_path[0] != '\0') {
|
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. */
|
/* Wait for the splash screen to have been displayed for as long as it should be. */
|
||||||
splash_screen_wait_delay();
|
splash_screen_wait_delay();
|
||||||
|
|
||||||
/* Set reset for USBD, USB2, AHBDMA, and APBDMA. */
|
/* Set reset for USBD, USB2, AHBDMA, and APBDMA on Erista. */
|
||||||
rst_enable(CARDEVICE_USBD);
|
if (!is_soc_mariko()) {
|
||||||
rst_enable(CARDEVICE_USB2);
|
rst_enable(CARDEVICE_USBD);
|
||||||
rst_enable(CARDEVICE_AHBDMA);
|
rst_enable(CARDEVICE_USB2);
|
||||||
rst_enable(CARDEVICE_APBDMA);
|
rst_enable(CARDEVICE_AHBDMA);
|
||||||
|
rst_enable(CARDEVICE_APBDMA);
|
||||||
|
}
|
||||||
|
|
||||||
/* Return the memory address for booting CPU0. */
|
/* Return the memory address for booting CPU0. */
|
||||||
return (uint32_t)exosphere_memaddr;
|
return (uint32_t)exosphere_memaddr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,8 @@ typedef struct {
|
||||||
#define MAILBOX_NX_BOOTLOADER_BASE 0x40000000
|
#define MAILBOX_NX_BOOTLOADER_BASE 0x40000000
|
||||||
#define MAKE_MAILBOX_NX_BOOTLOADER_REG(n) MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + n)
|
#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_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_SETUP_STATE MAKE_MAILBOX_NX_BOOTLOADER_REG(0xF8)
|
||||||
#define MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE MAKE_MAILBOX_NX_BOOTLOADER_REG(0xFC)
|
#define MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE MAKE_MAILBOX_NX_BOOTLOADER_REG(0xFC)
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "di.h"
|
#include "di.h"
|
||||||
#include "exocfg.h"
|
#include "exocfg.h"
|
||||||
#include "flow.h"
|
#include "flow.h"
|
||||||
|
#include "fuse.h"
|
||||||
#include "mc.h"
|
#include "mc.h"
|
||||||
#include "nxboot.h"
|
#include "nxboot.h"
|
||||||
#include "se.h"
|
#include "se.h"
|
||||||
|
@ -27,6 +28,11 @@
|
||||||
#include "timers.h"
|
#include "timers.h"
|
||||||
#include "sysreg.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) {
|
void nxboot_finish(uint32_t boot_memaddr) {
|
||||||
/* Boot up Exosphère. */
|
/* Boot up Exosphère. */
|
||||||
MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE = 0;
|
MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE = 0;
|
||||||
|
@ -34,21 +40,26 @@ void nxboot_finish(uint32_t boot_memaddr) {
|
||||||
|
|
||||||
/* Terminate the display. */
|
/* Terminate the display. */
|
||||||
display_end();
|
display_end();
|
||||||
|
|
||||||
/* Check if SMMU emulation has been used. */
|
if (is_soc_mariko()) {
|
||||||
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. */
|
/* Boot CPU0. */
|
||||||
cluster_boot_cpu0(boot_memaddr);
|
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. */
|
/* Wait for Exosphère to wake up. */
|
||||||
|
@ -59,6 +70,11 @@ void nxboot_finish(uint32_t boot_memaddr) {
|
||||||
/* Signal Exosphère. */
|
/* Signal Exosphère. */
|
||||||
MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_FINISHED_4X;
|
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. */
|
/* Halt ourselves in waitevent state. */
|
||||||
while (1) {
|
while (1) {
|
||||||
FLOW_CTLR_HALT_COP_EVENTS_0 = 0x50000000;
|
FLOW_CTLR_HALT_COP_EVENTS_0 = 0x50000000;
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "car.h"
|
#include "car.h"
|
||||||
#include "utils.h"
|
|
||||||
#include "timers.h"
|
#include "timers.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
static inline uint32_t get_clk_source_reg(CarDevice dev) {
|
static inline uint32_t get_clk_source_reg(CarDevice dev) {
|
||||||
switch (dev) {
|
switch (dev) {
|
||||||
|
@ -35,6 +35,7 @@ static inline uint32_t get_clk_source_reg(CarDevice dev) {
|
||||||
case CARDEVICE_KFUSE: return 0;
|
case CARDEVICE_KFUSE: return 0;
|
||||||
case CARDEVICE_CL_DVFS: return 0;
|
case CARDEVICE_CL_DVFS: return 0;
|
||||||
case CARDEVICE_CORESIGHT: return 0x1D4;
|
case CARDEVICE_CORESIGHT: return 0x1D4;
|
||||||
|
case CARDEVICE_MSELECT: return 0x3B4;
|
||||||
case CARDEVICE_ACTMON: return 0x3E8;
|
case CARDEVICE_ACTMON: return 0x3E8;
|
||||||
case CARDEVICE_BPMP: return 0;
|
case CARDEVICE_BPMP: return 0;
|
||||||
default: generic_panic();
|
default: generic_panic();
|
||||||
|
@ -58,6 +59,7 @@ static inline uint32_t get_clk_source_val(CarDevice dev) {
|
||||||
case CARDEVICE_KFUSE: return 0;
|
case CARDEVICE_KFUSE: return 0;
|
||||||
case CARDEVICE_CL_DVFS: return 0;
|
case CARDEVICE_CL_DVFS: return 0;
|
||||||
case CARDEVICE_CORESIGHT: return 0;
|
case CARDEVICE_CORESIGHT: return 0;
|
||||||
|
case CARDEVICE_MSELECT: return 0;
|
||||||
case CARDEVICE_ACTMON: return 6;
|
case CARDEVICE_ACTMON: return 6;
|
||||||
case CARDEVICE_BPMP: return 0;
|
case CARDEVICE_BPMP: return 0;
|
||||||
default: generic_panic();
|
default: generic_panic();
|
||||||
|
@ -81,6 +83,7 @@ static inline uint32_t get_clk_source_div(CarDevice dev) {
|
||||||
case CARDEVICE_KFUSE: return 0;
|
case CARDEVICE_KFUSE: return 0;
|
||||||
case CARDEVICE_CL_DVFS: return 0;
|
case CARDEVICE_CL_DVFS: return 0;
|
||||||
case CARDEVICE_CORESIGHT: return 4;
|
case CARDEVICE_CORESIGHT: return 4;
|
||||||
|
case CARDEVICE_MSELECT: return 6;
|
||||||
case CARDEVICE_ACTMON: return 0;
|
case CARDEVICE_ACTMON: return 0;
|
||||||
case CARDEVICE_BPMP: return 0;
|
case CARDEVICE_BPMP: return 0;
|
||||||
default: generic_panic();
|
default: generic_panic();
|
||||||
|
|
|
@ -51,6 +51,7 @@ typedef enum {
|
||||||
CARDEVICE_USB2 = ((1 << 5) | 0x1A),
|
CARDEVICE_USB2 = ((1 << 5) | 0x1A),
|
||||||
CARDEVICE_CORESIGHT = ((2 << 5) | 0x9),
|
CARDEVICE_CORESIGHT = ((2 << 5) | 0x9),
|
||||||
CARDEVICE_TSEC = ((2 << 5) | 0x13),
|
CARDEVICE_TSEC = ((2 << 5) | 0x13),
|
||||||
|
CARDEVICE_MSELECT = ((3 << 5) | 0x8),
|
||||||
CARDEVICE_ACTMON = ((3 << 5) | 0x17),
|
CARDEVICE_ACTMON = ((3 << 5) | 0x17),
|
||||||
CARDEVICE_TZRAM = ((3 << 5) | 0x1E),
|
CARDEVICE_TZRAM = ((3 << 5) | 0x1E),
|
||||||
CARDEVICE_SE = ((3 << 5) | 0x1F),
|
CARDEVICE_SE = ((3 << 5) | 0x1F),
|
||||||
|
|
|
@ -24,12 +24,14 @@
|
||||||
#define I2C1234_BASE 0x7000C000
|
#define I2C1234_BASE 0x7000C000
|
||||||
#define I2C56_BASE 0x7000D000
|
#define I2C56_BASE 0x7000D000
|
||||||
|
|
||||||
#define MAX77621_CPU_I2C_ADDR 0x1B
|
#define MAX77621_CPU_I2C_ADDR 0x1B
|
||||||
#define MAX77621_GPU_I2C_ADDR 0x1C
|
#define MAX77621_GPU_I2C_ADDR 0x1C
|
||||||
#define MAX17050_I2C_ADDR 0x36
|
#define MAX77812_PHASE31_CPU_I2C_ADDR 0x31
|
||||||
#define MAX77620_PWR_I2C_ADDR 0x3C
|
#define MAX77812_PHASE211_CPU_I2C_ADDR 0x33
|
||||||
#define MAX77620_RTC_I2C_ADDR 0x68
|
#define MAX17050_I2C_ADDR 0x36
|
||||||
#define BQ24193_I2C_ADDR 0x6B
|
#define MAX77620_PWR_I2C_ADDR 0x3C
|
||||||
|
#define MAX77620_RTC_I2C_ADDR 0x68
|
||||||
|
#define BQ24193_I2C_ADDR 0x6B
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
I2C_1 = 0,
|
I2C_1 = 0,
|
||||||
|
|
|
@ -35,6 +35,7 @@ static inline uint32_t get_clk_source_reg(CarDevice dev) {
|
||||||
case CARDEVICE_KFUSE: return 0;
|
case CARDEVICE_KFUSE: return 0;
|
||||||
case CARDEVICE_CL_DVFS: return 0;
|
case CARDEVICE_CL_DVFS: return 0;
|
||||||
case CARDEVICE_CORESIGHT: return 0x1D4;
|
case CARDEVICE_CORESIGHT: return 0x1D4;
|
||||||
|
case CARDEVICE_MSELECT: return 0x3B4;
|
||||||
case CARDEVICE_ACTMON: return 0x3E8;
|
case CARDEVICE_ACTMON: return 0x3E8;
|
||||||
case CARDEVICE_BPMP: return 0;
|
case CARDEVICE_BPMP: return 0;
|
||||||
default: generic_panic();
|
default: generic_panic();
|
||||||
|
@ -58,6 +59,7 @@ static inline uint32_t get_clk_source_val(CarDevice dev) {
|
||||||
case CARDEVICE_KFUSE: return 0;
|
case CARDEVICE_KFUSE: return 0;
|
||||||
case CARDEVICE_CL_DVFS: return 0;
|
case CARDEVICE_CL_DVFS: return 0;
|
||||||
case CARDEVICE_CORESIGHT: return 0;
|
case CARDEVICE_CORESIGHT: return 0;
|
||||||
|
case CARDEVICE_MSELECT: return 0;
|
||||||
case CARDEVICE_ACTMON: return 6;
|
case CARDEVICE_ACTMON: return 6;
|
||||||
case CARDEVICE_BPMP: return 0;
|
case CARDEVICE_BPMP: return 0;
|
||||||
default: generic_panic();
|
default: generic_panic();
|
||||||
|
@ -81,6 +83,7 @@ static inline uint32_t get_clk_source_div(CarDevice dev) {
|
||||||
case CARDEVICE_KFUSE: return 0;
|
case CARDEVICE_KFUSE: return 0;
|
||||||
case CARDEVICE_CL_DVFS: return 0;
|
case CARDEVICE_CL_DVFS: return 0;
|
||||||
case CARDEVICE_CORESIGHT: return 4;
|
case CARDEVICE_CORESIGHT: return 4;
|
||||||
|
case CARDEVICE_MSELECT: return 6;
|
||||||
case CARDEVICE_ACTMON: return 0;
|
case CARDEVICE_ACTMON: return 0;
|
||||||
case CARDEVICE_BPMP: return 0;
|
case CARDEVICE_BPMP: return 0;
|
||||||
default: generic_panic();
|
default: generic_panic();
|
||||||
|
|
|
@ -51,6 +51,7 @@ typedef enum {
|
||||||
CARDEVICE_USB2 = ((1 << 5) | 0x1A),
|
CARDEVICE_USB2 = ((1 << 5) | 0x1A),
|
||||||
CARDEVICE_CORESIGHT = ((2 << 5) | 0x9),
|
CARDEVICE_CORESIGHT = ((2 << 5) | 0x9),
|
||||||
CARDEVICE_TSEC = ((2 << 5) | 0x13),
|
CARDEVICE_TSEC = ((2 << 5) | 0x13),
|
||||||
|
CARDEVICE_MSELECT = ((3 << 5) | 0x8),
|
||||||
CARDEVICE_ACTMON = ((3 << 5) | 0x17),
|
CARDEVICE_ACTMON = ((3 << 5) | 0x17),
|
||||||
CARDEVICE_TZRAM = ((3 << 5) | 0x1E),
|
CARDEVICE_TZRAM = ((3 << 5) | 0x1E),
|
||||||
CARDEVICE_SE = ((3 << 5) | 0x1F),
|
CARDEVICE_SE = ((3 << 5) | 0x1F),
|
||||||
|
|
|
@ -14,87 +14,109 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "cluster.h"
|
#include "cluster.h"
|
||||||
#include "flow.h"
|
#include "flow.h"
|
||||||
#include "sysreg.h"
|
#include "sysreg.h"
|
||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
#include "car.h"
|
#include "car.h"
|
||||||
|
#include "fuse.h"
|
||||||
#include "mc.h"
|
#include "mc.h"
|
||||||
#include "timers.h"
|
#include "timers.h"
|
||||||
#include "pmc.h"
|
#include "pmc.h"
|
||||||
#include "max77620.h"
|
#include "max77620.h"
|
||||||
|
#include "max77812.h"
|
||||||
|
|
||||||
void _cluster_enable_power()
|
/* Determine the current SoC for Mariko specific code. */
|
||||||
{
|
static bool is_soc_mariko() {
|
||||||
/* Reboot I2C5. */
|
return (fuse_get_soc_type() == 1);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
volatile tegra_pmc_t *pmc = pmc_get_regs();
|
||||||
|
|
||||||
/* Check if the partition has already been turned on. */
|
/* Check if the partition has already been turned on. */
|
||||||
if (pmc->pwrgate_status & part)
|
if (pmc->pwrgate_status & part) {
|
||||||
return 1;
|
return;
|
||||||
|
|
||||||
uint32_t i = 5001;
|
|
||||||
while (pmc->pwrgate_toggle & 0x100)
|
|
||||||
{
|
|
||||||
udelay(1);
|
|
||||||
i--;
|
|
||||||
if (i < 1)
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
pmc->pwrgate_toggle = (toggle | 0x100);
|
||||||
|
|
||||||
i = 5001;
|
i = 5001;
|
||||||
while (i > 0)
|
while (i > 0) {
|
||||||
{
|
/* Check if the partition has already been turned on. */
|
||||||
if (pmc->pwrgate_status & part)
|
if (pmc->pwrgate_status & part) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
udelay(1);
|
udelay(1);
|
||||||
i--;
|
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();
|
volatile tegra_car_t *car = car_get_regs();
|
||||||
|
|
||||||
/* Set ACTIVE_CLUSER to FAST. */
|
/* Set ACTIVE_CLUSER to FAST. */
|
||||||
FLOW_CTLR_BPMP_CLUSTER_CONTROL_0 &= 0xFFFFFFFE;
|
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;
|
car->pllx_misc3 &= 0xFFFFFFF7;
|
||||||
udelay(2);
|
udelay(2);
|
||||||
car->pllx_base = 0x80404E02;
|
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_misc = ((car->pllx_misc & 0xFFFBFFFF) | 0x40000);
|
||||||
car->pllx_base = 0x40404E02;
|
car->pllx_base = 0x40404E02;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!(car->pllx_base & 0x8000000)) {
|
while (!(car->pllx_base & 0x8000000)) {
|
||||||
/* Wait. */
|
/* Wait. */
|
||||||
}
|
}
|
||||||
|
@ -115,20 +137,20 @@ void cluster_boot_cpu0(uint32_t entry)
|
||||||
car->cclk_brst_pol = 0x20008888;
|
car->cclk_brst_pol = 0x20008888;
|
||||||
car->super_cclk_div = 0x80000000;
|
car->super_cclk_div = 0x80000000;
|
||||||
car->clk_enb_v_set = 1;
|
car->clk_enb_v_set = 1;
|
||||||
|
|
||||||
clkrst_reboot(CARDEVICE_CORESIGHT);
|
clkrst_reboot(CARDEVICE_CORESIGHT);
|
||||||
|
|
||||||
/* CAR2PMC_CPU_ACK_WIDTH should be set to 0. */
|
/* CAR2PMC_CPU_ACK_WIDTH should be set to 0. */
|
||||||
car->cpu_softrst_ctrl2 &= 0xFFFFF000;
|
car->cpu_softrst_ctrl2 &= 0xFFFFF000;
|
||||||
|
|
||||||
/* Enable CPU rail. */
|
/* Enable CPU rail. */
|
||||||
_cluster_pmc_enable_partition(1, 0);
|
cluster_pmc_enable_partition(1, 0);
|
||||||
|
|
||||||
/* Enable cluster 0 non-CPU. */
|
/* Enable cluster 0 non-CPU. */
|
||||||
_cluster_pmc_enable_partition(0x8000, 15);
|
cluster_pmc_enable_partition(0x8000, 15);
|
||||||
|
|
||||||
/* Enable CE0. */
|
/* Enable CE0. */
|
||||||
_cluster_pmc_enable_partition(0x4000, 14);
|
cluster_pmc_enable_partition(0x4000, 14);
|
||||||
|
|
||||||
/* Request and wait for RAM repair. */
|
/* Request and wait for RAM repair. */
|
||||||
FLOW_CTLR_RAM_REPAIR_0 = 1;
|
FLOW_CTLR_RAM_REPAIR_0 = 1;
|
||||||
|
@ -138,41 +160,104 @@ void cluster_boot_cpu0(uint32_t entry)
|
||||||
|
|
||||||
MAKE_EXCP_VEC_REG(0x100) = 0;
|
MAKE_EXCP_VEC_REG(0x100) = 0;
|
||||||
|
|
||||||
/* Check for reset vector lock. */
|
|
||||||
if (SB_CSR_0 & 2) {
|
|
||||||
generic_panic();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set reset vector. */
|
/* Set reset vector. */
|
||||||
SB_AA64_RESET_LOW_0 = (entry | 1);
|
SB_AA64_RESET_LOW_0 = (entry | 1);
|
||||||
SB_AA64_RESET_HIGH_0 = 0;
|
SB_AA64_RESET_HIGH_0 = 0;
|
||||||
|
|
||||||
/* Non-secure reset vector write disable. */
|
/* Non-secure reset vector write disable. */
|
||||||
SB_CSR_0 = 2;
|
SB_CSR_0 = 2;
|
||||||
(void)SB_CSR_0;
|
(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. */
|
/* Set CPU_STRICT_TZ_APERTURE_CHECK. */
|
||||||
/* NOTE: [4.0.0+] This was added, but it breaks Exosphère. */
|
/* NOTE: [4.0.0+] This was added, but it breaks Exosphère. */
|
||||||
/* MAKE_MC_REG(MC_TZ_SECURITY_CTRL) = 1; */
|
/* MAKE_MC_REG(MC_TZ_SECURITY_CTRL) = 1; */
|
||||||
|
|
||||||
/* Clear MSELECT reset. */
|
/* Clear MSELECT reset. */
|
||||||
car->rst_dev_v &= 0xFFFFFFF7;
|
car->rst_dev_v &= 0xFFFFFFF7;
|
||||||
|
|
||||||
/* Clear NONCPU reset. */
|
/* Clear NONCPU reset. */
|
||||||
car->rst_cpug_cmplx_clr = 0x20000000;
|
car->rst_cpug_cmplx_clr = 0x20000000;
|
||||||
|
|
||||||
/* Clear CPU{0,1,2,3} POR and CORE, CX0, L2, and DBG reset.*/
|
/* 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. */
|
/* NOTE: [5.0.0+] This was changed so only CPU0 reset is cleared. */
|
||||||
/* car->rst_cpug_cmplx_clr = 0x411F000F; */
|
/* car->rst_cpug_cmplx_clr = 0x411F000F; */
|
||||||
car->rst_cpug_cmplx_clr = 0x41010001;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -24,12 +24,14 @@
|
||||||
#define I2C1234_BASE 0x7000C000
|
#define I2C1234_BASE 0x7000C000
|
||||||
#define I2C56_BASE 0x7000D000
|
#define I2C56_BASE 0x7000D000
|
||||||
|
|
||||||
#define MAX77621_CPU_I2C_ADDR 0x1B
|
#define MAX77621_CPU_I2C_ADDR 0x1B
|
||||||
#define MAX77621_GPU_I2C_ADDR 0x1C
|
#define MAX77621_GPU_I2C_ADDR 0x1C
|
||||||
#define MAX17050_I2C_ADDR 0x36
|
#define MAX77812_PHASE31_CPU_I2C_ADDR 0x31
|
||||||
#define MAX77620_PWR_I2C_ADDR 0x3C
|
#define MAX77812_PHASE211_CPU_I2C_ADDR 0x33
|
||||||
#define MAX77620_RTC_I2C_ADDR 0x68
|
#define MAX17050_I2C_ADDR 0x36
|
||||||
#define BQ24193_I2C_ADDR 0x6B
|
#define MAX77620_PWR_I2C_ADDR 0x3C
|
||||||
|
#define MAX77620_RTC_I2C_ADDR 0x68
|
||||||
|
#define BQ24193_I2C_ADDR 0x6B
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
I2C_1 = 0,
|
I2C_1 = 0,
|
||||||
|
|
81
sept/sept-secondary/src/max77812.h
Normal file
81
sept/sept-secondary/src/max77812.h
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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
|
Loading…
Reference in a new issue