tegra124: Implement starting up the main CPUs.

This will allow us to run the ROM stage on the main CPU0 instead of the AVP
coprocessor. In addition, this CL also fixes some problems in the clock init
function, and replaces the definition of the PMC register layout structure. I
originally implemented this new version by accident without realizing the
original existed, but since it's a bit more up to date we decided to use it
instead.

The procedure for bringing up the main CPUs happens in four broad phases.

1. Enable the external power for the CPU rail by talking to the PMIC over I2C.
2. Enable the internal power rail for the CPUs.
3. Un-gate power for the CPUs and associated bits and pieces.
4. Enable the CPU clocks and take CPU0 out of reset.

The reset address is stored in an memory location with the magical property
that the CPUs will use whatever address when they reset. No explanation is
given in the documentation why this location behaves that way, what other
values near it might do, etc., so we have to just follow the example of the
kernel and U-Boot and treat it the same way.

Some code still needs to be written which will call into the flow controller
and get it to shut down the AVP so that it isn't sitting there consuming power
while execution has moved on to the main CPU. In the mean time, the current
implementation is sufficient.

BUG=None
TEST=Built and booted into the bootblock on nyan. Wrote a small test function
which sets the stack pointer to an array allocated as a new stack and then
prints a hello world type message. Used that function and some code in earlier
parts of the bootblock to print the uP-Tag at address 0x60000000 from the CPU
and the AVP and verified that they were 0x55555555 and 0xaaaaaaaa, indicating
that the test function actually was running on the main CPU and not on the
AVP.

Change-Id: I9728f43155074ab6948853eb26879656feb6b8c0
Signed-off-by: Gabe Black <gabeblack@google.com>
Reviewed-on: https://chromium-review.googlesource.com/172917
Reviewed-by: Julius Werner <jwerner@chromium.org>
Commit-Queue: Gabe Black <gabeblack@chromium.org>
Tested-by: Gabe Black <gabeblack@chromium.org>
This commit is contained in:
Gabe Black 2013-10-11 17:56:11 -07:00 committed by chrome-internal-fetch
commit 7c5169a197
8 changed files with 405 additions and 391 deletions

View file

@ -6,6 +6,7 @@ bootblock-y += cbfs.c
bootblock-y += clock.c
bootblock-y += i2c.c
bootblock-y += monotonic_timer.c
bootblock-y += power.c
bootblock-y += ../tegra/gpio.c
bootblock-y += ../tegra/i2c.c
bootblock-y += ../tegra/pingroup.c

View file

@ -24,6 +24,7 @@
#include "clock.h"
#include "pinmux.h"
#include "power.h"
void main(void)
{
@ -45,7 +46,22 @@ void main(void)
bootblock_mainboard_init();
pinmux_set_config(PINMUX_CORE_PWR_REQ_INDEX,
PINMUX_CORE_PWR_REQ_FUNC_PWRON);
pinmux_set_config(PINMUX_CPU_PWR_REQ_INDEX,
PINMUX_CPU_PWR_REQ_FUNC_CPU);
pinmux_set_config(PINMUX_PWR_INT_N_INDEX,
PINMUX_PWR_INT_N_FUNC_PMICINTR |
PINMUX_TRISTATE |
PINMUX_INPUT_ENABLE);
power_enable_cpu_rail();
power_ungate_cpu();
entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, "fallback/romstage");
if (entry)
clock_cpu0_config_and_reset(entry);
hlt();
}

View file

@ -504,33 +504,6 @@ enum {
#define CLK_SYS_RATE_APB_RATE_SHIFT 0
#define CLK_SYS_RATE_APB_RATE_MASK (3 << CLK_SYS_RATE_AHB_RATE_SHIFT)
/* CLK_RST_CONTROLLER_RST_CPUxx_CMPLX_CLR 0x344 */
#define CLR_CPURESET0 (1 << 0)
#define CLR_CPURESET1 (1 << 1)
#define CLR_CPURESET2 (1 << 2)
#define CLR_CPURESET3 (1 << 3)
#define CLR_DBGRESET0 (1 << 12)
#define CLR_DBGRESET1 (1 << 13)
#define CLR_DBGRESET2 (1 << 14)
#define CLR_DBGRESET3 (1 << 15)
#define CLR_CORERESET0 (1 << 16)
#define CLR_CORERESET1 (1 << 17)
#define CLR_CORERESET2 (1 << 18)
#define CLR_CORERESET3 (1 << 19)
#define CLR_CXRESET0 (1 << 20)
#define CLR_CXRESET1 (1 << 21)
#define CLR_CXRESET2 (1 << 22)
#define CLR_CXRESET3 (1 << 23)
#define CLR_L2RESET (1 << 24)
#define CLR_NONCPURESET (1 << 29)
#define CLR_PRESETDBG (1 << 30)
/* CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR 0x34c */
#define CLR_CPU3_CLK_STP (1 << 11)
#define CLR_CPU2_CLK_STP (1 << 10)
#define CLR_CPU1_CLK_STP (1 << 9)
#define CLR_CPU0_CLK_STP (1 << 8)
/* CRC_CLK_SOURCE_MSELECT_0 0x3b4 */
#define MSELECT_CLK_SRC_PLLP_OUT0 (0 << 29)
@ -549,4 +522,46 @@ enum {
#define UTMIP_FORCE_PD_SAMP_B_POWERDOWN (1 << 2)
#define UTMIP_FORCE_PD_SAMP_A_POWERDOWN (1 << 0)
// CCLK_BRST_POL
enum {
CRC_CCLK_BRST_POL_PLLX_OUT0 = 0x8,
CRC_CCLK_BRST_POL_CPU_STATE_RUN = 0x2
};
// SUPER_CCLK_DIVIDER
enum {
CRC_SUPER_CCLK_DIVIDER_SUPER_CDIV_ENB = 1 << 31
};
// CLK_CPU_CMPLX_CLR
enum {
CRC_CLK_CLR_CPU0_STP = 0x1 << 8,
CRC_CLK_CLR_CPU1_STP = 0x1 << 9,
CRC_CLK_CLR_CPU2_STP = 0x1 << 10,
CRC_CLK_CLR_CPU3_STP = 0x1 << 11
};
// RST_CPUG_CMPLX_CLR
enum {
CRC_RST_CPUG_CLR_CPU0 = 0x1 << 0,
CRC_RST_CPUG_CLR_CPU1 = 0x1 << 1,
CRC_RST_CPUG_CLR_CPU2 = 0x1 << 2,
CRC_RST_CPUG_CLR_CPU3 = 0x1 << 3,
CRC_RST_CPUG_CLR_DBG0 = 0x1 << 12,
CRC_RST_CPUG_CLR_DBG1 = 0x1 << 13,
CRC_RST_CPUG_CLR_DBG2 = 0x1 << 14,
CRC_RST_CPUG_CLR_DBG3 = 0x1 << 15,
CRC_RST_CPUG_CLR_CORE0 = 0x1 << 16,
CRC_RST_CPUG_CLR_CORE1 = 0x1 << 17,
CRC_RST_CPUG_CLR_CORE2 = 0x1 << 18,
CRC_RST_CPUG_CLR_CORE3 = 0x1 << 19,
CRC_RST_CPUG_CLR_CX0 = 0x1 << 20,
CRC_RST_CPUG_CLR_CX1 = 0x1 << 21,
CRC_RST_CPUG_CLR_CX2 = 0x1 << 22,
CRC_RST_CPUG_CLR_CX3 = 0x1 << 23,
CRC_RST_CPUG_CLR_L2 = 0x1 << 24,
CRC_RST_CPUG_CLR_NONCPU = 0x1 << 29,
CRC_RST_CPUG_CLR_PDBG = 0x1 << 30,
};
#endif /* _TEGRA124_CLK_RST_H_ */

View file

@ -24,7 +24,7 @@
static struct clk_rst_ctlr *clk_rst = (void *)TEGRA_CLK_RST_BASE;
static struct flow_ctlr *flow = (void *)TEGRA_FLOW_BASE;
static struct pmc_ctlr *pmc = (void*)TEGRA_PMC_BASE;
static struct tegra_pmc_regs *pmc = (void*)TEGRA_PMC_BASE;
/* only needed in this one place. Avoid namespace pollution. Be green .*/
struct clk_pll_table {
@ -181,6 +181,51 @@ void clock_uart_config(void)
clrbits_le32(clkreset(CLK_UARTA_REG), CLK_UARTA_MASK);
}
void clock_cpu0_config_and_reset(void *entry)
{
void *evp_cpu_reset = (uint8_t *)TEGRA_EVP_BASE + 0x100;
write32((uintptr_t)entry, evp_cpu_reset);
// Wait for PLLX to lock.
while (!(readl(&clk_rst->crc_pll_simple[0].pll_base) & (0x1 << 27)))
;
// Set up cclk_brst and divider.
write32((CRC_CCLK_BRST_POL_PLLX_OUT0 << 0) |
(CRC_CCLK_BRST_POL_PLLX_OUT0 << 4) |
(CRC_CCLK_BRST_POL_PLLX_OUT0 << 8) |
(CRC_CCLK_BRST_POL_PLLX_OUT0 << 12) |
(CRC_CCLK_BRST_POL_CPU_STATE_RUN << 28),
&clk_rst->crc_cclk_brst_pol);
write32(CRC_SUPER_CCLK_DIVIDER_SUPER_CDIV_ENB,
&clk_rst->crc_super_cclk_div);
// Enable the clocks for CPUs 0-3.
uint32_t cpu_cmplx_clr = read32(&clk_rst->crc_clk_cpu_cmplx_clr);
cpu_cmplx_clr |= CRC_CLK_CLR_CPU0_STP | CRC_CLK_CLR_CPU1_STP |
CRC_CLK_CLR_CPU2_STP | CRC_CLK_CLR_CPU3_STP;
write32(cpu_cmplx_clr, &clk_rst->crc_clk_cpu_cmplx_clr);
// Enable other CPU related clocks.
setbits_le32(clkenable(CLK_CPU_REG), CLK_CPU_MASK);
setbits_le32(clkenablevw(CLK_VW_CPUG_REG), CLK_VW_CPUG_MASK);
// Disable the reset on the non-CPU parts of the fast cluster.
write32(CRC_RST_CPUG_CLR_NONCPU,
&clk_rst->crc_rst_cpug_cmplx_clr);
// Disable the various resets on the CPUs.
write32(CRC_RST_CPUG_CLR_CPU0 | CRC_RST_CPUG_CLR_CPU1 |
CRC_RST_CPUG_CLR_CPU2 | CRC_RST_CPUG_CLR_CPU3 |
CRC_RST_CPUG_CLR_DBG0 | CRC_RST_CPUG_CLR_DBG1 |
CRC_RST_CPUG_CLR_DBG2 | CRC_RST_CPUG_CLR_DBG3 |
CRC_RST_CPUG_CLR_CORE0 | CRC_RST_CPUG_CLR_CORE1 |
CRC_RST_CPUG_CLR_CORE2 | CRC_RST_CPUG_CLR_CORE3 |
CRC_RST_CPUG_CLR_CX0 | CRC_RST_CPUG_CLR_CX1 |
CRC_RST_CPUG_CLR_CX2 | CRC_RST_CPUG_CLR_CX3 |
CRC_RST_CPUG_CLR_L2 | CRC_RST_CPUG_CLR_PDBG,
&clk_rst->crc_rst_cpug_cmplx_clr);
}
/**
* The T124 requires some special clock initialization, including setting up
* the DVC I2C, turning on MSELECT and selecting the G CPU cluster
@ -215,13 +260,10 @@ void clock_init(void)
/* Ambiguous quote from u-boot. TODO: what's this mean?
* "should update same value in PMC_OSC_EDPD_OVER XOFS
field for warmboot "*/
val = readl(&pmc->pmc_osc_edpd_over);
val &= ~PMC_XOFS_MASK;
val |= (OSC_DRIVE_STRENGTH << PMC_XOFS_SHIFT);
writel(val, &pmc->pmc_osc_edpd_over);
/* Set HOLD_CKE_LOW_EN to 1 */
setbits_le32(&pmc->pmc_cntrl2, HOLD_CKE_LOW_EN);
val = readl(&pmc->osc_edpd_over);
val &= ~PMC_OSC_EDPD_OVER_XOFS_MASK;
val |= (OSC_DRIVE_STRENGTH << PMC_OSC_EDPD_OVER_XOFS_SHIFT);
writel(val, &pmc->osc_edpd_over);
init_pllx();
@ -238,12 +280,12 @@ void clock_config(void)
setbits_le32(clkenable(CLK_CACHE2_REG), CLK_CACHE2_MASK);
setbits_le32(clkenable(CLK_GPIO_REG), CLK_GPIO_MASK);
setbits_le32(clkenable(CLK_TMR_REG), CLK_TMR_MASK);
setbits_le32(clkenable(CLK_CPU_REG), CLK_CPU_MASK);
setbits_le32(clkenable(CLK_EMC_REG), CLK_EMC_MASK);
setbits_le32(clkenable(CLK_I2C1_REG), CLK_I2C1_MASK);
setbits_le32(clkenable(CLK_I2C2_REG), CLK_I2C2_MASK);
setbits_le32(clkenable(CLK_I2C3_REG), CLK_I2C3_MASK);
setbits_le32(clkenable(CLK_I2C5_REG), CLK_I2C5_MASK);
setbits_le32(clkenable(CLK_PMC_REG), CLK_PMC_MASK);
setbits_le32(clkenable(CLK_APBDMA_REG), CLK_APBDMA_MASK);
setbits_le32(clkenable(CLK_MEM_REG), CLK_MEM_MASK);
setbits_le32(clkenable(CLK_CSITE_REG), CLK_CSITE_MASK);
@ -255,7 +297,7 @@ void clock_config(void)
* divider that would set the MSELECT clock at 102MHz for a
* PLLP base of 408MHz.
*/
clock_ll_set_source_divisor((void *)CLK_VW_MSELECT_REG, 0,
clock_ll_set_source_divisor(&clk_rst->crc_clk_src_vw[1], 0,
CLK_DIVIDER(NVBL_PLLP_KHZ, 102000));
/* Give clock time to stabilize */
@ -278,12 +320,12 @@ void clock_config(void)
clrbits_le32(clkreset(CLK_CACHE2_REG), CLK_CACHE2_MASK);
clrbits_le32(clkreset(CLK_GPIO_REG), CLK_GPIO_MASK);
clrbits_le32(clkreset(CLK_TMR_REG), CLK_TMR_MASK);
clrbits_le32(clkreset(CLK_CPU_REG), CLK_CPU_MASK);
clrbits_le32(clkreset(CLK_EMC_REG), CLK_EMC_MASK);
clrbits_le32(clkreset(CLK_I2C5_REG), CLK_I2C5_MASK);
clrbits_le32(clkreset(CLK_I2C3_REG), CLK_I2C3_MASK);
clrbits_le32(clkreset(CLK_I2C2_REG), CLK_I2C2_MASK);
clrbits_le32(clkreset(CLK_I2C1_REG), CLK_I2C1_MASK);
clrbits_le32(clkreset(CLK_I2C2_REG), CLK_I2C2_MASK);
clrbits_le32(clkreset(CLK_I2C3_REG), CLK_I2C3_MASK);
clrbits_le32(clkreset(CLK_I2C5_REG), CLK_I2C5_MASK);
clrbits_le32(clkreset(CLK_PMC_REG), CLK_PMC_MASK);
clrbits_le32(clkreset(CLK_APBDMA_REG), CLK_APBDMA_MASK);
clrbits_le32(clkreset(CLK_MEM_REG), CLK_MEM_MASK);
clrbits_le32(clkreset(CLK_CSITE_REG), CLK_CSITE_MASK);

View file

@ -171,6 +171,7 @@ enum {
#define clkenablevw(x) &clk_rst->crc_clk_out_enb_vw[(x)]
void clock_uart_config(void);
void clock_cpu0_config_and_reset(void * entry);
void clock_config(void);
void clock_init(void);

View file

@ -17,361 +17,184 @@
#ifndef _TEGRA124_PMC_H_
#define _TEGRA124_PMC_H_
/* Power Management Controller (APBDEV_PMC_) registers */
struct pmc_ctlr {
u32 pmc_cntrl; /* _CNTRL_0, offset 00 */
u32 pmc_sec_disable; /* _SEC_DISABLE_0, offset 04 */
u32 pmc_pmc_swrst; /* _PMC_SWRST_0, offset 08 */
u32 pmc_wake_mask; /* _WAKE_MASK_0, offset 0C */
u32 pmc_wake_lvl; /* _WAKE_LVL_0, offset 10 */
u32 pmc_wake_status; /* _WAKE_STATUS_0, offset 14 */
u32 pmc_sw_wake_status; /* _SW_WAKE_STATUS_0, offset 18 */
u32 pmc_dpd_pads_oride; /* _DPD_PADS_ORIDE_0, offset 1C */
u32 pmc_dpd_sample; /* _DPD_PADS_SAMPLE_0, offset 20 */
u32 pmc_dpd_enable; /* _DPD_PADS_ENABLE_0, offset 24 */
u32 pmc_pwrgate_timer_off; /* _PWRGATE_TIMER_OFF_0, offset 28 */
u32 pmc_clamp_status; /* _PMC_CLAMP_STATUS_0, offset 2C */
u32 pmc_pwrgate_toggle; /* _PWRGATE_TOGGLE_0, offset 30 */
u32 pmc_remove_clamping; /* _REMOVE_CLAMPING_CMD_0, offset 34 */
u32 pmc_pwrgate_status; /* _PWRGATE_STATUS_0, offset 38 */
u32 pmc_pwrgood_timer; /* _PWRGOOD_TIMER_0, offset 3C */
u32 pmc_blink_timer; /* _BLINK_TIMER_0, offset 40 */
u32 pmc_no_iopower; /* _NO_IOPOWER_0, offset 44 */
u32 pmc_pwr_det; /* _PWR_DET_0, offset 48 */
u32 pmc_pwr_det_latch; /* _PWR_DET_LATCH_0, offset 4C */
#include <stdint.h>
u32 pmc_scratch0; /* _SCRATCH0_0, offset 50 */
u32 pmc_scratch1; /* _SCRATCH1_0, offset 54 */
u32 pmc_scratch2; /* _SCRATCH2_0, offset 58 */
u32 pmc_scratch3; /* _SCRATCH3_0, offset 5C */
u32 pmc_scratch4; /* _SCRATCH4_0, offset 60 */
u32 pmc_scratch5; /* _SCRATCH5_0, offset 64 */
u32 pmc_scratch6; /* _SCRATCH6_0, offset 68 */
u32 pmc_scratch7; /* _SCRATCH7_0, offset 6C */
u32 pmc_scratch8; /* _SCRATCH8_0, offset 70 */
u32 pmc_scratch9; /* _SCRATCH9_0, offset 74 */
u32 pmc_scratch10; /* _SCRATCH10_0, offset 78 */
u32 pmc_scratch11; /* _SCRATCH11_0, offset 7C */
u32 pmc_scratch12; /* _SCRATCH12_0, offset 80 */
u32 pmc_scratch13; /* _SCRATCH13_0, offset 84 */
u32 pmc_scratch14; /* _SCRATCH14_0, offset 88 */
u32 pmc_scratch15; /* _SCRATCH15_0, offset 8C */
u32 pmc_scratch16; /* _SCRATCH16_0, offset 90 */
u32 pmc_scratch17; /* _SCRATCH17_0, offset 94 */
u32 pmc_scratch18; /* _SCRATCH18_0, offset 98 */
u32 pmc_scratch19; /* _SCRATCH19_0, offset 9C */
u32 pmc_scratch20; /* _SCRATCH20_0, offset A0 */
u32 pmc_scratch21; /* _SCRATCH21_0, offset A4 */
u32 pmc_scratch22; /* _SCRATCH22_0, offset A8 */
u32 pmc_scratch23; /* _SCRATCH23_0, offset AC */
u32 pmc_secure_scratch0; /* _SECURE_SCRATCH0_0, offset B0 */
u32 pmc_secure_scratch1; /* _SECURE_SCRATCH1_0, offset B4 */
u32 pmc_secure_scratch2; /* _SECURE_SCRATCH2_0, offset B8 */
u32 pmc_secure_scratch3; /* _SECURE_SCRATCH3_0, offset BC */
u32 pmc_secure_scratch4; /* _SECURE_SCRATCH4_0, offset C0 */
u32 pmc_secure_scratch5; /* _SECURE_SCRATCH5_0, offset C4 */
u32 pmc_cpupwrgood_timer; /* _CPUPWRGOOD_TIMER_0, offset C8 */
u32 pmc_cpupwroff_timer; /* _CPUPWROFF_TIMER_0, offset CC */
u32 pmc_pg_mask; /* _PG_MASK_0, offset D0 */
u32 pmc_pg_mask_1; /* _PG_MASK_1_0, offset D4 */
u32 pmc_auto_wake_lvl; /* _AUTO_WAKE_LVL_0, offset D8 */
u32 pmc_auto_wake_lvl_mask; /* _AUTO_WAKE_LVL_MASK_0, offset DC */
u32 pmc_wake_delay; /* _WAKE_DELAY_0, offset E0 */
u32 pmc_pwr_det_val; /* _PWR_DET_VAL_0, offset E4 */
u32 pmc_ddr_pwr; /* _DDR_PWR_0, offset E8 */
u32 pmc_usb_debounce_del; /* _USB_DEBOUNCE_DEL_0, offset EC */
u32 pmc_usb_ao; /* _USB_AO_0, offset F0 */
u32 pmc_crypto_op; /* _CRYPTO_OP__0, offset F4 */
u32 pmc_pllp_wb0_override; /* _PLLP_WB0_OVERRIDE_0, offset F8 */
u32 pmc_scratch24; /* _SCRATCH24_0, offset FC */
u32 pmc_scratch25; /* _SCRATCH24_0, offset 100 */
u32 pmc_scratch26; /* _SCRATCH24_0, offset 104 */
u32 pmc_scratch27; /* _SCRATCH24_0, offset 108 */
u32 pmc_scratch28; /* _SCRATCH24_0, offset 10C */
u32 pmc_scratch29; /* _SCRATCH24_0, offset 110 */
u32 pmc_scratch30; /* _SCRATCH24_0, offset 114 */
u32 pmc_scratch31; /* _SCRATCH24_0, offset 118 */
u32 pmc_scratch32; /* _SCRATCH24_0, offset 11C */
u32 pmc_scratch33; /* _SCRATCH24_0, offset 120 */
u32 pmc_scratch34; /* _SCRATCH24_0, offset 124 */
u32 pmc_scratch35; /* _SCRATCH24_0, offset 128 */
u32 pmc_scratch36; /* _SCRATCH24_0, offset 12C */
u32 pmc_scratch37; /* _SCRATCH24_0, offset 130 */
u32 pmc_scratch38; /* _SCRATCH24_0, offset 134 */
u32 pmc_scratch39; /* _SCRATCH24_0, offset 138 */
u32 pmc_scratch40; /* _SCRATCH24_0, offset 13C */
u32 pmc_scratch41; /* _SCRATCH24_0, offset 140 */
u32 pmc_scratch42; /* _SCRATCH24_0, offset 144 */
u32 pmc_bo_mirror0; /* _BOUNDOUT_MIRROR0_0, offset 148 */
u32 pmc_bo_mirror1; /* _BOUNDOUT_MIRROR1_0, offset 14C */
u32 pmc_bo_mirror2; /* _BOUNDOUT_MIRROR2_0, offset 150 */
u32 pmc_sys_33v_en; /* _SYS_33V_EN_0, offset 154 */
u32 pmc_bo_mirror_access; /* _BOUNDOUT_MIRROR_ACCESS_0, off158 */
u32 pmc_gate; /* _GATE_0, offset 15C */
u32 pmc_wake2_mask; /* _WAKE2_MASK_0, offset 160 */
u32 pmc_wake2_lvl; /* _WAKE2_LVL_0, offset 164 */
u32 pmc_wake2_stat; /* _WAKE2_STATUS_0, offset 168 */
u32 pmc_sw_wake2_stat; /* _SW_WAKE2_STATUS_0, offset 16C */
u32 pmc_auto_wake2_lvl_mask; /* _AUTO_WAKE2_LVL_MASK_0, offset 170 */
u32 pmc_pg_mask2; /* _PG_MASK_2_0, offset 174 */
u32 pmc_pg_mask_ce1; /* _PG_MASK_CE1_0, offset 178 */
u32 pmc_pg_mask_ce2; /* _PG_MASK_CE2_0, offset 17C */
u32 pmc_pg_mask_ce3; /* _PG_MASK_CE3_0, offset 180 */
u32 pmc_pwrgate_timer_ce0; /* _PWRGATE_TIMER_CE_0_0, offset 184 */
u32 pmc_pwrgate_timer_ce1; /* _PWRGATE_TIMER_CE_1_0, offset 188 */
u32 pmc_pwrgate_timer_ce2; /* _PWRGATE_TIMER_CE_2_0, offset 18C */
u32 pmc_pwrgate_timer_ce3; /* _PWRGATE_TIMER_CE_3_0, offset 190 */
u32 pmc_pwrgate_timer_ce4; /* _PWRGATE_TIMER_CE_4_0, offset 194 */
u32 pmc_pwrgate_timer_ce5; /* _PWRGATE_TIMER_CE_5_0, offset 198 */
u32 pmc_pwrgate_timer_ce6; /* _PWRGATE_TIMER_CE_6_0, offset 19C */
u32 pmc_pcx_edpd_cntrl; /* _PCX_EDPD_CNTRL_0, offset 1A0 */
u32 pmc_osc_edpd_over; /* _OSC_EDPD_OVER_0, offset 1A4 */
u32 pmc_clk_out_cntrl; /* _CLK_OUT_CNTRL_0, offset 1A8 */
u32 pmc_sata_pwrgate; /* _SATA_PWRGT_0, offset 1AC */
u32 pmc_sensor_ctrl; /* _SENSOR_CTRL_0, offset 1B0 */
u32 pmc_reset_status; /* _RTS_STATUS_0, offset 1B4 */
u32 pmc_io_dpd_req; /* _IO_DPD_REQ_0, offset 1B8 */
u32 pmc_io_dpd_stat; /* _IO_DPD_STATUS_0, offset 1BC */
u32 pmc_io_dpd2_req; /* _IO_DPD2_REQ_0, offset 1C0 */
u32 pmc_io_dpd2_stat; /* _IO_DPD2_STATUS_0, offset 1C4 */
u32 pmc_sel_dpd_tim; /* _SEL_DPD_TIM_0, offset 1C8 */
u32 pmc_vddp_sel; /* _VDDP_SEL_0, offset 1CC */
u32 pmc_ddr_cfg; /* _DDR_CFG_0, offset 1D0 */
u32 pmc_e_no_vttgen; /* _E_NO_VTTGEN_0, offset 1D4 */
u32 pmc_reserved0; /* _RESERVED, offset 1D8 */
u32 pmc_pllm_wb0_ovrride_frq; /* _PLLM_WB0_OVERRIDE_FREQ_0, off 1DC */
u32 pmc_test_pwrgate; /* _TEST_PWRGATE_0, offset 1E0 */
u32 pmc_pwrgate_timer_mult; /* _PWRGATE_TIMER_MULT_0, offset 1E4 */
u32 pmc_dsi_sel_dpd; /* _DSI_SEL_DPD_0, offset 1E8 */
u32 pmc_utmip_uhsic_triggers; /* _UTMIP_UHSIC_TRIGGERS_0, off 1EC */
u32 pmc_utmip_uhsic_saved_st; /* _UTMIP_UHSIC_SAVED_STATE_0, off1F0 */
u32 pmc_utmip_pad_cfg; /* _UTMIP_PAD_CFG_0, offset 1F4 */
u32 pmc_utmip_term_pad_cfg; /* _UTMIP_TERM_PAD_CFG_0, offset 1F8 */
u32 pmc_utmip_uhsic_sleep_cfg; /* _UTMIP_UHSIC_SLEEP_CFG_0, off 1FC */
u32 pmc_todo_0[9]; /* offset 200-220 */
u32 pmc_secure_scratch6; /* _SECURE_SCRATCH6_0, offset 224 */
u32 pmc_secure_scratch7; /* _SECURE_SCRATCH7_0, offset 228 */
u32 pmc_scratch43; /* _SCRATCH43_0, offset 22C */
u32 pmc_scratch44; /* _SCRATCH44_0, offset 230 */
u32 pmc_scratch45;
u32 pmc_scratch46;
u32 pmc_scratch47;
u32 pmc_scratch48;
u32 pmc_scratch49;
u32 pmc_scratch50;
u32 pmc_scratch51;
u32 pmc_scratch52;
u32 pmc_scratch53;
u32 pmc_scratch54;
u32 pmc_scratch55; /* _SCRATCH55_0, offset 25C */
u32 pmc_scratch0_eco; /* _SCRATCH0_ECO_0, offset 260 */
u32 pmc_por_dpd_ctrl; /* _POR_DPD_CTRL_0, offset 264 */
u32 pmc_scratch2_eco; /* _SCRATCH2_ECO_0, offset 268 */
u32 pmc_todo_1[17]; /* TODO: 26C ~ 2AC */
u32 pmc_pllm_wb0_override2; /* _PLLM_WB0_OVERRIDE2, offset 2B0 */
u32 pmc_tsc_mult; /* _TSC_MULT_0, offset 2B4 */
u32 pmc_cpu_vsense_override; /* _CPU_VSENSE_OVERRIDE_0, offset 2B8 */
u32 pmc_glb_amap_cfg; /* _GLB_AMAP_CFG_0, offset 2BC */
u32 pmc_sticky_bits; /* _STICKY_BITS_0, offset 2C0 */
u32 pmc_sec_disable2; /* _SEC_DISALBE2, offset 2C4 */
u32 pmc_weak_bias; /* _WEAK_BIAS_0, offset 2C8 */
u32 pmc_todo_3[13]; /* TODO: 2CC ~ 2FC */
u32 pmc_secure_scratch8; /* _SECURE_SCRATCH8_0, offset 300 */
u32 pmc_secure_scratch9;
u32 pmc_secure_scratch10;
u32 pmc_secure_scratch11;
u32 pmc_secure_scratch12;
u32 pmc_secure_scratch13;
u32 pmc_secure_scratch14;
u32 pmc_secure_scratch15;
u32 pmc_secure_scratch16;
u32 pmc_secure_scratch17;
u32 pmc_secure_scratch18;
u32 pmc_secure_scratch19;
u32 pmc_secure_scratch20;
u32 pmc_secure_scratch21;
u32 pmc_secure_scratch22;
u32 pmc_secure_scratch23;
u32 pmc_secure_scratch24; /* _SECURE_SCRATCH24_0, offset 340 */
u32 pmc_secure_scratch25;
u32 pmc_secure_scratch26;
u32 pmc_secure_scratch27;
u32 pmc_secure_scratch28;
u32 pmc_secure_scratch29;
u32 pmc_secure_scratch30;
u32 pmc_secure_scratch31;
u32 pmc_secure_scratch32;
u32 pmc_secure_scratch33;
u32 pmc_secure_scratch34;
u32 pmc_secure_scratch35; /* _SECURE_SCRATCH35_0, offset 36C */
u32 pmc_reserved1[52]; /* RESERVED: 370 ~ 43C */
u32 pmc_cntrl2; /* _CNTRL2_0, offset 440 */
u32 pmc_reserved2[6]; /* RESERVED: 444 ~ 458 */
u32 pmc_io_dpd3_req; /* _IO_DPD3_REQ_0, offset 45c */
u32 pmc_io_dpd3_stat; /* _IO_DPD3_STATUS_0, offset 460 */
u32 pmc_strap_opt_a; /* _STRAPPING_OPT_A_0, offset 464 */
u32 pmc_reserved3[102]; /* RESERVED: 468 ~ 5FC */
u32 pmc_scratch56; /* _SCRATCH56_0, offset 600 */
u32 pmc_scratch57;
u32 pmc_scratch58;
u32 pmc_scratch59;
u32 pmc_scratch60;
u32 pmc_scratch61;
u32 pmc_scratch62;
u32 pmc_scratch63;
u32 pmc_scratch64;
u32 pmc_scratch65;
u32 pmc_scratch66;
u32 pmc_scratch67;
u32 pmc_scratch68;
u32 pmc_scratch69;
u32 pmc_scratch70;
u32 pmc_scratch71;
u32 pmc_scratch72;
u32 pmc_scratch73;
u32 pmc_scratch74;
u32 pmc_scratch75;
u32 pmc_scratch76;
u32 pmc_scratch77;
u32 pmc_scratch78;
u32 pmc_scratch79;
u32 pmc_scratch80;
u32 pmc_scratch81;
u32 pmc_scratch82;
u32 pmc_scratch83;
u32 pmc_scratch84;
u32 pmc_scratch85;
u32 pmc_scratch86;
u32 pmc_scratch87;
u32 pmc_scratch88;
u32 pmc_scratch89;
u32 pmc_scratch90;
u32 pmc_scratch91;
u32 pmc_scratch92;
u32 pmc_scratch93;
u32 pmc_scratch94;
u32 pmc_scratch95;
u32 pmc_scratch96;
u32 pmc_scratch97;
u32 pmc_scratch98;
u32 pmc_scratch99;
u32 pmc_scratch100;
u32 pmc_scratch101;
u32 pmc_scratch102;
u32 pmc_scratch103;
u32 pmc_scratch104;
u32 pmc_scratch105;
u32 pmc_scratch106;
u32 pmc_scratch107;
u32 pmc_scratch108;
u32 pmc_scratch109;
u32 pmc_scratch110;
u32 pmc_scratch111;
u32 pmc_scratch112;
u32 pmc_scratch113;
u32 pmc_scratch114;
u32 pmc_scratch115;
u32 pmc_scratch116;
u32 pmc_scratch117;
u32 pmc_scratch118;
u32 pmc_scratch119;
u32 pmc_scratch1_eco; /* offset 700 */
enum {
POWER_PARTID_CRAIL = 0,
POWER_PARTID_TD = 1,
POWER_PARTID_VE = 2,
POWER_PARTID_VDE = 4,
POWER_PARTID_L2C = 5,
POWER_PARTID_MPE = 6,
POWER_PARTID_HEG = 7,
POWER_PARTID_CE1 = 9,
POWER_PARTID_CE2 = 10,
POWER_PARTID_CE3 = 11,
POWER_PARTID_CELP = 12,
POWER_PARTID_CE0 = 14,
POWER_PARTID_C0NC = 15,
POWER_PARTID_C1NC = 16,
POWER_PARTID_DIS = 18,
POWER_PARTID_DISB = 19,
POWER_PARTID_XUSBA = 20,
POWER_PARTID_XUSBB = 21,
POWER_PARTID_XUSBC = 22
};
#define CPU_PWRED 1
#define CPU_CLMP 1
struct tegra_pmc_regs {
u32 cntrl;
u32 sec_disable;
u32 pmc_swrst;
u32 wake_mask;
u32 wake_lvl;
u32 wake_status;
u32 sw_wake_status;
u32 dpd_pads_oride;
u32 dpd_sample;
u32 dpd_enable;
u32 pwrgate_timer_off;
u32 clamp_status;
u32 pwrgate_toggle;
u32 remove_clamping_cmd;
u32 pwrgate_status;
u32 pwrgood_timer;
u32 blink_timer;
u32 no_iopower;
u32 pwr_det;
u32 pwr_det_latch;
u32 scratch[24];
u32 secure_scratch[6];
u32 cpupwrgood_timer;
u32 cpupwroff_timer;
u32 pg_mask;
u32 pg_mask_1;
u32 auto_wake_lvl;
u32 auto_wake_lvl_mask;
u32 wake_delay;
u32 pwr_det_val;
u32 ddr_pwr;
u32 usb_debounce_del;
u32 usb_a0;
u32 crypto_op;
u32 pllp_wb0_override;
u32 scratch24[43 - 24];
u32 bondout_mirror[3];
u32 sys_33v_en;
u32 bondout_mirror_access;
u32 gate;
u32 wake2_mask;
u32 wake2_lvl;
u32 wake2_status;
u32 sw_wake2_status;
u32 auto_wake2_lvl_mask;
u32 pg_mask_2;
u32 pg_mask_ce1;
u32 pg_mask_ce2;
u32 pg_mask_ce3;
u32 pwrgate_timer_ce[7];
u32 pcx_edpd_cntrl;
u32 osc_edpd_over;
u32 clk_out_cntrl;
u32 sata_pwrgt;
u32 sensor_ctrl;
u32 rst_status;
u32 io_dpd_req;
u32 io_dpd_status;
u32 io_dpd2_req;
u32 io_dpd2_status;
u32 sel_dpd_tim;
u32 vddp_sel;
u32 ddr_cfg;
u32 e_no_vttgen;
u8 _rsv0[4];
u32 pllm_wb0_override_freq;
u32 test_pwrgate;
u32 pwrgate_timer_mult;
u32 dis_sel_dpd;
u32 utmip_uhsic_triggers;
u32 utmip_uhsic_saved_state;
u32 utmip_pad_cfg;
u32 utmip_term_pad_cfg;
u32 utmip_uhsic_sleep_cfg;
u32 utmip_uhsic_sleepwalk_cfg;
u32 utmip_sleepwalk_p[3];
u32 uhsic_sleepwalk_p0;
u32 utmip_uhsic_status;
u32 utmip_uhsic_fake;
u32 bondout_mirror3[5 - 3];
u32 secure_scratch6[8 - 6];
u32 scratch43[56 - 43];
u32 scratch_eco[3];
u32 utmip_uhsic_line_wakeup;
u32 utmip_bias_master_cntrl;
u32 utmip_master_config;
u32 td_pwrgate_inter_part_timer;
u32 utmip_uhsic2_triggers;
u32 utmip_uhsic2_saved_state;
u32 utmip_uhsic2_sleep_cfg;
u32 utmip_uhsic2_sleepwalk_cfg;
u32 uhsic2_sleepwalk_p1;
u32 utmip_uhsic2_status;
u32 utmip_uhsic2_fake;
u32 utmip_uhsic2_line_wakeup;
u32 utmip_master2_config;
u32 utmip_uhsic_rpd_cfg;
u32 pg_mask_ce0;
u32 pg_mask3[5 - 3];
u32 pllm_wb0_override2;
u32 tsc_mult;
u32 cpu_vsense_override;
u32 glb_amap_cfg;
u32 sticky_bits;
u32 sec_disable2;
u32 weak_bias;
u32 reg_short;
u32 pg_mask_andor;
u8 _rsv1[0x2c];
u32 secure_scratch8[24 - 8];
u32 scratch56[120 - 56];
};
#define PARTID_CP 0xFFFFFFF8
#define START_CP (1 << 8)
enum {
PMC_PWRGATE_TOGGLE_PARTID_MASK = 0x1f,
PMC_PWRGATE_TOGGLE_PARTID_SHIFT = 0,
PMC_PWRGATE_TOGGLE_START = 0x1 << 8
};
#define CPUPWRREQ_OE (1 << 16)
#define CPUPWRREQ_POL (1 << 15)
enum {
PMC_CNTRL_KBC_CLK_DIS = 0x1 << 0,
PMC_CNTRL_RTC_CLK_DIS = 0x1 << 1,
PMC_CNTRL_RTC_RST = 0x1 << 2,
PMC_CNTRL_KBC_RST = 0x1 << 3,
PMC_CNTRL_MAIN_RST = 0x1 << 4,
PMC_CNTRL_LATCHWAKE_EN = 0x1 << 5,
PMC_CNTRL_GLITCHDET_DIS = 0x1 << 6,
PMC_CNTRL_BLINK_EN = 0x1 << 7,
PMC_CNTRL_PWRREQ_POLARITY = 0x1 << 8,
PMC_CNTRL_PWRREQ_OE = 0x1 << 9,
PMC_CNTRL_SYSCLK_POLARITY = 0x1 << 10,
PMC_CNTRL_SYSCLK_OE = 0x1 << 11,
PMC_CNTRL_PWRGATE_DIS = 0x1 << 12,
PMC_CNTRL_AOINIT = 0x1 << 13,
PMC_CNTRL_SIDE_EFFECT_LP0 = 0x1 << 14,
PMC_CNTRL_CPUPWRREQ_POLARITY = 0x1 << 15,
PMC_CNTRL_CPUPWRREQ_OE = 0x1 << 16,
PMC_CNTRL_INTR_POLARITY = 0x1 << 17,
PMC_CNTRL_FUSE_OVERRIDE = 0x1 << 18,
PMC_CNTRL_CPUPWRGOOD_EN = 0x1 << 19,
PMC_CNTRL_CPUPWRGOOD_SEL_SHIFT = 20,
PMC_CNTRL_CPUPWRGOOD_SEL_MASK =
0x3 << PMC_CNTRL_CPUPWRGOOD_SEL_SHIFT
};
#define CRAILID (0)
#define CE0ID (14)
#define C0NCID (15)
#define CRAIL (1 << CRAILID)
#define CE0 (1 << CE0ID)
#define C0NC (1 << C0NCID)
enum {
PMC_CNTRL2_HOLD_CKE_LOW_EN = 0x1 << 12
};
#define PMC_XOFS_SHIFT 1
#define PMC_XOFS_MASK (0x3F << PMC_XOFS_SHIFT)
#define TIMER_MULT_SHIFT 0
#define TIMER_MULT_MASK (3 << TIMER_MULT_SHIFT)
#define TIMER_MULT_CPU_SHIFT 2
#define TIMER_MULT_CPU_MASK (3 << TIMER_MULT_CPU_SHIFT)
#define MULT_1 0
#define MULT_2 1
#define MULT_4 2
#define MULT_8 3
#define AMAP_WRITE_SHIFT 20
#define AMAP_WRITE_ON (1 << AMAP_WRITE_SHIFT)
/* SEC_DISABLE_0, 0x04 */
#define SEC_DISABLE_WRITE0_ON (1 << 4)
#define SEC_DISABLE_READ0_ON (1 << 5)
#define SEC_DISABLE_WRITE1_ON (1 << 6)
#define SEC_DISABLE_READ1_ON (1 << 7)
#define SEC_DISABLE_WRITE2_ON (1 << 8)
#define SEC_DISABLE_READ2_ON (1 << 9)
#define SEC_DISABLE_WRITE3_ON (1 << 10)
#define SEC_DISABLE_READ3_ON (1 << 11)
#define SEC_DISABLE_AMAP_WRITE_ON (1 << 20)
/* APBDEV_PMC_PWRGATE_TOGGLE_0 0x30 */
#define PWRGATE_TOGGLE_PARTID_CRAIL 0
#define PWRGATE_TOGGLE_PARTID_TD 1
#define PWRGATE_TOGGLE_PARTID_VE 2
#define PWRGATE_TOGGLE_PARTID_VDE 4
#define PWRGATE_TOGGLE_PARTID_L2C 5
#define PWRGATE_TOGGLE_PARTID_MPE 6
#define PWRGATE_TOGGLE_PARTID_HEG 7
#define PWRGATE_TOGGLE_PARTID_CE1 9
#define PWRGATE_TOGGLE_PARTID_CE2 10
#define PWRGATE_TOGGLE_PARTID_CE3 11
#define PWRGATE_TOGGLE_PARTID_CELP 12
#define PWRGATE_TOGGLE_PARTID_CE0 14
#define PWRGATE_TOGGLE_PARTID_C0NC 15
#define PWRGATE_TOGGLE_PARTID_C1NC 16
#define PWRGATE_TOGGLE_PARTID_DIS 18
#define PWRGATE_TOGGLE_PARTID_DISB 19
#define PWRGATE_TOGGLE_PARTID_XUSBA 20
#define PWRGATE_TOGGLE_PARTID_XUSBB 21
#define PWRGATE_TOGGLE_PARTID_XUSBC 22
#define PWRGATE_TOGGLE_START (1 << 8)
/* APBDEV_PMC_PWRGATE_STATUS_0 0x38 */
#define PWRGATE_STATUS_CRAIL_ENABLE (1 << 0)
#define PWRGATE_STATUS_TD_ENABLE (1 << 1)
#define PWRGATE_STATUS_VE_ENABLE (1 << 2)
#define PWRGATE_STATUS_VDE_ENABLE (1 << 4)
#define PWRGATE_STATUS_L2C_ENABLE (1 << 5)
#define PWRGATE_STATUS_MPE_ENABLE (1 << 6)
#define PWRGATE_STATUS_HEG_ENABLE (1 << 7)
#define PWRGATE_STATUS_CE1_ENABLE (1 << 9)
#define PWRGATE_STATUS_CE2_ENABLE (1 << 10)
#define PWRGATE_STATUS_CE3_ENABLE (1 << 11)
#define PWRGATE_STATUS_CELP_ENABLE (1 << 12)
#define PWRGATE_STATUS_CE0_ENABLE (1 << 14)
#define PWRGATE_STATUS_C0NC_ENABLE (1 << 15)
#define PWRGATE_STATUS_C1NC_ENABLE (1 << 16)
#define PWRGATE_STATUS_DIS_ENABLE (1 << 18)
#define PWRGATE_STATUS_DISB_ENABLE (1 << 19)
#define PWRGATE_STATUS_XUSBA_ENABLE (1 << 20)
#define PWRGATE_STATUS_XUSBB_ENABLE (1 << 21)
#define PWRGATE_STATUS_XUSBC_ENABLE (1 << 22)
/* APBDEV_PMC_CNTRL2_0 0x440 */
#define HOLD_CKE_LOW_EN (1 << 12)
enum {
PMC_OSC_EDPD_OVER_XOFS_SHIFT = 1,
PMC_OSC_EDPD_OVER_XOFS_MASK =
0x3f << PMC_OSC_EDPD_OVER_XOFS_SHIFT
};
#endif /* _TEGRA124_PMC_H_ */

View file

@ -0,0 +1,87 @@
/*
* This file is part of the coreboot project.
*
* Copyright 2013 Google Inc.
* Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that 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, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <arch/io.h>
#include <console/console.h>
#include <soc/addressmap.h>
#include "pmc.h"
#include "power.h"
static struct tegra_pmc_regs * const pmc = (void *)TEGRA_PMC_BASE;
static int partition_powered(int id)
{
return read32(&pmc->pwrgate_status) & (0x1 << id);
}
static void power_ungate_partition(uint32_t id)
{
printk(BIOS_INFO, "Ungating power partition %d.\n", id);
if (!partition_powered(id)) {
uint32_t pwrgate_toggle = read32(&pmc->pwrgate_toggle);
pwrgate_toggle &= ~(PMC_PWRGATE_TOGGLE_PARTID_MASK);
pwrgate_toggle |= (id << PMC_PWRGATE_TOGGLE_PARTID_SHIFT);
pwrgate_toggle |= PMC_PWRGATE_TOGGLE_START;
write32(pwrgate_toggle, &pmc->pwrgate_toggle);
// Wait for the request to be accepted.
while (read32(&pmc->pwrgate_toggle) & PMC_PWRGATE_TOGGLE_START)
;
printk(BIOS_DEBUG, "Power gate toggle request accepted.\n");
// Wait for the partition to be powered.
while (!partition_powered(id))
;
}
printk(BIOS_INFO, "Ungated power partition %d.\n", id);
}
void power_enable_cpu_rail(void)
{
// Set the power gate timer multiplier to 8 (why 8?).
uint32_t pwrgate_timer_mult = read32(&pmc->pwrgate_timer_mult);
pwrgate_timer_mult |= (0x3 << 0);
/*
* From U-Boot:
* Set CPUPWRGOOD_TIMER - APB clock is 1/2 of SCLK (102MHz),
* set it for 5ms as per SysEng (102MHz/5mS = 510000).
*/
write32(510000, &pmc->cpupwrgood_timer);
power_ungate_partition(POWER_PARTID_CRAIL);
uint32_t cntrl = read32(&pmc->cntrl);
cntrl &= ~PMC_CNTRL_CPUPWRREQ_POLARITY;
cntrl |= PMC_CNTRL_CPUPWRREQ_OE;
write32(cntrl, &pmc->cntrl);
}
void power_ungate_cpu(void)
{
// Ungate power to the non-core parts of the fast cluster.
power_ungate_partition(POWER_PARTID_C0NC);
// Ungate power to CPU0 in the fast cluster.
power_ungate_partition(POWER_PARTID_CE0);
}

View file

@ -0,0 +1,29 @@
/*
* This file is part of the coreboot project.
*
* Copyright 2013 Google Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that 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, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __SOC_NVIDIA_TEGRA124_POWER_H__
#define __SOC_NVIDIA_TEGRA124_POWER_H__
// This function does not enable the external power to the rail, it enables
// the rail itself internal to the SOC.
void power_enable_cpu_rail(void);
void power_ungate_cpu(void);
#endif /* __SOC_NVIDIA_TEGRA124_POWER_H__ */