mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-08 05:01:44 +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_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();
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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,
|
||||
|
|
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_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();
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
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
|
||||
};
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -14,87 +14,109 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
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