diff options
29 files changed, 2874 insertions, 8 deletions
@@ -964,6 +964,7 @@ The following options need to be configured: CONFIG_CMD_BEDBUG * Include BedBug Debugger CONFIG_CMD_BMP * BMP support CONFIG_CMD_BSP * Board specific commands + CONFIG_CMD_BOOTAI * Android bootimg support CONFIG_CMD_BOOTD bootd CONFIG_CMD_BOOTI * ARM64 Linux kernel Image support CONFIG_CMD_CACHE * icache, dcache diff --git a/arch/arm/cpu/tegra-common/Makefile b/arch/arm/cpu/tegra-common/Makefile index a18c318739..0ba12738a7 100644 --- a/arch/arm/cpu/tegra-common/Makefile +++ b/arch/arm/cpu/tegra-common/Makefile @@ -11,7 +11,10 @@ obj-y += ap.o obj-y += board.o obj-y += cache.o obj-y += clock.o +obj-$(CONFIG_TEGRA_LP0) += crypto.o obj-y += lowlevel_init.o obj-y += pinmux-common.o obj-$(CONFIG_DISPLAY_CPUINFO) += sys_info.o obj-$(CONFIG_TEGRA124) += vpr.o +obj-$(CONFIG_TEGRA124_LP0) += t1x4_warmboot.o + diff --git a/arch/arm/cpu/tegra-common/crypto.c b/arch/arm/cpu/tegra-common/crypto.c new file mode 100644 index 0000000000..5f0b240e27 --- /dev/null +++ b/arch/arm/cpu/tegra-common/crypto.c @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * (C) Copyright 2010 - 2011 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/errno.h> +#include "crypto.h" +#include "aes.h" + +static u8 zero_key[16]; + +#define AES_CMAC_CONST_RB 0x87 /* from RFC 4493, Figure 2.2 */ + +enum security_op { + SECURITY_SIGN = 1 << 0, /* Sign the data */ + SECURITY_ENCRYPT = 1 << 1, /* Encrypt the data */ +}; + +static void debug_print_vector(char *name, u32 num_bytes, u8 *data) +{ + u32 i; + + debug("%s [%d] @0x%08x", name, num_bytes, (u32)data); + for (i = 0; i < num_bytes; i++) { + if (i % 16 == 0) + debug(" = "); + debug("%02x", data[i]); + if ((i+1) % 16 != 0) + debug(" "); + } + debug("\n"); +} + +/** + * Apply chain data to the destination using EOR + * + * Each array is of length AES_AES_KEY_LENGTH. + * + * \param cbc_chain_data Chain data + * \param src Source data + * \param dst Destination data, which is modified here + */ +static void apply_cbc_chain_data(u8 *cbc_chain_data, u8 *src, u8 *dst) +{ + int i; + + for (i = 0; i < 16; i++) + *dst++ = *src++ ^ *cbc_chain_data++; +} + +/** + * Encrypt some data with AES. + * + * \param key_schedule Expanded key to use + * \param src Source data to encrypt + * \param dst Destination buffer + * \param num_aes_blocks Number of AES blocks to encrypt + */ +static void encrypt_object(u8 *key_schedule, u8 *src, u8 *dst, + u32 num_aes_blocks) +{ + u8 tmp_data[AES_KEY_LENGTH]; + u8 *cbc_chain_data; + u32 i; + + cbc_chain_data = zero_key; /* Convenient array of 0's for IV */ + + for (i = 0; i < num_aes_blocks; i++) { + debug("encrypt_object: block %d of %d\n", i, num_aes_blocks); + debug_print_vector("AES Src", AES_KEY_LENGTH, src); + + /* Apply the chain data */ + apply_cbc_chain_data(cbc_chain_data, src, tmp_data); + debug_print_vector("AES Xor", AES_KEY_LENGTH, tmp_data); + + /* encrypt the AES block */ + aes_encrypt(tmp_data, key_schedule, dst); + debug_print_vector("AES Dst", AES_KEY_LENGTH, dst); + + /* Update pointers for next loop. */ + cbc_chain_data = dst; + src += AES_KEY_LENGTH; + dst += AES_KEY_LENGTH; + } +} + +/** + * Shift a vector left by one bit + * + * \param in Input vector + * \param out Output vector + * \param size Length of vector in bytes + */ +static void left_shift_vector(u8 *in, u8 *out, int size) +{ + int carry = 0; + int i; + + for (i = size - 1; i >= 0; i--) { + out[i] = (in[i] << 1) | carry; + carry = in[i] >> 7; /* get most significant bit */ + } +} + +/** + * Sign a block of data, putting the result into dst. + * + * \param key Input AES key, length AES_KEY_LENGTH + * \param key_schedule Expanded key to use + * \param src Source data of length 'num_aes_blocks' blocks + * \param dst Destination buffer, length AES_KEY_LENGTH + * \param num_aes_blocks Number of AES blocks to encrypt + */ +static void sign_object(u8 *key, u8 *key_schedule, u8 *src, u8 *dst, + u32 num_aes_blocks) +{ + u8 tmp_data[AES_KEY_LENGTH]; + u8 left[AES_KEY_LENGTH]; + u8 k1[AES_KEY_LENGTH]; + u8 *cbc_chain_data; + unsigned i; + + cbc_chain_data = zero_key; /* Convenient array of 0's for IV */ + + /* compute K1 constant needed by AES-CMAC calculation */ + for (i = 0; i < AES_KEY_LENGTH; i++) + tmp_data[i] = 0; + + encrypt_object(key_schedule, tmp_data, left, 1); + debug_print_vector("AES(key, nonce)", AES_KEY_LENGTH, left); + + left_shift_vector(left, k1, sizeof(left)); + debug_print_vector("L", AES_KEY_LENGTH, left); + + if ((left[0] >> 7) != 0) /* get MSB of L */ + k1[AES_KEY_LENGTH-1] ^= AES_CMAC_CONST_RB; + debug_print_vector("K1", AES_KEY_LENGTH, k1); + + /* compute the AES-CMAC value */ + for (i = 0; i < num_aes_blocks; i++) { + /* Apply the chain data */ + apply_cbc_chain_data(cbc_chain_data, src, tmp_data); + + /* for the final block, XOR K1 into the IV */ + if (i == num_aes_blocks - 1) + apply_cbc_chain_data(tmp_data, k1, tmp_data); + + /* encrypt the AES block */ + aes_encrypt(tmp_data, key_schedule, dst); + + debug("sign_obj: block %d of %d\n", i, num_aes_blocks); + debug_print_vector("AES-CMAC Src", AES_KEY_LENGTH, src); + debug_print_vector("AES-CMAC Xor", AES_KEY_LENGTH, tmp_data); + debug_print_vector("AES-CMAC Dst", AES_KEY_LENGTH, dst); + + /* Update pointers for next loop. */ + cbc_chain_data = dst; + src += AES_KEY_LENGTH; + } + + debug_print_vector("AES-CMAC Hash", AES_KEY_LENGTH, dst); +} + +/** + * Encrypt and sign a block of data (depending on security mode). + * + * \param key Input AES key, length AES_KEY_LENGTH + * \param oper Security operations mask to perform (enum security_op) + * \param src Source data + * \param length Size of source data + * \param sig_dst Destination address for signature, AES_KEY_LENGTH bytes + */ +static int encrypt_and_sign(u8 *key, enum security_op oper, u8 *src, + u32 length, u8 *sig_dst) +{ + u32 num_aes_blocks; + u8 key_schedule[AES_EXPAND_KEY_LENGTH]; + + debug("encrypt_and_sign: length = %d\n", length); + debug_print_vector("AES key", AES_KEY_LENGTH, key); + + /* + * The only need for a key is for signing/checksum purposes, so + * if not encrypting, expand a key of 0s. + */ + aes_expand_key(oper & SECURITY_ENCRYPT ? key : zero_key, key_schedule); + + num_aes_blocks = (length + AES_KEY_LENGTH - 1) / AES_KEY_LENGTH; + + if (oper & SECURITY_ENCRYPT) { + /* Perform this in place, resulting in src being encrypted. */ + debug("encrypt_and_sign: begin encryption\n"); + encrypt_object(key_schedule, src, src, num_aes_blocks); + debug("encrypt_and_sign: end encryption\n"); + } + + if (oper & SECURITY_SIGN) { + /* encrypt the data, overwriting the result in signature. */ + debug("encrypt_and_sign: begin signing\n"); + sign_object(key, key_schedule, src, sig_dst, num_aes_blocks); + debug("encrypt_and_sign: end signing\n"); + } + + return 0; +} + +int sign_data_block(u8 *source, unsigned length, u8 *signature) +{ + return encrypt_and_sign(zero_key, SECURITY_SIGN, source, + length, signature); +} diff --git a/arch/arm/cpu/tegra-common/crypto.h b/arch/arm/cpu/tegra-common/crypto.h new file mode 100644 index 0000000000..aff67e77b0 --- /dev/null +++ b/arch/arm/cpu/tegra-common/crypto.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * (C) Copyright 2010 - 2011 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 + */ + +#ifndef _CRYPTO_H_ +#define _CRYPTO_H_ + +/** + * Sign a block of data + * + * \param source Source data + * \param length Size of source data + * \param signature Destination address for signature, AES_KEY_LENGTH bytes + */ +int sign_data_block(u8 *source, unsigned length, u8 *signature); + +#endif /* #ifndef _CRYPTO_H_ */ diff --git a/arch/arm/cpu/tegra-common/t1x4_warmboot.c b/arch/arm/cpu/tegra-common/t1x4_warmboot.c new file mode 100644 index 0000000000..049fb0383f --- /dev/null +++ b/arch/arm/cpu/tegra-common/t1x4_warmboot.c @@ -0,0 +1,407 @@ +/* + * 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 <http://www.gnu.org/licenses/>. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/errno.h> +#include <asm/arch-tegra/ap.h> +#include <asm/arch-tegra/clk_rst.h> +#include <asm/arch/clock.h> +#include <asm/arch-tegra/pmc.h> +#include <asm/arch/pinmux.h> +#include <asm/arch/tegra.h> +#include <asm/arch-tegra/fuse.h> +#include <asm/arch/gp_padctrl.h> +#include <asm/arch-tegra/warmboot.h> +#include <asm/arch-tegra/sdram_param.h> +#include <asm/arch/wb_param.h> + +/* + * do_encode(): + * + * sdram->dst.dst_bit = (sdram->src.op1_bits > sdram->src.op2_bits); + * where src, dst, dst_bit, op1_bits, op2_bits are specified in encode_fields. + * + * @param encode pointer to struct encode_fields to specify all needed + * fields to do encoding + * @param sdram pointer to struct sdram_params for SDRAM parameters + */ +void do_encode(struct encode_fields *encode, struct sdram_params *sdram) +{ + u32 val, op1, op2; + + val = readl((char *)sdram + encode->src_offset); + debug("%s: sdram[%#x] => %#x\n", __func__, encode->src_offset, val); + op1 = val >> encode->op1_shift; + op1 &= encode->op1_mask; + op2 = val >> encode->op2_shift; + op2 &= encode->op2_mask; + + val = readl((char *)sdram + encode->dst_offset); + val &= ~(1 << encode->dst_shift); + if (op1 > op2) + val |= (1 << encode->dst_shift); + debug("%s: sdram[%#x] <= %#x\n", __func__, encode->dst_offset, val); + writel(val, (char *)sdram + encode->dst_offset); +} + +/* + * do_encode_list(): call do_encode() for each encode in encode_list + * + * @param encode_list pointer to struct encode_fields which contains list of + * pointers of encode + * @param num_list # of pointers of struct encode_fields in encode_list + * @param sdram pointer to struct sdram_params for SDRAM parameters + */ +void do_encode_list(struct encode_fields *encode_list, u32 num_list, + struct sdram_params *sdram) +{ + struct encode_fields *encode; + u32 i; + + for (i = 0, encode = encode_list; i < num_list; ++i, ++encode) + do_encode(encode, sdram); +} + +/* + * do_pack(): + * + * PMC.dst_offset.dst_bits = src_type.src_offset.src_bits; + * + * src_type, src_offset, src_bits, dst_offset, and dst_bits are specified + * in pack_fields. + * + * src_type can be SDRAM, PLLM registers, or CONSTant. + * The destination is always PMC registers. + * + * @param pack pointer to struct pack_fields to specify all needed + * fields to do packing + * @param sdram pointer to struct sdram_params for SDRAM parameters + */ +void do_pack(struct pack_fields *pack, struct sdram_params *sdram) +{ + u32 val, offset, type, reg; + struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + + offset = pack->src_offset; + type = pack->src_type; + + switch (type) { + case TYPE_SDRAM: + val = readl((char *)sdram + offset); + break; + case TYPE_PLLM: + val = readl((char *)&clkrst->crc_pll[CLOCK_ID_MEMORY] + + offset); + break; + case TYPE_CONST: + val = offset; + break; + default: + debug("src_type (%u) is not supported\n", type); + return; + } + + val >>= pack->src_shift; + val &= pack->src_mask; + val <<= pack->dst_shift; + + reg = readl(NV_PA_PMC_BASE + pack->dst_offset); + reg &= ~(pack->dst_mask << pack->dst_shift); + reg |= val; + writel(reg, NV_PA_PMC_BASE + pack->dst_offset); +} + +/* + * do_pack_list() : call do_pack() for each pack in pack_list. + * + * @param pack_list pointer to struct pack_fields which contains list of + * pointers of pack + * @param num_list # of pointers of struct pack_fields in pack_list + * @param sdram pointer to struct sdram_params for SDRAM parameters + */ +void do_pack_list(struct pack_fields *pack_list, u32 num_list, + struct sdram_params *sdram) +{ + struct pack_fields *pack; + u32 i; + + for (pack = pack_list, i = 0; i < num_list; ++i, ++pack) + do_pack(pack, sdram); +} + +/* + * t1x4_wb_save_sdram_params(): + * + * save sdram parameters to scratch registers so sdram parameters can be + * restored when system resumes from LP0. + * + * common routine for both T114 and T124 SOCs, but based on each SOC's + * encode_list and pack_lists (defined in wb_param.h) + * + * @param sdram pointer to struct sdram_params for SDRAM parameters + * @return 0 always + */ +int t1x4_wb_save_sdram_params(struct sdram_params *sdram) +{ + /* encode BIT6_GT_BIT7 bits in sdram.swizzle_rank_byte_encode */ + do_encode_list(encode_list, ARRAY_SIZE(encode_list), sdram); + + do_pack_list(pack_list_1, ARRAY_SIZE(pack_list_1), sdram); + + if (sdram->memory_type == MEMORY_TYPE_LPDDR2) + do_pack_list(pack_list_lpddr2, ARRAY_SIZE(pack_list_lpddr2), + sdram); + else if (sdram->memory_type == MEMORY_TYPE_DDR3) + do_pack_list(pack_list_ddr3, ARRAY_SIZE(pack_list_ddr3), + sdram); + + do_pack_list(pack_list_2, ARRAY_SIZE(pack_list_2), sdram); + + return 0; +} + +/* + * NOTE: If more than one of the following is enabled, only one of them will + * actually be used. RANDOM takes precedence over PATTERN and ZERO, and + * PATTERN takes precedence overy ZERO. + * + * RANDOM_AES_BLOCK_IS_PATTERN is to define a 32-bit PATTERN. + */ +#undef RANDOM_AES_BLOCK_IS_RANDOM /* to randomize the header */ +#undef RANDOM_AES_BLOCK_IS_PATTERN /* to patternize the header */ +#define RANDOM_AES_BLOCK_IS_ZERO /* to clear the header */ + +static u32 get_major_version(void) +{ + u32 major_id; + struct apb_misc_gp_ctlr *gp = + (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE; + + major_id = (readl(&gp->hidrev) & HIDREV_MAJORPREV_MASK) >> + HIDREV_MAJORPREV_SHIFT; + return major_id; +} + +static int is_production_mode_fuse_set(struct fuse_regs *fuse) +{ + return readl(&fuse->production_mode); +} + +static int is_odm_production_mode_fuse_set(struct fuse_regs *fuse) +{ + return readl(&fuse->security_mode); +} + +static int is_failure_analysis_mode(struct fuse_regs *fuse) +{ + return readl(&fuse->fa); +} + +static int is_odm_production_mode(void) +{ + struct fuse_regs *fuse = (struct fuse_regs *)NV_PA_FUSE_BASE; + + if (!is_failure_analysis_mode(fuse) && + is_odm_production_mode_fuse_set(fuse)) + return 1; + else + return 0; +} + +static int is_production_mode(void) +{ + struct fuse_regs *fuse = (struct fuse_regs *)NV_PA_FUSE_BASE; + + if (get_major_version() == 0) + return 1; + + if (!is_failure_analysis_mode(fuse) && + is_production_mode_fuse_set(fuse) && + !is_odm_production_mode_fuse_set(fuse)) + return 1; + else + return 0; +} + +static enum fuse_operating_mode fuse_get_operation_mode(u32 tegra_id) +{ + u32 chip_id; + struct apb_misc_gp_ctlr *gp = + (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE; + + chip_id = readl(&gp->hidrev); + chip_id = (chip_id & HIDREV_CHIPID_MASK) >> HIDREV_CHIPID_SHIFT; + if (chip_id == tegra_id) { + if (is_odm_production_mode()) { + printf("!! odm_production_mode is not supported !!\n"); + return MODE_UNDEFINED; + } else { + if (is_production_mode()) + return MODE_PRODUCTION; + else + return MODE_PREPRODUCTION; + } + } + return MODE_UNDEFINED; +} + +#if defined(RANDOM_AES_BLOCK_IS_RANDOM) +/* Currently, this routine returns a 32-bit all 0 seed. */ +static u32 query_random_seed(void) +{ + return 0; +} +#endif + +static void determine_crypto_options(u32 tegra_id, int *is_encrypted, + int *is_signed, int *use_zero_key) +{ + switch (fuse_get_operation_mode(tegra_id)) { + case MODE_PREPRODUCTION: + case MODE_PRODUCTION: + *is_encrypted = 0; + *is_signed = 1; + *use_zero_key = 1; + break; + case MODE_UNDEFINED: + default: + *is_encrypted = 0; + *is_signed = 0; + *use_zero_key = 0; + break; + } +} + +static int sign_wb_code(u32 start, u32 length, int use_zero_key) +{ + int err; + u8 *source; /* Pointer to source */ + u8 *hash; + + /* Calculate AES block parameters. */ + source = (u8 *)(start + offsetof(struct wb_header, random_aes_block)); + length -= offsetof(struct wb_header, random_aes_block); + hash = (u8 *)(start + offsetof(struct wb_header, hash_signature.hash)); + err = sign_data_block(source, length, hash); + + return err; +} + +/* + * t1x4_wb_prepare_code(): + * + * prepare WB code, which will be executed by AVP when system resumes from LP0. + * + * common routine for both T114 and T124 SOCs, except the caller must pass the + * T114 or T124 chip ID for checking. + * + * @param tegra_id SOC ID: CHIPID_TEGRA114 or CHIPID_TEGRA124 + * @param seg_address address where the WB code to be stored + * @param seg_length # of bytes allocated to store the WB code + * @return 0 if success + * !0 (error code) if failed + */ +int t1x4_wb_prepare_code(u32 tegra_id, u32 seg_address, u32 seg_length) +{ + int err = 0; + u32 length; /* length of the signed/encrypt code */ + struct wb_header *dst_header; /* Pointer to dest WB header */ + int is_encrypted; /* Segment is encrypted */ + int is_signed; /* Segment is signed */ + int use_zero_key; /* Use key of all zeros */ + + /* Determine crypto options. */ + determine_crypto_options(tegra_id, &is_encrypted, &is_signed, + &use_zero_key); + + /* Get the actual code limits. */ + length = roundup(((u32)wb_end - (u32)wb_start), 16); + + /* + * The region specified by seg_address must not be in IRAM and must be + * nonzero in length. + */ + if ((seg_length == 0) || (seg_address == 0) || + ((seg_address >= NV_PA_BASE_SRAM) && + (seg_address < (NV_PA_BASE_SRAM + NV_PA_BASE_SRAM_SIZE)))) { + err = -EFAULT; + goto fail; + } + + /* Things must be 16-byte aligned. */ + if ((seg_length & 0xF) || (seg_address & 0xF)) { + err = -EINVAL; + goto fail; + } + + /* Will the code fit? (destination includes wb_header + wb code) */ + if (seg_length < (length + sizeof(struct wb_header))) { + err = -EINVAL; + goto fail; + } + + dst_header = (struct wb_header *)seg_address; + memset((char *)dst_header, 0, sizeof(struct wb_header)); + + /* Populate the random_aes_block as requested. */ + { + u32 *aes_block = (u32 *)&(dst_header->random_aes_block); + u32 *end = (u32 *)(((u32)aes_block) + + sizeof(dst_header->random_aes_block)); + + do { +#if defined(RANDOM_AES_BLOCK_IS_RANDOM) + *aes_block++ = query_random_seed(); +#elif defined(RANDOM_AES_BLOCK_IS_PATTERN) + *aes_block++ = RANDOM_AES_BLOCK_IS_PATTERN; +#elif defined(RANDOM_AES_BLOCK_IS_ZERO) + *aes_block++ = 0; +#else + printf("None of RANDOM_AES_BLOCK_IS_XXX is defined; "); + printf("Default to pattern 0.\n"); + *aes_block++ = 0; +#endif + } while (aes_block < end); + } + + /* Populate the header. */ + dst_header->length_insecure = length + sizeof(struct wb_header); + dst_header->length_secure = length + sizeof(struct wb_header); + dst_header->destination = NV_WB_RUN_ADDRESS; + dst_header->entry_point = NV_WB_RUN_ADDRESS; + dst_header->code_length = length; + + if (is_encrypted) { + printf("!!!! Encryption is not supported !!!!\n"); + dst_header->length_insecure = 0; + err = -EACCES; + goto fail; + } else { + /* copy the wb code directly following dst_header. */ + memcpy((char *)(dst_header+1), (char *)wb_start, length); + } + + if (is_signed) + err = sign_wb_code(seg_address, dst_header->length_insecure, + use_zero_key); + +fail: + if (err) + printf("WB code not copied to LP0 location! (error=%d)\n", err); + + return err; +} diff --git a/arch/arm/cpu/tegra124-common/Makefile b/arch/arm/cpu/tegra124-common/Makefile index ff77992b33..4e8cfc5947 100644 --- a/arch/arm/cpu/tegra124-common/Makefile +++ b/arch/arm/cpu/tegra124-common/Makefile @@ -5,6 +5,11 @@ # SPDX-License-Identifier: GPL-2.0+ # +# The AVP is ARMv4T architecture so we must use special compiler +# flags for any startup files it might use. +CFLAGS_warmboot_avp.o += -march=armv4t + obj-y += clock.o obj-y += funcmux.o obj-y += pinmux.o +obj-$(CONFIG_TEGRA_LP0) += warmboot.o warmboot_avp.o diff --git a/arch/arm/cpu/tegra124-common/warmboot.c b/arch/arm/cpu/tegra124-common/warmboot.c new file mode 100644 index 0000000000..fa10f5888b --- /dev/null +++ b/arch/arm/cpu/tegra124-common/warmboot.c @@ -0,0 +1,48 @@ +/* + * 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 <http://www.gnu.org/licenses/>. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch-tegra/ap.h> +#include <asm/arch/gp_padctrl.h> +#include <asm/arch/clock.h> +#include <asm/arch-tegra/pmc.h> +#include <asm/arch-tegra/warmboot.h> +#include <asm/arch-tegra/sdram_param.h> + +int warmboot_save_sdram_params(void) +{ + u32 ram_code; + struct sdram_params sdram; + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + + /* get ram code that is used as index to array _params in BCT */ + ram_code = (readl(&pmc->pmc_strap_opt_a) & STRAP_OPT_A_RAM_CODE_MASK) + >> STRAP_OPT_A_RAM_CODE_SHIFT; + /* ram_code[1:0] selects SDRAM configuration set within the BCT */ + ram_code &= 3; + + memcpy(&sdram, + (char *)((struct sdram_params *)SDRAM_PARAMS_BASE + ram_code), + sizeof(sdram)); + + return t1x4_wb_save_sdram_params(&sdram); +} + +int warmboot_prepare_code(u32 seg_address, u32 seg_length) +{ + return t1x4_wb_prepare_code(CHIPID_TEGRA124, seg_address, seg_length); +} diff --git a/arch/arm/cpu/tegra124-common/warmboot_avp.c b/arch/arm/cpu/tegra124-common/warmboot_avp.c new file mode 100644 index 0000000000..bde67eb784 --- /dev/null +++ b/arch/arm/cpu/tegra124-common/warmboot_avp.c @@ -0,0 +1,374 @@ +/* + * 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 <http://www.gnu.org/licenses/>. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch-tegra/ap.h> +#include <asm/arch-tegra124/mc.h> +#include <asm/arch-tegra/clk_rst.h> +#include <asm/arch/clock.h> +#include <asm/arch-tegra/pmc.h> +#include <asm/arch/tegra.h> +#include <asm/arch/flow.h> +#include <asm/arch-tegra/warmboot.h> +#include <asm/arch/sysctr.h> +#include "warmboot_avp.h" + +void wb_start(void) +{ + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE; + struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + struct sysctr_ctlr *sysctr = (struct sysctr_ctlr *)NV_PA_TSC_BASE; + struct mc_ctlr *mc = (struct mc_ctlr *)NV_PA_MC_BASE; + u32 reg; + u32 reg_1; + u32 reg_saved; + u32 divm; + u32 divn; + u32 cpcon, lfcon; + + /* 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 != NV_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; + + /* + * Read oscillator drive strength from OSC_EDPD_OVER.XOFS and copy + * to OSC_CTRL.XOFS and set XOE + */ + reg = readl(&pmc->pmc_osc_edpd_over); + reg &= PMC_XOFS_MASK; + reg >>= PMC_XOFS_SHIFT; + + reg_1 = readl(&clkrst->crc_osc_ctrl); + reg_1 &= ~(OSC_XOE_MASK | OSC_XOFS_MASK); + + reg <<= OSC_XOFS_SHIFT; + reg |= OSC_XOE_ENABLE; + reg |= reg_1; + writel(reg, &clkrst->crc_osc_ctrl); + + /* + * Find out which CPU (slow or fast) to wake up. The default setting + * in flow controller is to wake up GCPU + */ + reg = readl(&pmc->pmc_scratch4); + if (reg & CPU_WAKEUP_CLUSTER) { + reg = readl(&flow->cluster_control); + reg |= ACTIVE_LP; + writel(reg, &flow->cluster_control); + } + + /* Program SUPER_CCLK_DIVIDER */ + reg = SUPER_CDIV_ENB_ENABLE; + writel(reg, &clkrst->crc_super_cclk_div); + + /* Enable the CoreSight clock */ + reg = CLK_ENB_CSITE; + writel(reg, &clkrst->crc_clk_enb_ex[TEGRA_DEV_U].set); + + /* + * De-assert CoreSight reset. + * NOTE: We're leaving the CoreSight clock on the oscillator for + * now. It will be restored to its original clock source + * when the CPU-side restoration code runs. + */ + reg = SWR_CSITE_RST; + writel(reg, &clkrst->crc_rst_dev_ex[TEGRA_DEV_U].clr); + + /* Find out the current osc frequency */ + reg = readl(&clkrst->crc_osc_ctrl); + reg >>= OSC_CTRL_OSC_FREQ_SHIFT; + + /* Find out the PLL-U value to use */ + if ((reg == OSC_FREQ_OSC12) || (reg == OSC_FREQ_OSC48)) { + divm = 0x0c; + divn = 0x3c0; + cpcon = 0x0c; + lfcon = 0x02; + } else if (reg == OSC_FREQ_OSC16P8) { + divm = 0x07; + divn = 0x190; + cpcon = 0x05; + lfcon = 0x02; + } else if ((reg == OSC_FREQ_OSC19P2) || (reg == OSC_FREQ_OSC38P4)) { + divm = 0x04; + divn = 0xc8; + cpcon = 0x03; + lfcon = 0x02; + } else if (reg == OSC_FREQ_OSC26) { + divm = 0x1a; + divn = 0x3c0; + cpcon = 0x0c; + lfcon = 0x02; + } else { + /* + * Unused code in OSC_FREQ is mapped to 13MHz - use 13MHz as + * default settings. + */ + divm = 0x0d; + divn = 0x3c0; + cpcon = 0x0c; + lfcon = 0x02; + } + + /* Program PLL-U */ + reg = PLLU_BYPASS_ENABLE | PLLU_OVERRIDE_ENABLE | (divn << 8) | + (divm << 0); + writel(reg, &clkrst->crc_pll[CLOCK_ID_USB].pll_base); + reg_1 = (cpcon << 8) | (lfcon << 4); + writel(reg_1, &clkrst->crc_pll[CLOCK_ID_USB].pll_misc); + + /* Enable PLL-U */ + reg &= ~PLLU_BYPASS_ENABLE; + reg |= PLLU_ENABLE_ENABLE; + writel(reg, &clkrst->crc_pll[CLOCK_ID_USB].pll_base); + reg_1 |= PLLU_LOCK_ENABLE_ENABLE; + writel(reg_1, &clkrst->crc_pll[CLOCK_ID_USB].pll_misc); + + /* + * Set the CPU reset vector. pmc_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); + + /* Set MSELECT clock source to PLL_P with 1:4 divider */ + reg = MSELECT_CLK_SRC_PLLP_OUT0 | MSELECT_CLK_DIVISOR_6; + writel(reg, + &clkrst->crc_clk_src_vw[PERIPHC_MSELECT - PERIPHC_VW_FIRST]); + + /* Enable clock to MSELECT */ + reg = SET_CLK_ENB_MSELECT_ENABLE; + writel(reg, &clkrst->crc_clk_enb_ex_vw[TEGRA_DEV_V].set); + + /* Bring MSELECT out of reset, after 2 microsecond wait */ + reg = readl(NV_PA_TMRUS_BASE); + while (1) { + if (readl(NV_PA_TMRUS_BASE) > (reg + 2)) + break; + } + + reg = SET_CLK_ENB_MSELECT_ENABLE; + writel(reg, &clkrst->crc_rst_dev_ex_vw[TEGRA_DEV_V].clr); + + /* Disable PLLX, since it is not used as CPU clock source */ + reg = readl(&clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base); + reg &= ~(PLLX_BASE_PLLX_ENABLE); + writel(reg, &clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base); + + /* Set CAR2PMC_CPU_ACK_WIDTH to 408 */ + reg = readl(&clkrst->crc_cpu_softrst_ctrl2); + reg |= CAR2PMC_CPU_ACK_WIDTH_408; + writel(reg, &clkrst->crc_cpu_softrst_ctrl2); + + /* Enable the CPU complex clock */ + reg = CLK_ENB_CPU; + writel(reg, &clkrst->crc_clk_enb_ex[TEGRA_DEV_L].set); + + reg = SET_CLK_ENB_CPUG_ENABLE | SET_CLK_ENB_CPULP_ENABLE; + writel(reg, &clkrst->crc_clk_enb_ex_vw[TEGRA_DEV_V].set); + + /* Take non-cpu of G and LP cluster OUT of reset */ + reg = CLR_NONCPURESET; + writel(reg, &clkrst->crc_rst_cpulp_cmplx_clr); + writel(reg, &clkrst->crc_rst_cpug_cmplx_clr); + + /* Clear software controlled reset of slow cluster */ + reg = CLR_CPURESET0 | CLR_DBGRESET0 | CLR_CORERESET0 | CLR_CXRESET0; + writel(reg, &clkrst->crc_rst_cpulp_cmplx_clr); + + /* Clear software controlled reset of fast cluster */ + reg = CLR_CPURESET0 | CLR_DBGRESET0 | CLR_CORERESET0 | CLR_CXRESET0 | + CLR_CPURESET1 | CLR_DBGRESET1 | CLR_CORERESET1 | CLR_CXRESET1 | + CLR_CPURESET2 | CLR_DBGRESET2 | CLR_CORERESET2 | CLR_CXRESET2 | + CLR_CPURESET3 | CLR_DBGRESET3 | CLR_CORERESET3 | CLR_CXRESET3; + writel(reg, &clkrst->crc_rst_cpug_cmplx_clr); + + /* Initialize System Counter (TSC) with osc frequency */ + /* Find out the current osc frequency */ + reg = readl(&clkrst->crc_osc_ctrl); + reg >>= OSC_CTRL_OSC_FREQ_SHIFT; + + if (reg == OSC_FREQ_OSC12) + reg_1 = 12000000; + else if (reg == OSC_FREQ_OSC48) + reg_1 = 48000000; + else if (reg == OSC_FREQ_OSC16P8) + reg_1 = 16800000; + else if (reg == OSC_FREQ_OSC19P2) + reg_1 = 19200000; + else if (reg == OSC_FREQ_OSC38P4) + reg_1 = 38400000; + else if (reg == OSC_FREQ_OSC26) + reg_1 = 26000000; + else + reg_1 = 13000000; + + /* write frequency (in reg_1) to SYSCTR0_CNTFID0 */ + writel(reg_1, &sysctr->cntfid0); + /* enable the TSC */ + reg = readl(&sysctr->cntcr); + reg |= TSC_CNTCR_ENABLE | TSC_CNTCR_HDBG; + writel(reg, &sysctr->cntcr); + + /* disable VPR */ + writel(0x00000000, &mc->mc_video_protect_size_mb); + writel(0x00000001, &mc->mc_video_protect_reg_ctrl); + /* read them back to make sure write operation completed */ + reg = readl(&mc->mc_video_protect_size_mb); + reg = readl(&mc->mc_video_protect_reg_ctrl); + + /* + * Reprogram PMC_CPUPWRGOOD_TIMER register: + * + * Kernel prepares PMC_CPUPWRGOOD_TIMER based on 32768Hz clock. + * Note that PMC_CPUPWRGOOD_TIMER is running at pclk. + * + * Need to reprogram PMC_CPUPWRGOOD_TIMER based on the current pclk, + * which is @408Mhz (pclk = sclk = pllp_out0) after reset. + * + * So, just multiply a factor = (408M/32K) to PMC_CPUPWRGOOD_TIMER. + * + * Save the original PMC_CPUPWRGOOD_TIMER register, need to restore + * it after CPU is powered up. + */ + reg = readl(&pmc->pmc_cpupwrgood_timer); + reg_saved = reg; + + reg *= (408000000 / 32768); + writel(reg, &pmc->pmc_cpupwrgood_timer); + + /* Find out which cluster (slow or fast) to power on */ + reg = readl(&pmc->pmc_scratch4); + if (reg & CPU_WAKEUP_CLUSTER) { + /* Power up the slow cluster non-CPU partition. */ + reg = PWRGATE_STATUS_C1NC_ENABLE; + reg_1 = PWRGATE_TOGGLE_PARTID_C1NC | PWRGATE_TOGGLE_START; + if (!(readl(&pmc->pmc_pwrgate_status) & reg)) { + /* partition is not on, turn it on */ + writel(reg_1, &pmc->pmc_pwrgate_toggle); + + /* wait until the partition is powered on */ + while (!(readl(&pmc->pmc_pwrgate_status) & reg)) + ; + + /* wait until clamp is off */ + while (readl(&pmc->pmc_clamp_status) & reg) + ; + } + + reg = PWRGATE_STATUS_CELP_ENABLE; + reg_1 = PWRGATE_TOGGLE_PARTID_CELP | PWRGATE_TOGGLE_START; + if (!(readl(&pmc->pmc_pwrgate_status) & reg)) { + /* partition is not on, turn it on */ + writel(reg_1, &pmc->pmc_pwrgate_toggle); + + /* wait until the partition is powered on */ + while (!(readl(&pmc->pmc_pwrgate_status) & reg)) + ; + + /* wait until clamp is off */ + while (readl(&pmc->pmc_clamp_status) & reg) + ; + } + } else { + /* FastCPU */ + reg = PWRGATE_STATUS_CRAIL_ENABLE; + reg_1 = PWRGATE_TOGGLE_PARTID_CRAIL | PWRGATE_TOGGLE_START; + if (!(readl(&pmc->pmc_pwrgate_status) & reg)) { + /* partition is not on, turn it on */ + writel(reg_1, &pmc->pmc_pwrgate_toggle); + + /* wait until the partition is powered on */ + while (!(readl(&pmc->pmc_pwrgate_status) & reg)) + ; + + /* wait until clamp is off */ + while (readl(&pmc->pmc_clamp_status) & reg) + ; + } + + reg = PWRGATE_STATUS_C0NC_ENABLE; + reg_1 = PWRGATE_TOGGLE_PARTID_C0NC | PWRGATE_TOGGLE_START; + if (!(readl(&pmc->pmc_pwrgate_status) & reg)) { + /* partition is not on, turn it on */ + writel(reg_1, &pmc->pmc_pwrgate_toggle); + + /* wait until the partition is powered on */ + while (!(readl(&pmc->pmc_pwrgate_status) & reg)) + ; + + /* wait until clamp is off */ + while (readl(&pmc->pmc_clamp_status) & reg) + ; + } + + reg = PWRGATE_STATUS_CE0_ENABLE; + reg_1 = PWRGATE_TOGGLE_PARTID_CE0 | PWRGATE_TOGGLE_START; + if (!(readl(&pmc->pmc_pwrgate_status) & reg)) { + /* partition is not on, turn it on */ + writel(reg_1, &pmc->pmc_pwrgate_toggle); + + /* wait until the partition is powered on */ + while (!(readl(&pmc->pmc_pwrgate_status) & reg)) + ; + + /* wait until clamp is off */ + while (readl(&pmc->pmc_clamp_status) & reg) + ; + } + } + + /* give I/O signals time to stable */ + reg = 20 | EVENT_MSEC | EVENT_MODE_STOP; + writel(reg, &flow->halt_cop_events); + + /* restore the original PMC_CPUPWRGOOD_TIMER register */ + writel(reg_saved, &pmc->pmc_cpupwrgood_timer); + +avp_halt: + reg = EVENT_MODE_STOP | EVENT_JTAG; + writel(reg, &flow->halt_cop_events); + goto avp_halt; + +do_reset: + writel(SWR_TRIG_SYS_RST, &clkrst->crc_rst_dev[TEGRA_DEV_L]); + + while (1) + ; +} + +/* + * 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) +{ +} diff --git a/arch/arm/cpu/tegra124-common/warmboot_avp.h b/arch/arm/cpu/tegra124-common/warmboot_avp.h new file mode 100644 index 0000000000..05ce949718 --- /dev/null +++ b/arch/arm/cpu/tegra124-common/warmboot_avp.h @@ -0,0 +1,32 @@ +/* + * 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 <http://www.gnu.org/licenses/>. + */ + +#ifndef _TEGRA124_WARMBOOT_AVP_H_ +#define _TEGRA124_WARMBOOT_AVP_H_ + +/* CRC_CCLK_BURST_POLICY_0 0x20 */ +#define CCLK_PLLP_BURST_POLICY 0x20004444 + +/* CRC_CLK_SOURCE_MSELECT_0, 0x3b4 */ +#define MSELECT_CLK_DIVISOR_6 6 + +/* PMC_SCRATCH4 bit 31 defines which Cluster suspends (1 = LP Cluster) */ +#define CPU_WAKEUP_CLUSTER (1 << 31) + +/* CPU_SOFTRST_CTRL2_0, 0x388 */ +#define CAR2PMC_CPU_ACK_WIDTH_408 408 + +#endif /* _TEGRA124_WARMBOOT_AVP_H_ */ diff --git a/arch/arm/include/asm/arch-tegra/ap.h b/arch/arm/include/asm/arch-tegra/ap.h index 5c8be94d97..7c04461dce 100644 --- a/arch/arm/include/asm/arch-tegra/ap.h +++ b/arch/arm/include/asm/arch-tegra/ap.h @@ -28,6 +28,7 @@ /* AP base physical address of internal SRAM */ #define NV_PA_BASE_SRAM 0x40000000 +#define NV_PA_BASE_SRAM_SIZE 0x20000 #define EXCEP_VECTOR_CPU_RESET_VECTOR (NV_PA_EVP_BASE + 0x100) #define CSITE_CPU_DBG0_LAR (NV_PA_CSITE_BASE + 0x10FB0) diff --git a/arch/arm/include/asm/arch-tegra/clk_rst.h b/arch/arm/include/asm/arch-tegra/clk_rst.h index 7d28e16f1c..b92f728c3d 100644 --- a/arch/arm/include/asm/arch-tegra/clk_rst.h +++ b/arch/arm/include/asm/arch-tegra/clk_rst.h @@ -208,6 +208,26 @@ struct clk_rst_ctlr { uint crc_clk_src_x[TEGRA_CLK_SOURCES_X]; /* XUSB, etc, 0x600-0x678 */ }; +#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 */ #define CPU3_CLK_STP_SHIFT 11 #define CPU2_CLK_STP_SHIFT 10 @@ -215,6 +235,17 @@ struct clk_rst_ctlr { #define CPU0_CLK_STP_SHIFT 8 #define CPU0_CLK_STP_MASK (1U << CPU0_CLK_STP_SHIFT) +/* CRC_OSC_CTRL_0 0x50 */ +#define OSC_CTRL_OSC_FREQ (0xf << 28) +#define OSC_CTRL_OSC_FREQ_SHIFT 28 +#define OSC_FREQ_OSC13 0 /* 13.0MHz */ +#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 */ + /* CLK_RST_CONTROLLER_PLLx_BASE_0 */ #define PLL_BYPASS_SHIFT 31 #define PLL_BYPASS_MASK (1U << PLL_BYPASS_SHIFT) @@ -290,6 +321,26 @@ enum { #define PLLP_OUT4_RSTN_EN (0 << 16) #define PLLP_OUT4_CLKEN (1 << 17) +/* CRC_PLLP_MISC_0 0xac */ +#define PLLP_MISC_PLLP_CPCON_8 (8 << 8) +#define PLLP_MISC_PLLP_LOCK_ENABLE (1 << 18) + +/* CRC_PLLU_BASE_0 0xc0 */ +#define PLLU_BYPASS_ENABLE (1 << 31) +#define PLLU_ENABLE_ENABLE (1 << 30) +#define PLLU_REF_DIS_REF_DISABLE (1 << 29) +#define PLLU_OVERRIDE_ENABLE (1 << 24) + +/* CRC_PLLU_MISC_0 0xcc */ +#define PLLU_LOCK_ENABLE_ENABLE (1 << 22) + +/* 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) + /* CLK_RST_CONTROLLER_UTMIP_PLL_CFG1_0 */ #define PLLU_POWERDOWN (1 << 16) #define PLL_ENABLE_POWERDOWN (1 << 14) diff --git a/arch/arm/include/asm/arch-tegra/sdram_param.h b/arch/arm/include/asm/arch-tegra/sdram_param.h new file mode 100644 index 0000000000..fd115bcefc --- /dev/null +++ b/arch/arm/include/asm/arch-tegra/sdram_param.h @@ -0,0 +1,344 @@ +/* + * 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 <http://www.gnu.org/licenses/>. + */ + +#ifndef _TEGRA124_SDRAM_PARAM_H_ +#define _TEGRA124_SDRAM_PARAM_H_ + +/* define SDRAM parameters offset in BCT */ +#define BCT_SDRAM_PARAMS_OFFSET 0x8f8 +#define SDRAM_PARAMS_BASE (NV_PA_BASE_SRAM + BCT_SDRAM_PARAMS_OFFSET) + +enum memory_type { + MEMORY_TYPE_NONE = 0, + MEMORY_TYPE_LPDDR2, + MEMORY_TYPE_DDR3, +}; + +/** + * Defines the SDRAM parameter structure + */ +struct sdram_params { + enum memory_type memory_type; + u32 pllm_input_divider; + u32 pllm_feedback_divider; + u32 pllm_stable_time; + u32 pllm_setup_control; + u32 pllm_select_div2; + u32 pllm_pdl_shift_ph45; + u32 pllm_pdl_shift_ph90; + u32 pllm_pdl_shift_ph135; + u32 pllm_kcp; + u32 pllm_kvco; + u32 emc_bct_spare0; + u32 emc_bct_spare1; + u32 emc_bct_spare2; + u32 emc_bct_spare3; + u32 emc_bct_spare4; + u32 emc_bct_spare5; + u32 emc_bct_spare6; + u32 emc_bct_spare7; + u32 emc_bct_spare8; + u32 emc_bct_spare9; + u32 emc_bct_spare10; + u32 emc_bct_spare11; + u32 emc_clock_source; + u32 emc_auto_cal_interval; + u32 emc_auto_cal_config; + u32 emc_auto_cal_config2; + u32 emc_auto_cal_config3; + u32 emc_auto_cal_wait; + u32 emc_adr_cfg; + u32 emc_pin_program_wait; + u32 emc_pin_extra_wait; + u32 emc_timing_control_wait; + u32 emc_rc; + u32 emc_rfc; + u32 emc_rfc_slr; + u32 emc_ras; + u32 emc_rp; + u32 emc_r2r; + u32 emc_w2w; + u32 emc_r2w; + u32 emc_w2r; + u32 emc_r2p; + u32 emc_w2p; + u32 emc_rd_rcd; + u32 emc_wr_rcd; + u32 emc_rdr; + u32 emc_rext; + u32 emc_wext; + u32 emc_wdv; + u32 emc_wdv_mask; + u32 emc_quse; + u32 emc_quse_width; + u32 emc_ibdly; + u32 emc_einput; + u32 emc_einput_duration; + u32 emc_puterm_extra; + u32 emc_puterm_width; + u32 emc_puterm_adj; + u32 emc_cdb_cntl1; + u32 emc_cdb_cntl2; + u32 emc_cdb_cntl3; + u32 emc_qrst; + u32 emc_qsafe; + u32 emc_rdv; + u32 emc_rdv_mask; + u32 emc_qpop; + u32 emc_ctt; + u32 emc_ctt_duration; + u32 emc_refresh; + u32 emc_burst_refresh_num; + u32 emc_pre_refresh_req_cnt; + u32 emc_pdex2wr; + u32 emc_pdex2rd; + u32 emc_pchg2pden; + u32 emc_act2pden; + u32 emc_ar2pden; + u32 emc_rw2pden; + u32 emc_txsr; + u32 emc_txsrdll; + u32 emc_tcke; + u32 emc_tckesr; + u32 emc_tpd; + u32 emc_tfaw; + u32 emc_trpab; + u32 emc_tclkstable; + u32 emc_tclkstop; + u32 emc_trefbw; + u32 emc_fbio_cfg5; + u32 emc_fbio_cfg6; + u32 emc_fbio_spare; + u32 emc_cfg_rsv; + u32 emc_mrs; + u32 emc_emrs; + u32 emc_emrs2; + u32 emc_emrs3; + u32 emc_mrw1; + u32 emc_mrw2; + u32 emc_mrw3; + u32 emc_mrw4; + u32 emc_mrw_extra; + u32 emc_warmboot_mrw_extra; + u32 emc_warmboot_extra_modereg_write_en; + u32 emc_extra_modereg_write_enable; + u32 emc_mrw_reset_command; + u32 emc_mrw_reset_ninit_wait; + u32 emc_mrs_wait_cnt; + u32 emc_mrs_wait_cnt2; + u32 emc_cfg; + u32 emc_cfg2; + u32 emc_cfg_pipe; + u32 emc_dbg; + u32 emc_cmdq; + u32 emc_mc2emcq; + u32 emc_dyn_self_ref_control; + u32 ahb_arb_xbar_ctrl_mem_init_done; + u32 emc_cfg_dig_dll; + u32 emc_cfg_dig_dll_period; + u32 emc_dev_select; + u32 emc_sel_dpd_ctrl; + u32 emc_dll_xform_dqs0; + u32 emc_dll_xform_dqs1; + u32 emc_dll_xform_dqs2; + u32 emc_dll_xform_dqs3; + u32 emc_dll_xform_dqs4; + u32 emc_dll_xform_dqs5; + u32 emc_dll_xform_dqs6; + u32 emc_dll_xform_dqs7; + u32 emc_dll_xform_dqs8; + u32 emc_dll_xform_dqs9; + u32 emc_dll_xform_dqs10; + u32 emc_dll_xform_dqs11; + u32 emc_dll_xform_dqs12; + u32 emc_dll_xform_dqs13; + u32 emc_dll_xform_dqs14; + u32 emc_dll_xform_dqs15; + u32 emc_dll_xform_quse0; + u32 emc_dll_xform_quse1; + u32 emc_dll_xform_quse2; + u32 emc_dll_xform_quse3; + u32 emc_dll_xform_quse4; + u32 emc_dll_xform_quse5; + u32 emc_dll_xform_quse6; + u32 emc_dll_xform_quse7; + u32 emc_dll_xform_addr0; + u32 emc_dll_xform_addr1; + u32 emc_dll_xform_addr2; + u32 emc_dll_xform_addr3; + u32 emc_dll_xform_addr4; + u32 emc_dll_xform_addr5; + u32 emc_dll_xform_quse8; + u32 emc_dll_xform_quse9; + u32 emc_dll_xform_quse10; + u32 emc_dll_xform_quse11; + u32 emc_dll_xform_quse12; + u32 emc_dll_xform_quse13; + u32 emc_dll_xform_quse14; + u32 emc_dll_xform_quse15; + u32 emc_dli_trim_txdqs0; + u32 emc_dli_trim_txdqs1; + u32 emc_dli_trim_txdqs2; + u32 emc_dli_trim_txdqs3; + u32 emc_dli_trim_txdqs4; + u32 emc_dli_trim_txdqs5; + u32 emc_dli_trim_txdqs6; + u32 emc_dli_trim_txdqs7; + u32 emc_dli_trim_txdqs8; + u32 emc_dli_trim_txdqs9; + u32 emc_dli_trim_txdqs10; + u32 emc_dli_trim_txdqs11; + u32 emc_dli_trim_txdqs12; + u32 emc_dli_trim_txdqs13; + u32 emc_dli_trim_txdqs14; + u32 emc_dli_trim_txdqs15; + u32 emc_dll_xform_dq0; + u32 emc_dll_xform_dq1; + u32 emc_dll_xform_dq2; + u32 emc_dll_xform_dq3; + u32 emc_dll_xform_dq4; + u32 emc_dll_xform_dq5; + u32 emc_dll_xform_dq6; + u32 emc_dll_xform_dq7; + u32 warmboot_wait; + u32 emc_ctt_term_ctrl; + u32 emc_odt_write; + u32 emc_odt_read; + u32 emc_zcal_interval; + u32 emc_zcal_wait_cnt; + u32 emc_zcal_mrw_cmd; + u32 emc_mrs_rest_dll; + u32 emc_zcal_init_dev0; + u32 emc_zcal_init_dev1; + u32 emc_zcal_init_wait; + u32 emc_zcal_warmcoldboot_enables; + u32 emc_mrw_lpddr2_zcal_warmboot; + u32 emc_zq_cal_ddr3_warmboot; + u32 emc_zcal_warmboot_wait; + u32 emc_mrs_warmboot_enable; + u32 emc_mrs_reset_dll_wait; + u32 emc_mrs_extra; + u32 emc_warmboot_mrs_extra; + u32 emc_emrs_ddr2_dll_enable; + u32 emc_mrs_ddr2_dll_reset; + u32 emc_emrs_ddr2_ocd_calib; + u32 emc_ddr2_wait; + u32 emc_clken_override; + u32 mc_dis_extra_snap_levels; + u32 emc_extra_refresh_num; + u32 emc_clken_override_all_warmboot; + u32 mc_clken_override_all_warmboot; + u32 emc_cfg_dig_dll_period_warmboot; + u32 pmc_vddp_sel; + u32 pmc_vddp_sel_wait; + u32 pmc_ddr_pwr; + u32 pmc_ddr_cfg; + u32 pmc_io_dpd3_req; + u32 pmc_io_dpd3_req_wait; + u32 pmc_reg_short; + u32 pmc_no_iopower; + u32 pmc_por_dpd_ctrl_wait; + u32 emc_xm2cmdpadctrl; + u32 emc_xm2cmdpadctrl2; + u32 emc_xm2cmdpadctrl3; + u32 emc_xm2cmdpadctrl4; + u32 emc_xm2cmdpadctrl5; + u32 emc_xm2dqspadctrl; + u32 emc_xm2dqspadctrl2; + u32 emc_xm2dqspadctrl3; + u32 emc_xm2dqspadctrl4; + u32 emc_xm2dqspadctrl5; + u32 emc_xm2dqspadctrl6; + u32 emc_xm2dqpadctrl; + u32 emc_xm2dqpadctrl2; + u32 emc_xm2dqpadctrl3; + u32 emc_xm2clkpadctrl; + u32 emc_xm2clkpadctrl2; + u32 emc_xm2comppadctrl; + u32 emc_xm2vttgenpadctrl; + u32 emc_xm2vttgenpadctrl2; + u32 emc_xm2vttgenpadctrl3; + u32 emc_acpd_control; + u32 emc_swizzle_rank0_byte_cfg; + u32 emc_swizzle_rank0_byte0; + u32 emc_swizzle_rank0_byte1; + u32 emc_swizzle_rank0_byte2; + u32 emc_swizzle_rank0_byte3; + u32 emc_swizzle_rank1_byte_cfg; + u32 emc_swizzle_rank1_byte0; + u32 emc_swizzle_rank1_byte1; + u32 emc_swizzle_rank1_byte2; + u32 emc_swizzle_rank1_byte3; + u32 emc_dsr_vttgen_drv; + u32 emc_txdsrvttgen; + u32 emc_bgbias_ctl0; + u32 mc_emem_adr_cfg; + u32 mc_emem_adr_cfg_dev0; + u32 mc_emem_adr_cfg_dev1; + u32 mc_emem_adr_cfg_bank_mask0; + u32 mc_emem_adr_cfg_bank_mask1; + u32 mc_emem_adr_cfg_bank_mask2; + u32 mc_emem_adr_cfg_bank_swizzle3; + u32 mc_emem_cfg; + u32 mc_emem_arb_cfg; + u32 mc_emem_arb_outstanding_req; + u32 mc_emem_arb_timing_rcd; + u32 mc_emem_arb_timing_rp; + u32 mc_emem_arb_timing_rc; + u32 mc_emem_arb_timing_ras; + u32 mc_emem_arb_timing_faw; + u32 mc_emem_arb_timing_rrd; + u32 mc_emem_arb_timing_rap2pre; + u32 mc_emem_arb_timing_wap2pre; + u32 mc_emem_arb_timing_r2r; + u32 mc_emem_arb_timing_w2w; + u32 mc_emem_arb_timing_r2w; + u32 mc_emem_arb_timing_w2r; + u32 mc_emem_arb_da_turns; + u32 mc_emem_arb_da_covers; + u32 mc_emem_arb_misc0; + u32 mc_emem_arb_misc1; + u32 mc_emem_arb_ring1_throttle; + u32 mc_emem_arb_override; + u32 mc_emem_arb_override1; + u32 mc_emem_arb_rsv; + u32 mc_clken_override; + u32 mc_stat_control; + u32 mc_display_snap_ring; + u32 mc_video_protect_bom; + u32 mc_video_protect_bom_adr_hi; + u32 mc_video_protect_size_mb; + u32 mc_video_protect_vpr_override; + u32 mc_video_protect_vpr_override1; + u32 mc_video_protect_gpu_override0; + u32 mc_video_protect_gpu_override1; + u32 mc_sec_carveout_bom; + u32 mc_sec_carveout_adr_hi; + u32 mc_sec_carveout_size_mb; + u32 mc_video_protect_write_access; + u32 mc_sec_carveout_protect_write_access; + u32 emc_ca_training_enable; + u32 emc_ca_training_timing_cntl1; + u32 emc_ca_training_timing_cntl2; + u32 swizzle_rank_byte_encode; + u32 bootrom_patch_control; + u32 bootrom_patch_data; + u32 mc_mts_carveout_bom; + u32 mc_mts_carveout_adr_hi; + u32 mc_mts_carveout_size_mb; + u32 mc_mts_carveout_reg_ctrl; +}; +#endif /* _TEGRA124_SDRAM_PARAM_H_ */ diff --git a/arch/arm/include/asm/arch-tegra/warmboot.h b/arch/arm/include/asm/arch-tegra/warmboot.h index 2e66e0f23b..6b37b60c68 100644 --- a/arch/arm/include/asm/arch-tegra/warmboot.h +++ b/arch/arm/include/asm/arch-tegra/warmboot.h @@ -8,11 +8,14 @@ #ifndef _WARM_BOOT_H_ #define _WARM_BOOT_H_ +#include <asm/arch-tegra/sdram_param.h> + #define STRAP_OPT_A_RAM_CODE_SHIFT 4 #define STRAP_OPT_A_RAM_CODE_MASK (0xf << STRAP_OPT_A_RAM_CODE_SHIFT) /* Defines the supported operating modes */ enum fuse_operating_mode { + MODE_PREPRODUCTION = 2, MODE_PRODUCTION = 3, MODE_UNDEFINED, }; @@ -39,7 +42,15 @@ struct hash { struct wb_header { u32 length_insecure; /* length of the code header */ u32 reserved[3]; +#ifdef CONFIG_TEGRA124 + u32 modules[64]; /* RsaKeyModulus */ + struct { + struct hash hash; /* hash of header+code, starts next field */ + u32 signature[64]; /* The RSA-PSS signature*/ + } hash_signature; +#else struct hash hash; /* hash of header+code, starts next field*/ +#endif struct hash random_aes_block; /* a data block to aid security. */ u32 length_secure; /* length of the code header */ u32 destination; /* destination address to put the wb code */ @@ -118,6 +129,83 @@ union scratch3_reg { u32 word; }; +enum field_type { + TYPE_SDRAM, + TYPE_PLLM, + TYPE_CONST, + TYPE_COUNT, +}; + +#define sdram_offset(member) offsetof(struct sdram_params, member) +#define pmc_offset(member) offsetof(struct pmc_ctlr, member) +#define pllm_offset(member) offsetof(struct clk_pllm, member) + +struct encode_fields { + u32 src_offset; + u32 op1_mask; + u32 op1_shift; + u32 op2_mask; + u32 op2_shift; + u32 dst_offset; + u32 dst_shift; +}; + +/* + * encode: set dst_off.dst_bit to 1 if (src_off.op1_bits > src_off.op2_bits) + * else set dst_off.dst_bit to 0. + */ +#define encode(src_off, op1_bits, op2_bits, dst_off, dst_bit) \ + { \ + .src_offset = src_off, \ + .op1_mask = 0xfffffffful >> \ + (31 - ((1 ? op1_bits) - (0 ? op1_bits))), \ + .op1_shift = 0 ? op1_bits, \ + .op2_mask = 0xfffffffful >> \ + (31 - ((1 ? op2_bits) - (0 ? op2_bits))), \ + .op2_shift = 0 ? op2_bits, \ + .dst_offset = dst_off, \ + .dst_shift = dst_bit, \ + } + +struct pack_fields { + enum field_type src_type; + u32 src_offset; /* for TYPE_CONST, this field is a constant */ + u32 src_mask; + u32 src_shift; + enum field_type dst_type; + u32 dst_offset; + u32 dst_mask; + u32 dst_shift; +}; + +/* + * pack: a macro to copy from bits in src to bits in dst. + * + * For example, + * pack(TYPE_SDRAM, sdram_offset(emc_clock_source), 7:0, + * pmc_offset(pmc_scratch6), 15:8) + * is to: + * copy bits 7:0 of sdram_offset.emc_clock_source to + * bits 15:8 of pmc_scratch6 register. + * + * The first parameter of pack determines the type of src: + * TYPE_SDRAM: src is of SDRAM parameter, + * TYPE_PLLM: src is of PLLM, + * TYPE_CONST: src is a constant. + */ +#define pack(_src_type, src_off, src_bits, dst_off, dst_bits) \ + { \ + .src_type = _src_type, \ + .src_offset = src_off, \ + .src_mask = 0xfffffffful >> \ + (31 - ((1 ? src_bits) - (0 ? src_bits))), \ + .src_shift = 0 ? src_bits, \ + .dst_offset = dst_off, \ + .dst_mask = 0xfffffffful >> \ + (31 - ((1 ? dst_bits) - (0 ? dst_bits))), \ + .dst_shift = 0 ? dst_bits, \ + } + /** * Save warmboot memory settings for a later resume @@ -131,4 +219,18 @@ int sign_data_block(u8 *source, u32 length, u8 *signature); void wb_start(void); /* Start of WB assembly code */ void wb_end(void); /* End of WB assembly code */ +/* Common routines for T114 and T124 SOCs */ + +/* + * t1x4_wb_save_sdram_params(): + * save sdram parameters to scratch registers so sdram parameters can be + * restored when system resumes from LP0 + */ +int t1x4_wb_save_sdram_params(struct sdram_params *sdram); + +/* + * t1x4_wb_prepare_code(): + * prepare WB code, which will be executed by AVP when system resumes from LP0 + */ +int t1x4_wb_prepare_code(u32 tegra_id, u32 seg_address, u32 seg_length); #endif diff --git a/arch/arm/include/asm/arch-tegra124/wb_param.h b/arch/arm/include/asm/arch-tegra124/wb_param.h new file mode 100644 index 0000000000..526228598d --- /dev/null +++ b/arch/arm/include/asm/arch-tegra124/wb_param.h @@ -0,0 +1,598 @@ +/* + * 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 <http://www.gnu.org/licenses/>. + */ + +#ifndef _TEGRA124_WB_PARAM_H_ +#define _TEGRA124_WB_PARAM_H_ + +#define e(src, op1, op2, dst, dbit) \ + encode(sdram_offset(src), op1, op2, sdram_offset(dst), dbit) + +struct encode_fields encode_list[] = { + e(emc_swizzle_rank0_byte0, 26:24, 30:28, swizzle_rank_byte_encode, 0), + e(emc_swizzle_rank0_byte1, 26:24, 30:28, swizzle_rank_byte_encode, 1), + e(emc_swizzle_rank0_byte2, 26:24, 30:28, swizzle_rank_byte_encode, 2), + e(emc_swizzle_rank0_byte3, 26:24, 30:28, swizzle_rank_byte_encode, 3), + e(emc_swizzle_rank1_byte0, 26:24, 30:28, swizzle_rank_byte_encode, 4), + e(emc_swizzle_rank1_byte1, 26:24, 30:28, swizzle_rank_byte_encode, 5), + e(emc_swizzle_rank1_byte2, 26:24, 30:28, swizzle_rank_byte_encode, 6), + e(emc_swizzle_rank1_byte3, 26:24, 30:28, swizzle_rank_byte_encode, 7), +}; + +#define s(offset, src, scratch, dst) \ + pack(TYPE_SDRAM, sdram_offset(offset), src, pmc_offset(scratch), dst) + +#define m(offset, src, scratch, dst) \ + pack(TYPE_PLLM, pllm_offset(offset), src, pmc_offset(scratch), dst) + +#define c(const, src, scratch, dst) \ + pack(TYPE_CONST, const, src, pmc_offset(scratch), dst) + +struct pack_fields pack_list_1[] = { + s(emc_clock_source, 7:0, pmc_scratch6, 15:8), + s(emc_clock_source, 31:29, pmc_scratch6, 18:16), + s(emc_clock_source, 26:26, pmc_scratch6, 19:19), + s(emc_odt_write, 5:0, pmc_scratch6, 25:20), + s(emc_odt_write, 11:8, pmc_scratch6, 29:26), + s(emc_odt_write, 30:30, pmc_scratch6, 30:30), + s(emc_odt_write, 31:31, pmc_scratch6, 31:31), + s(emc_xm2dqpadctrl2, 18:16, pmc_scratch7, 22:20), + s(emc_xm2dqpadctrl2, 22:20, pmc_scratch7, 25:23), + s(emc_xm2dqpadctrl2, 26:24, pmc_scratch7, 28:26), + s(emc_xm2dqpadctrl2, 30:28, pmc_scratch7, 31:29), + s(emc_xm2dqpadctrl3, 18:16, pmc_scratch8, 22:20), + s(emc_xm2dqpadctrl3, 22:20, pmc_scratch8, 25:23), + s(emc_xm2dqpadctrl3, 26:24, pmc_scratch8, 28:26), + s(emc_xm2dqpadctrl3, 30:28, pmc_scratch8, 31:29), + s(emc_txsrdll, 11:0, pmc_scratch9, 31:20), + c(0, 31:0, pmc_scratch10, 31:0), + s(emc_dsr_vttgen_drv, 5:0, pmc_scratch10, 25:20), + s(emc_dsr_vttgen_drv, 18:16, pmc_scratch10, 28:26), + s(emc_dsr_vttgen_drv, 26:24, pmc_scratch10, 31:29), + s(emc_fbio_spare, 31:24, pmc_scratch11, 7:0), + s(emc_fbio_spare, 23:16, pmc_scratch11, 15:8), + s(emc_fbio_spare, 15:8, pmc_scratch11, 23:16), + s(emc_fbio_spare, 7:0, pmc_scratch11, 31:24), + s(emc_cfg_rsv, 31:0, pmc_scratch12, 31:0), + s(emc_cdb_cntl2, 31:0, pmc_scratch13, 31:0), + s(mc_emem_arb_da_turns, 31:0, pmc_scratch14, 31:0), + s(emc_cfg_dig_dll, 0:0, pmc_scratch17, 0:0), + s(emc_cfg_dig_dll, 25:2, pmc_scratch17, 24:1), + s(emc_cfg_dig_dll, 31:27, pmc_scratch17, 29:25), + s(emc_cdb_cntl1, 29:0, pmc_scratch18, 29:0), + s(mc_emem_arb_misc0, 14:0, pmc_scratch19, 14:0), + s(mc_emem_arb_misc0, 30:16, pmc_scratch19, 29:15), + s(emc_xm2dqspadctrl, 4:0, pmc_scratch22, 4:0), + s(emc_xm2dqspadctrl, 12:8, pmc_scratch22, 9:5), + s(emc_xm2dqspadctrl, 31:14, pmc_scratch22, 27:10), + s(emc_rdr, 3:0, pmc_scratch22, 31:28), + s(emc_xm2dqpadctrl, 31:4, pmc_scratch23, 27:0), + s(emc_rext, 3:0, pmc_scratch23, 31:28), + s(emc_xm2comppadctrl, 16:0, pmc_scratch24, 16:0), + s(emc_xm2comppadctrl, 24:20, pmc_scratch24, 21:17), + s(emc_xm2comppadctrl, 27:27, pmc_scratch24, 22:22), + s(emc_xm2comppadctrl, 31:28, pmc_scratch24, 26:23), + s(emc_r2w, 4:0, pmc_scratch24, 31:27), + s(emc_cfg, 9:1, pmc_scratch25, 8:0), + s(emc_cfg, 26:16, pmc_scratch25, 19:9), + s(emc_cfg, 31:28, pmc_scratch25, 23:20), + s(emc_xm2vttgenpadctrl, 0:0, pmc_scratch25, 24:24), + s(emc_xm2vttgenpadctrl, 2:2, pmc_scratch25, 25:25), + s(emc_xm2vttgenpadctrl, 18:16, pmc_scratch25, 28:26), + s(emc_xm2vttgenpadctrl, 26:24, pmc_scratch25, 31:29), + s(emc_zcal_interval, 23:10, pmc_scratch26, 13:0), + s(emc_zcal_interval, 9:0, pmc_scratch26, 23:14), + s(emc_sel_dpd_ctrl, 5:2, pmc_scratch26, 27:24), + s(emc_sel_dpd_ctrl, 8:8, pmc_scratch26, 28:28), + s(emc_sel_dpd_ctrl, 18:16, pmc_scratch26, 31:29), + s(emc_xm2vttgenpadctrl3, 22:0, pmc_scratch27, 22:0), + s(emc_xm2vttgenpadctrl3, 24:24, pmc_scratch27, 23:23), + s(emc_swizzle_rank0_byte_cfg, 1:0, pmc_scratch27, 25:24), + s(emc_swizzle_rank0_byte_cfg, 5:4, pmc_scratch27, 27:26), + s(emc_swizzle_rank0_byte_cfg, 9:8, pmc_scratch27, 29:28), + s(emc_swizzle_rank0_byte_cfg, 13:12, pmc_scratch27, 31:30), + s(emc_xm2clkpadctrl2, 5:0, pmc_scratch28, 5:0), + s(emc_xm2clkpadctrl2, 13:8, pmc_scratch28, 11:6), + s(emc_xm2clkpadctrl2, 20:16, pmc_scratch28, 16:12), + s(emc_xm2clkpadctrl2, 23:23, pmc_scratch28, 17:17), + s(emc_xm2clkpadctrl2, 28:24, pmc_scratch28, 22:18), + s(emc_xm2clkpadctrl2, 31:31, pmc_scratch28, 23:23), + s(emc_swizzle_rank1_byte_cfg, 1:0, pmc_scratch28, 25:24), + s(emc_swizzle_rank1_byte_cfg, 5:4, pmc_scratch28, 27:26), + s(emc_swizzle_rank1_byte_cfg, 9:8, pmc_scratch28, 29:28), + s(emc_swizzle_rank1_byte_cfg, 13:12, pmc_scratch28, 31:30), + s(mc_emem_arb_da_covers, 23:0, pmc_scratch29, 23:0), + s(mc_emem_arb_rsv, 7:0, pmc_scratch29, 31:24), + s(emc_auto_cal_config, 4:0, pmc_scratch30, 4:0), + s(emc_auto_cal_config, 12:8, pmc_scratch30, 9:5), + s(emc_auto_cal_config, 18:16, pmc_scratch30, 12:10), + s(emc_auto_cal_config, 25:20, pmc_scratch30, 18:13), + s(emc_auto_cal_config, 31:28, pmc_scratch30, 22:19), + s(emc_rfc, 8:0, pmc_scratch30, 31:23), + s(emc_xm2dqspadctrl2, 21:0, pmc_scratch31, 21:0), + s(emc_xm2dqspadctrl2, 24:24, pmc_scratch31, 22:22), + s(emc_ar2pden, 8:0, pmc_scratch31, 31:23), + s(emc_xm2clkpadctrl, 0:0, pmc_scratch32, 0:0), + s(emc_xm2clkpadctrl, 4:2, pmc_scratch32, 3:1), + s(emc_xm2clkpadctrl, 7:7, pmc_scratch32, 4:4), + s(emc_xm2clkpadctrl, 31:14, pmc_scratch32, 22:5), + s(emc_rfc_slr, 8:0, pmc_scratch32, 31:23), + s(emc_xm2dqspadctrl3, 0:0, pmc_scratch33, 0:0), + s(emc_xm2dqspadctrl3, 5:5, pmc_scratch33, 1:1), + s(emc_xm2dqspadctrl3, 12:8, pmc_scratch33, 6:2), + s(emc_xm2dqspadctrl3, 18:14, pmc_scratch33, 11:7), + s(emc_xm2dqspadctrl3, 24:20, pmc_scratch33, 16:12), + s(emc_xm2dqspadctrl3, 30:26, pmc_scratch33, 21:17), + s(emc_txsr, 9:0, pmc_scratch33, 31:22), + s(mc_emem_arb_cfg, 8:0, pmc_scratch40, 8:0), + s(mc_emem_arb_cfg, 20:16, pmc_scratch40, 13:9), + s(mc_emem_arb_cfg, 27:24, pmc_scratch40, 17:14), + s(mc_emem_arb_cfg, 31:28, pmc_scratch40, 21:18), + s(emc_mc2emcq, 2:0, pmc_scratch40, 24:22), + s(emc_mc2emcq, 10:8, pmc_scratch40, 27:25), + s(emc_mc2emcq, 27:24, pmc_scratch40, 31:28), + s(emc_auto_cal_interval, 20:0, pmc_scratch42, 20:0), + s(mc_emem_arb_outstanding_req, 8:0, pmc_scratch42, 29:21), + s(mc_emem_arb_outstanding_req, 31:30, pmc_scratch42, 31:30), + s(emc_mrs_wait_cnt2, 9:0, pmc_scratch44, 9:0), + s(emc_mrs_wait_cnt2, 25:16, pmc_scratch44, 19:10), + s(emc_txdsrvttgen, 11:0, pmc_scratch44, 31:20), + s(emc_mrs_wait_cnt, 9:0, pmc_scratch45, 9:0), + s(emc_mrs_wait_cnt, 25:16, pmc_scratch45, 19:10), + s(emc_cfg_pipe, 1:0, pmc_scratch45, 21:20), + s(emc_cfg_pipe, 9:4, pmc_scratch45, 27:22), + s(emc_cfg_pipe, 15:12, pmc_scratch45, 31:28), + s(emc_xm2dqspadctrl4, 22:18, pmc_scratch46, 4:0), + s(emc_xm2dqspadctrl4, 16:12, pmc_scratch46, 9:5), + s(emc_xm2dqspadctrl4, 10:6, pmc_scratch46, 14:10), + s(emc_xm2dqspadctrl4, 4:0, pmc_scratch46, 19:15), + s(emc_zcal_wait_cnt, 9:0, pmc_scratch46, 29:20), + s(emc_xm2dqspadctrl5, 22:18, pmc_scratch47, 4:0), + s(emc_xm2dqspadctrl5, 16:12, pmc_scratch47, 9:5), + s(emc_xm2dqspadctrl5, 10:6, pmc_scratch47, 14:10), + s(emc_xm2dqspadctrl5, 4:0, pmc_scratch47, 19:15), + s(emc_xm2vttgenpadctrl2, 5:0, pmc_scratch47, 25:20), + s(emc_xm2vttgenpadctrl2, 31:28, pmc_scratch47, 29:26), + s(emc_xm2dqspadctrl6, 12:8, pmc_scratch48, 4:0), + s(emc_xm2dqspadctrl6, 18:14, pmc_scratch48, 9:5), + s(emc_xm2dqspadctrl6, 24:20, pmc_scratch48, 14:10), + s(emc_xm2dqspadctrl6, 30:26, pmc_scratch48, 19:15), + s(emc_auto_cal_config3, 4:0, pmc_scratch48, 24:20), + s(emc_auto_cal_config3, 12:8, pmc_scratch48, 29:25), + s(emc_fbio_cfg5, 1:0, pmc_scratch48, 31:30), + s(emc_dll_xform_quse8, 4:0, pmc_scratch50, 4:0), + s(emc_dll_xform_quse8, 22:8, pmc_scratch50, 19:5), + s(mc_emem_arb_ring1_throttle, 4:0, pmc_scratch50, 24:20), + s(mc_emem_arb_ring1_throttle, 20:16, pmc_scratch50, 29:25), + s(emc_fbio_cfg5, 3:2, pmc_scratch50, 31:30), + s(emc_dll_xform_quse9, 4:0, pmc_scratch51, 4:0), + s(emc_dll_xform_quse9, 22:8, pmc_scratch51, 19:5), + s(emc_ctt_term_ctrl, 2:0, pmc_scratch51, 22:20), + s(emc_ctt_term_ctrl, 12:8, pmc_scratch51, 27:23), + s(emc_ctt_term_ctrl, 31:31, pmc_scratch51, 28:28), + s(emc_fbio_cfg6, 2:0, pmc_scratch51, 31:29), + s(emc_dll_xform_quse10, 4:0, pmc_scratch56, 4:0), + s(emc_dll_xform_quse10, 22:8, pmc_scratch56, 19:5), + s(emc_xm2cmdpadctrl, 10:3, pmc_scratch56, 27:20), + s(emc_xm2cmdpadctrl, 28:28, pmc_scratch56, 28:28), + s(emc_puterm_adj, 1:0, pmc_scratch56, 30:29), + s(emc_puterm_adj, 7:7, pmc_scratch56, 31:31), + s(emc_dll_xform_quse11, 4:0, pmc_scratch57, 4:0), + s(emc_dll_xform_quse11, 22:8, pmc_scratch57, 19:5), + s(emc_wdv, 3:0, pmc_scratch57, 31:28), + s(emc_dll_xform_quse12, 4:0, pmc_scratch58, 4:0), + s(emc_dll_xform_quse12, 22:8, pmc_scratch58, 19:5), + s(emc_burst_refresh_num, 3:0, pmc_scratch58, 31:28), + s(emc_dll_xform_quse13, 4:0, pmc_scratch59, 4:0), + s(emc_dll_xform_quse13, 22:8, pmc_scratch59, 19:5), + s(emc_wext, 3:0, pmc_scratch59, 31:28), + s(emc_dll_xform_quse14, 4:0, pmc_scratch60, 4:0), + s(emc_dll_xform_quse14, 22:8, pmc_scratch60, 19:5), + s(emc_clken_override, 3:1, pmc_scratch60, 30:28), + s(emc_clken_override, 6:6, pmc_scratch60, 31:31), + s(emc_dll_xform_quse15, 4:0, pmc_scratch61, 4:0), + s(emc_dll_xform_quse15, 22:8, pmc_scratch61, 19:5), + s(emc_r2r, 3:0, pmc_scratch61, 31:28), + s(emc_dll_xform_dq4, 4:0, pmc_scratch62, 4:0), + s(emc_dll_xform_dq4, 22:8, pmc_scratch62, 19:5), + s(emc_rc, 6:0, pmc_scratch62, 26:20), + s(emc_w2r, 4:0, pmc_scratch62, 31:27), + s(emc_dll_xform_dq5, 4:0, pmc_scratch63, 4:0), + s(emc_dll_xform_dq5, 22:8, pmc_scratch63, 19:5), + s(emc_tfaw, 6:0, pmc_scratch63, 26:20), + s(emc_r2p, 4:0, pmc_scratch63, 31:27), + s(emc_dll_xform_dq6, 4:0, pmc_scratch64, 4:0), + s(emc_dll_xform_dq6, 22:8, pmc_scratch64, 19:5), + s(emc_dli_trim_txdqs0, 6:0, pmc_scratch64, 26:20), + s(emc_qsafe, 4:0, pmc_scratch64, 31:27), + s(emc_dll_xform_dq7, 4:0, pmc_scratch65, 4:0), + s(emc_dll_xform_dq7, 22:8, pmc_scratch65, 19:5), + s(emc_dli_trim_txdqs1, 6:0, pmc_scratch65, 26:20), + s(emc_tclkstable, 4:0, pmc_scratch65, 31:27), + s(emc_auto_cal_config2, 4:0, pmc_scratch66, 4:0), + s(emc_auto_cal_config2, 12:8, pmc_scratch66, 9:5), + s(emc_auto_cal_config2, 20:16, pmc_scratch66, 14:10), + s(emc_auto_cal_config2, 28:24, pmc_scratch66, 19:15), + s(emc_dli_trim_txdqs2, 6:0, pmc_scratch66, 26:20), + s(emc_tclkstop, 4:0, pmc_scratch66, 31:27), + s(mc_emem_arb_misc1, 1:0, pmc_scratch67, 1:0), + s(mc_emem_arb_misc1, 12:4, pmc_scratch67, 10:2), + s(mc_emem_arb_misc1, 25:21, pmc_scratch67, 15:11), + s(mc_emem_arb_misc1, 31:28, pmc_scratch67, 19:16), + s(emc_dli_trim_txdqs3, 6:0, pmc_scratch67, 26:20), + s(emc_einput_duration, 4:0, pmc_scratch67, 31:27), + s(emc_zcal_mrw_cmd, 7:0, pmc_scratch68, 7:0), + s(emc_zcal_mrw_cmd, 23:16, pmc_scratch68, 15:8), + s(emc_zcal_mrw_cmd, 31:30, pmc_scratch68, 17:16), + s(emc_trefbw, 13:0, pmc_scratch68, 31:18), + s(emc_xm2cmdpadctrl2, 31:14, pmc_scratch69, 17:0), + s(emc_dli_trim_txdqs4, 6:0, pmc_scratch69, 24:18), + s(emc_dli_trim_txdqs5, 6:0, pmc_scratch69, 31:25), + s(emc_xm2cmdpadctrl3, 31:14, pmc_scratch70, 17:0), + s(emc_dli_trim_txdqs6, 6:0, pmc_scratch70, 24:18), + s(emc_dli_trim_txdqs7, 6:0, pmc_scratch70, 31:25), + s(emc_xm2cmdpadctrl5, 2:0, pmc_scratch71, 2:0), + s(emc_xm2cmdpadctrl5, 6:4, pmc_scratch71, 5:3), + s(emc_xm2cmdpadctrl5, 10:8, pmc_scratch71, 8:6), + s(emc_xm2cmdpadctrl5, 14:12, pmc_scratch71, 11:9), + s(emc_xm2cmdpadctrl5, 18:16, pmc_scratch71, 14:12), + s(emc_xm2cmdpadctrl5, 22:20, pmc_scratch71, 17:15), + s(emc_dli_trim_txdqs8, 6:0, pmc_scratch71, 24:18), + s(emc_dli_trim_txdqs9, 6:0, pmc_scratch71, 31:25), + s(emc_cdb_cntl3, 17:0, pmc_scratch72, 17:0), + s(emc_dli_trim_txdqs10, 6:0, pmc_scratch72, 24:18), + s(emc_dli_trim_txdqs11, 6:0, pmc_scratch72, 31:25), + s(emc_swizzle_rank0_byte0, 2:0, pmc_scratch73, 2:0), + s(emc_swizzle_rank0_byte0, 6:4, pmc_scratch73, 5:3), + s(emc_swizzle_rank0_byte0, 10:8, pmc_scratch73, 8:6), + s(emc_swizzle_rank0_byte0, 14:12, pmc_scratch73, 11:9), + s(emc_swizzle_rank0_byte0, 18:16, pmc_scratch73, 14:12), + s(emc_swizzle_rank0_byte0, 22:20, pmc_scratch73, 17:15), + s(emc_dli_trim_txdqs12, 6:0, pmc_scratch73, 24:18), + s(emc_dli_trim_txdqs13, 6:0, pmc_scratch73, 31:25), + s(emc_swizzle_rank0_byte1, 2:0, pmc_scratch74, 2:0), + s(emc_swizzle_rank0_byte1, 6:4, pmc_scratch74, 5:3), + s(emc_swizzle_rank0_byte1, 10:8, pmc_scratch74, 8:6), + s(emc_swizzle_rank0_byte1, 14:12, pmc_scratch74, 11:9), + s(emc_swizzle_rank0_byte1, 18:16, pmc_scratch74, 14:12), + s(emc_swizzle_rank0_byte1, 22:20, pmc_scratch74, 17:15), + s(emc_dli_trim_txdqs14, 6:0, pmc_scratch74, 24:18), + s(emc_dli_trim_txdqs15, 6:0, pmc_scratch74, 31:25), + s(emc_swizzle_rank0_byte2, 2:0, pmc_scratch75, 2:0), + s(emc_swizzle_rank0_byte2, 6:4, pmc_scratch75, 5:3), + s(emc_swizzle_rank0_byte2, 10:8, pmc_scratch75, 8:6), + s(emc_swizzle_rank0_byte2, 14:12, pmc_scratch75, 11:9), + s(emc_swizzle_rank0_byte2, 18:16, pmc_scratch75, 14:12), + s(emc_swizzle_rank0_byte2, 22:20, pmc_scratch75, 17:15), + s(mc_emem_arb_timing_rp, 6:0, pmc_scratch75, 24:18), + s(mc_emem_arb_timing_rc, 6:0, pmc_scratch75, 31:25), + s(emc_swizzle_rank0_byte3, 2:0, pmc_scratch76, 2:0), + s(emc_swizzle_rank0_byte3, 6:4, pmc_scratch76, 5:3), + s(emc_swizzle_rank0_byte3, 10:8, pmc_scratch76, 8:6), + s(emc_swizzle_rank0_byte3, 14:12, pmc_scratch76, 11:9), + s(emc_swizzle_rank0_byte3, 18:16, pmc_scratch76, 14:12), + s(emc_swizzle_rank0_byte3, 22:20, pmc_scratch76, 17:15), + s(mc_emem_arb_timing_faw, 6:0, pmc_scratch76, 24:18), + s(mc_emem_arb_timing_wap2pre, 6:0, pmc_scratch76, 31:25), + s(emc_swizzle_rank1_byte0, 2:0, pmc_scratch77, 2:0), + s(emc_swizzle_rank1_byte0, 6:4, pmc_scratch77, 5:3), + s(emc_swizzle_rank1_byte0, 10:8, pmc_scratch77, 8:6), + s(emc_swizzle_rank1_byte0, 14:12, pmc_scratch77, 11:9), + s(emc_swizzle_rank1_byte0, 18:16, pmc_scratch77, 14:12), + s(emc_swizzle_rank1_byte0, 22:20, pmc_scratch77, 17:15), + s(emc_ras, 5:0, pmc_scratch77, 23:18), + s(emc_rp, 5:0, pmc_scratch77, 29:24), + s(emc_cfg2, 9:8, pmc_scratch77, 31:30), + s(emc_swizzle_rank1_byte1, 2:0, pmc_scratch78, 2:0), + s(emc_swizzle_rank1_byte1, 6:4, pmc_scratch78, 5:3), + s(emc_swizzle_rank1_byte1, 10:8, pmc_scratch78, 8:6), + s(emc_swizzle_rank1_byte1, 14:12, pmc_scratch78, 11:9), + s(emc_swizzle_rank1_byte1, 18:16, pmc_scratch78, 14:12), + s(emc_swizzle_rank1_byte1, 22:20, pmc_scratch78, 17:15), + s(emc_w2p, 5:0, pmc_scratch78, 23:18), + s(emc_rd_rcd, 5:0, pmc_scratch78, 29:24), + s(emc_cfg2, 27:26, pmc_scratch78, 31:30), + s(emc_swizzle_rank1_byte2, 2:0, pmc_scratch79, 2:0), + s(emc_swizzle_rank1_byte2, 6:4, pmc_scratch79, 5:3), + s(emc_swizzle_rank1_byte2, 10:8, pmc_scratch79, 8:6), + s(emc_swizzle_rank1_byte2, 14:12, pmc_scratch79, 11:9), + s(emc_swizzle_rank1_byte2, 18:16, pmc_scratch79, 14:12), + s(emc_swizzle_rank1_byte2, 22:20, pmc_scratch79, 17:15), + s(emc_wr_rcd, 5:0, pmc_scratch79, 23:18), + s(emc_quse, 5:0, pmc_scratch79, 29:24), + s(emc_fbio_cfg5, 4:4, pmc_scratch79, 31:31), + s(emc_swizzle_rank1_byte3, 2:0, pmc_scratch80, 2:0), + s(emc_swizzle_rank1_byte3, 6:4, pmc_scratch80, 5:3), + s(emc_swizzle_rank1_byte3, 10:8, pmc_scratch80, 8:6), + s(emc_swizzle_rank1_byte3, 14:12, pmc_scratch80, 11:9), + s(emc_swizzle_rank1_byte3, 18:16, pmc_scratch80, 14:12), + s(emc_swizzle_rank1_byte3, 22:20, pmc_scratch80, 17:15), + s(emc_qrst, 5:0, pmc_scratch80, 23:18), + s(emc_rdv, 5:0, pmc_scratch80, 29:24), + s(emc_fbio_cfg5, 6:5, pmc_scratch80, 31:30), + s(emc_dyn_self_ref_control, 15:0, pmc_scratch81, 15:0), + s(emc_dyn_self_ref_control, 31:31, pmc_scratch81, 16:16), + s(emc_pdex2wr, 5:0, pmc_scratch81, 22:17), + s(emc_pdex2rd, 5:0, pmc_scratch81, 28:23), + s(emc_refresh, 5:0, pmc_scratch82, 5:0), + s(emc_refresh, 15:6, pmc_scratch82, 15:6), + s(emc_cmdq, 4:0, pmc_scratch82, 20:16), + s(emc_cmdq, 10:8, pmc_scratch82, 23:21), + s(emc_cmdq, 14:12, pmc_scratch82, 26:24), + s(emc_cmdq, 28:24, pmc_scratch82, 31:27), + s(emc_acpd_control, 15:0, pmc_scratch83, 15:0), + s(emc_cfg_dig_dll_period, 15:0, pmc_scratch83, 31:16), + s(emc_dll_xform_dqs0, 4:0, pmc_scratch84, 4:0), + s(emc_dll_xform_dqs0, 22:12, pmc_scratch84, 15:5), + s(emc_dll_xform_dqs1, 4:0, pmc_scratch84, 20:16), + s(emc_dll_xform_dqs1, 22:12, pmc_scratch84, 31:21), + s(emc_dll_xform_dqs2, 4:0, pmc_scratch85, 4:0), + s(emc_dll_xform_dqs2, 22:12, pmc_scratch85, 15:5), + s(emc_dll_xform_dqs3, 4:0, pmc_scratch85, 20:16), + s(emc_dll_xform_dqs3, 22:12, pmc_scratch85, 31:21), + s(emc_dll_xform_dqs4, 4:0, pmc_scratch86, 4:0), + s(emc_dll_xform_dqs4, 22:12, pmc_scratch86, 15:5), + s(emc_dll_xform_dqs5, 4:0, pmc_scratch86, 20:16), + s(emc_dll_xform_dqs5, 22:12, pmc_scratch86, 31:21), + s(emc_dll_xform_dqs6, 4:0, pmc_scratch87, 4:0), + s(emc_dll_xform_dqs6, 22:12, pmc_scratch87, 15:5), + s(emc_dll_xform_dqs7, 4:0, pmc_scratch87, 20:16), + s(emc_dll_xform_dqs7, 22:12, pmc_scratch87, 31:21), + s(emc_dll_xform_dqs8, 4:0, pmc_scratch88, 4:0), + s(emc_dll_xform_dqs8, 22:12, pmc_scratch88, 15:5), + s(emc_dll_xform_dqs9, 4:0, pmc_scratch88, 20:16), + s(emc_dll_xform_dqs9, 22:12, pmc_scratch88, 31:21), + s(emc_dll_xform_dqs10, 4:0, pmc_scratch89, 4:0), + s(emc_dll_xform_dqs10, 22:12, pmc_scratch89, 15:5), + s(emc_dll_xform_dqs11, 4:0, pmc_scratch89, 20:16), + s(emc_dll_xform_dqs11, 22:12, pmc_scratch89, 31:21), + s(emc_dll_xform_dqs12, 4:0, pmc_scratch90, 4:0), + s(emc_dll_xform_dqs12, 22:12, pmc_scratch90, 15:5), + s(emc_dll_xform_dqs13, 4:0, pmc_scratch90, 20:16), + s(emc_dll_xform_dqs13, 22:12, pmc_scratch90, 31:21), + s(emc_dll_xform_dqs14, 4:0, pmc_scratch91, 4:0), + s(emc_dll_xform_dqs14, 22:12, pmc_scratch91, 15:5), + s(emc_dll_xform_dqs15, 4:0, pmc_scratch91, 20:16), + s(emc_dll_xform_dqs15, 22:12, pmc_scratch91, 31:21), + s(emc_dll_xform_quse0, 4:0, pmc_scratch92, 4:0), + s(emc_dll_xform_quse0, 22:12, pmc_scratch92, 15:5), + s(emc_dll_xform_quse1, 4:0, pmc_scratch92, 20:16), + s(emc_dll_xform_quse1, 22:12, pmc_scratch92, 31:21), + s(emc_dll_xform_quse2, 4:0, pmc_scratch93, 4:0), + s(emc_dll_xform_quse2, 22:12, pmc_scratch93, 15:5), + s(emc_dll_xform_quse3, 4:0, pmc_scratch93, 20:16), + s(emc_dll_xform_quse3, 22:12, pmc_scratch93, 31:21), + s(emc_dll_xform_quse4, 4:0, pmc_scratch94, 4:0), + s(emc_dll_xform_quse4, 22:12, pmc_scratch94, 15:5), + s(emc_dll_xform_quse5, 4:0, pmc_scratch94, 20:16), + s(emc_dll_xform_quse5, 22:12, pmc_scratch94, 31:21), + s(emc_dll_xform_quse6, 4:0, pmc_scratch95, 4:0), + s(emc_dll_xform_quse6, 22:12, pmc_scratch95, 15:5), + s(emc_dll_xform_quse7, 4:0, pmc_scratch95, 20:16), + s(emc_dll_xform_quse7, 22:12, pmc_scratch95, 31:21), + s(emc_dll_xform_dq0, 4:0, pmc_scratch96, 4:0), + s(emc_dll_xform_dq0, 22:12, pmc_scratch96, 15:5), + s(emc_dll_xform_dq1, 4:0, pmc_scratch96, 20:16), + s(emc_dll_xform_dq1, 22:12, pmc_scratch96, 31:21), + s(emc_dll_xform_dq2, 4:0, pmc_scratch97, 4:0), + s(emc_dll_xform_dq2, 22:12, pmc_scratch97, 15:5), + s(emc_dll_xform_dq3, 4:0, pmc_scratch97, 20:16), + s(emc_dll_xform_dq3, 22:12, pmc_scratch97, 31:21), + s(emc_pre_refresh_req_cnt, 15:0, pmc_scratch98, 15:0), + s(emc_dll_xform_addr0, 4:0, pmc_scratch98, 20:16), + s(emc_dll_xform_addr0, 22:12, pmc_scratch98, 31:21), + s(emc_dll_xform_addr1, 4:0, pmc_scratch99, 4:0), + s(emc_dll_xform_addr1, 22:12, pmc_scratch99, 15:5), + s(emc_dll_xform_addr2, 4:0, pmc_scratch99, 20:16), + s(emc_dll_xform_addr2, 22:12, pmc_scratch99, 31:21), + s(emc_dll_xform_addr3, 4:0, pmc_scratch100, 4:0), + s(emc_dll_xform_addr3, 22:12, pmc_scratch100, 15:5), + s(emc_dll_xform_addr4, 4:0, pmc_scratch100, 20:16), + s(emc_dll_xform_addr4, 22:12, pmc_scratch100, 31:21), + s(emc_dll_xform_addr5, 4:0, pmc_scratch101, 4:0), + s(emc_dll_xform_addr5, 22:12, pmc_scratch101, 15:5), + s(emc_pchg2pden, 5:0, pmc_scratch102, 5:0), + s(emc_act2pden, 5:0, pmc_scratch102, 11:6), + s(emc_rw2pden, 5:0, pmc_scratch102, 17:12), + s(emc_tcke, 5:0, pmc_scratch102, 23:18), + s(emc_trpab, 5:0, pmc_scratch102, 29:24), + s(emc_fbio_cfg5, 8:7, pmc_scratch102, 31:30), + s(emc_ctt, 5:0, pmc_scratch103, 5:0), + s(emc_einput, 5:0, pmc_scratch103, 11:6), + s(emc_puterm_extra, 21:16, pmc_scratch103, 17:12), + s(emc_tckesr, 5:0, pmc_scratch103, 23:18), + s(emc_tpd, 5:0, pmc_scratch103, 29:24), + s(emc_fbio_cfg5, 10:9, pmc_scratch103, 31:30), + s(emc_rdv_mask, 5:0, pmc_scratch104, 5:0), + s(emc_xm2cmdpadctrl4, 0:0, pmc_scratch104, 6:6), + s(emc_xm2cmdpadctrl4, 2:2, pmc_scratch104, 7:7), + s(emc_xm2cmdpadctrl4, 4:4, pmc_scratch104, 8:8), + s(emc_xm2cmdpadctrl4, 6:6, pmc_scratch104, 9:9), + s(emc_xm2cmdpadctrl4, 8:8, pmc_scratch104, 10:10), + s(emc_xm2cmdpadctrl4, 10:10, pmc_scratch104, 11:11), + s(emc_qpop, 5:0, pmc_scratch104, 17:12), + s(mc_emem_arb_timing_rcd, 5:0, pmc_scratch104, 23:18), + s(mc_emem_arb_timing_ras, 5:0, pmc_scratch104, 29:24), + s(emc_fbio_cfg5, 12:11, pmc_scratch104, 31:30), + s(mc_emem_arb_timing_rap2pre, 5:0, pmc_scratch105, 5:0), + s(mc_emem_arb_timing_r2w, 5:0, pmc_scratch105, 11:6), + s(mc_emem_arb_timing_w2r, 5:0, pmc_scratch105, 17:12), + s(emc_ibdly, 4:0, pmc_scratch105, 22:18), + s(mc_emem_arb_timing_r2r, 4:0, pmc_scratch105, 27:23), + s(emc_w2w, 3:0, pmc_scratch105, 31:28), + s(mc_emem_arb_timing_w2w, 4:0, pmc_scratch106, 4:0), + s(mc_emem_arb_override, 27:27, pmc_scratch106, 5:5), + s(mc_emem_arb_override, 26:26, pmc_scratch106, 6:6), + s(mc_emem_arb_override, 16:16, pmc_scratch106, 7:7), + s(mc_emem_arb_override, 10:10, pmc_scratch106, 8:8), + s(mc_emem_arb_override, 4:4, pmc_scratch106, 9:9), + s(emc_wdv_mask, 3:0, pmc_scratch106, 13:10), + s(emc_ctt_duration, 3:0, pmc_scratch106, 17:14), + s(emc_quse_width, 3:0, pmc_scratch106, 21:18), + s(emc_puterm_width, 3:0, pmc_scratch106, 25:22), + s(emc_bgbias_ctl0, 3:0, pmc_scratch106, 29:26), + s(emc_fbio_cfg5, 25:24, pmc_scratch106, 31:30), + s(mc_emem_arb_timing_rrd, 3:0, pmc_scratch107, 3:0), + s(emc_fbio_cfg5, 23:20, pmc_scratch107, 10:7), + s(emc_fbio_cfg5, 15:13, pmc_scratch107, 13:11), + s(emc_cfg2, 5:3, pmc_scratch107, 16:14), + s(emc_fbio_cfg5, 26:26, pmc_scratch107, 17:17), + s(emc_fbio_cfg5, 28:28, pmc_scratch107, 18:18), + s(emc_cfg2, 2:0, pmc_scratch107, 21:19), + s(emc_cfg2, 7:6, pmc_scratch107, 23:22), + s(emc_cfg2, 15:10, pmc_scratch107, 29:24), + s(emc_cfg2, 23:22, pmc_scratch107, 31:30), + s(emc_cfg2, 25:24, pmc_scratch108, 1:0), + s(emc_cfg2, 31:28, pmc_scratch108, 5:2), + s(bootrom_patch_data, 31:0, pmc_scratch15, 31:0), + s(bootrom_patch_control, 31:0, pmc_scratch16, 31:0), + s(emc_dev_select, 1:0, pmc_scratch17, 31:30), + s(emc_zcal_warmcoldboot_enables, 1:0, pmc_scratch18, 31:30), + s(emc_cfg_dig_dll_period_warmboot, 1:0, pmc_scratch19, 31:30), + s(emc_warmboot_extra_modereg_write_en, 0:0, pmc_scratch46, 30:30), + s(mc_clken_override_all_warmboot, 0:0, pmc_scratch46, 31:31), + s(emc_clken_override_all_warmboot, 0:0, pmc_scratch47, 30:30), + s(emc_mrs_warmboot_enable, 0:0, pmc_scratch47, 31:31), + s(emc_timing_control_wait, 7:0, pmc_scratch57, 27:20), + s(emc_zcal_warmboot_wait, 7:0, pmc_scratch58, 27:20), + s(emc_auto_cal_wait, 7:0, pmc_scratch59, 27:20), + s(warmboot_wait, 7:0, pmc_scratch60, 27:20), + s(emc_pin_program_wait, 7:0, pmc_scratch61, 27:20), + s(ahb_arb_xbar_ctrl_mem_init_done, 0:0, pmc_scratch79, 30:30), + s(emc_extra_refresh_num, 2:0, pmc_scratch81, 31:29), + s(swizzle_rank_byte_encode, 15:0, pmc_scratch101, 31:16), + s(memory_type, 2:0, pmc_scratch107, 6:4), +}; + +struct pack_fields pack_list_ddr3[] = { + s(emc_mrs, 13:0, pmc_scratch5, 13:0), + s(emc_emrs, 13:0, pmc_scratch5, 27:14), + s(emc_mrs, 21:20, pmc_scratch5, 29:28), + s(emc_mrs, 31:30, pmc_scratch5, 31:30), + s(emc_emrs2, 13:0, pmc_scratch7, 13:0), + s(emc_emrs, 21:20, pmc_scratch7, 15:14), + s(emc_emrs, 31:30, pmc_scratch7, 17:16), + s(emc_emrs2, 21:20, pmc_scratch7, 19:18), + s(emc_emrs3, 13:0, pmc_scratch8, 13:0), + s(emc_emrs2, 31:30, pmc_scratch8, 15:14), + s(emc_emrs3, 21:20, pmc_scratch8, 17:16), + s(emc_emrs3, 31:30, pmc_scratch8, 19:18), + s(emc_warmboot_mrs_extra, 13:0, pmc_scratch9, 13:0), + s(emc_warmboot_mrs_extra, 31:30, pmc_scratch9, 15:14), + s(emc_warmboot_mrs_extra, 21:20, pmc_scratch9, 17:16), + s(emc_zq_cal_ddr3_warmboot, 31:30, pmc_scratch9, 19:18), + s(emc_mrs, 27:26, pmc_scratch10, 1:0), + s(emc_emrs, 27:26, pmc_scratch10, 3:2), + s(emc_emrs2, 27:26, pmc_scratch10, 5:4), + s(emc_emrs3, 27:26, pmc_scratch10, 7:6), + s(emc_warmboot_mrs_extra, 27:27, pmc_scratch10, 8:8), + s(emc_warmboot_mrs_extra, 26:26, pmc_scratch10, 9:9), + s(emc_zq_cal_ddr3_warmboot, 0:0, pmc_scratch10, 10:10), + s(emc_zq_cal_ddr3_warmboot, 4:4, pmc_scratch10, 11:11), + c(0, 31:0, pmc_scratch116, 31:0), + c(0, 31:0, pmc_scratch117, 31:0), +}; + +struct pack_fields pack_list_lpddr2[] = { + s(emc_mrw_lpddr2_zcal_warmboot, 23:16, pmc_scratch5, 7:0), + s(emc_mrw_lpddr2_zcal_warmboot, 7:0, pmc_scratch5, 15:8), + s(emc_warmboot_mrw_extra, 23:16, pmc_scratch5, 23:16), + s(emc_warmboot_mrw_extra, 7:0, pmc_scratch5, 31:24), + s(emc_mrw_lpddr2_zcal_warmboot, 31:30, pmc_scratch6, 1:0), + s(emc_warmboot_mrw_extra, 31:30, pmc_scratch6, 3:2), + s(emc_mrw_lpddr2_zcal_warmboot, 27:26, pmc_scratch6, 5:4), + s(emc_warmboot_mrw_extra, 27:26, pmc_scratch6, 7:6), + s(emc_mrw1, 7:0, pmc_scratch7, 7:0), + s(emc_mrw1, 23:16, pmc_scratch7, 15:8), + s(emc_mrw1, 27:26, pmc_scratch7, 17:16), + s(emc_mrw1, 31:30, pmc_scratch7, 19:18), + s(emc_mrw2, 7:0, pmc_scratch8, 7:0), + s(emc_mrw2, 23:16, pmc_scratch8, 15:8), + s(emc_mrw2, 27:26, pmc_scratch8, 17:16), + s(emc_mrw2, 31:30, pmc_scratch8, 19:18), + s(emc_mrw3, 7:0, pmc_scratch9, 7:0), + s(emc_mrw3, 23:16, pmc_scratch9, 15:8), + s(emc_mrw3, 27:26, pmc_scratch9, 17:16), + s(emc_mrw3, 31:30, pmc_scratch9, 19:18), + s(emc_mrw4, 7:0, pmc_scratch10, 7:0), + s(emc_mrw4, 23:16, pmc_scratch10, 15:8), + s(emc_mrw4, 27:26, pmc_scratch10, 17:16), + s(emc_mrw4, 31:30, pmc_scratch10, 19:18), +}; + +struct pack_fields pack_list_2[] = { + s(mc_video_protect_gpu_override0, 31:0, pmc_secure_scratch8, 31:0), + s(mc_video_protect_vpr_override, 3:0, pmc_secure_scratch9, 3:0), + s(mc_video_protect_vpr_override, 11:6, pmc_secure_scratch9, 9:4), + s(mc_video_protect_vpr_override, 23:14, pmc_secure_scratch9, 19:10), + s(mc_video_protect_vpr_override, 26:26, pmc_secure_scratch9, 20:20), + s(mc_video_protect_vpr_override, 31:29, pmc_secure_scratch9, 23:21), + s(emc_fbio_cfg5, 19:16, pmc_secure_scratch9, 27:24), + s(mc_display_snap_ring, 1:0, pmc_secure_scratch9, 29:28), + s(mc_display_snap_ring, 31:31, pmc_secure_scratch9, 30:30), + s(emc_adr_cfg, 0:0, pmc_secure_scratch9, 31:31), + s(mc_video_protect_gpu_override1, 15:0, pmc_secure_scratch10, 15:0), + s(mc_emem_adr_cfg_bank_mask0, 15:0, pmc_secure_scratch10, 31:16), + s(mc_emem_adr_cfg_bank_mask1, 15:0, pmc_secure_scratch11, 15:0), + s(mc_emem_adr_cfg_bank_mask2, 15:0, pmc_secure_scratch11, 31:16), + s(mc_emem_cfg, 13:0, pmc_secure_scratch12, 13:0), + s(mc_emem_cfg, 31:31, pmc_secure_scratch12, 14:14), + s(mc_video_protect_bom, 31:20, pmc_secure_scratch12, 26:15), + s(mc_video_protect_vpr_override1, 1:0, pmc_secure_scratch12, 28:27), + s(mc_video_protect_vpr_override1, 4:4, pmc_secure_scratch12, 29:29), + s(mc_video_protect_bom_adr_hi, 1:0, pmc_secure_scratch12, 31:30), + s(mc_video_protect_size_mb, 11:0, pmc_secure_scratch13, 11:0), + s(mc_sec_carveout_bom, 31:20, pmc_secure_scratch13, 23:12), + s(mc_emem_adr_cfg_bank_swizzle3, 2:0, pmc_secure_scratch13, 26:24), + s(mc_video_protect_write_access, 1:0, pmc_secure_scratch13, 28:27), + s(mc_sec_carveout_adr_hi, 1:0, pmc_secure_scratch13, 30:29), + s(mc_emem_adr_cfg, 0:0, pmc_secure_scratch13, 31:31), + s(mc_sec_carveout_size_mb, 11:0, pmc_secure_scratch14, 11:0), + s(mc_mts_carveout_bom, 31:20, pmc_secure_scratch14, 23:12), + s(mc_mts_carveout_adr_hi, 1:0, pmc_secure_scratch14, 25:24), + s(mc_sec_carveout_protect_write_access, 0:0, pmc_secure_scratch14, 26:26), + s(mc_mts_carveout_reg_ctrl, 0:0, pmc_secure_scratch14, 27:27), + s(mc_mts_carveout_size_mb, 11:0, pmc_secure_scratch15, 11:0), + s(mc_emem_adr_cfg_dev0, 2:0, pmc_secure_scratch15, 14:12), + s(mc_emem_adr_cfg_dev0, 9:8, pmc_secure_scratch15, 16:15), + s(mc_emem_adr_cfg_dev0, 19:16, pmc_secure_scratch15, 20:17), + s(mc_emem_adr_cfg_dev1, 2:0, pmc_secure_scratch15, 23:21), + s(mc_emem_adr_cfg_dev1, 9:8, pmc_secure_scratch15, 25:24), + s(mc_emem_adr_cfg_dev1, 19:16, pmc_secure_scratch15, 29:26), + c(0x1555555, 25:0, pmc_sec_disable2, 25:0), + c(0xff, 7:0, pmc_sec_disable, 19:12), + c(0, 31:0, pmc_scratch2, 31:0), + m(pllm_base, 15:0, pmc_scratch2, 15:0), + m(pllm_base, 20:20, pmc_scratch2, 16:16), + m(pllm_misc2, 2:0, pmc_scratch2, 19:17), + c(0, 31:0, pmc_scratch35, 31:0), + m(pllm_misc1, 23:0, pmc_scratch35, 23:0), + m(pllm_misc1, 30:28, pmc_scratch35, 30:28), + c(0, 31:0, pmc_scratch3, 31:0), + s(pllm_input_divider, 7:0, pmc_scratch3, 7:0), + c(0x3e, 7:0, pmc_scratch3, 15:8), + c(0, 3:0, pmc_scratch3, 19:16), + s(pllm_kvco, 0:0, pmc_scratch3, 20:20), + s(pllm_kcp, 1:0, pmc_scratch3, 22:21), + c(0, 31:0, pmc_scratch36, 31:0), + s(pllm_setup_control, 23:0, pmc_scratch36, 23:0), + c(0, 31:0, pmc_scratch4, 31:0), + s(pllm_stable_time, 9:0, pmc_scratch4, 9:0), + s(pllm_stable_time, 9:0, pmc_scratch4, 19:10), + s(pllm_select_div2, 0:0, pmc_pllm_wb0_override2, 27:27), + c(1, 0:0, pmc_pllp_wb0_override, 11:11), +}; + +#endif /* _TEGRA124_WB_PARAM_H_ */ diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c index d01abcee13..5306a56aab 100644 --- a/board/nvidia/common/board.c +++ b/board/nvidia/common/board.c @@ -40,6 +40,7 @@ #include <i2c.h> #include <spi.h> #include "emc.h" +#include <libfdt.h> DECLARE_GLOBAL_DATA_PTR; @@ -164,9 +165,6 @@ int board_init(void) #ifdef CONFIG_TEGRA_LP0 /* save Sdram params to PMC 2, 4, and 24 for WB0 */ warmboot_save_sdram_params(); - - /* prepare the WB code to LP0 location */ - warmboot_prepare_code(TEGRA_LP0_ADDR, TEGRA_LP0_SIZE); #endif return 0; @@ -201,6 +199,34 @@ int board_late_init(void) /* Make sure we finish initing the LCD */ tegra_lcd_check_next_stage(gd->fdt_blob, 1); #endif + +#ifdef CONFIG_TEGRA_LP0 + /* prepare the WB code to LP0 location */ + warmboot_prepare_code(TEGRA_LP0_ADDR, TEGRA_LP0_SIZE); +#endif + +#ifdef CONFIG_TEGRA124 + if (getenv_yesno("recovery") != 1) { + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + unsigned int scratch = readl(&pmc->pmc_scratch0); + + writel(scratch & ~(1 << 30) & ~(1 << 31), &pmc->pmc_scratch0); + if (scratch & (1 << 30)) { + printf("Found reboot-mode = bootloader!\n"); + do_fastboot(NULL, 0, 0, NULL); + setenv("recovery", "0"); + } + else if (scratch & (1 << 31)) { + printf("Found reboot-mode = recovery!\n"); + setenv("recovery", "1"); + } + else { + printf("No reboot-mode found\n"); + setenv("recovery", "0"); + } + } +#endif + return 0; } @@ -253,3 +279,129 @@ void pad_init_mmc(struct mmc_host *host) #endif /* T30 */ } #endif /* MMC */ + +#ifdef CONFIG_SERIAL_TAG +void get_board_serial(struct tag_serialnr *serialnr) +{ + /* + * Check if we can read the EEPROM serial number + * and if so, use it instead. + */ +#if defined(CONFIG_SERIAL_EEPROM) + uchar data_buffer[NUM_SERIAL_ID_BYTES]; + + i2c_set_bus_num(EEPROM_I2C_BUS); + + if (i2c_read(EEPROM_I2C_ADDRESS, EEPROM_SERIAL_OFFSET, + 1, data_buffer, NUM_SERIAL_ID_BYTES)) { + printf("%s: I2C read of bus %d chip %d addr %d failed!\n", + __func__, EEPROM_I2C_BUS, EEPROM_I2C_ADDRESS, + EEPROM_SERIAL_OFFSET); + } else { +#ifdef DEBUG + int i; + printf("get_board_serial: Got "); + for (i = 0; i < NUM_SERIAL_ID_BYTES; i++) + printf("%02X:", data_buffer[i]); + printf("\n"); +#endif + serialnr->high = data_buffer[2]; + serialnr->high |= (u32)data_buffer[3] << 8; + serialnr->high |= (u32)data_buffer[0] << 16; + serialnr->high |= (u32)data_buffer[1] << 24; + + serialnr->low = data_buffer[7]; + serialnr->low |= (u32)data_buffer[6] << 8; + serialnr->low |= (u32)data_buffer[5] << 16; + serialnr->low |= (u32)data_buffer[4] << 24; + + printf("SEEPROM serialnr->high = %08X, ->low = %08X\n", + serialnr->high, serialnr->low); + } +#else + debug("No serial EEPROM onboard, using default values\n"); + + /* pass board id to kernel */ + serialnr->high = CONFIG_TEGRA_SERIAL_HIGH; + serialnr->low = CONFIG_TEGRA_SERIAL_LOW; + /* TODO: use FDT */ + + debug("Config file serialnr->high = %08X, ->low = %08X\n", + serialnr->high, serialnr->low); + +#endif /* SERIAL_EEPROM */ +} + +#ifdef CONFIG_OF_BOARD_SETUP +void fdt_serial_tag_setup(void *blob, bd_t *bd) +{ + struct tag_serialnr serialnr; + int offset, ret; + u32 val; + + offset = fdt_path_offset(blob, "/chosen/board_info"); + if (offset < 0) { + int chosen = fdt_path_offset(blob, "/chosen"); + offset = fdt_add_subnode(blob, chosen, "board_info"); + if (offset < 0) { + printf("ERROR: add node /chosen/board_info: %s.\n", + fdt_strerror(offset)); + return; + } + } + + get_board_serial(&serialnr); + + val = (serialnr.high & 0xFF0000) >> 16; + val |= (serialnr.high & 0xFF000000) >> 16; + val = cpu_to_fdt32(val); + ret = fdt_setprop(blob, offset, "id", &val, sizeof(val)); + if (ret < 0) { + printf("ERROR: could not update id property %s.\n", + fdt_strerror(ret)); + } + + val = serialnr.high & 0xFFFF; + val = cpu_to_fdt32(val); + ret = fdt_setprop(blob, offset, "sku", &val, sizeof(val)); + if (ret < 0) { + printf("ERROR: could not update sku property %s.\n", + fdt_strerror(ret)); + } + + val = serialnr.low >> 24; + val = cpu_to_fdt32(val); + ret = fdt_setprop(blob, offset, "fab", &val, sizeof(val)); + if (ret < 0) { + printf("ERROR: could not update fab property %s.\n", + fdt_strerror(ret)); + } + + val = (serialnr.low >> 16) & 0xFF; + val = cpu_to_fdt32(val); + ret = fdt_setprop(blob, offset, "major_revision", &val, sizeof(val)); + if (ret < 0) { + printf("ERROR: could not update major_revision property %s.\n", + fdt_strerror(ret)); + } + + val = (serialnr.low >> 8) & 0xFF; + val = cpu_to_fdt32(val); + ret = fdt_setprop(blob, offset, "minor_revision", &val, sizeof(val)); + if (ret < 0) { + printf("ERROR: could not update minor_revision property %s.\n", + fdt_strerror(ret)); + } +} +#endif /* OF_BOARD_SETUP */ +#endif /* SERIAL_TAG */ + +#ifdef CONFIG_OF_BOARD_SETUP +void ft_board_setup(void *blob, bd_t *bd) +{ + /* Overwrite DT file with right board info properties */ +#ifdef CONFIG_SERIAL_TAG + fdt_serial_tag_setup(blob, bd); +#endif /* SERIAL_TAG */ +} +#endif /* OF_BOARD_SETUP */ diff --git a/board/nvidia/jetson-tk1/jetson-tk1.c b/board/nvidia/jetson-tk1/jetson-tk1.c index 5d37718f3b..9e6c4d4e3d 100644 --- a/board/nvidia/jetson-tk1/jetson-tk1.c +++ b/board/nvidia/jetson-tk1/jetson-tk1.c @@ -8,8 +8,11 @@ #include <common.h> #include <asm/arch/gpio.h> #include <asm/arch/pinmux.h> +#include <asm/gpio.h> #include "pinmux-config-jetson-tk1.h" +#define KEY_RECOVERY_GPIO GPIO_PI1 + /* * Routine: pinmux_init * Description: Do individual peripheral pinmux configs @@ -27,3 +30,39 @@ void pinmux_init(void) pinmux_config_drvgrp_table(jetson_tk1_drvgrps, ARRAY_SIZE(jetson_tk1_drvgrps)); } + +#ifdef CONFIG_MISC_INIT_R +int misc_init_r(void) +{ + int bootdelay = 2; + int abort = 0; + unsigned long ts; + + /* Get GPIOs */ + gpio_request(KEY_RECOVERY_GPIO, "recovery_btn"); + + printf("Checking for recovery ...\n"); + /* delay 1000 ms */ + while ((bootdelay > 0) && (!abort)) { + --bootdelay; + /* delay 1000 ms */ + ts = get_timer(0); + do { + /* check for FORCE_RECOVERY button */ + if (!gpio_get_value(KEY_RECOVERY_GPIO)) { + printf("\n*** RECOVERY BUTTON ***"); + setenv("recovery", "1"); + abort = 1; + } + udelay(10000); + } while (!abort && get_timer(ts) < 1000); + printf("."); + } + printf("\n"); + + /* Free GPIOs */ + gpio_free(KEY_RECOVERY_GPIO); + + return 0; +} +#endif diff --git a/board/nvidia/jetson-tk1/pinmux-config-jetson-tk1.h b/board/nvidia/jetson-tk1/pinmux-config-jetson-tk1.h index d338818a64..eebf5456c1 100644 --- a/board/nvidia/jetson-tk1/pinmux-config-jetson-tk1.h +++ b/board/nvidia/jetson-tk1/pinmux-config-jetson-tk1.h @@ -27,6 +27,7 @@ static const struct tegra_gpio_config jetson_tk1_gpio_inits[] = { GPIO_INIT(H6, IN), GPIO_INIT(H7, OUT0), GPIO_INIT(I0, OUT0), + GPIO_INIT(I1, IN), GPIO_INIT(I2, OUT0), GPIO_INIT(I4, OUT0), GPIO_INIT(I5, IN), @@ -151,7 +152,7 @@ static const struct pmux_pingrp_config jetson_tk1_pingrps[] = { PINCFG(PH6, DEFAULT, UP, NORMAL, INPUT, DEFAULT, DEFAULT), PINCFG(PH7, DEFAULT, NORMAL, NORMAL, OUTPUT, DEFAULT, DEFAULT), PINCFG(PI0, DEFAULT, NORMAL, NORMAL, OUTPUT, DEFAULT, DEFAULT), - PINCFG(PI1, RSVD1, DOWN, TRISTATE, OUTPUT, DEFAULT, DEFAULT), + PINCFG(PI1, DEFAULT, UP, TRISTATE, INPUT, DEFAULT, DEFAULT), PINCFG(PI2, DEFAULT, NORMAL, NORMAL, OUTPUT, DEFAULT, DEFAULT), PINCFG(PI3, SPI4, NORMAL, NORMAL, OUTPUT, DEFAULT, DEFAULT), PINCFG(PI4, DEFAULT, NORMAL, NORMAL, OUTPUT, DEFAULT, DEFAULT), diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 3265d44f69..34644ffb1a 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -21,6 +21,10 @@ #include <linux/ctype.h> #include <linux/err.h> #include <u-boot/zlib.h> +#ifdef CONFIG_CMD_BOOTAI +#include <android_image.h> +#include <part.h> +#endif DECLARE_GLOBAL_DATA_PTR; @@ -642,6 +646,278 @@ U_BOOT_CMD( ); #endif /* CONFIG_CMD_BOOTZ */ +#ifdef CONFIG_CMD_BOOTAI + +#ifndef CONFIG_CMD_BOOTAI_BOOT_PART +#define CONFIG_CMD_BOOTAI_BOOT_PART "boot" +#endif + +#ifndef CONFIG_CMD_BOOTAI_RECOVERY_PART +#define CONFIG_CMD_BOOTAI_RECOVERY_PART "recovery" +#endif + +void bootimg_print_image_hdr(struct andr_img_hdr *hdr) +{ + int i; + printf (" Image magic: %s\n", hdr->magic); + + printf (" kernel_size: 0x%x\n", hdr->kernel_size); + printf (" kernel_addr: 0x%x\n", hdr->kernel_addr); + + printf (" rdisk_size: 0x%x\n", hdr->ramdisk_size); + printf (" rdisk_addr: 0x%x\n", hdr->ramdisk_addr); + + printf (" second_size: 0x%x\n", hdr->second_size); + printf (" second_addr: 0x%x\n", hdr->second_addr); + + printf (" tags_addr: 0x%x\n", hdr->tags_addr); + printf (" page_size: 0x%x\n", hdr->page_size); + + printf (" dt_size: 0x%x\n", hdr->dt_size); + + printf (" name: %s\n", hdr->name); + printf (" cmdline: %s\n", hdr->cmdline); + + for (i=0;i<8;i++) + printf (" id[%d]: 0x%x\n", i, hdr->id[i]); +} + +#define _ALIGN(n,pagesz) ((n + (pagesz - 1)) & (~(pagesz - 1))) + +int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); + +int do_bootai(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + u32 addr; + u32 fdt_addr = 0; + u32 kernel_addr = 0x81000000; + u32 ramdisk_addr = 0x82100000; + char ptn[16]; + int boot_from_mmc = 0; + struct andr_img_hdr *hdr; + u64 num_sectors; + int status; + u32 mmc_instance = 0; + + if (argc < 2) { + printf("%s: ERROR not enough arguments!!\n", __func__); + return -1; + } + + if (!(strcmp(argv[1], "ram"))) { + boot_from_mmc = 0; + if (argc < 3) { + printf("%s: ERROR not enough arguments for 'ram' call!!\n", __func__); + return -1; + } + addr = simple_strtoul(argv[2], NULL, 16); + } + else { + boot_from_mmc = 1; + if (argc > 1) + mmc_instance = simple_strtoul(argv[1], NULL, 10); + addr = CONFIG_USB_FASTBOOT_BUF_ADDR; + } + if (getenv_yesno("recovery") == 1) + strcpy(ptn, CONFIG_CMD_BOOTAI_RECOVERY_PART); + else + strcpy(ptn, CONFIG_CMD_BOOTAI_BOOT_PART); + + printf("%s: checking fdt_addr = %s\n", __func__, getenv("fdt_addr_r")); + fdt_addr = getenv_ulong("fdt_addr_r", 16, fdt_addr); + if (!fdt_addr) { + printf("%s: invalid fdtaddr in env\n", __func__); + goto fail; + } + + hdr = (struct andr_img_hdr *) addr; + + if (boot_from_mmc) { + int ret; + block_dev_desc_t *dev_desc; + disk_partition_t info; + unsigned sector; + + memset(hdr, 0, sizeof(struct andr_img_hdr)); + + dev_desc = get_dev("mmc", mmc_instance); + if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) { + printf("%s: invalid mmc device\n", __func__); + goto fail; + } + + ret = get_partition_info_efi_by_name(dev_desc, ptn, &info); + if (ret) { + printf("%s: cannot find '%s' partition\n", __func__, ptn); + goto fail; + } + num_sectors = ((sizeof(struct andr_img_hdr) / info.blksz) + 1); + printf("%s: MMC read %llu sectors * blksz(%lu) @ %lu (size= %lu)\n", __func__, num_sectors, info.blksz, info.start, info.size); + dev_desc->block_read(dev_desc->dev, info.start, num_sectors, (void*)hdr); + if (memcmp(hdr->magic, ANDR_BOOT_MAGIC, 8)) { + printf("%s: bad boot image magic\n", __func__); + goto fail; + } + + /* HACK: check if ramdisk_addr is an offset rather than full addr */ + /* HACK: shouldn't need every device to define MEMORY_BASE */ + if (hdr->ramdisk_addr < MEMORY_BASE) + hdr->ramdisk_addr += MEMORY_BASE; + + /* print kernel info */ + bootimg_print_image_hdr(hdr); + printf("\n\nramdisk sector count:%d\n", (int)(hdr->ramdisk_size / info.blksz) + 1); + + /* read kernel */ + sector = info.start + (hdr->page_size / info.blksz); + num_sectors = ((hdr->kernel_size / info.blksz) + 1); +#ifndef CONFIG_CMD_BOOTAI_IGNORE_HDR_ADDR + kernel_addr = hdr->kernel_addr; +#endif + status = dev_desc->block_read(dev_desc->dev, sector, num_sectors, (void*)kernel_addr); + if (status < 0) { + printf("%s: Could not read kernel image\n", __func__); + goto fail; + } + + /* read ramdisk */ + sector += _ALIGN(hdr->kernel_size, hdr->page_size) / info.blksz; + num_sectors = ((hdr->ramdisk_size / info.blksz) + 1); +#ifndef CONFIG_CMD_BOOTAI_IGNORE_HDR_ADDR + ramdisk_addr = hdr->ramdisk_addr; +#endif + status = dev_desc->block_read(dev_desc->dev, sector, num_sectors, (void*)ramdisk_addr); + if(status < 0) { + printf("%s: Could not read ramdisk\n", __func__); + goto fail; + } + + if ((hdr->second_size) && (!hdr->dt_size)) { + /* read devtree */ + sector += _ALIGN(hdr->ramdisk_size, hdr->page_size) / info.blksz; + debug("*** %s::devtree sector (second_size) == %u\n", __func__, sector); + num_sectors = ((hdr->second_size / info.blksz) + 1); + status = dev_desc->block_read(dev_desc->dev, sector, num_sectors, (void*)fdt_addr); + if(status < 0) { + printf("booti: Could not read devtree (second_size)\n"); + goto fail; + } + } + else if (hdr->dt_size) { + /* read devtree (preferring dt_size value */ + sector += _ALIGN(hdr->ramdisk_size, hdr->page_size) / info.blksz; + debug("*** %s::devtree sector (dt_size) == %u\n", __func__, sector); + num_sectors = ((hdr->dt_size / info.blksz) + 1); + status = dev_desc->block_read(dev_desc->dev, sector, num_sectors, (void*)fdt_addr); + if(status < 0) { + printf("%s: Could not read devtree (dt_size)\n", __func__); + goto fail; + } + } + else { + /* load 1mb of DTB partition */ + } + }else { + u32 kaddr, raddr; + + printf("Boot image downloaded using fastboot\n"); + + status = memcmp(hdr->magic, ANDR_BOOT_MAGIC, 8); + if (status != 0) { + printf("%s: bad boot image magic\n", __func__); + goto fail; + } + + /* print kernel info */ + bootimg_print_image_hdr(hdr); + + kaddr = addr + hdr->page_size; + raddr = kaddr + _ALIGN(hdr->kernel_size, hdr->page_size); +#ifndef CONFIG_CMD_BOOTAI_IGNORE_HDR_ADDR + kernel_addr = hdr->kernel_addr; +#endif + memmove((void *) kernel_addr, (void *)kaddr, hdr->kernel_size); + + /* check if ramdisk_addr is an offset rather than full addr */ + if (hdr->ramdisk_addr < MEMORY_BASE) + hdr->ramdisk_addr += MEMORY_BASE; + +#ifndef CONFIG_CMD_BOOTAI_IGNORE_HDR_ADDR + ramdisk_addr = hdr->ramdisk_addr; +#endif + memmove((void *) ramdisk_addr, (void *)raddr, hdr->ramdisk_size); + + raddr += _ALIGN(hdr->ramdisk_size, hdr->page_size); + + if ((hdr->second_size) && (!hdr->dt_size)) { + memmove((void *) fdt_addr, (void *)raddr, hdr->second_size); + } + else if (hdr->dt_size) { + raddr += _ALIGN(hdr->second_size, hdr->page_size); + memmove((void *) fdt_addr, (void *)raddr, hdr->dt_size); + } + else { + /* load 1mb of DTB partition */ + } + } + + // add boot.img cmdline to dtbootargs + if (hdr->cmdline) { + char temp[1024]; /* twice the size as normal */ + char *append = getenv("bootargs_append"); + if (append) { + sprintf(temp, "%s %s", append, hdr->cmdline); + setenv("bootargs", temp); + } + } + + printf("kernel @ %08x (%d)\n", kernel_addr, hdr->kernel_size); + printf("ramdisk @ %08x (%d)\n", ramdisk_addr, hdr->ramdisk_size); + printf("dtb @ %08x (%d)\n", fdt_addr, hdr->second_size); + printf("dt-size (%d)\n", hdr->dt_size); + + status = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START, + &images, 1); + + images.ep = kernel_addr; + images.rd_start = ramdisk_addr; + images.rd_end = ramdisk_addr + hdr->ramdisk_size; + if ((hdr->second_size) && (!hdr->dt_size)) { + images.ft_len = hdr->second_size; + images.ft_addr = (void *)fdt_addr; + } + else if (hdr->dt_size) { + images.ft_len = hdr->dt_size; + images.ft_addr = (void *)fdt_addr; + } + /* + * We are doing the BOOTM_STATE_LOADOS state ourselves, so must + * disable interrupts ourselves + */ + bootm_disable_interrupts(); + + images.os.os = IH_OS_LINUX; + status = do_bootm_states(cmdtp, flag, argc, argv, + BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO | + BOOTM_STATE_OS_GO, + &images, 1); + + printf("%s: Control returned to monitor - resetting...\n", __func__); + return status; + +fail: + return 1; +} + + +U_BOOT_CMD( + bootai, 3, 1, do_bootai, + "bootai - boot android bootimg from memory\n", + "<addr>\n - boot application image stored in memory\n" + "\t'addr' should be the address of boot image which is zImage+ramdisk.img\n" +); +#endif /* CONFIG_CMD_BOOTAI */ + #ifdef CONFIG_CMD_BOOTI /* See Documentation/arm64/booting.txt in the Linux kernel */ struct Image_header { diff --git a/common/cmd_fastboot.c b/common/cmd_fastboot.c index 909616dcb7..e17b3fa232 100644 --- a/common/cmd_fastboot.c +++ b/common/cmd_fastboot.c @@ -11,7 +11,7 @@ #include <command.h> #include <g_dnl.h> -static int do_fastboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +int do_fastboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { int ret; diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c index ca9c4aa15f..5ecc2c97d2 100644 --- a/drivers/mmc/tegra_mmc.c +++ b/drivers/mmc/tegra_mmc.c @@ -332,7 +332,13 @@ static int tegra_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, } len = data->blocks * data->blocksize; - bounce_buffer_start(&bbstate, buf, len, bbflags); + ret = bounce_buffer_start(&bbstate, buf, len, bbflags); + if (ret) { + printf("%s: bounce_buffer_start failed with error %d " + "(buf = %p, len = %u, flags = %u)\n", + __func__, ret, buf, len, bbflags); + return ret; + } } ret = mmc_send_cmd_bounced(mmc, cmd, data, &bbstate); diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c index 71b62e5005..990fcb43de 100644 --- a/drivers/usb/gadget/f_fastboot.c +++ b/drivers/usb/gadget/f_fastboot.c @@ -23,6 +23,11 @@ #ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV #include <fb_mmc.h> #endif +#if defined(CONFIG_TEGRA124) +#include <asm/io.h> +#include <asm/arch-tegra/pmc.h> +#include <android_image.h> +#endif #define FASTBOOT_VERSION "0.4" @@ -319,6 +324,18 @@ static void compl_do_reset(struct usb_ep *ep, struct usb_request *req) static void cb_reboot(struct usb_ep *ep, struct usb_request *req) { +#if defined(CONFIG_TEGRA124) + char *cmd = req->buf; + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + if (strncmp("-bootloader", cmd + 6, 11) == 0) { + printf("Setting reboot-bootloader!\n"); + writel(readl(&pmc->pmc_scratch0) | (1 << 30), &pmc->pmc_scratch0); + } + else if (strncmp("-recovery", cmd + 6, 9) == 0) { + printf("Setting reboot-recovery!\n"); + writel(readl(&pmc->pmc_scratch0) | (1 << 31), &pmc->pmc_scratch0); + } +#endif fastboot_func->in_req->complete = compl_do_reset; fastboot_tx_write_str("OKAY"); } @@ -463,12 +480,21 @@ static void cb_download(struct usb_ep *ep, struct usb_request *req) static void do_bootm_on_complete(struct usb_ep *ep, struct usb_request *req) { char boot_addr_start[12]; +#ifdef CONFIG_CMD_BOOTAI + char *bootm_args[] = { "bootai", "ram", boot_addr_start, NULL }; +#else char *bootm_args[] = { "bootm", boot_addr_start, NULL }; +#endif puts("Booting kernel..\n"); +#ifdef CONFIG_CMD_BOOTAI + sprintf(boot_addr_start, "0x%x", CONFIG_USB_FASTBOOT_BUF_ADDR); + do_bootai(NULL, 0, 3, bootm_args); +#else sprintf(boot_addr_start, "0x%lx", load_addr); do_bootm(NULL, 0, 2, bootm_args); +#endif /* This only happens if image is somehow faulty so we start over */ do_reset(NULL, 0, 0, NULL); @@ -502,6 +528,26 @@ static void cb_flash(struct usb_ep *ep, struct usb_request *req) } #endif +static void cb_oem(struct usb_ep *ep, struct usb_request *req) +{ + char *cmd = req->buf; +#if defined(CONFIG_TEGRA124) + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + if (strncmp("recovery", cmd + 4, 8) == 0) { + printf("Setting reboot-recovery!\n"); + writel(readl(&pmc->pmc_scratch0) | (1 << 31), &pmc->pmc_scratch0); + fastboot_func->in_req->complete = compl_do_reset; + fastboot_tx_write_str("OKAY"); + } else +#endif + if (strncmp("unlock", cmd + 4, 8) == 0) { + fastboot_tx_write_str("FAILnot implemented"); + } + else { + fastboot_tx_write_str("FAILunknown oem command"); + } +} + struct cmd_dispatch_info { char *cmd; void (*cb)(struct usb_ep *ep, struct usb_request *req); @@ -527,6 +573,10 @@ static const struct cmd_dispatch_info cmd_dispatch_info[] = { .cb = cb_flash, }, #endif + { + .cmd = "oem", + .cb = cb_oem, + }, }; static void rx_handler_command(struct usb_ep *ep, struct usb_request *req) diff --git a/include/android_image.h b/include/android_image.h index 094d60afe8..e982111484 100644 --- a/include/android_image.h +++ b/include/android_image.h @@ -31,7 +31,8 @@ struct andr_img_hdr { u32 tags_addr; /* physical addr for kernel tags */ u32 page_size; /* flash page size we assume */ - u32 unused[2]; /* future expansion: should be 0 */ + u32 dt_size; /* device tree in bytes */ + u32 unused; /* future expansion: should be 0 */ char name[ANDR_BOOT_NAME_SIZE]; /* asciiz product name */ diff --git a/include/command.h b/include/command.h index 6f06db1cc3..dc1d4ba73b 100644 --- a/include/command.h +++ b/include/command.h @@ -89,12 +89,19 @@ int cmd_process_error(cmd_tbl_t *cmdtp, int err); extern int cmd_get_data_size(char* arg, int default_size); #endif +#ifdef CONFIG_CMD_FASTBOOT +extern int do_fastboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]); +#endif + #ifdef CONFIG_CMD_BOOTD extern int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); #endif #ifdef CONFIG_CMD_BOOTM extern int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); extern int bootm_maybe_autostart(cmd_tbl_t *cmdtp, const char *cmd); +#ifdef CONFIG_CMD_BOOTAI +extern int do_bootai(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); +#endif #else static inline int bootm_maybe_autostart(cmd_tbl_t *cmdtp, const char *cmd) { diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h index be616e8bfd..56cc33745c 100644 --- a/include/config_distro_bootcmd.h +++ b/include/config_distro_bootcmd.h @@ -28,6 +28,25 @@ #define BOOTENV_DEV_NAME_BLKDEV(devtypeu, devtypel, instance) \ #devtypel #instance " " +#ifdef CONFIG_CMD_BOOTAI +#define BOOTENV_DEV_BLKDEV_ANDROID(devtypeu, devtypel, instance) \ + "bootcmd_" #devtypel #instance "=" \ + "if mmc dev " #instance "; " \ + "then setenv devtype mmc; " \ + "setenv devnum " #instance "; " \ + "bootai " #instance "; fi\0" + +#define BOOTENV_SHARED_ANDROID +#define BOOTENV_DEV_ANDROID BOOTENV_DEV_BLKDEV_ANDROID +#define BOOTENV_DEV_NAME_ANDROID BOOTENV_DEV_NAME_BLKDEV +#else +#define BOOTENV_SHARED_ANDROID +#define BOOTENV_DEV_ANDROID \ + BOOT_TARGET_DEVICES_references_ANDROID_without_CONFIG_CMD_BOOTAI +#define BOOTENV_DEV_NAME_ANDROID \ + BOOT_TARGET_DEVICES_references_ANDROID_without_CONFIG_CMD_BOOTAI +#endif + #ifdef CONFIG_CMD_MMC #define BOOTENV_SHARED_MMC BOOTENV_SHARED_BLKDEV(mmc) #define BOOTENV_DEV_MMC BOOTENV_DEV_BLKDEV diff --git a/include/configs/jetson-tk1.h b/include/configs/jetson-tk1.h index d67c025b9c..bf522b6990 100644 --- a/include/configs/jetson-tk1.h +++ b/include/configs/jetson-tk1.h @@ -10,8 +10,36 @@ #include <linux/sizes.h> +/* LP0 suspend / resume */ +#define CONFIG_TEGRA_LP0 +#define CONFIG_AES + #include "tegra124-common.h" +#ifdef CONFIG_SYS_MALLOC_LEN +#undef CONFIG_SYS_MALLOC_LEN +#endif +#define CONFIG_SYS_MALLOC_LEN (128 << 20) /* 128MB for fastboot bounce_buffer */ + +#ifdef CONFIG_TEGRA_LP0 +#define CONFIG_TEGRA124_LP0 +#endif + +#define CONFIG_OF_LIBFDT +#define CONFIG_OF_BOARD_SETUP +#define CONFIG_MISC_INIT_R /* call misc_init_r during start up */ + +#define CONFIG_SETUP_MEMORY_TAGS 1 +#define CONFIG_INITRD_TAG 1 +#define CONFIG_SERIAL_TAG 1 + +/* The following are used to retrieve the board id from an eeprom */ +#define CONFIG_SERIAL_EEPROM +#define EEPROM_I2C_BUS 1 +#define EEPROM_I2C_ADDRESS 0x56 +#define EEPROM_SERIAL_OFFSET 0x04 +#define NUM_SERIAL_ID_BYTES 8 + /* High-level configuration options */ #define V_PROMPT "Tegra124 (Jetson TK1) # " #define CONFIG_TEGRA_BOARD_STRING "NVIDIA Jetson TK1" @@ -22,6 +50,7 @@ #define CONFIG_SYS_NS16550_COM1 NV_PA_APB_UARTD_BASE #define CONFIG_BOARD_EARLY_INIT_F +#define CONFIG_BOARD_LATE_INIT /* I2C */ #define CONFIG_SYS_I2C_TEGRA @@ -70,6 +99,36 @@ #define CONFIG_CMD_NET #define CONFIG_CMD_DHCP +/* Fastboot support */ +#define CONFIG_CMD_FASTBOOT + +#ifdef CONFIG_CMD_FASTBOOT +#define CONFIG_ANDROID_BOOT_IMAGE +#define CONFIG_CMD_BOOTAI +#define CONFIG_CMD_BOOTAI_IGNORE_HDR_ADDR +#define MEMORY_BASE 0x80000000 +#define CONFIG_ADDR_DOWNLOAD (MEMORY_BASE + 0x12000000) +#define CONFIG_USB_FASTBOOT_BUF_ADDR CONFIG_ADDR_DOWNLOAD +#define CONFIG_USB_FASTBOOT_BUF_SIZE 0x40000000 +#define CONFIG_FASTBOOT_FLASH +#define CONFIG_FASTBOOT_FLASH_MMC_DEV 0 +#define BOARD_EXTRA_ENV_SETTINGS \ + "bootargs_append=" \ + "init=init console=ttyS0,115200n8 " \ + "lp0_vec=2064@0xf46ff000 mem=1862M@2048M vpr=151M@3945M tsec=32M@3913M " \ + "core_edp_mv=1150 core_edp_ma=4000 " \ + "tegraid=40.1.1.0.0 tegra_fbmem=32899072@0xad012000 fbcon=map:1 " \ + "video=tegrafb memtype=255 ddr_die=2048M@2048M section=256M " \ + "debug_uartport=lsport,3 " \ + "power_supply=Adapter audio_codec=rt5640 " \ + "modem_id=0 commchip_id=0 " \ + "usbcore.old_scheme_first=1 usb_port_owner_info=0 " \ + "lane_owner_info=6 emc_max_dvfs=0 touch_id=0@0 " \ + "pmuboard=0x0177:0x0000:0x02:0x43:0x00 " \ + "otf_key=c75e5bb91eb3bd947560357b64422f85 " \ + "board_info=0x0177:0x0000:0x02:0x43:0x00\0" +#endif + #include "tegra-common-usb-gadget.h" #include "tegra-common-post.h" diff --git a/include/configs/tegra-common-post.h b/include/configs/tegra-common-post.h index 23e3c8af31..dfe0229934 100644 --- a/include/configs/tegra-common-post.h +++ b/include/configs/tegra-common-post.h @@ -9,12 +9,24 @@ #define __TEGRA_COMMON_POST_H #ifndef CONFIG_SPL_BUILD +#ifdef CONFIG_CMD_BOOTAI +#define CONFIG_CMD_BOOTAI_BOOT_PART "LNX" +#define CONFIG_CMD_BOOTAI_RECOVERY_PART "SOS" #define BOOT_TARGET_DEVICES(func) \ func(MMC, mmc, 1) \ + func(ANDROID, android, 0) \ func(MMC, mmc, 0) \ func(USB, usb, 0) \ func(PXE, pxe, na) \ func(DHCP, dhcp, na) +#else +#define BOOT_TARGET_DEVICES(func) \ + func(MMC, mmc, 1) \ + func(MMC, mmc, 0) \ + func(USB, usb, 0) \ + func(PXE, pxe, na) \ + func(DHCP, dhcp, na) +#endif #include <config_distro_bootcmd.h> #else #define BOOTENV diff --git a/include/configs/tegra-common-usb-gadget.h b/include/configs/tegra-common-usb-gadget.h index 287460c132..ea3794feb3 100644 --- a/include/configs/tegra-common-usb-gadget.h +++ b/include/configs/tegra-common-usb-gadget.h @@ -15,8 +15,14 @@ #define CONFIG_CI_UDC #define CONFIG_CI_UDC_HAS_HOSTPC #define CONFIG_USB_GADGET_DUALSPEED +#ifdef CONFIG_CMD_FASTBOOT +/* Use Google fastboot vid/pid */ +#define CONFIG_G_DNL_VENDOR_NUM 0x18d1 +#define CONFIG_G_DNL_PRODUCT_NUM 0x0100 +#else #define CONFIG_G_DNL_VENDOR_NUM 0x0955 #define CONFIG_G_DNL_PRODUCT_NUM 0x701A +#endif #define CONFIG_G_DNL_MANUFACTURER "NVIDIA" #define CONFIG_USBDOWNLOAD_GADGET /* USB mass storage protocol */ diff --git a/include/configs/tegra-common.h b/include/configs/tegra-common.h index 834b3d5686..ed80b45bfe 100644 --- a/include/configs/tegra-common.h +++ b/include/configs/tegra-common.h @@ -105,7 +105,7 @@ * Increasing the size of the IO buffer as default nfsargs size is more * than 256 and so it is not possible to edit it */ -#define CONFIG_SYS_CBSIZE (256 * 2) /* Console I/O Buffer Size */ +#define CONFIG_SYS_CBSIZE (512 * 2) /* Console I/O Buffer Size */ /* Print Buffer Size */ #define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + \ sizeof(CONFIG_SYS_PROMPT) + 16) diff --git a/include/configs/tegra124-common.h b/include/configs/tegra124-common.h index 61e5026574..9fe04f81de 100644 --- a/include/configs/tegra124-common.h +++ b/include/configs/tegra124-common.h @@ -76,4 +76,10 @@ #define CONFIG_USB_EHCI_TXFIFO_THRESH 0x10 #define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 1 +#ifdef CONFIG_TEGRA_LP0 +#define TEGRA_LP0_ADDR 0xF46FF000 +#define TEGRA_LP0_SIZE 0x2000 +#define TEGRA_LP0_ALIGN 0x10 +#endif + #endif /* _TEGRA124_COMMON_H_ */ |