fusee: start fleshing out nxboot for Mariko

This commit is contained in:
hexkyz
2020-12-07 18:39:23 +00:00
committed by SciresM
parent 222300d03c
commit 4809ced64d
23 changed files with 804 additions and 308 deletions

View File

@@ -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();

View File

@@ -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),

View File

@@ -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,

View File

@@ -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();

View File

@@ -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),

View File

@@ -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);
}
}

View File

@@ -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,

View 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