diff options
author | Varun Wadekar <vwadekar@nvidia.com> | 2012-02-16 14:25:31 +0530 |
---|---|---|
committer | Gerrit <chrome-bot@google.com> | 2012-02-27 01:36:44 -0800 |
commit | 2ddff25f8bba1a9a0cb788222040b3aa32a31da8 (patch) | |
tree | d0ae1f1d5b8b3dfeb6cbbbf6a955219f469c2e20 | |
parent | 50d29eba6c6ada03dedb4e06061ceefa89709627 (diff) |
arm: tegra3: add warmboot code needed for LP0
BUG=chromium-os:23496
TEST=build and boot on Waluigi, Cardhu by enabling
CONFIG_TEGRA_LP0 and CONFIG_TEGRA3_WARMBOOT.
odification of the work done by:
a. Jimmy Zhang <jimmzhang@nvidia.com>
b. Yen Lin <yelin@nvidia.com>
c. Wei Ni <wni@nvidia.com>
Change-Id: If2fa63ccd23341694955bca25fb5cfc4a8a805ad
Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
Reviewed-on: https://gerrit.chromium.org/gerrit/13800
-rw-r--r-- | arch/arm/cpu/armv7/tegra3/Makefile | 7 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/tegra3/warmboot.c | 589 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/tegra3/warmboot_avp.c | 410 | ||||
-rw-r--r-- | arch/arm/include/asm/arch-tegra/clk_rst.h | 113 | ||||
-rw-r--r-- | arch/arm/include/asm/arch-tegra/pmc.h | 4 | ||||
-rw-r--r-- | arch/arm/include/asm/arch-tegra/warmboot_avp.h | 42 | ||||
-rw-r--r-- | include/configs/tegra3-common.h | 11 |
7 files changed, 1171 insertions, 5 deletions
diff --git a/arch/arm/cpu/armv7/tegra3/Makefile b/arch/arm/cpu/armv7/tegra3/Makefile index 3a4bc802c5c..a9642073083 100644 --- a/arch/arm/cpu/armv7/tegra3/Makefile +++ b/arch/arm/cpu/armv7/tegra3/Makefile @@ -1,5 +1,5 @@ # -# (C) Copyright 2010,2011 Nvidia Corporation. +# (C) Copyright 2010-2012 Nvidia Corporation. # # (C) Copyright 2000-2003 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. @@ -23,6 +23,10 @@ # MA 02111-1307 USA # +# The AVP is ARMv4T architecture so we must use special compiler +# flags for any files it might use. +CFLAGS_arch/arm/cpu/armv7/tegra3/warmboot_avp.o += -march=armv4t + include $(TOPDIR)/config.mk LIB = $(obj)lib$(SOC).o @@ -30,6 +34,7 @@ LIB = $(obj)lib$(SOC).o COBJS-y := board.o pinmux.o sys_info.o COBJS-$(CONFIG_VIDEO_TEGRA) += display.o +COBJS-$(CONFIG_TEGRA3_WARMBOOT) += warmboot.o warmboot_avp.o COBJS := $(COBJS-y) diff --git a/arch/arm/cpu/armv7/tegra3/warmboot.c b/arch/arm/cpu/armv7/tegra3/warmboot.c new file mode 100644 index 00000000000..c38776ebc77 --- /dev/null +++ b/arch/arm/cpu/armv7/tegra3/warmboot.c @@ -0,0 +1,589 @@ +/* + * (C) Copyright 2010 - 2012 + * NVIDIA Corporation <www.nvidia.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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; either version 2 of + * the License, or (at your option) any later version. + * + * 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 <common.h> +#include <asm/io.h> +#include <asm/errno.h> + +#include <asm/arch-tegra/clk_rst.h> +#include <asm/arch-tegra/pmc.h> +#include <asm/arch-tegra/ap20.h> +#include <asm/arch-tegra/warmboot.h> + +#include <asm/arch/clock.h> +#include <asm/arch/pinmux.h> +#include <asm/arch/tegra.h> +#include <asm/arch/fuse.h> +#include <asm/arch/gp_padctrl.h> +#include <asm/arch/sdram_param.h> + +enum field_type { + TYPE_SDRAM, + TYPE_PLLX, + TYPE_CONST, +}; + +struct pmc_scratch_field { + enum field_type field_type; + u32 offset_val; + u32 mask; + u32 shift_src; + u32 shift_dst; +}; + +#define pllx_offset(member) offsetof(struct clk_pll_simple, member) +#define sdram_offset(member) offsetof(struct sdram_params, member) + +#define field(type, param, field, dst) \ + { \ + .field_type = type, \ + .offset_val = param, \ + .mask = 0xfffffffful >> (31 - ((1 ? field) - (0 ? field))), \ + .shift_src = 0 ? field, \ + .shift_dst = 0 ? dst, \ + } + +static const struct pmc_scratch_field scratch_3[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_PLLX, pllx_offset(pll_base), 4 : 0, 4 : 0), + field(TYPE_PLLX, pllx_offset(pll_base), 17 : 8, 14 : 5), + field(TYPE_PLLX, pllx_offset(pll_base), 22 : 20, 17 : 15), + field(TYPE_PLLX, pllx_offset(pll_misc), 7 : 4, 21 : 18), + field(TYPE_PLLX, pllx_offset(pll_base), 11 : 8, 25 : 22), + field(TYPE_CONST, 0, 0 : 0, 26 : 26), +}; + +static const struct pmc_scratch_field scratch_4[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_CONST, -1, 9 : 0, 19 : 10), + field(TYPE_CONST, 1, 0 : 0, 31 : 31), +}; + +static const struct pmc_scratch_field scratch_5_ddr3[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_wb_emr3), 13 : 0, 13 : 0), + field(TYPE_SDRAM, sdram_offset(emc_wb_emr2), 13 : 0, 27 : 14), + field(TYPE_SDRAM, sdram_offset(emc_wb_emr3), 21 : 20, 29 : 28), + field(TYPE_SDRAM, sdram_offset(emc_wb_emr2), 21 : 20, 31 : 30), +}; + +static const struct pmc_scratch_field scratch_5_lpddr2[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_mrw_lpddr2_zcal_wb), 23 : 16, 7 : 0), + field(TYPE_SDRAM, sdram_offset(emc_mrw_lpddr2_zcal_wb), 7 : 0, 15 : 8), + field(TYPE_SDRAM, sdram_offset(emc_wb_mrw1), 23 : 16, 23 : 16), + field(TYPE_SDRAM, sdram_offset(emc_wb_mrw1), 7 : 0, 31 : 24), +}; + +static const struct pmc_scratch_field scratch_6_ddr3[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_wb_mrs_extra), 13 : 0, 13 : 0), + field(TYPE_SDRAM, sdram_offset(emc_wb_mrs), 13 : 0, 27 : 14), + field(TYPE_SDRAM, sdram_offset(emc_wb_mrs_extra), 21 : 20, 29 : 28), + field(TYPE_SDRAM, sdram_offset(emc_wb_mrs), 21 : 20, 31 : 30), +}; +static const struct pmc_scratch_field scratch_6_lpddr2[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_wb_mrw3), 23 : 16, 7 : 0), + field(TYPE_SDRAM, sdram_offset(emc_wb_mrw3), 7 : 0, 15 : 8), + field(TYPE_SDRAM, sdram_offset(emc_wb_mrw2), 23 : 16, 23 : 16), + field(TYPE_SDRAM, sdram_offset(emc_wb_mrw2), 7 : 0, 31 : 24), +}; + +static const struct pmc_scratch_field scratch_7_ddr3[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_wb_emrs), 13 : 0, 13 : 0), + field(TYPE_SDRAM, sdram_offset(emc_wb_emrs), 21 : 20, 15 : 14), + field(TYPE_SDRAM, sdram_offset(emc_wb_emr3), 26 : 26, 16 : 16), + field(TYPE_SDRAM, sdram_offset(emc_wb_emr2), 26 : 26, 17 : 17), + field(TYPE_SDRAM, sdram_offset(emc_wb_mrs_extra), 26 : 26, 18 : 18), + field(TYPE_SDRAM, sdram_offset(emc_wb_mrs), 26 : 26, 19 : 19), + field(TYPE_SDRAM, sdram_offset(emc_wb_emrs), 26 : 26, 20 : 20), + field(TYPE_SDRAM, sdram_offset(emc_zq_cal_ddr3_wb), 0 : 0, 21 : 21), + field(TYPE_SDRAM, sdram_offset(emc_zq_cal_ddr3_wb), 4 : 4, 22 : 22), + field(TYPE_SDRAM, sdram_offset(emc_rfc), 8 : 0, 31 : 23), +}; +static const struct pmc_scratch_field scratch_7_lpddr2[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_wb_mrw_extra), 23 : 16, 7 : 0), + field(TYPE_SDRAM, sdram_offset(emc_wb_mrw_extra), 7 : 0, 15 : 8), +}; + +static const struct pmc_scratch_field scratch_8[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_cfg_dig_dll), 0 : 0, 0 : 0), + field(TYPE_SDRAM, sdram_offset(emc_cfg_dig_dll), 2 : 2, 1 : 1), + field(TYPE_SDRAM, sdram_offset(emc_cfg_dig_dll), 4 : 4, 2 : 2), + field(TYPE_SDRAM, sdram_offset(emc_cfg_dig_dll), 5 : 5, 3 : 3), + field(TYPE_SDRAM, sdram_offset(emc_cfg_dig_dll), 7 : 6, 5 : 4), + field(TYPE_SDRAM, sdram_offset(emc_cfg_dig_dll), 11 : 8, 9 : 6), + field(TYPE_SDRAM, sdram_offset(emc_cfg_dig_dll), 25 : 16, 19 : 10), + field(TYPE_SDRAM, sdram_offset(emc_cfg_dig_dll), 27 : 27, 20 : 20), + field(TYPE_SDRAM, sdram_offset(emc_cfg_dig_dll), 29 : 28, 22 : 21), + field(TYPE_SDRAM, sdram_offset(emc_xm2cmd_pad_ctrl), 5 : 5, 23 : 23), + field(TYPE_SDRAM, sdram_offset(emc_xm2cmd_pad_ctrl), 10 : 10, 24 : 24), + field(TYPE_SDRAM, sdram_offset(emc_xm2cmd_pad_ctrl), 22 : 16, 31 : 25), +}; + +static const struct pmc_scratch_field scratch_9[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_dll_xform_dqs[0]), 4 : 0, 4 : 0), + field(TYPE_SDRAM, sdram_offset(emc_dll_xform_dqs[0]), 22 : 8, 19 : 5), + field(TYPE_SDRAM, sdram_offset(emc_xm2clk_pad_ctrl), 0 : 0, 20 : 20), + field(TYPE_SDRAM, sdram_offset(emc_xm2clk_pad_ctrl), 2 : 2, 21 : 21), + field(TYPE_SDRAM, sdram_offset(emc_xm2clk_pad_ctrl), 18 : 14, 26 : 22), + field(TYPE_SDRAM, sdram_offset(emc_xm2clk_pad_ctrl), 23 : 19, 31 : 27), +}; + +static const struct pmc_scratch_field scratch_10[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_dll_xform_quse[0]), 4 : 0, 4 : 0), + field(TYPE_SDRAM, sdram_offset(emc_dll_xform_quse[0]), 22 : 8, 19 : 5), + field(TYPE_SDRAM, sdram_offset(emc_auto_cal_config), 4 : 0, 24 : 20), + field(TYPE_SDRAM, sdram_offset(emc_auto_cal_config), 12 : 8, 29 : 25), + field(TYPE_SDRAM, sdram_offset(emc_auto_cal_config), 30 : 30, 30 : 30), + field(TYPE_SDRAM, sdram_offset(emc_cfg), 21 : 21, 31 : 31), +}; + +static const struct pmc_scratch_field scratch_11[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_dll_xform_dq[0]), 4 : 0, 4 : 0), + field(TYPE_SDRAM, sdram_offset(emc_dll_xform_dq[0]), 22 : 8, 19 : 5), + field(TYPE_SDRAM, sdram_offset(emc_sel_dpd_ctrl), 5 : 0, 25 : 20), + field(TYPE_SDRAM, sdram_offset(emc_sel_dpd_ctrl), 9 : 8, 27 : 26), + field(TYPE_SDRAM, sdram_offset(emc_sel_dpd_ctrl), 18 : 16, 30 : 28), + field(TYPE_SDRAM, sdram_offset(emc_adr_cfg), 7 : 7, 31 : 31) +}; + +static const struct pmc_scratch_field scratch_12[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_cfg2), 14 : 7, 7 : 0), + field(TYPE_SDRAM, sdram_offset(emc_cfg2), 19 : 18, 9 : 8), + field(TYPE_SDRAM, sdram_offset(emc_cfg2), 22 : 22, 10 : 10), + field(TYPE_SDRAM, sdram_offset(emc_cfg2), 30 : 24, 17 : 11), + field(TYPE_SDRAM, sdram_offset(emc_trefbw), 13 : 0, 31 : 18), +}; + +static const struct pmc_scratch_field scratch_13[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_zcal_mrw_cmd), 7 : 0, 7 : 0), + field(TYPE_SDRAM, sdram_offset(emc_zcal_mrw_cmd), 23 : 16, 15 : 8), + field(TYPE_SDRAM, sdram_offset(emc_dll_xform_dqs[1]), 22 : 8, 30 : 16), + field(TYPE_SDRAM, sdram_offset(mc_emem_adr_cfg), 0 : 0, 31 : 31), +}; + +static const struct pmc_scratch_field scratch_14[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_dll_xform_dqs[2]), 22 : 8, 14 : 0), + field(TYPE_SDRAM, sdram_offset(emc_dll_xform_dqs[3]), 22 : 8, 29 : 15), + field(TYPE_SDRAM, sdram_offset(emc_dev_select), 1 : 0, 31 : 30), +}; + +static const struct pmc_scratch_field scratch_15[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_dll_xform_dqs[4]), 22 : 8, 14 : 0), + field(TYPE_SDRAM, sdram_offset(emc_dll_xform_dqs[5]), 22 : 8, 29 : 15), + field(TYPE_SDRAM, sdram_offset(emc_cfg_dig_dll_period_wb), + 1 : 0, 31 : 30), +}; + +static const struct pmc_scratch_field scratch_16[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_dll_xform_dqs[6]), 22 : 8, 14 : 0), + field(TYPE_SDRAM, sdram_offset(emc_dll_xform_dqs[7]), 22 : 8, 29 : 15), + field(TYPE_SDRAM, sdram_offset(mc_emem_arb_misc0), 27 : 27, 30 : 30), + field(TYPE_SDRAM, sdram_offset(emc_wb_ext_mode_reg_enable), + 0 : 0, 31 : 31), +}; + +static const struct pmc_scratch_field scratch_17[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_dll_xform_quse[1]), 22 : 8, 14 : 0), + field(TYPE_SDRAM, sdram_offset(emc_dll_xform_quse[2]), 22 : 8, 29 : 15), + field(TYPE_SDRAM, sdram_offset(mc_clken_override_all_wb), + 0 : 0, 30 : 30), + field(TYPE_SDRAM, sdram_offset(emc_clken_override_all_wb), + 0 : 0, 31 : 31), +}; + +static const struct pmc_scratch_field scratch_18[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_dll_xform_quse[3]), 22 : 8, 14 : 0), + field(TYPE_SDRAM, sdram_offset(emc_dll_xform_quse[4]), 22 : 8, 29 : 15), + field(TYPE_SDRAM, sdram_offset(emc_mrs_wb_enable), 0 : 0, 30 : 30), + field(TYPE_SDRAM, sdram_offset(emc_zcal_wb_enable), 0 : 0, 31 : 31), +}; + +static const struct pmc_scratch_field scratch_19[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_dll_xform_quse[5]), 22 : 8, 14 : 0), + field(TYPE_SDRAM, sdram_offset(emc_dll_xform_quse[6]), 22 : 8, 29 : 15), + field(TYPE_SDRAM, sdram_offset(emc_fbio_cfg5), 1 : 0, 31 : 30), +}; + +static const struct pmc_scratch_field scratch_22[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_dll_xform_quse[7]), 22 : 8, 14 : 0), + field(TYPE_SDRAM, sdram_offset(emc_dll_xform_dq[1]), 22 : 8, 29 : 15), + field(TYPE_SDRAM, sdram_offset(emc_fbio_cfg5), 3 : 2, 31 : 30), +}; + +static const struct pmc_scratch_field scratch_23[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_dll_xform_dq[2]), 22 : 8, 14 : 0), + field(TYPE_SDRAM, sdram_offset(emc_dll_xform_dq[3]), 22 : 8, 29 : 15), + field(TYPE_SDRAM, sdram_offset(emc_clock_source), 1 : 0, 31 : 30), +}; + +static const struct pmc_scratch_field scratch_24[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_zcal_interval), 23 : 10, 13 : 0), + field(TYPE_SDRAM, sdram_offset(emc_xm2dqs_pad_ctrl2), 0 : 0, 14 : 14), + field(TYPE_SDRAM, sdram_offset(emc_xm2dqs_pad_ctrl2), 2 : 2, 15 : 15), + field(TYPE_SDRAM, sdram_offset(emc_xm2dqs_pad_ctrl2), 3 : 3, 16 : 16), + field(TYPE_SDRAM, sdram_offset(emc_xm2dqs_pad_ctrl2), 4 : 4, 17 : 17), + field(TYPE_SDRAM, sdram_offset(emc_xm2dqs_pad_ctrl2), 5 : 5, 18 : 18), + field(TYPE_SDRAM, sdram_offset(emc_xm2dqs_pad_ctrl2), 9 : 9, 19 : 19), + field(TYPE_SDRAM, sdram_offset(emc_xm2dqs_pad_ctrl2), 10 : 10, 20 : 20), + field(TYPE_SDRAM, sdram_offset(emc_xm2dqs_pad_ctrl2), 11 : 11, 21 : 21), + field(TYPE_SDRAM, sdram_offset(emc_xm2dqs_pad_ctrl2), 12 : 12, 22 : 22), + field(TYPE_SDRAM, sdram_offset(emc_xm2dqs_pad_ctrl2), 13 : 13, 23 : 23), + field(TYPE_SDRAM, sdram_offset(emc_xm2dqs_pad_ctrl2), 27 : 24, 27 : 24), + field(TYPE_SDRAM, sdram_offset(emc_rrd), 3 : 0, 31 : 28), +}; + +static const struct pmc_scratch_field scratch_25[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_xm2vttgen_pad_ctrl), 0 : 0, 0 : 0), + field(TYPE_SDRAM, sdram_offset(emc_xm2vttgen_pad_ctrl), 10 : 8, 3 : 1), + field(TYPE_SDRAM, sdram_offset(emc_xm2vttgen_pad_ctrl), 14 : 12, 6 : 4), + field(TYPE_SDRAM, sdram_offset(emc_xm2vttgen_pad_ctrl), 18 : 16, 9 : 7), + field(TYPE_SDRAM, sdram_offset(emc_xm2vttgen_pad_ctrl), + 26 : 24, 12 : 10), + field(TYPE_SDRAM, sdram_offset(mc_emem_arb_override), 27 : 27, 13 : 13), + field(TYPE_SDRAM, sdram_offset(mc_emem_arb_override), 26 : 26, 14 : 14), + field(TYPE_SDRAM, sdram_offset(mc_emem_arb_override), 24 : 24, 15 : 15), + field(TYPE_SDRAM, sdram_offset(mc_emem_arb_override), 16 : 16, 16 : 16), + field(TYPE_SDRAM, sdram_offset(mc_emem_arb_override), 10 : 10, 17 : 17), + field(TYPE_SDRAM, sdram_offset(mc_emem_arb_override), 7 : 0, 25 : 18), + field(TYPE_SDRAM, sdram_offset(emc_ras), 5 : 0, 31 : 26), +}; + +static const struct pmc_scratch_field scratch_26[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_refresh), 15 : 6, 9 : 0), + field(TYPE_SDRAM, sdram_offset(emc_zcal_wait_cnt), 9 : 0, 19 : 10), + field(TYPE_SDRAM, sdram_offset(emc_xm2vttgen_pad_ctrl2), + 2 : 0, 22 : 20), + field(TYPE_SDRAM, sdram_offset(emc_xm2vttgen_pad_ctrl2), + 27 : 26, 24 : 23), + field(TYPE_SDRAM, sdram_offset(emc_xm2vttgen_pad_ctrl2), + 29 : 28, 26 : 25), + field(TYPE_SDRAM, sdram_offset(emc_xm2vttgen_pad_ctrl2), + 31 : 30, 28 : 27), + field(TYPE_SDRAM, sdram_offset(emc_fbio_cfg6), 2 : 0, 31 : 29), +}; + +static const struct pmc_scratch_field scratch_27[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_xm2quse_pad_ctrl), 0 : 0, 0 : 0), + field(TYPE_SDRAM, sdram_offset(emc_xm2quse_pad_ctrl), 2 : 2, 1 : 1), + field(TYPE_SDRAM, sdram_offset(emc_xm2quse_pad_ctrl), 3 : 3, 2 : 2), + field(TYPE_SDRAM, sdram_offset(emc_xm2quse_pad_ctrl), 4 : 4, 3 : 3), + field(TYPE_SDRAM, sdram_offset(emc_xm2quse_pad_ctrl), 5 : 5, 4 : 4), + field(TYPE_SDRAM, sdram_offset(emc_xm2quse_pad_ctrl), 27 : 24, 8 : 5), + field(TYPE_SDRAM, sdram_offset(mc_emem_adr_cfg_dev0), 2 : 0, 11 : 9), + field(TYPE_SDRAM, sdram_offset(mc_emem_adr_cfg_dev0), 9 : 8, 13 : 12), + field(TYPE_SDRAM, sdram_offset(mc_emem_adr_cfg_dev0), 19 : 16, 17 : 14), + field(TYPE_SDRAM, sdram_offset(mc_emem_adr_cfg_dev1), 2 : 0, 20 : 18), + field(TYPE_SDRAM, sdram_offset(mc_emem_adr_cfg_dev1), 9 : 8, 22 : 21), + field(TYPE_SDRAM, sdram_offset(mc_emem_adr_cfg_dev1), 19 : 16, 26 : 23), + field(TYPE_SDRAM, sdram_offset(emc_r2w), 4 : 0, 31 : 27), +}; + +static const struct pmc_scratch_field scratch_28[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_fbio_spare), 31 : 24, 7 : 0), + field(TYPE_SDRAM, sdram_offset(emc_cfg_rsv), 7 : 0, 15 : 8), + field(TYPE_SDRAM, sdram_offset(emc_xm2comp_pad_ctrl), 3 : 0, 19 : 16), + field(TYPE_SDRAM, sdram_offset(emc_xm2comp_pad_ctrl), 7 : 5, 22 : 20), + field(TYPE_SDRAM, sdram_offset(emc_xm2comp_pad_ctrl), 10 : 10, 23 : 23), + field(TYPE_SDRAM, sdram_offset(mc_emem_arb_rsv), 7 : 0, 31 : 24), +}; + +static const struct pmc_scratch_field scratch_29[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_timing_control_wait), 7 : 0, 7 : 0), + field(TYPE_SDRAM, sdram_offset(emc_zcal_wb_wait), 7 : 0, 15 : 8), + field(TYPE_SDRAM, sdram_offset(emc_auto_cal_wait), 7 : 0, 23 : 16), + field(TYPE_SDRAM, sdram_offset(wb_wait), 7 : 0, 31 : 24), +}; + +static const struct pmc_scratch_field scratch_30[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_pin_program_wait), 7 : 0, 7 : 0), + field(TYPE_SDRAM, sdram_offset(emc_rc), 6 : 0, 14 : 8), + field(TYPE_SDRAM, sdram_offset(emc_dli_trim_txdqs[0]), 6 : 0, 21 : 5), + field(TYPE_SDRAM, sdram_offset(emc_dli_trim_txdqs[1]), 6 : 0, 28 : 22), + field(TYPE_SDRAM, sdram_offset(emc_extra_refresh_num) , 2 : 0, 31 : 29), +}; + +static const struct pmc_scratch_field scratch_31[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_dli_trim_txdqs[2]), 6 : 0, 6 : 0), + field(TYPE_SDRAM, sdram_offset(emc_dli_trim_txdqs[3]), 6 : 0, 13 : 7), + field(TYPE_SDRAM, sdram_offset(emc_dli_trim_txdqs[4]), 6 : 0, 20 : 14), + field(TYPE_SDRAM, sdram_offset(emc_dli_trim_txdqs[5]), 6 : 0, 27 : 21), + field(TYPE_SDRAM, sdram_offset(emc_rext), 3 : 0, 31 : 28), +}; + +static const struct pmc_scratch_field scratch_32[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_dli_trim_txdqs[6]), 6 : 0, 6 : 0), + field(TYPE_SDRAM, sdram_offset(emc_dli_trim_txdqs[7]), 6 : 0, 13 : 7), + field(TYPE_SDRAM, sdram_offset(emc_rp), 5 : 0, 19 : 14), + field(TYPE_SDRAM, sdram_offset(emc_w2p), 5 : 0, 25 : 20), + field(TYPE_SDRAM, sdram_offset(emc_rd_rcd), 5 : 0, 31 : 26), +}; + +static const struct pmc_scratch_field scratch_33[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_wr_rcd), 5 : 0, 5 : 0), + field(TYPE_SDRAM, sdram_offset(emc_tfaw), 5 : 0, 11 : 6), + field(TYPE_SDRAM, sdram_offset(emc_trpab), 5 : 0, 17 : 12), + field(TYPE_SDRAM, sdram_offset(emc_odt_write), 2 : 0, 20 : 18), + field(TYPE_SDRAM, sdram_offset(emc_odt_write), 4 : 4, 21 : 21), + field(TYPE_SDRAM, sdram_offset(emc_odt_write), 30 : 30, 22 : 22), + field(TYPE_SDRAM, sdram_offset(emc_odt_write), 31 : 31, 23 : 23), + field(TYPE_SDRAM, sdram_offset(emc_xm2dqs_pad_ctrl3), 0 : 0, 24 : 24), + field(TYPE_SDRAM, sdram_offset(emc_xm2dqs_pad_ctrl3), 5 : 5, 25 : 25), + field(TYPE_SDRAM, sdram_offset(emc_xm2dqs_pad_ctrl3), 27 : 24, 29 : 26), + field(TYPE_SDRAM, sdram_offset(emc_fbio_cfg5), 7 : 7, 31 : 31), + field(TYPE_SDRAM, sdram_offset(ahb_arbitration_xbar_ctrl_mem_init_done), + 0 : 0, 30 : 30), +}; + +static const struct pmc_scratch_field scratch_40[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_w2r), 4 : 0, 4 : 0), + field(TYPE_SDRAM, sdram_offset(emc_r2p), 4 : 0, 9 : 5), + field(TYPE_SDRAM, sdram_offset(emc_quse), 4 : 0, 14 : 10), + field(TYPE_SDRAM, sdram_offset(emc_qrst), 4 : 0, 19 : 15), + field(TYPE_SDRAM, sdram_offset(emc_rdv), 4 : 0, 24 : 20), + field(TYPE_SDRAM, sdram_offset(emc_ctt), 4 : 0, 29 : 25), + field(TYPE_SDRAM, sdram_offset(emc_fbio_cfg5), 8 : 8, 30 : 30), + field(TYPE_SDRAM, sdram_offset(emc_fbio_cfg5), 9 : 9, 31 : 31), +}; + +static const struct pmc_scratch_field scratch_42[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_wdv), 3 : 0, 3 : 0), + field(TYPE_SDRAM, sdram_offset(emc_qsafe), 3 : 0, 7 : 4), + field(TYPE_SDRAM, sdram_offset(emc_wext), 3 : 0, 11 : 8), + field(TYPE_SDRAM, sdram_offset(emc_fbio_cfg5), 15 : 13, 25 : 23), + field(TYPE_SDRAM, sdram_offset(emc_fbio_cfg5), 12 : 12, 26 : 26), + field(TYPE_SDRAM, sdram_offset(emc_quse_extra), 3 : 0, 31 : 28), + field(TYPE_SDRAM, sdram_offset(memory_type), 2 : 0, 14 : 12), + field(TYPE_SDRAM, sdram_offset(emc_clock_divider), 7 : 0, 22 : 15), + field(TYPE_SDRAM, sdram_offset(emc_clock_use_pllmud), 0 : 0, 27 : 27), +}; + +static const struct pmc_scratch_field scratch_44[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_xm2cmd_pad_ctrl), 6 : 6, 0 : 0), + field(TYPE_SDRAM, sdram_offset(emc_xm2cmd_pad_ctrl), 8 : 8, 1 : 1), + field(TYPE_SDRAM, sdram_offset(emc_ar2pden), 8 : 0, 10 : 2), + field(TYPE_SDRAM, sdram_offset(emc_fbio_spare), 23 : 16, 18 : 11), + field(TYPE_SDRAM, sdram_offset(emc_cfg_rsv), 15 : 8, 26 : 19), + field(TYPE_SDRAM, sdram_offset(emc_ctt_term_ctrl), 12 : 8, 31 : 27), +}; + +static const struct pmc_scratch_field scratch_45[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_pchg2pden), 5 : 0, 5 : 0), + field(TYPE_SDRAM, sdram_offset(emc_act2pden), 5 : 0, 11 : 6), + field(TYPE_SDRAM, sdram_offset(emc_rw2pden), 5 : 0, 17 : 12), + field(TYPE_SDRAM, sdram_offset(emc_xm2cmd_pad_ctrl2), 18 : 14, 22 : 18), + field(TYPE_SDRAM, sdram_offset(emc_xm2cmd_pad_ctrl2), 23 : 19, 27 : 23), + field(TYPE_SDRAM, sdram_offset(emc_xm2cmd_pad_ctrl2), 27 : 24, 31 : 28), +}; + +static const struct pmc_scratch_field scratch_46[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_xm2dqs_pad_ctrl), 4 : 0, 4 : 0), + field(TYPE_SDRAM, sdram_offset(emc_xm2dqs_pad_ctrl), 12 : 8, 9 : 5), + field(TYPE_SDRAM, sdram_offset(emc_xm2dqs_pad_ctrl), 18 : 14, 14 : 10), + field(TYPE_SDRAM, sdram_offset(emc_xm2dqs_pad_ctrl), 23 : 19, 19 : 15), + field(TYPE_SDRAM, sdram_offset(emc_xm2dq_pad_ctrl), 18 : 14, 24 : 20), + field(TYPE_SDRAM, sdram_offset(emc_xm2dq_pad_ctrl), 23 : 19, 29 : 25), + field(TYPE_SDRAM, sdram_offset(emc_cfg2), 17 : 16, 31 : 30), +}; + +static const struct pmc_scratch_field scratch_47[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_xm2cmd_pad_ctrl2), 31 : 28, 3 : 0), + field(TYPE_SDRAM, sdram_offset(emc_xm2dqs_pad_ctrl), 27 : 24, 7 : 4), + field(TYPE_SDRAM, sdram_offset(emc_xm2dqs_pad_ctrl), 31 : 28, 11 : 8), + field(TYPE_SDRAM, sdram_offset(emc_xm2dq_pad_ctrl), 27 : 24, 15 : 12), + field(TYPE_SDRAM, sdram_offset(emc_xm2dq_pad_ctrl), 31 : 28, 19 : 16), + field(TYPE_SDRAM, sdram_offset(emc_xm2clk_pad_ctrl), 27 : 24, 23 : 20), + field(TYPE_SDRAM, sdram_offset(emc_xm2clk_pad_ctrl), 31 : 28, 27 : 24), + field(TYPE_SDRAM, sdram_offset(emc_ctt_term_ctrl), 2 : 0, 30 : 28), + field(TYPE_SDRAM, sdram_offset(emc_cfg), 22 : 22, 31 : 31), +}; + +static const struct pmc_scratch_field scratch_48[] = { + field(TYPE_CONST, 0, 31 : 0, 31 : 0), + field(TYPE_SDRAM, sdram_offset(emc_xm2dq_pad_ctrl2), 18 : 16, 2 : 0), + field(TYPE_SDRAM, sdram_offset(emc_xm2dq_pad_ctrl2), 22 : 20, 5 : 3), + field(TYPE_SDRAM, sdram_offset(emc_xm2dq_pad_ctrl2), 26 : 24, 8 : 6), + field(TYPE_SDRAM, sdram_offset(emc_xm2dq_pad_ctrl2), 30 : 28, 11 : 9), + field(TYPE_SDRAM, sdram_offset(emc_xm2clk_pad_ctrl), 13 : 11, 14 : 12), + field(TYPE_SDRAM, sdram_offset(emc_cfg2), 21 : 20, 16 : 15), + field(TYPE_SDRAM, sdram_offset(emc_cfg), 23 : 23, 17 : 17), +}; + +struct pmc_scratch_reg { + const struct pmc_scratch_field *fields; + u32 scratch_off; + u32 num_fields; +}; + +#define scratch(num, field_list) \ + { \ + .scratch_off = offsetof(struct pmc_ctlr, num), \ + .fields = field_list, \ + .num_fields = ARRAY_SIZE(field_list), \ + } + +static const struct pmc_scratch_reg scratch[] = { + scratch(pmc_scratch3, scratch_3), + scratch(pmc_scratch4, scratch_4), + scratch(pmc_scratch5, scratch_5_ddr3), + scratch(pmc_scratch6, scratch_6_ddr3), + scratch(pmc_scratch7, scratch_7_ddr3), + scratch(pmc_scratch8, scratch_8), + scratch(pmc_scratch9, scratch_9), + scratch(pmc_scratch10, scratch_10), + scratch(pmc_scratch11, scratch_11), + scratch(pmc_scratch12, scratch_12), + scratch(pmc_scratch13, scratch_13), + scratch(pmc_scratch14, scratch_14), + scratch(pmc_scratch15, scratch_15), + scratch(pmc_scratch16, scratch_16), + scratch(pmc_scratch17, scratch_17), + scratch(pmc_scratch18, scratch_18), + scratch(pmc_scratch19, scratch_19), + scratch(pmc_scratch22, scratch_22), + scratch(pmc_scratch23, scratch_23), + scratch(pmc_scratch24, scratch_24), + scratch(pmc_scratch25, scratch_25), + scratch(pmc_scratch26, scratch_26), + scratch(pmc_scratch27, scratch_27), + scratch(pmc_scratch28, scratch_28), + scratch(pmc_scratch29, scratch_29), + scratch(pmc_scratch30, scratch_30), + scratch(pmc_scratch31, scratch_31), + scratch(pmc_scratch32, scratch_32), + scratch(pmc_scratch33, scratch_33), + scratch(pmc_scratch40, scratch_40), + scratch(pmc_scratch42, scratch_42), + scratch(pmc_scratch44, scratch_44), + scratch(pmc_scratch45, scratch_45), + scratch(pmc_scratch46, scratch_46), + scratch(pmc_scratch47, scratch_47), + scratch(pmc_scratch48, scratch_48), +}; + +static const struct pmc_scratch_reg scratch_lpddr2[] = { + scratch(pmc_scratch5, scratch_5_lpddr2), + scratch(pmc_scratch6, scratch_6_lpddr2), + scratch(pmc_scratch7, scratch_7_lpddr2), +}; + +void set_scratches(struct pmc_scratch_reg scratches, struct sdram_params *sdram) +{ + u32 j, scratch_off; + u32 reg = 0; + struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + + for (j = 0; j < scratches.num_fields; j++) { + const struct pmc_scratch_field *field = &scratches.fields[j]; + u32 val, offset, type; + + offset = field->offset_val; + type = field->field_type; + + switch (type) { + case TYPE_SDRAM: + val = readl((char *)sdram + offset); + break; + case TYPE_PLLX: + val = + readl((char *)&clkrst->crc_pll_simple[CLOCK_ID_XCPU] + + offset); + break; + case TYPE_CONST: + val = offset; + break; + default: + continue; + } + val >>= field->shift_src; + val &= field->mask; + val <<= field->shift_dst; + reg |= val; + } + + scratch_off = scratches.scratch_off; + writel(reg, NV_PA_PMC_BASE + scratch_off); +} + +void warmboot_save_sdram_params(void) +{ + u32 ram_code; + struct sdram_params sdram; + struct pmux_tri_ctlr *pmt = (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + u32 reg, i; + + /* get ram code that is used as index to array _params in BCT */ + reg = readl(&pmt->pmt_strap_opt_a) >> (0 ? STRAP_OPT_A_RAM_CODE_RANGE); + ram_code = reg & 3; + + memcpy(&sdram, + (char *)((struct sdram_params *)SDRAM_PARAMS_BASE + ram_code), + sizeof(sdram)); + + for (i = 0; i < ARRAY_SIZE(scratch); i++) + set_scratches(scratch[i], &sdram); + + if (sdram.memory_type == MEMORY_TYPE_LPDDR2) { + for (i = 0; i < ARRAY_SIZE(scratch_lpddr2); i++) + set_scratches(scratch_lpddr2[i], &sdram); + } + + writel(0xffffffff, &pmc->pmc_scratch2); + + setbits_le32(&pmc->pmc_pllp_wb0_override, PLLM_OVERRIDE_ENABLE); +} diff --git a/arch/arm/cpu/armv7/tegra3/warmboot_avp.c b/arch/arm/cpu/armv7/tegra3/warmboot_avp.c new file mode 100644 index 00000000000..02772d42c16 --- /dev/null +++ b/arch/arm/cpu/armv7/tegra3/warmboot_avp.c @@ -0,0 +1,410 @@ +/* + * (C) Copyright 2010 - 2012 + * NVIDIA Corporation <www.nvidia.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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; either version 2 of + * the License, or (at your option) any later version. + * + * 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 <common.h> +#include <asm/io.h> + +#include <asm/arch-tegra/clk_rst.h> +#include <asm/arch-tegra/pmc.h> +#include <asm/arch-tegra/flow.h> +#include <asm/arch-tegra/ap20.h> +#include <asm/arch-tegra/power.h> +#include <asm/arch/ahb.h> +#include <asm/arch-tegra/warmboot.h> +#include <asm/arch-tegra/warmboot_avp.h> +#include <asm/arch/clock.h> +#include <asm/arch/pinmux.h> +#include <asm/arch/tegra.h> +#include <asm/arch/sdmmc.h> + +#define RESET_CORESIGHT + +void wb_start(void) +{ + struct pmux_tri_ctlr *pmt = (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE; + struct sdmmc_ctlr *sdmmc4 = (struct sdmmc_ctlr *)NV_PA_SDMMC4_BASE; + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + struct ahb_ctlr *ahb = (struct ahb_ctlr *)TEGRA2_AHB_BASE; + struct clk_pll *pllp = &clkrst->crc_pll[CLOCK_ID_PERIPH]; + u32 reg, saved_reg; + u32 divm, divn; + u32 cpcon, lfcon; + u32 base, misc; + u32 status_mask, toggle, clamp; + u32 internal_periph_id; + + /* enable JTAG & TBE */ + writel(CONFIG_CTL_TBE | CONFIG_CTL_JTAG, &pmt->pmt_cfg_ctl); + + /* Are we running where we're supposed to be? */ + asm volatile ( + "adr %0, wb_start;" /* reg: wb_start address */ + : "=r"(reg) /* output */ + /* no input, no clobber list */ + ); + + if (reg != AP20_WB_RUN_ADDRESS) + goto do_reset; + + /* Are we running with AVP? */ + if (readl(NV_PA_PG_UP_BASE + PG_UP_TAG_0) != PG_UP_TAG_AVP) + goto do_reset; + + /* + * Save the current setting for CLK_BURST_POLICY and change clock + * source to CLKM + */ + saved_reg = readl(&clkrst->crc_sclk_brst_pol); + + reg = SCLK_SWAKE_FIQ_SRC_CLKM | SCLK_SWAKE_IRQ_SRC_CLKM | + SCLK_SWAKE_RUN_SRC_CLKM | SCLK_SWAKE_IDLE_SRC_CLKM | + SCLK_SYS_STATE_RUN; + writel(reg, &clkrst->crc_sclk_brst_pol); + + /* Update PLLP output dividers for 408 MHz operation */ + /* Set OUT1 to 9.6MHz and OUT2 to 48MHz (based on 408MHz of PLLP) */ + writel(PLLP_408_OUTA, &pllp->pll_out); + + writel(PLLP_408_OUTB, &pllp->pll_out_b); + + /* Set oscillator the drive strength */ + reg = readl(&clkrst->crc_osc_ctrl); + reg &= ~(OSC_CTRL_XOE | OSC_CTRL_XOFS); + reg |= OSC_CTRL_XOE_ENABLE | OSC_CTRL_XOFS_4; + writel(reg, &clkrst->crc_osc_ctrl); + + /* Set CPCON and enable PLLP lock bit */ + writel(PLLP_MISC_PLLP_CPCON_8 | PLLP_MISC_PLLP_LOCK_ENABLE, + &pllp->pll_misc); + + /* Find out the current osc frequency */ + reg = readl(&clkrst->crc_osc_ctrl); + + /* Find out the PLLP_BASE value to use */ + + /* + * Note: can not use switch statement: compiler builds tables on the + * local stack. We don't want to use anything on the stack. + */ + reg >>= OSC_CTRL_OSC_FREQ_SHIFT; + if ((reg == OSC_FREQ_OSC12) || (reg == OSC_FREQ_OSC48)) { + divm = 0x0c; + divn = 0x198; + } else if (reg == OSC_FREQ_OSC16P8) { + divm = 0x0e; + divn = 0x154; + } else if ((reg == OSC_FREQ_OSC19P2) || (reg == OSC_FREQ_OSC38P4)) { + divm = 0x10; + divn = 0x154; + } else if (reg == OSC_FREQ_OSC26) { + divm = 0x1a; + divn = 0x198; + } else { + /* + * Unused code in OSC_FREQ is mapped to 13MHz - use 13MHz as + * default settings. + */ + divm = 0x0d; + divn = 0x198; + } + + /* Change PLLP to be 408MHz */ + reg = (divm << PLLP_BASE_PLLP_DIVM_SHIFT) | + (divn << PLLP_BASE_PLLP_DIVN_SHIFT) | + PLLP_BASE_OVRRIDE_ENABLE | + PLLP_BASE_PLLP_ENABLE; + writel(reg, &pllp->pll_base); + + /* Wait till PLLP locks */ + while (1) { + reg = readl(&pllp->pll_base); + if (reg & PLLP_BASE_PLLP_LOCK_LOCK) + break; + } + + /* + * Wait for 250uS after lock bit is set to make sure pll is stable. + * The typical wait time is 300uS. Since we already check the lock + * bit, reduce the wait time to 250uS. + */ + reg = EVENT_ZERO_VAL_250 | EVENT_USEC | EVENT_MODE_STOP; + writel(reg, &flow->halt_cop_events); + + /* Restore setting for SCLK_BURST_POLICY */ + writel(saved_reg, &clkrst->crc_sclk_brst_pol); + + /* + * Enable the PPSB_STOPCLK feature to allow SCLK to be run at + * higher frequencies. See bug 811773. + */ + reg = readl(&clkrst->crc_misc_clk_enb); + reg |= MISC_CLK_ENB_EN_PPSB_STOPCLK_ENABLE; + writel(reg, &clkrst->crc_misc_clk_enb); + + reg = readl(&ahb->arbitration_xbar_ctrl); + reg |= ARBITRATION_XBAR_CTRL_PPSB_ENABLE_ENABLE; + writel(reg, &ahb->arbitration_xbar_ctrl); + +#ifdef RESET_CORESIGHT + /* Assert CoreSight reset */ + writel(SWR_CSITE_RST, &clkrst->crc_rst_dev_ex[TEGRA_DEV_U].set); +#endif + + /* + * Halt the G complex CPUs at the flow controller in case the G + * complex was running in a uni-processor configuration. + */ + writel(EVENT_MODE_STOP, &flow->halt_cpu_events); + writel(EVENT_MODE_STOP, &flow->halt_cpu1_events); + writel(EVENT_MODE_STOP, &flow->halt_cpu2_events); + writel(EVENT_MODE_STOP, &flow->halt_cpu3_events); + + /* + * Find out which CPU (LP or G) to wake up. The default setting + * in flow controller is to wake up GCPU. + * + * Select the LP CPU cluster. All accesses to the cluster-dependent + * CPU registers (legacy clock enables, resets, burst policy, flow + * controller) now refer to the LP CPU. + */ + reg = readl(&pmc->pmc_scratch4); + reg &= CPU_WAKEUP_CLUSTER; + if (reg) + setbits_le32(&flow->cluster_control, ACTIVE_LP); + + /* Hold all CPUs in reset. */ + reg = CPU_CMPLX_CPURESET0 | CPU_CMPLX_CPURESET1 | + CPU_CMPLX_CPURESET2 | CPU_CMPLX_CPURESET3 | + CPU_CMPLX_DERESET0 | CPU_CMPLX_DERESET1 | + CPU_CMPLX_DERESET2 | CPU_CMPLX_DERESET3 | + CPU_CMPLX_DBGRESET0 | CPU_CMPLX_DBGRESET1 | + CPU_CMPLX_DBGRESET2 | CPU_CMPLX_DBGRESET3; + writel(reg, &clkrst->crc_cpu_cmplx_set); + + /* Assert CPU complex reset. */ + reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_L]); + reg |= CPU_RST; + writel(reg, &clkrst->crc_rst_dev[TEGRA_DEV_L]); + + /* Program SUPER_CCLK_DIVIDER */ + writel(SUPER_CDIV_ENB, &clkrst->crc_super_cclk_div); + + /* Stop the clock to all CPUs. */ + reg = SET_CPU0_CLK_STP | SET_CPU1_CLK_STP | SET_CPU2_CLK_STP | + SET_CPU3_CLK_STP; + writel(reg, &clkrst->crc_clk_cpu_cmplx_set); + + /* Make sure the resets are held for at least 2 microseconds. */ + reg = readl(TIMER_USEC_CNTR); + while ((int)(readl(TIMER_USEC_CNTR) - reg) < 3) + {} + + writel(CLK_ENB_CSITE, &clkrst->crc_clk_enb_ex[TEGRA_DEV_U].set); + + /* De-assert CoreSight reset */ + writel(SWR_CSITE_RST, &clkrst->crc_rst_dev_ex[TEGRA_DEV_U].clr); + + /* Unlock debugger access. */ + writel(0xC5ACCE55, CSITE_CPU_DBG0_LAR); + + /* Find out the current osc frequency */ + reg = readl(&clkrst->crc_osc_ctrl); + reg >>= OSC_CTRL_OSC_FREQ_SHIFT; + if ((reg == OSC_FREQ_OSC12) || (reg == OSC_FREQ_OSC48)) { + divm = 0x0c; + divn = 0x3c0; + cpcon = 0x0c; + lfcon = 0x01; + } else if (reg == OSC_FREQ_OSC16P8) { + divm = 0x07; + divn = 0x190; + cpcon = 0x05; + lfcon = 0x00; + } else if ((reg == OSC_FREQ_OSC19P2) || (reg == OSC_FREQ_OSC38P4)) { + divm = 0x04; + divn = 0xc8; + cpcon = 0x03; + lfcon = 0x00; + } else if (reg == OSC_FREQ_OSC26) { + divm = 0x1a; + divn = 0x3c0; + cpcon = 0x0c; + lfcon = 0x01; + } else { + /* + * Unused code in OSC_FREQ is mapped to 13MHz - use 13MHz as + * default settings. + */ + divm = 0x0d; + divn = 0x3c0; + cpcon = 0x0c; + lfcon = 0x01; + } + + base = PLLU_BYPASS_ENABLE | (divn << 8) | (divm << 0); + writel(base, &clkrst->crc_pll[CLOCK_ID_USB].pll_base); + misc = (cpcon << 8) | (lfcon << 4); + writel(misc, &clkrst->crc_pll[CLOCK_ID_USB].pll_misc); + + base &= ~PLLU_BYPASS_ENABLE; + base |= PLLU_ENABLE; + writel(base, &clkrst->crc_pll[CLOCK_ID_USB].pll_base); + misc |= PLLU_LOCK_ENABLE; + writel(misc, &clkrst->crc_pll[CLOCK_ID_USB].pll_misc); + + /* + * Reenable eMMC boot block write protection + * 1. Enable SDMMC4 clock (it's OK to leave it on the default clock + * source, CLK_M, since only one register will be written). + * 2. Take SDMMC4 controller out of reset. + * 3. Set SDMMC4_VENDOR_CLOCK_CNTRL_0_HW_RSTN_OVERRIDE. + * 4. Restore SDMMC4 reset state. + * 5. Stop the clock to SDMMC4 controller. + */ + writel(SET_CLK_ENB_SDMMC4, &clkrst->crc_clk_enb_ex[TEGRA_DEV_L].set); + + saved_reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_L]); + reg = CLR_SDMMC4_RST_ENABLE; + writel(reg, &clkrst->crc_rst_dev_ex[TEGRA_DEV_L].clr); + + reg = readl(sdmmc4->vendor_clk_cntrl); + reg |= HW_RSTN_OVERRIDE_OVERRIDE; + writel(reg, &sdmmc4->vendor_clk_cntrl); + + writel(saved_reg, &clkrst->crc_rst_dev[TEGRA_DEV_L]); + + writel(CLR_CLK_ENB_SDMMC4_ENABLE, + &clkrst->crc_clk_enb_ex[TEGRA_DEV_L].clr); + + /* + * Set the CPU reset vector. SCRATCH41 contains the physical + * address of the CPU-side restoration code. + */ + reg = readl(&pmc->pmc_scratch41); + writel(reg, EXCEP_VECTOR_CPU_RESET_VECTOR); + + /* Select CPU complex clock source */ + writel(CCLK_PLLP_BURST_POLICY, &clkrst->crc_cclk_brst_pol); + + /* Enable CPU0 clock */ + reg = CPU_CMPLX_CLR_CPU0_CLK_STP; + writel(reg, &clkrst->crc_clk_cpu_cmplx_clr); + + /* Enable the CPU complex clock */ + writel(CLK_ENB_CPU, &clkrst->crc_clk_enb_ex[TEGRA_DEV_L].set); + + /* Set MSELECT clock source to PLL_P */ + reg = MSELECT_CLK_SRC_PLLP_OUT0; + internal_periph_id = 1; + writel(reg, &clkrst->crc_clk_src_vw[internal_periph_id]); + + /* Enable clock to MSELECT */ + writel(SET_CLK_ENB_MSELECT, + &clkrst->crc_clk_enb_ex_vw[TEGRA_DEV_V].set); + + /* Bring MSELECT out of reset */ + writel(SET_MSELECT_RST_ENABLE, + &clkrst->crc_rst_dev_ex_vw[TEGRA_DEV_V].clr); + + /* + * Find out which CPU (LP or G) to power on + * Power up the CPU0 partition if necessary. + * status_mask: bit mask for CPU enable in APBDEV_PMC_PWRGATE_STATUS_0 + * toggle: value to power on cpu + * clamp: value to remove clamping to CPU + */ + reg = readl(&pmc->pmc_scratch4); + if (reg & CPU_WAKEUP_CLUSTER) { + /* + * Setup registers for powering up LPCPU + * - PWRGATE_STATUS, A9LP + * - PWRGATE_TOGGLE, PARTID, A9LP , START, ENABLE + * - REMOVE_CLAMPING_CMD, A9LP, ENABLE + */ + status_mask = PWRGATE_STATUS_A9LP_ENABLE; + toggle = PWRGATE_TOGGLE_START | PWRGATE_TOGGLE_PARTID_A9LP; + clamp = REMOVE_CLAMPING_CMD_A9LP_ENABLE; + } else { + /* + * Setup registers for powering up GCPU + * - PWRGATE_STATUS, CPU + * - PWRGATE_TOGGLE, PARTID, CP , START, ENABLE + * - REMOVE_CLAMPING_CMD, CPU, ENABLE + */ + status_mask = PWRGATE_STATUS_CPU_ENABLE; + toggle = PWRGATE_TOGGLE_START | PWRGATE_TOGGLE_PARTID_CP; + clamp = REMOVE_CLAMPING_CMD_CPU_ENABLE; + } + + reg = readl(&pmc->pmc_pwrgate_status); + if (!(reg & status_mask)) + writel(toggle, &pmc->pmc_pwrgate_toggle); + + while (!(readl(&pmc->pmc_pwrgate_status) & status_mask)) + {} + + /* Remove the I/O clamps from the CPU0 power partition. */ + writel(clamp, &pmc->pmc_remove_clamping); + + /* Give I/O signals 20ms to stabilize. */ + writel(EVENT_ZERO_VAL_20 | EVENT_MSEC | EVENT_MODE_STOP, + &flow->halt_cop_events); + + /* Take CPU0 out of reset. */ + writel(CPU_CMPLX_CPURESET0 | CPU_CMPLX_DERESET0 | CPU_CMPLX_DBGRESET0, + &clkrst->crc_cpu_cmplx_clr); + + /* De-assert CPU complex reset. */ + writel(CPU_RST, &clkrst->crc_rst_dev_ex[TEGRA_DEV_L].clr); + + /* Unhalt the CPU at the flow controller. */ + writel(0, &flow->halt_cpu_events); + + /* avp_resume: no return after the write */ + reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_L]); + reg &= ~CPU_RST; + writel(reg, &clkrst->crc_rst_dev[TEGRA_DEV_L]); + + /* avp_halt: */ + while (1) + writel(EVENT_MODE_STOP | EVENT_JTAG, &flow->halt_cop_events); + +do_reset: + /* + * Execution comes here if something goes wrong. The chip is reset and + * a cold boot is performed. + */ + while (1) + writel(SWR_TRIG_SYS_RST, &clkrst->crc_rst_dev[TEGRA_DEV_L]); +} + +/* + * wb_end() is a dummy function, and must be directly following wb_start(), + * and is used to calculate the size of wb_start(). + */ +void wb_end(void) +{ +}
\ No newline at end of file diff --git a/arch/arm/include/asm/arch-tegra/clk_rst.h b/arch/arm/include/asm/arch-tegra/clk_rst.h index 0c36fbb6388..6bf9cb61314 100644 --- a/arch/arm/include/asm/arch-tegra/clk_rst.h +++ b/arch/arm/include/asm/arch-tegra/clk_rst.h @@ -1,5 +1,5 @@ /* - * (C) Copyright 2010,2011 + * (C) Copyright 2010-2012 * NVIDIA Corporation <www.nvidia.com> * * See file CREDITS for list of people who contributed to this @@ -267,6 +267,117 @@ enum { #define UTMIP_FORCE_PD_SAMP_B_POWERDOWN_RANGE 2:2 #define UTMIP_FORCE_PD_SAMP_A_POWERUP_RANGE 1:1 #define UTMIP_FORCE_PD_SAMP_A_POWERDOWN_RANGE 0:0 + +/* CRC_CCLK_BURST_POLICY_0 20h */ +#define CCLK_PLLP_BURST_POLICY 0x20004444 + +/* CRC_SUPER_CCLK_DIVIDER_0 24h */ +#define SUPER_CDIV_ENB (1 << 31) + +/* CRC_SCLK_BURST_POLICY_0 28h */ +#define SCLK_SYS_STATE_RUN (2 << 28) +#define SCLK_SWAKE_FIQ_SRC_CLKM (0 << 12) +#define SCLK_SWAKE_IRQ_SRC_CLKM (0 << 8) +#define SCLK_SWAKE_RUN_SRC_CLKM (0 << 4) +#define SCLK_SWAKE_IDLE_SRC_CLKM (0 << 0) + +/* CRC_CLK_CPU_CMPLX_CLR_0 34ch */ +#define CPU_CMPLX_CLR_CPU0_CLK_STP (1 << 8) + +/* CRC_MISC_CLK_ENN_0 48h */ +#define MISC_CLK_ENB_EN_PPSB_STOPCLK_ENABLE (1 << 0) + +/* CRC_OSC_CTRL_0 50h */ +#define OSC_CTRL_XOE (1 << 0) +#define OSC_CTRL_XOE_ENABLE (1 << 0) +#define OSC_CTRL_XOFS (0x3f << 4) +#define OSC_CTRL_XOFS_4 (0x4 << 4) +#define OSC_CTRL_OSC_FREQ_SHIFT 28 +#define OSC_FREQ_OSC19P2 4 /* 19.2MHz */ +#define OSC_FREQ_OSC12 8 /* 12.0MHz */ +#define OSC_FREQ_OSC26 12 /* 26.0MHz */ +#define OSC_FREQ_OSC16P8 1 /* 16.8MHz */ +#define OSC_FREQ_OSC38P4 5 /* 38.4MHz */ +#define OSC_FREQ_OSC48 9 /* 48.0MHz */ + +/* CRC_PLLP_BASE_0 a0h */ +#define PLLP_BASE_PLLP_DIVM_SHIFT 0 +#define PLLP_BASE_PLLP_DIVN_SHIFT 8 +#define PLLP_BASE_PLLP_LOCK_LOCK (1 << 27) +#define PLLP_BASE_OVRRIDE_ENABLE (1 << 28) +#define PLLP_BASE_PLLP_ENABLE (1 << 30) + +/* CRC_PLLP_OUTA_0 a4h */ +#define PLLP_OUTA_OUT1_RSTN_RESET_DISABLE (1 << 0) +#define PLLP_OUTA_OUT1_CLKEN (1 << 1) +#define PLLP_OUTA_OUT1_OVRRIDE (1 << 2) +#define PLLP_OUTA_OUT1_RATIO_83 (83 << 8) +#define PLLP_OUTA_OUT2_RSTN_RESET_DISABLE (1 << 16) +#define PLLP_OUTA_OUT2_CLKEN (1 << 17) +#define PLLP_OUTA_OUT2_OVRRIDE (1 << 18) +#define PLLP_OUTA_OUT2_RATIO_15 (15 << 24) +#define PLLP_408_OUTA (PLLP_OUTA_OUT2_RATIO_15 | \ + PLLP_OUTA_OUT2_OVRRIDE | \ + PLLP_OUTA_OUT2_CLKEN | \ + PLLP_OUTA_OUT2_RSTN_RESET_DISABLE | \ + PLLP_OUTA_OUT1_RATIO_83 | \ + PLLP_OUTA_OUT1_OVRRIDE | \ + PLLP_OUTA_OUT1_CLKEN | \ + PLLP_OUTA_OUT1_RSTN_RESET_DISABLE) + +/* CRC_PLLP_OUTB_0 a8h */ +#define PLLP_OUTA_OUT3_RSTN_RESET_DISABLE (1 << 0) +#define PLLP_OUTA_OUT3_CLKEN (1 << 1) +#define PLLP_OUTA_OUT3_OVRRIDE (1 << 2) +#define PLLP_OUTA_OUT3_RATIO_6 (6 << 8) +#define PLLP_OUTA_OUT4_RSTN_RESET_DISABLE (1 << 16) +#define PLLP_OUTA_OUT4_CLKEN (1 << 17) +#define PLLP_OUTA_OUT4_OVRRIDE (1 << 18) +#define PLLP_OUTA_OUT4_RATIO_6 (6 << 24) +#define PLLP_408_OUTB (PLLP_OUTA_OUT4_RATIO_6 | \ + PLLP_OUTA_OUT4_OVRRIDE | \ + PLLP_OUTA_OUT4_CLKEN | \ + PLLP_OUTA_OUT4_RSTN_RESET_DISABLE | \ + PLLP_OUTA_OUT3_RATIO_6 | \ + PLLP_OUTA_OUT3_OVRRIDE | \ + PLLP_OUTA_OUT3_CLKEN | \ + PLLP_OUTA_OUT3_RSTN_RESET_DISABLE) + +/* CRC_PLLP_MISC_0 ach */ +#define PLLP_MISC_PLLP_CPCON_8 (8 << 8) +#define PLLP_MISC_PLLP_LOCK_ENABLE (1 << 18) + +/* CRC_PLLU_BASE_0 c0h */ +#define PLLU_BYPASS_ENABLE (1 << 31) +#define PLLU_ENABLE (1 << 30) + +/* CRC_PLLU_MISC_0 cch */ +#define PLLU_LOCK_ENABLE (1 << 22) + +/* CRC_RST_DEV_L_CLR_0 304h */ +#define CLR_SDMMC4_RST_ENABLE (1 << 15) + +/* CRC_CLK_ENB_L_SET_0 320h */ +#define SET_CLK_ENB_SDMMC4 (1 << 15) + +/* CRC_CLK_ENB_L_CLR_0 324h */ +#define CLR_CLK_ENB_SDMMC4_ENABLE (1 << 15) + +/* CRC_CLK_CPU_CMPLX_SET_0 348h */ +#define SET_CPU0_CLK_STP (1 << 8) +#define SET_CPU1_CLK_STP (1 << 9) +#define SET_CPU2_CLK_STP (1 << 10) +#define SET_CPU3_CLK_STP (1 << 11) + +/* CRC_CLK_SOURCE_MSELECT_0 3b4 */ +#define MSELECT_CLK_SRC_PLLP_OUT0 (0 << 30) + +/* CRC_RST_DEV_V_SET_0 430h */ +#define SET_MSELECT_RST_ENABLE (1 << 3) + +/* CRC_CLK_ENB_V_SET_0 440h */ +#define SET_CLK_ENB_MSELECT (1 << 3) + #endif /* Tegra3 */ #endif /* CLK_RST_H */ diff --git a/arch/arm/include/asm/arch-tegra/pmc.h b/arch/arm/include/asm/arch-tegra/pmc.h index 9d1a0a81751..3f837798adb 100644 --- a/arch/arm/include/asm/arch-tegra/pmc.h +++ b/arch/arm/include/asm/arch-tegra/pmc.h @@ -1,5 +1,5 @@ /* - * (C) Copyright 2010,2011 + * (C) Copyright 2010-2012 * NVIDIA Corporation <www.nvidia.com> * * See file CREDITS for list of people who contributed to this @@ -132,6 +132,8 @@ struct pmc_ctlr { #endif }; +#define PLLM_OVERRIDE_ENABLE (1 << 11) + #define PWRGATE_ENABLE 0x100 #define CPU_PWRED 1 diff --git a/arch/arm/include/asm/arch-tegra/warmboot_avp.h b/arch/arm/include/asm/arch-tegra/warmboot_avp.h index 3b568e9d02f..afb9bf521d5 100644 --- a/arch/arm/include/asm/arch-tegra/warmboot_avp.h +++ b/arch/arm/include/asm/arch-tegra/warmboot_avp.h @@ -1,5 +1,5 @@ /* - * (C) Copyright 2010, 2011 + * (C) Copyright 2010-2012 * NVIDIA Corporation <www.nvidia.com> * * See file CREDITS for list of people who contributed to this @@ -27,6 +27,7 @@ #define TEGRA_DEV_L 0 #define TEGRA_DEV_H 1 #define TEGRA_DEV_U 2 +#define TEGRA_DEV_V 0 #define SIMPLE_PLLX (CLOCK_ID_XCPU - CLOCK_ID_FIRST_SIMPLE) #define SIMPLE_PLLE (CLOCK_ID_EPCI - CLOCK_ID_FIRST_SIMPLE) @@ -43,6 +44,7 @@ #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) #define PWRGATE_STATUS_CPU (1 << 0) #define PWRGATE_TOGGLE_PARTID_CPU (0 << 0) @@ -61,6 +63,15 @@ #define CPU_CMPLX_DBGRESET0 (1 << 12) #define CPU_CMPLX_DBGRESET1 (1 << 13) +#if defined(CONFIG_TEGRA3) +#define CPU_CMPLX_CPURESET2 (1 << 2) +#define CPU_CMPLX_CPURESET3 (1 << 3) +#define CPU_CMPLX_DERESET2 (1 << 6) +#define CPU_CMPLX_DERESET3 (1 << 7) +#define CPU_CMPLX_DBGRESET2 (1 << 14) +#define CPU_CMPLX_DBGRESET3 (1 << 15) +#endif + #define PLLM_OUT1_RSTN_RESET_DISABLE (1 << 0) #define PLLM_OUT1_CLKEN_ENABLE (1 << 1) #define PLLM_OUT1_RATIO_VAL_8 (8 << 8) @@ -72,11 +83,40 @@ #define SCLK_SWAKE_IDLE_SRC_PLLM_OUT1 (7 << 0) #define EVENT_ZERO_VAL_20 (20 << 0) +#define EVENT_ZERO_VAL_250 (250 << 0) #define EVENT_MSEC (1 << 24) +#define EVENT_USEC (1 << 25) #define EVENT_JTAG (1 << 28) #define EVENT_MODE_STOP (2 << 29) #define CCLK_PLLP_BURST_POLICY 0x20004444 +#if defined(CONFIG_TEGRA3) +/* FLOW_CTLR_CLUSTER_CONTROL_0 2ch */ +#define ACTIVE_LP (1 << 0) + +/* AHB_ARBITRATION_XBAR_CTRL_0 e0h */ +#define ARBITRATION_XBAR_CTRL_PPSB_ENABLE_ENABLE (1 << 2) + +/* SDMMC_VENDOR_CLOCK_CNTRL_0 100h */ +#define HW_RSTN_OVERRIDE_OVERRIDE (1 << 4) + +/* APBDEV_PMC_PWRGATE_TOGGLE_0 30h */ +#define PWRGATE_TOGGLE_PARTID_CP (0 << 0) +#define PWRGATE_TOGGLE_PARTID_A9LP (12 << 0) +#define PWRGATE_TOGGLE_START (1 << 8) + +/* APBDEV_PMC_REMOVE_CLAMPING_CMD_0 34h */ +#define REMOVE_CLAMPING_CMD_CPU_ENABLE (1 << 0) +#define REMOVE_CLAMPING_CMD_A9LP_ENABLE (1 << 12) + +/* APBDEV_PMC_PWRGATE_STATUS_0 38 */ +#define PWRGATE_STATUS_CPU_ENABLE (1 << 0) +#define PWRGATE_STATUS_A9LP_ENABLE (1 << 12) + +#define CPU_WAKEUP_CLUSTER (1 << 31) + +#endif + #endif diff --git a/include/configs/tegra3-common.h b/include/configs/tegra3-common.h index 3a5f234930b..ea391c19009 100644 --- a/include/configs/tegra3-common.h +++ b/include/configs/tegra3-common.h @@ -1,5 +1,5 @@ /* - * (C) Copyright 2010,2011 + * (C) Copyright 2010-2012 * NVIDIA Corporation <www.nvidia.com> * * See file CREDITS for list of people who contributed to this @@ -80,6 +80,15 @@ #define CONFIG_SYS_NO_FLASH +#ifdef CONFIG_TEGRA3_WARMBOOT +#define TEGRA_LP0_ADDR 0x9C406000 +#define TEGRA_LP0_SIZE SZ_8K +#define TEGRA_LP0_VEC \ + "lp0_vec=" QUOTE(TEGRA_LP0_SIZE) "@" QUOTE(TEGRA_LP0_ADDR) " " +#else +#define TEGRA_LP0_VEC +#endif + #define CONFIG_LOADADDR 0x80408000 /* def. location for kernel */ #define CONFIG_BOOTDELAY 3 /* -1 to disable auto boot */ #define CONFIG_ZERO_BOOTDELAY_CHECK |