Update to hekate bdk 5.5.6

This commit is contained in:
shchmue 2021-05-12 15:38:34 -06:00
parent 93909f149e
commit a7712b173c
95 changed files with 2720 additions and 1684 deletions

View file

@ -1,7 +1,7 @@
/*
* BPMP-Lite Cache/MMU and Frequency driver for Tegra X1
*
* Copyright (c) 2019-2020 CTCaer
* Copyright (c) 2019-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -212,43 +212,45 @@ const u8 pll_divn[] = {
//95 // BPMP_CLK_DEV_BOOST: 608MHz 49% - 152MHz APB.
};
bpmp_freq_t bpmp_clock_set = BPMP_CLK_NORMAL;
bpmp_freq_t bpmp_fid_current = BPMP_CLK_NORMAL;
void bpmp_clk_rate_get()
{
bool clk_src_is_pllp = ((CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) >> 4) & 7) == 3;
if (clk_src_is_pllp)
bpmp_clock_set = BPMP_CLK_NORMAL;
bpmp_fid_current = BPMP_CLK_NORMAL;
else
{
bpmp_clock_set = BPMP_CLK_HIGH_BOOST;
bpmp_fid_current = BPMP_CLK_HIGH_BOOST;
u8 pll_divn_curr = (CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) >> 10) & 0xFF;
for (u32 i = 1; i < sizeof(pll_divn); i++)
{
if (pll_divn[i] == pll_divn_curr)
{
bpmp_clock_set = i;
bpmp_fid_current = i;
break;
}
}
}
}
void bpmp_clk_rate_set(bpmp_freq_t fid)
bpmp_freq_t bpmp_clk_rate_set(bpmp_freq_t fid)
{
bpmp_freq_t prev_fid = bpmp_fid_current;
if (fid > (BPMP_CLK_MAX - 1))
fid = BPMP_CLK_MAX - 1;
if (bpmp_clock_set == fid)
return;
if (prev_fid == fid)
return prev_fid;
if (fid)
{
if (bpmp_clock_set)
if (prev_fid)
{
// Restore to PLLP source during PLLC4 configuration.
// Restore to PLLP source during PLLC configuration.
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003333; // PLLP_OUT.
msleep(1); // Wait a bit for clock source change.
}
@ -269,7 +271,10 @@ void bpmp_clk_rate_set(bpmp_freq_t fid)
// Disable PLLC to save power.
clock_disable_pllc();
}
bpmp_clock_set = fid;
bpmp_fid_current = fid;
// Return old fid in case of temporary swap.
return prev_fid;
}
// The following functions halt BPMP to reduce power while sleeping.

View file

@ -1,7 +1,7 @@
/*
* BPMP-Lite Cache/MMU and Frequency driver for Tegra X1
*
* Copyright (c) 2019-2020 CTCaer
* Copyright (c) 2019-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -53,6 +53,7 @@ typedef enum
BPMP_CLK_MAX
} bpmp_freq_t;
#define BPMP_CLK_LOWER_BOOST BPMP_CLK_SUPER_BOOST
#define BPMP_CLK_DEFAULT_BOOST BPMP_CLK_HYPER_BOOST
void bpmp_mmu_maintenance(u32 op, bool force);
@ -60,7 +61,7 @@ void bpmp_mmu_set_entry(int idx, bpmp_mmu_entry_t *entry, bool apply);
void bpmp_mmu_enable();
void bpmp_mmu_disable();
void bpmp_clk_rate_get();
void bpmp_clk_rate_set(bpmp_freq_t fid);
bpmp_freq_t bpmp_clk_rate_set(bpmp_freq_t fid);
void bpmp_usleep(u32 us);
void bpmp_msleep(u32 ms);
void bpmp_halt();

View file

@ -16,7 +16,6 @@
*/
#include <soc/ccplex.h>
#include <soc/fuse.h>
#include <soc/hw_init.h>
#include <soc/i2c.h>
#include <soc/clock.h>
@ -29,27 +28,24 @@
void _ccplex_enable_power_t210()
{
u8 tmp = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO); // Get current pinmuxing
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_AME_GPIO, tmp & ~BIT(5)); // Disable GPIO5 pinmuxing.
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO5, MAX77620_CNFG_GPIO_DRV_PUSHPULL | MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH);
// Configure GPIO5 and enable output in order to power CPU pmic.
max77620_config_gpio(5, MAX77620_GPIO_OUTPUT_ENABLE);
// Enable cores power.
// Configure CPU pmic.
// 1-3.x: MAX77621_NFSR_ENABLE.
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL1_REG,
MAX77621_AD_ENABLE | MAX77621_NFSR_ENABLE | MAX77621_SNS_ENABLE | MAX77621_RAMP_12mV_PER_US);
// 1.0.0-3.x: MAX77621_T_JUNCTION_120 | MAX77621_CKKADV_TRIP_DISABLE | MAX77621_INDUCTOR_NOMINAL.
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL2_REG,
MAX77621_T_JUNCTION_120 | MAX77621_WDTMR_ENABLE | MAX77621_CKKADV_TRIP_75mV_PER_US| MAX77621_INDUCTOR_NOMINAL);
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_0_95V);
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_DVS_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_0_95V);
max77621_config_default(REGULATOR_CPU0, MAX77621_CTRL_HOS_CFG);
// Set voltage and enable cores power.
max7762x_regulator_set_voltage(REGULATOR_CPU0, 950000);
max7762x_regulator_enable(REGULATOR_CPU0, true);
}
void _ccplex_enable_power_t210b01()
{
u8 pmic_cpu_addr = !(FUSE(FUSE_RESERVED_ODM28) & 1) ? MAX77812_PHASE31_CPU_I2C_ADDR : MAX77812_PHASE211_CPU_I2C_ADDR;
u8 tmp = i2c_recv_byte(I2C_5, pmic_cpu_addr, MAX77812_REG_EN_CTRL);
i2c_send_byte(I2C_5, pmic_cpu_addr, MAX77812_REG_EN_CTRL, tmp | MAX77812_EN_CTRL_EN_M4);
i2c_send_byte(I2C_5, pmic_cpu_addr, MAX77812_REG_M4_VOUT, MAX77812_M4_VOUT_0_80V);
// Set voltage and enable cores power.
max7762x_regulator_set_voltage(REGULATOR_CPU1, 800000);
max7762x_regulator_enable(REGULATOR_CPU1, true);
}
void ccplex_boot_cpu0(u32 entry)
@ -62,24 +58,31 @@ void ccplex_boot_cpu0(u32 entry)
else
_ccplex_enable_power_t210b01();
if (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & 0x40000000)) // PLLX_ENABLE.
// Enable PLLX and set it to 300 MHz.
if (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & PLLX_BASE_ENABLE)) // PLLX_ENABLE.
{
CLOCK(CLK_RST_CONTROLLER_PLLX_MISC_3) &= 0xFFFFFFF7; // Disable IDDQ.
usleep(2);
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x80404E02;
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x404E02;
// Bypass dividers.
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = PLLX_BASE_BYPASS | (4 << 20) | (78 << 8) | 2; // P div: 4 (5), N div: 78, M div: 2.
// Disable bypass
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = (4 << 20) | (78 << 8) | 2;
// Set PLLX_LOCK_ENABLE.
CLOCK(CLK_RST_CONTROLLER_PLLX_MISC) = (CLOCK(CLK_RST_CONTROLLER_PLLX_MISC) & 0xFFFBFFFF) | 0x40000;
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = 0x40404E02;
// Enable PLLX.
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = PLLX_BASE_ENABLE | (4 << 20) | (78 << 8) | 2;
}
while (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & 0x8000000))
// Wait for PLL to stabilize.
while (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & PLLX_BASE_LOCK))
;
// Configure MSELECT source and enable clock.
// Configure MSELECT source and enable clock to 102MHz.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) & 0x1FFFFF00) | 6;
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) = (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) & ~BIT(CLK_V_MSELECT)) | BIT(CLK_V_MSELECT);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = BIT(CLK_V_MSELECT);
// Configure initial CPU clock frequency and enable clock.
CLOCK(CLK_RST_CONTROLLER_CCLK_BURST_POLICY) = 0x20008888;
CLOCK(CLK_RST_CONTROLLER_CCLK_BURST_POLICY) = 0x20008888; // PLLX_OUT0_LJ.
CLOCK(CLK_RST_CONTROLLER_SUPER_CCLK_DIVIDER) = 0x80000000;
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = BIT(CLK_V_CPUG);
@ -88,12 +91,12 @@ void ccplex_boot_cpu0(u32 entry)
// CAR2PMC_CPU_ACK_WIDTH should be set to 0.
CLOCK(CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2) &= 0xFFFFF000;
// Enable CPU rail.
pmc_enable_partition(0, 1);
// Enable CPU main rail.
pmc_enable_partition(POWER_RAIL_CRAIL, ENABLE);
// Enable cluster 0 non-CPU rail.
pmc_enable_partition(15, 1);
// Enable CE0 rail.
pmc_enable_partition(14, 1);
pmc_enable_partition(POWER_RAIL_C0NC, ENABLE);
// Enable CPU0 rail.
pmc_enable_partition(POWER_RAIL_CE0, ENABLE);
// Request and wait for RAM repair.
FLOW_CTLR(FLOW_CTLR_RAM_REPAIR) = 1;
@ -113,7 +116,7 @@ void ccplex_boot_cpu0(u32 entry)
// MC(MC_TZ_SECURITY_CTRL) = 1;
// Clear MSELECT reset.
CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_V) &= ~BIT(CLK_V_MSELECT);
CLOCK(CLK_RST_CONTROLLER_RST_DEV_V_CLR) = BIT(CLK_V_MSELECT);
// Clear NONCPU reset.
CLOCK(CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR) = 0x20000000;
// Clear CPU0 reset.

View file

@ -21,6 +21,23 @@
#include <storage/sdmmc.h>
#include <utils/util.h>
typedef struct _clock_osc_t
{
u32 freq;
u16 min;
u16 max;
} clock_osc_t;
static const clock_osc_t _clock_osc_cnt[] = {
{ 12000, 706, 757 },
{ 13000, 766, 820 },
{ 16800, 991, 1059 },
{ 19200, 1133, 1210 },
{ 26000, 1535, 1638 },
{ 38400, 2268, 2418 },
{ 48000, 2836, 3023 }
};
/* clock_t: reset, enable, source, index, clk_src, clk_div */
static const clock_t _clock_uart[] = {
@ -42,7 +59,7 @@ static const clock_t _clock_i2c[] = {
};
static clock_t _clock_se = {
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_SE, CLK_V_SE, 0, 0
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_SE, CLK_V_SE, 0, 0 // 408MHz.
};
static clock_t _clock_tzram = {
@ -50,19 +67,19 @@ static clock_t _clock_tzram = {
};
static clock_t _clock_host1x = {
CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X, CLK_L_HOST1X, 4, 3
CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X, CLK_L_HOST1X, 4, 3 // 163.2MHz.
};
static clock_t _clock_tsec = {
CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_TSEC, CLK_U_TSEC, 0, 2
CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_TSEC, CLK_U_TSEC, 0, 2 // 204MHz.
};
static clock_t _clock_sor_safe = {
CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_NO_SOURCE, CLK_Y_SOR_SAFE, 0, 0
};
static clock_t _clock_sor0 = {
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_NO_SOURCE, CLK_X_SOR0, 0, 0
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_NOT_USED, CLK_X_SOR0, 0, 0
};
static clock_t _clock_sor1 = {
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_SOR1, CLK_X_SOR1, 0, 2
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_SOR1, CLK_X_SOR1, 0, 2 //204MHz.
};
static clock_t _clock_kfuse = {
CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_KFUSE, 0, 0
@ -72,11 +89,11 @@ static clock_t _clock_cl_dvfs = {
CLK_RST_CONTROLLER_RST_DEVICES_W, CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_NO_SOURCE, CLK_W_DVFS, 0, 0
};
static clock_t _clock_coresight = {
CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_CSITE, CLK_U_CSITE, 0, 4
CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_CSITE, CLK_U_CSITE, 0, 4 // 136MHz.
};
static clock_t _clock_pwm = {
CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, CLK_L_PWM, 6, 4 // Fref: 6.4MHz. Stock PLLP / 54: 7.55MHz.
CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, CLK_L_PWM, 6, 4 // Fref: 6.4MHz. HOS: PLLP / 54 = 7.55MHz.
};
static clock_t _clock_sdmmc_legacy_tm = {
@ -218,13 +235,13 @@ void clock_disable_sor1()
void clock_enable_kfuse()
{
u32 kfuse_clk_unmask = ~BIT(CLK_H_KFUSE);
CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) = (CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) & kfuse_clk_unmask) | BIT(CLK_H_KFUSE);
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) &= kfuse_clk_unmask;
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) = (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) & kfuse_clk_unmask) | BIT(CLK_H_KFUSE);
usleep(10);
CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) &= kfuse_clk_unmask;
usleep(20);
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = BIT(CLK_H_KFUSE);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_CLR) = BIT(CLK_H_KFUSE);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_KFUSE);
usleep(10); // Wait 10s to prevent glitching.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_KFUSE);
usleep(20); // Wait 20s fo kfuse hw to init.
}
void clock_disable_kfuse()
@ -721,3 +738,44 @@ void clock_sdmmc_disable(u32 id)
_clock_sdmmc_is_reset(id);
_clock_disable_pllc4(BIT(id));
}
u32 clock_get_osc_freq()
{
CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET) = OSC_FREQ_DET_TRIG | (2 - 1); // 2 periods of 32.76KHz window.
while (CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_BUSY)
;
u32 cnt = (CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_CNT);
CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET) = 0;
// Return frequency in KHz.
for (u32 i = 0; i < ARRAY_SIZE(_clock_osc_cnt); i++)
if (cnt >= _clock_osc_cnt[i].min && cnt <= _clock_osc_cnt[i].max)
return _clock_osc_cnt[i].freq;
return 0;
}
u32 clock_get_dev_freq(clock_pto_id_t id)
{
u32 val = ((id & PTO_SRC_SEL_MASK) << PTO_SRC_SEL_SHIFT) | PTO_DIV_SEL_DIV1 | PTO_CLK_ENABLE | (16 - 1); // 16 periods of 32.76KHz window.
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val;
usleep(2);
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val | PTO_CNT_RST;
usleep(2);
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val;
usleep(2);
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val | PTO_CNT_EN;
usleep(502);
while (CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_STATUS) & PTO_CLK_CNT_BUSY)
;
u32 cnt = CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_STATUS) & PTO_CLK_CNT;
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = 0;
u32 freq = ((cnt << 8) | 0x3E) / 125;
return freq;
}

View file

@ -35,6 +35,10 @@
#define CLK_RST_CONTROLLER_CLK_SYSTEM_RATE 0x30
#define CLK_RST_CONTROLLER_MISC_CLK_ENB 0x48
#define CLK_RST_CONTROLLER_OSC_CTRL 0x50
#define CLK_RST_CONTROLLER_OSC_FREQ_DET 0x58
#define CLK_RST_CONTROLLER_OSC_FREQ_DET_STATUS 0x5C
#define CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL 0x60
#define CLK_RST_CONTROLLER_PTO_CLK_CNT_STATUS 0x64
#define CLK_RST_CONTROLLER_PLLC_BASE 0x80
#define CLK_RST_CONTROLLER_PLLC_OUT 0x84
#define CLK_RST_CONTROLLER_PLLC_MISC 0x88
@ -156,11 +160,18 @@
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTAPE 0x710
#define CLK_NO_SOURCE 0x0
#define CLK_NOT_USED 0x0
/*! PLL control and status bits */
#define PLLX_BASE_LOCK BIT(27)
#define PLLX_BASE_REF_DIS BIT(29)
#define PLLX_BASE_ENABLE BIT(30)
#define PLLX_BASE_BYPASS BIT(31)
#define PLLCX_BASE_LOCK BIT(27)
#define PLLCX_BASE_REF_DIS BIT(29)
#define PLLCX_BASE_ENABLE BIT(30)
#define PLLCX_BASE_BYPASS BIT(31)
#define PLLA_OUT0_RSTN_CLR BIT(0)
#define PLLA_OUT0_CLKEN BIT(1)
@ -178,6 +189,140 @@
#define UTMIPLL_LOCK BIT(31)
/*! PTO_CLK_CNT */
#define PTO_REF_CLK_WIN_CFG_MASK 0xF
#define PTO_REF_CLK_WIN_CFG_16P 0xF
#define PTO_CNT_EN BIT(9)
#define PTO_CNT_RST BIT(10)
#define PTO_CLK_ENABLE BIT(13)
#define PTO_SRC_SEL_SHIFT 14
#define PTO_SRC_SEL_MASK 0x1FF
#define PTO_DIV_SEL_MASK (3 << 23)
#define PTO_DIV_SEL_GATED (0 << 23)
#define PTO_DIV_SEL_DIV1 (1 << 23)
#define PTO_DIV_SEL_DIV2_RISING (2 << 23)
#define PTO_DIV_SEL_DIV2_FALLING (3 << 23)
#define PTO_DIV_SEL_CPU_EARLY (0 << 23)
#define PTO_DIV_SEL_CPU_LATE (1 << 23)
#define PTO_CLK_CNT_BUSY BIT(31)
#define PTO_CLK_CNT 0xFFFFFF
/*! OSC_FREQ_DET */
#define OSC_REF_CLK_WIN_CFG_MASK 0xF
#define OSC_FREQ_DET_TRIG BIT(31)
#define OSC_FREQ_DET_BUSY BIT(31)
#define OSC_FREQ_DET_CNT 0xFFFF
/*! PLLs omitted as they need PTO enabled in MISC registers. Norm div is 2. */
typedef enum _clock_pto_id_t
{
CLK_PTO_PCLK_SYS = 0x06,
CLK_PTO_HCLK_SYS = 0x07,
CLK_PTO_UTMIP_240 = 0x0C,
CLK_PTO_CCLK_G = 0x12,
CLK_PTO_CCLK_G_DIV2 = 0x13,
CLK_PTO_SPI1 = 0x17,
CLK_PTO_SPI2 = 0x18,
CLK_PTO_SPI3 = 0x19,
CLK_PTO_SPI4 = 0x1A,
CLK_PTO_MAUD = 0x1B,
CLK_PTO_SCLK = 0x1C,
CLK_PTO_SDMMC1 = 0x20,
CLK_PTO_SDMMC2 = 0x21,
CLK_PTO_SDMMC3 = 0x22,
CLK_PTO_SDMMC4 = 0x23,
CLK_PTO_EMC = 0x24,
CLK_PTO_MSELECT = 0x2F,
CLK_PTO_VIC = 0x36,
CLK_PTO_NVDEC = 0x39,
CLK_PTO_NVENC = 0x3A,
CLK_PTO_NVJPG = 0x3B,
CLK_PTO_TSEC = 0x3C,
CLK_PTO_TSECB = 0x3D,
CLK_PTO_SE = 0x3E,
CLK_PTO_DSIA_LP = 0x62,
CLK_PTO_ISP = 0x64,
CLK_PTO_MC = 0x6A,
CLK_PTO_ACTMON = 0x6B,
CLK_PTO_CSITE = 0x6C,
CLK_PTO_HOST1X = 0x6F,
CLK_PTO_SE_2 = 0x74, // Same as CLK_PTO_SE.
CLK_PTO_SOC_THERM = 0x75,
CLK_PTO_TSEC_2 = 0x77, // Same as CLK_PTO_TSEC.
CLK_PTO_ACLK = 0x7C,
CLK_PTO_QSPI = 0x7D,
CLK_PTO_I2S1 = 0x80,
CLK_PTO_I2S2 = 0x81,
CLK_PTO_I2S3 = 0x82,
CLK_PTO_I2S4 = 0x83,
CLK_PTO_I2S5 = 0x84,
CLK_PTO_AHUB = 0x85,
CLK_PTO_APE = 0x86,
CLK_PTO_DVFS_SOC = 0x88,
CLK_PTO_DVFS_REF = 0x89,
CLK_PTO_SPDIF = 0x8F,
CLK_PTO_SPDIF_IN = 0x90,
CLK_PTO_UART_FST_MIPI_CAL = 0x91,
CLK_PTO_PWM = 0x93,
CLK_PTO_I2C1 = 0x94,
CLK_PTO_I2C2 = 0x95,
CLK_PTO_I2C3 = 0x96,
CLK_PTO_I2C4 = 0x97,
CLK_PTO_I2C5 = 0x98,
CLK_PTO_I2C6 = 0x99,
CLK_PTO_I2C_SLOW = 0x9A,
CLK_PTO_UARTAPE = 0x9B,
CLK_PTO_EXTPERIPH1 = 0x9D,
CLK_PTO_EXTPERIPH2 = 0x9E,
CLK_PTO_ENTROPY = 0xA0,
CLK_PTO_UARTA = 0xA1,
CLK_PTO_UARTB = 0xA2,
CLK_PTO_UARTC = 0xA3,
CLK_PTO_UARTD = 0xA4,
CLK_PTO_OWR = 0xA5,
CLK_PTO_HDA2CODEC_2X = 0xA7,
CLK_PTO_HDA = 0xA8,
CLK_PTO_SDMMC_LEGACY_TM = 0xAB,
CLK_PTO_SOR0 = 0xC0,
CLK_PTO_SOR1 = 0xC1,
CLK_PTO_DISP2 = 0xC4,
CLK_PTO_DISP1 = 0xC5,
CLK_PTO_XUSB_FALCON = 0x110,
CLK_PTO_XUSB_FS = 0x136,
CLK_PTO_XUSB_SS_HOST_DEV = 0x137,
CLK_PTO_XUSB_CORE_HOST = 0x138,
CLK_PTO_XUSB_CORE_DEV = 0x139,
} clock_pto_id_t;
/*
* CLOCK Peripherals:
* L 0 - 31
@ -216,7 +361,7 @@ enum CLK_L_DEV
CLK_L_USBD = 22,
CLK_L_ISP = 23,
CLK_L_3D = 24, // HIDDEN.
//CLK_L_ = 25,
CLK_L_IDE = 25, // RESERVED.
CLK_L_DISP2 = 26,
CLK_L_DISP1 = 27,
CLK_L_HOST1X = 28,
@ -244,11 +389,11 @@ enum CLK_H_DEV
CLK_H_SPI3 = 14,
CLK_H_I2C5 = 15,
CLK_H_DSI = 16,
//CLK_H_ = 17,
CLK_H_TVO = 17, // RESERVED.
CLK_H_HSI = 18, // HIDDEN.
CLK_H_HDMI = 19, // HIDDEN.
CLK_H_CSI = 20,
//CLK_H_ = 21,
CLK_H_TVDAC = 21, // RESERVED.
CLK_H_I2C2 = 22,
CLK_H_UARTC = 23,
CLK_H_MIPI_CAL = 24,
@ -263,14 +408,14 @@ enum CLK_H_DEV
enum CLK_U_DEV
{
//CLK_U_ = 0,
CLK_U_SPEEDO = 0, // RESERVED.
CLK_U_UARTD = 1,
CLK_U_UARTE = 2, // HIDDEN.
CLK_U_I2C3 = 3,
CLK_U_SPI4 = 4,
CLK_U_SDMMC3 = 5,
CLK_U_PCIE = 6,
CLK_U_UNUSED = 7, // RESERVED
CLK_U_OWR = 7, // RESERVED.
CLK_U_AFI = 8,
CLK_U_CSITE = 9,
CLK_U_PCIEXCLK = 10, // Only reset.
@ -444,9 +589,9 @@ enum CLK_Y_DEV
/*! Generic clock descriptor. */
typedef struct _clock_t
{
u32 reset;
u32 enable;
u32 source;
u16 reset;
u16 enable;
u16 source;
u8 index;
u8 clk_src;
u8 clk_div;
@ -494,4 +639,7 @@ int clock_sdmmc_is_not_reset_and_enabled(u32 id);
void clock_sdmmc_enable(u32 id, u32 val);
void clock_sdmmc_disable(u32 id);
u32 clock_get_osc_freq();
u32 clock_get_dev_freq(clock_pto_id_t id);
#endif

View file

@ -2,7 +2,7 @@
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 shuffle2
* Copyright (c) 2018 balika011
* Copyright (c) 2019 CTCaer
* Copyright (c) 2019-2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -76,6 +76,35 @@ u32 fuse_read_odm_keygen_rev()
return 0;
}
u32 fuse_read_dramid(bool raw_id)
{
u32 dramid = (fuse_read_odm(4) & 0xF8) >> 3;
if (raw_id)
return dramid;
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210)
{
if (dramid > 6)
dramid = 0;
}
else
{
if (dramid > 27)
dramid = 8;
}
return dramid;
}
u32 fuse_read_hw_state()
{
if ((fuse_read_odm(4) & 3) != 3)
return FUSE_NX_HW_STATE_PROD;
else
return FUSE_NX_HW_STATE_DEV;
}
u32 fuse_read_hw_type()
{
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01)
@ -118,6 +147,7 @@ u32 fuse_read(u32 addr)
FUSE(FUSE_ADDR) = addr;
FUSE(FUSE_CTRL) = (FUSE(FUSE_ADDR) & ~FUSE_CMD_MASK) | FUSE_READ;
fuse_wait_idle();
return FUSE(FUSE_RDATA);
}

View file

@ -2,6 +2,7 @@
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 shuffle2
* Copyright (c) 2018 balika011
* Copyright (c) 2019-2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -64,9 +65,10 @@
#define FUSE_OPT_X_COORDINATE 0x214
#define FUSE_OPT_Y_COORDINATE 0x218
#define FUSE_GPU_IDDQ_CALIB 0x228
#define FUSE_RESERVED_ODM28 0x240
#define FUSE_USB_CALIB_EXT 0x350
#define FUSE_RESERVED_ODM28_T210B01 0x240
/*! Fuse commands. */
#define FUSE_READ 0x1
#define FUSE_WRITE 0x2
@ -83,9 +85,17 @@ enum
FUSE_NX_HW_TYPE_HOAG
};
enum
{
FUSE_NX_HW_STATE_PROD,
FUSE_NX_HW_STATE_DEV
};
void fuse_disable_program();
u32 fuse_read_odm(u32 idx);
u32 fuse_read_odm_keygen_rev();
u32 fuse_read_dramid(bool raw_id);
u32 fuse_read_hw_state();
u32 fuse_read_hw_type();
u8 fuse_count_burnt(u32 val);
void fuse_wait_idle();

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -18,7 +18,7 @@
#include <string.h>
#include <soc/hw_init.h>
#include <gfx/di.h>
#include <display/di.h>
#include <input/joycon.h>
#include <input/touch.h>
#include <sec/se.h>
@ -42,6 +42,7 @@
#include <storage/nx_sd.h>
#include <storage/sdmmc.h>
#include <thermal/fan.h>
#include <thermal/tmp451.h>
#include <utils/util.h>
extern boot_cfg_t b_cfg;
@ -87,6 +88,7 @@ static void _config_oscillators()
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // Set HCLK div to 1 and PCLK div to 3.
}
// The uart is skipped for Copper, Hoag and Calcio. Used in Icosa, Iowa and Aula.
static void _config_gpios(bool nx_hoag)
{
// Clamp inputs when tristated.
@ -263,7 +265,7 @@ static void _config_se_brom()
FUSE(FUSE_PRIVATE_KEY3)
};
// Set SBK to slot 14.
se_aes_key_set(14, sbk, 0x10);
se_aes_key_set(14, sbk, SE_KEY_128_SIZE);
// Lock SBK from being read.
se_key_acc_ctrl(14, SE_KEY_TBL_DIS_KEYREAD_FLAG);
@ -275,7 +277,7 @@ static void _config_se_brom()
// This memset needs to happen here, else TZRAM will behave weirdly later on.
memset((void *)TZRAM_BASE, 0, 0x10000);
PMC(APBDEV_PMC_CRYPTO_OP) = PMC_CRYPTO_OP_SE_ENABLE;
SE(SE_INT_STATUS_REG_OFFSET) = 0x1F;
SE(SE_INT_STATUS_REG) = 0x1F; // Clear all SE interrupts.
// Clear the boot reason to avoid problems later
PMC(APBDEV_PMC_SCRATCH200) = 0x0;
@ -285,17 +287,21 @@ static void _config_se_brom()
static void _config_regulators(bool tegra_t210)
{
// Set RTC/AO domain to POR voltage.
if (tegra_t210)
max7762x_regulator_set_voltage(REGULATOR_LDO4, 1000000);
// Disable low battery shutdown monitor.
max77620_low_battery_monitor_config(false);
// Disable SDMMC1 IO power.
gpio_write(GPIO_PORT_E, GPIO_PIN_4, GPIO_LOW);
max77620_regulator_enable(REGULATOR_LDO2, 0);
max7762x_regulator_enable(REGULATOR_LDO2, false);
sd_power_cycle_time_start = get_tmr_ms();
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CNFGBBC, MAX77620_CNFGBBC_RESISTOR_1K);
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1,
BIT(6) | (3 << MAX77620_ONOFFCNFG1_MRT_SHIFT)); // PWR delay for forced shutdown off.
MAX77620_ONOFFCNFG1_RSVD | (3 << MAX77620_ONOFFCNFG1_MRT_SHIFT)); // PWR delay for forced shutdown off.
if (tegra_t210)
{
@ -313,28 +319,18 @@ static void _config_regulators(bool tegra_t210)
(4 << MAX77620_FPS_TIME_PERIOD_SHIFT) | (2 << MAX77620_FPS_PD_PERIOD_SHIFT)); // 3.x+
// Set vdd_core voltage to 1.125V.
max77620_regulator_set_voltage(REGULATOR_SD0, 1125000);
max7762x_regulator_set_voltage(REGULATOR_SD0, 1125000);
// Fix CPU/GPU after a L4T warmboot.
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO5, 2);
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO6, 2);
// Fix CPU/GPU after L4T warmboot.
max77620_config_gpio(5, MAX77620_GPIO_OUTPUT_DISABLE);
max77620_config_gpio(6, MAX77620_GPIO_OUTPUT_DISABLE);
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_REG, MAX77621_VOUT_0_95V); // Disable power.
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_DVS_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_1_09V); // Enable DVS power.
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL1_REG, MAX77621_RAMP_50mV_PER_US);
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_CONTROL2_REG,
MAX77621_T_JUNCTION_120 | MAX77621_FT_ENABLE | MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS |
MAX77621_CKKADV_TRIP_150mV_PER_US | MAX77621_INDUCTOR_NOMINAL);
i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_VOUT_REG, MAX77621_VOUT_0_95V); // Disable power.
i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_VOUT_DVS_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_1_09V); // Enable DVS power.
i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_CONTROL1_REG, MAX77621_RAMP_50mV_PER_US);
i2c_send_byte(I2C_5, MAX77621_GPU_I2C_ADDR, MAX77621_CONTROL2_REG,
MAX77621_T_JUNCTION_120 | MAX77621_FT_ENABLE | MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS |
MAX77621_CKKADV_TRIP_150mV_PER_US | MAX77621_INDUCTOR_NOMINAL);
// Set POR configuration.
max77621_config_default(REGULATOR_CPU0, MAX77621_CTRL_POR_CFG);
max77621_config_default(REGULATOR_GPU0, MAX77621_CTRL_POR_CFG);
}
else // Tegra X1+ set vdd_core voltage to 1.05V.
max77620_regulator_set_voltage(REGULATOR_SD0, 1050000);
max7762x_regulator_set_voltage(REGULATOR_SD0, 1050000);
}
void hw_init()
@ -373,7 +369,8 @@ void hw_init()
#ifdef DEBUG_UART_PORT
clock_enable_uart(DEBUG_UART_PORT);
uart_init(DEBUG_UART_PORT, 115200);
uart_init(DEBUG_UART_PORT, DEBUG_UART_BAUDRATE);
uart_invert(DEBUG_UART_PORT, DEBUG_UART_INVERT, UART_INVERT_TXD);
#endif
// Enable Dynamic Voltage and Frequency Scaling device clock.
@ -391,17 +388,20 @@ void hw_init()
//! TODO: Why? Device is NFC MCU on Lite.
if (nx_hoag)
max77620_regulator_set_volt_and_flags(REGULATOR_LDO8, 2800000, MAX77620_POWER_MODE_NORMAL);
{
max7762x_regulator_set_voltage(REGULATOR_LDO8, 2800000);
max7762x_regulator_enable(REGULATOR_LDO8, true);
}
// Initialize I2C1 for various power related devices.
i2c_init(I2C_1);
// Enable charger in case it's disabled.
bq24193_enable_charger();
// Initialize various regulators based on Erista/Mariko platform.
_config_regulators(tegra_t210);
// Enable charger in case it's disabled.
bq24193_enable_charger();
_config_pmc_scratch(); // Missing from 4.x+
// Set BPMP/SCLK to PLLP_OUT (408MHz).
@ -421,19 +421,18 @@ void hw_init()
bpmp_mmu_enable();
}
void hw_reinit_workaround(bool extra_reconfig, u32 magic)
void hw_reinit_workaround(bool coreboot, u32 bl_magic)
{
// Disable BPMP max clock.
bpmp_clk_rate_set(BPMP_CLK_NORMAL);
#ifdef NYX
// Deinit touchscreen, 5V regulators and Joy-Con.
touch_power_off();
// Disable temperature sensor, touchscreen, 5V regulators and Joy-Con.
tmp451_end();
set_fan_duty(0);
touch_power_off();
jc_deinit();
regulator_disable_5v(REGULATOR_5V_ALL);
clock_disable_uart(UART_B);
clock_disable_uart(UART_C);
regulator_5v_disable(REGULATOR_5V_ALL);
#endif
// Flush/disable MMU cache and set DRAM clock to 204MHz.
@ -445,10 +444,10 @@ void hw_reinit_workaround(bool extra_reconfig, u32 magic)
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= BIT(CLK_V_AHUB);
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= BIT(CLK_Y_APE);
if (extra_reconfig)
// Do coreboot mitigations.
if (coreboot)
{
msleep(10);
PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_SDMMC1_IO_EN;
clock_disable_cl_dvfs();
@ -457,13 +456,27 @@ void hw_reinit_workaround(bool extra_reconfig, u32 magic)
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO);
gpio_config(GPIO_PORT_E, GPIO_PIN_6, GPIO_MODE_SPIO);
gpio_config(GPIO_PORT_H, GPIO_PIN_6, GPIO_MODE_SPIO);
// Reinstate SD controller power.
PMC(APBDEV_PMC_NO_IOPOWER) &= ~(PMC_NO_IOPOWER_SDMMC1_IO_EN);
}
// Power off display.
display_end();
// Seamless display or display power off.
switch (bl_magic)
{
case BL_MAGIC_CRBOOT_SLD:;
// Set pwm to 0%, switch to gpio mode and restore pwm duty.
u32 brightness = display_get_backlight_brightness();
display_backlight_brightness(0, 1000);
gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_GPIO);
display_backlight_brightness(brightness, 0);
break;
default:
display_end();
}
// Enable clock to USBD and init SDMMC1 to avoid hangs with bad hw inits.
if (magic == 0xBAADF00D)
if (bl_magic == BL_MAGIC_BROKEN_HWI)
{
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_USBD);
sdmmc_init(&sd_sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID, 0);

View file

@ -20,8 +20,11 @@
#include <utils/types.h>
#define BL_MAGIC_CRBOOT_SLD 0x30444C53 // SLD0, seamless display type 0.
#define BL_MAGIC_BROKEN_HWI 0xBAADF00D // Broken hwinit.
void hw_init();
void hw_reinit_workaround(bool extra_reconfig, u32 magic);
void hw_reinit_workaround(bool coreboot, u32 magic);
u32 hw_get_chip_id();
#endif

View file

@ -136,10 +136,10 @@ static int _i2c_send_single(u32 i2c_idx, u32 dev_addr, u8 *buf, u32 size)
// Initiate transaction on normal mode.
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | NORMAL_MODE_GO;
u32 timeout = get_tmr_ms() + 400; // Actual for max 8 bytes at 100KHz is 0.74ms.
u32 timeout = get_tmr_us() + 200000; // Actual for max 8 bytes at 100KHz is 0.74ms.
while (base[I2C_STATUS] & I2C_STATUS_BUSY)
{
if (get_tmr_ms() > timeout)
if (get_tmr_us() > timeout)
return 0;
}
@ -168,10 +168,10 @@ static int _i2c_recv_single(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr)
// Initiate transaction on normal mode.
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | NORMAL_MODE_GO;
u32 timeout = get_tmr_ms() + 400; // Actual for max 8 bytes at 100KHz is 0.74ms.
u32 timeout = get_tmr_us() + 200000; // Actual for max 8 bytes at 100KHz is 0.74ms.
while (base[I2C_STATUS] & I2C_STATUS_BUSY)
{
if (get_tmr_ms() > timeout)
if (get_tmr_us() > timeout)
return 0;
}

View file

@ -133,6 +133,10 @@ static irq_status_t _irq_handle_source(u32 irq)
}
}
// Do not re-enable if not handled.
if (status == IRQ_NONE)
return status;
if (irqs[idx].flags & IRQ_FLAG_ONE_OFF)
irq_free(irq);
else
@ -148,7 +152,9 @@ void irq_handler()
if (!irq_init_done)
{
_irq_disable_source(irq);
_irq_ack_source(irq);
return;
}
@ -156,9 +162,10 @@ void irq_handler()
int err = _irq_handle_source(irq);
//TODO: disable if unhandhled.
if (err == IRQ_NONE)
gfx_printf("Unhandled IRQ: %d\n", irq);
{
DPRINTF("Unhandled IRQ got disabled: %d!\n", irq);
}
}
static void _irq_init()
@ -170,6 +177,9 @@ static void _irq_init()
void irq_end()
{
if (!irq_init_done)
return;
_irq_free_all();
irq_disable_cpu_irq_exceptions();
irq_init_done = false;

View file

@ -14,11 +14,69 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <soc/hw_init.h>
#include <soc/pmc.h>
#include <soc/t210.h>
#include <utils/util.h>
int pmc_enable_partition(u32 part, int enable)
void pmc_scratch_lock(pmc_sec_lock_t lock_mask)
{
// Lock Private key disable, Fuse write enable, MC carveout, Warmboot PA id and Warmboot address.
if (lock_mask & PMC_SEC_LOCK_MISC)
{
PMC(APBDEV_PMC_SEC_DISABLE) |= 0x700FF0; // RW lock: 0-3.
PMC(APBDEV_PMC_SEC_DISABLE2) |= 0xFC000000; // RW lock: 21-23.
PMC(APBDEV_PMC_SEC_DISABLE3) |= 0x3F0FFF00; // RW lock: 28-33, 36-38.
PMC(APBDEV_PMC_SEC_DISABLE6) |= 0xC000000; // RW lock: 85.
PMC(APBDEV_PMC_SEC_DISABLE8) |= 0xFF00FF00; // RW lock: 108-111, 116-119.
// SE2 context.
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01)
{
PMC(APBDEV_PMC_SEC_DISABLE9) |= 0x3FF; // RW lock: 120-124. (0xB38)
PMC(APBDEV_PMC_SEC_DISABLE10) = 0xFFFFFFFF; // RW lock: 135-150.
}
}
if (lock_mask & PMC_SEC_LOCK_LP0_PARAMS)
{
PMC(APBDEV_PMC_SEC_DISABLE2) |= 0x3FCFFFF; // RW lock: 8-15, 17-20.
PMC(APBDEV_PMC_SEC_DISABLE4) |= 0x3F3FFFFF; // RW lock: 40-50, 52-54.
PMC(APBDEV_PMC_SEC_DISABLE5) = 0xFFFFFFFF; // RW lock: 56-71.
PMC(APBDEV_PMC_SEC_DISABLE6) |= 0xF3FFC00F; // RW lock: 72-73, 79-84, 86-87.
PMC(APBDEV_PMC_SEC_DISABLE7) |= 0x3FFFFF; // RW lock: 88-98.
PMC(APBDEV_PMC_SEC_DISABLE8) |= 0xFF; // RW lock: 104-107.
}
if (lock_mask & PMC_SEC_LOCK_RST_VECTOR)
PMC(APBDEV_PMC_SEC_DISABLE3) |= 0xF00000; // RW lock: 34-35.
if (lock_mask & PMC_SEC_LOCK_CARVEOUTS)
{
PMC(APBDEV_PMC_SEC_DISABLE2) |= 0x30000; // RW lock: 16.
PMC(APBDEV_PMC_SEC_DISABLE3) |= 0xC0000000; // RW lock: 39.
PMC(APBDEV_PMC_SEC_DISABLE4) |= 0xC0C00000; // RW lock: 51, 55.
PMC(APBDEV_PMC_SEC_DISABLE6) |= 0x3FF0; // RW lock: 74-78.
PMC(APBDEV_PMC_SEC_DISABLE7) |= 0xFFC00000; // RW lock: 99-103.
}
if (lock_mask & PMC_SEC_LOCK_TZ_CMAC_W)
PMC(APBDEV_PMC_SEC_DISABLE8) |= 0x550000; // W lock: 112-115.
if (lock_mask & PMC_SEC_LOCK_TZ_CMAC_R)
PMC(APBDEV_PMC_SEC_DISABLE8) |= 0xAA0000; // R lock: 112-115.
if (lock_mask & PMC_SEC_LOCK_TZ_KEK_W)
PMC(APBDEV_PMC_SEC_DISABLE3) |= 0x55; // W lock: 24-27.
if (lock_mask & PMC_SEC_LOCK_TZ_KEK_R)
PMC(APBDEV_PMC_SEC_DISABLE3) |= 0xAA; // R lock: 24-27.
if (lock_mask & PMC_SEC_LOCK_SE_SRK)
PMC(APBDEV_PMC_SEC_DISABLE) |= 0xFF000; // RW lock: 4-7
}
int pmc_enable_partition(pmc_power_rail_t part, u32 enable)
{
u32 part_mask = BIT(part);
u32 desired_state = enable << part;

View file

@ -91,6 +91,8 @@
#define APBDEV_PMC_SEC_DISABLE6 0x5B8
#define APBDEV_PMC_SEC_DISABLE7 0x5BC
#define APBDEV_PMC_SEC_DISABLE8 0x5C0
#define APBDEV_PMC_SEC_DISABLE9 0x5C4
#define APBDEV_PMC_SEC_DISABLE10 0x5C8
#define APBDEV_PMC_SCRATCH188 0x810
#define APBDEV_PMC_SCRATCH190 0x818
#define APBDEV_PMC_SCRATCH200 0x840
@ -98,6 +100,54 @@
#define APBDEV_PMC_TZRAM_SEC_DISABLE 0xBEC
#define APBDEV_PMC_TZRAM_NON_SEC_DISABLE 0xBF0
int pmc_enable_partition(u32 part, int enable);
typedef enum _pmc_sec_lock_t
{
PMC_SEC_LOCK_MISC = BIT(0),
PMC_SEC_LOCK_LP0_PARAMS = BIT(1),
PMC_SEC_LOCK_RST_VECTOR = BIT(2),
PMC_SEC_LOCK_CARVEOUTS = BIT(3),
PMC_SEC_LOCK_TZ_CMAC_W = BIT(4),
PMC_SEC_LOCK_TZ_CMAC_R = BIT(5),
PMC_SEC_LOCK_TZ_KEK_W = BIT(6),
PMC_SEC_LOCK_TZ_KEK_R = BIT(7),
PMC_SEC_LOCK_SE_SRK = BIT(8),
} pmc_sec_lock_t;
typedef enum _pmc_power_rail_t
{
POWER_RAIL_CRAIL = 0,
POWER_RAIL_3D0 = 1,
POWER_RAIL_VENC = 2,
POWER_RAIL_PCIE = 3,
POWER_RAIL_VDEC = 4,
POWER_RAIL_L2C = 5,
POWER_RAIL_MPE = 6,
POWER_RAIL_HEG = 7,
POWER_RAIL_SATA = 8,
POWER_RAIL_CE1 = 9,
POWER_RAIL_CE2 = 10,
POWER_RAIL_CE3 = 11,
POWER_RAIL_CELP = 12,
POWER_RAIL_3D1 = 13,
POWER_RAIL_CE0 = 14,
POWER_RAIL_C0NC = 15,
POWER_RAIL_C1NC = 16,
POWER_RAIL_SOR = 17,
POWER_RAIL_DIS = 18,
POWER_RAIL_DISB = 19,
POWER_RAIL_XUSBA = 20,
POWER_RAIL_XUSBB = 21,
POWER_RAIL_XUSBC = 22,
POWER_RAIL_VIC = 23,
POWER_RAIL_IRAM = 24,
POWER_RAIL_NVDEC = 25,
POWER_RAIL_NVJPG = 26,
POWER_RAIL_AUD = 27,
POWER_RAIL_DFD = 28,
POWER_RAIL_VE2 = 29
} pmc_power_rail_t;
void pmc_scratch_lock(pmc_sec_lock_t lock_mask);
int pmc_enable_partition(pmc_power_rail_t part, u32 enable);
#endif

View file

@ -122,7 +122,12 @@ u32 uart_get_IIR(u32 idx)
{
uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]);
return uart->UART_IIR_FCR;
u32 iir = uart->UART_IIR_FCR & UART_IIR_INT_MASK;
if (iir & UART_IIR_NO_INT)
return 0;
else
return ((iir >> 1) + 1); // Return encoded interrupt.
}
void uart_set_IIR(u32 idx)

View file

@ -54,6 +54,17 @@
#define UART_IIR_FCR_RX_CLR 0x2
#define UART_IIR_FCR_EN_FIFO 0x1
#define UART_IIR_NO_INT BIT(0)
#define UART_IIR_INT_MASK 0xF
/* Custom returned interrupt results. Actual interrupts are -1 */
#define UART_IIR_NOI 0 // No interrupt.
#define UART_IIR_MSI 1 // Modem status interrupt.
#define UART_IIR_THRI 2 // Transmitter holding register empty.
#define UART_IIR_RDI 3 // Receiver data interrupt.
#define UART_IIR_ERROR 4 // Overrun Error, Parity Error, Framing Error, Break.
#define UART_IIR_REDI 5 // Receiver end of data interrupt.
#define UART_IIR_RDTI 7 // Receiver data timeout interrupt.
#define UART_MCR_RTS 0x2
#define UART_MCR_DTR 0x1