diff --git a/src/soc/nvidia/tegra132/Kconfig b/src/soc/nvidia/tegra132/Kconfig index d90b8aaa8a..23f7c6e7f2 100644 --- a/src/soc/nvidia/tegra132/Kconfig +++ b/src/soc/nvidia/tegra132/Kconfig @@ -7,9 +7,21 @@ config SOC_NVIDIA_TEGRA132 select ARCH_RAMSTAGE_ARMV8_64 select ARM_LPAE select DYNAMIC_CBMEM + select BOOTBLOCK_CONSOLE + select HAVE_UART_SPECIAL + select HAVE_UART_MEMORY_MAPPED + select ARM_BOOTBLOCK_CUSTOM if SOC_NVIDIA_TEGRA132 +config BOOTBLOCK_CPU_INIT + string + default "soc/nvidia/tegra132/bootblock.c" + help + CPU/SoC-specific bootblock code. This is useful if the + bootblock must load microcode or copy data from ROM before + searching for the bootblock. + config BOOTBLOCK_ROM_OFFSET hex default 0x0 @@ -22,4 +34,24 @@ config CBFS_ROM_OFFSET hex "offset of CBFS data in ROM" default 0x40080 +config BOOTBLOCK_BASE + hex + default 0x40020000 + +config ROMSTAGE_BASE + hex + default 0x4002c000 + +config RAMSTAGE_BASE + hex + default 0x80200000 + +config STACK_TOP + hex + default 0x40020000 + +config STACK_BOTTOM + hex + default 0x4001c000 + endif diff --git a/src/soc/nvidia/tegra132/Makefile.inc b/src/soc/nvidia/tegra132/Makefile.inc index b03833920a..5c6fe81a1a 100644 --- a/src/soc/nvidia/tegra132/Makefile.inc +++ b/src/soc/nvidia/tegra132/Makefile.inc @@ -1,13 +1,29 @@ +bootblock-y += bootblock.c +bootblock-y += bootblock_asm.S bootblock-y += cbfs.c bootblock-y += timer.c +bootblock-y += clock.c +bootblock-y += ../tegra/gpio.c +bootblock-y += ../tegra/pingroup.c +bootblock-y += ../tegra/pinmux.c +bootblock-y += ../tegra/apbmisc.c +ifeq ($(CONFIG_BOOTBLOCK_CONSOLE),y) +bootblock-$(CONFIG_DRIVERS_UART) += uart.c +endif romstage-y += cbfs.c romstage-y += cbmem.c romstage-y += timer.c +romstage-y += ../tegra/gpio.c +romstage-y += ../tegra/pinmux.c +romstage-$(CONFIG_DRIVERS_UART) += uart.c ramstage-y += cbfs.c ramstage-y += cbmem.c ramstage-y += timer.c +ramstage-y += ../tegra/gpio.c +ramstage-y += ../tegra/pinmux.c +ramstage-$(CONFIG_DRIVERS_UART) += uart.c CPPFLAGS_common += -Isrc/soc/nvidia/tegra132/include/ diff --git a/src/soc/nvidia/tegra132/bootblock.c b/src/soc/nvidia/tegra132/bootblock.c new file mode 100644 index 0000000000..2d8c10ff94 --- /dev/null +++ b/src/soc/nvidia/tegra132/bootblock.c @@ -0,0 +1,59 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 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 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "pinmux.h" +#include "power.h" + +void main(void) +{ + // enable pinmux clamp inputs + clamp_tristate_inputs(); + + // enable JTAG at the earliest stage + enable_jtag(); + + clock_early_uart(); + + // Serial out, tristate off. + pinmux_set_config(PINMUX_KB_ROW9_INDEX, PINMUX_KB_ROW9_FUNC_UA3); + // Serial in, tristate_on. + pinmux_set_config(PINMUX_KB_ROW10_INDEX, PINMUX_KB_ROW10_FUNC_UA3 | + PINMUX_PULL_UP | + PINMUX_INPUT_ENABLE); + // Mux some pins away from uart A. + pinmux_set_config(PINMUX_UART2_CTS_N_INDEX, + PINMUX_UART2_CTS_N_FUNC_UB3 | + PINMUX_INPUT_ENABLE); + pinmux_set_config(PINMUX_UART2_RTS_N_INDEX, + PINMUX_UART2_RTS_N_FUNC_UB3); + + if (CONFIG_BOOTBLOCK_CONSOLE) { + console_init(); + exception_init(); + printk(BIOS_INFO, "Tegra132: Bootblock here\n"); + } +} diff --git a/src/soc/nvidia/tegra132/bootblock_asm.S b/src/soc/nvidia/tegra132/bootblock_asm.S new file mode 100644 index 0000000000..ebd64a7425 --- /dev/null +++ b/src/soc/nvidia/tegra132/bootblock_asm.S @@ -0,0 +1,89 @@ +/* + * Early initialization code for ARM architecture. + * + * This file is based off of the OMAP3530/ARM Cortex start.S file from Das + * U-Boot, which itself got the file from armboot. + * + * Copyright (c) 2004 Texas Instruments + * Copyright (c) 2001 Marius Gröger + * Copyright (c) 2002 Alex Züpke + * Copyright (c) 2002 Gary Jennejohn + * Copyright (c) 2003 Richard Woodruff + * Copyright (c) 2003 Kshitij + * Copyright (c) 2006-2008 Syed Mohammed Khasim + * Copyright (c) 2013 The Chromium OS Authors + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +ENTRY(_start) + /* + * Set the cpu to System mode with IRQ and FIQ disabled. Prefetch/Data + * aborts may happen early and crash before the abort handlers are + * installed, but at least the problem will show up near the code that + * causes it. + */ + msr cpsr_cxf, #0xdf + + /* + * Initialize the stack to a known value. This is used to check for + * stack overflow later in the boot process. + */ + ldr r0, .Stack + ldr r1, .Stack_size + sub r0, r0, r1 + ldr r1, .Stack + ldr r2, =0xdeadbeef +init_stack_loop: + str r2, [r0] + add r0, #4 + cmp r0, r1 + bne init_stack_loop + +/* Set stackpointer in internal RAM to call bootblock main() */ +call_bootblock: + ldr sp, .Stack /* Set up stack pointer */ + ldr r0,=0x00000000 + /* + * The current design of cpu_info places the + * struct at the top of the stack. The number of + * words pushed must be at least as large as that + * struct. + */ + push {r0-r2} + bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ + /* + * Use "bl" instead of "b" even though we do not intend to return. + * "bl" gets compiled to "blx" if we're transitioning from ARM to + * Thumb. However, "b" will not and GCC may attempt to create a + * wrapper which is currently broken. + */ + bl main +ENDPROC(_start) + +/* we do it this way because it's a 32-bit constant and + * in some cases too far away to be loaded as just an offset + * from IP + */ +.align 2 +.Stack: + .word CONFIG_STACK_TOP +.align 2 +/* create this size the same way we do in ramstage.ld: top-bottom */ +.Stack_size: + .word CONFIG_STACK_TOP - CONFIG_STACK_BOTTOM diff --git a/src/soc/nvidia/tegra132/clk_rst.h b/src/soc/nvidia/tegra132/clk_rst.h new file mode 100644 index 0000000000..9e2b33f4d7 --- /dev/null +++ b/src/soc/nvidia/tegra132/clk_rst.h @@ -0,0 +1,551 @@ +/* + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * + * 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 . + */ + +#ifndef _TEGRA132_CLK_RST_H_ +#define _TEGRA132_CLK_RST_H_ + +/* Clock/Reset Controller (CLK_RST_CONTROLLER_) regs */ +struct __attribute__ ((__packed__)) clk_rst_ctlr { + u32 rst_src; /* _RST_SOURCE, 0x000 */ + u32 rst_dev_l; /* _RST_DEVICES_L, 0x004 */ + u32 rst_dev_h; /* _RST_DEVICES_H, 0x008 */ + u32 rst_dev_u; /* _RST_DEVICES_U, 0x00c */ + u32 clk_out_enb_l; /* _CLK_OUT_ENB_L, 0x010 */ + u32 clk_out_enb_h; /* _CLK_OUT_ENB_H, 0x014 */ + u32 clk_out_enb_u; /* _CLK_OUT_ENB_U, 0x018 */ + u32 _rsv0; /* 0x01c */ + u32 cclk_brst_pol; /* _CCLK_BURST_POLICY, 0x020 */ + u32 super_cclk_div; /* _SUPER_CCLK_DIVIDER, 0x024 */ + u32 sclk_brst_pol; /* _SCLK_BURST_POLICY, 0x028 */ + u32 super_sclk_div; /* _SUPER_SCLK_DIVIDER, 0x02C */ + u32 clk_sys_rate; /* _CLK_SYSTEM_RATE, 0x030 */ + u32 _rsv1[3]; /* 0x034-03c */ + u32 cop_clk_skip_plcy; /* _COP_CLK_SKIP_POLICY, 0x040 */ + u32 clk_mask_arm; /* _CLK_MASK_ARM, 0x044 */ + u32 misc_clk_enb; /* _MISC_CLK_ENB, 0x048 */ + u32 clk_cpu_cmplx; /* _CLK_CPU_CMPLX, 0x04C */ + u32 osc_ctrl; /* _OSC_CTRL, 0x050 */ + u32 pll_lfsr; /* _PLL_LFSR, 0x054 */ + u32 osc_freq_det; /* _OSC_FREQ_DET, 0x058 */ + u32 osc_freq_det_stat; /* _OSC_FREQ_DET_STATUS, 0x05C */ + u32 _rsv2[8]; /* 0x060-07C */ + u32 pllc_base; /* _PLLC_BASE, 0x080 */ + u32 pllc_out; /* _PLLC_OUT, 0x084 */ + u32 pllc_misc2; /* _PLLC_MISC2, 0x088 */ + u32 pllc_misc; /* _PLLC_MISC, 0x08c */ + u32 pllm_base; /* _PLLM_BASE, 0x090 */ + u32 pllm_out; /* _PLLM_OUT, 0x094 */ + u32 pllm_misc1; /* _PLLM_MISC1, 0x098 */ + u32 pllm_misc2; /* _PLLM_MISC2, 0x09c */ + u32 pllp_base; /* _PLLP_BASE, 0x0a0 */ + u32 pllp_outa; /* _PLLP_OUTA, 0x0a4 */ + u32 pllp_outb; /* _PLLP_OUTB, 0x0a8 */ + u32 pllp_misc; /* _PLLP_MISC, 0x0ac */ + u32 plla_base; /* _PLLA_BASE, 0x0b0 */ + u32 plla_out; /* _PLLA_OUT, 0x0b4 */ + u32 _rsv3; /* 0x0b8 */ + u32 plla_misc; /* _PLLA_MISC, 0x0bc */ + u32 pllu_base; /* _PLLU_BASE, 0x0c0 */ + u32 _rsv4[2]; /* 0x0c4-0c8 */ + u32 pllu_misc; /* _PLLU_MISC, 0x0cc */ + u32 plld_base; /* _PLLD_BASE, 0x0d0 */ + u32 _rsv5[2]; /* 0x0d4-0d8 */ + u32 plld_misc; /* _PLLD_MISC, 0x0dc */ + u32 pllx_base; /* _PLLX_BASE, 0x0e0 */ + u32 pllx_misc; /* _PLLX_MISC, 0x0e4 */ + u32 plle_base; /* _PLLE_BASE, 0x0e8 */ + u32 plle_misc; /* _PLLE_MISC, 0x0ec */ + u32 plls_base; /* _PLLS_BASE, 0x0f0 */ + u32 plls_misc; /* _PLLS_MISC, 0x0f4 */ + u32 _rsv6[2]; /* 0x0f8-0fc */ + u32 clk_src_i2s1; /* _CLK_SOURCE_I2S1, 0x100 */ + u32 clk_src_i2s2; /* _CLK_SOURCE_I2S2, 0x104 */ + u32 clk_src_spdif_out; /* _CLK_SOURCE_SPDIF_OUT, 0x108 */ + u32 clk_src_spdif_in; /* _CLK_SOURCE_SPDIF_IN, 0x10c */ + u32 clk_src_pwm; /* _CLK_SOURCE_PWM, 0x110 */ + u32 _rsv7; /* 0x114 */ + u32 clk_src_sbc2; /* _CLK_SOURCE_SBC2, 0x118 */ + u32 clk_src_sbc3; /* _CLK_SOURCE_SBC3, 0x11c */ + u32 _rsv8; /* 0x120 */ + u32 clk_src_i2c1; /* _CLK_SOURCE_I2C1, 0x124 */ + u32 clk_src_i2c5; /* _CLK_SOURCE_I2C5, 0x128 */ + u32 _rsv9[2]; /* 0x12c-130 */ + u32 clk_src_sbc1; /* _CLK_SOURCE_SBC1, 0x134 */ + u32 clk_src_disp1; /* _CLK_SOURCE_DISP1, 0x138 */ + u32 clk_src_disp2; /* _CLK_SOURCE_DISP2, 0x13c */ + u32 _rsv10[2]; /* 0x140-144 */ + u32 clk_src_vi; /* _CLK_SOURCE_VI, 0x148 */ + u32 _rsv11; /* 0x14c */ + u32 clk_src_sdmmc1; /* _CLK_SOURCE_SDMMC1, 0x150 */ + u32 clk_src_sdmmc2; /* _CLK_SOURCE_SDMMC2, 0x154 */ + u32 clk_src_g3d; /* _CLK_SOURCE_G3D, 0x158 */ + u32 clk_src_g2d; /* _CLK_SOURCE_G2D, 0x15c */ + u32 clk_src_ndflash; /* _CLK_SOURCE_NDFLASH, 0x160 */ + u32 clk_src_sdmmc4; /* _CLK_SOURCE_SDMMC4, 0x164 */ + u32 clk_src_vfir; /* _CLK_SOURCE_VFIR, 0x168 */ + u32 clk_src_epp; /* _CLK_SOURCE_EPP, 0x16c */ + u32 clk_src_mpe; /* _CLK_SOURCE_MPE, 0x170 */ + u32 clk_src_hsi; /* _CLK_SOURCE_HSI, 0x174 */ + u32 clk_src_uarta; /* _CLK_SOURCE_UARTA, 0x178 */ + u32 clk_src_uartb; /* _CLK_SOURCE_UARTB, 0x17c */ + u32 clk_src_host1x; /* _CLK_SOURCE_HOST1X, 0x180 */ + u32 _rsv12[2]; /* 0x184-188 */ + u32 clk_src_hdmi; /* _CLK_SOURCE_HDMI, 0x18c */ + u32 _rsv13[2]; /* 0x190-194 */ + u32 clk_src_i2c2; /* _CLK_SOURCE_I2C2, 0x198 */ + u32 clk_src_emc; /* _CLK_SOURCE_EMC, 0x19c */ + u32 clk_src_uartc; /* _CLK_SOURCE_UARTC, 0x1a0 */ + u32 _rsv14; /* 0x1a4 */ + u32 clk_src_vi_sensor; /* _CLK_SOURCE_VI_SENSOR, 0x1a8 */ + u32 _rsv15[2]; /* 0x1ac-1b0 */ + u32 clk_src_sbc4; /* _CLK_SOURCE_SBC4, 0x1b4 */ + u32 clk_src_i2c3; /* _CLK_SOURCE_I2C3, 0x1b8 */ + u32 clk_src_sdmmc3; /* _CLK_SOURCE_SDMMC3, 0x1bc */ + u32 clk_src_uartd; /* _CLK_SOURCE_UARTD, 0x1c0 */ + u32 clk_src_uarte; /* _CLK_SOURCE_UARTE, 0x1c4 */ + u32 clk_src_vde; /* _CLK_SOURCE_VDE, 0x1c8 */ + u32 clk_src_owr; /* _CLK_SOURCE_OWR, 0x1cc */ + u32 clk_src_nor; /* _CLK_SOURCE_NOR, 0x1d0 */ + u32 clk_src_csite; /* _CLK_SOURCE_CSITE, 0x1d4 */ + u32 clk_src_i2s0; /* _CLK_SOURCE_I2S0, 0x1d8 */ + u32 clk_src_dtv; /* _CLK_SOURCE_DTV, 0x1dc */ + u32 _rsv16[4]; /* 0x1e0-1ec */ + u32 clk_src_msenc; /* _CLK_SOURCE_MSENC, 0x1f0 */ + u32 clk_src_tsec; /* _CLK_SOURCE_TSEC, 0x1f4 */ + u32 _rsv17; /* 0x1f8 */ + u32 clk_src_osc; /* _CLK_SOURCE_OSC, 0x1fc */ + u32 _rsv18[32]; /* 0x200-27c */ + u32 clk_out_enb_x; /* _CLK_OUT_ENB_X_0, 0x280 */ + u32 clk_enb_x_set; /* _CLK_ENB_X_SET_0, 0x284 */ + u32 clk_enb_x_clr; /* _CLK_ENB_X_CLR_0, 0x288 */ + u32 rst_devices_x; /* _RST_DEVICES_X_0, 0x28c */ + u32 rst_dev_x_set; /* _RST_DEV_X_SET_0, 0x290 */ + u32 rst_dev_x_clr; /* _RST_DEV_X_CLR_0, 0x294 */ + u32 _rsv19[23]; /* 0x298-2f0 */ + u32 dfll_base; /* _DFLL_BASE_0, 0x2f4 */ + u32 _rsv20[2]; /* 0x2f8-2fc */ + u32 rst_dev_l_set; /* _RST_DEV_L_SET 0x300 */ + u32 rst_dev_l_clr; /* _RST_DEV_L_CLR 0x304 */ + u32 rst_dev_h_set; /* _RST_DEV_H_SET 0x308 */ + u32 rst_dev_h_clr; /* _RST_DEV_H_CLR 0x30c */ + u32 rst_dev_u_set; /* _RST_DEV_U_SET 0x310 */ + u32 rst_dev_u_clr; /* _RST_DEV_U_CLR 0x314 */ + u32 _rsv21[2]; /* 0x318-31c */ + u32 clk_enb_l_set; /* _CLK_ENB_L_SET 0x320 */ + u32 clk_enb_l_clr; /* _CLK_ENB_L_CLR 0x324 */ + u32 clk_enb_h_set; /* _CLK_ENB_H_SET 0x328 */ + u32 clk_enb_h_clr; /* _CLK_ENB_H_CLR 0x32c */ + u32 clk_enb_u_set; /* _CLK_ENB_U_SET 0x330 */ + u32 clk_enb_u_clk; /* _CLK_ENB_U_CLR 0x334 */ + u32 _rsv22; /* 0x338 */ + u32 ccplex_pg_sm_ovrd; /* _CCPLEX_PG_SM_OVRD, 0x33c */ + u32 rst_cpu_cmplx_set; /* _RST_CPU_CMPLX_SET, 0x340 */ + u32 rst_cpu_cmplx_clr; /* _RST_CPU_CMPLX_CLR, 0x344 */ + u32 clk_cpu_cmplx_set; /* _CLK_CPU_CMPLX_SET, 0x348 */ + u32 clk_cpu_cmplx_clr; /* _CLK_CPU_CMPLX_SET, 0x34c */ + u32 _rsv23[2]; /* 0x350-354 */ + u32 rst_dev_v; /* _RST_DEVICES_V, 0x358 */ + u32 rst_dev_w; /* _RST_DEVICES_W, 0x35c */ + u32 clk_out_enb_v; /* _CLK_OUT_ENB_V, 0x360 */ + u32 clk_out_enb_w; /* _CLK_OUT_ENB_W, 0x364 */ + u32 cclkg_brst_pol; /* _CCLKG_BURST_POLICY, 0x368 */ + u32 super_cclkg_div; /* _SUPER_CCLKG_DIVIDER, 0x36c */ + u32 cclklp_brst_pol; /* _CCLKLP_BURST_POLICY, 0x370 */ + u32 super_cclkp_div; /* _SUPER_CCLKLP_DIVIDER, 0x374 */ + u32 clk_cpug_cmplx; /* _CLK_CPUG_CMPLX, 0x378 */ + u32 clk_cpulp_cmplx; /* _CLK_CPULP_CMPLX, 0x37c */ + u32 cpu_softrst_ctrl; /* _CPU_SOFTRST_CTRL, 0x380 */ + u32 cpu_softrst_ctrl1; /* _CPU_SOFTRST_CTRL1, 0x384 */ + u32 cpu_softrst_ctrl2; /* _CPU_SOFTRST_CTRL2, 0x388 */ + u32 _rsv24[9]; /* 0x38c-3ac */ + u32 clk_src_g3d2; /* _CLK_SOURCE_G3D2, 0x3b0 */ + u32 clk_src_mselect; /* _CLK_SOURCE_MSELECT, 0x3b4 */ + u32 clk_src_tsensor; /* _CLK_SOURCE_TSENSOR, 0x3b8 */ + u32 clk_src_i2s3; /* _CLK_SOURCE_I2S3, 0x3bc */ + u32 clk_src_i2s4; /* _CLK_SOURCE_I2S4, 0x3c0 */ + u32 clk_src_i2c4; /* _CLK_SOURCE_I2C4, 0x3c4 */ + u32 clk_src_sbc5; /* _CLK_SOURCE_SBC5, 0x3c8 */ + u32 clk_src_sbc6; /* _CLK_SOURCE_SBC6, 0x3cc */ + u32 clk_src_audio; /* _CLK_SOURCE_AUDIO, 0x3d0 */ + u32 _rsv25; /* 0x3d4 */ + u32 clk_src_dam0; /* _CLK_SOURCE_DAM0, 0x3d8 */ + u32 clk_src_dam1; /* _CLK_SOURCE_DAM1, 0x3dc */ + u32 clk_src_dam2; /* _CLK_SOURCE_DAM2, 0x3e0 */ + u32 clk_src_hda2codec_2x; /* _CLK_SOURCE_HDA2CODEC_2X,0x3e4 */ + u32 clk_src_actmon; /* _CLK_SOURCE_ACTMON, 0x3e8 */ + u32 clk_src_extperiph1; /* _CLK_SOURCE_EXTPERIPH1, 0x3ec */ + u32 clk_src_extperiph2; /* _CLK_SOURCE_EXTPERIPH2, 0x3f0 */ + u32 clk_src_extperiph3; /* _CLK_SOURCE_EXTPERIPH3, 0x3f4 */ + u32 clk_src_nand_speed; /* _CLK_SOURCE_NAND_SPEED, 0x3f8 */ + u32 clk_src_i2c_slow; /* _CLK_SOURCE_I2C_SLOW, 0x3fc */ + u32 clk_src_sys; /* _CLK_SOURCE_SYS, 0x400 */ + u32 _rsv26[4]; /* 0x404-410 */ + u32 clk_src_sor; /* _CLK_SOURCE_SOR_0, 0x414 */ + u32 _rsv261[2]; /* 0x404-410 */ + u32 clk_src_sata_oob; /* _CLK_SOURCE_SATA_OOB, 0x420 */ + u32 clk_src_sata; /* _CLK_SOURCE_SATA, 0x424 */ + u32 clk_src_hda; /* _CLK_SOURCE_HDA, 0x428 */ + u32 _rsv27; /* 0x42c */ + u32 rst_dev_v_set; /* _RST_DEV_V_SET, 0x430 */ + u32 rst_dev_v_clr; /* _RST_DEV_V_CLR, 0x434 */ + u32 rst_dev_w_set; /* _RST_DEV_W_SET, 0x438 */ + u32 rst_dev_w_clr; /* _RST_DEV_W_CLR, 0x43c */ + u32 clk_enb_v_set; /* _CLK_ENB_V_SET, 0x440 */ + u32 clk_enb_v_clr; /* _CLK_ENB_V_CLR, 0x444 */ + u32 clk_enb_w_set; /* _CLK_ENB_W_SET, 0x448 */ + u32 clk_enb_w_clr; /* _CLK_ENB_W_CLR, 0x44c */ + u32 rst_cpug_cmplx_set; /* _RST_CPUG_CMPLX_SET, 0x450 */ + u32 rst_cpug_cmplx_clr; /* _RST_CPUG_CMPLX_CLR, 0x454 */ + u32 rst_cpulp_cmplx_set; /* _RST_CPULP_CMPLX_SET, 0x458 */ + u32 rst_cpulp_cmplx_clr; /* _RST_CPULP_CMPLX_CLR, 0x45C */ + u32 clk_cpug_cmplx_set; /* _CLK_CPUG_CMPLX_SET, 0x460 */ + u32 clk_cpug_cmplx_clr; /* _CLK_CPUG_CMPLX_CLR, 0x464 */ + u32 clk_cpulp_cmplx_set; /* _CLK_CPULP_CMPLX_SET, 0x468 */ + u32 clk_cpulp_cmplx_clr; /* _CLK_CPULP_CMPLX_CLR, 0x46c */ + u32 cpu_cmplx_status; /* _CPU_CMPLX_STATUS, 0x470 */ + u32 _rsv28; /* 0x474 */ + u32 intstatus; /* _INTSTATUS, 0x478 */ + u32 intmask; /* _INTMASK, 0x47c */ + u32 utmip_pll_cfg0; /* _UTMIP_PLL_CFG0, 0x480 */ + u32 utmip_pll_cfg1; /* _UTMIP_PLL_CFG1, 0x484 */ + u32 utmip_pll_cfg2; /* _UTMIP_PLL_CFG2, 0x488 */ + u32 plle_aux; /* _PLLE_AUX, 0x48c */ + u32 sata_pll_cfg0; /* _SATA_PLL_CFG0, 0x490 */ + u32 sata_pll_cfg1; /* _SATA_PLL_CFG1, 0x494 */ + u32 pcie_pll_cfg0; /* _PCIE_PLL_CFG0, 0x498 */ + u32 prog_audio_dly_clk; /* _PROG_AUDIO_DLY_CLK, 0x49c */ + u32 audio_sync_clk_i2s0; /* _AUDIO_SYNC_CLK_I2S0, 0x4a0 */ + u32 audio_sync_clk_i2s1; /* _AUDIO_SYNC_CLK_I2S1, 0x4a4 */ + u32 audio_sync_clk_i2s2; /* _AUDIO_SYNC_CLK_I2S2, 0x4a8 */ + u32 audio_sync_clk_i2s3; /* _AUDIO_SYNC_CLK_I2S3, 0x4ac */ + u32 audio_sync_clk_i2s4; /* _AUDIO_SYNC_CLK_I2S4, 0x4b0 */ + u32 audio_sync_clk_spdif; /* _AUDIO_SYNC_CLK_SPDIF, 0x4b4 */ + u32 plld2_base; /* _PLLD2_BASE, 0x4b8 */ + u32 plld2_misc; /* _PLLD2_MISC, 0x4bc */ + u32 utmip_pll_cfg3; /* _UTMIP_PLL_CFG3, 0x4c0 */ + u32 pllrefe_base; /* _PLLREFE_BASE, 0x4c4 */ + u32 pllrefe_misc; /* _PLLREFE_MISC, 0x4c8 */ + u32 _rsv29[7]; /* 0x4cc-4e4 */ + u32 pllc2_base; /* _PLLC2_BASE, 0x4e8 */ + u32 pllc2_misc0; /* _PLLC2_MISC_0, 0x4ec */ + u32 pllc2_misc1; /* _PLLC2_MISC_1, 0x4f0 */ + u32 pllc2_misc2; /* _PLLC2_MISC_2, 0x4f4 */ + u32 pllc2_misc3; /* _PLLC2_MISC_3, 0x4f8 */ + u32 pllc3_base; /* _PLLC3_BASE, 0x4fc */ + u32 pllc3_misc0; /* _PLLC3_MISC_0, 0x500 */ + u32 pllc3_misc1; /* _PLLC3_MISC_1, 0x504 */ + u32 pllc3_misc2; /* _PLLC3_MISC_2, 0x508 */ + u32 pllc3_misc3; /* _PLLC3_MISC_3, 0x50c */ + u32 pllx_misc1; /* _PLLX_MISC_1, 0x510 */ + u32 pllx_misc2; /* _PLLX_MISC_2, 0x514 */ + u32 pllx_misc3; /* _PLLX_MISC_3, 0x518 */ + u32 xusbio_pll_cfg0; /* _XUSBIO_PLL_CFG0, 0x51c */ + u32 xusbio_pll_cfg1; /* _XUSBIO_PLL_CFG1, 0x520 */ + u32 plle_aux1; /* _PLLE_AUX1, 0x524 */ + u32 pllp_reshift; /* _PLLP_RESHIFT, 0x528 */ + u32 utmipll_hw_pwrdn_cfg0; /* _UTMIPLL_HW_PWRDN_CFG0, 0x52c */ + u32 pllu_hw_pwrdn_cfg0; /* _PLLU_HW_PWRDN_CFG0, 0x530 */ + u32 xusb_pll_cfg0; /* _XUSB_PLL_CFG0, 0x534 */ + u32 _rsv30; /* 0x538 */ + u32 clk_cpu_misc; /* _CLK_CPU_MISC, 0x53c */ + u32 clk_cpug_misc; /* _CLK_CPUG_MISC, 0x540 */ + u32 clk_cpulp_misc; /* _CLK_CPULP_MISC, 0x544 */ + u32 pllx_hw_ctrl_cfg; /* _PLLX_HW_CTRL_CFG, 0x548 */ + u32 pllx_sw_ramp_cfg; /* _PLLX_SW_RAMP_CFG, 0x54c */ + u32 pllx_hw_ctrl_status; /* _PLLX_HW_CTRL_STATUS, 0x550 */ + u32 _rsv31; /* 0x554 */ + u32 super_gr3d_clk_div; /* _SUPER_GR3D_CLK_DIVIDER, 0x558 */ + u32 spare_reg0; /* _SPARE_REG0, 0x55c */ + u32 _rsv32[4]; /* 0x560-0x56c */ + u32 plld2_ss_cfg; /* _PLLD2_SS_CFG 0x570 */ + u32 _rsv32_1[7]; /* 0x574-58c */ + u32 plldp_base; /* _PLLDP_BASE, 0x590 */ + u32 plldp_misc; /* _PLLDP_MISC, 0x594 */ + u32 plldp_ss_cfg; /* _PLLDP_SS_CFG, 0x598 */ + u32 _rsrv32_2[25]; + u32 clk_src_xusb_core_host; /* _CLK_SOURCE_XUSB_CORE_HOST 0x600 */ + u32 clk_src_xusb_falcon; /* _CLK_SOURCE_XUSB_FALCON 0x604 */ + u32 clk_src_xusb_fs; /* _CLK_SOURCE_XUSB_FS 0x608 */ + u32 clk_src_xusb_core_dev; /* _CLK_SOURCE_XUSB_CORE_DEV 0x60c */ + u32 clk_src_xusb_ss; /* _CLK_SOURCE_XUSB_SS 0x610 */ + u32 clk_src_cilab; /* _CLK_SOURCE_CILAB 0x614 */ + u32 clk_src_cilcd; /* _CLK_SOURCE_CILCD 0x618 */ + u32 clk_src_cile; /* _CLK_SOURCE_CILE 0x61c */ + u32 clk_src_dsia_lp; /* _CLK_SOURCE_DSIA_LP 0x620 */ + u32 clk_src_dsib_lp; /* _CLK_SOURCE_DSIB_LP 0x624 */ + u32 clk_src_entropy; /* _CLK_SOURCE_ENTROPY 0x628 */ + u32 clk_src_dvfs_ref; /* _CLK_SOURCE_DVFS_REF 0x62c */ + u32 clk_src_dvfs_soc; /* _CLK_SOURCE_DVFS_SOC 0x630 */ + u32 clk_src_traceclkin; /* _CLK_SOURCE_TRACECLKIN 0x634 */ + u32 clk_src_adx0; /* _CLK_SOURCE_ADX0 0x638 */ + u32 clk_src_amx0; /* _CLK_SOURCE_AMX0 0x63c */ + u32 clk_src_emc_latency; /* _CLK_SOURCE_EMC_LATENCY 0x640 */ + u32 clk_src_soc_therm; /* _CLK_SOURCE_SOC_THERM 0x644 */ +}; +check_member(clk_rst_ctlr, clk_src_soc_therm, 0x644); + +#define TEGRA_DEV_L 0 +#define TEGRA_DEV_H 1 +#define TEGRA_DEV_U 2 +#define TEGRA_DEV_V 0 +#define TEGRA_DEV_W 1 + +#define SIMPLE_PLLX (CLOCK_ID_XCPU - CLOCK_ID_FIRST_SIMPLE) + +/* Bits to enable/reset modules */ +#define CLK_ENB_CPU (1 << 0) +#define SWR_TRIG_SYS_RST (1 << 2) +#define SWR_CSITE_RST (1 << 9) +#define CLK_ENB_CSITE (1 << 9) + +/* CRC_SUPER_CCLK_DIVIDER_0 0x24 */ +#define SUPER_CDIV_ENB_ENABLE (1 << 31) + +/* CLK_RST_CONTROLLER_MISC_CLK_ENB 0x48 */ +#define EN_PPSB_STOPCLK (1 << 0) + +/* CLK_RST_CONTROLLER_CLK_CPU_CMPLX_0 (0x4C) */ +#define CPU3_CLK_STP_SHIFT 11 +#define CPU2_CLK_STP_SHIFT 10 +#define CPU1_CLK_STP_SHIFT 9 +#define CPU0_CLK_STP_SHIFT 8 +#define CPU0_CLK_STP_MASK (1U << CPU0_CLK_STP_SHIFT) + +/* CRC_OSC_CTRL_0 0x50 */ +#define OSC_FREQ_SHIFT 28 +#define OSC_FREQ_MASK (0xf << OSC_FREQ_SHIFT) +#define OSC_PREDIV_SHIFT 26 +#define OSC_PREDIV_MASK (0x3 << OSC_PREDIV_SHIFT) +#define OSC_XOFS_SHIFT 4 +#define OSC_XOFS_MASK (0x3F << OSC_XOFS_SHIFT) +#define OSC_DRIVE_STRENGTH 7 +#define OSC_XOBP (1 << 1) +#define OSC_XOE (1 << 0) + +enum { + OSC_FREQ_12 = 8, /* 12.0MHz */ + OSC_FREQ_13 = 0, /* 13.0MHz */ + OSC_FREQ_16P8 = 1, /* 16.8MHz */ + OSC_FREQ_19P2 = 4, /* 19.2MHz */ + OSC_FREQ_26 = 12, /* 26.0MHz */ + OSC_FREQ_38P4 = 5, /* 38.4MHz */ + OSC_FREQ_48 = 9, /* 48.0MHz */ +}; + +/* CLK_RST_CONTROLLER_PLL*_BASE_0 */ +#define PLL_BASE_BYPASS (1U << 31) +#define PLL_BASE_ENABLE (1U << 30) +#define PLL_BASE_REF_DIS (1U << 29) +#define PLL_BASE_OVRRIDE (1U << 28) +#define PLL_BASE_LOCK (1U << 27) + +#define PLL_BASE_DIVP_SHIFT 20 +#define PLL_BASE_DIVP_MASK (7U << PLL_BASE_DIVP_SHIFT) + +#define PLL_BASE_DIVN_SHIFT 8 +#define PLL_BASE_DIVN_MASK (0x3ffU << PLL_BASE_DIVN_SHIFT) + +#define PLL_BASE_DIVM_SHIFT 0 +#define PLL_BASE_DIVM_MASK (0x1f << PLL_BASE_DIVM_SHIFT) + +/* SPECIAL CASE: PLLM, PLLC and PLLX use different-sized fields here */ +#define PLLCX_BASE_DIVP_MASK (0xfU << PLL_BASE_DIVP_SHIFT) +#define PLLM_BASE_DIVP_MASK (0x1U << PLL_BASE_DIVP_SHIFT) +#define PLLCMX_BASE_DIVN_MASK (0xffU << PLL_BASE_DIVN_SHIFT) +#define PLLCMX_BASE_DIVM_MASK (0xffU << PLL_BASE_DIVM_SHIFT) + +/* PLLM specific registers */ +#define PLLM_MISC1_SETUP_SHIFT 0 +#define PLLM_MISC1_PD_LSHIFT_PH45_SHIFT 28 +#define PLLM_MISC1_PD_LSHIFT_PH90_SHIFT 29 +#define PLLM_MISC1_PD_LSHIFT_PH135_SHIFT 30 +#define PLLM_MISC2_KCP_SHIFT 1 +#define PLLM_MISC2_KVCO_SHIFT 0 +#define PLLM_OUT1_RSTN_RESET_DISABLE (1 << 0) + +/* Generic, indiscriminate divisor mask. May catch some innocent bystander bits + * on the side that we don't particularly care about. */ +#define PLL_BASE_DIV_MASK (0xffffff) + +/* CLK_RST_CONTROLLER_PLL*_OUT*_0 */ +#define PLL_OUT_RSTN (1 << 0) +#define PLL_OUT_CLKEN (1 << 1) +#define PLL_OUT_OVR (1 << 2) + +#define PLL_OUT_RATIO_SHIFT 8 +#define PLL_OUT_RATIO_MASK (0xffU << PLL_OUT_RATIO_SHIFT) + +#define PLL_OUT1_SHIFT 0 +#define PLL_OUT2_SHIFT 16 +#define PLL_OUT3_SHIFT 0 +#define PLL_OUT4_SHIFT 16 + +/* CLK_RST_CONTROLLER_PLL*_MISC_0 */ +#define PLL_MISC_DCCON (1 << 20) + +#define PLL_MISC_CPCON_SHIFT 8 +#define PLL_MISC_CPCON_MASK (0xfU << PLL_MISC_CPCON_SHIFT) + +#define PLL_MISC_LFCON_SHIFT 4 +#define PLL_MISC_LFCON_MASK (0xfU << PLL_MISC_LFCON_SHIFT) + +/* This bit is different all over the place. Oh joy... */ +#define PLLDPD2_MISC_LOCK_ENABLE (1 << 30) +#define PLLC_MISC_LOCK_ENABLE (1 << 24) +#define PLLUD_MISC_LOCK_ENABLE (1 << 22) +#define PLLD_MISC_CLK_ENABLE (1 << 30) +#define PLLPAXS_MISC_LOCK_ENABLE (1 << 18) +#define PLLE_MISC_LOCK_ENABLE (1 << 9) + +#define PLLU_MISC_VCO_FREQ (1 << 20) + +/* PLLX_BASE_0 0xe0 */ +#define PLLX_BASE_PLLX_ENABLE (1 << 30) + +/* CLK_RST_CONTROLLER_PLLX_MISC_3 */ +#define PLLX_IDDQ_SHIFT 3 +#define PLLX_IDDQ_MASK (1U << PLLX_IDDQ_SHIFT) + +#define CLK_DIVISOR_MASK (0xffff) + +#define CLK_SOURCE_SHIFT 29 +#define CLK_SOURCE_MASK (0x7 << CLK_SOURCE_SHIFT) + +#define CLK_SOURCE_EMC_MC_EMC_SAME_FREQ (1 << 16) + +#define CLK_UART_DIV_OVERRIDE (1 << 24) + +/* CLK_RST_CONTROLLER_SCLK_BURST_POLICY */ +#define SCLK_SYS_STATE_SHIFT 28U +#define SCLK_SYS_STATE_MASK (15U << SCLK_SYS_STATE_SHIFT) +enum { + SCLK_SYS_STATE_STDBY, + SCLK_SYS_STATE_IDLE, + SCLK_SYS_STATE_RUN, + SCLK_SYS_STATE_IRQ = 4U, + SCLK_SYS_STATE_FIQ = 8U, +}; +#define SCLK_COP_FIQ_MASK (1 << 27) +#define SCLK_CPU_FIQ_MASK (1 << 26) +#define SCLK_COP_IRQ_MASK (1 << 25) +#define SCLK_CPU_IRQ_MASK (1 << 24) + +#define SCLK_FIQ_SHIFT 12 +#define SCLK_FIQ_MASK (7 << SCLK_FIQ_SHIFT) +#define SCLK_IRQ_SHIFT 8 +#define SCLK_IRQ_MASK (7 << SCLK_FIQ_SHIFT) +#define SCLK_RUN_SHIFT 4 +#define SCLK_RUN_MASK (7 << SCLK_FIQ_SHIFT) +#define SCLK_IDLE_SHIFT 0 +#define SCLK_IDLE_MASK (7 << SCLK_FIQ_SHIFT) +enum { + SCLK_SOURCE_CLKM, + SCLK_SOURCE_PLLC_OUT1, + SCLK_SOURCE_PLLP_OUT4, + SCLK_SOURCE_PLLP_OUT3, + SCLK_SOURCE_PLLP_OUT2, + SCLK_SOURCE_PLLC_OUT0, + SCLK_SOURCE_CLKS, + SCLK_SOURCE_PLLM_OUT1, +}; + +/* CLK_RST_CONTROLLER_SUPER_SCLK_DIVIDER 0x2c */ +#define SCLK_DIV_ENB (1 << 31) +#define SCLK_DIVIDEND_SHIFT 8 +#define SCLK_DIVIDEND_MASK (0xff << SCLK_DIVIDEND_SHIFT) +#define SCLK_DIVISOR_SHIFT 0 +#define SCLK_DIVISOR_MASK (0xff << SCLK_DIVISOR_SHIFT) + +/* CLK_RST_CONTROLLER_CLK_SYSTEM_RATE 0x30 */ +#define HCLK_DISABLE (1 << 7) +#define HCLK_DIVISOR_SHIFT 4 +#define HCLK_DIVISOR_MASK (3 << AHB_RATE_SHIFT) +#define PCLK_DISABLE (1 << 3) +#define PCLK_DIVISOR_SHIFT 0 +#define PCLK_DIVISOR_MASK (3 << AHB_RATE_SHIFT) + +/* CRC_CLK_SOURCE_MSELECT_0 0x3b4 */ +#define MSELECT_CLK_SRC_PLLP_OUT0 (0 << 29) + +/* CRC_CLK_ENB_V_SET_0 0x440 */ +#define SET_CLK_ENB_CPUG_ENABLE (1 << 0) +#define SET_CLK_ENB_CPULP_ENABLE (1 << 1) +#define SET_CLK_ENB_MSELECT_ENABLE (1 << 3) + +/* CLK_RST_CONTROLLER_UTMIP_PLL_CFG1_0 0x484 */ +#define PLLU_POWERDOWN (1 << 16) +#define PLL_ENABLE_POWERDOWN (1 << 14) +#define PLL_ACTIVE_POWERDOWN (1 << 12) + +/* CLK_RST_CONTROLLER_UTMIP_PLL_CFG2_0 0x488 */ +#define UTMIP_FORCE_PD_SAMP_C_POWERDOWN (1 << 4) +#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, +}; + +// RST_CPULP_CMPLX_CLR +enum { + CRC_RST_CPULP_CLR_CPU0 = 0x1 << 0, + CRC_RST_CPULP_CLR_DBG0 = 0x1 << 12, + CRC_RST_CPULP_CLR_CORE0 = 0x1 << 16, + CRC_RST_CPULP_CLR_CX0 = 0x1 << 20, + CRC_RST_CPULP_CLR_L2 = 0x1 << 24, + CRC_RST_CPULP_CLR_NONCPU = 0x1 << 29, + CRC_RST_CPULP_CLR_PDBG = 0x1 << 30, +}; + +#endif /* _TEGRA132_CLK_RST_H_ */ diff --git a/src/soc/nvidia/tegra132/clock.c b/src/soc/nvidia/tegra132/clock.c new file mode 100644 index 0000000000..5237712ef3 --- /dev/null +++ b/src/soc/nvidia/tegra132/clock.c @@ -0,0 +1,662 @@ +/* + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * Copyright 2014 Google Inc. + * + * 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 . + */ +#include +#include +#include +#include +#include +#include +#include "clk_rst.h" +#include "flow.h" +#include "maincpu.h" +#include "pmc.h" +#include "sysctr.h" + +static struct clk_rst_ctlr *clk_rst = (void *)TEGRA_CLK_RST_BASE; +static struct flow_ctlr *flow = (void *)TEGRA_FLOW_BASE; +static struct tegra_pmc_regs *pmc = (void *)TEGRA_PMC_BASE; +static struct sysctr_regs *sysctr = (void *)TEGRA_SYSCTR0_BASE; + +struct pll_dividers { + u32 n : 10; + u32 m : 8; + u32 p : 4; + u32 cpcon : 4; + u32 lfcon : 4; + u32 : 2; +}; + +/* Some PLLs have more restrictive divider bit lengths or are missing some + * fields. Make sure to use the right struct in the osc_table definition to get + * compile-time checking, but keep the bits aligned with struct pll_dividers so + * they can be used interchangeably at run time. Add new formats as required. */ +struct pllcx_dividers { + u32 n : 8; + u32 : 2; + u32 m : 8; + u32 p : 4; + u32 : 10; +}; +struct pllpad_dividers { + u32 n : 10; + u32 m : 5; + u32 : 3; + u32 p : 3; + u32 : 1; + u32 cpcon : 4; + u32 : 6; +}; +struct pllu_dividers { + u32 n : 10; + u32 m : 5; + u32 : 3; + u32 p : 1; + u32 : 3; + u32 cpcon : 4; + u32 lfcon : 4; + u32 : 2; +}; + +union __attribute__((transparent_union)) pll_fields { + u32 raw; + struct pll_dividers div; + struct pllcx_dividers cx; + struct pllpad_dividers pad; + struct pllu_dividers u; +}; + +/* This table defines the frequency dividers for every PLL to turn the external + * OSC clock into the frequencies defined by TEGRA_PLL*_KHZ in soc/clock.h. + * All PLLs have three dividers (n, m and p), with the governing formula for + * the output frequency being CF = (IN / m), VCO = CF * n and OUT = VCO / (2^p). + * All divisor configurations must meet the PLL's constraints for VCO and CF: + * PLLX: 12 MHz < CF < 50 MHz, 700 MHz < VCO < 3000 MHz + * PLLC: 12 MHz < CF < 50 MHz, 600 MHz < VCO < 1400 MHz + * PLLM: 12 MHz < CF < 50 MHz, 400 MHz < VCO < 1066 MHz + * PLLP: 1 MHz < CF < 6 MHz, 200 MHz < VCO < 700 MHz + * PLLD: 1 MHz < CF < 6 MHz, 500 MHz < VCO < 1000 MHz + * PLLU: 1 MHz < CF < 6 MHz, 480 MHz < VCO < 960 MHz + * PLLDP: 12 MHz < CF < 38 MHz, 600 MHz < VCO < 1200 MHz + * (values taken from Linux' drivers/clk/tegra/clk-tegra124.c). */ +struct { + int khz; + struct pllcx_dividers pllx; /* target: CONFIG_PLLX_KHZ */ + struct pllcx_dividers pllc; /* target: 600 MHz */ + /* PLLM is set up dynamically by clock_sdram(). */ + /* PLLP is hardwired to 408 MHz in HW (unless we set BASE_OVRD). */ + struct pllu_dividers pllu; /* target; 960 MHz */ + struct pllcx_dividers plldp; /* target; 270 MHz */ + /* PLLDP treats p differently (OUT = VCO / (p + 1) for p < 6). */ +} static const osc_table[16] = { + [OSC_FREQ_12]{ + .khz = 12000, + .pllx = {.n = TEGRA_PLLX_KHZ / 12000, .m = 1, .p = 0}, + .pllc = {.n = 50, .m = 1, .p = 0}, + .pllu = {.n = 960, .m = 12, .p = 0, .cpcon = 12, .lfcon = 2}, + .plldp = {.n = 90, .m = 1, .p = 3}, + }, + [OSC_FREQ_13]{ + .khz = 13000, + .pllx = {.n = TEGRA_PLLX_KHZ / 13000, .m = 1, .p = 0}, + .pllc = {.n = 46, .m = 1, .p = 0}, /* 598.0 MHz */ + .pllu = {.n = 960, .m = 13, .p = 0, .cpcon = 12, .lfcon = 2}, + .plldp = {.n = 83, .m = 1, .p = 3}, /* 269.8 MHz */ + }, + [OSC_FREQ_16P8]{ + .khz = 16800, + .pllx = {.n = TEGRA_PLLX_KHZ / 16800, .m = 1, .p = 0}, + .pllc = {.n = 71, .m = 1, .p = 1}, /* 596.4 MHz */ + .pllu = {.n = 400, .m = 7, .p = 0, .cpcon = 5, .lfcon = 2}, + .plldp = {.n = 64, .m = 1, .p = 3}, /* 268.8 MHz */ + }, + [OSC_FREQ_19P2]{ + .khz = 19200, + .pllx = {.n = TEGRA_PLLX_KHZ / 19200, .m = 1, .p = 0}, + .pllc = {.n = 62, .m = 1, .p = 1}, /* 595.2 MHz */ + .pllu = {.n = 200, .m = 4, .p = 0, .cpcon = 3, .lfcon = 2}, + .plldp = {.n = 56, .m = 1, .p = 3}, /* 268.8 MHz */ + }, + [OSC_FREQ_26]{ + .khz = 26000, + .pllx = {.n = TEGRA_PLLX_KHZ / 26000, .m = 1, .p = 0}, + .pllc = {.n = 23, .m = 1, .p = 0}, /* 598.0 MHz */ + .pllu = {.n = 960, .m = 26, .p = 0, .cpcon = 12, .lfcon = 2}, + .plldp = {.n = 83, .m = 2, .p = 3}, /* 269.8 MHz */ + }, + /* These oscillators get predivided as PLL inputs... n/m/p divisors for + * 38.4 should always match 19.2, and 48 should always match 12. */ + [OSC_FREQ_38P4]{ + .khz = 38400, + .pllx = {.n = TEGRA_PLLX_KHZ / 19200, .m = 1, .p = 0}, + .pllc = {.n = 62, .m = 1, .p = 1}, /* 595.2 MHz */ + .pllu = {.n = 200, .m = 4, .p = 0, .cpcon = 3, .lfcon = 2}, + .plldp = {.n = 56, .m = 1, .p = 3}, /* 268.8 MHz */ + }, + [OSC_FREQ_48]{ + .khz = 48000, + .pllx = {.n = TEGRA_PLLX_KHZ / 12000, .m = 1, .p = 0}, + .pllc = {.n = 50, .m = 1, .p = 0}, + .pllu = {.n = 960, .m = 12, .p = 0, .cpcon = 12, .lfcon = 2}, + .plldp = {.n = 90, .m = 1, .p = 3}, + }, +}; + +/* Get the oscillator frequency, from the corresponding hardware + * configuration field. This is actually a per-soc thing. Avoid the + * temptation to make it common. + */ +static u32 clock_get_osc_bits(void) +{ + return (readl(&clk_rst->osc_ctrl) & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT; +} + +int clock_get_osc_khz(void) +{ + return osc_table[clock_get_osc_bits()].khz; +} + +int clock_get_pll_input_khz(void) +{ + u32 osc_ctrl = readl(&clk_rst->osc_ctrl); + u32 osc_bits = (osc_ctrl & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT; + u32 pll_ref_div = (osc_ctrl & OSC_PREDIV_MASK) >> OSC_PREDIV_SHIFT; + return osc_table[osc_bits].khz >> pll_ref_div; +} + +void clock_init_arm_generic_timer(void) +{ + uint32_t freq = clock_get_osc_khz() * 1000; + // Set the cntfrq register. + __asm__ __volatile__("mcr p15, 0, %0, c14, c0, 0\n" :: "r"(freq)); + + // Record the system timer frequency. + write32(freq, &sysctr->cntfid0); + // Enable the system counter. + uint32_t cntcr = read32(&sysctr->cntcr); + cntcr |= SYSCTR_CNTCR_EN | SYSCTR_CNTCR_HDBG; + write32(cntcr, &sysctr->cntcr); +} + +#define SOR0_CLK_SEL0 (1 << 14) +#define SOR0_CLK_SEL1 (1 << 15) + +void sor_clock_stop(void) +{ + /* The Serial Output Resource clock has to be off + * before we start the plldp. Learned the hard way. + * FIXME: this has to be cleaned up a bit more. + * Waiting on some new info from Nvidia. + */ + clrbits_le32(&clk_rst->clk_src_sor, SOR0_CLK_SEL0 | SOR0_CLK_SEL1); +} + +void sor_clock_start(void) +{ + /* uses PLLP, has a non-standard bit layout. */ + setbits_le32(&clk_rst->clk_src_sor, SOR0_CLK_SEL0); +} + +static void init_pll(u32 *base, u32 *misc, const union pll_fields pll, u32 lock) +{ + u32 dividers = pll.div.n << PLL_BASE_DIVN_SHIFT | + pll.div.m << PLL_BASE_DIVM_SHIFT | + pll.div.p << PLL_BASE_DIVP_SHIFT; + u32 misc_con = pll.div.cpcon << PLL_MISC_CPCON_SHIFT | + pll.div.lfcon << PLL_MISC_LFCON_SHIFT; + + /* Write dividers but BYPASS the PLL while we're messing with it. */ + writel(dividers | PLL_BASE_BYPASS, base); + /* + * Set Lock bit, CPCON and LFCON fields (default to 0 if it doesn't + * exist for this PLL) + */ + writel(lock | misc_con, misc); + + /* Enable PLL and take it back out of BYPASS */ + writel(dividers | PLL_BASE_ENABLE, base); + + /* Wait for lock ready */ + while (!(readl(base) & PLL_BASE_LOCK)); +} + +static void init_utmip_pll(void) +{ + int khz = clock_get_pll_input_khz(); + + /* Shut off PLL crystal clock while we mess with it */ + clrbits_le32(&clk_rst->utmip_pll_cfg2, 1 << 30); /* PHY_XTAL_CLKEN */ + udelay(1); + + write32(80 << 16 | /* (rst) phy_divn */ + 1 << 8 | /* (rst) phy_divm */ + 0, &clk_rst->utmip_pll_cfg0); /* 960MHz * 1 / 80 == 12 MHz */ + + write32(div_round_up(khz, 8000) << 27 | /* pllu_enbl_cnt / 8 (1us) */ + 0 << 16 | /* PLLU pwrdn */ + 0 << 14 | /* pll_enable pwrdn */ + 0 << 12 | /* pll_active pwrdn */ + div_round_up(khz, 102) << 0 | /* phy_stbl_cnt / 256 (2.5ms) */ + 0, &clk_rst->utmip_pll_cfg1); + + /* TODO: TRM can't decide if actv is 5us or 10us, keep an eye on it */ + write32(0 << 24 | /* SAMP_D/XDEV pwrdn */ + div_round_up(khz, 3200) << 18 | /* phy_actv_cnt / 16 (5us) */ + div_round_up(khz, 256) << 6 | /* pllu_stbl_cnt / 256 (1ms) */ + 0 << 4 | /* SAMP_C/USB3 pwrdn */ + 0 << 2 | /* SAMP_B/XHOST pwrdn */ + 0 << 0 | /* SAMP_A/USBD pwrdn */ + 0, &clk_rst->utmip_pll_cfg2); + + setbits_le32(&clk_rst->utmip_pll_cfg2, 1 << 30); /* PHY_XTAL_CLKEN */ +} + +/* Graphics just has to be different. There's a few more bits we + * need to set in here, but it makes sense just to restrict all the + * special bits to this one function. + */ +static void graphics_pll(void) +{ + int osc = clock_get_osc_bits(); + u32 *cfg = &clk_rst->plldp_ss_cfg; + /* the vendor code sets the dither bit (28) + * an undocumented bit (24) + * and clamp while we mess with it (22) + * Dither is pretty important to display port + * so we really do need to handle these bits. + * I'm not willing to not clamp it, even if + * it might "mostly work" with it not set, + * I don't want to find out in a few months + * that it is needed. + */ + u32 scfg = (1<<28) | (1<<24) | (1<<22); + writel(scfg, cfg); + init_pll(&clk_rst->plldp_base, &clk_rst->plldp_misc, + osc_table[osc].plldp, PLLDPD2_MISC_LOCK_ENABLE); + /* leave dither and undoc bits set, release clamp */ + scfg = (1<<28) | (1<<24); + writel(scfg, cfg); + + /* disp1 will be set when panel information (pixel clock) is + * retrieved (clock_display). + */ +} + +/* Init PLLD clock source. */ +int +clock_display(u32 frequency) +{ + /** + * plld (fo) = vco >> p, where 500MHz < vco < 1000MHz + * = (cf * n) >> p, where 1MHz < cf < 6MHz + * = ((ref / m) * n) >> p + * + * Iterate the possible values of p (3 bits, 2^7) to find out a minimum + * safe vco, then find best (m, n). since m has only 5 bits, we can + * iterate all possible values. Note Tegra 124 supports 11 bits for n, + * but our pll_fields has only 10 bits for n. + * + * Note values undershoot or overshoot target output frequency may not + * work if the values are not in "safe" range by panel specification. + */ + struct pllpad_dividers plld = { 0 }; + u32 ref = clock_get_pll_input_khz() * 1000, m, n, p = 0; + u32 cf, vco; + u32 diff, best_diff; + const u32 max_m = 1 << 5, max_n = 1 << 10, max_p = 1 << 3, + mhz = 1000 * 1000, min_vco = 500 * mhz, max_vco = 1000 * mhz, + min_cf = 1 * mhz, max_cf = 6 * mhz; + + for (vco = frequency; vco < min_vco && p < max_p; p++) + vco <<= 1; + + if (vco < min_vco || vco > max_vco) { + printk(BIOS_ERR, "%s: Cannot find out a supported VCO" + " for Frequency (%u).\n", __func__, frequency); + return -1; + } + + plld.p = p; + best_diff = vco; + + for (m = 1; m < max_m && best_diff; m++) { + cf = ref / m; + if (cf < min_cf) + break; + if (cf > max_cf) + continue; + + n = vco / cf; + if (n >= max_n) + continue; + + diff = vco - n * cf; + if (n + 1 < max_n && diff > cf / 2) { + n++; + diff = cf - diff; + } + + if (diff >= best_diff) + continue; + + best_diff = diff; + plld.m = m; + plld.n = n; + } + + if (plld.n < 50) + plld.cpcon = 2; + else if (plld.n < 300) + plld.cpcon = 3; + else if (plld.n < 600) + plld.cpcon = 8; + else + plld.cpcon = 12; + + if (best_diff) { + printk(BIOS_ERR, "%s: Failed to match output frequency %u, " + "best difference is %u.\n", __func__, frequency, + best_diff); + } + + printk(BIOS_DEBUG, "%s: PLLD=%u ref=%u, m/n/p/cpcon=%u/%u/%u/%u\n", + __func__, (ref / plld.m * plld.n) >> plld.p, ref, plld.m, plld.n, + plld.p, plld.cpcon); + + init_pll(&clk_rst->plld_base, &clk_rst->plld_misc, plld, + (PLLUD_MISC_LOCK_ENABLE | PLLD_MISC_CLK_ENABLE)); + return 0; +} + +/* Initialize the UART and put it on CLK_M so we can use it during clock_init(). + * Will later move it to PLLP in clock_config(). The divisor must be very small + * to accomodate 12KHz OSCs, so we override the 16.0 UART divider with the 15.1 + * CLK_SOURCE divider to get more precision. (This might still not be enough for + * some OSCs... if you use 13KHz, be prepared to have a bad time.) The 1900 has + * been determined through trial and error (must lead to div 13 at 24MHz). */ +void clock_early_uart(void) +{ + write32(CLK_M << CLK_SOURCE_SHIFT | CLK_UART_DIV_OVERRIDE | + CLK_DIVIDER(TEGRA_CLK_M_KHZ, 1900), &clk_rst->clk_src_uarta); + setbits_le32(&clk_rst->clk_out_enb_l, CLK_L_UARTA); + udelay(2); + clrbits_le32(&clk_rst->rst_dev_l, CLK_L_UARTA); +} + +/* Enable output clock (CLK1~3) for external peripherals. */ +void clock_external_output(int clk_id) +{ + switch (clk_id) { + case 1: + setbits_le32(&pmc->clk_out_cntrl, 1 << 2); + break; + case 2: + setbits_le32(&pmc->clk_out_cntrl, 1 << 10); + break; + case 3: + setbits_le32(&pmc->clk_out_cntrl, 1 << 18); + break; + default: + printk(BIOS_CRIT, "ERROR: Unknown output clock id %d\n", + clk_id); + break; + } +} + +/* Start PLLM for SDRAM. */ +void clock_sdram(u32 m, u32 n, u32 p, u32 setup, u32 ph45, u32 ph90, + u32 ph135, u32 kvco, u32 kcp, u32 stable_time, u32 emc_source, + u32 same_freq) +{ + u32 misc1 = ((setup << PLLM_MISC1_SETUP_SHIFT) | + (ph45 << PLLM_MISC1_PD_LSHIFT_PH45_SHIFT) | + (ph90 << PLLM_MISC1_PD_LSHIFT_PH90_SHIFT) | + (ph135 << PLLM_MISC1_PD_LSHIFT_PH135_SHIFT)), + misc2 = ((kvco << PLLM_MISC2_KVCO_SHIFT) | + (kcp << PLLM_MISC2_KCP_SHIFT)), + base; + + if (same_freq) + emc_source |= CLK_SOURCE_EMC_MC_EMC_SAME_FREQ; + else + emc_source &= ~CLK_SOURCE_EMC_MC_EMC_SAME_FREQ; + + /* + * Note PLLM_BASE.PLLM_OUT1_RSTN must be in RESET_ENABLE mode, and + * PLLM_BASE.ENABLE must be in DISABLE state (both are the default + * values after coldboot reset). + */ + + writel(misc1, &clk_rst->pllm_misc1); + writel(misc2, &clk_rst->pllm_misc2); + + /* PLLM.BASE needs BYPASS=0, different from general init_pll */ + base = readl(&clk_rst->pllm_base); + base &= ~(PLLCMX_BASE_DIVN_MASK | PLLCMX_BASE_DIVM_MASK | + PLLM_BASE_DIVP_MASK | PLL_BASE_BYPASS); + base |= ((m << PLL_BASE_DIVM_SHIFT) | (n << PLL_BASE_DIVN_SHIFT) | + (p << PLL_BASE_DIVP_SHIFT)); + writel(base, &clk_rst->pllm_base); + + setbits_le32(&clk_rst->pllm_base, PLL_BASE_ENABLE); + /* stable_time is required, before we can start to check lock. */ + udelay(stable_time); + + while (!(readl(&clk_rst->pllm_base) & PLL_BASE_LOCK)) { + udelay(1); + } + /* + * After PLLM reports being locked, we have to delay 10us before + * enabling PLLM_OUT. + */ + udelay(10); + + /* Put OUT1 out of reset state (start to output). */ + setbits_le32(&clk_rst->pllm_out, PLLM_OUT1_RSTN_RESET_DISABLE); + + /* Enable and start MEM(MC) and EMC. */ + clock_enable_clear_reset(0, CLK_H_MEM | CLK_H_EMC, 0, 0, 0, 0); + writel(emc_source, &clk_rst->clk_src_emc); + udelay(IO_STABILIZATION_DELAY); +} + +void clock_cpu0_config_and_reset(void *entry) +{ + void * const evp_cpu_reset = (uint8_t *)TEGRA_EVP_BASE + 0x100; + + write32(CONFIG_STACK_TOP, &maincpu_stack_pointer); + write32((uintptr_t)entry, &maincpu_entry_point); + write32((uintptr_t)&maincpu_setup, evp_cpu_reset); + + /* Set active CPU cluster to G */ + clrbits_le32(&flow->cluster_control, 1); + + // 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->cclk_brst_pol); + write32(CRC_SUPER_CCLK_DIVIDER_SUPER_CDIV_ENB, + &clk_rst->super_cclk_div); + + // Enable the clocks for CPUs 0-3. + uint32_t cpu_cmplx_clr = read32(&clk_rst->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->clk_cpu_cmplx_clr); + + // Enable other CPU related clocks. + setbits_le32(&clk_rst->clk_out_enb_l, CLK_L_CPU); + setbits_le32(&clk_rst->clk_out_enb_v, CLK_V_CPUG); + setbits_le32(&clk_rst->clk_out_enb_v, CLK_V_CPULP); + + // Disable the reset on the non-CPU parts of the fast cluster. + write32(CRC_RST_CPUG_CLR_NONCPU, + &clk_rst->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->rst_cpug_cmplx_clr); + + // Disable the reset on the non-CPU parts of the slow cluster. + write32(CRC_RST_CPULP_CLR_NONCPU, + &clk_rst->rst_cpulp_cmplx_clr); + // Disable the various resets on the LP CPU. + write32(CRC_RST_CPULP_CLR_CPU0 | CRC_RST_CPULP_CLR_DBG0 | + CRC_RST_CPULP_CLR_CORE0 | CRC_RST_CPULP_CLR_CX0 | + CRC_RST_CPULP_CLR_L2 | CRC_RST_CPULP_CLR_PDBG, + &clk_rst->rst_cpulp_cmplx_clr); +} + +void clock_halt_avp(void) +{ + for (;;) { + write32(FLOW_EVENT_JTAG | FLOW_EVENT_LIC_IRQ | + FLOW_EVENT_GIC_IRQ | FLOW_MODE_WAITEVENT, + &flow->halt_cop_events); + } +} + +void clock_init(void) +{ + u32 osc = clock_get_osc_bits(); + + /* Set PLLC dynramp_step A to 0x2b and B to 0xb (from U-Boot -- why? */ + writel(0x2b << 17 | 0xb << 9, &clk_rst->pllc_misc2); + + /* Max out the AVP clock before everything else (need PLLC for that). */ + init_pll(&clk_rst->pllc_base, &clk_rst->pllc_misc, + osc_table[osc].pllc, PLLC_MISC_LOCK_ENABLE); + + /* Typical ratios are 1:2:2 or 1:2:3 sclk:hclk:pclk (See: APB DMA + * features section in the TRM). */ + write32(1 << HCLK_DIVISOR_SHIFT | 0 << PCLK_DIVISOR_SHIFT, + &clk_rst->clk_sys_rate); /* pclk = hclk = sclk/2 */ + write32(CLK_DIVIDER(TEGRA_PLLC_KHZ, 300000) << PLL_OUT_RATIO_SHIFT | + PLL_OUT_CLKEN | PLL_OUT_RSTN, &clk_rst->pllc_out); + write32(SCLK_SYS_STATE_RUN << SCLK_SYS_STATE_SHIFT | + SCLK_SOURCE_PLLC_OUT1 << SCLK_RUN_SHIFT, + &clk_rst->sclk_brst_pol); /* sclk = 300 MHz */ + + /* Change the oscillator drive strength (from U-Boot -- why?) */ + clrsetbits_le32(&clk_rst->osc_ctrl, OSC_XOFS_MASK, + OSC_DRIVE_STRENGTH << OSC_XOFS_SHIFT); + + /* + * Ambiguous quote from u-boot. TODO: what's this mean? + * "should update same value in PMC_OSC_EDPD_OVER XOFS + * field for warmboot " + */ + clrsetbits_le32(&pmc->osc_edpd_over, PMC_OSC_EDPD_OVER_XOFS_MASK, + OSC_DRIVE_STRENGTH << PMC_OSC_EDPD_OVER_XOFS_SHIFT); + + /* Disable IDDQ for PLLX before we set it up (from U-Boot -- why?) */ + clrbits_le32(&clk_rst->pllx_misc3, PLLX_IDDQ_MASK); + + /* Set up PLLP_OUT(1|2|3|4) divisor to generate (9.6|48|102|204)MHz */ + write32((CLK_DIVIDER(TEGRA_PLLP_KHZ, 9600) << PLL_OUT_RATIO_SHIFT | + PLL_OUT_OVR | PLL_OUT_CLKEN | PLL_OUT_RSTN) << PLL_OUT1_SHIFT | + (CLK_DIVIDER(TEGRA_PLLP_KHZ, 48000) << PLL_OUT_RATIO_SHIFT | + PLL_OUT_OVR | PLL_OUT_CLKEN | PLL_OUT_RSTN) << PLL_OUT2_SHIFT, + &clk_rst->pllp_outa); + write32((CLK_DIVIDER(TEGRA_PLLP_KHZ, 102000) << PLL_OUT_RATIO_SHIFT | + PLL_OUT_OVR | PLL_OUT_CLKEN | PLL_OUT_RSTN) << PLL_OUT3_SHIFT | + (CLK_DIVIDER(TEGRA_PLLP_KHZ, 204000) << PLL_OUT_RATIO_SHIFT | + PLL_OUT_OVR | PLL_OUT_CLKEN | PLL_OUT_RSTN) << PLL_OUT4_SHIFT, + &clk_rst->pllp_outb); + + /* init pllx */ + init_pll(&clk_rst->pllx_base, &clk_rst->pllx_misc, + osc_table[osc].pllx, PLLPAXS_MISC_LOCK_ENABLE); + + /* init pllu */ + init_pll(&clk_rst->pllu_base, &clk_rst->pllu_misc, + osc_table[osc].pllu, PLLUD_MISC_LOCK_ENABLE); + + init_utmip_pll(); + graphics_pll(); +} + +void clock_enable_clear_reset(u32 l, u32 h, u32 u, u32 v, u32 w, u32 x) +{ + if (l) writel(l, &clk_rst->clk_enb_l_set); + if (h) writel(h, &clk_rst->clk_enb_h_set); + if (u) writel(u, &clk_rst->clk_enb_u_set); + if (v) writel(v, &clk_rst->clk_enb_v_set); + if (w) writel(w, &clk_rst->clk_enb_w_set); + if (x) writel(x, &clk_rst->clk_enb_x_set); + + /* Give clocks time to stabilize. */ + udelay(IO_STABILIZATION_DELAY); + + if (l) writel(l, &clk_rst->rst_dev_l_clr); + if (h) writel(h, &clk_rst->rst_dev_h_clr); + if (u) writel(u, &clk_rst->rst_dev_u_clr); + if (v) writel(v, &clk_rst->rst_dev_v_clr); + if (w) writel(w, &clk_rst->rst_dev_w_clr); + if (x) writel(x, &clk_rst->rst_dev_x_clr); +} + +void clock_reset_l(u32 bit) +{ + writel(bit, &clk_rst->rst_dev_l_set); + udelay(1); + writel(bit, &clk_rst->rst_dev_l_clr); +} + +void clock_reset_h(u32 bit) +{ + writel(bit, &clk_rst->rst_dev_h_set); + udelay(1); + writel(bit, &clk_rst->rst_dev_h_clr); +} + +void clock_reset_u(u32 bit) +{ + writel(bit, &clk_rst->rst_dev_u_set); + udelay(1); + writel(bit, &clk_rst->rst_dev_u_clr); +} + +void clock_reset_v(u32 bit) +{ + writel(bit, &clk_rst->rst_dev_v_set); + udelay(1); + writel(bit, &clk_rst->rst_dev_v_clr); +} + +void clock_reset_w(u32 bit) +{ + writel(bit, &clk_rst->rst_dev_w_set); + udelay(1); + writel(bit, &clk_rst->rst_dev_w_clr); +} + +void clock_reset_x(u32 bit) +{ + writel(bit, &clk_rst->rst_dev_x_set); + udelay(1); + writel(bit, &clk_rst->rst_dev_x_clr); +} diff --git a/src/soc/nvidia/tegra132/flow.h b/src/soc/nvidia/tegra132/flow.h new file mode 100644 index 0000000000..01dbc14208 --- /dev/null +++ b/src/soc/nvidia/tegra132/flow.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved. + * + * 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 . + */ + +#ifndef _TEGRA132_FLOW_H_ +#define _TEGRA132_FLOW_H_ + +struct flow_ctlr { + u32 halt_cpu_events; /* offset 0x00 */ + u32 halt_cop_events; /* offset 0x04 */ + u32 cpu_csr; /* offset 0x08 */ + u32 cop_csr; /* offset 0x0c */ + u32 xrq_events; /* offset 0x10 */ + u32 halt_cpu1_events; /* offset 0x14 */ + u32 cpu1_csr; /* offset 0x18 */ + u32 halt_cpu2_events; /* offset 0x1c */ + u32 cpu2_csr; /* offset 0x20 */ + u32 halt_cpu3_events; /* offset 0x24 */ + u32 cpu3_csr; /* offset 0x28 */ + u32 cluster_control; /* offset 0x2c */ + u32 halt_cop1_events; /* offset 0x30 */ + u32 halt_cop1_csr; /* offset 0x34 */ + u32 cpu_pwr_csr; /* offset 0x38 */ + u32 mpid; /* offset 0x3c */ + u32 ram_repair; /* offset 0x40 */ +}; +check_member(flow_ctlr, ram_repair, 0x40); + +enum { + FLOW_MODE_SHIFT = 29, + FLOW_MODE_MASK = 0x7 << FLOW_MODE_SHIFT, + + FLOW_MODE_NONE = 0 << FLOW_MODE_SHIFT, + FLOW_MODE_RUN_AND_INT = 1 << FLOW_MODE_SHIFT, + FLOW_MODE_WAITEVENT = 2 << FLOW_MODE_SHIFT, + FLOW_MODE_WAITEVENT_AND_INT = 3 << FLOW_MODE_SHIFT, + FLOW_MODE_STOP_UNTIL_IRQ = 4 << FLOW_MODE_SHIFT, + FLOW_MODE_STOP_UNTIL_IRQ_AND_INT = 5 << FLOW_MODE_SHIFT, + FLOW_MODE_STOP_UNTIL_EVENT_AND_IRQ = 6 << FLOW_MODE_SHIFT, +}; + +/* HALT_COP_EVENTS_0, 0x04 */ +enum { + FLOW_EVENT_GIC_FIQ = 1 << 8, + FLOW_EVENT_GIC_IRQ = 1 << 9, + FLOW_EVENT_LIC_FIQ = 1 << 10, + FLOW_EVENT_LIC_IRQ = 1 << 11, + FLOW_EVENT_IBF = 1 << 12, + FLOW_EVENT_IBE = 1 << 13, + FLOW_EVENT_OBF = 1 << 14, + FLOW_EVENT_OBE = 1 << 15, + FLOW_EVENT_XRQ_A = 1 << 16, + FLOW_EVENT_XRQ_B = 1 << 17, + FLOW_EVENT_XRQ_C = 1 << 18, + FLOW_EVENT_XRQ_D = 1 << 19, + FLOW_EVENT_SMP30 = 1 << 20, + FLOW_EVENT_SMP31 = 1 << 21, + FLOW_EVENT_X_RDY = 1 << 22, + FLOW_EVENT_SEC = 1 << 23, + FLOW_EVENT_MSEC = 1 << 24, + FLOW_EVENT_USEC = 1 << 25, + FLOW_EVENT_X32K = 1 << 26, + FLOW_EVENT_SCLK = 1 << 27, + FLOW_EVENT_JTAG = 1 << 28 +}; + +#endif /* _TEGRA132_FLOW_H_ */ diff --git a/src/soc/nvidia/tegra132/include/soc/clock.h b/src/soc/nvidia/tegra132/include/soc/clock.h index 5fc10c3ca4..6f69fefbc6 100644 --- a/src/soc/nvidia/tegra132/include/soc/clock.h +++ b/src/soc/nvidia/tegra132/include/soc/clock.h @@ -18,7 +18,12 @@ #ifndef __SOC_NVIDIA_TEGRA132_CLOCK_H__ #define __SOC_NVIDIA_TEGRA132_CLOCK_H__ +#include +#include +#include +#include #include +#include enum { CLK_L_CPU = 0x1 << 0, @@ -174,6 +179,7 @@ enum { #define CLOCK_PLL_STABLE_DELAY_US 300 #define IO_STABILIZATION_DELAY (2) + /* Calculate clock fractional divider value from ref and target frequencies. * This is for a U7.1 format. This is not well written up in the book and * there have been some questions about this macro, so here we go. @@ -195,7 +201,7 @@ enum { * and voila, upper 7 bits are (ref/freq-1), and lowest bit is h. Since you * will assign this to a u8, it gets nicely truncated for you. */ -#define CLK_DIVIDER(REF, FREQ) ((((REF) * 2) / (FREQ)) - 2) +#define CLK_DIVIDER(REF, FREQ) (div_round_up(((REF) * 2), (FREQ)) - 2) /* Calculate clock frequency value from reference and clock divider value * The discussion in the book is pretty lacking. @@ -216,11 +222,23 @@ enum { */ #define CLK_FREQUENCY(REF, REG) (((REF) * 2) / ((REG) + 2)) +static inline void _clock_set_div(u32 *reg, const char *name, u32 div, + u32 div_mask, u32 src) +{ + // The I2C and UART divisors are 16 bit while all the others are 8 bit. + // The I2C clocks are handled by the specialized macro below, but the + // UART clocks aren't. Don't use this function on UART clocks. + if (div & ~div_mask) { + printk(BIOS_ERR, "%s clock divisor overflow!", name); + hlt(); + } + clrsetbits_le32(reg, CLK_SOURCE_MASK | CLK_DIVISOR_MASK, + src << CLK_SOURCE_SHIFT | div); +} + #define clock_configure_irregular_source(device, src, freq, src_id) \ - clrsetbits_le32(&clk_rst->clk_src_##device, \ - CLK_SOURCE_MASK | CLK_DIVISOR_MASK, \ - src_id << CLK_SOURCE_SHIFT | \ - CLK_DIVIDER(TEGRA_##src##_KHZ, freq)) + _clock_set_div(&clk_rst->clk_src_##device, #device, \ + CLK_DIVIDER(TEGRA_##src##_KHZ, freq), 0xff, src_id) /* Warning: Some devices just use different bits for the same sources for no * apparent reason. *Always* double-check the TRM before trusting this macro. */ @@ -232,11 +250,12 @@ enum { * We can deal with those here and make it easier to select what the actual * bus frequency will be. The 0x19 value is the default divisor in the * clk_divisor register in the controller, and 8 is just a magic number in the - * documentation. Multiplying by 2 compensates for the different format of the - * divisor. + * documentation. */ #define clock_configure_i2c_scl_freq(device, src, freq) \ - clock_configure_source(device, src, (freq) * (0x19 + 1) * 8 * 2) + _clock_set_div(&clk_rst->clk_src_##device, #device, \ + div_round_up(TEGRA_##src##_KHZ, (freq) * (0x19 + 1) * 8) - 1, \ + 0xffff, src) enum clock_source { /* Careful: Not true for all sources, always check TRM! */ PLLP = 0, @@ -259,6 +278,8 @@ enum clock_source { /* Careful: Not true for all sources, always check TRM! */ #define TEGRA_PLLU_KHZ (960000) int clock_get_osc_khz(void); +int clock_get_pll_input_khz(void); +int clock_display(u32 frequency); void clock_early_uart(void); void clock_external_output(int clk_id); void clock_sdram(u32 m, u32 n, u32 p, u32 setup, u32 ph45, u32 ph90, @@ -267,6 +288,12 @@ void clock_sdram(u32 m, u32 n, u32 p, u32 setup, u32 ph45, u32 ph90, void clock_cpu0_config_and_reset(void * entry); void clock_halt_avp(void); void clock_enable_clear_reset(u32 l, u32 h, u32 u, u32 v, u32 w, u32 x); +void clock_reset_l(u32 l); +void clock_reset_h(u32 h); +void clock_reset_u(u32 u); +void clock_reset_v(u32 v); +void clock_reset_w(u32 w); +void clock_reset_x(u32 x); void clock_init(void); void clock_init_arm_generic_timer(void); void sor_clock_stop(void); diff --git a/src/soc/nvidia/tegra132/maincpu.S b/src/soc/nvidia/tegra132/maincpu.S new file mode 100644 index 0000000000..898d821d7e --- /dev/null +++ b/src/soc/nvidia/tegra132/maincpu.S @@ -0,0 +1,55 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +ENTRY(maincpu_setup) + /* + * Set the cpu to System mode with IRQ and FIQ disabled. Prefetch/Data + * aborts may happen early and crash before the abort handlers are + * installed, but at least the problem will show up near the code that + * causes it. + */ + msr cpsr, #0xdf + + ldr sp, maincpu_stack_pointer + eor lr, lr + ldr r0, maincpu_entry_point + bx r0 +ENDPROC(maincpu_setup) + + .align 2 + + .global maincpu_stack_pointer +maincpu_stack_pointer: + .word 0 + + .global maincpu_entry_point +maincpu_entry_point: + .word 0 diff --git a/src/soc/nvidia/tegra132/maincpu.h b/src/soc/nvidia/tegra132/maincpu.h new file mode 100644 index 0000000000..1f795dfc66 --- /dev/null +++ b/src/soc/nvidia/tegra132/maincpu.h @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 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_TEGRA132_MAINCPU_H__ +#define __SOC_NVIDIA_TEGRA132_MAINCPU_H__ + +#include + +extern u32 maincpu_stack_pointer; +extern u32 maincpu_entry_point; +void maincpu_setup(void); + +#endif /* __SOC_NVIDIA_TEGRA132_MAINCPU_H__ */ diff --git a/src/soc/nvidia/tegra132/pinmux.h b/src/soc/nvidia/tegra132/pinmux.h new file mode 100644 index 0000000000..2bed25381a --- /dev/null +++ b/src/soc/nvidia/tegra132/pinmux.h @@ -0,0 +1,260 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 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_TEGRA132_PINMUX_H__ +#define __SOC_NVIDIA_TEGRA132_PINMUX_H__ + +#include +#include + +#define PINMUX_CONSTANTS(index, name, gpio, func0, func1, func2, func3) \ + PINMUX_##name##_INDEX = index, \ + PINMUX_##name##_FUNC_##func0 = 0, \ + PINMUX_##name##_FUNC_##func1 = 1, \ + PINMUX_##name##_FUNC_##func2 = 2, \ + PINMUX_##name##_FUNC_##func3 = 3, \ + PINMUX_GPIO_##gpio = PINMUX_##name##_INDEX + +enum { + PINMUX_CONSTANTS(0, ULPI_DATA0, O1, SPI3, HSI, UA3, ULPI), + PINMUX_CONSTANTS(1, ULPI_DATA1, O2, SPI3, HSI, UA3, ULPI), + PINMUX_CONSTANTS(2, ULPI_DATA2, O3, SPI3, HSI, UA3, ULPI), + PINMUX_CONSTANTS(3, ULPI_DATA3, O4, SPI3, HSI, UA3, ULPI), + PINMUX_CONSTANTS(4, ULPI_DATA4, O5, SPI2, HSI, UA3, ULPI), + PINMUX_CONSTANTS(5, ULPI_DATA5, O6, SPI2, HSI, UA3, ULPI), + PINMUX_CONSTANTS(6, ULPI_DATA6, O7, SPI2, HSI, UA3, ULPI), + PINMUX_CONSTANTS(7, ULPI_DATA7, O0, SPI2, HSI, UA3, ULPI), + PINMUX_CONSTANTS(8, ULPI_CLK, Y0, SPI1, SPI5, UD3, ULPI), + PINMUX_CONSTANTS(9, ULPI_DIR, Y1, SPI1, SPI5, UD3, ULPI), + PINMUX_CONSTANTS(10, ULPI_NXT, Y2, SPI1, SPI5, UD3, ULPI), + PINMUX_CONSTANTS(11, ULPI_STP, Y3, SPI1, SPI5, UD3, ULPI), + PINMUX_CONSTANTS(12, DAP3_FS, P0, I2S2, SPI5, DCA, DCB), + PINMUX_CONSTANTS(13, DAP3_DIN, P1, I2S2, SPI5, DCA, DCB), + PINMUX_CONSTANTS(14, DAP3_DOUT, P2, I2S2, SPI5, DCA, RES3), + PINMUX_CONSTANTS(15, DAP3_SCLK, P3, I2S2, SPI5, RES2, DCB), + PINMUX_CONSTANTS(16, GPIO_PV0, V0, RES0, RES1, RES2, RES3), + PINMUX_CONSTANTS(17, GPIO_PV1, V1, RES0, RES1, RES2, RES3), + PINMUX_CONSTANTS(18, SDMMC1_CLK, Z0, SDMMC1, CLK12M, RES2, RES3), + PINMUX_CONSTANTS(19, SDMMC1_CMD, Z1, SDMMC1, SPDIF, SPI4, UA3), + PINMUX_CONSTANTS(20, SDMMC1_DAT3, Y4, SDMMC1, SPDIF, SPI4, UA3), + PINMUX_CONSTANTS(21, SDMMC1_DAT2, Y5, SDMMC1, PWM0, SPI4, UA3), + PINMUX_CONSTANTS(22, SDMMC1_DAT1, Y6, SDMMC1, PWM1, SPI4, UA3), + PINMUX_CONSTANTS(23, SDMMC1_DAT0, Y7, SDMMC1, RES1, SPI4, UA3), + PINMUX_CONSTANTS(26, CLK2_OUT, W5, EXTPERIPH2, RES1, RES2, RES3), + PINMUX_CONSTANTS(27, CLK2_REQ, CC5, DAP, RES1, RES2, RES3), + PINMUX_CONSTANTS(68, HDMI_INT, N7, RES0, RES1, RES2, RES3), + PINMUX_CONSTANTS(69, DDC_SCL, V4, I2C4, RES1, RES2, RES3), + PINMUX_CONSTANTS(70, DDC_SDA, V5, I2C4, RES1, RES2, RES3), + PINMUX_CONSTANTS(89, UART2_RXD, C3, IR3, SPDIF, UA3, SPI4), + PINMUX_CONSTANTS(90, UART2_TXD, C2, IR3, SPDIF, UA3, SPI4), + PINMUX_CONSTANTS(91, UART2_RTS_N, J6, UA3, UB3, NOR, SPI4), + PINMUX_CONSTANTS(92, UART2_CTS_N, J5, UA3, UB3, NOR, SPI4), + PINMUX_CONSTANTS(93, UART3_TXD, W6, UC3, RES1, NOR, SPI4), + PINMUX_CONSTANTS(94, UART3_RXD, W7, UC3, RES1, NOR, SPI4), + PINMUX_CONSTANTS(95, UART3_CTS_N, A1, UC3, SDMMC1, DTV, NOR), + PINMUX_CONSTANTS(96, UART3_RTS_N, C0, UC3, PWM0, DTV, NOR), + PINMUX_CONSTANTS(97, GPIO_PU0, U0, OWR, UA3, NOR, RES3), + PINMUX_CONSTANTS(98, GPIO_PU1, U1, RES0, UA3, NOR, RES3), + PINMUX_CONSTANTS(99, GPIO_PU2, U2, RES0, UA3, NOR, RES3), + PINMUX_CONSTANTS(100, GPIO_PU3, U3, PWM0, UA3, NOR, DCB), + PINMUX_CONSTANTS(101, GPIO_PU4, U4, PWM1, UA3, NOR, DCB), + PINMUX_CONSTANTS(102, GPIO_PU5, U5, PWM2, UA3, NOR, DCB), + PINMUX_CONSTANTS(103, GPIO_PU6, U6, PWM3, UA3, RES2, NOR), + PINMUX_CONSTANTS(104, GEN1_I2C_SDA, C5, I2C1, RES1, RES2, RES3), + PINMUX_CONSTANTS(105, GEN1_I2C_SCL, C4, I2C1, RES1, RES2, RES3), + PINMUX_CONSTANTS(106, DAP4_FS, P4, I2S3, NOR, DTV, RES3), + PINMUX_CONSTANTS(107, DAP4_DIN, P5, I2S3, NOR, RES2, RES3), + PINMUX_CONSTANTS(108, DAP4_DOUT, P6, I2S3, NOR, DTV, RES3), + PINMUX_CONSTANTS(109, DAP4_SCLK, P7, I2S3, NOR, RES2, RES3), + PINMUX_CONSTANTS(110, CLK3_OUT, EE0, EXTPERIPH3, RES1, RES2, RES3), + PINMUX_CONSTANTS(111, CLK3_REQ, EE1, DEV3, RES1, RES2, RES3), + PINMUX_CONSTANTS(112, GPIO_PC7, C7, RES0, RES1, NOR_WP_N, NOR_INT1), + PINMUX_CONSTANTS(113, GPIO_PI5, I5, SDMMC2, RES1, NOR, RES3), + PINMUX_CONSTANTS(114, GPIO_PI7, I7, RES0, TRACE, NOR, DTV), + PINMUX_CONSTANTS(115, GPIO_PK0, K0, RES0, SDMMC3, NOR, SOC_THERM), + PINMUX_CONSTANTS(116, GPIO_PK1, K1, SDMMC2, TRACE, NOR, RES3), + PINMUX_CONSTANTS(117, GPIO_PJ0, J0, RES0, RES1, NOR, USB), + PINMUX_CONSTANTS(118, GPIO_PJ2, J2, RES0, RES1, NOR, SOC_THERM), + PINMUX_CONSTANTS(119, GPIO_PK3, K3, SDMMC2, TRACE, NOR, CCLA), + PINMUX_CONSTANTS(120, GPIO_PK4, K4, SDMMC2, RES1, NOR_AD22, NOR_INT1), + PINMUX_CONSTANTS(121, GPIO_PK2, K2, RES0, RES1, NOR, RES3), + PINMUX_CONSTANTS(122, GPIO_PI3, I3, RES0, RES1, NOR, SPI4), + PINMUX_CONSTANTS(123, GPIO_PI6, I6, RES0, RES1, NOR, SDMMC2), + PINMUX_CONSTANTS(124, GPIO_PG0, G0, RES0, RES1, NOR, RES3), + PINMUX_CONSTANTS(125, GPIO_PG1, G1, RES0, RES1, NOR, RES3), + PINMUX_CONSTANTS(126, GPIO_PG2, G2, RES0, TRACE, NOR, RES3), + PINMUX_CONSTANTS(127, GPIO_PG3, G3, RES0, TRACE, NOR, RES3), + PINMUX_CONSTANTS(128, GPIO_PG4, G4, RES0, TMDS, NOR, SPI4), + PINMUX_CONSTANTS(129, GPIO_PG5, G5, RES0, RES1, NOR, SPI4), + PINMUX_CONSTANTS(130, GPIO_PG6, G6, RES0, RES1, NOR, SPI4), + PINMUX_CONSTANTS(131, GPIO_PG7, G7, RES0, RES1, NOR, SPI4), + PINMUX_CONSTANTS(132, GPIO_PH0, H0, PWM0, TRACE, NOR, DTV), + PINMUX_CONSTANTS(133, GPIO_PH1, H1, PWM1, TMDS, NOR, DCA), + PINMUX_CONSTANTS(134, GPIO_PH2, H2, PWM2, TDMS, NOR, CLDVFS), + PINMUX_CONSTANTS(135, GPIO_PH3, H3, PWM3, SPI4, NOR, CLDVFS), + PINMUX_CONSTANTS(136, GPIO_PH4, H4, SDMMC2, RES1, NOR, RES3), + PINMUX_CONSTANTS(137, GPIO_PH5, H5, SDMMC2, RES1, NOR, RES3), + PINMUX_CONSTANTS(138, GPIO_PH6, H6, SDMMC2, TRACE, NOR, DTV), + PINMUX_CONSTANTS(139, GPIO_PH7, H7, SDMMC2, TRACE, NOR, DTV), + PINMUX_CONSTANTS(140, GPIO_PJ7, J7, UD3, RES1, NOR_AD16, NOR_INT2), + PINMUX_CONSTANTS(141, GPIO_PB0, B0, UD3, RES1, NOR, RES3), + PINMUX_CONSTANTS(142, GPIO_PB1, B1, UD3, RES1, NOR, RES3), + PINMUX_CONSTANTS(143, GPIO_PK7, K7, UD3, RES1, NOR, RES3), + PINMUX_CONSTANTS(144, GPIO_PI0, I0, RES0, RES1, NOR, RES3), + PINMUX_CONSTANTS(145, GPIO_PI1, I1, RES0, RES1, NOR, RES3), + PINMUX_CONSTANTS(146, GPIO_PI2, I2, SDMMC2, TRACE, NOR, RES3), + PINMUX_CONSTANTS(147, GPIO_PI4, I4, SPI4, TRACE, NOR, DCA), + PINMUX_CONSTANTS(148, GEN2_I2C_SCL, T5, I2C2, RES1, NOR, RES3), + PINMUX_CONSTANTS(149, GEN2_I2C_SDA, T6, I2C2, RES1, NOR, RES3), + PINMUX_CONSTANTS(150, SDMMC4_CLK, CC4, SDMMC4, RES1, NOR, RES3), + PINMUX_CONSTANTS(151, SDMMC4_CMD, T7, SDMMC4, RES1, NOR, RES3), + PINMUX_CONSTANTS(152, SDMMC4_DAT0, AA0, SDMMC4, SPI3, NOR, RES3), + PINMUX_CONSTANTS(153, SDMMC4_DAT1, AA1, SDMMC4, SPI3, NOR, RES3), + PINMUX_CONSTANTS(154, SDMMC4_DAT2, AA2, SDMMC4, SPI3, NOR, RES3), + PINMUX_CONSTANTS(155, SDMMC4_DAT3, AA3, SDMMC4, SPI3, NOR, RES3), + PINMUX_CONSTANTS(156, SDMMC4_DAT4, AA4, SDMMC4, SPI3, NOR, RES3), + PINMUX_CONSTANTS(157, SDMMC4_DAT5, AA5, SDMMC4, SPI3, RES2, RES3), + PINMUX_CONSTANTS(158, SDMMC4_DAT6, AA6, SDMMC4, SPI3, NOR, RES3), + PINMUX_CONSTANTS(159, SDMMC4_DAT7, AA7, SDMMC4, RES1, NOR, RES3), + PINMUX_CONSTANTS(161, CAM_MCLK, CC0, VIMCLK_PRI, VIMCLK_ALT1, + VIMCLK_ALT3, SDMMC2), + PINMUX_CONSTANTS(162, GPIO_PCC1, CC1, I2S4, RES1, RES2, SDMMC2), + PINMUX_CONSTANTS(163, GPIO_PBB0, BB0, VGP6, VIMCLK2_PRI, SDMMC2, + VIMCLK2_ALT3), + PINMUX_CONSTANTS(164, CAM_I2C_SCL, BB1, VGP1, I2C3, RES2, SDMMC2), + PINMUX_CONSTANTS(165, CAM_I2C_SDA, BB2, VGP2, I2C3, RES2, SDMMC2), + PINMUX_CONSTANTS(166, GPIO_PBB3, BB3, VGP3, DCA, DCB, SDMMC2), + PINMUX_CONSTANTS(167, GPIO_PBB4, BB4, VGP4, DCA, DCB, SDMMC2), + PINMUX_CONSTANTS(168, GPIO_PBB5, BB5, VGP5, DCA, RES2, SDMMC2), + PINMUX_CONSTANTS(169, GPIO_PBB6, BB6, I2S4, RES1, DCB, SDMMC2), + PINMUX_CONSTANTS(170, GPIO_PBB7, BB7, I2S4, RES1, RES2, SDMMC2), + PINMUX_CONSTANTS(171, GPIO_PCC2, CC2, I2S4, RES1, SDMMC3, SDMMC2), + PINMUX_CONSTANTS(172, JTAG_RTCK, NONE172, RTCK, RES1, RES2, RES3), + PINMUX_CONSTANTS(173, PWR_I2C_SCL, Z6, I2CPMU, RES1, RES2, RES3), + PINMUX_CONSTANTS(174, PWR_I2C_SDA, Z7, I2CPMU, RES1, RES2, RES3), + PINMUX_CONSTANTS(175, KB_ROW0, R0, RES0, RES1, RES2, RES3), + PINMUX_CONSTANTS(176, KB_ROW1, R1, RES0, RES1, RES2, RES3), + PINMUX_CONSTANTS(177, KB_ROW2, R2, RES0, RES1, RES2, RES3), + PINMUX_CONSTANTS(178, KB_ROW3, R3, RES0, DCA, SYS_CLK, DCB), + PINMUX_CONSTANTS(179, KB_ROW4, R4, RES0, DCA, RES2, DCB), + PINMUX_CONSTANTS(180, KB_ROW5, R5, RES0, DCA, RES2, DCB), + PINMUX_CONSTANTS(181, KB_ROW6, R6, RES0, DCA_LSC0, DCA_LSPII, DCB), + PINMUX_CONSTANTS(182, KB_ROW7, R7, RES0, RES1, CLDVFS, UA3), + PINMUX_CONSTANTS(183, KB_ROW8, S0, RES0, RES1, CLDVFS, UA3), + PINMUX_CONSTANTS(184, KB_ROW9, S1, RES0, RES1, RES2, UA3), + PINMUX_CONSTANTS(185, KB_ROW10, S2, RES0, RES1, RES2, UA3), + PINMUX_CONSTANTS(186, KB_ROW11, S3, RES0, RES1, RES2, IR3), + PINMUX_CONSTANTS(187, KB_ROW12, S4, RES0, RES1, RES2, IR3), + PINMUX_CONSTANTS(188, KB_ROW13, S5, RES0, RES1, SPI2, RES3), + PINMUX_CONSTANTS(189, KB_ROW14, S6, RES0, RES1, SPI2, RES3), + PINMUX_CONSTANTS(190, KB_ROW15, S7, RES0, SOC_THERM, RES2, RES3), + PINMUX_CONSTANTS(191, KB_COL0, Q0, RES0, RES1, SPI2, RES3), + PINMUX_CONSTANTS(192, KB_COL1, Q1, RES0, RES1, SPI2, RES3), + PINMUX_CONSTANTS(193, KB_COL2, Q2, RES0, RES1, SPI2, RES3), + PINMUX_CONSTANTS(194, KB_COL3, Q3, RES0, DCA, PWM2, UA3), + PINMUX_CONSTANTS(195, KB_COL4, Q4, RES0, OWR, SDMMC3, UA3), + PINMUX_CONSTANTS(196, KB_COL5, Q5, RES0, RES1, SDMMC3, RES3), + PINMUX_CONSTANTS(197, KB_COL6, Q6, RES0, RES1, SPI2, UD3), + PINMUX_CONSTANTS(198, KB_COL7, Q7, RES0, RES1, SPI2, UD3), + PINMUX_CONSTANTS(199, CLK_32K_OUT, A0, BLINK, SOC_THERM, RES2, RES3), + PINMUX_CONSTANTS(201, CORE_PWR_REQ, NONE201, PWRON, RES1, RES2, RES3), + PINMUX_CONSTANTS(202, CPU_PWR_REQ, NONE202, CPU, RES1, RES2, RES3), + PINMUX_CONSTANTS(203, PWR_INT_N, NONE203, PMICINTR, RES1, RES2, RES3), + PINMUX_CONSTANTS(204, CLK_32K_IN, NONE204, CLK_32K_IN, RES1, RES2, + RES3), + PINMUX_CONSTANTS(205, OWR, NONE205, OWR, RES1, RES2, RES3), + PINMUX_CONSTANTS(206, DAP1_FS, N0, I2S0, DAP1, NOR, RES3), + PINMUX_CONSTANTS(207, DAP1_DIN, N1, I2S0, DAP1, NOR, RES3), + PINMUX_CONSTANTS(208, DAP1_DOUT, N2, I2S0, DAP1, NOR, SATA), + PINMUX_CONSTANTS(209, DAP1_SCLK, N3, I2S0, DAP1, NOR, RES3), + PINMUX_CONSTANTS(210, DAP_MCLK1_REQ, EE2, DAP, DAP1, SATA, RES3), + PINMUX_CONSTANTS(211, DAP_MCLK1, W4, EXTPERIPH1, DAP2, RES2, RES3), + PINMUX_CONSTANTS(212, SPDIF_IN, K6, SPDIF, RES1, RES2, I2C3), + PINMUX_CONSTANTS(213, SPDIF_OUT, K5, SPDIF, RES1, RES2, I2C3), + PINMUX_CONSTANTS(214, DAP2_FS, A2, I2S1, DAP2, NOR, RES3), + PINMUX_CONSTANTS(215, DAP2_DIN, A4, I2S1, DAP2, NOR, RES3), + PINMUX_CONSTANTS(216, DAP2_DOUT, A5, I2S1, DAP2, NOR, RES3), + PINMUX_CONSTANTS(217, DAP2_SCLK, A3, I2S1, SAP2, NOR, RES3), + PINMUX_CONSTANTS(218, DVFS_PWM, X0, SPI6, CLDVFS, NOR, RES3), + PINMUX_CONSTANTS(219, GPIO_X1_AUD, X1, SPI6, RES1, NOR, RES3), + PINMUX_CONSTANTS(220, GPIO_X3_AUD, X3, SPI6, SPI1, NOR, RES3), + PINMUX_CONSTANTS(221, DVFS_CLK, X2, SPI6, CLDVFS_CLK, NOR, RES3), + PINMUX_CONSTANTS(222, GPIO_X4_AUD, X4, NOR, SPI1, SPI2, DAP2), + PINMUX_CONSTANTS(223, GPIO_X5_AUD, X5, NOR, SPI1, SPI2, RES3), + PINMUX_CONSTANTS(224, GPIO_X6_AUD, X6, SPI6, SPI1, SPI2, NOR), + PINMUX_CONSTANTS(225, GPIO_X7_AUD, X7, RES0, SPI1, SPI2, RES3), + PINMUX_CONSTANTS(228, SDMMC3_CLK, A6, SDMMC3, RES1, RES2, SPI3), + PINMUX_CONSTANTS(229, SDMMC3_CMD, A7, SDMMC3, PWM3, UA3, SPI3), + PINMUX_CONSTANTS(230, SDMMC3_DAT0, B7, SDMMC3, RES1, RES2, SPI3), + PINMUX_CONSTANTS(231, SDMMC3_DAT1, B6, SDMMC3, PWM2, UA3, SPI3), + PINMUX_CONSTANTS(232, SDMMC3_DAT2, B5, SDMMC3, PWM1, DCA, SPI3), + PINMUX_CONSTANTS(233, SDMMC3_DAT3, B4, SDMMC3, PWM0, DCB, SPI3), + PINMUX_CONSTANTS(239, PEX_L0_RST_N, DD1, PE0, RES1, RES2, RES3), + PINMUX_CONSTANTS(240, PEX_L0_CLKREQ_N, DD2, PE0, RES1, RES2, RES3), + PINMUX_CONSTANTS(241, PEX_WAKE_N, DD3, PE, RES1, RES2, RES3), + PINMUX_CONSTANTS(243, PEX_L1_RST_N, DD5, PE1, RES1, RES2, RES3), + PINMUX_CONSTANTS(244, PEX_L1_CLKREQ_N, DD6, PE1, RES1, RES2, RES3), + PINMUX_CONSTANTS(248, HDMI_CEC, EE3, CEC, RES1, RES2, RES3), + PINMUX_CONSTANTS(249, SDMMC1_WP_N, V3, SDMMC1, CLK12M, SPI4, UA3), + PINMUX_CONSTANTS(250, SDMMC3_CD_N, V2, SDMMC3, OWR, RES2, RES3), + PINMUX_CONSTANTS(251, GPIO_W2_AUD, W2, SPI6, RES1, SPI2, I2C1), + PINMUX_CONSTANTS(252, GPIO_W3_AUD, W3, SPI6, SPI1, SPI2, I2C1), + PINMUX_CONSTANTS(253, USB_VBUS_EN0, N4, USB, RES1, RES2, RES3), + PINMUX_CONSTANTS(254, USB_VBUS_EN1, N5, USB, RES1, RES2, RES3), + PINMUX_CONSTANTS(255, SDMMC3_CLK_LB_IN, EE5, SDMMC3, RES1, RES2, RES3), + PINMUX_CONSTANTS(256, SDMMC3_CLK_LB_OUT, EE4, SDMMC3, RES1, RES2, RES3), + PINMUX_CONSTANTS(258, RESET_OUT_N, NONE258, RES0, RES1, RES2, RESET), + PINMUX_CONSTANTS(259, KB_ROW16, T0, RES0, RES1, RES2, UC3), + PINMUX_CONSTANTS(260, KB_ROW17, T1, RES0, RES1, RES2, UC3), + PINMUX_CONSTANTS(261, USB_VBUS_EN2, FF1, USB, RES1, RES2, RES3), + PINMUX_CONSTANTS(262, GPIO_PFF2, FF2, SATA, RES1, RES2, RES3), + PINMUX_CONSTANTS(268, DP_HPD, FF0, DP, RES1, RES2, RES3), + + // Where do these go? + /* + PINMUX_JTAG_TRST_N_JTAG_TRST_N = 0, + + PINMUX_JTAG_TDO_JTAG_TDO = 0, + + PINMUX_JTAG_TMS_JTAG_TMS = 0, + + PINMUX_JTAG_TCK_JTAG_TCK = 0, + // What do functions 1 and 2 do? + + PINMUX_JTAG_TDI_JTAG_TDI = 0, + PINMUX_JTAG_TDI_PWR_BREAK = 1, + + PINMUX_TEST_MODE_EN_TEST_MODE_EN = 0, + PINMUX_TEST_MODE_EN_VIMCLK_PRI = 1, + PINMUX_TEST_MODE_EN_VIMCLK_ALT1 = 2, + PINMUX_TEST_MODE_EN_VIMCLK_ALT3 = 3, + + PINMUX_DP_AUX_CH0_P_I2C_CLK = 0, + PINMUX_DP_AUX_CH0_P_SDMMC3_DAT3 = 1, + PINMUX_DP_AUX_CH0_P_PM3_PWM0 = 2, + PINMUX_DP_AUX_CH0_P_DCB_LPM0 = 3, + + PINMUX_DP_AUX_CH0_N_I2C6_DAT = 0, + PINMUX_DP_AUX_CH0_N_SDMMC3_DAT2 = 1, + PINMUX_DP_AUX_CH0_N_PM3_PWM1 = 2, + PINMUX_DP_AUX_CH0_N_DCA_LPM0 = 3, + */ +}; + +#endif /* __SOC_NVIDIA_TEGRA132_PINMUX_H__ */ diff --git a/src/soc/nvidia/tegra132/pmc.h b/src/soc/nvidia/tegra132/pmc.h new file mode 100644 index 0000000000..e9fbcd602e --- /dev/null +++ b/src/soc/nvidia/tegra132/pmc.h @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2010 - 2013, NVIDIA CORPORATION. All rights reserved. + * + * 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 . + */ + +#ifndef _TEGRA132_PMC_H_ +#define _TEGRA132_PMC_H_ + +#include + +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 +}; + +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 scratch0; + u32 scratch1; + u32 scratch2; + u32 scratch3; + u32 scratch4; + u32 scratch5; + u32 scratch6; + u32 scratch7; + u32 scratch8; + u32 scratch9; + u32 scratch10; + u32 scratch11; + u32 scratch12; + u32 scratch13; + u32 scratch14; + u32 scratch15; + u32 scratch16; + u32 scratch17; + u32 scratch18; + u32 scratch19; + u32 odmdata; + u32 scratch21; + u32 scratch22; + u32 scratch23; + u32 secure_scratch0; + u32 secure_scratch1; + u32 secure_scratch2; + u32 secure_scratch3; + u32 secure_scratch4; + u32 secure_scratch5; + 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; + u32 scratch25; + u32 scratch26; + u32 scratch27; + u32 scratch28; + u32 scratch29; + u32 scratch30; + u32 scratch31; + u32 scratch32; + u32 scratch33; + u32 scratch34; + u32 scratch35; + u32 scratch36; + u32 scratch37; + u32 scratch38; + u32 scratch39; + u32 scratch40; + u32 scratch41; + u32 scratch42; + 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; + u32 secure_scratch7; + u32 scratch43; + u32 scratch44; + u32 scratch45; + u32 scratch46; + u32 scratch47; + u32 scratch48; + u32 scratch49; + u32 scratch50; + u32 scratch51; + u32 scratch52; + u32 scratch53; + u32 scratch54; + u32 scratch55; + u32 scratch0_eco; + u32 por_dpd_ctrl; + u32 scratch2_eco; + 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; + u32 secure_scratch9; + u32 secure_scratch10; + u32 secure_scratch11; + u32 secure_scratch12; + u32 secure_scratch13; + u32 secure_scratch14; + u32 secure_scratch15; + u32 secure_scratch16; + u32 secure_scratch17; + u32 secure_scratch18; + u32 secure_scratch19; + u32 secure_scratch20; + u32 secure_scratch21; + u32 secure_scratch22; + u32 secure_scratch23; + u32 secure_scratch24; + u32 secure_scratch25; + u32 secure_scratch26; + u32 secure_scratch27; + u32 secure_scratch28; + u32 secure_scratch29; + u32 secure_scratch30; + u32 secure_scratch31; + u32 secure_scratch32; + u32 secure_scratch33; + u32 secure_scratch34; + u32 secure_scratch35; + u8 _rsv2[0xd0]; + u32 cntrl2; + u8 _rsv3[0x18]; + u32 io_dpd3_req; + u32 io_dqd3_status; + u32 strapping_opt_a; + u8 _rsv4[0x198]; + u32 scratch56; + u32 scratch57; + u32 scratch58; + u32 scratch59; + u32 scratch60; + u32 scratch61; + u32 scratch62; + u32 scratch63; + u32 scratch64; + u32 scratch65; + u32 scratch66; + u32 scratch67; + u32 scratch68; + u32 scratch69; + u32 scratch70; + u32 scratch71; + u32 scratch72; + u32 scratch73; + u32 scratch74; + u32 scratch75; + u32 scratch76; + u32 scratch77; + u32 scratch78; + u32 scratch79; + u32 scratch80; + u32 scratch81; + u32 scratch82; + u32 scratch83; + u32 scratch84; + u32 scratch85; + u32 scratch86; + u32 scratch87; + u32 scratch88; + u32 scratch89; + u32 scratch90; + u32 scratch91; + u32 scratch92; + u32 scratch93; + u32 scratch94; + u32 scratch95; + u32 scratch96; + u32 scratch97; + u32 scratch98; + u32 scratch99; + u32 scratch100; + u32 scratch101; + u32 scratch102; + u32 scratch103; + u32 scratch104; + u32 scratch105; + u32 scratch106; + u32 scratch107; + u32 scratch108; + u32 scratch109; + u32 scratch110; + u32 scratch111; + u32 scratch112; + u32 scratch113; + u32 scratch114; + u32 scratch115; + u32 scratch116; + u32 scratch117; + u32 scratch118; + u32 scratch119; +}; + +check_member(tegra_pmc_regs, scratch119, 0x6fc); + +enum { + PMC_PWRGATE_TOGGLE_PARTID_MASK = 0x1f, + PMC_PWRGATE_TOGGLE_PARTID_SHIFT = 0, + PMC_PWRGATE_TOGGLE_START = 0x1 << 8 +}; + +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 +}; + +enum { + PMC_DDR_PWR_EMMC_MASK = 1 << 1, + PMC_DDR_PWR_VAL_MASK = 1 << 0, +}; + +enum { + PMC_DDR_CFG_PKG_MASK = 1 << 0, + PMC_DDR_CFG_IF_MASK = 1 << 1, + PMC_DDR_CFG_XM0_RESET_TRI_MASK = 1 << 12, + PMC_DDR_CFG_XM0_RESET_DPDIO_MASK = 1 << 13, +}; + +enum { + PMC_NO_IOPOWER_MEM_MASK = 1 << 7, + PMC_NO_IOPOWER_MEM_COMP_MASK = 1 << 16, +}; + +enum { + PMC_POR_DPD_CTRL_MEM0_ADDR0_CLK_SEL_DPD_MASK = 1 << 0, + PMC_POR_DPD_CTRL_MEM0_ADDR1_CLK_SEL_DPD_MASK = 1 << 1, + PMC_POR_DPD_CTRL_MEM0_HOLD_CKE_LOW_OVR_MASK = 1 << 31, +}; + +enum { + PMC_CNTRL2_HOLD_CKE_LOW_EN = 0x1 << 12 +}; + +enum { + PMC_OSC_EDPD_OVER_XOFS_SHIFT = 1, + PMC_OSC_EDPD_OVER_XOFS_MASK = + 0x3f << PMC_OSC_EDPD_OVER_XOFS_SHIFT +}; + +enum { + PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT = 4, + PMC_STRAPPING_OPT_A_RAM_CODE_MASK = + 0xf << PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT, +}; + +#endif /* _TEGRA132_PMC_H_ */ diff --git a/src/soc/nvidia/tegra132/power.h b/src/soc/nvidia/tegra132/power.h new file mode 100644 index 0000000000..9283b5583a --- /dev/null +++ b/src/soc/nvidia/tegra132/power.h @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 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_TEGRA132_POWER_H__ +#define __SOC_NVIDIA_TEGRA132_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_TEGRA132_POWER_H__ */ diff --git a/src/soc/nvidia/tegra132/sysctr.h b/src/soc/nvidia/tegra132/sysctr.h new file mode 100644 index 0000000000..ea9746ddf2 --- /dev/null +++ b/src/soc/nvidia/tegra132/sysctr.h @@ -0,0 +1,55 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 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_TEGRA132_SYSCTR_H__ +#define __SOC_NVIDIA_TEGRA132_SYSCTR_H__ + +#include + +enum { + SYSCTR_CNTCR_EN = 1 << 0, + SYSCTR_CNTCR_HDBG = 1 << 1, + SYSCTR_CNTCR_FCREQ = 1 << 8 +}; + +struct sysctr_regs { + uint32_t cntcr; + uint32_t cntsr; + uint32_t cntcv0; + uint32_t cntcv1; + uint8_t _rsv0[0x10]; + uint32_t cntfid0; + uint32_t cntfid1; + uint8_t _rsv1[0xfa8]; + uint32_t counterid4; + uint32_t counterid5; + uint32_t counterid6; + uint32_t counterid7; + uint32_t counterid0; + uint32_t counterid1; + uint32_t counterid2; + uint32_t counterid3; + uint32_t counterid8; + uint32_t counterid9; + uint32_t counterid10; + uint32_t counterid11; +}; +check_member(sysctr_regs, counterid11, 0xffc); + +#endif /* __SOC_NVIDIA_TEGRA132_SYSCTR_H__ */ diff --git a/src/soc/nvidia/tegra132/uart.c b/src/soc/nvidia/tegra132/uart.c new file mode 100644 index 0000000000..80328af9bf --- /dev/null +++ b/src/soc/nvidia/tegra132/uart.c @@ -0,0 +1,161 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2009 Samsung Electronics + * + * 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 +#include +#include +#include /* for __console definition */ +#include +#include + +/* + * TODO: Use DRIVERS_UART_8250MEM driver instead. + * There is an issue in the IO call functions where x86 and ARM + * ordering is reversed. This 8250MEM driver uses the x86 convention. + * This driver can be replaced once the IO calls are sorted. + */ +struct tegra132_uart { + union { + uint32_t thr; // Transmit holding register. + uint32_t rbr; // Receive buffer register. + uint32_t dll; // Divisor latch lsb. + }; + union { + uint32_t ier; // Interrupt enable register. + uint32_t dlm; // Divisor latch msb. + }; + union { + uint32_t iir; // Interrupt identification register. + uint32_t fcr; // FIFO control register. + }; + uint32_t lcr; // Line control register. + uint32_t mcr; // Modem control register. + uint32_t lsr; // Line status register. + uint32_t msr; // Modem status register. +} __attribute__ ((packed)); + +static void tegra132_uart_tx_flush(struct tegra132_uart *uart_ptr); +static int tegra132_uart_tst_byte(struct tegra132_uart *uart_ptr); + +static void tegra132_uart_init(struct tegra132_uart *uart_ptr) +{ + const uint8_t line_config = UART8250_LCR_WLS_8; // 8n1 + + uint16_t divisor = (u16) uart_baudrate_divisor(default_baudrate(), + uart_platform_refclk(), 16); + + tegra132_uart_tx_flush(uart_ptr); + + // Disable interrupts. + write8(0, &uart_ptr->ier); + // Force DTR and RTS to high. + write8(UART8250_MCR_DTR | UART8250_MCR_RTS, &uart_ptr->mcr); + // Set line configuration, access divisor latches. + write8(UART8250_LCR_DLAB | line_config, &uart_ptr->lcr); + // Set the divisor. + write8(divisor & 0xff, &uart_ptr->dll); + write8((divisor >> 8) & 0xff, &uart_ptr->dlm); + // Hide the divisor latches. + write8(line_config, &uart_ptr->lcr); + // Enable FIFOs, and clear receive and transmit. + write8(UART8250_FCR_FIFO_EN | + UART8250_FCR_CLEAR_RCVR | + UART8250_FCR_CLEAR_XMIT, &uart_ptr->fcr); +} + +static unsigned char tegra132_uart_rx_byte(struct tegra132_uart *uart_ptr) +{ + if (!tegra132_uart_tst_byte(uart_ptr)) + return 0; + return read8(&uart_ptr->rbr); +} + +static void tegra132_uart_tx_byte(struct tegra132_uart *uart_ptr, unsigned char data) +{ + while (!(read8(&uart_ptr->lsr) & UART8250_LSR_THRE)); + write8(data, &uart_ptr->thr); +} + +static void tegra132_uart_tx_flush(struct tegra132_uart *uart_ptr) +{ + while (!(read8(&uart_ptr->lsr) & UART8250_LSR_TEMT)); +} + +static int tegra132_uart_tst_byte(struct tegra132_uart *uart_ptr) +{ + return (read8(&uart_ptr->lsr) & UART8250_LSR_DR) == UART8250_LSR_DR; +} + +/* FIXME: Add mainboard override */ +unsigned int uart_platform_refclk(void) +{ + return 408000000; +} + +uintptr_t uart_platform_base(int idx) +{ + /* Default to UART A */ + unsigned int base = 0x70006000; + /* UARTs A - E are mapped as index 0 - 4 */ + if ((idx < 5) && (idx >= 0)) { + if (idx != 1) { /* Not UART B */ + base += idx * 0x100; + } else { + base += 0x40; + } + } + return base; +} + +void uart_init(int idx) +{ + struct tegra132_uart *uart_ptr = uart_platform_baseptr(idx); + tegra132_uart_init(uart_ptr); +} + +unsigned char uart_rx_byte(int idx) +{ + struct tegra132_uart *uart_ptr = uart_platform_baseptr(idx); + return tegra132_uart_rx_byte(uart_ptr); +} + +void uart_tx_byte(int idx, unsigned char data) +{ + struct tegra132_uart *uart_ptr = uart_platform_baseptr(idx); + tegra132_uart_tx_byte(uart_ptr, data); +} + +void uart_tx_flush(int idx) +{ + struct tegra132_uart *uart_ptr = uart_platform_baseptr(idx); + tegra132_uart_tx_flush(uart_ptr); +} + +#ifndef __PRE_RAM__ +void uart_fill_lb(void *data) +{ + struct lb_serial serial; + serial.type = LB_SERIAL_TYPE_MEMORY_MAPPED; + serial.baseaddr = uart_platform_base(CONFIG_UART_FOR_CONSOLE); + serial.baud = default_baudrate(); + lb_add_serial(&serial, data); + + lb_add_console(LB_TAG_CONSOLE_SERIAL8250MEM, data); +} +#endif