All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 0/14] tegra: warmboot (suspend / resume) support
@ 2011-12-26 19:32 Simon Glass
  2011-12-26 19:32 ` [U-Boot] [PATCH 01/14] Add AES crypto library Simon Glass
                   ` (13 more replies)
  0 siblings, 14 replies; 51+ messages in thread
From: Simon Glass @ 2011-12-26 19:32 UTC (permalink / raw)
  To: u-boot

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

-- 
1.7.3.1

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 01/14] Add AES crypto library
  2011-12-26 19:32 [U-Boot] [PATCH 0/14] tegra: warmboot (suspend / resume) support Simon Glass
@ 2011-12-26 19:32 ` Simon Glass
  2012-01-08  5:49   ` Mike Frysinger
  2011-12-26 19:32 ` [U-Boot] [PATCH 02/14] tegra: Move ap20.h header into arch location Simon Glass
                   ` (12 subsequent siblings)
  13 siblings, 1 reply; 51+ messages in thread
From: Simon Glass @ 2011-12-26 19:32 UTC (permalink / raw)
  To: u-boot

From: Yen Lin <yelin@nvidia.com>

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.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
 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

diff --git a/include/aes.h b/include/aes.h
new file mode 100644
index 0000000..41b0db2
--- /dev/null
+++ b/include/aes.h
@@ -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_ */
diff --git a/lib/Makefile b/lib/Makefile
index 54708c2..df24133 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -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
diff --git a/lib/aes.c b/lib/aes.c
new file mode 100644
index 0000000..4f413c0
--- /dev/null
+++ b/lib/aes.c
@@ -0,0 +1,599 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * (C) Copyright 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
+ */
+
+/*
+ * advanced encryption standard
+ * author: karl malbrain, malbrain at yahoo.com
+ *
+ * This work, including the source code, documentation
+ * and related data, is placed into the public domain.
+ *
+ * The orginal author is Karl Malbrain.
+ *
+ * THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+ * OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+ * MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ * ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+ * RESULTING FROM THE USE, MODIFICATION, OR
+ * REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#include <common.h>
+#include "aes.h"
+
+/* forward s-box */
+static u8 sbox[256] = {
+	0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
+	0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
+	0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
+	0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
+	0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
+	0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
+	0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
+	0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
+	0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
+	0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
+	0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
+	0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
+	0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
+	0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
+	0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
+	0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
+	0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
+	0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
+	0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
+	0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
+	0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
+	0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
+	0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
+	0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
+	0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
+	0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
+	0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
+	0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
+	0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
+	0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
+	0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
+	0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
+};
+
+/* inverse s-box */
+static u8 inv_sbox[256] = {
+	0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
+	0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
+	0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
+	0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
+	0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
+	0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
+	0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
+	0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
+	0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
+	0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
+	0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
+	0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
+	0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
+	0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
+	0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
+	0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
+	0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
+	0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
+	0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
+	0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
+	0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
+	0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
+	0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
+	0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
+	0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
+	0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
+	0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
+	0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
+	0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
+	0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
+	0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
+	0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
+};
+
+/* combined Xtimes2[Sbox[]] */
+static u8 x2_sbox[256] = {
+	0xc6, 0xf8, 0xee, 0xf6, 0xff, 0xd6, 0xde, 0x91,
+	0x60, 0x02, 0xce, 0x56, 0xe7, 0xb5, 0x4d, 0xec,
+	0x8f, 0x1f, 0x89, 0xfa, 0xef, 0xb2, 0x8e, 0xfb,
+	0x41, 0xb3, 0x5f, 0x45, 0x23, 0x53, 0xe4, 0x9b,
+	0x75, 0xe1, 0x3d, 0x4c, 0x6c, 0x7e, 0xf5, 0x83,
+	0x68, 0x51, 0xd1, 0xf9, 0xe2, 0xab, 0x62, 0x2a,
+	0x08, 0x95, 0x46, 0x9d, 0x30, 0x37, 0x0a, 0x2f,
+	0x0e, 0x24, 0x1b, 0xdf, 0xcd, 0x4e, 0x7f, 0xea,
+	0x12, 0x1d, 0x58, 0x34, 0x36, 0xdc, 0xb4, 0x5b,
+	0xa4, 0x76, 0xb7, 0x7d, 0x52, 0xdd, 0x5e, 0x13,
+	0xa6, 0xb9, 0x00, 0xc1, 0x40, 0xe3, 0x79, 0xb6,
+	0xd4, 0x8d, 0x67, 0x72, 0x94, 0x98, 0xb0, 0x85,
+	0xbb, 0xc5, 0x4f, 0xed, 0x86, 0x9a, 0x66, 0x11,
+	0x8a, 0xe9, 0x04, 0xfe, 0xa0, 0x78, 0x25, 0x4b,
+	0xa2, 0x5d, 0x80, 0x05, 0x3f, 0x21, 0x70, 0xf1,
+	0x63, 0x77, 0xaf, 0x42, 0x20, 0xe5, 0xfd, 0xbf,
+	0x81, 0x18, 0x26, 0xc3, 0xbe, 0x35, 0x88, 0x2e,
+	0x93, 0x55, 0xfc, 0x7a, 0xc8, 0xba, 0x32, 0xe6,
+	0xc0, 0x19, 0x9e, 0xa3, 0x44, 0x54, 0x3b, 0x0b,
+	0x8c, 0xc7, 0x6b, 0x28, 0xa7, 0xbc, 0x16, 0xad,
+	0xdb, 0x64, 0x74, 0x14, 0x92, 0x0c, 0x48, 0xb8,
+	0x9f, 0xbd, 0x43, 0xc4, 0x39, 0x31, 0xd3, 0xf2,
+	0xd5, 0x8b, 0x6e, 0xda, 0x01, 0xb1, 0x9c, 0x49,
+	0xd8, 0xac, 0xf3, 0xcf, 0xca, 0xf4, 0x47, 0x10,
+	0x6f, 0xf0, 0x4a, 0x5c, 0x38, 0x57, 0x73, 0x97,
+	0xcb, 0xa1, 0xe8, 0x3e, 0x96, 0x61, 0x0d, 0x0f,
+	0xe0, 0x7c, 0x71, 0xcc, 0x90, 0x06, 0xf7, 0x1c,
+	0xc2, 0x6a, 0xae, 0x69, 0x17, 0x99, 0x3a, 0x27,
+	0xd9, 0xeb, 0x2b, 0x22, 0xd2, 0xa9, 0x07, 0x33,
+	0x2d, 0x3c, 0x15, 0xc9, 0x87, 0xaa, 0x50, 0xa5,
+	0x03, 0x59, 0x09, 0x1a, 0x65, 0xd7, 0x84, 0xd0,
+	0x82, 0x29, 0x5a, 0x1e, 0x7b, 0xa8, 0x6d, 0x2c
+};
+
+/* combined Xtimes3[Sbox[]] */
+static u8 x3_sbox[256] = {
+	0xa5, 0x84, 0x99, 0x8d, 0x0d, 0xbd, 0xb1, 0x54,
+	0x50, 0x03, 0xa9, 0x7d, 0x19, 0x62, 0xe6, 0x9a,
+	0x45, 0x9d, 0x40, 0x87, 0x15, 0xeb, 0xc9, 0x0b,
+	0xec, 0x67, 0xfd, 0xea, 0xbf, 0xf7, 0x96, 0x5b,
+	0xc2, 0x1c, 0xae, 0x6a, 0x5a, 0x41, 0x02, 0x4f,
+	0x5c, 0xf4, 0x34, 0x08, 0x93, 0x73, 0x53, 0x3f,
+	0x0c, 0x52, 0x65, 0x5e, 0x28, 0xa1, 0x0f, 0xb5,
+	0x09, 0x36, 0x9b, 0x3d, 0x26, 0x69, 0xcd, 0x9f,
+	0x1b, 0x9e, 0x74, 0x2e, 0x2d, 0xb2, 0xee, 0xfb,
+	0xf6, 0x4d, 0x61, 0xce, 0x7b, 0x3e, 0x71, 0x97,
+	0xf5, 0x68, 0x00, 0x2c, 0x60, 0x1f, 0xc8, 0xed,
+	0xbe, 0x46, 0xd9, 0x4b, 0xde, 0xd4, 0xe8, 0x4a,
+	0x6b, 0x2a, 0xe5, 0x16, 0xc5, 0xd7, 0x55, 0x94,
+	0xcf, 0x10, 0x06, 0x81, 0xf0, 0x44, 0xba, 0xe3,
+	0xf3, 0xfe, 0xc0, 0x8a, 0xad, 0xbc, 0x48, 0x04,
+	0xdf, 0xc1, 0x75, 0x63, 0x30, 0x1a, 0x0e, 0x6d,
+	0x4c, 0x14, 0x35, 0x2f, 0xe1, 0xa2, 0xcc, 0x39,
+	0x57, 0xf2, 0x82, 0x47, 0xac, 0xe7, 0x2b, 0x95,
+	0xa0, 0x98, 0xd1, 0x7f, 0x66, 0x7e, 0xab, 0x83,
+	0xca, 0x29, 0xd3, 0x3c, 0x79, 0xe2, 0x1d, 0x76,
+	0x3b, 0x56, 0x4e, 0x1e, 0xdb, 0x0a, 0x6c, 0xe4,
+	0x5d, 0x6e, 0xef, 0xa6, 0xa8, 0xa4, 0x37, 0x8b,
+	0x32, 0x43, 0x59, 0xb7, 0x8c, 0x64, 0xd2, 0xe0,
+	0xb4, 0xfa, 0x07, 0x25, 0xaf, 0x8e, 0xe9, 0x18,
+	0xd5, 0x88, 0x6f, 0x72, 0x24, 0xf1, 0xc7, 0x51,
+	0x23, 0x7c, 0x9c, 0x21, 0xdd, 0xdc, 0x86, 0x85,
+	0x90, 0x42, 0xc4, 0xaa, 0xd8, 0x05, 0x01, 0x12,
+	0xa3, 0x5f, 0xf9, 0xd0, 0x91, 0x58, 0x27, 0xb9,
+	0x38, 0x13, 0xb3, 0x33, 0xbb, 0x70, 0x89, 0xa7,
+	0xb6, 0x22, 0x92, 0x20, 0x49, 0xff, 0x78, 0x7a,
+	0x8f, 0xf8, 0x80, 0x17, 0xda, 0x31, 0xc6, 0xb8,
+	0xc3, 0xb0, 0x77, 0x11, 0xcb, 0xfc, 0xd6, 0x3a
+};
+
+/*
+ * modular multiplication tables based on:
+ *
+ * Xtime2[x] = (x & 0x80 ? 0x1b : 0) ^ (x + x)
+ * Xtime3[x] = x^Xtime2[x];
+ */
+static u8 x_time_9[256] = {
+	0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f,
+	0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
+	0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf,
+	0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7,
+	0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04,
+	0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
+	0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94,
+	0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc,
+	0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49,
+	0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01,
+	0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9,
+	0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91,
+	0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72,
+	0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a,
+	0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2,
+	0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa,
+	0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3,
+	0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b,
+	0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43,
+	0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b,
+	0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8,
+	0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0,
+	0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78,
+	0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30,
+	0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5,
+	0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed,
+	0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35,
+	0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d,
+	0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e,
+	0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6,
+	0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e,
+	0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46
+};
+
+static u8 x_time_b[256] = {
+	0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31,
+	0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69,
+	0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81,
+	0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9,
+	0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a,
+	0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12,
+	0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa,
+	0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2,
+	0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7,
+	0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f,
+	0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77,
+	0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f,
+	0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc,
+	0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4,
+	0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c,
+	0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54,
+	0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6,
+	0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e,
+	0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76,
+	0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e,
+	0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd,
+	0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5,
+	0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d,
+	0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55,
+	0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30,
+	0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68,
+	0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80,
+	0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8,
+	0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b,
+	0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13,
+	0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb,
+	0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3
+};
+
+static u8 x_time_d[256] = {
+	0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23,
+	0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b,
+	0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3,
+	0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b,
+	0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98,
+	0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0,
+	0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48,
+	0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20,
+	0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e,
+	0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26,
+	0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e,
+	0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6,
+	0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5,
+	0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d,
+	0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25,
+	0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d,
+	0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9,
+	0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91,
+	0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29,
+	0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41,
+	0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42,
+	0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a,
+	0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92,
+	0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa,
+	0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94,
+	0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc,
+	0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44,
+	0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c,
+	0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f,
+	0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47,
+	0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff,
+	0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97
+};
+
+static u8 x_time_e[256] = {
+	0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a,
+	0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a,
+	0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca,
+	0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba,
+	0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1,
+	0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81,
+	0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11,
+	0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61,
+	0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87,
+	0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7,
+	0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67,
+	0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17,
+	0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c,
+	0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c,
+	0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc,
+	0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc,
+	0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b,
+	0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b,
+	0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b,
+	0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb,
+	0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0,
+	0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0,
+	0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50,
+	0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20,
+	0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6,
+	0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6,
+	0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26,
+	0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56,
+	0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d,
+	0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d,
+	0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd,
+	0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d
+};
+
+/*
+ * Exchanges columns in each of 4 rows
+ * row0 - unchanged, row1- shifted left 1,
+ * row2 - shifted left 2 and row3 - shifted left 3
+ */
+static void shift_rows(u8 *state)
+{
+	u8 tmp;
+
+	/* just substitute row 0 */
+	state[0] = sbox[state[0]];
+	state[4] = sbox[state[4]];
+	state[8] = sbox[state[8]];
+	state[12] = sbox[state[12]];
+
+	/* rotate row 1 */
+	tmp = sbox[state[1]];
+	state[1] = sbox[state[5]];
+	state[5] = sbox[state[9]];
+	state[9] = sbox[state[13]];
+	state[13] = tmp;
+
+	/* rotate row 2 */
+	tmp = sbox[state[2]];
+	state[2] = sbox[state[10]];
+	state[10] = tmp;
+	tmp = sbox[state[6]];
+	state[6] = sbox[state[14]];
+	state[14] = tmp;
+
+	/* rotate row 3 */
+	tmp = sbox[state[15]];
+	state[15] = sbox[state[11]];
+	state[11] = sbox[state[7]];
+	state[7] = sbox[state[3]];
+	state[3] = tmp;
+}
+
+/*
+ * restores columns in each of 4 rows
+ * row0 - unchanged, row1- shifted right 1,
+ * row2 - shifted right 2 and row3 - shifted right 3
+ */
+static void inv_shift_rows(u8 *state)
+{
+	u8 tmp;
+
+	/* restore row 0 */
+	state[0] = inv_sbox[state[0]];
+	state[4] = inv_sbox[state[4]];
+	state[8] = inv_sbox[state[8]];
+	state[12] = inv_sbox[state[12]];
+
+	/* restore row 1 */
+	tmp = inv_sbox[state[13]];
+	state[13] = inv_sbox[state[9]];
+	state[9] = inv_sbox[state[5]];
+	state[5] = inv_sbox[state[1]];
+	state[1] = tmp;
+
+	/* restore row 2 */
+	tmp = inv_sbox[state[2]];
+	state[2] = inv_sbox[state[10]];
+	state[10] = tmp;
+	tmp = inv_sbox[state[6]];
+	state[6] = inv_sbox[state[14]];
+	state[14] = tmp;
+
+	/* restore row 3 */
+	tmp = inv_sbox[state[3]];
+	state[3] = inv_sbox[state[7]];
+	state[7] = inv_sbox[state[11]];
+	state[11] = inv_sbox[state[15]];
+	state[15] = tmp;
+}
+
+/* recombine and mix each row in a column */
+static void mix_sub_columns(u8 *state)
+{
+	u8 tmp[4 * AES_STATECOLS];
+
+	/* mixing column 0 */
+	tmp[0] = x2_sbox[state[0]] ^ x3_sbox[state[5]] ^
+		 sbox[state[10]] ^ sbox[state[15]];
+	tmp[1] = sbox[state[0]] ^ x2_sbox[state[5]] ^
+		 x3_sbox[state[10]] ^ sbox[state[15]];
+	tmp[2] = sbox[state[0]] ^ sbox[state[5]] ^
+		 x2_sbox[state[10]] ^ x3_sbox[state[15]];
+	tmp[3] = x3_sbox[state[0]] ^ sbox[state[5]] ^
+		 sbox[state[10]] ^ x2_sbox[state[15]];
+
+	/* mixing column 1 */
+	tmp[4] = x2_sbox[state[4]] ^ x3_sbox[state[9]] ^
+		 sbox[state[14]] ^ sbox[state[3]];
+	tmp[5] = sbox[state[4]] ^ x2_sbox[state[9]] ^
+		 x3_sbox[state[14]] ^ sbox[state[3]];
+	tmp[6] = sbox[state[4]] ^ sbox[state[9]] ^
+		 x2_sbox[state[14]] ^ x3_sbox[state[3]];
+	tmp[7] = x3_sbox[state[4]] ^ sbox[state[9]] ^
+		 sbox[state[14]] ^ x2_sbox[state[3]];
+
+	/* mixing column 2 */
+	tmp[8] = x2_sbox[state[8]] ^ x3_sbox[state[13]] ^
+		 sbox[state[2]] ^ sbox[state[7]];
+	tmp[9] = sbox[state[8]] ^ x2_sbox[state[13]] ^
+		 x3_sbox[state[2]] ^       sbox[state[7]];
+	tmp[10] = sbox[state[8]] ^ sbox[state[13]] ^
+		  x2_sbox[state[2]] ^ x3_sbox[state[7]];
+	tmp[11] = x3_sbox[state[8]] ^ sbox[state[13]] ^
+		  sbox[state[2]] ^ x2_sbox[state[7]];
+
+	/* mixing column 3 */
+	tmp[12] = x2_sbox[state[12]] ^ x3_sbox[state[1]] ^
+		  sbox[state[6]] ^ sbox[state[11]];
+	tmp[13] = sbox[state[12]] ^ x2_sbox[state[1]] ^
+		  x3_sbox[state[6]] ^ sbox[state[11]];
+	tmp[14] = sbox[state[12]] ^ sbox[state[1]] ^
+		  x2_sbox[state[6]] ^ x3_sbox[state[11]];
+	tmp[15] = x3_sbox[state[12]] ^ sbox[state[1]] ^
+		  sbox[state[6]] ^ x2_sbox[state[11]];
+
+	memcpy(state, tmp, sizeof(tmp));
+}
+
+/* restore and un-mix each row in a column */
+static void inv_mix_sub_columns(u8 *state)
+{
+	u8 tmp[4 * AES_STATECOLS];
+	int  i;
+
+	/* restore column 0 */
+	tmp[0] = x_time_e[state[0]] ^ x_time_b[state[1]] ^
+		 x_time_d[state[2]] ^ x_time_9[state[3]];
+	tmp[5] = x_time_9[state[0]] ^ x_time_e[state[1]] ^
+		 x_time_b[state[2]] ^ x_time_d[state[3]];
+	tmp[10] = x_time_d[state[0]] ^ x_time_9[state[1]] ^
+		  x_time_e[state[2]] ^ x_time_b[state[3]];
+	tmp[15] = x_time_b[state[0]] ^ x_time_d[state[1]] ^
+		  x_time_9[state[2]] ^ x_time_e[state[3]];
+
+	/* restore column 1 */
+	tmp[4] = x_time_e[state[4]] ^ x_time_b[state[5]] ^
+		 x_time_d[state[6]] ^ x_time_9[state[7]];
+	tmp[9] = x_time_9[state[4]] ^ x_time_e[state[5]] ^
+		 x_time_b[state[6]] ^ x_time_d[state[7]];
+	tmp[14] = x_time_d[state[4]] ^ x_time_9[state[5]] ^
+		  x_time_e[state[6]] ^ x_time_b[state[7]];
+	tmp[3] = x_time_b[state[4]] ^ x_time_d[state[5]] ^
+		 x_time_9[state[6]] ^ x_time_e[state[7]];
+
+	/* restore column 2 */
+	tmp[8] = x_time_e[state[8]] ^ x_time_b[state[9]] ^
+		 x_time_d[state[10]] ^ x_time_9[state[11]];
+	tmp[13] = x_time_9[state[8]] ^ x_time_e[state[9]] ^
+		  x_time_b[state[10]] ^ x_time_d[state[11]];
+	tmp[2] = x_time_d[state[8]] ^ x_time_9[state[9]] ^
+		 x_time_e[state[10]] ^ x_time_b[state[11]];
+	tmp[7] = x_time_b[state[8]] ^ x_time_d[state[9]] ^
+		 x_time_9[state[10]] ^ x_time_e[state[11]];
+
+	/* restore column 3 */
+	tmp[12] = x_time_e[state[12]] ^ x_time_b[state[13]] ^
+		  x_time_d[state[14]] ^ x_time_9[state[15]];
+	tmp[1] = x_time_9[state[12]] ^ x_time_e[state[13]] ^
+		 x_time_b[state[14]] ^ x_time_d[state[15]];
+	tmp[6] = x_time_d[state[12]] ^ x_time_9[state[13]] ^
+		 x_time_e[state[14]] ^ x_time_b[state[15]];
+	tmp[11] = x_time_b[state[12]] ^ x_time_d[state[13]] ^
+		  x_time_9[state[14]] ^ x_time_e[state[15]];
+
+	for (i = 0; i < 4 * AES_STATECOLS; i++)
+		state[i] = inv_sbox[tmp[i]];
+}
+
+/*
+ * encrypt/decrypt columns of the key
+ * n.b. you can replace this with
+ *      byte-wise xor if you wish.
+ */
+static void add_round_key(u32 *state, u32 *key)
+{
+	int idx;
+
+	for (idx = 0; idx < 4; idx++)
+		state[idx] ^= key[idx];
+}
+
+static u8 rcon[11] = {
+	0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36
+};
+
+/* produce AES_STATECOLS bytes for each round */
+void aes_expand_key(u8 *key, u8 *expkey)
+{
+	u8 tmp0, tmp1, tmp2, tmp3, tmp4;
+	u32 idx;
+
+	memcpy(expkey, key, AES_KEYCOLS * 4);
+
+	for (idx = AES_KEYCOLS; idx < AES_STATECOLS * (AES_ROUNDS + 1); idx++) {
+		tmp0 = expkey[4*idx - 4];
+		tmp1 = expkey[4*idx - 3];
+		tmp2 = expkey[4*idx - 2];
+		tmp3 = expkey[4*idx - 1];
+		if (!(idx % AES_KEYCOLS)) {
+			tmp4 = tmp3;
+			tmp3 = sbox[tmp0];
+			tmp0 = sbox[tmp1] ^ rcon[idx / AES_KEYCOLS];
+			tmp1 = sbox[tmp2];
+			tmp2 = sbox[tmp4];
+		} else if ((AES_KEYCOLS > 6) && (idx % AES_KEYCOLS == 4)) {
+			tmp0 = sbox[tmp0];
+			tmp1 = sbox[tmp1];
+			tmp2 = sbox[tmp2];
+			tmp3 = sbox[tmp3];
+		}
+
+		expkey[4*idx+0] = expkey[4*idx - 4*AES_KEYCOLS + 0] ^ tmp0;
+		expkey[4*idx+1] = expkey[4*idx - 4*AES_KEYCOLS + 1] ^ tmp1;
+		expkey[4*idx+2] = expkey[4*idx - 4*AES_KEYCOLS + 2] ^ tmp2;
+		expkey[4*idx+3] = expkey[4*idx - 4*AES_KEYCOLS + 3] ^ tmp3;
+	}
+}
+
+/* encrypt one 128 bit block */
+void aes_encrypt(u8 *in, u8 *expkey, u8 *out)
+{
+	u8 state[AES_STATECOLS * 4];
+	u32 round;
+
+	memcpy(state, in, AES_STATECOLS * 4);
+	add_round_key((u32 *)state, (u32 *)expkey);
+
+	for (round = 1; round < AES_ROUNDS + 1; round++) {
+		if (round < AES_ROUNDS)
+			mix_sub_columns(state);
+		else
+			shift_rows(state);
+
+		add_round_key((u32 *)state,
+			      (u32 *)expkey + round * AES_STATECOLS);
+	}
+
+	memcpy(out, state, sizeof(state));
+}
+
+void aes_decrypt(u8 *in, u8 *expkey, u8 *out)
+{
+	u8 state[AES_STATECOLS * 4];
+	int round;
+
+	memcpy(state, in, sizeof(state));
+
+	add_round_key((u32 *)state,
+		      (u32 *)expkey + AES_ROUNDS * AES_STATECOLS);
+	inv_shift_rows(state);
+
+	for (round = AES_ROUNDS; round--; ) {
+		add_round_key((u32 *)state,
+			      (u32 *)expkey + round * AES_STATECOLS);
+		if (round)
+			inv_mix_sub_columns(state);
+	}
+
+	memcpy(out, state, sizeof(state));
+}
-- 
1.7.3.1

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 02/14] tegra: Move ap20.h header into arch location
  2011-12-26 19:32 [U-Boot] [PATCH 0/14] tegra: warmboot (suspend / resume) support Simon Glass
  2011-12-26 19:32 ` [U-Boot] [PATCH 01/14] Add AES crypto library Simon Glass
@ 2011-12-26 19:32 ` Simon Glass
  2011-12-26 19:32 ` [U-Boot] [PATCH 03/14] tegra: Add crypto library for warmboot code Simon Glass
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 51+ messages in thread
From: Simon Glass @ 2011-12-26 19:32 UTC (permalink / raw)
  To: u-boot

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

Signed-off-by: Simon Glass <sjg@chromium.org>
---
 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%)

diff --git a/arch/arm/cpu/armv7/tegra2/ap20.c b/arch/arm/cpu/armv7/tegra2/ap20.c
index 3ea2e26..da7128c 100644
--- a/arch/arm/cpu/armv7/tegra2/ap20.c
+++ b/arch/arm/cpu/armv7/tegra2/ap20.c
@@ -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>
diff --git a/arch/arm/cpu/armv7/tegra2/board.c b/arch/arm/cpu/armv7/tegra2/board.c
index 2c91e69..c8b903e 100644
--- a/arch/arm/cpu/armv7/tegra2/board.c
+++ b/arch/arm/cpu/armv7/tegra2/board.c
@@ -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;
 
diff --git a/arch/arm/cpu/armv7/tegra2/ap20.h b/arch/arm/include/asm/arch-tegra2/ap20.h
similarity index 100%
rename from arch/arm/cpu/armv7/tegra2/ap20.h
rename to arch/arm/include/asm/arch-tegra2/ap20.h
-- 
1.7.3.1

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 03/14] tegra: Add crypto library for warmboot code
  2011-12-26 19:32 [U-Boot] [PATCH 0/14] tegra: warmboot (suspend / resume) support Simon Glass
  2011-12-26 19:32 ` [U-Boot] [PATCH 01/14] Add AES crypto library Simon Glass
  2011-12-26 19:32 ` [U-Boot] [PATCH 02/14] tegra: Move ap20.h header into arch location Simon Glass
@ 2011-12-26 19:32 ` Simon Glass
  2012-01-08  5:51   ` Mike Frysinger
  2011-12-26 19:32 ` [U-Boot] [PATCH 04/14] tegra: Add flow, gp_padctl, fuse, sdram headers Simon Glass
                   ` (10 subsequent siblings)
  13 siblings, 1 reply; 51+ messages in thread
From: Simon Glass @ 2011-12-26 19:32 UTC (permalink / raw)
  To: u-boot

From: Yen Lin <yelin@nvidia.com>

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

Signed-off-by: Simon Glass <sjg@chromium.org>
---
 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

diff --git a/arch/arm/cpu/armv7/tegra2/crypto.c b/arch/arm/cpu/armv7/tegra2/crypto.c
new file mode 100644
index 0000000..563ce6b
--- /dev/null
+++ b/arch/arm/cpu/armv7/tegra2/crypto.c
@@ -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);
+}
diff --git a/arch/arm/cpu/armv7/tegra2/crypto.h b/arch/arm/cpu/armv7/tegra2/crypto.h
new file mode 100644
index 0000000..aff67e7
--- /dev/null
+++ b/arch/arm/cpu/armv7/tegra2/crypto.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * (C) Copyright 2010 - 2011 NVIDIA Corporation <www.nvidia.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _CRYPTO_H_
+#define _CRYPTO_H_
+
+/**
+ * Sign a block of data
+ *
+ * \param source	Source data
+ * \param length	Size of source data
+ * \param signature	Destination address for signature, AES_KEY_LENGTH bytes
+ */
+int sign_data_block(u8 *source, unsigned length, u8 *signature);
+
+#endif /* #ifndef _CRYPTO_H_ */
-- 
1.7.3.1

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 04/14] tegra: Add flow, gp_padctl, fuse, sdram headers
  2011-12-26 19:32 [U-Boot] [PATCH 0/14] tegra: warmboot (suspend / resume) support Simon Glass
                   ` (2 preceding siblings ...)
  2011-12-26 19:32 ` [U-Boot] [PATCH 03/14] tegra: Add crypto library for warmboot code Simon Glass
@ 2011-12-26 19:32 ` Simon Glass
  2011-12-26 19:32 ` [U-Boot] [PATCH 05/14] tegra: Add tegra_get_chip_type() to detect SKU Simon Glass
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 51+ messages in thread
From: Simon Glass @ 2011-12-26 19:32 UTC (permalink / raw)
  To: u-boot

From: Yen Lin <yelin@nvidia.com>

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

Signed-off-by: Simon Glass <sjg@chromium.org>
---
 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

diff --git a/arch/arm/include/asm/arch-tegra2/flow.h b/arch/arm/include/asm/arch-tegra2/flow.h
new file mode 100644
index 0000000..cce6cbf
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra2/flow.h
@@ -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
diff --git a/arch/arm/include/asm/arch-tegra2/fuse.h b/arch/arm/include/asm/arch-tegra2/fuse.h
new file mode 100644
index 0000000..b7e3808
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra2/fuse.h
@@ -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_ */
diff --git a/arch/arm/include/asm/arch-tegra2/gp_padctrl.h b/arch/arm/include/asm/arch-tegra2/gp_padctrl.h
new file mode 100644
index 0000000..25bb46d
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra2/gp_padctrl.h
@@ -0,0 +1,64 @@
+/*
+ *  (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 _GP_PADCTRL_H_
+#define _GP_PADCTRL_H_
+
+/* APB_MISC_GP and padctrl registers */
+struct apb_misc_gp_ctlr {
+	u32	modereg;	/* 0x00: APB_MISC_GP_MODEREG */
+	u32	hidrev;		/* 0x04: APB_MISC_GP_HIDREV */
+	u32	reserved0[22];	/* 0x08 - 0x5C: */
+	u32	emu_revid;	/* 0x60: APB_MISC_GP_EMU_REVID */
+	u32	xactor_scratch;	/* 0x64: APB_MISC_GP_XACTOR_SCRATCH */
+	u32	aocfg1;		/* 0x68: APB_MISC_GP_AOCFG1PADCTRL */
+	u32	aocfg2;		/* 0x6c: APB_MISC_GP_AOCFG2PADCTRL */
+	u32	atcfg1;		/* 0x70: APB_MISC_GP_ATCFG1PADCTRL */
+	u32	atcfg2;		/* 0x74: APB_MISC_GP_ATCFG2PADCTRL */
+	u32	cdevcfg1;	/* 0x78: APB_MISC_GP_CDEV1CFGPADCTRL */
+	u32	cdevcfg2;	/* 0x7C: APB_MISC_GP_CDEV2CFGPADCTRL */
+	u32	csuscfg;	/* 0x80: APB_MISC_GP_CSUSCFGPADCTRL */
+	u32	dap1cfg;	/* 0x84: APB_MISC_GP_DAP1CFGPADCTRL */
+	u32	dap2cfg;	/* 0x88: APB_MISC_GP_DAP2CFGPADCTRL */
+	u32	dap3cfg;	/* 0x8C: APB_MISC_GP_DAP3CFGPADCTRL */
+	u32	dap4cfg;	/* 0x90: APB_MISC_GP_DAP4CFGPADCTRL */
+	u32	dbgcfg;		/* 0x94: APB_MISC_GP_DBGCFGPADCTRL */
+	u32	lcdcfg1;	/* 0x98: APB_MISC_GP_LCDCFG1PADCTRL */
+	u32	lcdcfg2;	/* 0x9C: APB_MISC_GP_LCDCFG2PADCTRL */
+	u32	sdmmc2_cfg;	/* 0xA0: APB_MISC_GP_SDMMC2CFGPADCTRL */
+	u32	sdmmc3_cfg;	/* 0xA4: APB_MISC_GP_SDMMC3CFGPADCTRL */
+	u32	spicfg;		/* 0xA8: APB_MISC_GP_SPICFGPADCTRL */
+	u32	uaacfg;		/* 0xAC: APB_MISC_GP_UAACFGPADCTRL */
+	u32	uabcfg;		/* 0xB0: APB_MISC_GP_UABCFGPADCTRL */
+	u32	uart2cfg;	/* 0xB4: APB_MISC_GP_UART2CFGPADCTRL */
+	u32	uart3cfg;	/* 0xB8: APB_MISC_GP_UART3CFGPADCTRL */
+	u32	vicfg1;		/* 0xBC: APB_MISC_GP_VICFG1PADCTRL */
+	u32	vicfg2;		/* 0xC0: APB_MISC_GP_VICFG2PADCTRL */
+	u32	xm2cfga;	/* 0xC4: APB_MISC_GP_XM2CFGAPADCTRL */
+	u32	xm2cfgc;	/* 0xC8: APB_MISC_GP_XM2CFGCPADCTRL */
+	u32	xm2cfgd;	/* 0xCC: APB_MISC_GP_XM2CFGDPADCTRL */
+	u32	xm2clkcfg;	/* 0xD0: APB_MISC_GP_XM2CLKCFGPADCTRL */
+	u32	memcomp;	/* 0xD4: APB_MISC_GP_MEMCOMPPADCTRL */
+};
+
+#endif
diff --git a/arch/arm/include/asm/arch-tegra2/sdram_param.h b/arch/arm/include/asm/arch-tegra2/sdram_param.h
new file mode 100644
index 0000000..6c427d0
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra2/sdram_param.h
@@ -0,0 +1,148 @@
+/*
+ *  (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 _SDRAM_PARAM_H_
+#define _SDRAM_PARAM_H_
+
+/*
+ * Defines the number of 32-bit words provided in each set of SDRAM parameters
+ * for arbitration configuration data.
+ */
+#define BCT_SDRAM_ARB_CONFIG_WORDS 27
+
+enum memory_type {
+	MEMORY_TYPE_NONE = 0,
+	MEMORY_TYPE_DDR,
+	MEMORY_TYPE_LPDDR,
+	MEMORY_TYPE_DDR2,
+	MEMORY_TYPE_LPDDR2,
+	MEMORY_TYPE_NUM,
+	MEMORY_TYPE_FORCE32 = 0x7FFFFFFF
+};
+
+/* Defines the SDRAM parameter structure */
+struct sdram_params {
+	enum memory_type memory_type;
+	u32 pllm_charge_pump_setup_control;
+	u32 pllm_loop_filter_setup_control;
+	u32 pllm_input_divider;
+	u32 pllm_feedback_divider;
+	u32 pllm_post_divider;
+	u32 pllm_stable_time;
+	u32 emc_clock_divider;
+	u32 emc_auto_cal_interval;
+	u32 emc_auto_cal_config;
+	u32 emc_auto_cal_wait;
+	u32 emc_pin_program_wait;
+	u32 emc_rc;
+	u32 emc_rfc;
+	u32 emc_ras;
+	u32 emc_rp;
+	u32 emc_r2w;
+	u32 emc_w2r;
+	u32 emc_r2p;
+	u32 emc_w2p;
+	u32 emc_rd_rcd;
+	u32 emc_wr_rcd;
+	u32 emc_rrd;
+	u32 emc_rext;
+	u32 emc_wdv;
+	u32 emc_quse;
+	u32 emc_qrst;
+	u32 emc_qsafe;
+	u32 emc_rdv;
+	u32 emc_refresh;
+	u32 emc_burst_refresh_num;
+	u32 emc_pdex2wr;
+	u32 emc_pdex2rd;
+	u32 emc_pchg2pden;
+	u32 emc_act2pden;
+	u32 emc_ar2pden;
+	u32 emc_rw2pden;
+	u32 emc_txsr;
+	u32 emc_tcke;
+	u32 emc_tfaw;
+	u32 emc_trpab;
+	u32 emc_tclkstable;
+	u32 emc_tclkstop;
+	u32 emc_trefbw;
+	u32 emc_quseextra;
+	u32 emc_fbioc_fg1;
+	u32 emc_fbio_dqsib_dly;
+	u32 emc_fbio_dqsib_dly_msb;
+	u32 emc_fbio_quse_dly;
+	u32 emc_fbio_quse_dly_msb;
+	u32 emc_fbio_cfg5;
+	u32 emc_fbio_cfg6;
+	u32 emc_fbio_spare;
+	u32 emc_mrs;
+	u32 emc_emrs;
+	u32 emc_mrw1;
+	u32 emc_mrw2;
+	u32 emc_mrw3;
+	u32 emc_mrw_reset_command;
+	u32 emc_mrw_reset_init_wait;
+	u32 emc_adr_cfg;
+	u32 emc_adr_cfg1;
+	u32 emc_emem_cfg;
+	u32 emc_low_latency_config;
+	u32 emc_cfg;
+	u32 emc_cfg2;
+	u32 emc_dbg;
+	u32 ahb_arbitration_xbar_ctrl;
+	u32 emc_cfg_dig_dll;
+	u32 emc_dll_xform_dqs;
+	u32 emc_dll_xform_quse;
+	u32 warm_boot_wait;
+	u32 emc_ctt_term_ctrl;
+	u32 emc_odt_write;
+	u32 emc_odt_read;
+	u32 emc_zcal_ref_cnt;
+	u32 emc_zcal_wait_cnt;
+	u32 emc_zcal_mrw_cmd;
+	u32 emc_mrs_reset_dll;
+	u32 emc_mrw_zq_init_dev0;
+	u32 emc_mrw_zq_init_dev1;
+	u32 emc_mrw_zq_init_wait;
+	u32 emc_mrs_reset_dll_wait;
+	u32 emc_emrs_emr2;
+	u32 emc_emrs_emr3;
+	u32 emc_emrs_ddr2_dll_enable;
+	u32 emc_mrs_ddr2_dll_reset;
+	u32 emc_emrs_ddr2_ocd_calib;
+	u32 emc_edr2_wait;
+	u32 emc_cfg_clktrim0;
+	u32 emc_cfg_clktrim1;
+	u32 emc_cfg_clktrim2;
+	u32 pmc_ddr_pwr;
+	u32 apb_misc_gp_xm2cfga_padctrl;
+	u32 apb_misc_gp_xm2cfgc_padctrl;
+	u32 apb_misc_gp_xm2cfgc_padctrl2;
+	u32 apb_misc_gp_xm2cfgd_padctrl;
+	u32 apb_misc_gp_xm2cfgd_padctrl2;
+	u32 apb_misc_gp_xm2clkcfg_padctrl;
+	u32 apb_misc_gp_xm2comp_padctrl;
+	u32 apb_misc_gp_xm2vttgen_padctrl;
+	u32 arbitration_config[BCT_SDRAM_ARB_CONFIG_WORDS];
+};
+#endif
diff --git a/arch/arm/include/asm/arch-tegra2/tegra2.h b/arch/arm/include/asm/arch-tegra2/tegra2.h
index d1a70da..c4cd9bb 100644
--- a/arch/arm/include/asm/arch-tegra2/tegra2.h
+++ b/arch/arm/include/asm/arch-tegra2/tegra2.h
@@ -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
-- 
1.7.3.1

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 05/14] tegra: Add tegra_get_chip_type() to detect SKU
  2011-12-26 19:32 [U-Boot] [PATCH 0/14] tegra: warmboot (suspend / resume) support Simon Glass
                   ` (3 preceding siblings ...)
  2011-12-26 19:32 ` [U-Boot] [PATCH 04/14] tegra: Add flow, gp_padctl, fuse, sdram headers Simon Glass
@ 2011-12-26 19:32 ` Simon Glass
  2012-01-09 23:24   ` Stephen Warren
  2011-12-26 19:32 ` [U-Boot] [PATCH 06/14] tegra: Add EMC support for optimal memory timings Simon Glass
                   ` (8 subsequent siblings)
  13 siblings, 1 reply; 51+ messages in thread
From: Simon Glass @ 2011-12-26 19:32 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
 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(-)

diff --git a/arch/arm/cpu/armv7/tegra2/ap20.c b/arch/arm/cpu/armv7/tegra2/ap20.c
index da7128c..311e93f 100644
--- a/arch/arm/cpu/armv7/tegra2/ap20.c
+++ b/arch/arm/cpu/armv7/tegra2/ap20.c
@@ -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)
 {
diff --git a/arch/arm/include/asm/arch-tegra2/ap20.h b/arch/arm/include/asm/arch-tegra2/ap20.h
index a4b4d73..d222c44 100644
--- a/arch/arm/include/asm/arch-tegra2/ap20.h
+++ b/arch/arm/include/asm/arch-tegra2/ap20.h
@@ -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);
diff --git a/arch/arm/include/asm/arch-tegra2/tegra2.h b/arch/arm/include/asm/arch-tegra2/tegra2.h
index c4cd9bb..f33726d 100644
--- a/arch/arm/include/asm/arch-tegra2/tegra2.h
+++ b/arch/arm/include/asm/arch-tegra2/tegra2.h
@@ -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
-- 
1.7.3.1

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 06/14] tegra: Add EMC support for optimal memory timings
  2011-12-26 19:32 [U-Boot] [PATCH 0/14] tegra: warmboot (suspend / resume) support Simon Glass
                   ` (4 preceding siblings ...)
  2011-12-26 19:32 ` [U-Boot] [PATCH 05/14] tegra: Add tegra_get_chip_type() to detect SKU Simon Glass
@ 2011-12-26 19:32 ` Simon Glass
  2012-01-09 23:38   ` Stephen Warren
  2011-12-26 19:33 ` [U-Boot] [PATCH 07/14] tegra: Add PMU to manage power supplies Simon Glass
                   ` (7 subsequent siblings)
  13 siblings, 1 reply; 51+ messages in thread
From: Simon Glass @ 2011-12-26 19:32 UTC (permalink / raw)
  To: u-boot

From: Jimmy Zhang <jimmzhang@nvidia.com>

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

Signed-off-by: Simon Glass <sjg@chromium.org>
---
 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

diff --git a/arch/arm/cpu/armv7/tegra2/Makefile b/arch/arm/cpu/armv7/tegra2/Makefile
index e9ac6c9..dcd6329 100644
--- a/arch/arm/cpu/armv7/tegra2/Makefile
+++ b/arch/arm/cpu/armv7/tegra2/Makefile
@@ -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)
diff --git a/arch/arm/cpu/armv7/tegra2/emc.c b/arch/arm/cpu/armv7/tegra2/emc.c
new file mode 100644
index 0000000..563fe89
--- /dev/null
+++ b/arch/arm/cpu/armv7/tegra2/emc.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/ap20.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/emc.h>
+#include <asm/arch/tegra2.h>
+
+static const struct tegra_emc_table *tegra_emc_table;
+static int tegra_emc_table_size;
+
+static inline void emc_writel(u32 val, unsigned long addr)
+{
+	writel(val, TEGRA2_EMC_BASE + addr);
+}
+
+static inline u32 emc_readl(unsigned long addr)
+{
+	return readl(TEGRA2_EMC_BASE + addr);
+}
+
+/*
+ * This table defines the ordering of the registers provided to
+ * tegra_set_mmc()
+ * TODO: Convert to fdt version once available
+ */
+static const unsigned long emc_reg_addr[TEGRA_EMC_NUM_REGS] = {
+	0x2c,	/* RC */
+	0x30,	/* RFC */
+	0x34,	/* RAS */
+	0x38,	/* RP */
+	0x3c,	/* R2W */
+	0x40,	/* W2R */
+	0x44,	/* R2P */
+	0x48,	/* W2P */
+	0x4c,	/* RD_RCD */
+	0x50,	/* WR_RCD */
+	0x54,	/* RRD */
+	0x58,	/* REXT */
+	0x5c,	/* WDV */
+	0x60,	/* QUSE */
+	0x64,	/* QRST */
+	0x68,	/* QSAFE */
+	0x6c,	/* RDV */
+	0x70,	/* REFRESH */
+	0x74,	/* BURST_REFRESH_NUM */
+	0x78,	/* PDEX2WR */
+	0x7c,	/* PDEX2RD */
+	0x80,	/* PCHG2PDEN */
+	0x84,	/* ACT2PDEN */
+	0x88,	/* AR2PDEN */
+	0x8c,	/* RW2PDEN */
+	0x90,	/* TXSR */
+	0x94,	/* TCKE */
+	0x98,	/* TFAW */
+	0x9c,	/* TRPAB */
+	0xa0,	/* TCLKSTABLE */
+	0xa4,	/* TCLKSTOP */
+	0xa8,	/* TREFBW */
+	0xac,	/* QUSE_EXTRA */
+	0x114,	/* FBIO_CFG6 */
+	0xb0,	/* ODT_WRITE */
+	0xb4,	/* ODT_READ */
+	0x104,	/* FBIO_CFG5 */
+	0x2bc,	/* CFG_DIG_DLL */
+	0x2c0,	/* DLL_XFORM_DQS */
+	0x2c4,	/* DLL_XFORM_QUSE */
+	0x2e0,	/* ZCAL_REF_CNT */
+	0x2e4,	/* ZCAL_WAIT_CNT */
+	0x2a8,	/* AUTO_CAL_INTERVAL */
+	0x2d0,	/* CFG_CLKTRIM_0 */
+	0x2d4,	/* CFG_CLKTRIM_1 */
+	0x2d8,	/* CFG_CLKTRIM_2 */
+};
+
+/* 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)
+
+static int tegra_emc_set_rate(unsigned long rate)
+{
+	int i;
+	int j;
+
+	if (!tegra_emc_table)
+		return -1;
+
+	/* The EMC clock rate is twice the bus rate, and the bus rate is
+	 * measured in kHz */
+	rate = rate / 2 / 1000;
+
+	for (i = 0; i < tegra_emc_table_size; i++)
+		if (tegra_emc_table[i].rate == rate)
+			break;
+
+	if (i >= tegra_emc_table_size)
+		return -1;
+
+	for (j = 0; j < TEGRA_EMC_NUM_REGS; j++)
+		emc_writel(tegra_emc_table[i].regs[j], emc_reg_addr[j]);
+
+	/*
+	 * trigger emc with new settings by updating clk_rst's source EMC
+	 * Set PLLM_OUT0 (bits: 31:30= 0) and divisor bits 7:0 = 0 (ie 1)
+	 */
+	clock_ll_set_source_divisor(PERIPH_ID_EMC, 0, 0);
+	udelay(1);
+	return 0;
+}
+
+int tegra_set_emc(const struct tegra_emc_table *table, int table_size)
+{
+	unsigned long rate;
+
+	if (!table) {
+		tegra_emc_table = NULL;
+		tegra_emc_table_size = 0;
+		return -1;
+	}
+
+	tegra_emc_table = table;
+	tegra_emc_table_size = table_size;
+
+	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;
+	}
+
+	tegra_emc_set_rate(rate);
+
+	return 0;
+}
diff --git a/arch/arm/include/asm/arch-tegra2/emc.h b/arch/arm/include/asm/arch-tegra2/emc.h
new file mode 100644
index 0000000..a1d1e9d
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra2/emc.h
@@ -0,0 +1,107 @@
+/*
+ * 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 _ARCH_EMC_H_
+#define _ARCH_EMC_H_
+
+#include <asm/types.h>
+
+#define TEGRA_EMC_NUM_REGS	46
+
+struct tegra_emc_table {
+	unsigned long rate;
+	u32 regs[TEGRA_EMC_NUM_REGS];
+};
+
+/* EMC Registers */
+struct emc_ctlr {
+	u32 cfg;		/* 0x00: EMC_CFG */
+	u32 reserved0[3];	/* 0x04 ~ 0x0C */
+	u32 adr_cfg;		/* 0x10: EMC_ADR_CFG */
+	u32 adr_cfg1;		/* 0x14: EMC_ADR_CFG_1 */
+	u32 reserved1[2];	/* 0x18 ~ 0x18 */
+	u32 refresh_ctrl;	/* 0x20: EMC_REFCTRL */
+	u32 pin;		/* 0x24: EMC_PIN */
+	u32 timing_ctrl;	/* 0x28: EMC_TIMING_CONTROL */
+	u32 rc;			/* 0x2C: EMC_RC */
+	u32 rfc;		/* 0x30: EMC_RFC */
+	u32 ras;		/* 0x34: EMC_RAS */
+	u32 rp;			/* 0x38: EMC_RP */
+	u32 r2w;		/* 0x3C: EMC_R2W */
+	u32 w2r;		/* 0x40: EMC_W2R */
+	u32 r2p;		/* 0x44: EMC_R2P */
+	u32 w2p;		/* 0x48: EMC_W2P */
+	u32 rd_rcd;		/* 0x4C: EMC_RD_RCD */
+	u32 wd_rcd;		/* 0x50: EMC_WD_RCD */
+	u32 rrd;		/* 0x54: EMC_RRD */
+	u32 rext;		/* 0x58: EMC_REXT */
+	u32 wdv;		/* 0x5C: EMC_WDV */
+	u32 quse;		/* 0x60: EMC_QUSE */
+	u32 qrst;		/* 0x64: EMC_QRST */
+	u32 qsafe;		/* 0x68: EMC_QSAFE */
+	u32 rdv;		/* 0x6C: EMC_RDV */
+	u32 refresh;		/* 0x70: EMC_REFRESH */
+	u32 burst_refresh_num;	/* 0x74: EMC_BURST_REFRESH_NUM */
+	u32 pdex2wr;		/* 0x78: EMC_PDEX2WR */
+	u32 pdex2rd;		/* 0x7c: EMC_PDEX2RD */
+	u32 pchg2pden;		/* 0x80: EMC_PCHG2PDEN */
+	u32 act2pden;		/* 0x84: EMC_ACT2PDEN */
+	u32 ar2pden;		/* 0x88: EMC_AR2PDEN */
+	u32 rw2pden;		/* 0x8C: EMC_RW2PDEN */
+	u32 txsr;		/* 0x90: EMC_TXSR */
+	u32 tcke;		/* 0x94: EMC_TCKE */
+	u32 tfaw;		/* 0x98: EMC_TFAW */
+	u32 trpab;		/* 0x9C: EMC_TRPAB */
+	u32 tclkstable;		/* 0xA0: EMC_TCLKSTABLE */
+	u32 tclkstop;		/* 0xA4: EMC_TCLKSTOP */
+	u32 trefbw;		/* 0xA8: EMC_TREFBW */
+	u32 quse_extra;		/* 0xAC: EMC_QUSE_EXTRA */
+	u32 odt_write;		/* 0xB0: EMC_ODT_WRITE */
+	u32 odt_read;		/* 0xB4: EMC_ODT_READ */
+	u32 reserved2[5];	/* 0xB8 ~ 0xC8 */
+	u32 mrs;		/* 0xCC: EMC_MRS */
+	u32 emrs;		/* 0xD0: EMC_EMRS */
+	u32 ref;		/* 0xD4: EMC_REF */
+	u32 pre;		/* 0xD8: EMC_PRE */
+	u32 nop;		/* 0xDC: EMC_NOP */
+	u32 self_ref;		/* 0xE0: EMC_SELF_REF */
+	u32 dpd;		/* 0xE4: EMC_DPD */
+	u32 mrw;		/* 0xE8: EMC_MRW */
+	u32 mrr;		/* 0xEC: EMC_MRR */
+	u32 reserved3;		/* 0xF0: */
+	u32 fbio_cfg1;		/* 0xF4: EMC_FBIO_CFG1 */
+	u32 fbio_dqsib_dly;	/* 0xF8: EMC_FBIO_DQSIB_DLY */
+	u32 fbio_dqsib_dly_msb;	/* 0xFC: EMC_FBIO_DQSIB_DLY_MSG */
+	u32 fbio_spare;		/* 0x100: SBIO_SPARE */
+				/* There are more registers ... */
+};
+
+/**
+ * Set up the memory timings according to a provided table
+ *
+ * @param table		Memory timing table
+ * @param table_size	Number of entries in table
+ */
+int tegra_set_emc(const struct tegra_emc_table *table, int table_size);
+
+#endif
diff --git a/arch/arm/include/asm/arch-tegra2/tegra2.h b/arch/arm/include/asm/arch-tegra2/tegra2.h
index f33726d..480ec0c 100644
--- a/arch/arm/include/asm/arch-tegra2/tegra2.h
+++ b/arch/arm/include/asm/arch-tegra2/tegra2.h
@@ -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
-- 
1.7.3.1

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 07/14] tegra: Add PMU to manage power supplies
  2011-12-26 19:32 [U-Boot] [PATCH 0/14] tegra: warmboot (suspend / resume) support Simon Glass
                   ` (5 preceding siblings ...)
  2011-12-26 19:32 ` [U-Boot] [PATCH 06/14] tegra: Add EMC support for optimal memory timings Simon Glass
@ 2011-12-26 19:33 ` Simon Glass
  2012-01-10 17:56   ` Stephen Warren
  2011-12-26 19:33 ` [U-Boot] [PATCH 08/14] tegra: Set up PMU for Nvidia boards Simon Glass
                   ` (6 subsequent siblings)
  13 siblings, 1 reply; 51+ messages in thread
From: Simon Glass @ 2011-12-26 19:33 UTC (permalink / raw)
  To: u-boot

From: Jimmy Zhang <jimmzhang@nvidia.com>

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.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
 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

diff --git a/arch/arm/cpu/armv7/tegra2/Makefile b/arch/arm/cpu/armv7/tegra2/Makefile
index dcd6329..dba684d 100644
--- a/arch/arm/cpu/armv7/tegra2/Makefile
+++ b/arch/arm/cpu/armv7/tegra2/Makefile
@@ -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)
diff --git a/arch/arm/cpu/armv7/tegra2/pmu.c b/arch/arm/cpu/armv7/tegra2/pmu.c
new file mode 100644
index 0000000..4bc87ae
--- /dev/null
+++ b/arch/arm/cpu/armv7/tegra2/pmu.c
@@ -0,0 +1,355 @@
+/*
+ * 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/io.h>
+#include <asm/arch/ap20.h>
+#include <asm/arch/pmu.h>
+#include <asm/arch/tegra2.h>
+#include <asm/arch/sys_proto.h>
+#include <i2c.h>
+
+/*
+ * abs() handles unsigned ints, shorts and chars and returns a signed long.
+ * TODO: Move this into common?
+ */
+#define abs(x) ({						\
+		long ret;					\
+		{						\
+			typeof((x)) __x = (x);			\
+			ret = (__x < 0) ? -__x : __x;		\
+		}						\
+		ret;						\
+	})
+
+/* Amount to step voltage by (either positive or negative) */
+#define stp(x, y) ((x < y) ? VDD_TRANSITION_STEP : -VDD_TRANSITION_STEP)
+
+#define MAX_I2C_RETRY	3
+int pmu_read(int reg)
+{
+	int	i;
+	uchar	data;
+	int	retval = -1;
+	int	old_bus_num;
+
+	old_bus_num = i2c_get_bus_num();
+	i2c_set_bus_num(DVC_I2C_BUS_NUMBER);
+
+	for (i = 0; i < MAX_I2C_RETRY; ++i) {
+		if (!i2c_read(PMU_I2C_ADDRESS, reg, 1, &data, 1)) {
+			retval = (int)data;
+			goto exit;
+		}
+
+		/* i2c access failed, retry */
+		udelay(100);
+	}
+
+exit:
+	i2c_set_bus_num(old_bus_num);
+	return retval;
+}
+
+int pmu_write(int reg, uchar *data, uint len)
+{
+	int	i;
+	int	retval = -1;
+	int	old_bus_num;
+
+	old_bus_num = i2c_get_bus_num();
+	i2c_set_bus_num(DVC_I2C_BUS_NUMBER);
+
+	for (i = 0; i < MAX_I2C_RETRY; ++i) {
+		if (!i2c_write(PMU_I2C_ADDRESS, reg, 1, data, len)) {
+			retval = 0;
+			goto exit;
+		}
+
+		/* i2c access failed, retry */
+		udelay(100);
+	}
+
+exit:
+	i2c_set_bus_num(old_bus_num);
+	return retval;
+}
+
+#ifdef CONFIG_TEGRA_CLOCK_SCALING
+struct vdd_settings {
+	int	data;
+	int	nominal;
+};
+
+enum vdd_type {
+	core = 0,
+	cpu = 1,
+};
+
+static struct vdd_settings vdd_current[] = {
+	/* vdd core */
+	{.data		= 0,
+	 .nominal	= 0,
+	},
+
+	/* vdd cpu */
+	{.data		= 0,
+	 .nominal	= 0,
+	},
+};
+
+static int vdd_init_nominal_table(void)
+{
+	/* by default, the table has been filled with T25 settings */
+	switch (tegra_get_chip_type()) {
+	case TEGRA_SOC_T20:
+		vdd_current[core].nominal = VDD_CORE_NOMINAL_T20;
+		vdd_current[cpu].nominal = VDD_CPU_NOMINAL_T20;
+		break;
+	case TEGRA_SOC_T25:
+		vdd_current[core].nominal = VDD_CORE_NOMINAL_T25;
+		vdd_current[cpu].nominal = VDD_CPU_NOMINAL_T25;
+		break;
+	default:
+		/* unknown chip type */
+		return -1;
+	}
+	return 0;
+}
+
+/* get current vdd_core and vdd_cpu */
+static int tegra2_get_voltage(void)
+{
+	int	reg;
+	int	data1, data2;
+
+	/*
+	 * Each vdd has two supply sources, ie, v1 and v2.
+	 * The supply control reg1 and reg2 determine the current selection.
+	 */
+	/* get supply control reg1 and reg2 */
+	data1 = pmu_read(PMU_SUPPLY_CONTROL_REG1);
+	if (data1 == -1)
+		return -1;
+
+	data2 = pmu_read(PMU_SUPPLY_CONTROL_REG2);
+	if (data2 == -1)
+		return -1;
+
+	reg = PMU_CORE_VOLTAGE_REG;	/* set default to v1 */
+	if ((data1 | data2) & VDD_CORE_SUPPLY2_SEL)
+		reg++;	/* v2 is selected*/
+
+	/* get vdd_core */
+	vdd_current[core].data = pmu_read(reg);
+	if (vdd_current[core].data == -1)
+		return -1;
+
+	reg = PMU_CPU_VOLTAGE_REG;	/* set default to v1 */
+	if ((data1 | data2) & VDD_CPU_SUPPLY2_SEL)
+		reg++;	/* v2 is selected*/
+
+	/* get vdd_cpu */
+	vdd_current[cpu].data = pmu_read(reg);
+	if (vdd_current[cpu].data == -1)
+		return -1;
+
+	return 0;
+}
+
+static int tegra2_set_voltage(int reg, int data, int control)
+{
+	uchar	data_buffer[3];
+	uchar	control_bit = (uchar)control;
+
+	/*
+	 * only one supply is needed in u-boot. set both v1 and v2 to
+	 * same value.
+	 *
+	 * when both v1 and v2 are set to same value, we just need to set
+	 * control1 reg to trigger the supply selection.
+	 */
+	data_buffer[0] = data_buffer[1] = (uchar)data;
+	data_buffer[2] = VDD_TRANSITION_RATE;
+
+	if (!pmu_write(reg, data_buffer, 3) &&		/* v1, v2 and rate */
+	    !pmu_write(PMU_SUPPLY_CONTROL_REG1, &control_bit, 1)) /* trigger */
+		return 0;
+	return -1;
+}
+
+int pmu_is_voltage_nominal(void)
+{
+	if ((vdd_current[core].data == vdd_current[core].nominal) &&
+	    (vdd_current[cpu].data == vdd_current[cpu].nominal))
+		return 1;
+	return 0;
+}
+
+static void calculate_next_voltage(int *data, int nominal, int step)
+{
+	if (abs(nominal - *data) > VDD_TRANSITION_STEP)
+		*data += step;
+	else
+		*data = nominal;
+}
+
+/*
+ * It is required by tegra2 soc that vdd_core must be higher than vdd_cpu
+ * with certain range at all time. If current settings doesn't meet this
+ * condition, pmu_adjust_voltage just simply returns without setting any
+ * voltage.
+ */
+static int pmu_adjust_voltage(void)
+{
+	int step_core, step_cpu;
+	int adjust_vdd_core_late;
+
+	/*
+	 * if vdd_core < vdd_cpu + rel
+	 *    skip
+	 *
+	 * This condition may happen when system reboots due to kernel crash.
+	 */
+	if (vdd_current[core].data < (vdd_current[cpu].data + VDD_RELATION))
+		return -1;
+
+	/*
+	 * Since vdd_core and vdd_cpu may both stand at either greater or less
+	 * than their nominal voltage, the adjustment may go either directions.
+	 *
+	 * Make sure vdd_core is always higher than vdd_cpu with certain margin.
+	 * So, find out which vdd to adjust first in each step.
+	 *
+	 * case 1: both vdd_core and vdd_cpu need to move up
+	 *              adjust vdd_core before vdd_cpu
+	 *
+	 * case 2: both vdd_core and vdd_cpu need to move down
+	 *              adjust vdd_cpu before vdd_core
+	 *
+	 * case 3: vdd_core moves down and vdd_cpu moves up
+	 *              adjusting either one first is fine.
+	 */
+	step_core = stp(vdd_current[core].data, vdd_current[core].nominal);
+	step_cpu = stp(vdd_current[cpu].data, vdd_current[cpu].nominal);
+
+	/*
+	 * Adjust vdd_core and vdd_cpu one step@a time until they reach
+	 * their nominal values.
+	 */
+	while ((vdd_current[core].data != vdd_current[core].nominal) ||
+	       (vdd_current[cpu].data != vdd_current[cpu].nominal)) {
+
+		adjust_vdd_core_late = 0;
+
+		/* if vdd_core hasn't reached its nominal value? */
+		if (vdd_current[core].data != vdd_current[core].nominal) {
+
+			calculate_next_voltage(&vdd_current[core].data,
+					       vdd_current[core].nominal,
+					       step_core);
+
+			/*
+			 * if case 1 and case 3, set new vdd_core first.
+			 * otherwise, hold down until new vdd_cpu is set.
+			 */
+			if (step_cpu > 0) {
+				/* adjust vdd_core first */
+				if (tegra2_set_voltage(PMU_CORE_VOLTAGE_REG,
+						vdd_current[core].data,
+						VDD_CORE_SUPPLY_CONTROL))
+					return -1;
+			} else
+				/* set flag to adjust vdd_core later */
+				adjust_vdd_core_late = 1;
+		}
+
+		/* if vdd_cpu hasn't reached its nominal value? */
+		if (vdd_current[cpu].data != vdd_current[cpu].nominal) {
+
+			calculate_next_voltage(&vdd_current[cpu].data,
+					       vdd_current[cpu].nominal,
+					       step_cpu);
+
+			/* adjust vdd_cpu */
+			if (tegra2_set_voltage(PMU_CPU_VOLTAGE_REG,
+					       vdd_current[cpu].data,
+					       VDD_CPU_SUPPLY_CONTROL))
+				return -1;
+		}
+
+		/*
+		 * if vdd_core late flag is set
+		 */
+		if (adjust_vdd_core_late) {
+			/* adjust vdd_core */
+			if (tegra2_set_voltage(PMU_CORE_VOLTAGE_REG,
+					       vdd_current[core].data,
+					       VDD_CORE_SUPPLY_CONTROL))
+				return -1;
+		}
+	}
+	return 0;
+}
+
+static int pmu_set_pwm_mode(int smx)
+{
+	int ret = 0;
+	uchar val = 0;
+
+	ret = pmu_read(PMU_PWM_PFM_MODE_REG);
+	if (ret == -1)
+		return ret;
+
+	val = (uchar)ret;
+	val |= (1 << smx);
+
+	ret = pmu_write(PMU_PWM_PFM_MODE_REG, &val, 1);
+	if (ret == -1)
+		return ret;
+
+	return 0;
+}
+
+int pmu_set_nominal(void)
+{
+	/* fill in nominal values based on chip type */
+	if (vdd_init_nominal_table())
+		return -1;
+
+	/* Set SM1 in PWM-only mode */
+	if (pmu_set_pwm_mode(SM1_PWM_BIT))
+		return -1;
+
+	/* get current voltage settings */
+	if (tegra2_get_voltage())
+		return -1;
+
+	/* if current voltage is already set to nominal, skip */
+	if (pmu_is_voltage_nominal())
+		return 0;
+
+	/* adjust vdd_core and/or vdd_cpu */
+	return pmu_adjust_voltage();
+}
+#endif /* CONFIG_TEGRA_CLOCK_SCALING */
diff --git a/arch/arm/include/asm/arch-tegra2/pmu.h b/arch/arm/include/asm/arch-tegra2/pmu.h
new file mode 100644
index 0000000..303dda7
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra2/pmu.h
@@ -0,0 +1,63 @@
+/*
+ *  (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 _ARCH_PMU_H_
+#define _ARCH_PMU_H_
+
+#define DVC_I2C_BUS_NUMBER	0
+#define PMU_I2C_ADDRESS		0x34
+
+#define PMU_CORE_VOLTAGE_REG	0x26
+#define PMU_CPU_VOLTAGE_REG	0x23
+#define PMU_SUPPLY_CONTROL_REG1	0x20
+#define PMU_SUPPLY_CONTROL_REG2	0x21
+#define VDD_CPU_SUPPLY_CONTROL	0x01
+#define VDD_CPU_SUPPLY2_SEL	0x02
+#define VDD_CORE_SUPPLY_CONTROL	0x04
+#define VDD_CORE_SUPPLY2_SEL	0x08
+
+#define VDD_CORE_NOMINAL_T25	0x17	/* 1.3v */
+#define VDD_CPU_NOMINAL_T25	0x10	/* 1.125v */
+
+#define VDD_CORE_NOMINAL_T20	0x16	/* 1.275v */
+#define VDD_CPU_NOMINAL_T20	0x0f	/* 1.1v */
+
+#define VDD_RELATION		0x02	/*  50mv */
+#define VDD_TRANSITION_STEP	0x06	/* 150mv */
+#define VDD_TRANSITION_RATE	0x06	/* 3.52mv/us */
+
+/*
+ * SMn PWM/PFM Mode Selection
+ */
+#define PMU_PWM_PFM_MODE_REG	0x47
+#define SM0_PWM_BIT		0
+#define SM1_PWM_BIT		1
+#define SM2_PWM_BIT		2
+
+int pmu_read(int reg);
+int pmu_write(int reg, uchar *data, uint len);
+
+int pmu_set_nominal(void);
+int pmu_is_voltage_nominal(void);
+
+#endif	/* _ARCH_PMU_H_ */
-- 
1.7.3.1

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 08/14] tegra: Set up PMU for Nvidia boards
  2011-12-26 19:32 [U-Boot] [PATCH 0/14] tegra: warmboot (suspend / resume) support Simon Glass
                   ` (6 preceding siblings ...)
  2011-12-26 19:33 ` [U-Boot] [PATCH 07/14] tegra: Add PMU to manage power supplies Simon Glass
@ 2011-12-26 19:33 ` Simon Glass
  2012-01-10 18:02   ` Stephen Warren
  2011-12-26 19:33 ` [U-Boot] [PATCH 09/14] tegra: Add warmboot implementation Simon Glass
                   ` (5 subsequent siblings)
  13 siblings, 1 reply; 51+ messages in thread
From: Simon Glass @ 2011-12-26 19:33 UTC (permalink / raw)
  To: u-boot

Adjust PMU to permit maximum frequency operation.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
 board/nvidia/common/board.c |   10 ++++++++++
 1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c
index 63edfdb..10c0a67 100644
--- a/board/nvidia/common/board.c
+++ b/board/nvidia/common/board.c
@@ -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;
 }
 
-- 
1.7.3.1

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 09/14] tegra: Add warmboot implementation
  2011-12-26 19:32 [U-Boot] [PATCH 0/14] tegra: warmboot (suspend / resume) support Simon Glass
                   ` (7 preceding siblings ...)
  2011-12-26 19:33 ` [U-Boot] [PATCH 08/14] tegra: Set up PMU for Nvidia boards Simon Glass
@ 2011-12-26 19:33 ` Simon Glass
  2012-01-10 18:30   ` Stephen Warren
  2011-12-26 19:33 ` [U-Boot] [PATCH 10/14] tegra: Setup PMC scratch info from ap20 setup Simon Glass
                   ` (4 subsequent siblings)
  13 siblings, 1 reply; 51+ messages in thread
From: Simon Glass @ 2011-12-26 19:33 UTC (permalink / raw)
  To: u-boot

From: Yen Lin <yelin@nvidia.com>

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

Signed-off-by: Simon Glass <sjg@chromium.org>
---
 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

diff --git a/arch/arm/cpu/armv7/tegra2/Makefile b/arch/arm/cpu/armv7/tegra2/Makefile
index dba684d..a70659e 100644
--- a/arch/arm/cpu/armv7/tegra2/Makefile
+++ b/arch/arm/cpu/armv7/tegra2/Makefile
@@ -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))
diff --git a/arch/arm/cpu/armv7/tegra2/warmboot.c b/arch/arm/cpu/armv7/tegra2/warmboot.c
new file mode 100644
index 0000000..ae86620
--- /dev/null
+++ b/arch/arm/cpu/armv7/tegra2/warmboot.c
@@ -0,0 +1,444 @@
+/*
+ * (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/io.h>
+#include <asm/errno.h>
+#include <asm/arch/ap20.h>
+#include <asm/arch/clk_rst.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/pmc.h>
+#include <asm/arch/pinmux.h>
+#include <asm/arch/tegra2.h>
+#include <asm/arch/fuse.h>
+#include <asm/arch/emc.h>
+#include <asm/arch/gp_padctrl.h>
+#include <asm/arch/warmboot.h>
+#include <asm/arch/sdram_param.h>
+
+#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)
+
+union osc_ctrl_reg {
+	struct {
+		u32 xoe:1;
+		u32 xobp:1;
+		u32 reserved0:2;
+		u32 xofs:6;
+		u32 reserved1:2;
+		u32 xods:5;
+		u32 reserved2:3;
+		u32 oscfi_spare:8;
+		u32 pll_ref_div:2;
+		u32 osc_freq:2;
+	};
+	u32 word;
+};
+
+union pll_base_reg {
+	struct {
+		u32 pll_divm:5;
+		u32 reserved0:3;
+		u32 pll_divn:10;
+		u32 reserved1:2;
+		u32 pll_divp:3;
+		u32 reserved2:4;
+		u32 pll_lock:1;
+		u32 reserved3:1;
+		u32 pll_ref_dis:1;
+		u32 pll_enable:1;
+		u32 pll_bypass:1;
+	};
+	u32 word;
+};
+
+union pll_misc_reg {
+	struct {
+		u32 pll_vcocon:4;
+		u32 pll_lfcon:4;
+		u32 pll_cpcon:4;
+		u32 pll_lock_sel:6;
+		u32 reserved0:1;
+		u32 pll_lock_enable:1;
+		u32 reserved1:1;
+		u32 pll_dccon:1;
+		u32 pll_pts:2;
+		u32 reserved2:6;
+		u32 pll_out1_div_byp:1;
+		u32 pll_out1_inv_clk:1;
+	};
+	u32 word;
+};
+
+union xm2cfga_reg {
+	struct {
+		u32 reserved0:2;
+		u32 hsm_en:1;
+		u32 reserved1:2;
+		u32 preemp_en:1;
+		u32 vref_en:1;
+		u32 reserved2:5;
+		u32 cal_drvdn:5;
+		u32 reserved3:3;
+		u32 cal_drvup:5;
+		u32 reserved4:3;
+		u32 cal_drvdn_slwr:2;
+		u32 cal_drvup_slwf:2;
+	};
+	u32 word;
+};
+
+union xm2cfgd_reg {
+	struct {
+		u32 reserved0:2;
+		u32 hsm_en:1;
+		u32 schmt_en:1;
+		u32 lpmd:2;
+		u32 vref_en:1;
+		u32 reserved1:5;
+		u32 cal_drvdn:5;
+		u32 reserved2:3;
+		u32 cal_drvup:5;
+		u32 reserved3:3;
+		u32 cal_drvdn_slwr:2;
+		u32 cal_drvup_slwf:2;
+	};
+	u32 word;
+};
+
+union fbio_spare_reg {
+	struct {
+		u32 reserved:24;
+		u32 cfg_wb0:8;
+	};
+	u32 word;
+};
+
+union scratch2_reg {
+	struct {
+		u32 pllm_base_divm:5;
+		u32 pllm_base_divn:10;
+		u32 pllm_base_divp:3;
+		u32 pllm_misc_lfcon:4;
+		u32 pllm_misc_cpcon:4;
+		u32 gp_xm2cfga_padctrl_preemp:1;
+		u32 gp_xm2cfgd_padctrl_schmt:1;
+		u32 osc_ctrl_xobp:1;
+		u32 memory_type:3;
+	};
+	u32 word;
+};
+
+union scratch4_reg {
+	struct {
+		u32 emc_clock_divider:8;
+		u32 pllm_stable_time:8;
+		u32 pllx_stable_time:8;
+		u32 emc_fbio_spare_cfg_wb0:8;
+	};
+	u32 word;
+};
+
+union scratch24_reg {
+	struct {
+		u32 emc_auto_cal_wait:8;
+		u32 emc_pin_program_wait:8;
+		u32 warmboot_wait:8;
+		u32 reserved:8;
+	};
+	u32 word;
+};
+
+void warmboot_save_sdram_params(void)
+{
+	u32 ram_code;
+	struct sdram_params sdram;
+	struct pmux_tri_ctlr *pmt = (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+	struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+	struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
+	struct apb_misc_gp_ctlr *gp =
+			(struct apb_misc_gp_ctlr *)TEGRA2_APB_MISC_GP_BASE;
+	struct emc_ctlr *emc = (struct emc_ctlr *)TEGRA2_EMC_BASE;
+	union osc_ctrl_reg osc_ctrl;
+	union pll_base_reg pllm_base;
+	union pll_misc_reg pllm_misc;
+	union scratch2_reg scratch2;
+	union scratch4_reg scratch4;
+	union scratch24_reg scratch24;
+	union xm2cfga_reg xm2cfga;
+	union xm2cfgd_reg xm2cfgd;
+	union fbio_spare_reg fbio_spare;
+
+	/* get ram code that is used as index to array sdram_params in BCT */
+	ram_code = (readl(&pmt->pmt_strap_opt_a) >>
+			STRAP_OPT_A_RAM_CODE_SHIFT) & 3;
+	memcpy(&sdram,
+	       (char *)((struct sdram_params *)SDRAM_PARAMS_BASE + ram_code),
+	       sizeof(sdram));
+
+	osc_ctrl.word = readl(&clkrst->crc_osc_ctrl);
+	pllm_base.word = readl(&clkrst->crc_pll[CLOCK_ID_MEMORY].pll_base);
+	pllm_misc.word = readl(&clkrst->crc_pll[CLOCK_ID_MEMORY].pll_misc);
+	xm2cfga.word = readl(&gp->xm2cfga);
+	xm2cfgd.word = readl(&gp->xm2cfgd);
+
+	scratch2.word = 0;
+	scratch2.osc_ctrl_xobp = osc_ctrl.xobp;
+	scratch2.pllm_base_divm = pllm_base.pll_divm;
+	scratch2.pllm_base_divn = pllm_base.pll_divn;
+	scratch2.pllm_base_divp = pllm_base.pll_divp;
+	scratch2.pllm_misc_cpcon = pllm_misc.pll_cpcon;
+	scratch2.pllm_misc_lfcon = pllm_misc.pll_lfcon;
+	scratch2.gp_xm2cfga_padctrl_preemp = xm2cfga.preemp_en;
+	scratch2.gp_xm2cfgd_padctrl_schmt = xm2cfgd.schmt_en;
+	scratch2.memory_type = sdram.memory_type;
+	writel(scratch2.word, &pmc->pmc_scratch2);
+
+	/* collect data from various sources for pmc_scratch4 */
+	fbio_spare.word = readl(&emc->fbio_spare);
+	scratch4.word = 0;
+	scratch4.emc_fbio_spare_cfg_wb0 = fbio_spare.cfg_wb0;
+	scratch4.emc_clock_divider = sdram.emc_clock_divider;
+	scratch4.pllm_stable_time = -1;
+	scratch4.pllx_stable_time = -1;
+	writel(scratch4.word, &pmc->pmc_scratch4);
+
+	/* collect various data from sdram for pmc_scratch24 */
+	scratch24.word = 0;
+	scratch24.emc_pin_program_wait = sdram.emc_pin_program_wait;
+	scratch24.emc_auto_cal_wait = sdram.emc_auto_cal_wait;
+	scratch24.warmboot_wait = sdram.warm_boot_wait;
+	writel(scratch24.word, &pmc->pmc_scratch24);
+}
+
+/*
+ * 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 */
+
+static u32 get_major_version(void)
+{
+	u32 major_id;
+	struct apb_misc_gp_ctlr *gp =
+		(struct apb_misc_gp_ctlr *)TEGRA2_APB_MISC_GP_BASE;
+
+	major_id = (readl(&gp->hidrev) & HIDREV_MAJORPREV_MASK) >>
+			HIDREV_MAJORPREV_SHIFT;
+	return major_id;
+}
+
+static int is_production_mode_fuse_set(struct fuse_regs *fuse)
+{
+	return readl(&fuse->production_mode);
+}
+
+static int is_odm_production_mode_fuse_set(struct fuse_regs *fuse)
+{
+	return readl(&fuse->security_mode);
+}
+
+static int is_failure_analysis_mode(struct fuse_regs *fuse)
+{
+	return readl(&fuse->fa);
+}
+
+static int ap20_is_odm_production_mode(void)
+{
+	struct fuse_regs *fuse = (struct fuse_regs *)TEGRA2_FUSE_BASE;
+
+	if (!is_failure_analysis_mode(fuse) &&
+	    is_odm_production_mode_fuse_set(fuse))
+		return 1;
+	else
+		return 0;
+}
+
+static int ap20_is_production_mode(void)
+{
+	struct fuse_regs *fuse = (struct fuse_regs *)TEGRA2_FUSE_BASE;
+
+	if (get_major_version() == 0)
+		return 1;
+
+	if (!is_failure_analysis_mode(fuse) &&
+	    is_production_mode_fuse_set(fuse) &&
+	    !is_odm_production_mode_fuse_set(fuse))
+		return 1;
+	else
+		return 0;
+}
+
+static enum fuse_operating_mode fuse_get_operation_mode(void)
+{
+	u32 chip_id;
+	struct apb_misc_gp_ctlr *gp =
+		(struct apb_misc_gp_ctlr *)TEGRA2_APB_MISC_GP_BASE;
+
+	chip_id = (readl(&gp->hidrev) & HIDREV_CHIPID_MASK) >>
+			HIDREV_CHIPID_SHIFT;
+	if (chip_id == CHIPID_TEGRA2) {
+		if (ap20_is_odm_production_mode()) {
+			printf("!! odm_production_mode is not supported !!\n");
+			return MODE_UNDEFINED;
+		} else
+			if (ap20_is_production_mode())
+				return MODE_PRODUCTION;
+			else
+				return MODE_UNDEFINED;
+	}
+	return MODE_UNDEFINED;
+}
+
+/* Currently, this routine returns a 32-bit all 0 seed. */
+static u32 query_random_seed(void)
+{
+	return 0;
+}
+
+static void determine_crypto_options(int *is_encrypted, int *is_signed,
+				     int *use_zero_key)
+{
+	switch (fuse_get_operation_mode()) {
+	case MODE_PRODUCTION:
+		*is_encrypted = 0;
+		*is_signed = 1;
+		*use_zero_key = 1;
+		break;
+	case MODE_UNDEFINED:
+	default:
+		*is_encrypted = 0;
+		*is_signed = 0;
+		*use_zero_key  = 0;
+		break;
+	}
+}
+
+static int sign_wb_code(u32 start, u32 length, int use_zero_key)
+{
+	int err;
+	u8 *source;		/* Pointer to source */
+	u8 *hash;
+
+	/* Calculate AES block parameters. */
+	source = (u8 *)(start + offsetof(struct wb_header, random_aes_block));
+	length -= offsetof(struct wb_header, random_aes_block);
+	hash = (u8 *)(start + offsetof(struct wb_header, hash));
+	err = sign_data_block(source, length, hash);
+
+	return err;
+}
+
+int warmboot_prepare_code(u32 seg_address, u32 seg_length)
+{
+	int err = 0;
+	u32 length;			/* length of the signed/encrypt code */
+	struct wb_header *dst_header;	/* Pointer to dest WB header */
+	int is_encrypted;		/* Segment is encrypted */
+	int is_signed;			/* Segment is signed */
+	int use_zero_key;		/* Use key of all zeros */
+
+	/* Determine crypto options. */
+	determine_crypto_options(&is_encrypted, &is_signed, &use_zero_key);
+
+	/* Get the actual code limits. */
+	length = roundup(((u32)wb_end - (u32)wb_start), 16);
+
+	/*
+	 * The region specified by seg_address must not be in IRAM and must be
+	 * nonzero in length.
+	 */
+	if ((seg_length == 0) || (seg_address == 0) ||
+	    (seg_address >= AP20_BASE_PA_SRAM)) {
+		err = -EFAULT;
+		goto fail;
+	}
+
+	/* Things must be 16-byte aligned. */
+	if ((seg_length & 0xF) || (seg_address & 0xF)) {
+		err = -EINVAL;
+		goto fail;
+	}
+
+	/* Will the code fit? (destination includes wb_header + wb code) */
+	if (seg_length < (length + sizeof(struct wb_header))) {
+		err = -EINVAL;
+		goto fail;
+	}
+
+	dst_header = (struct wb_header *)seg_address;
+	memset((char *)dst_header, 0, sizeof(struct wb_header));
+
+	/* Populate the random_aes_block as requested. */
+	{
+		u32 *aes_block = (u32 *)&(dst_header->random_aes_block);
+		u32 *end = (u32 *)(((u32)aes_block) +
+				   sizeof(dst_header->random_aes_block));
+
+		do {
+#if defined(RANDOM_AES_BLOCK_IS_RANDOM)
+			*aes_block++ = query_random_seed();
+#elif defined(RANDOM_AES_BLOCK_IS_PATTERN)
+			*aes_block++ = RANDOM_AES_BLOCK_IS_PATTERN;
+#elif defined(RANDOM_AES_BLOCK_IS_ZERO)
+			*aes_block++ = 0;
+#else
+			printf("None of RANDOM_AES_BLOCK_IS_XXX is defined; ");
+			printf("Default to pattern 0.\n");
+			*aes_block++ = 0;
+#endif
+		} while (aes_block < end);
+	}
+
+	/* Populate the header. */
+	dst_header->length_in_secure = length + sizeof(struct wb_header);
+	dst_header->length_secure = length + sizeof(struct wb_header);
+	dst_header->destination = AP20_WB_RUN_ADDRESS;
+	dst_header->entry_point = AP20_WB_RUN_ADDRESS;
+	dst_header->code_length = length;
+
+	if (is_encrypted) {
+		printf("!!!! Encryption is not supported !!!!\n");
+		dst_header->length_in_secure = 0;
+		err = -EACCES;
+		goto fail;
+	} else
+		/* copy the wb code directly following dst_header. */
+		memcpy((char *)(dst_header+1), (char *)wb_start, length);
+
+	if (is_signed)
+		err = sign_wb_code(seg_address, dst_header->length_in_secure,
+				   use_zero_key);
+
+fail:
+	if (err)
+		printf("WB code not copied to LP0 location! (error=%d)\n", err);
+
+	return err;
+}
diff --git a/arch/arm/cpu/armv7/tegra2/warmboot_avp.c b/arch/arm/cpu/armv7/tegra2/warmboot_avp.c
new file mode 100644
index 0000000..6d04a4e
--- /dev/null
+++ b/arch/arm/cpu/armv7/tegra2/warmboot_avp.c
@@ -0,0 +1,312 @@
+/*
+ * (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/io.h>
+#include <asm/arch/ap20.h>
+#include <asm/arch/clk_rst.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/pinmux.h>
+#include <asm/arch/pmc.h>
+#include <asm/arch/tegra2.h>
+#include <asm/arch/flow.h>
+#include <asm/arch/warmboot.h>
+#include "warmboot_avp.h"
+
+#define DEBUG_RESET_CORESIGHT
+
+union osc_ctrl_reg {
+	struct {
+		u32 xoe:1;
+		u32 xobp:1;
+		u32 reserved0:2;
+		u32 xofs:6;
+		u32 reserved1:2;
+		u32 xods:5;
+		u32 reserved2:3;
+		u32 oscfi_spare:8;
+		u32 pll_ref_div:2;
+		u32 osc_freq:2;
+	};
+	u32 word;
+};
+
+union pllx_base_reg {
+	struct {
+		u32 divm:5;
+		u32 reserved0:3;
+		u32 divn:10;
+		u32 reserved1:2;
+		u32 divp:3;
+		u32 reserved2:4;
+		u32 lock:1;
+		u32 reserved3:1;
+		u32 ref_dis:1;
+		u32 enable:1;
+		u32 bypass:1;
+	};
+	u32 word;
+};
+
+union pllx_misc_reg {
+	struct {
+		u32 vcocon:4;
+		u32 lfcon:4;
+		u32 cpcon:4;
+		u32 lock_sel:6;
+		u32 reserved0:1;
+		u32 lock_enable:1;
+		u32 reserved1:1;
+		u32 dccon:1;
+		u32 pts:2;
+		u32 reserved2:6;
+		u32 out1_div_byp:1;
+		u32 out1_inv_clk:1;
+	};
+	u32 word;
+};
+
+union scratch3_reg {
+	struct {
+		u32 pllx_base_divm:5;
+		u32 pllx_base_divn:10;
+		u32 pllx_base_divp:3;
+		u32 pllx_misc_lfcon:4;
+		u32 pllx_misc_cpcon:4;
+	};
+	u32 word;
+};
+
+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 */
+	);
+
+	if (reg != AP20_WB_RUN_ADDRESS)
+		goto do_reset;
+
+	/* Are we running with AVP? */
+	if (readl(NV_PA_PG_UP_BASE + PG_UP_TAG_0) != PG_UP_TAG_AVP)
+		goto do_reset;
+
+#ifdef DEBUG_RESET_CORESIGHT
+	/* Assert CoreSight reset */
+	reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_U]);
+	reg |= SWR_CSITE_RST;
+	writel(reg, &clkrst->crc_rst_dev[TEGRA_DEV_U]);
+#endif
+
+	/* 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);
+
+	/* Power up the CPU complex if necessary */
+	if (!(readl(&pmc->pmc_pwrgate_status) & PWRGATE_STATUS_CPU)) {
+		reg = PWRGATE_TOGGLE_PARTID_CPU | PWRGATE_TOGGLE_START;
+		writel(reg, &pmc->pmc_pwrgate_toggle);
+		while (!(readl(&pmc->pmc_pwrgate_status) & PWRGATE_STATUS_CPU))
+			;
+	}
+
+	/* Remove the I/O clamps from the CPU power partition. */
+	reg = readl(&pmc->pmc_remove_clamping);
+	reg |= CPU_CLMP;
+	writel(reg, &pmc->pmc_remove_clamping);
+
+	reg = EVENT_ZERO_VAL_20 | EVENT_MSEC | EVENT_MODE_STOP;
+	writel(reg, &flow->halt_cop_events);
+
+	/* Assert CPU complex reset */
+	reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_L]);
+	reg |= CPU_RST;
+	writel(reg, &clkrst->crc_rst_dev[TEGRA_DEV_L]);
+
+	/* Hold both CPUs in reset */
+	reg = CPU_CMPLX_CPURESET0 | CPU_CMPLX_CPURESET1 | CPU_CMPLX_DERESET0 |
+	      CPU_CMPLX_DERESET1 | CPU_CMPLX_DBGRESET0 | CPU_CMPLX_DBGRESET1;
+	writel(reg, &clkrst->crc_cpu_cmplx_set);
+
+	/* Halt CPU1 at the flow controller for uni-processor configurations */
+	writel(EVENT_MODE_STOP, &flow->halt_cpu1_events);
+
+	/*
+	 * Set the CPU reset vector. SCRATCH41 contains the physical
+	 * address of the CPU-side restoration code.
+	 */
+	reg = readl(&pmc->pmc_scratch41);
+	writel(reg, EXCEP_VECTOR_CPU_RESET_VECTOR);
+
+	/* Select CPU complex clock source */
+	writel(CCLK_PLLP_BURST_POLICY, &clkrst->crc_cclk_brst_pol);
+
+	/* Start the CPU0 clock and stop the CPU1 clock */
+	reg = CPU_CMPLX_CPU_BRIDGE_CLKDIV_4 | CPU_CMPLX_CPU0_CLK_STP_RUN |
+	      CPU_CMPLX_CPU1_CLK_STP_STOP;
+	writel(reg, &clkrst->crc_clk_cpu_cmplx);
+
+	/* Enable the CPU complex clock */
+	reg = readl(&clkrst->crc_clk_out_enb[TEGRA_DEV_L]);
+	reg |= CLK_ENB_CPU;
+	writel(reg, &clkrst->crc_clk_out_enb[TEGRA_DEV_L]);
+
+	/* Make sure the resets were held for at least 2 microseconds */
+	reg = readl(TIMER_USEC_CNTR);
+	while (readl(TIMER_USEC_CNTR) <= (reg + 2))
+		;
+
+#ifdef DEBUG_RESET_CORESIGHT
+	/*
+	 * De-assert CoreSight reset.
+	 * NOTE: We're leaving the CoreSight clock on the oscillator for
+	 *	now. It will be restored to its original clock source
+	 *	when the CPU-side restoration code runs.
+	 */
+	reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_U]);
+	reg &= ~SWR_CSITE_RST;
+	writel(reg, &clkrst->crc_rst_dev[TEGRA_DEV_U]);
+#endif
+
+	/* Unlock the CPU CoreSight interfaces */
+	reg = 0xC5ACCE55;
+	writel(reg, CSITE_CPU_DBG0_LAR);
+	writel(reg, CSITE_CPU_DBG1_LAR);
+
+	/*
+	 * Sample the microsecond timestamp again. This is the time we must
+	 * use when returning from LP0 for PLL stabilization delays.
+	 */
+	reg = readl(TIMER_USEC_CNTR);
+	writel(reg, &pmc->pmc_scratch1);
+
+	pllx_base.word = 0;
+	pllx_misc.word = 0;
+	scratch3.word = readl(&pmc->pmc_scratch3);
+
+	/* Get the OSC. For 19.2 MHz, use 19 to make the calculations easier */
+	reg = (readl(TIMER_USEC_CFG) & USEC_CFG_DIVISOR_MASK) + 1;
+
+	/*
+	 * According to the TRM, for 19.2MHz OSC, the USEC_DIVISOR is 0x5f, and
+	 * USEC_DIVIDEND is 0x04. So, if USEC_DIVISOR > 26, OSC is 19.2 MHz.
+	 *
+	 * reg is used to calculate the pllx freq, which is used to determine if
+	 * to set dccon or not.
+	 */
+	if (reg > 26)
+		reg = 19;
+
+	/* PLLX_BASE.PLLX_DIVM */
+	if (scratch3.pllx_base_divm == reg)
+		reg = 0;
+	else
+		reg = 1;
+
+	/* PLLX_BASE.PLLX_DIVN */
+	pllx_base.divn = scratch3.pllx_base_divn;
+	reg = scratch3.pllx_base_divn << reg;
+
+	/* PLLX_BASE.PLLX_DIVP */
+	pllx_base.divp = scratch3.pllx_base_divp;
+	reg = reg >> scratch3.pllx_base_divp;
+
+	pllx_base.bypass = 1;
+
+	/* PLLX_MISC_DCCON must be set for pllx frequency > 600 MHz. */
+	if (reg > 600)
+		pllx_misc.dccon = 1;
+
+	/* PLLX_MISC_LFCON */
+	pllx_misc.lfcon = scratch3.pllx_misc_lfcon;
+
+	/* PLLX_MISC_CPCON */
+	pllx_misc.cpcon = scratch3.pllx_misc_cpcon;
+
+	writel(pllx_misc.word, &clkrst->crc_pll_simple[SIMPLE_PLLX].pll_misc);
+	writel(pllx_base.word, &clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base);
+
+	pllx_base.enable = 1;
+	writel(pllx_base.word, &clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base);
+	pllx_base.bypass = 0;
+	writel(pllx_base.word, &clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base);
+
+	writel(0, flow->halt_cpu_events);
+
+	reg = CPU_CMPLX_CPURESET0 | CPU_CMPLX_DBGRESET0 | CPU_CMPLX_DERESET0;
+	writel(reg, &clkrst->crc_cpu_cmplx_clr);
+
+	reg = PLLM_OUT1_RSTN_RESET_DISABLE | PLLM_OUT1_CLKEN_ENABLE |
+	      PLLM_OUT1_RATIO_VAL_8;
+	writel(reg, &clkrst->crc_pll[CLOCK_ID_MEMORY].pll_out);
+
+	reg = SCLK_SWAKE_FIQ_SRC_PLLM_OUT1 | SCLK_SWAKE_IRQ_SRC_PLLM_OUT1 |
+	      SCLK_SWAKE_RUN_SRC_PLLM_OUT1 | SCLK_SWAKE_IDLE_SRC_PLLM_OUT1 |
+	      SCLK_SYS_STATE_IDLE;
+	writel(reg, &clkrst->crc_sclk_brst_pol);
+
+	/* avp_resume: no return after the write */
+	reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_L]);
+	reg &= ~CPU_RST;
+	writel(reg, &clkrst->crc_rst_dev[TEGRA_DEV_L]);
+
+	/* avp_halt: */
+avp_halt:
+	reg = EVENT_MODE_STOP | EVENT_JTAG;
+	writel(reg, flow->halt_cop_events);
+	goto avp_halt;
+
+do_reset:
+	/*
+	 * Execution comes here if something goes wrong. The chip is reset and
+	 * a cold boot is performed.
+	 */
+	writel(SWR_TRIG_SYS_RST, &clkrst->crc_rst_dev[TEGRA_DEV_L]);
+	goto do_reset;
+}
+
+/*
+ * wb_end() is a dummy function, and must be directly following wb_start(),
+ * and is used to calculate the size of wb_start().
+ */
+void wb_end(void)
+{
+}
diff --git a/arch/arm/cpu/armv7/tegra2/warmboot_avp.h b/arch/arm/cpu/armv7/tegra2/warmboot_avp.h
new file mode 100644
index 0000000..4b71c07
--- /dev/null
+++ b/arch/arm/cpu/armv7/tegra2/warmboot_avp.h
@@ -0,0 +1,81 @@
+/*
+ * (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 _WARMBOOT_AVP_H_
+#define _WARMBOOT_AVP_H_
+
+#define TEGRA_DEV_L			0
+#define TEGRA_DEV_H			1
+#define TEGRA_DEV_U			2
+
+#define SIMPLE_PLLX			(CLOCK_ID_XCPU - CLOCK_ID_FIRST_SIMPLE)
+#define SIMPLE_PLLE			(CLOCK_ID_EPCI - CLOCK_ID_FIRST_SIMPLE)
+
+#define TIMER_USEC_CNTR			(NV_PA_TMRUS_BASE + 0)
+#define TIMER_USEC_CFG			(NV_PA_TMRUS_BASE + 4)
+
+#define USEC_CFG_DIVISOR_MASK		0xffff
+
+#define CONFIG_CTL_TBE			(1 << 7)
+#define CONFIG_CTL_JTAG			(1 << 6)
+
+#define CPU_RST				(1 << 0)
+#define CLK_ENB_CPU			(1 << 0)
+#define SWR_TRIG_SYS_RST		(1 << 2)
+#define SWR_CSITE_RST			(1 << 9)
+
+#define PWRGATE_STATUS_CPU		(1 << 0)
+#define PWRGATE_TOGGLE_PARTID_CPU	(0 << 0)
+#define PWRGATE_TOGGLE_START		(1 << 8)
+
+#define CPU_CMPLX_CPU_BRIDGE_CLKDIV_4	(3 << 0)
+#define CPU_CMPLX_CPU0_CLK_STP_STOP	(1 << 8)
+#define CPU_CMPLX_CPU0_CLK_STP_RUN	(0 << 8)
+#define CPU_CMPLX_CPU1_CLK_STP_STOP	(1 << 9)
+#define CPU_CMPLX_CPU1_CLK_STP_RUN	(0 << 9)
+
+#define CPU_CMPLX_CPURESET0		(1 << 0)
+#define CPU_CMPLX_CPURESET1		(1 << 1)
+#define CPU_CMPLX_DERESET0		(1 << 4)
+#define CPU_CMPLX_DERESET1		(1 << 5)
+#define CPU_CMPLX_DBGRESET0		(1 << 12)
+#define CPU_CMPLX_DBGRESET1		(1 << 13)
+
+#define PLLM_OUT1_RSTN_RESET_DISABLE	(1 << 0)
+#define PLLM_OUT1_CLKEN_ENABLE		(1 << 1)
+#define PLLM_OUT1_RATIO_VAL_8		(8 << 8)
+
+#define SCLK_SYS_STATE_IDLE		(1 << 28)
+#define SCLK_SWAKE_FIQ_SRC_PLLM_OUT1	(7 << 12)
+#define SCLK_SWAKE_IRQ_SRC_PLLM_OUT1	(7 << 8)
+#define SCLK_SWAKE_RUN_SRC_PLLM_OUT1	(7 << 4)
+#define SCLK_SWAKE_IDLE_SRC_PLLM_OUT1	(7 << 0)
+
+#define EVENT_ZERO_VAL_20		(20 << 0)
+#define EVENT_MSEC			(1 << 24)
+#define EVENT_JTAG			(1 << 28)
+#define EVENT_MODE_STOP			(2 << 29)
+
+#define CCLK_PLLP_BURST_POLICY		0x20004444
+
+#endif
diff --git a/arch/arm/include/asm/arch-tegra2/tegra2.h b/arch/arm/include/asm/arch-tegra2/tegra2.h
index 480ec0c..32027b1 100644
--- a/arch/arm/include/asm/arch-tegra2/tegra2.h
+++ b/arch/arm/include/asm/arch-tegra2/tegra2.h
@@ -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)
diff --git a/arch/arm/include/asm/arch-tegra2/warmboot.h b/arch/arm/include/asm/arch-tegra2/warmboot.h
new file mode 100644
index 0000000..d8512a1
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra2/warmboot.h
@@ -0,0 +1,81 @@
+/*
+ * (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 _WARM_BOOT_H_
+#define _WARM_BOOT_H_
+
+/* bit fields definitions for APB_MISC_GP_HIDREV register */
+#define HIDREV_CHIPID_SHIFT		8
+#define HIDREV_CHIPID_MASK		(0xff << HIDREV_CHIPID_SHIFT)
+#define HIDREV_MAJORPREV_SHIFT		4
+#define HIDREV_MAJORPREV_MASK		(0xf << HIDREV_MAJORPREV_SHIFT)
+
+/* CHIPID field returned from APB_MISC_GP_HIDREV register */
+#define CHIPID_TEGRA2				0x20
+
+#define STRAP_OPT_A_RAM_CODE_SHIFT	4
+#define STRAP_OPT_A_RAM_CODE_MASK	(0xf << STRAP_OPT_A_RAM_CODE_SHIFT)
+
+/* Defines the supported operating modes */
+enum fuse_operating_mode {
+	MODE_PRODUCTION = 3,
+	MODE_UNDEFINED,
+};
+
+/* Defines the CMAC-AES-128 hash length in 32 bit words. (128 bits = 4 words) */
+enum {
+	HASH_LENGTH = 4
+};
+
+/* Defines the storage for a hash value (128 bits) */
+struct hash {
+	u32 hash[HASH_LENGTH];
+};
+
+/*
+ * 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 */
+	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 */
+};
+
+void warmboot_save_sdram_params(void);
+int warmboot_prepare_code(u32 seg_address, u32 seg_length);
+int sign_data_block(u8 *source, u32 length, u8 *signature);
+void wb_start(void);	/* Start of WB assembly code */
+void wb_end(void);	/* End of WB assembly code */
+
+#endif
-- 
1.7.3.1

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 10/14] tegra: Setup PMC scratch info from ap20 setup
  2011-12-26 19:32 [U-Boot] [PATCH 0/14] tegra: warmboot (suspend / resume) support Simon Glass
                   ` (8 preceding siblings ...)
  2011-12-26 19:33 ` [U-Boot] [PATCH 09/14] tegra: Add warmboot implementation Simon Glass
@ 2011-12-26 19:33 ` Simon Glass
  2011-12-26 19:33 ` [U-Boot] [PATCH 11/14] tegra: Set up warmboot code on Nvidia boards Simon Glass
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 51+ messages in thread
From: Simon Glass @ 2011-12-26 19:33 UTC (permalink / raw)
  To: u-boot

From: Yen Lin <yelin@nvidia.com>

Save SDRAM parameters into the warmboot scratch registers

Signed-off-by: Simon Glass <sjg@chromium.org>
---
 arch/arm/cpu/armv7/tegra2/ap20.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/arch/arm/cpu/armv7/tegra2/ap20.c b/arch/arm/cpu/armv7/tegra2/ap20.c
index 311e93f..c0943eb 100644
--- a/arch/arm/cpu/armv7/tegra2/ap20.c
+++ b/arch/arm/cpu/armv7/tegra2/ap20.c
@@ -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)
-- 
1.7.3.1

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 11/14] tegra: Set up warmboot code on Nvidia boards
  2011-12-26 19:32 [U-Boot] [PATCH 0/14] tegra: warmboot (suspend / resume) support Simon Glass
                   ` (9 preceding siblings ...)
  2011-12-26 19:33 ` [U-Boot] [PATCH 10/14] tegra: Setup PMC scratch info from ap20 setup Simon Glass
@ 2011-12-26 19:33 ` Simon Glass
  2011-12-26 19:33 ` [U-Boot] [PATCH 12/14] tegra: Set vdd_core and vdd_cpu to high Simon Glass
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 51+ messages in thread
From: Simon Glass @ 2011-12-26 19:33 UTC (permalink / raw)
  To: u-boot

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

Signed-off-by: Simon Glass <sjg@chromium.org>
---
 board/nvidia/common/board.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c
index 10c0a67..fbdd260 100644
--- a/board/nvidia/common/board.c
+++ b/board/nvidia/common/board.c
@@ -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();
 
-- 
1.7.3.1

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 12/14] tegra: Set vdd_core and vdd_cpu to high
  2011-12-26 19:32 [U-Boot] [PATCH 0/14] tegra: warmboot (suspend / resume) support Simon Glass
                   ` (10 preceding siblings ...)
  2011-12-26 19:33 ` [U-Boot] [PATCH 11/14] tegra: Set up warmboot code on Nvidia boards Simon Glass
@ 2011-12-26 19:33 ` Simon Glass
  2012-01-10 18:40   ` Stephen Warren
  2011-12-26 19:33 ` [U-Boot] [PATCH 13/14] tegra: Add EMC settings for Seaboard, Harmony Simon Glass
  2011-12-26 19:33 ` [U-Boot] [PATCH 14/14] tegra: Enable LP0 on Seaboard Simon Glass
  13 siblings, 1 reply; 51+ messages in thread
From: Simon Glass @ 2011-12-26 19:33 UTC (permalink / raw)
  To: u-boot

From: Jimmy Zhang <jimmzhang@nvidia.com>

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)

Signed-off-by: Simon Glass <sjg@chromium.org>
---
 board/nvidia/common/board.c |   18 ++++++++++++++++++
 1 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c
index fbdd260..cda2417 100644
--- a/board/nvidia/common/board.c
+++ b/board/nvidia/common/board.c
@@ -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();
 
-- 
1.7.3.1

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 13/14] tegra: Add EMC settings for Seaboard, Harmony
  2011-12-26 19:32 [U-Boot] [PATCH 0/14] tegra: warmboot (suspend / resume) support Simon Glass
                   ` (11 preceding siblings ...)
  2011-12-26 19:33 ` [U-Boot] [PATCH 12/14] tegra: Set vdd_core and vdd_cpu to high Simon Glass
@ 2011-12-26 19:33 ` Simon Glass
  2012-01-10 18:46   ` Stephen Warren
  2011-12-26 19:33 ` [U-Boot] [PATCH 14/14] tegra: Enable LP0 on Seaboard Simon Glass
  13 siblings, 1 reply; 51+ messages in thread
From: Simon Glass @ 2011-12-26 19:33 UTC (permalink / raw)
  To: u-boot

From: Jimmy Zhang <jimmzhang@nvidia.com>

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

Signed-off-by: Simon Glass <sjg@chromium.org>
---
 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

diff --git a/board/nvidia/common/Makefile b/board/nvidia/common/Makefile
index 3e748fd..a93d458 100644
--- a/board/nvidia/common/Makefile
+++ b/board/nvidia/common/Makefile
@@ -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)
diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c
index cda2417..2569ae1 100644
--- a/board/nvidia/common/board.c
+++ b/board/nvidia/common/board.c
@@ -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
 
diff --git a/board/nvidia/common/emc.c b/board/nvidia/common/emc.c
new file mode 100644
index 0000000..8be2fba
--- /dev/null
+++ b/board/nvidia/common/emc.c
@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/ap20.h>
+#include <asm/arch/clk_rst.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/emc.h>
+#include <asm/arch/pmu.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/tegra2.h>
+
+static const struct tegra_emc_table seaboard_emc_tables_hynix_333Mhz[] = {
+	{
+		.rate = 166500,   /* SDRAM frequency */
+		.regs = {
+			0x0000000a,   /* RC */
+			0x00000021,   /* RFC */
+			0x00000008,   /* RAS */
+			0x00000003,   /* RP */
+			0x00000004,   /* R2W */
+			0x00000004,   /* W2R */
+			0x00000002,   /* R2P */
+			0x0000000c,   /* W2P */
+			0x00000003,   /* RD_RCD */
+			0x00000003,   /* WR_RCD */
+			0x00000002,   /* RRD */
+			0x00000001,   /* REXT */
+			0x00000004,   /* WDV */
+			0x00000005,   /* QUSE */
+			0x00000004,   /* QRST */
+			0x00000009,   /* QSAFE */
+			0x0000000d,   /* RDV */
+			0x000004df,   /* REFRESH */
+			0x00000000,   /* BURST_REFRESH_NUM */
+			0x00000003,   /* PDEX2WR */
+			0x00000003,   /* PDEX2RD */
+			0x00000003,   /* PCHG2PDEN */
+			0x00000003,   /* ACT2PDEN */
+			0x00000001,   /* AR2PDEN */
+			0x0000000a,   /* RW2PDEN */
+			0x000000c8,   /* TXSR */
+			0x00000003,   /* TCKE */
+			0x00000006,   /* TFAW */
+			0x00000004,   /* TRPAB */
+			0x0000000f,   /* TCLKSTABLE */
+			0x00000002,   /* TCLKSTOP */
+			0x00000000,   /* TREFBW */
+			0x00000000,   /* QUSE_EXTRA */
+			0x00000002,   /* FBIO_CFG6 */
+			0x00000000,   /* ODT_WRITE */
+			0x00000000,   /* ODT_READ */
+			0x00000083,   /* FBIO_CFG5 */
+			0xa04004ae,   /* CFG_DIG_DLL */
+			0x007fd010,   /* DLL_XFORM_DQS */
+			0x00000000,   /* DLL_XFORM_QUSE */
+			0x00000000,   /* ZCAL_REF_CNT */
+			0x00000000,   /* ZCAL_WAIT_CNT */
+			0x00000000,   /* AUTO_CAL_INTERVAL */
+			0x00000000,   /* CFG_CLKTRIM_0 */
+			0x00000000,   /* CFG_CLKTRIM_1 */
+			0x00000000,   /* CFG_CLKTRIM_2 */
+		}
+	}, {
+		.rate = 333000,   /* SDRAM frequency */
+		.regs = {
+			0x00000014,   /* RC */
+			0x00000041,   /* RFC */
+			0x0000000f,   /* RAS */
+			0x00000005,   /* RP */
+			0x00000004,   /* R2W */
+			0x00000005,   /* W2R */
+			0x00000003,   /* R2P */
+			0x0000000c,   /* W2P */
+			0x00000005,   /* RD_RCD */
+			0x00000005,   /* WR_RCD */
+			0x00000003,   /* RRD */
+			0x00000001,   /* REXT */
+			0x00000004,   /* WDV */
+			0x00000005,   /* QUSE */
+			0x00000004,   /* QRST */
+			0x00000009,   /* QSAFE */
+			0x0000000d,   /* RDV */
+			0x000009ff,   /* REFRESH */
+			0x00000000,   /* BURST_REFRESH_NUM */
+			0x00000003,   /* PDEX2WR */
+			0x00000003,   /* PDEX2RD */
+			0x00000005,   /* PCHG2PDEN */
+			0x00000005,   /* ACT2PDEN */
+			0x00000001,   /* AR2PDEN */
+			0x0000000f,   /* RW2PDEN */
+			0x000000c8,   /* TXSR */
+			0x00000003,   /* TCKE */
+			0x0000000c,   /* TFAW */
+			0x00000006,   /* TRPAB */
+			0x0000000f,   /* TCLKSTABLE */
+			0x00000002,   /* TCLKSTOP */
+			0x00000000,   /* TREFBW */
+			0x00000000,   /* QUSE_EXTRA */
+			0x00000002,   /* FBIO_CFG6 */
+			0x00000000,   /* ODT_WRITE */
+			0x00000000,   /* ODT_READ */
+			0x00000083,   /* FBIO_CFG5 */
+			0xe034048b,   /* CFG_DIG_DLL */
+			0x007e8010,   /* DLL_XFORM_DQS */
+			0x00000000,   /* DLL_XFORM_QUSE */
+			0x00000000,   /* ZCAL_REF_CNT */
+			0x00000000,   /* ZCAL_WAIT_CNT */
+			0x00000000,   /* AUTO_CAL_INTERVAL */
+			0x00000000,   /* CFG_CLKTRIM_0 */
+			0x00000000,   /* CFG_CLKTRIM_1 */
+			0x00000000,   /* CFG_CLKTRIM_2 */
+		}
+	}
+};
+
+static const struct tegra_emc_table seaboard_emc_tables_hynix_380Mhz[] = {
+	{
+		.rate = 190000,   /* SDRAM frequency */
+		.regs = {
+			0x0000000c,   /* RC */
+			0x00000026,   /* RFC */
+			0x00000009,   /* RAS */
+			0x00000003,   /* RP */
+			0x00000004,   /* R2W */
+			0x00000004,   /* W2R */
+			0x00000002,   /* R2P */
+			0x0000000c,   /* W2P */
+			0x00000003,   /* RD_RCD */
+			0x00000003,   /* WR_RCD */
+			0x00000002,   /* RRD */
+			0x00000001,   /* REXT */
+			0x00000004,   /* WDV */
+			0x00000005,   /* QUSE */
+			0x00000004,   /* QRST */
+			0x00000009,   /* QSAFE */
+			0x0000000d,   /* RDV */
+			0x0000059f,   /* REFRESH */
+			0x00000000,   /* BURST_REFRESH_NUM */
+			0x00000003,   /* PDEX2WR */
+			0x00000003,   /* PDEX2RD */
+			0x00000003,   /* PCHG2PDEN */
+			0x00000003,   /* ACT2PDEN */
+			0x00000001,   /* AR2PDEN */
+			0x0000000b,   /* RW2PDEN */
+			0x000000c8,   /* TXSR */
+			0x00000003,   /* TCKE */
+			0x00000007,   /* TFAW */
+			0x00000004,   /* TRPAB */
+			0x0000000f,   /* TCLKSTABLE */
+			0x00000002,   /* TCLKSTOP */
+			0x00000000,   /* TREFBW */
+			0x00000000,   /* QUSE_EXTRA */
+			0x00000002,   /* FBIO_CFG6 */
+			0x00000000,   /* ODT_WRITE */
+			0x00000000,   /* ODT_READ */
+			0x00000083,   /* FBIO_CFG5 */
+			0xa06204ae,   /* CFG_DIG_DLL */
+			0x007dc010,   /* DLL_XFORM_DQS */
+			0x00000000,   /* DLL_XFORM_QUSE */
+			0x00000000,   /* ZCAL_REF_CNT */
+			0x00000000,   /* ZCAL_WAIT_CNT */
+			0x00000000,   /* AUTO_CAL_INTERVAL */
+			0x00000000,   /* CFG_CLKTRIM_0 */
+			0x00000000,   /* CFG_CLKTRIM_1 */
+			0x00000000,   /* CFG_CLKTRIM_2 */
+		}
+	}, {
+		.rate = 380000,   /* SDRAM frequency */
+		.regs = {
+			0x00000017,   /* RC */
+			0x0000004b,   /* RFC */
+			0x00000012,   /* RAS */
+			0x00000006,   /* RP */
+			0x00000004,   /* R2W */
+			0x00000005,   /* W2R */
+			0x00000003,   /* R2P */
+			0x0000000c,   /* W2P */
+			0x00000006,   /* RD_RCD */
+			0x00000006,   /* WR_RCD */
+			0x00000003,   /* RRD */
+			0x00000001,   /* REXT */
+			0x00000004,   /* WDV */
+			0x00000005,   /* QUSE */
+			0x00000004,   /* QRST */
+			0x00000009,   /* QSAFE */
+			0x0000000d,   /* RDV */
+			0x00000b5f,   /* REFRESH */
+			0x00000000,   /* BURST_REFRESH_NUM */
+			0x00000003,   /* PDEX2WR */
+			0x00000003,   /* PDEX2RD */
+			0x00000006,   /* PCHG2PDEN */
+			0x00000006,   /* ACT2PDEN */
+			0x00000001,   /* AR2PDEN */
+			0x00000011,   /* RW2PDEN */
+			0x000000c8,   /* TXSR */
+			0x00000003,   /* TCKE */
+			0x0000000e,   /* TFAW */
+			0x00000007,   /* TRPAB */
+			0x0000000f,   /* TCLKSTABLE */
+			0x00000002,   /* TCLKSTOP */
+			0x00000000,   /* TREFBW */
+			0x00000000,   /* QUSE_EXTRA */
+			0x00000002,   /* FBIO_CFG6 */
+			0x00000000,   /* ODT_WRITE */
+			0x00000000,   /* ODT_READ */
+			0x00000083,   /* FBIO_CFG5 */
+			0xe044048b,   /* CFG_DIG_DLL */
+			0x007d8010,   /* DLL_XFORM_DQS */
+			0x00000000,   /* DLL_XFORM_QUSE */
+			0x00000000,   /* ZCAL_REF_CNT */
+			0x00000000,   /* ZCAL_WAIT_CNT */
+			0x00000000,   /* AUTO_CAL_INTERVAL */
+			0x00000000,   /* CFG_CLKTRIM_0 */
+			0x00000000,   /* CFG_CLKTRIM_1 */
+			0x00000000,   /* CFG_CLKTRIM_2 */
+		}
+	}
+};
+
+void seaboard_emc_init(void)
+{
+	switch (tegra_get_chip_type()) {
+	case TEGRA_SOC_T20:
+		tegra_set_emc(seaboard_emc_tables_hynix_333Mhz,
+			ARRAY_SIZE(seaboard_emc_tables_hynix_333Mhz));
+		break;
+	case TEGRA_SOC_T25:
+		tegra_set_emc(seaboard_emc_tables_hynix_380Mhz,
+			ARRAY_SIZE(seaboard_emc_tables_hynix_380Mhz));
+		break;
+	default:
+		/* unknown chip type, no clk change*/
+		tegra_set_emc(NULL, 0);
+		break;
+	}
+}
+
+struct emc_init {
+	unsigned int	id;		/* board id */
+	void		(*init)(void);
+};
+
+static struct emc_init board_table[] = {
+	{
+		.id	= MACH_TYPE_HARMONY,
+		.init	= NULL,
+	},
+	{
+		.id	= MACH_TYPE_SEABOARD,
+		.init	= seaboard_emc_init,
+	},
+};
+
+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
+	for (i = 0; i < ARRAY_SIZE(board_table); i++) {
+		if (board_table[i].id == gd->bd->bi_arch_number) {
+			if (board_table[i].init) {
+				board_table[i].init();
+				return 0;
+			} else
+				return -1;
+		}
+	}
+	return -1;
+}
diff --git a/board/nvidia/common/emc.h b/board/nvidia/common/emc.h
new file mode 100644
index 0000000..ec1b115
--- /dev/null
+++ b/board/nvidia/common/emc.h
@@ -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
-- 
1.7.3.1

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 14/14] tegra: Enable LP0 on Seaboard
  2011-12-26 19:32 [U-Boot] [PATCH 0/14] tegra: warmboot (suspend / resume) support Simon Glass
                   ` (12 preceding siblings ...)
  2011-12-26 19:33 ` [U-Boot] [PATCH 13/14] tegra: Add EMC settings for Seaboard, Harmony Simon Glass
@ 2011-12-26 19:33 ` Simon Glass
  13 siblings, 0 replies; 51+ messages in thread
From: Simon Glass @ 2011-12-26 19:33 UTC (permalink / raw)
  To: u-boot

This enables LP0 to support suspend / resume on Seaboard.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
 include/configs/seaboard.h      |    7 +++++++
 include/configs/tegra2-common.h |   17 +++++++++++++++++
 2 files changed, 24 insertions(+), 0 deletions(-)

diff --git a/include/configs/seaboard.h b/include/configs/seaboard.h
index 6e04278..97faa57 100644
--- a/include/configs/seaboard.h
+++ b/include/configs/seaboard.h
@@ -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 */
diff --git a/include/configs/tegra2-common.h b/include/configs/tegra2-common.h
index 6549d00..6c38f51 100644
--- a/include/configs/tegra2-common.h
+++ b/include/configs/tegra2-common.h
@@ -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 */
 
-- 
1.7.3.1

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 01/14] Add AES crypto library
  2011-12-26 19:32 ` [U-Boot] [PATCH 01/14] Add AES crypto library Simon Glass
@ 2012-01-08  5:49   ` Mike Frysinger
  2012-01-08  8:57     ` Marek Vasut
  0 siblings, 1 reply; 51+ messages in thread
From: Mike Frysinger @ 2012-01-08  5:49 UTC (permalink / raw)
  To: u-boot

On Monday 26 December 2011 14:32:54 Simon Glass wrote:
> --- /dev/null
> +++ b/lib/aes.c
>
> +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

> +static void mix_sub_columns(u8 *state)
> +{
> ...
> +		 x3_sbox[state[2]] ^       sbox[state[7]];

looks bad whitespace after that ^

> +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>

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 03/14] tegra: Add crypto library for warmboot code
  2011-12-26 19:32 ` [U-Boot] [PATCH 03/14] tegra: Add crypto library for warmboot code Simon Glass
@ 2012-01-08  5:51   ` Mike Frysinger
  2012-01-08 16:42     ` Simon Glass
  0 siblings, 1 reply; 51+ messages in thread
From: Mike Frysinger @ 2012-01-08  5:51 UTC (permalink / raw)
  To: u-boot

On Monday 26 December 2011 14:32:56 Simon Glass wrote:
> --- /dev/null
> +++ b/arch/arm/cpu/armv7/tegra2/crypto.c
>
> +#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

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>

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 01/14] Add AES crypto library
  2012-01-08  5:49   ` Mike Frysinger
@ 2012-01-08  8:57     ` Marek Vasut
  2012-01-08  9:09       ` Mike Frysinger
  0 siblings, 1 reply; 51+ messages in thread
From: Marek Vasut @ 2012-01-08  8:57 UTC (permalink / raw)
  To: u-boot

> On Monday 26 December 2011 14:32:54 Simon Glass wrote:
> > --- /dev/null
> > +++ b/lib/aes.c
> > 
> > +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
> 
> > +static void mix_sub_columns(u8 *state)
> > +{
> > ...
> > +		 x3_sbox[state[2]] ^       sbox[state[7]];
> 
> looks bad whitespace after that ^
> 
> > +static u8 rcon[11] = {
> 
> const
> -mike

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

M

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 01/14] Add AES crypto library
  2012-01-08  8:57     ` Marek Vasut
@ 2012-01-08  9:09       ` Mike Frysinger
  2012-01-08 10:40         ` Marek Vasut
  0 siblings, 1 reply; 51+ messages in thread
From: Mike Frysinger @ 2012-01-08  9:09 UTC (permalink / raw)
  To: u-boot

On Sunday 08 January 2012 03:57:47 Marek Vasut wrote:
> > On Monday 26 December 2011 14:32:54 Simon Glass wrote:
> > > --- /dev/null
> > > +++ b/lib/aes.c
> > > 
> > > +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
> > 
> > > +static void mix_sub_columns(u8 *state)
> > > +{
> > > ...
> > > +		 x3_sbox[state[2]] ^       sbox[state[7]];
> > 
> > looks bad whitespace after that ^
> > 
> > > +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>

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 01/14] Add AES crypto library
  2012-01-08  9:09       ` Mike Frysinger
@ 2012-01-08 10:40         ` Marek Vasut
  2012-01-08 16:35           ` Simon Glass
  0 siblings, 1 reply; 51+ messages in thread
From: Marek Vasut @ 2012-01-08 10:40 UTC (permalink / raw)
  To: u-boot

> On Sunday 08 January 2012 03:57:47 Marek Vasut wrote:
> > > On Monday 26 December 2011 14:32:54 Simon Glass wrote:
> > > > --- /dev/null
> > > > +++ b/lib/aes.c
> > > > 
> > > > +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
> > > 
> > > > +static void mix_sub_columns(u8 *state)
> > > > +{
> > > > ...
> > > > +		 x3_sbox[state[2]] ^       sbox[state[7]];
> > > 
> > > looks bad whitespace after that ^
> > > 
> > > > +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

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 01/14] Add AES crypto library
  2012-01-08 10:40         ` Marek Vasut
@ 2012-01-08 16:35           ` Simon Glass
  0 siblings, 0 replies; 51+ messages in thread
From: Simon Glass @ 2012-01-08 16:35 UTC (permalink / raw)
  To: u-boot

Hi Marek,

On Sun, Jan 8, 2012 at 2:40 AM, Marek Vasut <marek.vasut@gmail.com> wrote:
>> On Sunday 08 January 2012 03:57:47 Marek Vasut wrote:
>> > > On Monday 26 December 2011 14:32:54 Simon Glass wrote:
>> > > > --- /dev/null
>> > > > +++ b/lib/aes.c
>> > > >
>> > > > +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
>> > >
>> > > > +static void mix_sub_columns(u8 *state)
>> > > > +{
>> > > > ...
>> > > > + ? ? ? ? ? ? ? ?x3_sbox[state[2]] ^ ? ? ? sbox[state[7]];
>> > >
>> > > looks bad whitespace after that ^
>> > >
>> > > > +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.

>>
>> i don't think checkpatch catches const

Nope.

>> -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

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

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 03/14] tegra: Add crypto library for warmboot code
  2012-01-08  5:51   ` Mike Frysinger
@ 2012-01-08 16:42     ` Simon Glass
  0 siblings, 0 replies; 51+ messages in thread
From: Simon Glass @ 2012-01-08 16:42 UTC (permalink / raw)
  To: u-boot

Hi Mike,

On Sat, Jan 7, 2012 at 9:51 PM, Mike Frysinger <vapier@gentoo.org> wrote:
> On Monday 26 December 2011 14:32:56 Simon Glass wrote:
>> --- /dev/null
>> +++ b/arch/arm/cpu/armv7/tegra2/crypto.c
>>
>> +#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
>
> 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

> -mike

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 05/14] tegra: Add tegra_get_chip_type() to detect SKU
  2011-12-26 19:32 ` [U-Boot] [PATCH 05/14] tegra: Add tegra_get_chip_type() to detect SKU Simon Glass
@ 2012-01-09 23:24   ` Stephen Warren
  2012-01-12 19:35     ` Simon Glass
  0 siblings, 1 reply; 51+ messages in thread
From: Stephen Warren @ 2012-01-09 23:24 UTC (permalink / raw)
  To: u-boot

On 12/26/2011 12:32 PM, Simon Glass wrote:
> 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.
...
> diff --git a/arch/arm/cpu/armv7/tegra2/ap20.c b/arch/arm/cpu/armv7/tegra2/ap20.c
...
> +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.

-- 
nvpublic

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 06/14] tegra: Add EMC support for optimal memory timings
  2011-12-26 19:32 ` [U-Boot] [PATCH 06/14] tegra: Add EMC support for optimal memory timings Simon Glass
@ 2012-01-09 23:38   ` Stephen Warren
  2012-01-12 20:43     ` Simon Glass
  0 siblings, 1 reply; 51+ messages in thread
From: Stephen Warren @ 2012-01-09 23:38 UTC (permalink / raw)
  To: u-boot

On 12/26/2011 12:32 PM, Simon Glass wrote:
> From: Jimmy Zhang <jimmzhang@nvidia.com>
> 
> Add support for setting up the memory controller parameters. Boards
> can call tegra_set_emc() with a table containing the required
> parameters.
...
> diff --git a/arch/arm/cpu/armv7/tegra2/emc.c b/arch/arm/cpu/armv7/tegra2/emc.c
...
> +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.

> +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/

> +/* 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)
...
> +int tegra_set_emc(const struct tegra_emc_table *table, int table_size)
...
> +       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?

-- 
nvpublic

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 07/14] tegra: Add PMU to manage power supplies
  2011-12-26 19:33 ` [U-Boot] [PATCH 07/14] tegra: Add PMU to manage power supplies Simon Glass
@ 2012-01-10 17:56   ` Stephen Warren
  2012-01-12 23:17     ` Simon Glass
  0 siblings, 1 reply; 51+ messages in thread
From: Stephen Warren @ 2012-01-10 17:56 UTC (permalink / raw)
  To: u-boot

On 12/26/2011 12:33 PM, Simon Glass wrote:
> From: Jimmy Zhang <jimmzhang@nvidia.com>
> 
> 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.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>  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.

-- 
nvpublic

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 08/14] tegra: Set up PMU for Nvidia boards
  2011-12-26 19:33 ` [U-Boot] [PATCH 08/14] tegra: Set up PMU for Nvidia boards Simon Glass
@ 2012-01-10 18:02   ` Stephen Warren
  2012-01-12 23:42     ` Simon Glass
  0 siblings, 1 reply; 51+ messages in thread
From: Stephen Warren @ 2012-01-10 18:02 UTC (permalink / raw)
  To: u-boot

On 12/26/2011 12:33 PM, Simon Glass wrote:
> Adjust PMU to permit maximum frequency operation.
...
> diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c
...
> +#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?

-- 
nvpublic

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 09/14] tegra: Add warmboot implementation
  2011-12-26 19:33 ` [U-Boot] [PATCH 09/14] tegra: Add warmboot implementation Simon Glass
@ 2012-01-10 18:30   ` Stephen Warren
  2012-01-13 19:34     ` Simon Glass
  0 siblings, 1 reply; 51+ messages in thread
From: Stephen Warren @ 2012-01-10 18:30 UTC (permalink / raw)
  To: u-boot

On 12/26/2011 12:33 PM, Simon Glass wrote:
> From: Yen Lin <yelin@nvidia.com>
> 
> Add code to set up the warm boot area in the Tegra CPU ready for a
> resume after suspend.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>

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.

> diff --git a/arch/arm/cpu/armv7/tegra2/Makefile b/arch/arm/cpu/armv7/tegra2/Makefile
...
> -SOBJS  := lowlevel_init.o
> +SOBJS-y        := lowlevel_init.o
...
> +SOBJS  := $(SOBJS-y)

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

> diff --git a/arch/arm/cpu/armv7/tegra2/warmboot.c b/arch/arm/cpu/armv7/tegra2/warmboot.c
...
> +#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.

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

> +/* 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.

> +int warmboot_prepare_code(u32 seg_address, u32 seg_length)
...
> +       /*
> +        * 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.

...
> +       /* Populate the random_aes_block as requested. */
> +       {
> +               u32 *aes_block = (u32 *)&(dst_header->random_aes_block);
> +               u32 *end = (u32 *)(((u32)aes_block) +
> +                                  sizeof(dst_header->random_aes_block));
> +
> +               do {
> +#if defined(RANDOM_AES_BLOCK_IS_RANDOM)
> +                       *aes_block++ = query_random_seed();
> +#elif defined(RANDOM_AES_BLOCK_IS_PATTERN)
> +                       *aes_block++ = RANDOM_AES_BLOCK_IS_PATTERN;
> +#elif defined(RANDOM_AES_BLOCK_IS_ZERO)
> +                       *aes_block++ = 0;
> +#else
> +                       printf("None of RANDOM_AES_BLOCK_IS_XXX is defined; ");
> +                       printf("Default to pattern 0.\n");
> +                       *aes_block++ = 0;
> +#endif

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?

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

> diff --git a/arch/arm/cpu/armv7/tegra2/warmboot_avp.c b/arch/arm/cpu/armv7/tegra2/warmboot_avp.c
...
> +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 */
> +       );
> +
> +       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).

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

> diff --git a/arch/arm/include/asm/arch-tegra2/warmboot.h b/arch/arm/include/asm/arch-tegra2/warmboot.h
...
> +/*
> + * 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/ ?

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

-- 
nvpublic

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 12/14] tegra: Set vdd_core and vdd_cpu to high
  2011-12-26 19:33 ` [U-Boot] [PATCH 12/14] tegra: Set vdd_core and vdd_cpu to high Simon Glass
@ 2012-01-10 18:40   ` Stephen Warren
  2012-01-13 17:55     ` Simon Glass
  0 siblings, 1 reply; 51+ messages in thread
From: Stephen Warren @ 2012-01-10 18:40 UTC (permalink / raw)
  To: u-boot

On 12/26/2011 12:33 PM, Simon Glass wrote:
> From: Jimmy Zhang <jimmzhang@nvidia.com>
> 
> 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?

> diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c
...
>  /*
> + * 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
> +}

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

-- 
nvpublic

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 13/14] tegra: Add EMC settings for Seaboard, Harmony
  2011-12-26 19:33 ` [U-Boot] [PATCH 13/14] tegra: Add EMC settings for Seaboard, Harmony Simon Glass
@ 2012-01-10 18:46   ` Stephen Warren
  2012-01-12 23:05     ` Simon Glass
  0 siblings, 1 reply; 51+ messages in thread
From: Stephen Warren @ 2012-01-10 18:46 UTC (permalink / raw)
  To: u-boot

On 12/26/2011 12:33 PM, Simon Glass wrote:
> From: Jimmy Zhang <jimmzhang@nvidia.com>
> 
> Set Seaboard and Harmony to optimal memory settings based on the SOC
> in use (T20 or T25).
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>

> diff --git a/board/nvidia/common/emc.c b/board/nvidia/common/emc.c
...
> +static const struct tegra_emc_table seaboard_emc_tables_hynix_333Mhz[] = {
...
> +static const struct tegra_emc_table seaboard_emc_tables_hynix_380Mhz[] = {
...
> +void seaboard_emc_init(void)
...
> +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.

> +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?

-- 
nvpublic

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 05/14] tegra: Add tegra_get_chip_type() to detect SKU
  2012-01-09 23:24   ` Stephen Warren
@ 2012-01-12 19:35     ` Simon Glass
  2012-01-12 19:48       ` Stephen Warren
  0 siblings, 1 reply; 51+ messages in thread
From: Simon Glass @ 2012-01-12 19:35 UTC (permalink / raw)
  To: u-boot

Hi Stephen,

On Mon, Jan 9, 2012 at 3:24 PM, Stephen Warren <swarren@nvidia.com> wrote:
> On 12/26/2011 12:32 PM, Simon Glass wrote:
>> 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.
> ...
>> diff --git a/arch/arm/cpu/armv7/tegra2/ap20.c b/arch/arm/cpu/armv7/tegra2/ap20.c
> ...
>> +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.

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

Regards,
Simon

>
> --
> nvpublic

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 05/14] tegra: Add tegra_get_chip_type() to detect SKU
  2012-01-12 19:35     ` Simon Glass
@ 2012-01-12 19:48       ` Stephen Warren
  2012-01-13 21:06         ` Simon Glass
  0 siblings, 1 reply; 51+ messages in thread
From: Stephen Warren @ 2012-01-12 19:48 UTC (permalink / raw)
  To: u-boot

Simon Glass wrote at Thursday, January 12, 2012 12:36 PM:
> On Mon, Jan 9, 2012 at 3:24 PM, Stephen Warren <swarren@nvidia.com> wrote:
> > On 12/26/2011 12:32 PM, Simon Glass wrote:
...
> > 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_*.

-- 
nvpublic

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 06/14] tegra: Add EMC support for optimal memory timings
  2012-01-09 23:38   ` Stephen Warren
@ 2012-01-12 20:43     ` Simon Glass
  2012-01-13 17:47       ` Simon Glass
  0 siblings, 1 reply; 51+ messages in thread
From: Simon Glass @ 2012-01-12 20:43 UTC (permalink / raw)
  To: u-boot

Hi Stephen,

On Mon, Jan 9, 2012 at 3:38 PM, Stephen Warren <swarren@nvidia.com> wrote:
> On 12/26/2011 12:32 PM, Simon Glass wrote:
>> From: Jimmy Zhang <jimmzhang@nvidia.com>
>>
>> Add support for setting up the memory controller parameters. Boards
>> can call tegra_set_emc() with a table containing the required
>> parameters.
> ...
>> diff --git a/arch/arm/cpu/armv7/tegra2/emc.c b/arch/arm/cpu/armv7/tegra2/emc.c
> ...
>> +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.

>
>> +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.

>
>> +/* 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)
> ...
>> +int tegra_set_emc(const struct tegra_emc_table *table, int table_size)
> ...
>> + ? ? ? 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.

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

>
> 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

>
> --
> nvpublic

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 13/14] tegra: Add EMC settings for Seaboard, Harmony
  2012-01-10 18:46   ` Stephen Warren
@ 2012-01-12 23:05     ` Simon Glass
  2012-01-12 23:42       ` Stephen Warren
  0 siblings, 1 reply; 51+ messages in thread
From: Simon Glass @ 2012-01-12 23:05 UTC (permalink / raw)
  To: u-boot

Hi Stephen,

On Tue, Jan 10, 2012 at 10:46 AM, Stephen Warren <swarren@nvidia.com> wrote:
> On 12/26/2011 12:33 PM, Simon Glass wrote:
>> From: Jimmy Zhang <jimmzhang@nvidia.com>
>>
>> Set Seaboard and Harmony to optimal memory settings based on the SOC
>> in use (T20 or T25).
>>
>> Signed-off-by: Simon Glass <sjg@chromium.org>
>
>> diff --git a/board/nvidia/common/emc.c b/board/nvidia/common/emc.c
> ...
>> +static const struct tegra_emc_table seaboard_emc_tables_hynix_333Mhz[] = {
> ...
>> +static const struct tegra_emc_table seaboard_emc_tables_hynix_380Mhz[] = {
> ...
>> +void seaboard_emc_init(void)
> ...
>> +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.

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

Updated the commit description :-)

>
>> +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.

>
> 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.

> 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

>
> --
> nvpublic

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 07/14] tegra: Add PMU to manage power supplies
  2012-01-10 17:56   ` Stephen Warren
@ 2012-01-12 23:17     ` Simon Glass
  2012-01-12 23:43       ` Stephen Warren
  0 siblings, 1 reply; 51+ messages in thread
From: Simon Glass @ 2012-01-12 23:17 UTC (permalink / raw)
  To: u-boot

Hi Stephen,

On Tue, Jan 10, 2012 at 9:56 AM, Stephen Warren <swarren@nvidia.com> wrote:
> On 12/26/2011 12:33 PM, Simon Glass wrote:
>> From: Jimmy Zhang <jimmzhang@nvidia.com>
>>
>> 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.
>>
>> Signed-off-by: Simon Glass <sjg@chromium.org>
>> ---
>> ?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.

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

Regards,
Simon

>
> --
> nvpublic

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 13/14] tegra: Add EMC settings for Seaboard, Harmony
  2012-01-12 23:05     ` Simon Glass
@ 2012-01-12 23:42       ` Stephen Warren
  2012-01-12 23:54         ` Simon Glass
  0 siblings, 1 reply; 51+ messages in thread
From: Stephen Warren @ 2012-01-12 23:42 UTC (permalink / raw)
  To: u-boot

Simon Glass wrote at Thursday, January 12, 2012 4:05 PM:
> On Tue, Jan 10, 2012 at 10:46 AM, Stephen Warren <swarren@nvidia.com> wrote:
> > On 12/26/2011 12:33 PM, Simon Glass wrote:
> >> From: Jimmy Zhang <jimmzhang@nvidia.com>
> >>
> >> Set Seaboard and Harmony to optimal memory settings based on the SOC
> >> in use (T20 or T25).
...
> >> +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.
> 
> > 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?

> > 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.

-- 
nvpublic

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 08/14] tegra: Set up PMU for Nvidia boards
  2012-01-10 18:02   ` Stephen Warren
@ 2012-01-12 23:42     ` Simon Glass
  0 siblings, 0 replies; 51+ messages in thread
From: Simon Glass @ 2012-01-12 23:42 UTC (permalink / raw)
  To: u-boot

Hi Stephen,

On Tue, Jan 10, 2012 at 10:02 AM, Stephen Warren <swarren@nvidia.com> wrote:
> On 12/26/2011 12:33 PM, Simon Glass wrote:
>> Adjust PMU to permit maximum frequency operation.
> ...
>> diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c
> ...
>> +#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

>
> --
> nvpublic

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 07/14] tegra: Add PMU to manage power supplies
  2012-01-12 23:17     ` Simon Glass
@ 2012-01-12 23:43       ` Stephen Warren
  2012-01-12 23:55         ` Simon Glass
  0 siblings, 1 reply; 51+ messages in thread
From: Stephen Warren @ 2012-01-12 23:43 UTC (permalink / raw)
  To: u-boot

Simon Glass wrote at Thursday, January 12, 2012 4:17 PM:
> On Tue, Jan 10, 2012 at 9:56 AM, Stephen Warren <swarren@nvidia.com> wrote:
> > On 12/26/2011 12:33 PM, Simon Glass wrote:
> >> From: Jimmy Zhang <jimmzhang@nvidia.com>
> >>
> >> 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.
> >>
> >> Signed-off-by: Simon Glass <sjg@chromium.org>
> >> ---
> >> ?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.
> 
> 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".

-- 
nvpublic

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 13/14] tegra: Add EMC settings for Seaboard, Harmony
  2012-01-12 23:42       ` Stephen Warren
@ 2012-01-12 23:54         ` Simon Glass
  2012-01-13  0:01           ` Stephen Warren
  0 siblings, 1 reply; 51+ messages in thread
From: Simon Glass @ 2012-01-12 23:54 UTC (permalink / raw)
  To: u-boot

Hi Stephen,

On Thu, Jan 12, 2012 at 3:42 PM, Stephen Warren <swarren@nvidia.com> wrote:
> Simon Glass wrote at Thursday, January 12, 2012 4:05 PM:
>> On Tue, Jan 10, 2012 at 10:46 AM, Stephen Warren <swarren@nvidia.com> wrote:
>> > On 12/26/2011 12:33 PM, Simon Glass wrote:
>> >> From: Jimmy Zhang <jimmzhang@nvidia.com>
>> >>
>> >> Set Seaboard and Harmony to optimal memory settings based on the SOC
>> >> in use (T20 or T25).
> ...
>> >> +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.
>>
>> > 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?

We call board_emc_init() after pmu_set_nominal().

>
> 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
>

>> > 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.

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

Regards,
Simon

>
> --
> nvpublic
>

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 07/14] tegra: Add PMU to manage power supplies
  2012-01-12 23:43       ` Stephen Warren
@ 2012-01-12 23:55         ` Simon Glass
  0 siblings, 0 replies; 51+ messages in thread
From: Simon Glass @ 2012-01-12 23:55 UTC (permalink / raw)
  To: u-boot

Hi Stephen,

On Thu, Jan 12, 2012 at 3:43 PM, Stephen Warren <swarren@nvidia.com> wrote:
> Simon Glass wrote at Thursday, January 12, 2012 4:17 PM:
>> On Tue, Jan 10, 2012 at 9:56 AM, Stephen Warren <swarren@nvidia.com> wrote:
>> > On 12/26/2011 12:33 PM, Simon Glass wrote:
>> >> From: Jimmy Zhang <jimmzhang@nvidia.com>
>> >>
>> >> 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.
>> >>
>> >> Signed-off-by: Simon Glass <sjg@chromium.org>
>> >> ---
>> >> ?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.
>>
>> 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

>
> --
> nvpublic
>

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 13/14] tegra: Add EMC settings for Seaboard, Harmony
  2012-01-12 23:54         ` Simon Glass
@ 2012-01-13  0:01           ` Stephen Warren
  2012-01-13  0:05             ` Simon Glass
  0 siblings, 1 reply; 51+ messages in thread
From: Stephen Warren @ 2012-01-13  0:01 UTC (permalink / raw)
  To: u-boot

Simon Glass wrote at Thursday, January 12, 2012 4:55 PM:
> On Thu, Jan 12, 2012 at 3:42 PM, Stephen Warren <swarren@nvidia.com> wrote:
> > Simon Glass wrote at Thursday, January 12, 2012 4:05 PM:
> >> On Tue, Jan 10, 2012 at 10:46 AM, Stephen Warren <swarren@nvidia.com> wrote:
> >> > On 12/26/2011 12:33 PM, Simon Glass wrote:
> >> >> From: Jimmy Zhang <jimmzhang@nvidia.com>
> >> >>
> >> >> Set Seaboard and Harmony to optimal memory settings based on the SOC
> >> >> in use (T20 or T25).
> > ...
> >> >> +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.
> >>
> >> > 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?
> 
> We call board_emc_init() after pmu_set_nominal().
> 
> >
> > 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

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?

-- 
nvpublic

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 13/14] tegra: Add EMC settings for Seaboard, Harmony
  2012-01-13  0:01           ` Stephen Warren
@ 2012-01-13  0:05             ` Simon Glass
  2012-01-13  0:10               ` Stephen Warren
  0 siblings, 1 reply; 51+ messages in thread
From: Simon Glass @ 2012-01-13  0:05 UTC (permalink / raw)
  To: u-boot

Hi Stephen,

On Thu, Jan 12, 2012 at 4:01 PM, Stephen Warren <swarren@nvidia.com> wrote:
> Simon Glass wrote at Thursday, January 12, 2012 4:55 PM:
>> On Thu, Jan 12, 2012 at 3:42 PM, Stephen Warren <swarren@nvidia.com> wrote:
>> > Simon Glass wrote at Thursday, January 12, 2012 4:05 PM:
>> >> On Tue, Jan 10, 2012 at 10:46 AM, Stephen Warren <swarren@nvidia.com> wrote:
>> >> > On 12/26/2011 12:33 PM, Simon Glass wrote:
>> >> >> From: Jimmy Zhang <jimmzhang@nvidia.com>
>> >> >>
>> >> >> Set Seaboard and Harmony to optimal memory settings based on the SOC
>> >> >> in use (T20 or T25).
>> > ...
>> >> >> +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.
>> >>
>> >> > 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?
>>
>> We call board_emc_init() after pmu_set_nominal().
>>
>> >
>> > 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
>
> 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

>
> --
> nvpublic
>

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 13/14] tegra: Add EMC settings for Seaboard, Harmony
  2012-01-13  0:05             ` Simon Glass
@ 2012-01-13  0:10               ` Stephen Warren
  2012-01-13  0:18                 ` Simon Glass
  0 siblings, 1 reply; 51+ messages in thread
From: Stephen Warren @ 2012-01-13  0:10 UTC (permalink / raw)
  To: u-boot

Simon Glass wrote at Thursday, January 12, 2012 5:06 PM:
> On Thu, Jan 12, 2012 at 4:01 PM, Stephen Warren <swarren@nvidia.com> wrote:
> > Simon Glass wrote at Thursday, January 12, 2012 4:55 PM:
> >> On Thu, Jan 12, 2012 at 3:42 PM, Stephen Warren <swarren@nvidia.com> wrote:
> >> > Simon Glass wrote at Thursday, January 12, 2012 4:05 PM:
> >> >> On Tue, Jan 10, 2012 at 10:46 AM, Stephen Warren <swarren@nvidia.com> wrote:
> >> >> > On 12/26/2011 12:33 PM, Simon Glass wrote:
> >> >> >> From: Jimmy Zhang <jimmzhang@nvidia.com>
> >> >> >>
> >> >> >> Set Seaboard and Harmony to optimal memory settings based on the SOC
> >> >> >> in use (T20 or T25).
> >> > ...
> >> >> >> +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.
> >> >>
> >> >> > 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?
> >>
> >> We call board_emc_init() after pmu_set_nominal().
> >>
> >> >
> >> > 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
> >
> > 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?

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.

-- 
nvpublic

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 13/14] tegra: Add EMC settings for Seaboard, Harmony
  2012-01-13  0:10               ` Stephen Warren
@ 2012-01-13  0:18                 ` Simon Glass
  0 siblings, 0 replies; 51+ messages in thread
From: Simon Glass @ 2012-01-13  0:18 UTC (permalink / raw)
  To: u-boot

Hi Stephen,

On Thu, Jan 12, 2012 at 4:10 PM, Stephen Warren <swarren@nvidia.com> wrote:
> Simon Glass wrote at Thursday, January 12, 2012 5:06 PM:
>> On Thu, Jan 12, 2012 at 4:01 PM, Stephen Warren <swarren@nvidia.com> wrote:
>> > Simon Glass wrote at Thursday, January 12, 2012 4:55 PM:
>> >> On Thu, Jan 12, 2012 at 3:42 PM, Stephen Warren <swarren@nvidia.com> wrote:
>> >> > Simon Glass wrote at Thursday, January 12, 2012 4:05 PM:
>> >> >> On Tue, Jan 10, 2012 at 10:46 AM, Stephen Warren <swarren@nvidia.com> wrote:
>> >> >> > On 12/26/2011 12:33 PM, Simon Glass wrote:
>> >> >> >> From: Jimmy Zhang <jimmzhang@nvidia.com>
>> >> >> >>
>> >> >> >> Set Seaboard and Harmony to optimal memory settings based on the SOC
>> >> >> >> in use (T20 or T25).
>> >> > ...
>> >> >> >> +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.
>> >> >>
>> >> >> > 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?
>> >>
>> >> We call board_emc_init() after pmu_set_nominal().
>> >>
>> >> >
>> >> > 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
>> >
>> > 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?
>
> 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

>
> --
> nvpublic
>

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 06/14] tegra: Add EMC support for optimal memory timings
  2012-01-12 20:43     ` Simon Glass
@ 2012-01-13 17:47       ` Simon Glass
  0 siblings, 0 replies; 51+ messages in thread
From: Simon Glass @ 2012-01-13 17:47 UTC (permalink / raw)
  To: u-boot

Hi Stephen,

On Thu, Jan 12, 2012 at 12:43 PM, Simon Glass <sjg@chromium.org> wrote:
> Hi Stephen,
>
> On Mon, Jan 9, 2012 at 3:38 PM, Stephen Warren <swarren@nvidia.com> wrote:
>> On 12/26/2011 12:32 PM, Simon Glass wrote:
>>> From: Jimmy Zhang <jimmzhang@nvidia.com>
>>>
>>> Add support for setting up the memory controller parameters. Boards
>>> can call tegra_set_emc() with a table containing the required
>>> parameters.
>> ...
>>> diff --git a/arch/arm/cpu/armv7/tegra2/emc.c b/arch/arm/cpu/armv7/tegra2/emc.c
>> ...
>>> +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.
>
>>
>>> +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.
>
>>
>>> +/* 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)
>> ...
>>> +int tegra_set_emc(const struct tegra_emc_table *table, int table_size)
>> ...
>>> + ? ? ? 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.
>
> OK. It might be time to move this to the fdt, I will take a look.
>
>>
>> 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.

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

Regards,
Simon

>
> Regards,
> Simon
>
>>
>> --
>> nvpublic

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 12/14] tegra: Set vdd_core and vdd_cpu to high
  2012-01-10 18:40   ` Stephen Warren
@ 2012-01-13 17:55     ` Simon Glass
  0 siblings, 0 replies; 51+ messages in thread
From: Simon Glass @ 2012-01-13 17:55 UTC (permalink / raw)
  To: u-boot

Hi Stephen,

On Tue, Jan 10, 2012 at 10:40 AM, Stephen Warren <swarren@nvidia.com> wrote:
> On 12/26/2011 12:33 PM, Simon Glass wrote:
>> From: Jimmy Zhang <jimmzhang@nvidia.com>
>>
>> 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.

>
> 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?
>
>> diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c
> ...
>> ?/*
>> + * 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
>> +}
>
> 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

>
> --
> nvpublic

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 09/14] tegra: Add warmboot implementation
  2012-01-10 18:30   ` Stephen Warren
@ 2012-01-13 19:34     ` Simon Glass
  2012-01-13 22:04       ` Yen Lin
  0 siblings, 1 reply; 51+ messages in thread
From: Simon Glass @ 2012-01-13 19:34 UTC (permalink / raw)
  To: u-boot

Hi Stephen,

[Yen please can you read this also?]

On Tue, Jan 10, 2012 at 10:30 AM, Stephen Warren <swarren@nvidia.com> wrote:
> On 12/26/2011 12:33 PM, Simon Glass wrote:
>> From: Yen Lin <yelin@nvidia.com>
>>
>> Add code to set up the warm boot area in the Tegra CPU ready for a
>> resume after suspend.
>>
>> Signed-off-by: Simon Glass <sjg@chromium.org>
>
> 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.

>
> 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.
>
>> diff --git a/arch/arm/cpu/armv7/tegra2/Makefile b/arch/arm/cpu/armv7/tegra2/Makefile
> ...
>> -SOBJS ?:= lowlevel_init.o
>> +SOBJS-y ? ? ? ?:= lowlevel_init.o
> ...
>> +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.

>
>> diff --git a/arch/arm/cpu/armv7/tegra2/warmboot.c b/arch/arm/cpu/armv7/tegra2/warmboot.c
> ...
>> +#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.

>
>> +/*
>> + * 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

>
>> +/* 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.

Well I think I'll just punt this stuff.

>
>> +int warmboot_prepare_code(u32 seg_address, u32 seg_length)
> ...
>> + ? ? ? /*
>> + ? ? ? ?* 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.
>

Done

> ...
>> + ? ? ? /* Populate the random_aes_block as requested. */
>> + ? ? ? {
>> + ? ? ? ? ? ? ? u32 *aes_block = (u32 *)&(dst_header->random_aes_block);
>> + ? ? ? ? ? ? ? u32 *end = (u32 *)(((u32)aes_block) +
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?sizeof(dst_header->random_aes_block));
>> +
>> + ? ? ? ? ? ? ? do {
>> +#if defined(RANDOM_AES_BLOCK_IS_RANDOM)
>> + ? ? ? ? ? ? ? ? ? ? ? *aes_block++ = query_random_seed();
>> +#elif defined(RANDOM_AES_BLOCK_IS_PATTERN)
>> + ? ? ? ? ? ? ? ? ? ? ? *aes_block++ = RANDOM_AES_BLOCK_IS_PATTERN;
>> +#elif defined(RANDOM_AES_BLOCK_IS_ZERO)
>> + ? ? ? ? ? ? ? ? ? ? ? *aes_block++ = 0;
>> +#else
>> + ? ? ? ? ? ? ? ? ? ? ? printf("None of RANDOM_AES_BLOCK_IS_XXX is defined; ");
>> + ? ? ? ? ? ? ? ? ? ? ? printf("Default to pattern 0.\n");
>> + ? ? ? ? ? ? ? ? ? ? ? *aes_block++ = 0;
>> +#endif
>
> 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.

>
>> + ? ? ? ? ? ? ? } while (aes_block < end);
>> + ? ? ? }
>
>> diff --git a/arch/arm/cpu/armv7/tegra2/warmboot_avp.c b/arch/arm/cpu/armv7/tegra2/warmboot_avp.c
> ...
>> +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 */
>> + ? ? ? );
>> +
>> + ? ? ? 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.

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

>
> 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.

>
> 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.

>
>> diff --git a/arch/arm/include/asm/arch-tegra2/warmboot.h b/arch/arm/include/asm/arch-tegra2/warmboot.h
> ...
>> +/*
>> + * 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.

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

Regards,
Simon

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 05/14] tegra: Add tegra_get_chip_type() to detect SKU
  2012-01-12 19:48       ` Stephen Warren
@ 2012-01-13 21:06         ` Simon Glass
  0 siblings, 0 replies; 51+ messages in thread
From: Simon Glass @ 2012-01-13 21:06 UTC (permalink / raw)
  To: u-boot

Hi Stephen,

On Thu, Jan 12, 2012 at 11:48 AM, Stephen Warren <swarren@nvidia.com> wrote:
> Simon Glass wrote at Thursday, January 12, 2012 12:36 PM:
>> On Mon, Jan 9, 2012 at 3:24 PM, Stephen Warren <swarren@nvidia.com> wrote:
>> > On 12/26/2011 12:32 PM, Simon Glass wrote:
> ...
>> > 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_*.

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

Regards,
Simon

>
> --
> nvpublic
>

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 09/14] tegra: Add warmboot implementation
  2012-01-13 19:34     ` Simon Glass
@ 2012-01-13 22:04       ` Yen Lin
  2012-01-13 23:05         ` Simon Glass
  0 siblings, 1 reply; 51+ messages in thread
From: Yen Lin @ 2012-01-13 22:04 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Fri, 2012-01-13 at 11:34 -0800, Simon Glass wrote:
> Hi Stephen,
> 
> [Yen please can you read this also?]
> 
> On Tue, Jan 10, 2012 at 10:30 AM, Stephen Warren <swarren@nvidia.com> wrote:
> > On 12/26/2011 12:33 PM, Simon Glass wrote:
> >> From: Yen Lin <yelin@nvidia.com>
> >>
> >> Add code to set up the warm boot area in the Tegra CPU ready for a
> >> resume after suspend.
> >>
> >> Signed-off-by: Simon Glass <sjg@chromium.org>
> >
> > 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.
> 

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.
-----------------------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 09/14] tegra: Add warmboot implementation
  2012-01-13 22:04       ` Yen Lin
@ 2012-01-13 23:05         ` Simon Glass
  2012-01-13 23:08           ` Stephen Warren
  0 siblings, 1 reply; 51+ messages in thread
From: Simon Glass @ 2012-01-13 23:05 UTC (permalink / raw)
  To: u-boot

Hi Yen,

On Fri, Jan 13, 2012 at 2:04 PM, Yen Lin <yelin@nvidia.com> wrote:
> Hi Simon,
>
> On Fri, 2012-01-13 at 11:34 -0800, Simon Glass wrote:
>> Hi Stephen,
>>
>> [Yen please can you read this also?]
>>
>> On Tue, Jan 10, 2012 at 10:30 AM, Stephen Warren <swarren@nvidia.com> wrote:
>> > On 12/26/2011 12:33 PM, Simon Glass wrote:
>> >> From: Yen Lin <yelin@nvidia.com>
>> >>
>> >> Add code to set up the warm boot area in the Tegra CPU ready for a
>> >> resume after suspend.
>> >>
>> >> Signed-off-by: Simon Glass <sjg@chromium.org>
>> >
>> > 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.
>>
>
> 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

>
>
> 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.
> -----------------------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 09/14] tegra: Add warmboot implementation
  2012-01-13 23:05         ` Simon Glass
@ 2012-01-13 23:08           ` Stephen Warren
  2012-01-14  0:04             ` Yen Lin
  0 siblings, 1 reply; 51+ messages in thread
From: Stephen Warren @ 2012-01-13 23:08 UTC (permalink / raw)
  To: u-boot

On 01/13/2012 04:05 PM, Simon Glass wrote:
> On Fri, Jan 13, 2012 at 2:04 PM, Yen Lin <yelin@nvidia.com> wrote:
>> On Fri, 2012-01-13 at 11:34 -0800, Simon Glass wrote:
>>> On Tue, Jan 10, 2012 at 10:30 AM, Stephen Warren <swarren@nvidia.com> wrote:
>>>> On 12/26/2011 12:33 PM, Simon Glass wrote:
...
>>> 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.
> 
> 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?

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

-- 
nvpublic

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [U-Boot] [PATCH 09/14] tegra: Add warmboot implementation
  2012-01-13 23:08           ` Stephen Warren
@ 2012-01-14  0:04             ` Yen Lin
  0 siblings, 0 replies; 51+ messages in thread
From: Yen Lin @ 2012-01-14  0:04 UTC (permalink / raw)
  To: u-boot

On Fri, 2012-01-13 at 15:08 -0800, Stephen Warren wrote:
> On 01/13/2012 04:05 PM, Simon Glass wrote:
> > On Fri, Jan 13, 2012 at 2:04 PM, Yen Lin <yelin@nvidia.com> wrote:
> >> On Fri, 2012-01-13 at 11:34 -0800, Simon Glass wrote:
> >>> On Tue, Jan 10, 2012 at 10:30 AM, Stephen Warren <swarren@nvidia.com> wrote:
> >>>> On 12/26/2011 12:33 PM, Simon Glass wrote:
> ...
> >>> 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.
> > 
> > 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?
> 

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.

> > 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.
-----------------------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 51+ messages in thread

end of thread, other threads:[~2012-01-14  0:04 UTC | newest]

Thread overview: 51+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-12-26 19:32 [U-Boot] [PATCH 0/14] tegra: warmboot (suspend / resume) support Simon Glass
2011-12-26 19:32 ` [U-Boot] [PATCH 01/14] Add AES crypto library Simon Glass
2012-01-08  5:49   ` Mike Frysinger
2012-01-08  8:57     ` Marek Vasut
2012-01-08  9:09       ` Mike Frysinger
2012-01-08 10:40         ` Marek Vasut
2012-01-08 16:35           ` Simon Glass
2011-12-26 19:32 ` [U-Boot] [PATCH 02/14] tegra: Move ap20.h header into arch location Simon Glass
2011-12-26 19:32 ` [U-Boot] [PATCH 03/14] tegra: Add crypto library for warmboot code Simon Glass
2012-01-08  5:51   ` Mike Frysinger
2012-01-08 16:42     ` Simon Glass
2011-12-26 19:32 ` [U-Boot] [PATCH 04/14] tegra: Add flow, gp_padctl, fuse, sdram headers Simon Glass
2011-12-26 19:32 ` [U-Boot] [PATCH 05/14] tegra: Add tegra_get_chip_type() to detect SKU Simon Glass
2012-01-09 23:24   ` Stephen Warren
2012-01-12 19:35     ` Simon Glass
2012-01-12 19:48       ` Stephen Warren
2012-01-13 21:06         ` Simon Glass
2011-12-26 19:32 ` [U-Boot] [PATCH 06/14] tegra: Add EMC support for optimal memory timings Simon Glass
2012-01-09 23:38   ` Stephen Warren
2012-01-12 20:43     ` Simon Glass
2012-01-13 17:47       ` Simon Glass
2011-12-26 19:33 ` [U-Boot] [PATCH 07/14] tegra: Add PMU to manage power supplies Simon Glass
2012-01-10 17:56   ` Stephen Warren
2012-01-12 23:17     ` Simon Glass
2012-01-12 23:43       ` Stephen Warren
2012-01-12 23:55         ` Simon Glass
2011-12-26 19:33 ` [U-Boot] [PATCH 08/14] tegra: Set up PMU for Nvidia boards Simon Glass
2012-01-10 18:02   ` Stephen Warren
2012-01-12 23:42     ` Simon Glass
2011-12-26 19:33 ` [U-Boot] [PATCH 09/14] tegra: Add warmboot implementation Simon Glass
2012-01-10 18:30   ` Stephen Warren
2012-01-13 19:34     ` Simon Glass
2012-01-13 22:04       ` Yen Lin
2012-01-13 23:05         ` Simon Glass
2012-01-13 23:08           ` Stephen Warren
2012-01-14  0:04             ` Yen Lin
2011-12-26 19:33 ` [U-Boot] [PATCH 10/14] tegra: Setup PMC scratch info from ap20 setup Simon Glass
2011-12-26 19:33 ` [U-Boot] [PATCH 11/14] tegra: Set up warmboot code on Nvidia boards Simon Glass
2011-12-26 19:33 ` [U-Boot] [PATCH 12/14] tegra: Set vdd_core and vdd_cpu to high Simon Glass
2012-01-10 18:40   ` Stephen Warren
2012-01-13 17:55     ` Simon Glass
2011-12-26 19:33 ` [U-Boot] [PATCH 13/14] tegra: Add EMC settings for Seaboard, Harmony Simon Glass
2012-01-10 18:46   ` Stephen Warren
2012-01-12 23:05     ` Simon Glass
2012-01-12 23:42       ` Stephen Warren
2012-01-12 23:54         ` Simon Glass
2012-01-13  0:01           ` Stephen Warren
2012-01-13  0:05             ` Simon Glass
2012-01-13  0:10               ` Stephen Warren
2012-01-13  0:18                 ` Simon Glass
2011-12-26 19:33 ` [U-Boot] [PATCH 14/14] tegra: Enable LP0 on Seaboard Simon Glass

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.