Skip to contentSkip to conversation

tegra: warmboot (suspend / resume) support

PATCH Superseded Simon Glass 5 participants 51 messages Dec 26, 2011 – Jan 14, 2012

Subsystems (3)

v1 of 4 Superseded Latest is v4 →

lore
Share & tools
lore
#0 lore raw

cover tegra: warmboot (suspend / resume) support

This series adds support for warm boot, allowing the device to suspend and resume. U-Boot sets up some 'warm boot' code in a special area such that the SOC can find it on a resume. This code is responsible for setting up memory and clocked and then allowing the OS to continue where it left off.

Jimmy Zhang (4):
tegra: Add EMC support for optimal memory timings
tegra: Add PMU to manage power supplies
tegra: Set vdd_core and vdd_cpu to high
tegra: Add EMC settings for Seaboard, Harmony

Simon Glass (5):
tegra: Move ap20.h header into arch location
tegra: Add tegra_get_chip_type() to detect SKU
tegra: Set up PMU for Nvidia boards
tegra: Set up warmboot code on Nvidia boards
tegra: Enable LP0 on Seaboard

Yen Lin (5):
Add AES crypto library
tegra: Add crypto library for warmboot code
tegra: Add flow, gp_padctl, fuse, sdram headers
tegra: Add warmboot implementation
tegra: Setup PMC scratch info from ap20 setup

 arch/arm/cpu/armv7/tegra2/Makefile                 |    8 +-
 arch/arm/cpu/armv7/tegra2/ap20.c                   |   32 +-
 arch/arm/cpu/armv7/tegra2/board.c                  |    4 +-
 arch/arm/cpu/armv7/tegra2/crypto.c                 |  234 ++++++++
 arch/arm/cpu/armv7/tegra2/crypto.h                 |   36 ++
 arch/arm/cpu/armv7/tegra2/emc.c                    |  165 ++++++
 arch/arm/cpu/armv7/tegra2/pmu.c                    |  355 ++++++++++++
 arch/arm/cpu/armv7/tegra2/warmboot.c               |  444 +++++++++++++++
 arch/arm/cpu/armv7/tegra2/warmboot_avp.c           |  312 ++++++++++
 arch/arm/cpu/armv7/tegra2/warmboot_avp.h           |   81 +++
 .../tegra2 => include/asm/arch-tegra2}/ap20.h      |    7 +
 arch/arm/include/asm/arch-tegra2/emc.h             |  107 ++++
 arch/arm/include/asm/arch-tegra2/flow.h            |   36 ++
 arch/arm/include/asm/arch-tegra2/fuse.h            |   39 ++
 arch/arm/include/asm/arch-tegra2/gp_padctrl.h      |   64 +++
 arch/arm/include/asm/arch-tegra2/pmu.h             |   63 ++
 arch/arm/include/asm/arch-tegra2/sdram_param.h     |  148 +++++
 arch/arm/include/asm/arch-tegra2/tegra2.h          |   26 +
 arch/arm/include/asm/arch-tegra2/warmboot.h        |   81 +++
 board/nvidia/common/Makefile                       |    1 +
 board/nvidia/common/board.c                        |   37 ++
 board/nvidia/common/emc.c                          |  295 ++++++++++
 board/nvidia/common/emc.h                          |   29 +
 include/aes.h                                      |   70 +++
 include/configs/seaboard.h                         |    7 +
 include/configs/tegra2-common.h                    |   17 +
 lib/Makefile                                       |    1 +
 lib/aes.c                                          |  599 ++++++++++++++++++++
 28 files changed, 3294 insertions(+), 4 deletions(-)
 create mode 100644 arch/arm/cpu/armv7/tegra2/crypto.c
 create mode 100644 arch/arm/cpu/armv7/tegra2/crypto.h
 create mode 100644 arch/arm/cpu/armv7/tegra2/emc.c
 create mode 100644 arch/arm/cpu/armv7/tegra2/pmu.c
 create mode 100644 arch/arm/cpu/armv7/tegra2/warmboot.c
 create mode 100644 arch/arm/cpu/armv7/tegra2/warmboot_avp.c
 create mode 100644 arch/arm/cpu/armv7/tegra2/warmboot_avp.h
 rename arch/arm/{cpu/armv7/tegra2 => include/asm/arch-tegra2}/ap20.h (96%)
 create mode 100644 arch/arm/include/asm/arch-tegra2/emc.h
 create mode 100644 arch/arm/include/asm/arch-tegra2/flow.h
 create mode 100644 arch/arm/include/asm/arch-tegra2/fuse.h
 create mode 100644 arch/arm/include/asm/arch-tegra2/gp_padctrl.h
 create mode 100644 arch/arm/include/asm/arch-tegra2/pmu.h
 create mode 100644 arch/arm/include/asm/arch-tegra2/sdram_param.h
 create mode 100644 arch/arm/include/asm/arch-tegra2/warmboot.h
 create mode 100644 board/nvidia/common/emc.c
 create mode 100644 board/nvidia/common/emc.h
 create mode 100644 include/aes.h
 create mode 100644 lib/aes.c
Signature · 1 line
1.7.3.1
#1 lore raw

PATCH 1/14 Add AES crypto library

From: Yen Lin <[email protected]>

Add support for AES using an implementation form Karl Malbrain. This offers small code size (around 5KB on ARM) and supports 128-bit AES only.

---
 include/aes.h |   70 +++++++
 lib/Makefile  |    1 +
 lib/aes.c     |  599 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 670 insertions(+), 0 deletions(-)
 create mode 100644 include/aes.h
 create mode 100644 lib/aes.c
include/aes.h new file +70 -0
new file mode 100644
index 0000000..41b0db2
@@ -0,0 +1,70 @@
+/*
+ * 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 _AES_REF_H_
+#define _AES_REF_H_
+
+/*
+ * AES encryption library, with small code size, supporting only 128-bit AES
+ *
+ * AES is a stream cipher which works a block at a time, with each block
+ * in this case being AES_KEY_LENGTH bytes.
+ */
+
+enum {
+	AES_STATECOLS	= 4,	/* columns in the state & expanded key */
+	AES_KEYCOLS	= 4,	/* columns in a key */
+	AES_ROUNDS	= 10,	/* rounds in encryption */
+
+	AES_KEY_LENGTH	= 128 / 8,
+	AES_EXPAND_KEY_LENGTH	= 4 * AES_STATECOLS * (AES_ROUNDS + 1),
+};
+
+/**
+ * Expand a key into a key schedule, which is then used for the other
+ * operations.
+ *
+ * \param key		Key, of length AES_KEY_LENGTH bytes
+ * \param expkey	Buffer to place expanded key, AES_EXPAND_KEY_LENGTH
+ */
+void aes_expand_key(u8 *key, u8 *expkey);
+
+/**
+ * Encrypt a single block of data
+ *
+ * in		Input data
+ * expkey	Expanded key to use for encryption (from aes_expand_key())
+ * out		Output data
+ */
+void aes_encrypt(u8 *in, u8 *expkey, u8 *out);
+
+/**
+ * Decrypt a single block of data
+ *
+ * in		Input data
+ * expkey	Expanded key to use for decryption (from aes_expand_key())
+ * out		Output data
+ */
+void aes_decrypt(u8 *in, u8 *expkey, u8 *out);
+
+#endif /* _AES_REF_H_ */
lib/Makefile +1 -0
index 54708c2..df24133 100644
@@ -27,6 +27,7 @@ LIB	= $(obj)libgeneric.o
 
 ifndef CONFIG_SPL_BUILD
 COBJS-$(CONFIG_ADDR_MAP) += addr_map.o
+COBJS-$(CONFIG_AES) += aes.o
 COBJS-$(CONFIG_BZIP2) += bzlib.o
 COBJS-$(CONFIG_BZIP2) += bzlib_crctable.o
 COBJS-$(CONFIG_BZIP2) += bzlib_decompress.o
lib/aes.c new file +599 -0

599 lines not on this page · raw message

Signature · 1 line
1.7.3.1
#2 lore raw

PATCH 1/14 Add AES crypto library

lib/aes.c line 299

Quoted 11 lines · On Monday 26 December 2011 14:32:54 Simon Glass wrote:
lib/aes.c new file +8 -0
 
+static u8 sbox[256] = {
+static u8 inv_sbox[256] = {
+static u8 x2_sbox[256] = {
+static u8 x3_sbox[256] = {
+static u8 x_time_9[256] = {
+static u8 x_time_b[256] = {
+static u8 x_time_d[256] = {
+static u8 x_time_e[256] = {

const

lib/aes.c line 439

Quoted 4 lines
lib/aes.c new file +3 -0
+static void mix_sub_columns(u8 *state)
+{
...
+		 x3_sbox[state[2]] ^       sbox[state[7]];

looks bad whitespace after that ^

Quoted 1 line

+static u8 rcon[11] = {

const
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120108/ea6a1bbb/attachment.pgp>

#3 lore raw

PATCH 1/14 Add AES crypto library

Quoted 22 lines · On Monday 26 December 2011 14:32:54 Simon Glass wrote:

lib/aes.c line 299

Quoted 11 lines
lib/aes.c new file +8 -0
 
+static u8 sbox[256] = {
+static u8 inv_sbox[256] = {
+static u8 x2_sbox[256] = {
+static u8 x3_sbox[256] = {
+static u8 x_time_9[256] = {
+static u8 x_time_b[256] = {
+static u8 x_time_d[256] = {
+static u8 x_time_e[256] = {

const

lib/aes.c line 439

Quoted 4 lines
lib/aes.c new file +3 -0
+static void mix_sub_columns(u8 *state)
+{
...
+		 x3_sbox[state[2]] ^       sbox[state[7]];

looks bad whitespace after that ^

Quoted 4 lines
Quoted 1 line

+static u8 rcon[11] = {

const
-mike

We already have checkpatch in tools ... run it on the series.

M

#4 lore raw

PATCH 1/14 Add AES crypto library

Quoted 22 lines · On Sunday 08 January 2012 03:57:47 Marek Vasut wrote:
Quoted 22 lines · On Monday 26 December 2011 14:32:54 Simon Glass wrote:

lib/aes.c line 299

Quoted 11 lines
lib/aes.c new file +8 -0
 
+static u8 sbox[256] = {
+static u8 inv_sbox[256] = {
+static u8 x2_sbox[256] = {
+static u8 x3_sbox[256] = {
+static u8 x_time_9[256] = {
+static u8 x_time_b[256] = {
+static u8 x_time_d[256] = {
+static u8 x_time_e[256] = {

const

lib/aes.c line 439

Quoted 4 lines
lib/aes.c new file +3 -0
+static void mix_sub_columns(u8 *state)
+{
...
+		 x3_sbox[state[2]] ^       sbox[state[7]];

looks bad whitespace after that ^

Quoted 5 lines
Quoted 3 lines
Quoted 1 line

+static u8 rcon[11] = {

const

We already have checkpatch in tools ... run it on the series.

i don't think checkpatch catches const
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120108/3250cc48/attachment.pgp>

#5 lore raw

PATCH 1/14 Add AES crypto library

Quoted 23 lines · On Sunday 08 January 2012 03:57:47 Marek Vasut wrote:
Quoted 22 lines
Quoted 22 lines · On Monday 26 December 2011 14:32:54 Simon Glass wrote:

lib/aes.c line 299

Quoted 11 lines
lib/aes.c new file +8 -0
 
+static u8 sbox[256] = {
+static u8 inv_sbox[256] = {
+static u8 x2_sbox[256] = {
+static u8 x3_sbox[256] = {
+static u8 x_time_9[256] = {
+static u8 x_time_b[256] = {
+static u8 x_time_d[256] = {
+static u8 x_time_e[256] = {

const

lib/aes.c line 439

Quoted 4 lines
lib/aes.c new file +3 -0
+static void mix_sub_columns(u8 *state)
+{
...
+		 x3_sbox[state[2]] ^       sbox[state[7]];

looks bad whitespace after that ^

Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
Quoted 1 line

+static u8 rcon[11] = {

const

We already have checkpatch in tools ... run it on the series.

i don't think checkpatch catches const
-mike

No, but it catches whitespaces ... M

#6 lore raw

PATCH 1/14 Add AES crypto library

Hi Marek,

Quoted 23 lines · Marek Vasut
Quoted 23 lines · On Sunday 08 January 2012 03:57:47 Marek Vasut wrote:
Quoted 22 lines
Quoted 22 lines · On Monday 26 December 2011 14:32:54 Simon Glass wrote:

lib/aes.c line 299

Quoted 11 lines
lib/aes.c new file +8 -0
 
+static u8 sbox[256] = {
+static u8 inv_sbox[256] = {
+static u8 x2_sbox[256] = {
+static u8 x3_sbox[256] = {
+static u8 x_time_9[256] = {
+static u8 x_time_b[256] = {
+static u8 x_time_d[256] = {
+static u8 x_time_e[256] = {

const

lib/aes.c

Quoted 4 lines
lib/aes.c new file +3 -0
+static void mix_sub_columns(u8 *state)
+{
...
+ ? ? ? ? ? ? ? ?x3_sbox[state[2]] ^ ? ? ? sbox[state[7]];

looks bad whitespace after that ^

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 3 lines
Quoted 1 line

+static u8 rcon[11] = {

const

We already have checkpatch in tools ... run it on the series.

This happened as part of my using patman to submit this series. I just checked it again and there are no warnings.

Quoted 2 lines
Quoted 2 lines

i don't think checkpatch catches const

Nope.

Quoted 3 lines
Quoted 1 line

-mike

No, but it catches whitespaces ... M

Not in this case, unfortunately. Sometimes we still need beady eyes :-)

I will fix these two.

Regards,
Simon

Quoted 4 lines

_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

#7 lore raw

PATCH 2/14 tegra: Move ap20.h header into arch location

In reply to Simon Glass

We want to include this from board code, so move the header into an easily-accessible location.

---
 arch/arm/cpu/armv7/tegra2/ap20.c                   |    2 +-
 arch/arm/cpu/armv7/tegra2/board.c                  |    4 ++--
 .../tegra2 => include/asm/arch-tegra2}/ap20.h      |    0
 3 files changed, 3 insertions(+), 3 deletions(-)
 rename arch/arm/{cpu/armv7/tegra2 => include/asm/arch-tegra2}/ap20.h (100%)
arch/arm/cpu/armv7/tegra2/ap20.c +1 -1
index 3ea2e26..da7128c 100644
@@ -21,9 +21,9 @@
 * MA 02111-1307 USA
 */
 
-#include "ap20.h"
 #include <asm/io.h>
 #include <asm/arch/tegra2.h>
+#include <asm/arch/ap20.h>
 #include <asm/arch/clk_rst.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/pmc.h>
arch/arm/cpu/armv7/tegra2/board.c +2 -2
index 2c91e69..c8b903e 100644
@@ -23,12 +23,12 @@
 
 #include <common.h>
 #include <asm/io.h>
-#include "ap20.h"
+#include <asm/arch/ap20.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/funcmux.h>
+#include <asm/arch/pmc.h>
 #include <asm/arch/sys_proto.h>
 #include <asm/arch/tegra2.h>
-#include <asm/arch/pmc.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
arch/arm/include/asm/arch-tegra2/ap20.h renamed from arch/arm/cpu/armv7/tegra2/ap20.h +0 -0
similarity index 100%
rename from arch/arm/cpu/armv7/tegra2/ap20.h
rename to arch/arm/include/asm/arch-tegra2/ap20.h
Signature · 1 line
1.7.3.1
#8 lore raw

PATCH 3/14 tegra: Add crypto library for warmboot code

In reply to Simon Glass

From: Yen Lin <[email protected]>

Provides an interface to aes.c for the warmboot code.

---
 arch/arm/cpu/armv7/tegra2/crypto.c |  234 ++++++++++++++++++++++++++++++++++++
 arch/arm/cpu/armv7/tegra2/crypto.h |   36 ++++++
 2 files changed, 270 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/cpu/armv7/tegra2/crypto.c
 create mode 100644 arch/arm/cpu/armv7/tegra2/crypto.h
arch/arm/cpu/armv7/tegra2/crypto.c new file +234 -0
new file mode 100644
index 0000000..563ce6b
@@ -0,0 +1,234 @@
+/*
+ * 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 */
+};
+
+#ifdef DEBUG
+static void debug_print_vector(char *name, u32 num_bytes, u8 *data)
+{
+	u32 i;
+
+	printf("%s [%d] @0x%08x", name, num_bytes, (u32)data);
+	for (i = 0; i < num_bytes; i++) {
+		if (i % 16 == 0)
+			printf(" = ");
+		printf("%02x", data[i]);
+		if ((i+1) % 16 != 0)
+			printf(" ");
+	}
+	printf("\n");
+}
+#else
+#define debug_print_vector(name, num_bytes, data)
+#endif
+
+/**
+ * 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);
+}
arch/arm/cpu/armv7/tegra2/crypto.h new file +36 -0
new file mode 100644
index 0000000..aff67e7
@@ -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_ */
Signature · 1 line
1.7.3.1
#9 lore raw

PATCH 3/14 tegra: Add crypto library for warmboot code

Quoted 11 lines · On Monday 26 December 2011 14:32:56 Simon Glass wrote:
arch/arm/cpu/armv7/tegra2/crypto.c new file +8 -0
 
+#ifdef DEBUG
+static void debug_print_vector(char *name, u32 num_bytes, u8 *data)
+{
+	u32 i;
+
+	printf("%s [%d] @0x%08x", name, num_bytes, (u32)data);
+	for (i = 0; i < num_bytes; i++) {
+		if (i % 16 == 0)

arch/arm/cpu/armv7/tegra2/crypto.c line 55

Quoted 10 lines
arch/arm/cpu/armv7/tegra2/crypto.c new file +10 -0
+			printf(" = ");
+		printf("%02x", data[i]);
+		if ((i+1) % 16 != 0)
+			printf(" ");
+	}
+	printf("\n");
+}
+#else
+#define debug_print_vector(name, num_bytes, data)
+#endif

if you used debug() instead of printf(), wouldn't this get optimized without the #ifdef protection ?
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120108/022ecb01/attachment.pgp>

#10 lore raw

PATCH 3/14 tegra: Add crypto library for warmboot code

Hi Mike,

Quoted 17 lines · Mike Frysinger
Quoted 16 lines · On Monday 26 December 2011 14:32:56 Simon Glass wrote:
arch/arm/cpu/armv7/tegra2/crypto.c new file +13 -0
 
+#ifdef DEBUG
+static void debug_print_vector(char *name, u32 num_bytes, u8 *data)
+{
+ ? ? u32 i;
+
+ ? ? printf("%s [%d] @0x%08x", name, num_bytes, (u32)data);
+ ? ? for (i = 0; i < num_bytes; i++) {
+ ? ? ? ? ? ? if (i % 16 == 0)
+ ? ? ? ? ? ? ? ? ? ? printf(" = ");
+ ? ? ? ? ? ? printf("%02x", data[i]);
+ ? ? ? ? ? ? if ((i+1) % 16 != 0)
+ ? ? ? ? ? ? ? ? ? ? printf(" ");
+ ? ? }
Quoted 8 lines

arch/arm/cpu/armv7/tegra2/crypto.c line 55

Quoted 5 lines

+ ? ? printf("\n");

arch/arm/cpu/armv7/tegra2/crypto.c new file +4 -0
+}
+#else
+#define debug_print_vector(name, num_bytes, data)
+#endif

if you used debug() instead of printf(), wouldn't this get optimized without the #ifdef protection ?

Yes it does, clever compiler. I will change it.

Regards
Simon

Quoted 1 line

-mike

#11 lore raw

PATCH 4/14 tegra: Add flow, gp_padctl, fuse, sdram headers

In reply to Simon Glass

From: Yen Lin <[email protected]>

These headers provide access to additional Tegra features.

flow - start/stop CPUs
sdram - parameters for SDRAM
fuse - access to on-chip fuses / security settings gp_padctl - pad control and general purpose registers

---
 arch/arm/include/asm/arch-tegra2/flow.h        |   36 ++++++
 arch/arm/include/asm/arch-tegra2/fuse.h        |   39 ++++++
 arch/arm/include/asm/arch-tegra2/gp_padctrl.h  |   64 ++++++++++
 arch/arm/include/asm/arch-tegra2/sdram_param.h |  148 ++++++++++++++++++++++++
 arch/arm/include/asm/arch-tegra2/tegra2.h      |    1 +
 5 files changed, 288 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/include/asm/arch-tegra2/flow.h
 create mode 100644 arch/arm/include/asm/arch-tegra2/fuse.h
 create mode 100644 arch/arm/include/asm/arch-tegra2/gp_padctrl.h
 create mode 100644 arch/arm/include/asm/arch-tegra2/sdram_param.h
arch/arm/include/asm/arch-tegra2/flow.h new file +36 -0
new file mode 100644
index 0000000..cce6cbf
@@ -0,0 +1,36 @@
+/*
+ * (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 _FLOW_H_
+#define _FLOW_H_
+
+struct flow_ctlr {
+	u32	halt_cpu_events;
+	u32	halt_cop_events;
+	u32	cpu_csr;
+	u32	cop_csr;
+	u32	halt_cpu1_events;
+	u32	cpu1_csr;
+};
+
+#endif
arch/arm/include/asm/arch-tegra2/fuse.h new file +39 -0
new file mode 100644
index 0000000..b7e3808
@@ -0,0 +1,39 @@
+/*
+ *  (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 _FUSE_H_
+#define _FUSE_H_
+
+/* FUSE registers */
+struct fuse_regs {
+	u32 reserved0[64];		/* 0x00 - 0xFC: */
+	u32 production_mode;		/* 0x100: FUSE_PRODUCTION_MODE */
+	u32 reserved1[3];		/* 0x104 - 0x10c: */
+	u32 sku_info;			/* 0x110 */
+	u32 reserved2[13];		/* 0x114 - 0x144: */
+	u32 fa;				/* 0x148: FUSE_FA */
+	u32 reserved3[21];		/* 0x14C - 0x19C: */
+	u32 security_mode;		/* 0x1A0: FUSE_SECURITY_MODE */
+};
+
+#endif	/* ifndef _FUSE_H_ */
arch/arm/include/asm/arch-tegra2/gp_padctrl.h new file +64 -0

64 lines not on this page · raw message

arch/arm/include/asm/arch-tegra2/sdram_param.h new file +148 -0

148 lines not on this page · raw message

arch/arm/include/asm/arch-tegra2/tegra2.h +1 -0
index d1a70da..c4cd9bb 100644
@@ -44,6 +44,7 @@
 #define TEGRA2_I2C2_BASE	(NV_PA_APB_MISC_BASE + 0xC400)
 #define TEGRA2_I2C3_BASE	(NV_PA_APB_MISC_BASE + 0xC500)
 #define TEGRA2_DVC_BASE		(NV_PA_APB_MISC_BASE + 0xD000)
+#define TEGRA2_FUSE_BASE	(NV_PA_APB_MISC_BASE + 0xF800)
 #define NV_PA_CSITE_BASE	0x70040000
 #define TEGRA_USB1_BASE		0xC5000000
 #define TEGRA_USB3_BASE		0xC5008000
Signature · 1 line
1.7.3.1
#12 lore raw

PATCH 5/14 tegra: Add tegra_get_chip_type() to detect SKU

In reply to Simon Glass

We want to know which type of chip we are running on - the Tegra family has several SKUs. This can be determined by reading a fuse register, so add this function to ap20.

---
 arch/arm/cpu/armv7/tegra2/ap20.c          |   24 ++++++++++++++++++++++++
 arch/arm/include/asm/arch-tegra2/ap20.h   |    7 +++++++
 arch/arm/include/asm/arch-tegra2/tegra2.h |   23 +++++++++++++++++++++++
 3 files changed, 54 insertions(+), 0 deletions(-)
arch/arm/cpu/armv7/tegra2/ap20.c +24 -0
index da7128c..311e93f 100644
@@ -26,11 +26,35 @@
 #include <asm/arch/ap20.h>
 #include <asm/arch/clk_rst.h>
 #include <asm/arch/clock.h>
+#include <asm/arch/fuse.h>
 #include <asm/arch/pmc.h>
 #include <asm/arch/pinmux.h>
 #include <asm/arch/scu.h>
 #include <common.h>
 
+int tegra_get_chip_type(void)
+{
+	struct fuse_regs *fuse = (struct fuse_regs *)TEGRA2_FUSE_BASE;
+	uint tegra_sku_id;
+
+	tegra_sku_id = readl(&fuse->sku_info) & 0xff;
+
+	switch (tegra_sku_id) {
+	case SKU_ID_T20:
+		return TEGRA_SOC_T20;
+	case SKU_ID_T25SE:
+	case SKU_ID_AP25:
+	case SKU_ID_T25:
+	case SKU_ID_AP25E:
+	case SKU_ID_T25E:
+		return TEGRA_SOC_T25;
+
+	default:
+		/* unknown sku id */
+		return TEGRA_SOC_UNKNOWN;
+	}
+}
+
 /* Returns 1 if the current CPU executing is a Cortex-A9, else 0 */
 static int ap20_cpu_is_cortexa9(void)
 {
arch/arm/include/asm/arch-tegra2/ap20.h +7 -0
index a4b4d73..d222c44 100644
@@ -100,3 +100,10 @@ void tegra2_start(void);
 
 /* This is the main entry into U-Boot, used by the Cortex-A9 */
 extern void _start(void);
+
+/**
+ * Works out the SOC type used for clocks settings
+ *
+ * @return	SOC type - see TEGRA_SOC...
+ */
+int tegra_get_chip_type(void);
arch/arm/include/asm/arch-tegra2/tegra2.h +23 -0
index c4cd9bb..f33726d 100644
@@ -59,6 +59,29 @@
 struct timerus {
 	unsigned int cntr_1us;
 };
+
+/* Address at which WB code runs, it must not overlap Bootrom's IRAM usage */
+#define AP20_WB_RUN_ADDRESS	0x40020000
+
+/* These are the available SKUs (product types) for Tegra */
+enum {
+	SKU_ID_T20		= 0x8,
+	SKU_ID_T25SE		= 0x14,
+	SKU_ID_AP25		= 0x17,
+	SKU_ID_T25		= 0x18,
+	SKU_ID_AP25E		= 0x1b,
+	SKU_ID_T25E		= 0x1c,
+};
+
+/* These are the SOC categories that affect clocking */
+enum {
+	TEGRA_SOC_T20,
+	TEGRA_SOC_T25,
+
+	TEGRA_SOC_COUNT,
+	TEGRA_SOC_UNKNOWN	= -1,
+};
+
 #else  /* __ASSEMBLY__ */
 #define PRM_RSTCTRL		TEGRA2_PMC_BASE
 #endif
Signature · 1 line
1.7.3.1
#13 lore raw

PATCH 5/14 tegra: Add tegra_get_chip_type() to detect SKU

Quoted 3 lines · Simon Glass

We want to know which type of chip we are running on - the Tegra family has several SKUs. This can be determined by reading a fuse register, so add this function to ap20.

...

Quoted 1 line
arch/arm/cpu/armv7/tegra2/ap20.c +0 -0

...

arch/arm/cpu/armv7/tegra2/ap20.c line 42

Quoted 8 lines
arch/arm/cpu/armv7/tegra2/ap20.c +8 -0
+int tegra_get_chip_type(void)
+{
+	struct fuse_regs *fuse = (struct fuse_regs *)TEGRA2_FUSE_BASE;
+	uint tegra_sku_id;
+
+	tegra_sku_id = readl(&fuse->sku_info) & 0xff;
+
+	switch (tegra_sku_id) {

I think this should read/validate/switch-on the SoC ID field too; I assume the SKU IDs can only be interpreted relative to some specific SoC ID.

Chip ID is bits 15:8 of the register APB_MISC + 0x804, and has value 0x20 for Tegra20, 0x30 for Tegra30.

Signature · 1 line
nvpublic
#14 lore raw

PATCH 5/14 tegra: Add tegra_get_chip_type() to detect SKU

Hi Stephen,

Quoted 19 lines · Stephen Warren
Quoted 3 lines · Simon Glass

We want to know which type of chip we are running on - the Tegra family has several SKUs. This can be determined by reading a fuse register, so add this function to ap20.

...

Quoted 1 line
arch/arm/cpu/armv7/tegra2/ap20.c +0 -0

...

arch/arm/cpu/armv7/tegra2/ap20.c

Quoted 8 lines
arch/arm/cpu/armv7/tegra2/ap20.c +8 -0
+int tegra_get_chip_type(void)
+{
+ ? ? struct fuse_regs *fuse = (struct fuse_regs *)TEGRA2_FUSE_BASE;
+ ? ? uint tegra_sku_id;
+
+ ? ? tegra_sku_id = readl(&fuse->sku_info) & 0xff;
+
+ ? ? switch (tegra_sku_id) {

I think this should read/validate/switch-on the SoC ID field too; I assume the SKU IDs can only be interpreted relative to some specific SoC ID.

Quoted 2 lines

Chip ID is bits 15:8 of the register APB_MISC + 0x804, and has value 0x20 for Tegra20, 0x30 for Tegra30.

My TRM doesn't mention those values. What version are you referring to? I have v06.

Regards,
Simon

Quoted 3 lines

--
nvpublic

#15 lore raw

PATCH 5/14 tegra: Add tegra_get_chip_type() to detect SKU

Simon Glass wrote at Thursday, January 12, 2012 12:36 PM:

Quoted 2 lines · Stephen Warren
Quoted 1 line · Simon Glass

...

Quoted 8 lines
Quoted 5 lines

I think this should read/validate/switch-on the SoC ID field too; I assume the SKU IDs can only be interpreted relative to some specific SoC ID.

Chip ID is bits 15:8 of the register APB_MISC + 0x804, and has value 0x20 for Tegra20, 0x30 for Tegra30.

My TRM doesn't mention those values. What version are you referring to? I have v06.

In both v06 and v01p (the public version), the register is in section 11.1.6.8. I guess that doesn't actually define the values of the fields, sigh. But, I can say that Tegra20 is 0x20 and Tegra30 is 0x30.

For example, see:

http://nv-tegra.nvidia.com/gitweb/?p=linux-2.6.git;a=blob;f=arch/arm/mach-tegra/fuse.c;h=fd703f9c1621a6d93db787e60b0d1b6314f8fb3e;hb=android-tegra-nv-2.6.39

function void tegra_get_tegraid_from_hw, and:

http://nv-tegra.nvidia.com/gitweb/?p=linux-2.6.git;a=blob;f=arch/arm/mach-tegra/include/mach/hardware.h;h=d8f9bfbce42d4255d3e91db166f283a48bb4a8f2;hb=android-tegra-nv-2.6.39

for definitions of TEGRA_CHIPID_*.

Signature · 1 line
nvpublic
#16 lore raw

PATCH 5/14 tegra: Add tegra_get_chip_type() to detect SKU

Hi Stephen,

Quoted 19 lines · Stephen Warren

Simon Glass wrote at Thursday, January 12, 2012 12:36 PM:

Quoted 2 lines · Stephen Warren
Quoted 1 line · Simon Glass

...

Quoted 8 lines
Quoted 5 lines

I think this should read/validate/switch-on the SoC ID field too; I assume the SKU IDs can only be interpreted relative to some specific SoC ID.

Chip ID is bits 15:8 of the register APB_MISC + 0x804, and has value 0x20 for Tegra20, 0x30 for Tegra30.

My TRM doesn't mention those values. What version are you referring to? I have v06.

In both v06 and v01p (the public version), the register is in section 11.1.6.8. I guess that doesn't actually define the values of the fields, sigh. But, I can say that Tegra20 is 0x20 and Tegra30 is 0x30.

For example, see:

Quoted 7 lines

http://nv-tegra.nvidia.com/gitweb/?p=linux-2.6.git;a=blob;f=arch/arm/mach-tegra/fuse.c;h=fd703f9c1621a6d93db787e60b0d1b6314f8fb3e;hb=android-tegra-nv-2.6.39

function void tegra_get_tegraid_from_hw, and:

http://nv-tegra.nvidia.com/gitweb/?p=linux-2.6.git;a=blob;f=arch/arm/mach-tegra/include/mach/hardware.h;h=d8f9bfbce42d4255d3e91db166f283a48bb4a8f2;hb=android-tegra-nv-2.6.39

for definitions of TEGRA_CHIPID_*.

OK, I will put this in as you say with a suitable comment.

Regards,
Simon

Quoted 4 lines

--
nvpublic

#17 lore raw

PATCH 6/14 tegra: Add EMC support for optimal memory timings

In reply to Simon Glass

From: Jimmy Zhang <[email protected]>

Add support for setting up the memory controller parameters. Boards can call tegra_set_emc() with a table containing the required parameters.

---
 arch/arm/cpu/armv7/tegra2/Makefile        |    1 +
 arch/arm/cpu/armv7/tegra2/emc.c           |  165 +++++++++++++++++++++++++++++
 arch/arm/include/asm/arch-tegra2/emc.h    |  107 +++++++++++++++++++
 arch/arm/include/asm/arch-tegra2/tegra2.h |    1 +
 4 files changed, 274 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/cpu/armv7/tegra2/emc.c
 create mode 100644 arch/arm/include/asm/arch-tegra2/emc.h
arch/arm/cpu/armv7/tegra2/Makefile +1 -0
index e9ac6c9..dcd6329 100644
@@ -34,6 +34,7 @@ LIB	=  $(obj)lib$(SOC).o
 
 SOBJS	:= lowlevel_init.o
 COBJS-y	:= ap20.o board.o clock.o funcmux.o pinmux.o sys_info.o timer.o
+COBJS-$(CONFIG_TEGRA_CLOCK_SCALING) += emc.o
 COBJS-$(CONFIG_USB_EHCI_TEGRA) += usb.o
 
 COBJS	:= $(COBJS-y)
arch/arm/cpu/armv7/tegra2/emc.c new file +165 -0

165 lines not on this page · raw message

arch/arm/include/asm/arch-tegra2/emc.h new file +107 -0

107 lines not on this page · raw message

arch/arm/include/asm/arch-tegra2/tegra2.h +1 -0
index f33726d..480ec0c 100644
@@ -44,6 +44,7 @@
 #define TEGRA2_I2C2_BASE	(NV_PA_APB_MISC_BASE + 0xC400)
 #define TEGRA2_I2C3_BASE	(NV_PA_APB_MISC_BASE + 0xC500)
 #define TEGRA2_DVC_BASE		(NV_PA_APB_MISC_BASE + 0xD000)
+#define TEGRA2_EMC_BASE		(NV_PA_APB_MISC_BASE + 0xF400)
 #define TEGRA2_FUSE_BASE	(NV_PA_APB_MISC_BASE + 0xF800)
 #define NV_PA_CSITE_BASE	0x70040000
 #define TEGRA_USB1_BASE		0xC5000000
Signature · 1 line
1.7.3.1
#18 lore raw

PATCH 6/14 tegra: Add EMC support for optimal memory timings

Quoted 5 lines · Simon Glass

From: Jimmy Zhang <[email protected]>

Add support for setting up the memory controller parameters. Boards can call tegra_set_emc() with a table containing the required parameters.

...

Quoted 1 line
arch/arm/cpu/armv7/tegra2/emc.c +0 -0

...

arch/arm/cpu/armv7/tegra2/emc.c line 31

Quoted 2 lines
arch/arm/cpu/armv7/tegra2/emc.c +2 -0
+static const struct tegra_emc_table *tegra_emc_table;
+static int tegra_emc_table_size;

This isn't "table_size", but "number_of_tables" or "num_tables" or "table_count". This sounds nit-picky, but it made me think about this change more than I needed to given its simplicity.

arch/arm/cpu/armv7/tegra2/emc.c line 49

Quoted 2 lines
arch/arm/cpu/armv7/tegra2/emc.c +2 -0
+static const unsigned long emc_reg_addr[TEGRA_EMC_NUM_REGS] = {
+       0x2c,   /* RC */

For reference, I validated that the order or registers here matches that in the DT binding that Olof published for the kernel, which is good.

http://patchwork.ozlabs.org/patch/132928/

Quoted 8 lines
arch/arm/cpu/armv7/tegra2/emc.c +8 -0
+/* The EMC registers have shadow registers.  When the EMC clock is updated
+ * in the clock controller, the shadow registers are copied to the active
+ * registers, allowing glitchless memory bus frequency changes.
+ * This function updates the shadow registers for a new clock frequency,
+ * and relies on the clock lock on the emc clock to avoid races between
+ * multiple frequency changes */
+#define EMC_SDRAM_RATE_T20     (333000 * 2 * 1000)
+#define EMC_SDRAM_RATE_T25     (380000 * 2 * 1000)

...

Quoted 1 line

+int tegra_set_emc(const struct tegra_emc_table *table, int table_size)

...

arch/arm/cpu/armv7/tegra2/emc.c line 160

Quoted 11 lines
arch/arm/cpu/armv7/tegra2/emc.c +11 -0
+       switch (tegra_get_chip_type()) {
+       case TEGRA_SOC_T20:
+               rate  = EMC_SDRAM_RATE_T20;
+               break;
+       case TEGRA_SOC_T25:
+               rate  = EMC_SDRAM_RATE_T25;
+               break;
+       default:
+               /* unknown chip type, no clk change*/
+               return -1;
+       }

I'm not convinced that limiting this to those two specific clocks is correct. I've certainly seen BCTs that appear to run the EMC clock at other frequencies. Specifically, for Seaboard, we appear to have BCTs for 190, 333, 380, and 400MHz internally. I think a board should be able to at least override the default rate selected by that switch statement.

In tegra_emc_set_rate(), it's unclear to me why clock_ll_set_source_divisor() is used to trigger use of the new EMC register content, rather than say clock_set_rate(). I guess that's just how the HW work?

Signature · 1 line
nvpublic
#19 lore raw

PATCH 6/14 tegra: Add EMC support for optimal memory timings

Hi Stephen,

Quoted 7 lines · Stephen Warren
Quoted 5 lines · Simon Glass

From: Jimmy Zhang <[email protected]>

Add support for setting up the memory controller parameters. Boards can call tegra_set_emc() with a table containing the required parameters.

...

Quoted 8 lines
Quoted 1 line
arch/arm/cpu/armv7/tegra2/emc.c +0 -0

...

arch/arm/cpu/armv7/tegra2/emc.c line 31

Quoted 2 lines
arch/arm/cpu/armv7/tegra2/emc.c +2 -0
+static const struct tegra_emc_table *tegra_emc_table;
+static int tegra_emc_table_size;

This isn't "table_size", but "number_of_tables" or "num_tables" or "table_count". This sounds nit-picky, but it made me think about this change more than I needed to given its simplicity.

OK changed to num_emc_tables.

Quoted 8 lines
Quoted 3 lines

+static const unsigned long emc_reg_addr[TEGRA_EMC_NUM_REGS] = {
+ ? ? ? 0x2c, ? /* RC */

For reference, I validated that the order or registers here matches that in the DT binding that Olof published for the kernel, which is good.

http://patchwork.ozlabs.org/patch/132928/

Yes I would hope so :-) Thanks for checking. I can't see it committed, so will reply on that thread.

Quoted 24 lines
Quoted 9 lines
arch/arm/cpu/armv7/tegra2/emc.c +8 -0
+/* The EMC registers have shadow registers. ?When the EMC clock is updated
+ * in the clock controller, the shadow registers are copied to the active
+ * registers, allowing glitchless memory bus frequency changes.
+ * This function updates the shadow registers for a new clock frequency,
+ * and relies on the clock lock on the emc clock to avoid races between
+ * multiple frequency changes */
+#define EMC_SDRAM_RATE_T20 ? ? (333000 * 2 * 1000)
+#define EMC_SDRAM_RATE_T25 ? ? (380000 * 2 * 1000)

...

Quoted 1 line

+int tegra_set_emc(const struct tegra_emc_table *table, int table_size)

...

Quoted 11 lines

+ ? ? ? switch (tegra_get_chip_type()) {
+ ? ? ? case TEGRA_SOC_T20:
+ ? ? ? ? ? ? ? rate ?= EMC_SDRAM_RATE_T20;
+ ? ? ? ? ? ? ? break;
+ ? ? ? case TEGRA_SOC_T25:
+ ? ? ? ? ? ? ? rate ?= EMC_SDRAM_RATE_T25;
+ ? ? ? ? ? ? ? break;
+ ? ? ? default:
+ ? ? ? ? ? ? ? /* unknown chip type, no clk change*/
+ ? ? ? ? ? ? ? return -1;
+ ? ? ? }

Quoted 5 lines

I'm not convinced that limiting this to those two specific clocks is correct. I've certainly seen BCTs that appear to run the EMC clock at other frequencies. Specifically, for Seaboard, we appear to have BCTs for 190, 333, 380, and 400MHz internally. I think a board should be able to at least override the default rate selected by that switch statement.

OK. It might be time to move this to the fdt, I will take a look.

Quoted 5 lines

In tegra_emc_set_rate(), it's unclear to me why clock_ll_set_source_divisor() is used to trigger use of the new EMC register content, rather than say clock_set_rate(). I guess that's just how the HW work?

It should be possible to do something like:

	clock_adjust_periph_pll(PERIPH_ID_EMC, CLOCK_ID_MEMORY, 0,
				clock_get_rate(CLOCK_ID_MEMORY));

although it is a lot less efficient. I will try it.

Regards,
Simon

Quoted 3 lines

--
nvpublic

#20 lore raw

PATCH 6/14 tegra: Add EMC support for optimal memory timings

Hi Stephen,

Quoted 71 lines · Simon Glass

Hi Stephen,

Quoted 7 lines · Stephen Warren
Quoted 5 lines · Simon Glass

From: Jimmy Zhang <[email protected]>

Add support for setting up the memory controller parameters. Boards can call tegra_set_emc() with a table containing the required parameters.

...

Quoted 8 lines
Quoted 1 line
arch/arm/cpu/armv7/tegra2/emc.c +0 -0

...

arch/arm/cpu/armv7/tegra2/emc.c line 31

Quoted 2 lines
arch/arm/cpu/armv7/tegra2/emc.c +2 -0
+static const struct tegra_emc_table *tegra_emc_table;
+static int tegra_emc_table_size;

This isn't "table_size", but "number_of_tables" or "num_tables" or "table_count". This sounds nit-picky, but it made me think about this change more than I needed to given its simplicity.

OK changed to num_emc_tables.

Quoted 8 lines
Quoted 3 lines

+static const unsigned long emc_reg_addr[TEGRA_EMC_NUM_REGS] = {
+ ? ? ? 0x2c, ? /* RC */

For reference, I validated that the order or registers here matches that in the DT binding that Olof published for the kernel, which is good.

http://patchwork.ozlabs.org/patch/132928/

Yes I would hope so :-) Thanks for checking. I can't see it committed, so will reply on that thread.

Quoted 24 lines
Quoted 9 lines
arch/arm/cpu/armv7/tegra2/emc.c +8 -0
+/* The EMC registers have shadow registers. ?When the EMC clock is updated
+ * in the clock controller, the shadow registers are copied to the active
+ * registers, allowing glitchless memory bus frequency changes.
+ * This function updates the shadow registers for a new clock frequency,
+ * and relies on the clock lock on the emc clock to avoid races between
+ * multiple frequency changes */
+#define EMC_SDRAM_RATE_T20 ? ? (333000 * 2 * 1000)
+#define EMC_SDRAM_RATE_T25 ? ? (380000 * 2 * 1000)

...

Quoted 1 line

+int tegra_set_emc(const struct tegra_emc_table *table, int table_size)

...

Quoted 11 lines

+ ? ? ? switch (tegra_get_chip_type()) {
+ ? ? ? case TEGRA_SOC_T20:
+ ? ? ? ? ? ? ? rate ?= EMC_SDRAM_RATE_T20;
+ ? ? ? ? ? ? ? break;
+ ? ? ? case TEGRA_SOC_T25:
+ ? ? ? ? ? ? ? rate ?= EMC_SDRAM_RATE_T25;
+ ? ? ? ? ? ? ? break;
+ ? ? ? default:
+ ? ? ? ? ? ? ? /* unknown chip type, no clk change*/
+ ? ? ? ? ? ? ? return -1;
+ ? ? ? }

Quoted 5 lines

I'm not convinced that limiting this to those two specific clocks is correct. I've certainly seen BCTs that appear to run the EMC clock at other frequencies. Specifically, for Seaboard, we appear to have BCTs for 190, 333, 380, and 400MHz internally. I think a board should be able to at least override the default rate selected by that switch statement.

OK. It might be time to move this to the fdt, I will take a look.

Quoted 5 lines

In tegra_emc_set_rate(), it's unclear to me why clock_ll_set_source_divisor() is used to trigger use of the new EMC register content, rather than say clock_set_rate(). I guess that's just how the HW work?

Quoted 6 lines

It should be possible to do something like:

? ? ? ?clock_adjust_periph_pll(PERIPH_ID_EMC, CLOCK_ID_MEMORY, 0, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?clock_get_rate(CLOCK_ID_MEMORY));

although it is a lot less efficient. I will try it.

Yes that works. I want to reduce use of the xxx_ll() functions as much as possible so have changed this.

Regards,
Simon

Quoted 7 lines

Regards,
Simon

Quoted 3 lines

--
nvpublic

#21 lore raw

PATCH 7/14 tegra: Add PMU to manage power supplies

In reply to Simon Glass

From: Jimmy Zhang <[email protected]>

Power supplies must be adjusted in line with clock frequency. This code provides a simple routine to set the voltage to allow operation at maximum frequency.

---
 arch/arm/cpu/armv7/tegra2/Makefile     |    1 +
 arch/arm/cpu/armv7/tegra2/pmu.c        |  355 ++++++++++++++++++++++++++++++++
 arch/arm/include/asm/arch-tegra2/pmu.h |   63 ++++++
 3 files changed, 419 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/cpu/armv7/tegra2/pmu.c
 create mode 100644 arch/arm/include/asm/arch-tegra2/pmu.h
arch/arm/cpu/armv7/tegra2/Makefile +1 -0
index dcd6329..dba684d 100644
@@ -35,6 +35,7 @@ LIB	=  $(obj)lib$(SOC).o
 SOBJS	:= lowlevel_init.o
 COBJS-y	:= ap20.o board.o clock.o funcmux.o pinmux.o sys_info.o timer.o
 COBJS-$(CONFIG_TEGRA_CLOCK_SCALING) += emc.o
+COBJS-$(CONFIG_TEGRA_PMU) += pmu.o
 COBJS-$(CONFIG_USB_EHCI_TEGRA) += usb.o
 
 COBJS	:= $(COBJS-y)
arch/arm/cpu/armv7/tegra2/pmu.c new file +355 -0

355 lines not on this page · raw message

arch/arm/include/asm/arch-tegra2/pmu.h new file +63 -0

63 lines not on this page · raw message

Signature · 1 line
1.7.3.1
#22 lore raw

PATCH 7/14 tegra: Add PMU to manage power supplies

Quoted 6 lines · Simon Glass

From: Jimmy Zhang <[email protected]>

Power supplies must be adjusted in line with clock frequency. This code provides a simple routine to set the voltage to allow operation at maximum frequency.

Quoted 8 lines
---
 arch/arm/cpu/armv7/tegra2/Makefile     |    1 +
 arch/arm/cpu/armv7/tegra2/pmu.c        |  355 ++++++++++++++++++++++++++++++++
 arch/arm/include/asm/arch-tegra2/pmu.h |   63 ++++++
 3 files changed, 419 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/cpu/armv7/tegra2/pmu.c
 create mode 100644 arch/arm/include/asm/arch-tegra2/pmu.h

This driver appears to be for an I2C-based device, so I assume it'd for a particular PMIC not Tegra's PMC HW module. I imagine this is a driver for the TI TPS6586X, right?

As such, naming this "pmu" and putting it into the Tegra directory doesn't make sense. There should be a generic TPS6586X driver, and possibly a separate file and patch to implement the use of that chip in conjunction with Tegra.

Signature · 1 line
nvpublic
#23 lore raw

PATCH 7/14 tegra: Add PMU to manage power supplies

Hi Stephen,

Quoted 16 lines · Stephen Warren
Quoted 6 lines · Simon Glass

From: Jimmy Zhang <[email protected]>

Power supplies must be adjusted in line with clock frequency. This code provides a simple routine to set the voltage to allow operation at maximum frequency.

Quoted 8 lines

---

?arch/arm/cpu/armv7/tegra2/Makefile ? ? | ? ?1 +
?arch/arm/cpu/armv7/tegra2/pmu.c ? ? ? ?| ?355 ++++++++++++++++++++++++++++++++
?arch/arm/include/asm/arch-tegra2/pmu.h | ? 63 ++++++

?3 files changed, 419 insertions(+), 0 deletions(-) ?create mode 100644 arch/arm/cpu/armv7/tegra2/pmu.c ?create mode 100644 arch/arm/include/asm/arch-tegra2/pmu.h

Quoted 8 lines

This driver appears to be for an I2C-based device, so I assume it'd for a particular PMIC not Tegra's PMC HW module. I imagine this is a driver for the TI TPS6586X, right?

As such, naming this "pmu" and putting it into the Tegra directory doesn't make sense. There should be a generic TPS6586X driver, and possibly a separate file and patch to implement the use of that chip in conjunction with Tegra.

Oh dear, but yes you are right. It is a TPS658621C according to my schematic. I will leap into this also.

Regards,
Simon

Quoted 3 lines

--
nvpublic

#24 lore raw

PATCH 7/14 tegra: Add PMU to manage power supplies

Simon Glass wrote at Thursday, January 12, 2012 4:17 PM:

Quoted 21 lines · Stephen Warren
Quoted 20 lines · Simon Glass
Quoted 6 lines

From: Jimmy Zhang <[email protected]>

Power supplies must be adjusted in line with clock frequency. This code provides a simple routine to set the voltage to allow operation at maximum frequency.

Quoted 8 lines

---

?arch/arm/cpu/armv7/tegra2/Makefile ? ? | ? ?1 +
?arch/arm/cpu/armv7/tegra2/pmu.c ? ? ? ?| ?355 ++++++++++++++++++++++++++++++++
?arch/arm/include/asm/arch-tegra2/pmu.h | ? 63 ++++++

?3 files changed, 419 insertions(+), 0 deletions(-) ?create mode 100644 arch/arm/cpu/armv7/tegra2/pmu.c ?create mode 100644 arch/arm/include/asm/arch-tegra2/pmu.h

This driver appears to be for an I2C-based device, so I assume it'd for a particular PMIC not Tegra's PMC HW module. I imagine this is a driver for the TI TPS6586X, right?

Quoted 7 lines
Quoted 4 lines

As such, naming this "pmu" and putting it into the Tegra directory doesn't make sense. There should be a generic TPS6586X driver, and possibly a separate file and patch to implement the use of that chip in conjunction with Tegra.

Oh dear, but yes you are right. It is a TPS658621C according to my schematic. I will leap into this also.

I believe some number of the devices are compatible, hence the kernel has a tps6586x driver rather than more individual drivers for each value of "x".

Signature · 1 line
nvpublic
#25 lore raw

PATCH 7/14 tegra: Add PMU to manage power supplies

Hi Stephen,

Quoted 27 lines · Stephen Warren

Simon Glass wrote at Thursday, January 12, 2012 4:17 PM:

Quoted 26 lines · Stephen Warren
Quoted 24 lines · Simon Glass
Quoted 6 lines

From: Jimmy Zhang <[email protected]>

Power supplies must be adjusted in line with clock frequency. This code provides a simple routine to set the voltage to allow operation at maximum frequency.

Quoted 8 lines

---

?arch/arm/cpu/armv7/tegra2/Makefile ? ? | ? ?1 +
?arch/arm/cpu/armv7/tegra2/pmu.c ? ? ? ?| ?355 ++++++++++++++++++++++++++++++++
?arch/arm/include/asm/arch-tegra2/pmu.h | ? 63 ++++++

?3 files changed, 419 insertions(+), 0 deletions(-) ?create mode 100644 arch/arm/cpu/armv7/tegra2/pmu.c ?create mode 100644 arch/arm/include/asm/arch-tegra2/pmu.h

This driver appears to be for an I2C-based device, so I assume it'd for a particular PMIC not Tegra's PMC HW module. I imagine this is a driver for the TI TPS6586X, right?

As such, naming this "pmu" and putting it into the Tegra directory doesn't make sense. There should be a generic TPS6586X driver, and possibly a separate file and patch to implement the use of that chip in conjunction with Tegra.

Quoted 6 lines
Quoted 2 lines

Oh dear, but yes you are right. It is a TPS658621C according to my schematic. I will leap into this also.

I believe some number of the devices are compatible, hence the kernel has a tps6586x driver rather than more individual drivers for each value of "x".

OK I will follow along with that.

Regards,
Simon

Quoted 4 lines

--
nvpublic

#26 lore raw

PATCH 8/14 tegra: Set up PMU for Nvidia boards

In reply to Simon Glass

Adjust PMU to permit maximum frequency operation.

---
 board/nvidia/common/board.c |   10 ++++++++++
 1 files changed, 10 insertions(+), 0 deletions(-)
board/nvidia/common/board.c +10 -0
index 63edfdb..10c0a67 100644
@@ -31,6 +31,8 @@
 #include <asm/arch/clk_rst.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/pinmux.h>
+#include <asm/arch/pmc.h>
+#include <asm/arch/pmu.h>
 #include <asm/arch/uart.h>
 #include <spi.h>
 #include <asm/arch/usb.h>
@@ -81,6 +83,14 @@ int board_init(void)
 	board_usb_init(gd->fdt_blob);
 #endif
 
+#ifdef CONFIG_TEGRA2_I2C
+	i2c_init_board();
+
+#ifdef CONFIG_TEGRA_PMU
+	pmu_set_nominal();
+#endif
+#endif
+
 	return 0;
 }
 
Signature · 1 line
1.7.3.1
#27 lore raw

PATCH 8/14 tegra: Set up PMU for Nvidia boards

Quoted 1 line · Simon Glass

Adjust PMU to permit maximum frequency operation.

...

Quoted 1 line
board/nvidia/common/board.c +0 -0

...

board/nvidia/common/board.c int board_init(void) · line 95

Quoted 10 lines
board/nvidia/common/board.c +8 -0
+#ifdef CONFIG_TEGRA2_I2C
+	i2c_init_board();
+
+#ifdef CONFIG_TEGRA_PMU
+	pmu_set_nominal();
+#endif
+#endif
+
 	return 0;
 }

I think there's some patch confusion here; weren't the outer ifdef and call to i2c_init_board() added in the I2C patch series too?

Signature · 1 line
nvpublic
#28 lore raw

PATCH 8/14 tegra: Set up PMU for Nvidia boards

Hi Stephen,

Quoted 5 lines · Stephen Warren
Quoted 1 line · Simon Glass

Adjust PMU to permit maximum frequency operation.

...

Quoted 1 line
board/nvidia/common/board.c +0 -0

...

Quoted 13 lines
Quoted 10 lines
board/nvidia/common/board.c +8 -0
+#ifdef CONFIG_TEGRA2_I2C
+ ? ? i2c_init_board();
+
+#ifdef CONFIG_TEGRA_PMU
+ ? ? pmu_set_nominal();
+#endif
+#endif
+

? ? ? return 0;
?}

I think there's some patch confusion here; weren't the outer ifdef and call to i2c_init_board() added in the I2C patch series too?

Yes, I moved some code around and duplicated it. I will fix this.

Regards,
Simon

Quoted 3 lines

--
nvpublic

#29 lore raw

PATCH 9/14 tegra: Add warmboot implementation

In reply to Simon Glass

From: Yen Lin <[email protected]>

Add code to set up the warm boot area in the Tegra CPU ready for a resume after suspend.

---
 arch/arm/cpu/armv7/tegra2/Makefile          |    6 +-
 arch/arm/cpu/armv7/tegra2/warmboot.c        |  444 +++++++++++++++++++++++++++
 arch/arm/cpu/armv7/tegra2/warmboot_avp.c    |  312 +++++++++++++++++++
 arch/arm/cpu/armv7/tegra2/warmboot_avp.h    |   81 +++++
 arch/arm/include/asm/arch-tegra2/tegra2.h   |    1 +
 arch/arm/include/asm/arch-tegra2/warmboot.h |   81 +++++
 6 files changed, 924 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/cpu/armv7/tegra2/warmboot.c
 create mode 100644 arch/arm/cpu/armv7/tegra2/warmboot_avp.c
 create mode 100644 arch/arm/cpu/armv7/tegra2/warmboot_avp.h
 create mode 100644 arch/arm/include/asm/arch-tegra2/warmboot.h
arch/arm/cpu/armv7/tegra2/Makefile +5 -1
index dba684d..a70659e 100644
@@ -27,17 +27,21 @@
 # flags for any startup files it might use.
 CFLAGS_arch/arm/cpu/armv7/tegra2/ap20.o += -march=armv4t
 CFLAGS_arch/arm/cpu/armv7/tegra2/clock.o += -march=armv4t
+CFLAGS_arch/arm/cpu/armv7/tegra2/warmboot_avp.o += -march=armv4t
 
 include $(TOPDIR)/config.mk
 
 LIB	=  $(obj)lib$(SOC).o
 
-SOBJS	:= lowlevel_init.o
+SOBJS-y	:= lowlevel_init.o
 COBJS-y	:= ap20.o board.o clock.o funcmux.o pinmux.o sys_info.o timer.o
+
 COBJS-$(CONFIG_TEGRA_CLOCK_SCALING) += emc.o
 COBJS-$(CONFIG_TEGRA_PMU) += pmu.o
 COBJS-$(CONFIG_USB_EHCI_TEGRA) += usb.o
+COBJS-$(CONFIG_TEGRA2_LP0) += crypto.o warmboot.o warmboot_avp.o
 
+SOBJS	:= $(SOBJS-y)
 COBJS	:= $(COBJS-y)
 SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS) $(SOBJS))
arch/arm/cpu/armv7/tegra2/warmboot.c new file +444 -0

444 lines not on this page · raw message

arch/arm/cpu/armv7/tegra2/warmboot_avp.c new file +312 -0

312 lines not on this page · raw message

arch/arm/cpu/armv7/tegra2/warmboot_avp.h new file +81 -0

81 lines not on this page · raw message

arch/arm/include/asm/arch-tegra2/tegra2.h +1 -0
index 480ec0c..32027b1 100644
@@ -33,6 +33,7 @@
 #define NV_PA_GPIO_BASE		0x6000D000
 #define NV_PA_EVP_BASE		0x6000F000
 #define NV_PA_APB_MISC_BASE	0x70000000
+#define TEGRA2_APB_MISC_GP_BASE	(NV_PA_APB_MISC_BASE + 0x0800)
 #define NV_PA_APB_UARTA_BASE	(NV_PA_APB_MISC_BASE + 0x6000)
 #define NV_PA_APB_UARTB_BASE	(NV_PA_APB_MISC_BASE + 0x6040)
 #define NV_PA_APB_UARTC_BASE	(NV_PA_APB_MISC_BASE + 0x6200)
arch/arm/include/asm/arch-tegra2/warmboot.h new file +81 -0

81 lines not on this page · raw message

Signature · 1 line
1.7.3.1
#30 lore raw

PATCH 9/14 tegra: Add warmboot implementation

Quoted 6 lines · Simon Glass

From: Yen Lin <[email protected]>

Add code to set up the warm boot area in the Tegra CPU ready for a resume after suspend.

How come Yen's S-o-b line is missing here?

As a general comment on this patch, it contains a lot of structure definitions and defines that should really be part of the clock module's headers and similar; why not just included the clock headers and place all the definitions in those headers if they aren't already there?

There's also some amount of code duplication; e.g. wasn't get_major_version() part of another patch you recently posted that implements APIs to return SKU IDs etc? If not, it seems like it belongs there. Only warmboot_avp.c appears to run on the AVP, so I don't think needing ARMv4 compile flags is an argument for not putting this code in a more logical place.

Quoted 1 line
arch/arm/cpu/armv7/tegra2/Makefile +0 -0

...

Quoted 2 lines
arch/arm/cpu/armv7/tegra2/Makefile +1 -1
-SOBJS  := lowlevel_init.o
+SOBJS-y        := lowlevel_init.o

...

Quoted 1 line

+SOBJS := $(SOBJS-y)

That's really a separate patch, but I guess it's fine.

Quoted 1 line
arch/arm/cpu/armv7/tegra2/warmboot.c +0 -0

...

arch/arm/cpu/armv7/tegra2/warmboot.c line 41

Quoted 3 lines
arch/arm/cpu/armv7/tegra2/warmboot.c +3 -0
+#define BCT_OFFSET             0x100           /* BCT starts at 0x100 */
+#define BCT_SDRAM_PARAMS_OFFSET        (BCT_OFFSET + 0x88)
+#define SDRAM_PARAMS_BASE      (AP20_BASE_PA_SRAM + BCT_SDRAM_PARAMS_OFFSET)

BCT_OFFSET is where the BCT is stored within some warmboot-specific memory location. I think the comment should be explicit about this, because IIRC the BCT starts at offset 0 within the (cold) boot flash memory, so the comment is confusing until you trace through the code and find what SDRAM_PARAMS_BASE is used for.

arch/arm/cpu/armv7/tegra2/warmboot.c line 244

Quoted 10 lines
arch/arm/cpu/armv7/tegra2/warmboot.c +10 -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.
+ */
+#define RANDOM_AES_BLOCK_IS_RANDOM     /* to randomize the header */
+#undef RANDOM_AES_BLOCK_IS_PATTERN     /* to patternize the header */
+#undef RANDOM_AES_BLOCK_IS_ZERO                /* to clear the header */

Why not just used ifdefs to make sure that only (and exactly) one of these is defined?

arch/arm/cpu/armv7/tegra2/warmboot.c line 323

Quoted 5 lines
arch/arm/cpu/armv7/tegra2/warmboot.c +5 -0
+/* Currently, this routine returns a 32-bit all 0 seed. */
+static u32 query_random_seed(void)
+{
+       return 0;
+}

So the random option isn't really implemented at all. Perhaps just remove it completely; if someone wants it, they have to implement this function for it to be useful anyway, so adding the call to the function at the same time seems reasonable enough?

If not, at least make this print something at run-time so it's obvious it isn't really working.

Quoted 1 line

+int warmboot_prepare_code(u32 seg_address, u32 seg_length)

...

arch/arm/cpu/armv7/tegra2/warmboot.c line 381

Quoted 9 lines
arch/arm/cpu/armv7/tegra2/warmboot.c +9 -0
+       /*
+        * 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 >= AP20_BASE_PA_SRAM)) {
+               err = -EFAULT;
+               goto fail;
+       }

The IRAM check only validates that the address isn't at, within, or after the IRAM location, which doesn't exactly match the comment. If the restriction is "within" IRAM, the end address needs to be checked too. Isn't the real restriction that the address needs to be within SDRAM though? If so, it seems better to check that directly.

...

Quoted 8 lines
arch/arm/cpu/armv7/tegra2/warmboot.c +8 -0
+       /* 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)

arch/arm/cpu/armv7/tegra2/warmboot.c line 415

Quoted 10 lines
arch/arm/cpu/armv7/tegra2/warmboot.c +10 -0
+                       *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

Why not issue a compile error so the person who configured U-Boot is immediately aware of the problem, instead of delaying the issue to run-time?

Quoted 4 lines
arch/arm/cpu/armv7/tegra2/warmboot.c +2 -0
+               } while (aes_block < end);
+       }
arch/arm/cpu/armv7/tegra2/warmboot_avp.c +0 -0

...

Quoted 15 lines
arch/arm/cpu/armv7/tegra2/warmboot_avp.c +15 -0
+void wb_start(void)
+{
+       struct pmux_tri_ctlr *pmt = (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+       struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_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;
+       union osc_ctrl_reg osc_ctrl;
+       union pllx_base_reg pllx_base;
+       union pllx_misc_reg pllx_misc;
+       union scratch3_reg scratch3;
+       u32 reg;
+
+       /* enable JTAG & TBE */
+       writel(CONFIG_CTL_TBE | CONFIG_CTL_JTAG, &pmt->pmt_cfg_ctl);

arch/arm/cpu/armv7/tegra2/warmboot_avp.c line 124

Quoted 10 lines
arch/arm/cpu/armv7/tegra2/warmboot_avp.c +10 -0
+
+       /* Are we running where we're supposed to be? */
+       asm volatile (
+               "adr    %0, wb_start;"  /* reg: wb_start address */
+               : "=r"(reg)             /* output */
+                                       /* no input, no clobber list */
+       );
+
+       if (reg != AP20_WB_RUN_ADDRESS)
+               goto do_reset;

Does that code actually work; for it to work, the code would need to be either explicitly compile PIC (position independent) or accidentally be synthesized to code that happens to be PIC (not sure that's possible/likely).

arch/arm/cpu/armv7/tegra2/warmboot_avp.c line 141

Quoted 5 lines
arch/arm/cpu/armv7/tegra2/warmboot_avp.c +5 -0
+       /* Set the drive strength */
+       osc_ctrl.word = readl(&clkrst->crc_osc_ctrl);
+       osc_ctrl.xofs = 4;
+       osc_ctrl.xoe = 1;
+       writel(osc_ctrl.word, &clkrst->crc_osc_ctrl);

Isn't that board-specific?

Shouldn't the code save the old value during suspend, and restore it later or something like that, or be a board-specific #define?

A general question: How much does this all depend on specific interactions with the kernel? Does the kernel have to follow some specific protocol during suspend to make this all work? In mainline, there's no suspend support in Tegra, so I'm slightly worried that when it gets upstreamed, this code might need changes to address any review comments there?

Quoted 1 line
arch/arm/include/asm/arch-tegra2/warmboot.h +0 -0

...

arch/arm/include/asm/arch-tegra2/warmboot.h line 65

Quoted 11 lines
arch/arm/include/asm/arch-tegra2/warmboot.h +11 -0
+/*
+ * Defines the code header information for the boot rom.
+ *
+ * The code immediately follows the code header.
+ *
+ * Note that the code header needs to be 16 bytes aligned to preserve
+ * the alignment of relevant data for hash and decryption computations without
+ * requiring extra copies to temporary memory areas.
+ */
+struct wb_header {
+       u32 length_in_secure;   /* length of the code header */

I assume s/in_secure/insecure/ ?

Quoted 8 lines
arch/arm/include/asm/arch-tegra2/warmboot.h +8 -0
+       u32 reserved[3];
+       struct hash hash;       /* hash of header+code, starts next field*/
+       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 */
+       u32 entry_point;        /* execution address of the wb code */
+       u32 code_length;        /* length of the code */
+};
Signature · 1 line
nvpublic
#31 lore raw

PATCH 9/14 tegra: Add warmboot implementation

Hi Stephen,

[Yen please can you read this also?]

Quoted 6 lines · Stephen Warren
Quoted 5 lines · Simon Glass

From: Yen Lin <[email protected]>

Add code to set up the warm boot area in the Tegra CPU ready for a resume after suspend.

Quoted 8 lines
Quoted 1 line

How come Yen's S-o-b line is missing here?

As a general comment on this patch, it contains a lot of structure definitions and defines that should really be part of the clock module's headers and similar; why not just included the clock headers and place all the definitions in those headers if they aren't already there?

Yes this bit of it got a pretty light review at the time and I was reluctant to press on the bitfields when that side of things was still up in the air. No functions exist to access these things and using the clk_rst.h header adds a mountain of ugly reg & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT to the code. I am still uncomfortable with how this sort of thing is done in U-Boot.

Also the AVP code cannot call functions in clock.c (they are in SDRAM which isn't on yet), so we need the structures or some sort of access there anyway.

I will tidy up some low-hanging fruit in warmboot.c but don't know that I can do much with warmboot_avp.c. At least it isn't assembler anymore!

But there a few questions here. Firstly it seems that it saves some memory speed info to scratch2 but never restores it. Then it restores CPU speed from scratch3 but I can't see where it saves it. Does Yen have any comments on that? Apparently it works because we have been using it, but... If it is saving things that are never restored I could dump that and reduce the code size.

Quoted 8 lines

There's also some amount of code duplication; e.g. wasn't get_major_version() part of another patch you recently posted that implements APIs to return SKU IDs etc? If not, it seems like it belongs there. Only warmboot_avp.c appears to run on the AVP, so I don't think needing ARMv4 compile flags is an argument for not putting this code in a more logical place.

Quoted 8 lines
Quoted 1 line
arch/arm/cpu/armv7/tegra2/Makefile +0 -0

...

Quoted 2 lines
arch/arm/cpu/armv7/tegra2/Makefile +1 -1
-SOBJS ?:= lowlevel_init.o
+SOBJS-y ? ? ? ?:= lowlevel_init.o

...

Quoted 1 line

+SOBJS ?:= $(SOBJS-y)

That's really a separate patch, but I guess it's fine.

I can remove it now that wamboot is in C.

Quoted 12 lines
Quoted 2 lines
arch/arm/cpu/armv7/tegra2/warmboot.c +0 -0

...

arch/arm/cpu/armv7/tegra2/warmboot.c

Quoted 3 lines
arch/arm/cpu/armv7/tegra2/warmboot.c +3 -0
+#define BCT_OFFSET ? ? ? ? ? ? 0x100 ? ? ? ? ? /* BCT starts at 0x100 */
+#define BCT_SDRAM_PARAMS_OFFSET ? ? ? ?(BCT_OFFSET + 0x88)
+#define SDRAM_PARAMS_BASE ? ? ?(AP20_BASE_PA_SRAM + BCT_SDRAM_PARAMS_OFFSET)

BCT_OFFSET is where the BCT is stored within some warmboot-specific memory location. I think the comment should be explicit about this, because IIRC the BCT starts at offset 0 within the (cold) boot flash memory, so the comment is confusing until you trace through the code and find what SDRAM_PARAMS_BASE is used for.

OK, I think I can just remove those first two defines.

Quoted 14 lines

arch/arm/cpu/armv7/tegra2/warmboot.c

Quoted 11 lines
arch/arm/cpu/armv7/tegra2/warmboot.c +10 -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.
+ */
+#define RANDOM_AES_BLOCK_IS_RANDOM ? ? /* to randomize the header */
+#undef RANDOM_AES_BLOCK_IS_PATTERN ? ? /* to patternize the header */
+#undef RANDOM_AES_BLOCK_IS_ZERO ? ? ? ? ? ? ? ?/* to clear the header */

Why not just used ifdefs to make sure that only (and exactly) one of these is defined?

OK

Quoted 12 lines

arch/arm/cpu/armv7/tegra2/warmboot.c line 323

Quoted 6 lines
arch/arm/cpu/armv7/tegra2/warmboot.c +5 -0
+/* Currently, this routine returns a 32-bit all 0 seed. */
+static u32 query_random_seed(void)
+{
+ ? ? ? return 0;
+}

So the random option isn't really implemented at all. Perhaps just remove it completely; if someone wants it, they have to implement this function for it to be useful anyway, so adding the call to the function at the same time seems reasonable enough?

Quoted 2 lines

If not, at least make this print something at run-time so it's obvious it isn't really working.

Well I think I'll just punt this stuff.

Quoted 13 lines
Quoted 2 lines

+int warmboot_prepare_code(u32 seg_address, u32 seg_length)

...

Quoted 9 lines

+ ? ? ? /*
+ ? ? ? ?* 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 >= AP20_BASE_PA_SRAM)) {
+ ? ? ? ? ? ? ? err = -EFAULT;
+ ? ? ? ? ? ? ? goto fail;
+ ? ? ? }

Quoted 6 lines

The IRAM check only validates that the address isn't at, within, or after the IRAM location, which doesn't exactly match the comment. If the restriction is "within" IRAM, the end address needs to be checked too. Isn't the real restriction that the address needs to be within SDRAM though? If so, it seems better to check that directly.

Done

Quoted 14 lines

...

Quoted 13 lines

+ ? ? ? /* 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));

arch/arm/cpu/armv7/tegra2/warmboot.c +8 -0
+
+ ? ? ? ? ? ? ? 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;
Quoted 8 lines

arch/arm/cpu/armv7/tegra2/warmboot.c

Quoted 5 lines
arch/arm/cpu/armv7/tegra2/warmboot.c +5 -0
+#else
+ ? ? ? ? ? ? ? ? ? ? ? printf("None of RANDOM_AES_BLOCK_IS_XXX is defined; ");
+ ? ? ? ? ? ? ? ? ? ? ? printf("Default to pattern 0.\n");
+ ? ? ? ? ? ? ? ? ? ? ? *aes_block++ = 0;
+#endif

Why not issue a compile error so the person who configured U-Boot is immediately aware of the problem, instead of delaying the issue to run-time?

Will punt this.

Quoted 28 lines
Quoted 5 lines

+ ? ? ? ? ? ? ? } while (aes_block < end);
+ ? ? ? }

arch/arm/cpu/armv7/tegra2/warmboot_avp.c +0 -0

...

Quoted 22 lines
arch/arm/cpu/armv7/tegra2/warmboot_avp.c +22 -0
+void wb_start(void)
+{
+ ? ? ? struct pmux_tri_ctlr *pmt = (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+ ? ? ? struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_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;
+ ? ? ? union osc_ctrl_reg osc_ctrl;
+ ? ? ? union pllx_base_reg pllx_base;
+ ? ? ? union pllx_misc_reg pllx_misc;
+ ? ? ? union scratch3_reg scratch3;
+ ? ? ? u32 reg;
+
+ ? ? ? /* enable JTAG & TBE */
+ ? ? ? writel(CONFIG_CTL_TBE | CONFIG_CTL_JTAG, &pmt->pmt_cfg_ctl);
+
+ ? ? ? /* Are we running where we're supposed to be? */
+ ? ? ? asm volatile (
+ ? ? ? ? ? ? ? "adr ? ?%0, wb_start;" ?/* reg: wb_start address */
+ ? ? ? ? ? ? ? : "=r"(reg) ? ? ? ? ? ? /* output */
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* no input, no clobber list */
+ ? ? ? );
Quoted 8 lines
Quoted 3 lines

+
+ ? ? ? if (reg != AP20_WB_RUN_ADDRESS)
+ ? ? ? ? ? ? ? goto do_reset;

Does that code actually work; for it to work, the code would need to be either explicitly compile PIC (position independent) or accidentally be synthesized to code that happens to be PIC (not sure that's possible/likely).

ARM is normally PIC unless you try hard.

Quoted 8 lines
Quoted 6 lines

+ ? ? ? /* Set the drive strength */
+ ? ? ? osc_ctrl.word = readl(&clkrst->crc_osc_ctrl);
+ ? ? ? osc_ctrl.xofs = 4;
+ ? ? ? osc_ctrl.xoe = 1;
+ ? ? ? writel(osc_ctrl.word, &clkrst->crc_osc_ctrl);

Isn't that board-specific?

If so it currently works on all boards.

Quoted 3 lines

Shouldn't the code save the old value during suspend, and restore it later or something like that, or be a board-specific #define?

Maybe, but I'm not aware of any differences. Perhaps something to look at later if it is needed? I will add a TODO.

Quoted 7 lines

A general question: How much does this all depend on specific interactions with the kernel? Does the kernel have to follow some specific protocol during suspend to make this all work? In mainline, there's no suspend support in Tegra, so I'm slightly worried that when it gets upstreamed, this code might need changes to address any review comments there?

My limited understanding is that U-Boot's bit has a clear and small responsibility to get the memory and CPU clocks running so that the A9 cores start up again, and it is up to Linux to take it from there.

Both the code to save the info and restore it are in U-Boot. There may be some gotchas when the kernel stuff goes upstream, not sure.

Quoted 16 lines
Quoted 2 lines
arch/arm/include/asm/arch-tegra2/warmboot.h +0 -0

...

arch/arm/include/asm/arch-tegra2/warmboot.h

Quoted 11 lines
arch/arm/include/asm/arch-tegra2/warmboot.h +11 -0
+/*
+ * Defines the code header information for the boot rom.
+ *
+ * The code immediately follows the code header.
+ *
+ * Note that the code header needs to be 16 bytes aligned to preserve
+ * the alignment of relevant data for hash and decryption computations without
+ * requiring extra copies to temporary memory areas.
+ */
+struct wb_header {
+ ? ? ? u32 length_in_secure; ? /* length of the code header */

I assume s/in_secure/insecure/ ?

Seems likely to me, will change it.

Quoted 10 lines
Quoted 9 lines

+ ? ? ? u32 reserved[3];
+ ? ? ? struct hash hash; ? ? ? /* hash of header+code, starts next field*/
+ ? ? ? 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 */
+ ? ? ? u32 entry_point; ? ? ? ?/* execution address of the wb code */
+ ? ? ? u32 code_length; ? ? ? ?/* length of the code */
+};

Quoted 2 lines

--
nvpublic

Regards,
Simon

#32 lore raw

PATCH 9/14 tegra: Add warmboot implementation

Hi Simon,

Quoted 35 lines · Simon Glass

Hi Stephen,

[Yen please can you read this also?]

Quoted 6 lines · Stephen Warren
Quoted 5 lines · Simon Glass

From: Yen Lin <[email protected]>

Add code to set up the warm boot area in the Tegra CPU ready for a resume after suspend.

Quoted 8 lines
Quoted 1 line

How come Yen's S-o-b line is missing here?

As a general comment on this patch, it contains a lot of structure definitions and defines that should really be part of the clock module's headers and similar; why not just included the clock headers and place all the definitions in those headers if they aren't already there?

Yes this bit of it got a pretty light review at the time and I was reluctant to press on the bitfields when that side of things was still up in the air. No functions exist to access these things and using the clk_rst.h header adds a mountain of ugly reg & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT to the code. I am still uncomfortable with how this sort of thing is done in U-Boot.

Also the AVP code cannot call functions in clock.c (they are in SDRAM which isn't on yet), so we need the structures or some sort of access there anyway.

I will tidy up some low-hanging fruit in warmboot.c but don't know that I can do much with warmboot_avp.c. At least it isn't assembler anymore!

Quoted 7 lines

But there a few questions here. Firstly it seems that it saves some memory speed info to scratch2 but never restores it. Then it restores CPU speed from scratch3 but I can't see where it saves it. Does Yen have any comments on that? Apparently it works because we have been using it, but... If it is saving things that are never restored I could dump that and reduce the code size.

U-boot code saves sdram parameters to scratch2, scratch4, and scratch 24 registers, so when system resumes, bootrom can restore sdram parameters from these registers.

The scratch3 register content was saved by kernel before suspend, and is used by the warmboot code to restore PLLX settings.

Regards,

Yen

-----------------------------------------------------------------------------------
This email message is for the sole use of the intended recipient(s) and may contain confidential information. Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message.
-----------------------------------------------------------------------------------

#33 lore raw

PATCH 9/14 tegra: Add warmboot implementation

Hi Yen,

Quoted 46 lines · Yen Lin

Hi Simon,

Quoted 35 lines · Simon Glass

Hi Stephen,

[Yen please can you read this also?]

Quoted 6 lines · Stephen Warren
Quoted 5 lines · Simon Glass

From: Yen Lin <[email protected]>

Add code to set up the warm boot area in the Tegra CPU ready for a resume after suspend.

Quoted 8 lines
Quoted 1 line

How come Yen's S-o-b line is missing here?

As a general comment on this patch, it contains a lot of structure definitions and defines that should really be part of the clock module's headers and similar; why not just included the clock headers and place all the definitions in those headers if they aren't already there?

Yes this bit of it got a pretty light review at the time and I was reluctant to press on the bitfields when that side of things was still up in the air. No functions exist to access these things and using the clk_rst.h header adds a mountain of ugly reg & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT to the code. I am still uncomfortable with how this sort of thing is done in U-Boot.

Also the AVP code cannot call functions in clock.c (they are in SDRAM which isn't on yet), so we need the structures or some sort of access there anyway.

I will tidy up some low-hanging fruit in warmboot.c but don't know that I can do much with warmboot_avp.c. At least it isn't assembler anymore!

Quoted 7 lines

But there a few questions here. Firstly it seems that it saves some memory speed info to scratch2 but never restores it. Then it restores CPU speed from scratch3 but I can't see where it saves it. Does Yen have any comments on that? Apparently it works because we have been using it, but... If it is saving things that are never restored I could dump that and reduce the code size.

Quoted 6 lines

U-boot code saves sdram parameters to scratch2, scratch4, and scratch 24 registers, so when system resumes, bootrom can restore sdram parameters from these registers.

The scratch3 register content was saved by kernel before suspend, and is used by the warmboot code to restore PLLX settings.

Thanks for the info.

On resume I do not see it using scratch2, 4 or 24 within U-Boot. Are those used in the kernel?

I should add something to document this so the kernel people can match up when that side of it goes up stream.

Regards,
Simon

Quoted 13 lines

Regards,

Yen

-----------------------------------------------------------------------------------
This email message is for the sole use of the intended recipient(s) and may contain confidential information. ?Any unauthorized review, use, disclosure or distribution is prohibited. ?If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message.
-----------------------------------------------------------------------------------

#34 lore raw

PATCH 9/14 tegra: Add warmboot implementation

Quoted 4 lines · Simon Glass
Quoted 3 lines · Yen Lin
Quoted 2 lines · Simon Glass
Quoted 1 line · Stephen Warren

On 12/26/2011 12:33 PM, Simon Glass wrote:

...

Quoted 12 lines
Quoted 12 lines
Quoted 7 lines

But there a few questions here. Firstly it seems that it saves some memory speed info to scratch2 but never restores it. Then it restores CPU speed from scratch3 but I can't see where it saves it. Does Yen have any comments on that? Apparently it works because we have been using it, but... If it is saving things that are never restored I could dump that and reduce the code size.

U-boot code saves sdram parameters to scratch2, scratch4, and scratch 24 registers, so when system resumes, bootrom can restore sdram parameters from these registers.

Quoted 7 lines
Quoted 2 lines

The scratch3 register content was saved by kernel before suspend, and is used by the warmboot code to restore PLLX settings.

Thanks for the info.

On resume I do not see it using scratch2, 4 or 24 within U-Boot. Are those used in the kernel?

The Tegra boot ROM (which contains the power-on code for the AVP) is what interprets these, according to Yen above.

One question for Yen: Why doesn't the boot ROM read the SDRAM parameters from the BCT like it does during a cold boot? Perhaps there's some interaction with clock settings, so the boot ROM needs to know the clock/voltage/... state the kernel was in when suspending, rather than just using the "usual" cold boot settings?

Quoted 2 lines

I should add something to document this so the kernel people can match up when that side of it goes up stream.

Signature · 1 line
nvpublic
#35 lore raw

PATCH 9/14 tegra: Add warmboot implementation

Quoted 26 lines · Stephen Warren
Quoted 4 lines · Simon Glass
Quoted 3 lines · Yen Lin
Quoted 2 lines · Simon Glass
Quoted 1 line · Stephen Warren

On 12/26/2011 12:33 PM, Simon Glass wrote:

...

Quoted 12 lines
Quoted 12 lines
Quoted 7 lines

But there a few questions here. Firstly it seems that it saves some memory speed info to scratch2 but never restores it. Then it restores CPU speed from scratch3 but I can't see where it saves it. Does Yen have any comments on that? Apparently it works because we have been using it, but... If it is saving things that are never restored I could dump that and reduce the code size.

U-boot code saves sdram parameters to scratch2, scratch4, and scratch 24 registers, so when system resumes, bootrom can restore sdram parameters from these registers.

Quoted 7 lines
Quoted 2 lines

The scratch3 register content was saved by kernel before suspend, and is used by the warmboot code to restore PLLX settings.

Thanks for the info.

On resume I do not see it using scratch2, 4 or 24 within U-Boot. Are those used in the kernel?

Quoted 9 lines

The Tegra boot ROM (which contains the power-on code for the AVP) is what interprets these, according to Yen above.

One question for Yen: Why doesn't the boot ROM read the SDRAM parameters from the BCT like it does during a cold boot? Perhaps there's some interaction with clock settings, so the boot ROM needs to know the clock/voltage/... state the kernel was in when suspending, rather than just using the "usual" cold boot settings?

This is to reduce latency. During resume, Bootrom will not read BCT (from SPI or EMMC) to set SDRAM parameters. Instead, it reads directly from those scratch registers to set SDRAM.

Quoted 3 lines
Quoted 2 lines

I should add something to document this so the kernel people can match up when that side of it goes up stream.

-----------------------------------------------------------------------------------
This email message is for the sole use of the intended recipient(s) and may contain confidential information. Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message.
-----------------------------------------------------------------------------------

#36 lore raw

PATCH 10/14 tegra: Setup PMC scratch info from ap20 setup

In reply to Simon Glass

From: Yen Lin <[email protected]>

Save SDRAM parameters into the warmboot scratch registers

---
 arch/arm/cpu/armv7/tegra2/ap20.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)
arch/arm/cpu/armv7/tegra2/ap20.c +6 -0
index 311e93f..c0943eb 100644
@@ -30,6 +30,7 @@
 #include <asm/arch/pmc.h>
 #include <asm/arch/pinmux.h>
 #include <asm/arch/scu.h>
+#include <asm/arch/warmboot.h>
 #include <common.h>
 
 int tegra_get_chip_type(void)
@@ -310,6 +311,11 @@ void init_pmc_scratch(void)
 
 	/* ODMDATA is for kernel use to determine RAM size, LP config, etc. */
 	writel(CONFIG_SYS_BOARD_ODMDATA, &pmc->pmc_scratch20);
+
+#ifdef CONFIG_TEGRA2_LP0
+	/* save Sdram params to PMC 2, 4, and 24 for WB0 */
+	warmboot_save_sdram_params();
+#endif
 }
 
 void tegra2_start(void)
Signature · 1 line
1.7.3.1
#37 lore raw

PATCH 11/14 tegra: Set up warmboot code on Nvidia boards

In reply to Simon Glass

Call the function to put warmboot boot in a suitable place for resume.

---
 board/nvidia/common/board.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)
board/nvidia/common/board.c +5 -0
index 10c0a67..fbdd260 100644
@@ -34,6 +34,7 @@
 #include <asm/arch/pmc.h>
 #include <asm/arch/pmu.h>
 #include <asm/arch/uart.h>
+#include <asm/arch/warmboot.h>
 #include <spi.h>
 #include <asm/arch/usb.h>
 #include <i2c.h>
@@ -83,6 +84,10 @@ int board_init(void)
 	board_usb_init(gd->fdt_blob);
 #endif
 
+#ifdef CONFIG_TEGRA2_LP0
+	/* prepare the WB code to LP0 location */
+	warmboot_prepare_code(TEGRA_LP0_ADDR, TEGRA_LP0_SIZE);
+#endif
 #ifdef CONFIG_TEGRA2_I2C
 	i2c_init_board();
 
Signature · 1 line
1.7.3.1
#38 lore raw

PATCH 12/14 tegra: Set vdd_core and vdd_cpu to high

In reply to Simon Glass

From: Jimmy Zhang <[email protected]>

At cold boot, the default voltage supplied by pmu is not high enough to support emc to run at its highest clock frequency. The code added here is to update the default vdd_core and vdd_cpu to higher values.

(Sorry if I have mangled this comment)

---
 board/nvidia/common/board.c |   18 ++++++++++++++++++
 1 files changed, 18 insertions(+), 0 deletions(-)
board/nvidia/common/board.c +18 -0
index fbdd260..cda2417 100644
@@ -30,6 +30,7 @@
 #include <asm/arch/board.h>
 #include <asm/arch/clk_rst.h>
 #include <asm/arch/clock.h>
+#include <asm/arch/fuse.h>
 #include <asm/arch/pinmux.h>
 #include <asm/arch/pmc.h>
 #include <asm/arch/pmu.h>
@@ -56,6 +57,21 @@ int timer_init(void)
 }
 
 /*
+ * Routine: power_det_init
+ * Description: turn off power detects
+ */
+static void power_det_init(void)
+{
+#if defined(CONFIG_TEGRA2)
+	struct pmc_ctlr *const pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
+
+	/* turn off power detects */
+	writel(0, &pmc->pmc_pwr_det_latch);
+	writel(0, &pmc->pmc_pwr_det);
+#endif
+}
+
+/*
  * Routine: board_init
  * Description: Early hardware init.
  */
@@ -88,6 +104,8 @@ int board_init(void)
 	/* prepare the WB code to LP0 location */
 	warmboot_prepare_code(TEGRA_LP0_ADDR, TEGRA_LP0_SIZE);
 #endif
+
+	power_det_init();
 #ifdef CONFIG_TEGRA2_I2C
 	i2c_init_board();
 
Signature · 1 line
1.7.3.1
#39 lore raw

PATCH 12/14 tegra: Set vdd_core and vdd_cpu to high

Quoted 7 lines · Simon Glass

From: Jimmy Zhang <[email protected]>

At cold boot, the default voltage supplied by pmu is not high enough to support emc to run at its highest clock frequency. The code added here is to update the default vdd_core and vdd_cpu to higher values.

(Sorry if I have mangled this comment)

?? Remove that last line?

I thought this issue only affected the T25 SKU when coupled with a particular voltage regulator that wasn't reprogrammed to explicitly support T25. Hence, shouldn't this code only be enabled for specific boards?

Quoted 1 line
board/nvidia/common/board.c +0 -0

...

Quoted 4 lines

/*
+ * Routine: power_det_init
+ * Description: turn off power detects
+ */

board/nvidia/common/board.c int timer_init(void) · line 72

Quoted 10 lines
board/nvidia/common/board.c +10 -0
+static void power_det_init(void)
+{
+#if defined(CONFIG_TEGRA2)
+	struct pmc_ctlr *const pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
+
+	/* turn off power detects */
+	writel(0, &pmc->pmc_pwr_det_latch);
+	writel(0, &pmc->pmc_pwr_det);
+#endif
+}

I can't tell how that code relates to the commit description.

Signature · 1 line
nvpublic
#40 lore raw

PATCH 12/14 tegra: Set vdd_core and vdd_cpu to high

Hi Stephen,

Quoted 10 lines · Stephen Warren
Quoted 7 lines · Simon Glass

From: Jimmy Zhang <[email protected]>

At cold boot, the default voltage supplied by pmu is not high enough to support emc to run at its highest clock frequency. The code added here is to update the default vdd_core and vdd_cpu to higher values.

(Sorry if I have mangled this comment)

?? Remove that last line?

Actually that is the truth! Unfortunately this commit originally brought in the whole PMU and assorted other things in one big patch. I split those things out in this series, and I think this may actually relate to something else.

Quoted 7 lines

I thought this issue only affected the T25 SKU when coupled with a particular voltage regulator that wasn't reprogrammed to explicitly support T25. Hence, shouldn't this code only be enabled for specific boards?

Quoted 1 line
board/nvidia/common/board.c +0 -0

...

Quoted 16 lines
Quoted 4 lines

?/*
+ * Routine: power_det_init
+ * Description: turn off power detects
+ */

board/nvidia/common/board.c int timer_init(void) · line 72

Quoted 10 lines
board/nvidia/common/board.c +10 -0
+static void power_det_init(void)
+{
+#if defined(CONFIG_TEGRA2)
+ ? ? struct pmc_ctlr *const pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
+
+ ? ? /* turn off power detects */
+ ? ? writel(0, &pmc->pmc_pwr_det_latch);
+ ? ? writel(0, &pmc->pmc_pwr_det);
+#endif
+}

I can't tell how that code relates to the commit description.

Neither could I, hence my comment. But I think I just made a mistake - I have been back through the commits and actually I think it should be:

Tegra core power rail has leakage voltage around 0.2V while system in suspend mode. The source of the leakage should be coming from PMC
power detect
logic for IO rails power detection.
That can be disabled by writing a '0' to PWR_DET_LATCH followed by
writing '0'

    to PWR_DET (APBDEV_PMC_PWR_DET_0).

so I will change it.

Regards,
Simon

Quoted 3 lines

--
nvpublic

#41 lore raw

PATCH 13/14 tegra: Add EMC settings for Seaboard, Harmony

In reply to Simon Glass

From: Jimmy Zhang <[email protected]>

Set Seaboard and Harmony to optimal memory settings based on the SOC in use (T20 or T25).

---
 board/nvidia/common/Makefile |    1 +
 board/nvidia/common/board.c  |    4 +
 board/nvidia/common/emc.c    |  295 ++++++++++++++++++++++++++++++++++++++++++
 board/nvidia/common/emc.h    |   29 ++++
 4 files changed, 329 insertions(+), 0 deletions(-)
 create mode 100644 board/nvidia/common/emc.c
 create mode 100644 board/nvidia/common/emc.h
board/nvidia/common/Makefile +1 -0
index 3e748fd..a93d458 100644
@@ -27,6 +27,7 @@ LIB	= $(obj)lib$(VENDOR).o
 
 COBJS-y += board.o
 COBJS-$(CONFIG_SPI_UART_SWITCH) += uart-spi-switch.o
+COBJS-$(CONFIG_TEGRA_CLOCK_SCALING) += emc.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
board/nvidia/common/board.c +4 -0
index cda2417..2569ae1 100644
@@ -30,6 +30,7 @@
 #include <asm/arch/board.h>
 #include <asm/arch/clk_rst.h>
 #include <asm/arch/clock.h>
+#include <asm/arch/emc.h>
 #include <asm/arch/fuse.h>
 #include <asm/arch/pinmux.h>
 #include <asm/arch/pmc.h>
@@ -40,6 +41,7 @@
 #include <asm/arch/usb.h>
 #include <i2c.h>
 #include "board.h"
+#include "emc.h"
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -111,6 +113,8 @@ int board_init(void)
 
 #ifdef CONFIG_TEGRA_PMU
 	pmu_set_nominal();
+
+	board_emc_init();
 #endif
 #endif
 
board/nvidia/common/emc.c new file +295 -0

295 lines not on this page · raw message

board/nvidia/common/emc.h new file +29 -0
new file mode 100644
index 0000000..ec1b115
@@ -0,0 +1,29 @@
+/*
+ * 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 _NVIDIA_EMC_H_
+#define _NVIDIA_EMC_H_
+
+int board_emc_init(void);
+
+#endif
Signature · 1 line
1.7.3.1
#42 lore raw

PATCH 13/14 tegra: Add EMC settings for Seaboard, Harmony

Quoted 8 lines · Simon Glass

From: Jimmy Zhang <[email protected]>

Set Seaboard and Harmony to optimal memory settings based on the SOC in use (T20 or T25).

board/nvidia/common/emc.c +0 -0

...

Quoted 1 line

+static const struct tegra_emc_table seaboard_emc_tables_hynix_333Mhz[] = {

...

Quoted 1 line

+static const struct tegra_emc_table seaboard_emc_tables_hynix_380Mhz[] = {

...

Quoted 1 line

+void seaboard_emc_init(void)

...

board/nvidia/common/emc.c line 273

Quoted 10 lines
board/nvidia/common/emc.c +10 -0
+static struct emc_init board_table[] = {
+       {
+               .id     = MACH_TYPE_HARMONY,
+               .init   = NULL,
+       },
+       {
+               .id     = MACH_TYPE_SEABOARD,
+               .init   = seaboard_emc_init,
+       },
+};

Why not just put the Seaboard-specific code into Seaboard's board directory instead of a common location? Then you wouldn't need this table at all, and boards other than Seaboard wouldn't be required to carry the Seaboard EMC tables.

There don't appear to be any tables for Harmony, which is inconsistent with the commit description.

board/nvidia/common/emc.c line 284

Quoted 10 lines
board/nvidia/common/emc.c +10 -0
+int board_emc_init(void)
+{
+       int     i;
+       DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_TEGRA_PMU
+       /* if voltage has not been set properly, return */
+       if (!pmu_is_voltage_nominal())
+               return -1;
+#endif

Why/when would the PMU voltage not be nominal?

Can't we error out the compile if the options that cause the PMU voltage to be initialized to nominal are not set, instead of detecting this at runtime?

Finally, I don't think there are EMC tables here for all the EMC frequencies that we have BCTs for. Perhaps that's not an issue, and perhaps I should ignore the other BCTs (e.g. 400MHZ EMC) since nobody actually uses them?

Signature · 1 line
nvpublic
#43 lore raw

PATCH 13/14 tegra: Add EMC settings for Seaboard, Harmony

Hi Stephen,

Quoted 16 lines · Stephen Warren
Quoted 8 lines · Simon Glass

From: Jimmy Zhang <[email protected]>

Set Seaboard and Harmony to optimal memory settings based on the SOC in use (T20 or T25).

board/nvidia/common/emc.c +0 -0

...

Quoted 1 line

+static const struct tegra_emc_table seaboard_emc_tables_hynix_333Mhz[] = {

...

Quoted 1 line

+static const struct tegra_emc_table seaboard_emc_tables_hynix_380Mhz[] = {

...

Quoted 1 line

+void seaboard_emc_init(void)

...

Quoted 15 lines

board/nvidia/common/emc.c

Quoted 10 lines
board/nvidia/common/emc.c +10 -0
+static struct emc_init board_table[] = {
+ ? ? ? {
+ ? ? ? ? ? ? ? .id ? ? = MACH_TYPE_HARMONY,
+ ? ? ? ? ? ? ? .init ? = NULL,
+ ? ? ? },
+ ? ? ? {
+ ? ? ? ? ? ? ? .id ? ? = MACH_TYPE_SEABOARD,
+ ? ? ? ? ? ? ? .init ? = seaboard_emc_init,
+ ? ? ? },
+};

Why not just put the Seaboard-specific code into Seaboard's board directory instead of a common location? Then you wouldn't need this table at all, and boards other than Seaboard wouldn't be required to carry the Seaboard EMC tables.

I have moved this into the device tree.

Quoted 2 lines

There don't appear to be any tables for Harmony, which is inconsistent with the commit description.

Updated the commit description :-)

Quoted 13 lines

board/nvidia/common/emc.c line 284

Quoted 11 lines
board/nvidia/common/emc.c +10 -0
+int board_emc_init(void)
+{
+ ? ? ? int ? ? i;
+ ? ? ? DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_TEGRA_PMU
+ ? ? ? /* if voltage has not been set properly, return */
+ ? ? ? if (!pmu_is_voltage_nominal())
+ ? ? ? ? ? ? ? return -1;
+#endif

Why/when would the PMU voltage not be nominal?

On boot, it starts up lower and we raise it to nominal so we can run at full speed.

Quoted 4 lines

Can't we error out the compile if the options that cause the PMU voltage to be initialized to nominal are not set, instead of detecting this at runtime?

I don't think so, since we can't know in U-Boot what the start-up voltages are.

Quoted 4 lines

Finally, I don't think there are EMC tables here for all the EMC frequencies that we have BCTs for. Perhaps that's not an issue, and perhaps I should ignore the other BCTs (e.g. 400MHZ EMC) since nobody actually uses them?

Yes I think maximum speed is all anyone is probably interested in now.

Regards,
Simon

Quoted 3 lines

--
nvpublic

#44 lore raw

PATCH 13/14 tegra: Add EMC settings for Seaboard, Harmony

Simon Glass wrote at Thursday, January 12, 2012 4:05 PM:

Quoted 6 lines · Stephen Warren
Quoted 5 lines · Simon Glass
Quoted 4 lines

From: Jimmy Zhang <[email protected]>

Set Seaboard and Harmony to optimal memory settings based on the SOC in use (T20 or T25).

...

Quoted 13 lines
Quoted 4 lines
Quoted 4 lines
board/nvidia/common/emc.c new file +4 -0
+int board_emc_init(void)
+{
+ ? ? ? int ? ? i;
+ ? ? ? DECLARE_GLOBAL_DATA_PTR;
Quoted 8 lines

board/nvidia/common/emc.c line 284

Quoted 6 lines
board/nvidia/common/emc.c new file +6 -0
+
+#ifdef CONFIG_TEGRA_PMU
+ ? ? ? /* if voltage has not been set properly, return */
+ ? ? ? if (!pmu_is_voltage_nominal())
+ ? ? ? ? ? ? ? return -1;
+#endif

Why/when would the PMU voltage not be nominal?

Quoted 8 lines

On boot, it starts up lower and we raise it to nominal so we can run at full speed.

Quoted 3 lines

Can't we error out the compile if the options that cause the PMU voltage to be initialized to nominal are not set, instead of detecting this at runtime?

I don't think so, since we can't know in U-Boot what the start-up voltages are.

So how does the system get to the nominal state? And if board_emc_init() is called when the system isn't in the nominal state, does it somehow get called again later once it is, so that the EMC initialization doesn't fail the error-check quoted above?

In other words, presumably U-Boot explicitly programs the PMU into the nominal stage at some point. Shouldn't we defer calling board_emc_init() until after that time, thus making that error-check redundant?

Quoted 6 lines
Quoted 4 lines

Finally, I don't think there are EMC tables here for all the EMC frequencies that we have BCTs for. Perhaps that's not an issue, and perhaps I should ignore the other BCTs (e.g. 400MHZ EMC) since nobody actually uses them?

Yes I think maximum speed is all anyone is probably interested in now.

400MHz is faster than the entries in the table in this change, IIRC. But if the tables in this change are for the standard frequencies average people use (i.e. not those doing board/memory quals), it's probably fine.

Signature · 1 line
nvpublic
#45 lore raw

PATCH 13/14 tegra: Add EMC settings for Seaboard, Harmony

Hi Stephen,

Quoted 28 lines · Stephen Warren

Simon Glass wrote at Thursday, January 12, 2012 4:05 PM:

Quoted 6 lines · Stephen Warren
Quoted 5 lines · Simon Glass
Quoted 4 lines

From: Jimmy Zhang <[email protected]>

Set Seaboard and Harmony to optimal memory settings based on the SOC in use (T20 or T25).

...

Quoted 20 lines
Quoted 4 lines
Quoted 4 lines
board/nvidia/common/emc.c new file +4 -0
+int board_emc_init(void)
+{
+ ? ? ? int ? ? i;
+ ? ? ? DECLARE_GLOBAL_DATA_PTR;
Quoted 8 lines

board/nvidia/common/emc.c line 284

Quoted 6 lines
board/nvidia/common/emc.c new file +6 -0
+
+#ifdef CONFIG_TEGRA_PMU
+ ? ? ? /* if voltage has not been set properly, return */
+ ? ? ? if (!pmu_is_voltage_nominal())
+ ? ? ? ? ? ? ? return -1;
+#endif

Why/when would the PMU voltage not be nominal?

On boot, it starts up lower and we raise it to nominal so we can run at full speed.

Quoted 3 lines

Can't we error out the compile if the options that cause the PMU voltage to be initialized to nominal are not set, instead of detecting this at runtime?

Quoted 6 lines
Quoted 1 line

I don't think so, since we can't know in U-Boot what the start-up voltages are.

So how does the system get to the nominal state? And if board_emc_init() is called when the system isn't in the nominal state, does it somehow get called again later once it is, so that the EMC initialization doesn't fail the error-check quoted above?

We call board_emc_init() after pmu_set_nominal().

Quoted 4 lines

In other words, presumably U-Boot explicitly programs the PMU into the nominal stage at some point. Shouldn't we defer calling board_emc_init() until after that time, thus making that error-check redundant?

Yes, but if you look at the patch above, that's what we do:

 #ifdef CONFIG_TEGRA_PMU
       pmu_set_nominal();

+
+ board_emc_init();
#endif
#endif

Quoted 7 lines
Quoted 7 lines
Quoted 6 lines

Finally, I don't think there are EMC tables here for all the EMC frequencies that we have BCTs for. Perhaps that's not an issue, and perhaps I should ignore the other BCTs (e.g. 400MHZ EMC) since nobody actually uses them?

Quoted 5 lines
Quoted 1 line

Yes I think maximum speed is all anyone is probably interested in now.

400MHz is faster than the entries in the table in this change, IIRC. But if the tables in this change are for the standard frequencies average people use (i.e. not those doing board/memory quals), it's probably fine.

OK, perhaps I should have said maximum speed that actually works reliably :-)

Regards,
Simon

Quoted 4 lines

--
nvpublic

#46 lore raw

PATCH 13/14 tegra: Add EMC settings for Seaboard, Harmony

Simon Glass wrote at Thursday, January 12, 2012 4:55 PM:

Quoted 47 lines · Stephen Warren
Quoted 28 lines

Simon Glass wrote at Thursday, January 12, 2012 4:05 PM:

Quoted 6 lines · Stephen Warren
Quoted 5 lines · Simon Glass
Quoted 4 lines

From: Jimmy Zhang <[email protected]>

Set Seaboard and Harmony to optimal memory settings based on the SOC in use (T20 or T25).

...

Quoted 20 lines
Quoted 4 lines
Quoted 4 lines
board/nvidia/common/emc.c new file +4 -0
+int board_emc_init(void)
+{
+ ? ? ? int ? ? i;
+ ? ? ? DECLARE_GLOBAL_DATA_PTR;
Quoted 8 lines

board/nvidia/common/emc.c line 284

Quoted 6 lines
board/nvidia/common/emc.c new file +6 -0
+
+#ifdef CONFIG_TEGRA_PMU
+ ? ? ? /* if voltage has not been set properly, return */
+ ? ? ? if (!pmu_is_voltage_nominal())
+ ? ? ? ? ? ? ? return -1;
+#endif

Why/when would the PMU voltage not be nominal?

On boot, it starts up lower and we raise it to nominal so we can run at full speed.

Quoted 3 lines

Can't we error out the compile if the options that cause the PMU voltage to be initialized to nominal are not set, instead of detecting this at runtime?

Quoted 6 lines
Quoted 1 line

I don't think so, since we can't know in U-Boot what the start-up voltages are.

So how does the system get to the nominal state? And if board_emc_init() is called when the system isn't in the nominal state, does it somehow get called again later once it is, so that the EMC initialization doesn't fail the error-check quoted above?

We call board_emc_init() after pmu_set_nominal().

Quoted 4 lines

In other words, presumably U-Boot explicitly programs the PMU into the nominal stage at some point. Shouldn't we defer calling board_emc_init() until after that time, thus making that error-check redundant?

Yes, but if you look at the patch above, that's what we do:

 #ifdef CONFIG_TEGRA_PMU
       pmu_set_nominal();

board/nvidia/common/board.c int board_init(void) · line 119

Quoted 4 lines
board/nvidia/common/board.c +2 -0
+
+       board_emc_init();
 #endif
 #endif

OK, so in practice,

/* if voltage has not been set properly, return */ if (!pmu_is_voltage_nominal())

... will never fire. My original point was that if so, why is that check needed? I suppose it's a reasonable safety net though - that's the reason?

Signature · 1 line
nvpublic
#47 lore raw

PATCH 13/14 tegra: Add EMC settings for Seaboard, Harmony

Hi Stephen,

Quoted 53 lines · Stephen Warren

Simon Glass wrote at Thursday, January 12, 2012 4:55 PM:

Quoted 43 lines · Stephen Warren
Quoted 28 lines

Simon Glass wrote at Thursday, January 12, 2012 4:05 PM:

Quoted 6 lines · Stephen Warren
Quoted 5 lines · Simon Glass
Quoted 4 lines

From: Jimmy Zhang <[email protected]>

Set Seaboard and Harmony to optimal memory settings based on the SOC in use (T20 or T25).

...

Quoted 20 lines
Quoted 4 lines
Quoted 4 lines
board/nvidia/common/emc.c new file +4 -0
+int board_emc_init(void)
+{
+ ? ? ? int ? ? i;
+ ? ? ? DECLARE_GLOBAL_DATA_PTR;
Quoted 8 lines

board/nvidia/common/emc.c line 284

Quoted 6 lines
board/nvidia/common/emc.c new file +6 -0
+
+#ifdef CONFIG_TEGRA_PMU
+ ? ? ? /* if voltage has not been set properly, return */
+ ? ? ? if (!pmu_is_voltage_nominal())
+ ? ? ? ? ? ? ? return -1;
+#endif

Why/when would the PMU voltage not be nominal?

On boot, it starts up lower and we raise it to nominal so we can run at full speed.

Quoted 3 lines

Can't we error out the compile if the options that cause the PMU voltage to be initialized to nominal are not set, instead of detecting this at runtime?

Quoted 6 lines
Quoted 1 line

I don't think so, since we can't know in U-Boot what the start-up voltages are.

So how does the system get to the nominal state? And if board_emc_init() is called when the system isn't in the nominal state, does it somehow get called again later once it is, so that the EMC initialization doesn't fail the error-check quoted above?

We call board_emc_init() after pmu_set_nominal().

Quoted 4 lines

In other words, presumably U-Boot explicitly programs the PMU into the nominal stage at some point. Shouldn't we defer calling board_emc_init() until after that time, thus making that error-check redundant?

Quoted 8 lines

Yes, but if you look at the patch above, that's what we do:

?#ifdef CONFIG_TEGRA_PMU
? ? ? ?pmu_set_nominal();
+
+ ? ? ? board_emc_init();
?#endif
?#endif

Quoted 8 lines

OK, so in practice,

/* if voltage has not been set properly, return */ if (!pmu_is_voltage_nominal())

... will never fire. My original point was that if so, why is that check needed? I suppose it's a reasonable safety net though - that's the reason?

OK I see. It certainly shouldn't - it is a check that everything is well since this code is in a different file and it is possible that someone may get this wrong. If they do then the system may continue but die later in interesting ways. Still, the user has other equally complex things to worry about.

I'm happy to remove this particularly as this might become example code for other boards - what do you think?

Regards,
Simon

Quoted 4 lines

--
nvpublic

#48 lore raw

PATCH 13/14 tegra: Add EMC settings for Seaboard, Harmony

Simon Glass wrote at Thursday, January 12, 2012 5:06 PM:

Quoted 63 lines · Stephen Warren
Quoted 53 lines

Simon Glass wrote at Thursday, January 12, 2012 4:55 PM:

Quoted 43 lines · Stephen Warren
Quoted 28 lines

Simon Glass wrote at Thursday, January 12, 2012 4:05 PM:

Quoted 6 lines · Stephen Warren
Quoted 5 lines · Simon Glass
Quoted 4 lines

From: Jimmy Zhang <[email protected]>

Set Seaboard and Harmony to optimal memory settings based on the SOC in use (T20 or T25).

...

Quoted 20 lines
Quoted 4 lines
Quoted 4 lines
(quoted diff) +4 -0
+int board_emc_init(void)
+{
+ ? ? ? int ? ? i;
+ ? ? ? DECLARE_GLOBAL_DATA_PTR;
Quoted 8 lines

Review

Quoted 6 lines
(quoted diff) +6 -0
+
+#ifdef CONFIG_TEGRA_PMU
+ ? ? ? /* if voltage has not been set properly, return */
+ ? ? ? if (!pmu_is_voltage_nominal())
+ ? ? ? ? ? ? ? return -1;
+#endif

Why/when would the PMU voltage not be nominal?

On boot, it starts up lower and we raise it to nominal so we can run at full speed.

Quoted 3 lines

Can't we error out the compile if the options that cause the PMU voltage to be initialized to nominal are not set, instead of detecting this at runtime?

Quoted 6 lines
Quoted 1 line

I don't think so, since we can't know in U-Boot what the start-up voltages are.

So how does the system get to the nominal state? And if board_emc_init() is called when the system isn't in the nominal state, does it somehow get called again later once it is, so that the EMC initialization doesn't fail the error-check quoted above?

We call board_emc_init() after pmu_set_nominal().

Quoted 4 lines

In other words, presumably U-Boot explicitly programs the PMU into the nominal stage at some point. Shouldn't we defer calling board_emc_init() until after that time, thus making that error-check redundant?

Quoted 8 lines

Yes, but if you look at the patch above, that's what we do:

?#ifdef CONFIG_TEGRA_PMU
? ? ? ?pmu_set_nominal();
+
+ ? ? ? board_emc_init();
?#endif
?#endif

Quoted 8 lines

OK, so in practice,

/* if voltage has not been set properly, return */ if (!pmu_is_voltage_nominal())

... will never fire. My original point was that if so, why is that check needed? I suppose it's a reasonable safety net though - that's the reason?

Quoted 8 lines

OK I see. It certainly shouldn't - it is a check that everything is well since this code is in a different file and it is possible that someone may get this wrong. If they do then the system may continue but die later in interesting ways. Still, the user has other equally complex things to worry about.

I'm happy to remove this particularly as this might become example code for other boards - what do you think?

The check itself is probably fine for the reasons you state. However, I'd suggest adjusting the comment to something more like:

This code should only be called once the PMU is operating at nominal voltage. Hence, this test should never fail. However, this prevents unpredictable failures from occurring later if this pre-condition is not met.

Signature · 1 line
nvpublic
#49 lore raw

PATCH 13/14 tegra: Add EMC settings for Seaboard, Harmony

Hi Stephen,

Quoted 73 lines · Stephen Warren

Simon Glass wrote at Thursday, January 12, 2012 5:06 PM:

Quoted 63 lines · Stephen Warren
Quoted 53 lines

Simon Glass wrote at Thursday, January 12, 2012 4:55 PM:

Quoted 43 lines · Stephen Warren
Quoted 28 lines

Simon Glass wrote at Thursday, January 12, 2012 4:05 PM:

Quoted 6 lines · Stephen Warren
Quoted 5 lines · Simon Glass
Quoted 4 lines

From: Jimmy Zhang <[email protected]>

Set Seaboard and Harmony to optimal memory settings based on the SOC in use (T20 or T25).

...

Quoted 20 lines
Quoted 4 lines
Quoted 4 lines
(quoted diff) +4 -0
+int board_emc_init(void)
+{
+ ? ? ? int ? ? i;
+ ? ? ? DECLARE_GLOBAL_DATA_PTR;
Quoted 8 lines

Review

Quoted 6 lines
(quoted diff) +6 -0
+
+#ifdef CONFIG_TEGRA_PMU
+ ? ? ? /* if voltage has not been set properly, return */
+ ? ? ? if (!pmu_is_voltage_nominal())
+ ? ? ? ? ? ? ? return -1;
+#endif

Why/when would the PMU voltage not be nominal?

On boot, it starts up lower and we raise it to nominal so we can run at full speed.

Quoted 3 lines

Can't we error out the compile if the options that cause the PMU voltage to be initialized to nominal are not set, instead of detecting this at runtime?

Quoted 6 lines
Quoted 1 line

I don't think so, since we can't know in U-Boot what the start-up voltages are.

So how does the system get to the nominal state? And if board_emc_init() is called when the system isn't in the nominal state, does it somehow get called again later once it is, so that the EMC initialization doesn't fail the error-check quoted above?

We call board_emc_init() after pmu_set_nominal().

Quoted 4 lines

In other words, presumably U-Boot explicitly programs the PMU into the nominal stage at some point. Shouldn't we defer calling board_emc_init() until after that time, thus making that error-check redundant?

Quoted 8 lines

Yes, but if you look at the patch above, that's what we do:

?#ifdef CONFIG_TEGRA_PMU
? ? ? ?pmu_set_nominal();
+
+ ? ? ? board_emc_init();
?#endif
?#endif

Quoted 8 lines

OK, so in practice,

/* if voltage has not been set properly, return */ if (!pmu_is_voltage_nominal())

... will never fire. My original point was that if so, why is that check needed? I suppose it's a reasonable safety net though - that's the reason?

Quoted 8 lines

OK I see. It certainly shouldn't - it is a check that everything is well since this code is in a different file and it is possible that someone may get this wrong. If they do then the system may continue but die later in interesting ways. Still, the user has other equally complex things to worry about.

I'm happy to remove this particularly as this might become example code for other boards - what do you think?

Quoted 7 lines

The check itself is probably fine for the reasons you state. However, I'd suggest adjusting the comment to something more like:

This code should only be called once the PMU is operating at nominal voltage. Hence, this test should never fail. However, this prevents unpredictable failures from occurring later if this pre-condition is not met.

OK, will do.

Regards,
Simon

Quoted 4 lines

--
nvpublic

#50 lore raw

PATCH 14/14 tegra: Enable LP0 on Seaboard

In reply to Simon Glass

This enables LP0 to support suspend / resume on Seaboard.

---
 include/configs/seaboard.h      |    7 +++++++
 include/configs/tegra2-common.h |   17 +++++++++++++++++
 2 files changed, 24 insertions(+), 0 deletions(-)
include/configs/seaboard.h +7 -0
index 6e04278..97faa57 100644
@@ -25,6 +25,13 @@
 #define __CONFIG_H
 
 #include <asm/sizes.h>
+
+/* LP0 suspend / resume */
+#define CONFIG_TEGRA2_LP0
+#define CONFIG_AES
+#define CONFIG_TEGRA_PMU
+#define CONFIG_TEGRA_CLOCK_SCALING
+
 #include "tegra2-common.h"
 
 /* Enable fdt support for Seaboard. Flash the image in u-boot-dtb.bin */
include/configs/tegra2-common.h +17 -0
index 6549d00..6c38f51 100644
@@ -26,6 +26,14 @@
 #include <asm/sizes.h>
 
 /*
+ * QUOTE(m) will evaluate to a string version of the value of the macro m
+ * passed in.  The extra level of indirection here is to first evaluate the
+ * macro m before applying the quoting operator.
+ */
+#define QUOTE_(m)       #m
+#define QUOTE(m)        QUOTE_(m)
+
+/*
  * High Level Configuration Options
  */
 #define CONFIG_ARMCORTEXA9		/* This is an ARM V7 CPU core */
@@ -50,6 +58,15 @@
 #define CONFIG_CMDLINE_TAG		/* enable passing of ATAGs */
 #define CONFIG_OF_LIBFDT		/* enable passing of devicetree */
 
+#ifdef CONFIG_TEGRA2_LP0
+#define TEGRA_LP0_ADDR			0x1C406000
+#define TEGRA_LP0_SIZE			0x2000
+#define TEGRA_LP0_VEC \
+	"lp0_vec=" QUOTE(TEGRA_LP0_SIZE) "@" QUOTE(TEGRA_LP0_ADDR) " "
+#else
+#define TEGRA_LP0_VEC
+#endif
+
 /* Environment */
 #define CONFIG_ENV_SIZE			0x2000	/* Total Size Environment */
 
Signature · 1 line
1.7.3.1