summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVenu Byravarasu <vbyravarasu@nvidia.com>2010-05-17 11:30:37 +0530
committerGary King <gking@nvidia.com>2010-05-17 11:38:48 -0700
commit7babb616e672128db7ec4a3efa8fbe0c09fed1b5 (patch)
treef55d88e06805192f334ecc4b93461accd6380e0a
parentb8a0f3f1d92e521fb517219daa5083363a4a57e0 (diff)
tegra-kernel-fuse: Add fuse burning support from Linux via sysfs
A fuse module is added to support programming and reading back fuse values. This module is built as part of kernel. Bug 657504 Tested on: Whistler Change-Id: I5663679c8d41834aa4077e9940a0595f6575af64 Reviewed-on: http://git-master/r/1259 Reviewed-by: Andy Carman <acarman@nvidia.com> Tested-by: Andy Carman <acarman@nvidia.com> Reviewed-by: Gary King <gking@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/Makefile2
-rw-r--r--arch/arm/mach-tegra/include/fuse_bitmap.h787
-rw-r--r--arch/arm/mach-tegra/include/nvddk_bootdevices.h90
-rw-r--r--arch/arm/mach-tegra/include/nvddk_fuse.h423
-rw-r--r--arch/arm/mach-tegra/include/nvddk_operatingmodes.h70
-rw-r--r--arch/arm/mach-tegra/include/nvodm_query_discovery.h34
-rw-r--r--arch/arm/mach-tegra/nvddk/Makefile2
-rw-r--r--arch/arm/mach-tegra/nvddk/nvddk_fuse_ap20.c1642
-rw-r--r--arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b.c63
-rw-r--r--arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_supply_info_table.h10
-rw-r--r--arch/arm/mach-tegra/odm_kit/query/whistler/subboards/nvodm_query_discovery_e1116_addresses.h85
-rw-r--r--arch/arm/mach-tegra/odm_kit/query/whistler/subboards/nvodm_query_discovery_e1116_peripherals.h12
-rw-r--r--arch/arm/mach-tegra/sysfs-fuse.c481
13 files changed, 3635 insertions, 66 deletions
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 4dc32e649534..ff1f43f22259 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -8,7 +8,6 @@ ccflags-y += -DNV_DEBUG=0
endif
ccflags-y += -Iarch/arm/mach-tegra/nvrm/core/common
-
# Mandatory components
obj-y += clock.o
obj-y += io.o
@@ -18,6 +17,7 @@ obj-y += pinmux-t2-tables.o
obj-y += pinmux.o
obj-y += timer.o
obj-y += tegra_sysmap.o
+obj-y += sysfs-fuse.o
# IOVMM support
obj-$(CONFIG_TEGRA_IOVMM_GART) += iovmm-gart.o
diff --git a/arch/arm/mach-tegra/include/fuse_bitmap.h b/arch/arm/mach-tegra/include/fuse_bitmap.h
new file mode 100644
index 000000000000..38b09541862e
--- /dev/null
+++ b/arch/arm/mach-tegra/include/fuse_bitmap.h
@@ -0,0 +1,787 @@
+/*
+ * Copyright (c) 2010 NVIDIA Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NVIDIA Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+// ****************************************************************
+// This file is automatically generated by FUSEGEN. Do NOT modify.
+// ****************************************************************
+#define FUSE_ENABLE_FUSE_PROGRAM__WIDTH 1
+#define FUSE_ENABLE_FUSE_PROGRAM__PRI_ALIAS_0 0x0
+#define FUSE_ENABLE_FUSE_PROGRAM__PRI_ALIAS_0_DATA 0:0
+#define FUSE_ENABLE_FUSE_PROGRAM__PRI_ALIAS_0_WIDTH 1
+#define FUSE_ENABLE_FUSE_PROGRAM__RED_ALIAS_0 0x1
+#define FUSE_ENABLE_FUSE_PROGRAM__RED_ALIAS_0_DATA 0:0
+#define FUSE_ENABLE_FUSE_PROGRAM__RED_ALIAS_0_WIDTH 1
+
+#define FUSE_DISABLE_FUSE_PROGRAM__WIDTH 1
+#define FUSE_DISABLE_FUSE_PROGRAM__PRI_ALIAS_0 0x0
+#define FUSE_DISABLE_FUSE_PROGRAM__PRI_ALIAS_0_DATA 1:1
+#define FUSE_DISABLE_FUSE_PROGRAM__PRI_ALIAS_0_WIDTH 1
+#define FUSE_DISABLE_FUSE_PROGRAM__RED_ALIAS_0 0x1
+#define FUSE_DISABLE_FUSE_PROGRAM__RED_ALIAS_0_DATA 1:1
+#define FUSE_DISABLE_FUSE_PROGRAM__RED_ALIAS_0_WIDTH 1
+
+#define FUSE_BYPASS_FUSES__WIDTH 1
+#define FUSE_BYPASS_FUSES__PRI_ALIAS_0 0x0
+#define FUSE_BYPASS_FUSES__PRI_ALIAS_0_DATA 2:2
+#define FUSE_BYPASS_FUSES__PRI_ALIAS_0_WIDTH 1
+#define FUSE_BYPASS_FUSES__RED_ALIAS_0 0x1
+#define FUSE_BYPASS_FUSES__RED_ALIAS_0_DATA 2:2
+#define FUSE_BYPASS_FUSES__RED_ALIAS_0_WIDTH 1
+
+#define FUSE_JTAG_DIRECT_ACCESS_DISABLE__WIDTH 1
+#define FUSE_JTAG_DIRECT_ACCESS_DISABLE__PRI_ALIAS_0 0x0
+#define FUSE_JTAG_DIRECT_ACCESS_DISABLE__PRI_ALIAS_0_DATA 3:3
+#define FUSE_JTAG_DIRECT_ACCESS_DISABLE__PRI_ALIAS_0_WIDTH 1
+#define FUSE_JTAG_DIRECT_ACCESS_DISABLE__RED_ALIAS_0 0x1
+#define FUSE_JTAG_DIRECT_ACCESS_DISABLE__RED_ALIAS_0_DATA 3:3
+#define FUSE_JTAG_DIRECT_ACCESS_DISABLE__RED_ALIAS_0_WIDTH 1
+
+#define FUSE_RAMREPAIR_CHAIN_1_SIZE__WIDTH 16
+#define FUSE_RAMREPAIR_CHAIN_1_SIZE__PRI_ALIAS_0 0x0
+#define FUSE_RAMREPAIR_CHAIN_1_SIZE__PRI_ALIAS_0_DATA 19:4
+#define FUSE_RAMREPAIR_CHAIN_1_SIZE__PRI_ALIAS_0_WIDTH 16
+#define FUSE_RAMREPAIR_CHAIN_1_SIZE__RED_ALIAS_0 0x1
+#define FUSE_RAMREPAIR_CHAIN_1_SIZE__RED_ALIAS_0_DATA 19:4
+#define FUSE_RAMREPAIR_CHAIN_1_SIZE__RED_ALIAS_0_WIDTH 16
+
+#define FUSE_PRODUCTION_MODE__WIDTH 1
+#define FUSE_PRODUCTION_MODE__PRI_ALIAS_0 0x0
+#define FUSE_PRODUCTION_MODE__PRI_ALIAS_0_DATA 20:20
+#define FUSE_PRODUCTION_MODE__PRI_ALIAS_0_WIDTH 1
+#define FUSE_PRODUCTION_MODE__RED_ALIAS_0 0x1
+#define FUSE_PRODUCTION_MODE__RED_ALIAS_0_DATA 20:20
+#define FUSE_PRODUCTION_MODE__RED_ALIAS_0_WIDTH 1
+
+#define FUSE_JTAG_SECUREID_VALID__WIDTH 1
+#define FUSE_JTAG_SECUREID_VALID__PRI_ALIAS_0 0x0
+#define FUSE_JTAG_SECUREID_VALID__PRI_ALIAS_0_DATA 21:21
+#define FUSE_JTAG_SECUREID_VALID__PRI_ALIAS_0_WIDTH 1
+#define FUSE_JTAG_SECUREID_VALID__RED_ALIAS_0 0x1
+#define FUSE_JTAG_SECUREID_VALID__RED_ALIAS_0_DATA 21:21
+#define FUSE_JTAG_SECUREID_VALID__RED_ALIAS_0_WIDTH 1
+
+#define FUSE_FA__WIDTH 1
+#define FUSE_FA__PRI_ALIAS_0 0x0
+#define FUSE_FA__PRI_ALIAS_0_DATA 22:22
+#define FUSE_FA__PRI_ALIAS_0_WIDTH 1
+#define FUSE_FA__RED_ALIAS_0 0x1
+#define FUSE_FA__RED_ALIAS_0_DATA 22:22
+#define FUSE_FA__RED_ALIAS_0_WIDTH 1
+
+#define FUSE_SECURITY_MODE__WIDTH 1
+#define FUSE_SECURITY_MODE__PRI_ALIAS_0 0x0
+#define FUSE_SECURITY_MODE__PRI_ALIAS_0_DATA 23:23
+#define FUSE_SECURITY_MODE__PRI_ALIAS_0_WIDTH 1
+#define FUSE_SECURITY_MODE__RED_ALIAS_0 0x1
+#define FUSE_SECURITY_MODE__RED_ALIAS_0_DATA 23:23
+#define FUSE_SECURITY_MODE__RED_ALIAS_0_WIDTH 1
+
+#define FUSE_ARM_DEBUG_DIS__WIDTH 1
+#define FUSE_ARM_DEBUG_DIS__PRI_ALIAS_0 0x0
+#define FUSE_ARM_DEBUG_DIS__PRI_ALIAS_0_DATA 24:24
+#define FUSE_ARM_DEBUG_DIS__PRI_ALIAS_0_WIDTH 1
+#define FUSE_ARM_DEBUG_DIS__RED_ALIAS_0 0x1
+#define FUSE_ARM_DEBUG_DIS__RED_ALIAS_0_DATA 24:24
+#define FUSE_ARM_DEBUG_DIS__RED_ALIAS_0_WIDTH 1
+
+#define FUSE_OBS_DIS__WIDTH 1
+#define FUSE_OBS_DIS__PRI_ALIAS_0 0x0
+#define FUSE_OBS_DIS__PRI_ALIAS_0_DATA 25:25
+#define FUSE_OBS_DIS__PRI_ALIAS_0_WIDTH 1
+#define FUSE_OBS_DIS__RED_ALIAS_0 0x1
+#define FUSE_OBS_DIS__RED_ALIAS_0_DATA 25:25
+#define FUSE_OBS_DIS__RED_ALIAS_0_WIDTH 1
+
+#define FUSE_JTAG_SECUREID_0__WIDTH 32
+#define FUSE_JTAG_SECUREID_0__PRI_ALIAS_0 0x2
+#define FUSE_JTAG_SECUREID_0__PRI_ALIAS_0_DATA 31:0
+#define FUSE_JTAG_SECUREID_0__PRI_ALIAS_0_WIDTH 32
+#define FUSE_JTAG_SECUREID_0__RED_ALIAS_0 0x3
+#define FUSE_JTAG_SECUREID_0__RED_ALIAS_0_DATA 31:0
+#define FUSE_JTAG_SECUREID_0__RED_ALIAS_0_WIDTH 32
+
+#define FUSE_JTAG_SECUREID_1__WIDTH 32
+#define FUSE_JTAG_SECUREID_1__PRI_ALIAS_0 0x4
+#define FUSE_JTAG_SECUREID_1__PRI_ALIAS_0_DATA 31:0
+#define FUSE_JTAG_SECUREID_1__PRI_ALIAS_0_WIDTH 32
+#define FUSE_JTAG_SECUREID_1__RED_ALIAS_0 0x5
+#define FUSE_JTAG_SECUREID_1__RED_ALIAS_0_DATA 31:0
+#define FUSE_JTAG_SECUREID_1__RED_ALIAS_0_WIDTH 32
+
+#define FUSE_SKU_INFO__WIDTH 8
+#define FUSE_SKU_INFO__PRI_ALIAS_0 0x6
+#define FUSE_SKU_INFO__PRI_ALIAS_0_DATA 7:0
+#define FUSE_SKU_INFO__PRI_ALIAS_0_WIDTH 8
+#define FUSE_SKU_INFO__RED_ALIAS_0 0x7
+#define FUSE_SKU_INFO__RED_ALIAS_0_DATA 7:0
+#define FUSE_SKU_INFO__RED_ALIAS_0_WIDTH 8
+
+#define FUSE_PROCESS_CALIB__WIDTH 2
+#define FUSE_PROCESS_CALIB__PRI_ALIAS_0 0x6
+#define FUSE_PROCESS_CALIB__PRI_ALIAS_0_DATA 9:8
+#define FUSE_PROCESS_CALIB__PRI_ALIAS_0_WIDTH 2
+#define FUSE_PROCESS_CALIB__RED_ALIAS_0 0x7
+#define FUSE_PROCESS_CALIB__RED_ALIAS_0_DATA 9:8
+#define FUSE_PROCESS_CALIB__RED_ALIAS_0_WIDTH 2
+
+#define FUSE_IO_CALIB__WIDTH 10
+#define FUSE_IO_CALIB__PRI_ALIAS_0 0x6
+#define FUSE_IO_CALIB__PRI_ALIAS_0_DATA 19:10
+#define FUSE_IO_CALIB__PRI_ALIAS_0_WIDTH 10
+#define FUSE_IO_CALIB__RED_ALIAS_0 0x7
+#define FUSE_IO_CALIB__RED_ALIAS_0_DATA 19:10
+#define FUSE_IO_CALIB__RED_ALIAS_0_WIDTH 10
+
+#define FUSE_DAC_CRT_CALIB__WIDTH 8
+#define FUSE_DAC_CRT_CALIB__PRI_ALIAS_0 0x6
+#define FUSE_DAC_CRT_CALIB__PRI_ALIAS_0_DATA 27:20
+#define FUSE_DAC_CRT_CALIB__PRI_ALIAS_0_WIDTH 8
+#define FUSE_DAC_CRT_CALIB__RED_ALIAS_0 0x7
+#define FUSE_DAC_CRT_CALIB__RED_ALIAS_0_DATA 27:20
+#define FUSE_DAC_CRT_CALIB__RED_ALIAS_0_WIDTH 8
+
+#define FUSE_DAC_HDTV_CALIB__WIDTH 8
+#define FUSE_DAC_HDTV_CALIB__PRI_ALIAS_0 0x6
+#define FUSE_DAC_HDTV_CALIB__PRI_ALIAS_0_DATA 31:28
+#define FUSE_DAC_HDTV_CALIB__PRI_ALIAS_0_WIDTH 4
+#define FUSE_DAC_HDTV_CALIB__PRI_ALIAS_1 0x8
+#define FUSE_DAC_HDTV_CALIB__PRI_ALIAS_1_DATA 3:0
+#define FUSE_DAC_HDTV_CALIB__PRI_ALIAS_1_WIDTH 4
+#define FUSE_DAC_HDTV_CALIB__RED_ALIAS_0 0x7
+#define FUSE_DAC_HDTV_CALIB__RED_ALIAS_0_DATA 31:28
+#define FUSE_DAC_HDTV_CALIB__RED_ALIAS_0_WIDTH 4
+#define FUSE_DAC_HDTV_CALIB__RED_ALIAS_1 0x9
+#define FUSE_DAC_HDTV_CALIB__RED_ALIAS_1_DATA 3:0
+#define FUSE_DAC_HDTV_CALIB__RED_ALIAS_1_WIDTH 4
+
+#define FUSE_DAC_SDTV_CALIB__WIDTH 8
+#define FUSE_DAC_SDTV_CALIB__PRI_ALIAS_0 0x8
+#define FUSE_DAC_SDTV_CALIB__PRI_ALIAS_0_DATA 11:4
+#define FUSE_DAC_SDTV_CALIB__PRI_ALIAS_0_WIDTH 8
+#define FUSE_DAC_SDTV_CALIB__RED_ALIAS_0 0x9
+#define FUSE_DAC_SDTV_CALIB__RED_ALIAS_0_DATA 11:4
+#define FUSE_DAC_SDTV_CALIB__RED_ALIAS_0_WIDTH 8
+
+#define FUSE_RESERVED_PRODUCTION__WIDTH 4
+#define FUSE_RESERVED_PRODUCTION__PRI_ALIAS_0 0x8
+#define FUSE_RESERVED_PRODUCTION__PRI_ALIAS_0_DATA 15:12
+#define FUSE_RESERVED_PRODUCTION__PRI_ALIAS_0_WIDTH 4
+#define FUSE_RESERVED_PRODUCTION__RED_ALIAS_0 0x9
+#define FUSE_RESERVED_PRODUCTION__RED_ALIAS_0_DATA 15:12
+#define FUSE_RESERVED_PRODUCTION__RED_ALIAS_0_WIDTH 4
+
+#define FUSE_HDMI_LANE0_CALIB__WIDTH 6
+#define FUSE_HDMI_LANE0_CALIB__PRI_ALIAS_0 0x8
+#define FUSE_HDMI_LANE0_CALIB__PRI_ALIAS_0_DATA 21:16
+#define FUSE_HDMI_LANE0_CALIB__PRI_ALIAS_0_WIDTH 6
+#define FUSE_HDMI_LANE0_CALIB__RED_ALIAS_0 0x9
+#define FUSE_HDMI_LANE0_CALIB__RED_ALIAS_0_DATA 21:16
+#define FUSE_HDMI_LANE0_CALIB__RED_ALIAS_0_WIDTH 6
+
+#define FUSE_HDMI_LANE1_CALIB__WIDTH 6
+#define FUSE_HDMI_LANE1_CALIB__PRI_ALIAS_0 0x8
+#define FUSE_HDMI_LANE1_CALIB__PRI_ALIAS_0_DATA 27:22
+#define FUSE_HDMI_LANE1_CALIB__PRI_ALIAS_0_WIDTH 6
+#define FUSE_HDMI_LANE1_CALIB__RED_ALIAS_0 0x9
+#define FUSE_HDMI_LANE1_CALIB__RED_ALIAS_0_DATA 27:22
+#define FUSE_HDMI_LANE1_CALIB__RED_ALIAS_0_WIDTH 6
+
+#define FUSE_HDMI_LANE2_CALIB__WIDTH 6
+#define FUSE_HDMI_LANE2_CALIB__PRI_ALIAS_0 0x8
+#define FUSE_HDMI_LANE2_CALIB__PRI_ALIAS_0_DATA 31:28
+#define FUSE_HDMI_LANE2_CALIB__PRI_ALIAS_0_WIDTH 4
+#define FUSE_HDMI_LANE2_CALIB__PRI_ALIAS_1 0xa
+#define FUSE_HDMI_LANE2_CALIB__PRI_ALIAS_1_DATA 1:0
+#define FUSE_HDMI_LANE2_CALIB__PRI_ALIAS_1_WIDTH 2
+#define FUSE_HDMI_LANE2_CALIB__RED_ALIAS_0 0x9
+#define FUSE_HDMI_LANE2_CALIB__RED_ALIAS_0_DATA 31:28
+#define FUSE_HDMI_LANE2_CALIB__RED_ALIAS_0_WIDTH 4
+#define FUSE_HDMI_LANE2_CALIB__RED_ALIAS_1 0xb
+#define FUSE_HDMI_LANE2_CALIB__RED_ALIAS_1_DATA 1:0
+#define FUSE_HDMI_LANE2_CALIB__RED_ALIAS_1_WIDTH 2
+
+#define FUSE_HDMI_LANE3_CALIB__WIDTH 6
+#define FUSE_HDMI_LANE3_CALIB__PRI_ALIAS_0 0xa
+#define FUSE_HDMI_LANE3_CALIB__PRI_ALIAS_0_DATA 7:2
+#define FUSE_HDMI_LANE3_CALIB__PRI_ALIAS_0_WIDTH 6
+#define FUSE_HDMI_LANE3_CALIB__RED_ALIAS_0 0xb
+#define FUSE_HDMI_LANE3_CALIB__RED_ALIAS_0_DATA 7:2
+#define FUSE_HDMI_LANE3_CALIB__RED_ALIAS_0_WIDTH 6
+
+#define FUSE_PRIVATE_KEY0__WIDTH 32
+#define FUSE_PRIVATE_KEY0__PRI_ALIAS_0 0xa
+#define FUSE_PRIVATE_KEY0__PRI_ALIAS_0_DATA 31:8
+#define FUSE_PRIVATE_KEY0__PRI_ALIAS_0_WIDTH 24
+#define FUSE_PRIVATE_KEY0__PRI_ALIAS_1 0xc
+#define FUSE_PRIVATE_KEY0__PRI_ALIAS_1_DATA 7:0
+#define FUSE_PRIVATE_KEY0__PRI_ALIAS_1_WIDTH 8
+#define FUSE_PRIVATE_KEY0__RED_ALIAS_0 0xb
+#define FUSE_PRIVATE_KEY0__RED_ALIAS_0_DATA 31:8
+#define FUSE_PRIVATE_KEY0__RED_ALIAS_0_WIDTH 24
+#define FUSE_PRIVATE_KEY0__RED_ALIAS_1 0xd
+#define FUSE_PRIVATE_KEY0__RED_ALIAS_1_DATA 7:0
+#define FUSE_PRIVATE_KEY0__RED_ALIAS_1_WIDTH 8
+
+#define FUSE_PRIVATE_KEY1__WIDTH 32
+#define FUSE_PRIVATE_KEY1__PRI_ALIAS_0 0xc
+#define FUSE_PRIVATE_KEY1__PRI_ALIAS_0_DATA 31:8
+#define FUSE_PRIVATE_KEY1__PRI_ALIAS_0_WIDTH 24
+#define FUSE_PRIVATE_KEY1__PRI_ALIAS_1 0xe
+#define FUSE_PRIVATE_KEY1__PRI_ALIAS_1_DATA 7:0
+#define FUSE_PRIVATE_KEY1__PRI_ALIAS_1_WIDTH 8
+#define FUSE_PRIVATE_KEY1__RED_ALIAS_0 0xd
+#define FUSE_PRIVATE_KEY1__RED_ALIAS_0_DATA 31:8
+#define FUSE_PRIVATE_KEY1__RED_ALIAS_0_WIDTH 24
+#define FUSE_PRIVATE_KEY1__RED_ALIAS_1 0xf
+#define FUSE_PRIVATE_KEY1__RED_ALIAS_1_DATA 7:0
+#define FUSE_PRIVATE_KEY1__RED_ALIAS_1_WIDTH 8
+
+#define FUSE_PRIVATE_KEY2__WIDTH 32
+#define FUSE_PRIVATE_KEY2__PRI_ALIAS_0 0xe
+#define FUSE_PRIVATE_KEY2__PRI_ALIAS_0_DATA 31:8
+#define FUSE_PRIVATE_KEY2__PRI_ALIAS_0_WIDTH 24
+#define FUSE_PRIVATE_KEY2__PRI_ALIAS_1 0x10
+#define FUSE_PRIVATE_KEY2__PRI_ALIAS_1_DATA 7:0
+#define FUSE_PRIVATE_KEY2__PRI_ALIAS_1_WIDTH 8
+#define FUSE_PRIVATE_KEY2__RED_ALIAS_0 0xf
+#define FUSE_PRIVATE_KEY2__RED_ALIAS_0_DATA 31:8
+#define FUSE_PRIVATE_KEY2__RED_ALIAS_0_WIDTH 24
+#define FUSE_PRIVATE_KEY2__RED_ALIAS_1 0x11
+#define FUSE_PRIVATE_KEY2__RED_ALIAS_1_DATA 7:0
+#define FUSE_PRIVATE_KEY2__RED_ALIAS_1_WIDTH 8
+
+#define FUSE_PRIVATE_KEY3__WIDTH 32
+#define FUSE_PRIVATE_KEY3__PRI_ALIAS_0 0x10
+#define FUSE_PRIVATE_KEY3__PRI_ALIAS_0_DATA 31:8
+#define FUSE_PRIVATE_KEY3__PRI_ALIAS_0_WIDTH 24
+#define FUSE_PRIVATE_KEY3__PRI_ALIAS_1 0x12
+#define FUSE_PRIVATE_KEY3__PRI_ALIAS_1_DATA 7:0
+#define FUSE_PRIVATE_KEY3__PRI_ALIAS_1_WIDTH 8
+#define FUSE_PRIVATE_KEY3__RED_ALIAS_0 0x11
+#define FUSE_PRIVATE_KEY3__RED_ALIAS_0_DATA 31:8
+#define FUSE_PRIVATE_KEY3__RED_ALIAS_0_WIDTH 24
+#define FUSE_PRIVATE_KEY3__RED_ALIAS_1 0x13
+#define FUSE_PRIVATE_KEY3__RED_ALIAS_1_DATA 7:0
+#define FUSE_PRIVATE_KEY3__RED_ALIAS_1_WIDTH 8
+
+#define FUSE_PRIVATE_KEY4__WIDTH 32
+#define FUSE_PRIVATE_KEY4__PRI_ALIAS_0 0x12
+#define FUSE_PRIVATE_KEY4__PRI_ALIAS_0_DATA 31:8
+#define FUSE_PRIVATE_KEY4__PRI_ALIAS_0_WIDTH 24
+#define FUSE_PRIVATE_KEY4__PRI_ALIAS_1 0x14
+#define FUSE_PRIVATE_KEY4__PRI_ALIAS_1_DATA 7:0
+#define FUSE_PRIVATE_KEY4__PRI_ALIAS_1_WIDTH 8
+#define FUSE_PRIVATE_KEY4__RED_ALIAS_0 0x13
+#define FUSE_PRIVATE_KEY4__RED_ALIAS_0_DATA 31:8
+#define FUSE_PRIVATE_KEY4__RED_ALIAS_0_WIDTH 24
+#define FUSE_PRIVATE_KEY4__RED_ALIAS_1 0x15
+#define FUSE_PRIVATE_KEY4__RED_ALIAS_1_DATA 7:0
+#define FUSE_PRIVATE_KEY4__RED_ALIAS_1_WIDTH 8
+
+#define FUSE_BOOT_DEVICE_INFO__WIDTH 16
+#define FUSE_BOOT_DEVICE_INFO__PRI_ALIAS_0 0x14
+#define FUSE_BOOT_DEVICE_INFO__PRI_ALIAS_0_DATA 23:8
+#define FUSE_BOOT_DEVICE_INFO__PRI_ALIAS_0_WIDTH 16
+#define FUSE_BOOT_DEVICE_INFO__RED_ALIAS_0 0x15
+#define FUSE_BOOT_DEVICE_INFO__RED_ALIAS_0_DATA 23:8
+#define FUSE_BOOT_DEVICE_INFO__RED_ALIAS_0_WIDTH 16
+
+#define FUSE_RESERVED_SW__WIDTH 8
+#define FUSE_RESERVED_SW__PRI_ALIAS_0 0x14
+#define FUSE_RESERVED_SW__PRI_ALIAS_0_DATA 31:24
+#define FUSE_RESERVED_SW__PRI_ALIAS_0_WIDTH 8
+#define FUSE_RESERVED_SW__RED_ALIAS_0 0x15
+#define FUSE_RESERVED_SW__RED_ALIAS_0_DATA 31:24
+#define FUSE_RESERVED_SW__RED_ALIAS_0_WIDTH 8
+
+#define FUSE_ARM_DEBUG_CONTROL__WIDTH 4
+#define FUSE_ARM_DEBUG_CONTROL__PRI_ALIAS_0 0x16
+#define FUSE_ARM_DEBUG_CONTROL__PRI_ALIAS_0_DATA 3:0
+#define FUSE_ARM_DEBUG_CONTROL__PRI_ALIAS_0_WIDTH 4
+#define FUSE_ARM_DEBUG_CONTROL__RED_ALIAS_0 0x17
+#define FUSE_ARM_DEBUG_CONTROL__RED_ALIAS_0_DATA 3:0
+#define FUSE_ARM_DEBUG_CONTROL__RED_ALIAS_0_WIDTH 4
+
+#define FUSE_RESERVED_ODM0__WIDTH 32
+#define FUSE_RESERVED_ODM0__PRI_ALIAS_0 0x16
+#define FUSE_RESERVED_ODM0__PRI_ALIAS_0_DATA 31:4
+#define FUSE_RESERVED_ODM0__PRI_ALIAS_0_WIDTH 28
+#define FUSE_RESERVED_ODM0__PRI_ALIAS_1 0x18
+#define FUSE_RESERVED_ODM0__PRI_ALIAS_1_DATA 3:0
+#define FUSE_RESERVED_ODM0__PRI_ALIAS_1_WIDTH 4
+#define FUSE_RESERVED_ODM0__RED_ALIAS_0 0x17
+#define FUSE_RESERVED_ODM0__RED_ALIAS_0_DATA 31:4
+#define FUSE_RESERVED_ODM0__RED_ALIAS_0_WIDTH 28
+#define FUSE_RESERVED_ODM0__RED_ALIAS_1 0x19
+#define FUSE_RESERVED_ODM0__RED_ALIAS_1_DATA 3:0
+#define FUSE_RESERVED_ODM0__RED_ALIAS_1_WIDTH 4
+
+#define FUSE_RESERVED_ODM1__WIDTH 32
+#define FUSE_RESERVED_ODM1__PRI_ALIAS_0 0x18
+#define FUSE_RESERVED_ODM1__PRI_ALIAS_0_DATA 31:4
+#define FUSE_RESERVED_ODM1__PRI_ALIAS_0_WIDTH 28
+#define FUSE_RESERVED_ODM1__PRI_ALIAS_1 0x1a
+#define FUSE_RESERVED_ODM1__PRI_ALIAS_1_DATA 3:0
+#define FUSE_RESERVED_ODM1__PRI_ALIAS_1_WIDTH 4
+#define FUSE_RESERVED_ODM1__RED_ALIAS_0 0x19
+#define FUSE_RESERVED_ODM1__RED_ALIAS_0_DATA 31:4
+#define FUSE_RESERVED_ODM1__RED_ALIAS_0_WIDTH 28
+#define FUSE_RESERVED_ODM1__RED_ALIAS_1 0x1b
+#define FUSE_RESERVED_ODM1__RED_ALIAS_1_DATA 3:0
+#define FUSE_RESERVED_ODM1__RED_ALIAS_1_WIDTH 4
+
+#define FUSE_RESERVED_ODM2__WIDTH 32
+#define FUSE_RESERVED_ODM2__PRI_ALIAS_0 0x1a
+#define FUSE_RESERVED_ODM2__PRI_ALIAS_0_DATA 31:4
+#define FUSE_RESERVED_ODM2__PRI_ALIAS_0_WIDTH 28
+#define FUSE_RESERVED_ODM2__PRI_ALIAS_1 0x1c
+#define FUSE_RESERVED_ODM2__PRI_ALIAS_1_DATA 3:0
+#define FUSE_RESERVED_ODM2__PRI_ALIAS_1_WIDTH 4
+#define FUSE_RESERVED_ODM2__RED_ALIAS_0 0x1b
+#define FUSE_RESERVED_ODM2__RED_ALIAS_0_DATA 31:4
+#define FUSE_RESERVED_ODM2__RED_ALIAS_0_WIDTH 28
+#define FUSE_RESERVED_ODM2__RED_ALIAS_1 0x1d
+#define FUSE_RESERVED_ODM2__RED_ALIAS_1_DATA 3:0
+#define FUSE_RESERVED_ODM2__RED_ALIAS_1_WIDTH 4
+
+#define FUSE_RESERVED_ODM3__WIDTH 32
+#define FUSE_RESERVED_ODM3__PRI_ALIAS_0 0x1c
+#define FUSE_RESERVED_ODM3__PRI_ALIAS_0_DATA 31:4
+#define FUSE_RESERVED_ODM3__PRI_ALIAS_0_WIDTH 28
+#define FUSE_RESERVED_ODM3__PRI_ALIAS_1 0x1e
+#define FUSE_RESERVED_ODM3__PRI_ALIAS_1_DATA 3:0
+#define FUSE_RESERVED_ODM3__PRI_ALIAS_1_WIDTH 4
+#define FUSE_RESERVED_ODM3__RED_ALIAS_0 0x1d
+#define FUSE_RESERVED_ODM3__RED_ALIAS_0_DATA 31:4
+#define FUSE_RESERVED_ODM3__RED_ALIAS_0_WIDTH 28
+#define FUSE_RESERVED_ODM3__RED_ALIAS_1 0x1f
+#define FUSE_RESERVED_ODM3__RED_ALIAS_1_DATA 3:0
+#define FUSE_RESERVED_ODM3__RED_ALIAS_1_WIDTH 4
+
+#define FUSE_RESERVED_ODM4__WIDTH 32
+#define FUSE_RESERVED_ODM4__PRI_ALIAS_0 0x1e
+#define FUSE_RESERVED_ODM4__PRI_ALIAS_0_DATA 31:4
+#define FUSE_RESERVED_ODM4__PRI_ALIAS_0_WIDTH 28
+#define FUSE_RESERVED_ODM4__PRI_ALIAS_1 0x20
+#define FUSE_RESERVED_ODM4__PRI_ALIAS_1_DATA 3:0
+#define FUSE_RESERVED_ODM4__PRI_ALIAS_1_WIDTH 4
+#define FUSE_RESERVED_ODM4__RED_ALIAS_0 0x1f
+#define FUSE_RESERVED_ODM4__RED_ALIAS_0_DATA 31:4
+#define FUSE_RESERVED_ODM4__RED_ALIAS_0_WIDTH 28
+#define FUSE_RESERVED_ODM4__RED_ALIAS_1 0x21
+#define FUSE_RESERVED_ODM4__RED_ALIAS_1_DATA 3:0
+#define FUSE_RESERVED_ODM4__RED_ALIAS_1_WIDTH 4
+
+#define FUSE_RESERVED_ODM5__WIDTH 32
+#define FUSE_RESERVED_ODM5__PRI_ALIAS_0 0x20
+#define FUSE_RESERVED_ODM5__PRI_ALIAS_0_DATA 31:4
+#define FUSE_RESERVED_ODM5__PRI_ALIAS_0_WIDTH 28
+#define FUSE_RESERVED_ODM5__PRI_ALIAS_1 0x22
+#define FUSE_RESERVED_ODM5__PRI_ALIAS_1_DATA 3:0
+#define FUSE_RESERVED_ODM5__PRI_ALIAS_1_WIDTH 4
+#define FUSE_RESERVED_ODM5__RED_ALIAS_0 0x21
+#define FUSE_RESERVED_ODM5__RED_ALIAS_0_DATA 31:4
+#define FUSE_RESERVED_ODM5__RED_ALIAS_0_WIDTH 28
+#define FUSE_RESERVED_ODM5__RED_ALIAS_1 0x23
+#define FUSE_RESERVED_ODM5__RED_ALIAS_1_DATA 3:0
+#define FUSE_RESERVED_ODM5__RED_ALIAS_1_WIDTH 4
+
+#define FUSE_RESERVED_ODM6__WIDTH 32
+#define FUSE_RESERVED_ODM6__PRI_ALIAS_0 0x22
+#define FUSE_RESERVED_ODM6__PRI_ALIAS_0_DATA 31:4
+#define FUSE_RESERVED_ODM6__PRI_ALIAS_0_WIDTH 28
+#define FUSE_RESERVED_ODM6__PRI_ALIAS_1 0x24
+#define FUSE_RESERVED_ODM6__PRI_ALIAS_1_DATA 3:0
+#define FUSE_RESERVED_ODM6__PRI_ALIAS_1_WIDTH 4
+#define FUSE_RESERVED_ODM6__RED_ALIAS_0 0x23
+#define FUSE_RESERVED_ODM6__RED_ALIAS_0_DATA 31:4
+#define FUSE_RESERVED_ODM6__RED_ALIAS_0_WIDTH 28
+#define FUSE_RESERVED_ODM6__RED_ALIAS_1 0x25
+#define FUSE_RESERVED_ODM6__RED_ALIAS_1_DATA 3:0
+#define FUSE_RESERVED_ODM6__RED_ALIAS_1_WIDTH 4
+
+#define FUSE_RESERVED_ODM7__WIDTH 32
+#define FUSE_RESERVED_ODM7__PRI_ALIAS_0 0x24
+#define FUSE_RESERVED_ODM7__PRI_ALIAS_0_DATA 31:4
+#define FUSE_RESERVED_ODM7__PRI_ALIAS_0_WIDTH 28
+#define FUSE_RESERVED_ODM7__PRI_ALIAS_1 0x26
+#define FUSE_RESERVED_ODM7__PRI_ALIAS_1_DATA 3:0
+#define FUSE_RESERVED_ODM7__PRI_ALIAS_1_WIDTH 4
+#define FUSE_RESERVED_ODM7__RED_ALIAS_0 0x25
+#define FUSE_RESERVED_ODM7__RED_ALIAS_0_DATA 31:4
+#define FUSE_RESERVED_ODM7__RED_ALIAS_0_WIDTH 28
+#define FUSE_RESERVED_ODM7__RED_ALIAS_1 0x27
+#define FUSE_RESERVED_ODM7__RED_ALIAS_1_DATA 3:0
+#define FUSE_RESERVED_ODM7__RED_ALIAS_1_WIDTH 4
+
+#define FUSE_NOR_INFO__WIDTH 2
+#define FUSE_NOR_INFO__PRI_ALIAS_0 0x26
+#define FUSE_NOR_INFO__PRI_ALIAS_0_DATA 5:4
+#define FUSE_NOR_INFO__PRI_ALIAS_0_WIDTH 2
+#define FUSE_NOR_INFO__RED_ALIAS_0 0x27
+#define FUSE_NOR_INFO__RED_ALIAS_0_DATA 5:4
+#define FUSE_NOR_INFO__RED_ALIAS_0_WIDTH 2
+
+#define FUSE_USB_CALIB__WIDTH 7
+#define FUSE_USB_CALIB__PRI_ALIAS_0 0x26
+#define FUSE_USB_CALIB__PRI_ALIAS_0_DATA 12:6
+#define FUSE_USB_CALIB__PRI_ALIAS_0_WIDTH 7
+#define FUSE_USB_CALIB__RED_ALIAS_0 0x27
+#define FUSE_USB_CALIB__RED_ALIAS_0_DATA 12:6
+#define FUSE_USB_CALIB__RED_ALIAS_0_WIDTH 7
+
+#define FUSE_KFUSE_PRIVKEY_CTRL__WIDTH 2
+#define FUSE_KFUSE_PRIVKEY_CTRL__PRI_ALIAS_0 0x26
+#define FUSE_KFUSE_PRIVKEY_CTRL__PRI_ALIAS_0_DATA 14:13
+#define FUSE_KFUSE_PRIVKEY_CTRL__PRI_ALIAS_0_WIDTH 2
+#define FUSE_KFUSE_PRIVKEY_CTRL__RED_ALIAS_0 0x27
+#define FUSE_KFUSE_PRIVKEY_CTRL__RED_ALIAS_0_DATA 14:13
+#define FUSE_KFUSE_PRIVKEY_CTRL__RED_ALIAS_0_WIDTH 2
+
+#define FUSE_PACKAGE_INFO__WIDTH 2
+#define FUSE_PACKAGE_INFO__PRI_ALIAS_0 0x26
+#define FUSE_PACKAGE_INFO__PRI_ALIAS_0_DATA 16:15
+#define FUSE_PACKAGE_INFO__PRI_ALIAS_0_WIDTH 2
+#define FUSE_PACKAGE_INFO__RED_ALIAS_0 0x27
+#define FUSE_PACKAGE_INFO__RED_ALIAS_0_DATA 16:15
+#define FUSE_PACKAGE_INFO__RED_ALIAS_0_WIDTH 2
+
+#define FUSE_SPARE_BIT_0__WIDTH 1
+#define FUSE_SPARE_BIT_0__PRI_ALIAS_0 0x26
+#define FUSE_SPARE_BIT_0__PRI_ALIAS_0_DATA 17:17
+#define FUSE_SPARE_BIT_0__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_1__WIDTH 1
+#define FUSE_SPARE_BIT_1__PRI_ALIAS_0 0x26
+#define FUSE_SPARE_BIT_1__PRI_ALIAS_0_DATA 18:18
+#define FUSE_SPARE_BIT_1__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_2__WIDTH 1
+#define FUSE_SPARE_BIT_2__PRI_ALIAS_0 0x26
+#define FUSE_SPARE_BIT_2__PRI_ALIAS_0_DATA 19:19
+#define FUSE_SPARE_BIT_2__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_3__WIDTH 1
+#define FUSE_SPARE_BIT_3__PRI_ALIAS_0 0x26
+#define FUSE_SPARE_BIT_3__PRI_ALIAS_0_DATA 20:20
+#define FUSE_SPARE_BIT_3__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_4__WIDTH 1
+#define FUSE_SPARE_BIT_4__PRI_ALIAS_0 0x26
+#define FUSE_SPARE_BIT_4__PRI_ALIAS_0_DATA 21:21
+#define FUSE_SPARE_BIT_4__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_5__WIDTH 1
+#define FUSE_SPARE_BIT_5__PRI_ALIAS_0 0x26
+#define FUSE_SPARE_BIT_5__PRI_ALIAS_0_DATA 22:22
+#define FUSE_SPARE_BIT_5__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_6__WIDTH 1
+#define FUSE_SPARE_BIT_6__PRI_ALIAS_0 0x26
+#define FUSE_SPARE_BIT_6__PRI_ALIAS_0_DATA 23:23
+#define FUSE_SPARE_BIT_6__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_7__WIDTH 1
+#define FUSE_SPARE_BIT_7__PRI_ALIAS_0 0x26
+#define FUSE_SPARE_BIT_7__PRI_ALIAS_0_DATA 24:24
+#define FUSE_SPARE_BIT_7__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_8__WIDTH 1
+#define FUSE_SPARE_BIT_8__PRI_ALIAS_0 0x26
+#define FUSE_SPARE_BIT_8__PRI_ALIAS_0_DATA 25:25
+#define FUSE_SPARE_BIT_8__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_9__WIDTH 1
+#define FUSE_SPARE_BIT_9__PRI_ALIAS_0 0x26
+#define FUSE_SPARE_BIT_9__PRI_ALIAS_0_DATA 26:26
+#define FUSE_SPARE_BIT_9__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_10__WIDTH 1
+#define FUSE_SPARE_BIT_10__PRI_ALIAS_0 0x26
+#define FUSE_SPARE_BIT_10__PRI_ALIAS_0_DATA 27:27
+#define FUSE_SPARE_BIT_10__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_11__WIDTH 1
+#define FUSE_SPARE_BIT_11__PRI_ALIAS_0 0x26
+#define FUSE_SPARE_BIT_11__PRI_ALIAS_0_DATA 28:28
+#define FUSE_SPARE_BIT_11__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_12__WIDTH 1
+#define FUSE_SPARE_BIT_12__PRI_ALIAS_0 0x26
+#define FUSE_SPARE_BIT_12__PRI_ALIAS_0_DATA 29:29
+#define FUSE_SPARE_BIT_12__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_13__WIDTH 1
+#define FUSE_SPARE_BIT_13__PRI_ALIAS_0 0x26
+#define FUSE_SPARE_BIT_13__PRI_ALIAS_0_DATA 30:30
+#define FUSE_SPARE_BIT_13__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_14__WIDTH 1
+#define FUSE_SPARE_BIT_14__PRI_ALIAS_0 0x26
+#define FUSE_SPARE_BIT_14__PRI_ALIAS_0_DATA 31:31
+#define FUSE_SPARE_BIT_14__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_15__WIDTH 1
+#define FUSE_SPARE_BIT_15__PRI_ALIAS_0 0x27
+#define FUSE_SPARE_BIT_15__PRI_ALIAS_0_DATA 17:17
+#define FUSE_SPARE_BIT_15__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_16__WIDTH 1
+#define FUSE_SPARE_BIT_16__PRI_ALIAS_0 0x27
+#define FUSE_SPARE_BIT_16__PRI_ALIAS_0_DATA 18:18
+#define FUSE_SPARE_BIT_16__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_17__WIDTH 1
+#define FUSE_SPARE_BIT_17__PRI_ALIAS_0 0x27
+#define FUSE_SPARE_BIT_17__PRI_ALIAS_0_DATA 19:19
+#define FUSE_SPARE_BIT_17__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_18__WIDTH 1
+#define FUSE_SPARE_BIT_18__PRI_ALIAS_0 0x27
+#define FUSE_SPARE_BIT_18__PRI_ALIAS_0_DATA 20:20
+#define FUSE_SPARE_BIT_18__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_19__WIDTH 1
+#define FUSE_SPARE_BIT_19__PRI_ALIAS_0 0x27
+#define FUSE_SPARE_BIT_19__PRI_ALIAS_0_DATA 21:21
+#define FUSE_SPARE_BIT_19__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_20__WIDTH 1
+#define FUSE_SPARE_BIT_20__PRI_ALIAS_0 0x27
+#define FUSE_SPARE_BIT_20__PRI_ALIAS_0_DATA 22:22
+#define FUSE_SPARE_BIT_20__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_21__WIDTH 1
+#define FUSE_SPARE_BIT_21__PRI_ALIAS_0 0x27
+#define FUSE_SPARE_BIT_21__PRI_ALIAS_0_DATA 23:23
+#define FUSE_SPARE_BIT_21__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_22__WIDTH 1
+#define FUSE_SPARE_BIT_22__PRI_ALIAS_0 0x27
+#define FUSE_SPARE_BIT_22__PRI_ALIAS_0_DATA 24:24
+#define FUSE_SPARE_BIT_22__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_23__WIDTH 1
+#define FUSE_SPARE_BIT_23__PRI_ALIAS_0 0x27
+#define FUSE_SPARE_BIT_23__PRI_ALIAS_0_DATA 25:25
+#define FUSE_SPARE_BIT_23__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_24__WIDTH 1
+#define FUSE_SPARE_BIT_24__PRI_ALIAS_0 0x27
+#define FUSE_SPARE_BIT_24__PRI_ALIAS_0_DATA 26:26
+#define FUSE_SPARE_BIT_24__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_25__WIDTH 1
+#define FUSE_SPARE_BIT_25__PRI_ALIAS_0 0x27
+#define FUSE_SPARE_BIT_25__PRI_ALIAS_0_DATA 27:27
+#define FUSE_SPARE_BIT_25__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_26__WIDTH 1
+#define FUSE_SPARE_BIT_26__PRI_ALIAS_0 0x27
+#define FUSE_SPARE_BIT_26__PRI_ALIAS_0_DATA 28:28
+#define FUSE_SPARE_BIT_26__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_27__WIDTH 1
+#define FUSE_SPARE_BIT_27__PRI_ALIAS_0 0x27
+#define FUSE_SPARE_BIT_27__PRI_ALIAS_0_DATA 29:29
+#define FUSE_SPARE_BIT_27__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_28__WIDTH 1
+#define FUSE_SPARE_BIT_28__PRI_ALIAS_0 0x27
+#define FUSE_SPARE_BIT_28__PRI_ALIAS_0_DATA 30:30
+#define FUSE_SPARE_BIT_28__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_29__WIDTH 1
+#define FUSE_SPARE_BIT_29__PRI_ALIAS_0 0x27
+#define FUSE_SPARE_BIT_29__PRI_ALIAS_0_DATA 31:31
+#define FUSE_SPARE_BIT_29__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_30__WIDTH 1
+#define FUSE_SPARE_BIT_30__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_30__PRI_ALIAS_0_DATA 0:0
+#define FUSE_SPARE_BIT_30__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_31__WIDTH 1
+#define FUSE_SPARE_BIT_31__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_31__PRI_ALIAS_0_DATA 1:1
+#define FUSE_SPARE_BIT_31__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_32__WIDTH 1
+#define FUSE_SPARE_BIT_32__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_32__PRI_ALIAS_0_DATA 2:2
+#define FUSE_SPARE_BIT_32__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_33__WIDTH 1
+#define FUSE_SPARE_BIT_33__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_33__PRI_ALIAS_0_DATA 3:3
+#define FUSE_SPARE_BIT_33__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_34__WIDTH 1
+#define FUSE_SPARE_BIT_34__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_34__PRI_ALIAS_0_DATA 4:4
+#define FUSE_SPARE_BIT_34__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_35__WIDTH 1
+#define FUSE_SPARE_BIT_35__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_35__PRI_ALIAS_0_DATA 5:5
+#define FUSE_SPARE_BIT_35__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_36__WIDTH 1
+#define FUSE_SPARE_BIT_36__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_36__PRI_ALIAS_0_DATA 6:6
+#define FUSE_SPARE_BIT_36__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_37__WIDTH 1
+#define FUSE_SPARE_BIT_37__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_37__PRI_ALIAS_0_DATA 7:7
+#define FUSE_SPARE_BIT_37__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_38__WIDTH 1
+#define FUSE_SPARE_BIT_38__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_38__PRI_ALIAS_0_DATA 8:8
+#define FUSE_SPARE_BIT_38__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_39__WIDTH 1
+#define FUSE_SPARE_BIT_39__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_39__PRI_ALIAS_0_DATA 9:9
+#define FUSE_SPARE_BIT_39__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_40__WIDTH 1
+#define FUSE_SPARE_BIT_40__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_40__PRI_ALIAS_0_DATA 10:10
+#define FUSE_SPARE_BIT_40__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_41__WIDTH 1
+#define FUSE_SPARE_BIT_41__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_41__PRI_ALIAS_0_DATA 11:11
+#define FUSE_SPARE_BIT_41__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_42__WIDTH 1
+#define FUSE_SPARE_BIT_42__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_42__PRI_ALIAS_0_DATA 12:12
+#define FUSE_SPARE_BIT_42__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_43__WIDTH 1
+#define FUSE_SPARE_BIT_43__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_43__PRI_ALIAS_0_DATA 13:13
+#define FUSE_SPARE_BIT_43__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_44__WIDTH 1
+#define FUSE_SPARE_BIT_44__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_44__PRI_ALIAS_0_DATA 14:14
+#define FUSE_SPARE_BIT_44__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_45__WIDTH 1
+#define FUSE_SPARE_BIT_45__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_45__PRI_ALIAS_0_DATA 15:15
+#define FUSE_SPARE_BIT_45__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_46__WIDTH 1
+#define FUSE_SPARE_BIT_46__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_46__PRI_ALIAS_0_DATA 16:16
+#define FUSE_SPARE_BIT_46__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_47__WIDTH 1
+#define FUSE_SPARE_BIT_47__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_47__PRI_ALIAS_0_DATA 17:17
+#define FUSE_SPARE_BIT_47__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_48__WIDTH 1
+#define FUSE_SPARE_BIT_48__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_48__PRI_ALIAS_0_DATA 18:18
+#define FUSE_SPARE_BIT_48__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_49__WIDTH 1
+#define FUSE_SPARE_BIT_49__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_49__PRI_ALIAS_0_DATA 19:19
+#define FUSE_SPARE_BIT_49__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_50__WIDTH 1
+#define FUSE_SPARE_BIT_50__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_50__PRI_ALIAS_0_DATA 20:20
+#define FUSE_SPARE_BIT_50__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_51__WIDTH 1
+#define FUSE_SPARE_BIT_51__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_51__PRI_ALIAS_0_DATA 21:21
+#define FUSE_SPARE_BIT_51__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_52__WIDTH 1
+#define FUSE_SPARE_BIT_52__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_52__PRI_ALIAS_0_DATA 22:22
+#define FUSE_SPARE_BIT_52__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_53__WIDTH 1
+#define FUSE_SPARE_BIT_53__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_53__PRI_ALIAS_0_DATA 23:23
+#define FUSE_SPARE_BIT_53__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_54__WIDTH 1
+#define FUSE_SPARE_BIT_54__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_54__PRI_ALIAS_0_DATA 24:24
+#define FUSE_SPARE_BIT_54__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_55__WIDTH 1
+#define FUSE_SPARE_BIT_55__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_55__PRI_ALIAS_0_DATA 25:25
+#define FUSE_SPARE_BIT_55__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_56__WIDTH 1
+#define FUSE_SPARE_BIT_56__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_56__PRI_ALIAS_0_DATA 26:26
+#define FUSE_SPARE_BIT_56__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_57__WIDTH 1
+#define FUSE_SPARE_BIT_57__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_57__PRI_ALIAS_0_DATA 27:27
+#define FUSE_SPARE_BIT_57__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_58__WIDTH 1
+#define FUSE_SPARE_BIT_58__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_58__PRI_ALIAS_0_DATA 28:28
+#define FUSE_SPARE_BIT_58__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_59__WIDTH 1
+#define FUSE_SPARE_BIT_59__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_59__PRI_ALIAS_0_DATA 29:29
+#define FUSE_SPARE_BIT_59__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_60__WIDTH 1
+#define FUSE_SPARE_BIT_60__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_60__PRI_ALIAS_0_DATA 30:30
+#define FUSE_SPARE_BIT_60__PRI_ALIAS_0_WIDTH 1
+
+#define FUSE_SPARE_BIT_61__WIDTH 1
+#define FUSE_SPARE_BIT_61__PRI_ALIAS_0 0x28
+#define FUSE_SPARE_BIT_61__PRI_ALIAS_0_DATA 31:31
+#define FUSE_SPARE_BIT_61__PRI_ALIAS_0_WIDTH 1
+
diff --git a/arch/arm/mach-tegra/include/nvddk_bootdevices.h b/arch/arm/mach-tegra/include/nvddk_bootdevices.h
new file mode 100644
index 000000000000..97f460d9df28
--- /dev/null
+++ b/arch/arm/mach-tegra/include/nvddk_bootdevices.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2010 NVIDIA Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NVIDIA Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef INCLUDED_NVDDK_BOOTDEVICES_H
+#define INCLUDED_NVDDK_BOOTDEVICES_H
+
+/**
+ * @defgroup nvddk_bootdevices_group Boot Device Types
+ *
+ * Provides types of boot devices for NVIDIA Tegra functions.
+ *
+ * @ingroup nvddk_group
+ * @{
+ */
+
+/**
+ * Defines the supported secondary boot device types.
+ */
+typedef enum
+{
+ // Specifies NAND flash (SLC and MLC).
+ NvDdkSecBootDeviceType_Nand = 1,
+
+ // Specifies NOR flash.
+ NvDdkSecBootDeviceType_Nor,
+
+ // Specifies SPI flash.
+ NvDdkSecBootDeviceType_Spi,
+
+ // Specifies eMMC flash
+ // @note eSD is only supported on Tegra 2 devices.
+ NvDdkSecBootDeviceType_eMMC,
+
+ // Specifies 16-bit NAND flash.
+ NvDdkSecBootDeviceType_Nand_x16,
+
+ // Specifies mobileLBA NAND flash (Tegra 2 only).
+ NvDdkSecBootDeviceType_MobileLbaNand,
+
+ // Specifies SD flash.
+ // @note eSD is only supported on Tegra 2 devices.
+ NvDdkSecBootDeviceType_Sdmmc,
+
+ // Specifies MuxOneNAND flash (Tegra 2 only).
+ NvDdkSecBootDeviceType_MuxOneNand,
+
+ // Specifies the maximum number of flash device types
+ // -- Should appear after the last legal item.
+ NvDdkSecBootDeviceType_Max,
+
+ // Undefined.
+ NvDdkSecBootDeviceType_Undefined,
+
+ // Ignore -- Forces compilers to make 32-bit enums.
+ NvDdkSecBootDeviceType_Force32 = 0x7FFFFFFF
+} NvDdkSecBootDeviceType;
+
+/** @} */
+
+#endif // INCLUDED_NVDDK_BOOTDEVICES_H
+
diff --git a/arch/arm/mach-tegra/include/nvddk_fuse.h b/arch/arm/mach-tegra/include/nvddk_fuse.h
new file mode 100644
index 000000000000..52796d3c86f8
--- /dev/null
+++ b/arch/arm/mach-tegra/include/nvddk_fuse.h
@@ -0,0 +1,423 @@
+/*
+ * Copyright (c) 2010 NVIDIA Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NVIDIA Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef INCLUDED_NVDDK_FUSE_H
+#define INCLUDED_NVDDK_FUSE_H
+
+#include "nvrm_module.h"
+/**
+ * @defgroup nvddk_fuse_group Fuse Programming APIs
+ *
+ * Enables fuse programming.
+ *
+ * @par Library Usage
+ *
+ * - Calling the NvDdkDisableFuseProgram() API before exiting the boot loader
+ * disables further fuse programming until the next system reset. (See the
+ * example code.)
+ * - It is advised that you disable the JTAG while using this code in
+ * the final version.
+ * - Enabling clock and voltage to program the fuse is out of scope of this
+ * library. You must ensure that these are enabled prior to using the library
+ * functions.
+ * - The library works on physical mapped memory or on virtual mapped with
+ * one-to-one mapping for the fuse registers.
+ *
+ * @par Example Code
+ *
+ * The following example shows one way to use Fuse Programming APIs.
+ * @note You must ensure fuse clock and fuse voltage is enabled prior
+ * to programming fuses.
+ *
+ * @code
+ * //
+ * // Fuse Programming Example
+ * //
+ * #include "nvddk_fuse.h"
+ * #include "nvtest.h"
+ * #include "nvrm_init.h"
+ * #include "nvrm_pmu.h"
+ * #include "nvodm_query_discovery.h"
+ * #include "nvodm_services.h"
+ *
+ * #define DISABLE_PROGRMING_TEST 0
+ *
+ * static NvError NvddkFuseProgramTest(NvTestApplicationHandle h )
+ * {
+ * NvError err = NvSuccess;
+ * err = NvDdkFuseProgram();
+ * if(err != NvError_Success)
+ * {
+ * NvOsDebugPrintf("NvDdkFuseProgram failed \n");
+ * return err;
+ * }
+ * // Check fuse sense.
+ * NvDdkFuseSense();
+ * // Verify the fuses and return the result.
+ * err = NvDdkFuseVerify();
+ * if(err != NvError_Success)
+ * NvOsDebugPrintf("NvDdkFuseVerify failed \n");
+ * return err;
+ * }
+ *
+ * static NvError PrepareFuseData(void)
+ * {
+ * // Initialize argument sizes to zero to perform initial queries.
+ * NvU32 BootDevSel_Size = 0;
+ * NvU32 BootDevConfig_Size = 0;
+ * NvU32 ResevOdm_size = 0;
+ * NvU32 size = 0;
+ *
+ * // Specify values to be programmed.
+ * NvU16 BootDevConfig_Data = 0x9; // Set device config value to 0x9.
+ * NvU8 BootDevSel_Data = 0x1; // Set boot select to 0x1 for NAND.
+ * NvU8 ResevOdm_Data[32] = {0xEF,0xCD,0xAB,0x89,
+ * 0x78,0x56,0x34,0x12,
+ * 0xa,0xb,0xc,0xd,
+ * 0xAA,0xBB,0xCC,0xDD,
+ * 0,0,0,0,
+ * 0,0,0,0,
+ * 0x78,0x56,0x34,0x12,
+ * 0x78,0x56,0x34,0x12};
+ *
+ * NvU8 skpDevSelStrap_data = 1;
+ * NvError e;
+ *
+ * // Query the sizes of the fuse values.
+ * e = NvDdkFuseGet(NvDdkFuseDataType_SecBootDeviceSelect,
+ * &BootDevSel_Data, &BootDevSel_Size);
+ * if (e != NvError_Success) return e;
+ *
+ * e = NvDdkFuseGet(NvDdkFuseDataType_SecBootDeviceConfig,
+ * &BootDevConfig_Data, &BootDevConfig_Size);
+ * if (e != NvError_Success) return e;
+ *
+ * #ifdef DISABLE_PROGRMING_TEST
+ * NvDdkDisableFuseProgram();
+ * #endif
+ *
+ * e = NvDdkFuseGet(NvDdkFuseDataType_ReservedOdm,
+ * &ResevOdm_Data, &ResevOdm_size);
+ * if (e != NvError_Success) return e;
+ *
+ * e = NvDdkFuseGet(NvDdkFuseDataType_SkipDevSelStraps,
+ * &skpDevSelStrap_data, &size);
+ * if (e != NvError_Success) return e;
+ *
+ *
+ * // Set the fuse values.
+ * e = NvDdkFuseSet(NvDdkFuseDataType_SecBootDeviceSelect,
+ * &BootDevSel_Data, &BootDevSel_Size);
+ * if (e != NvError_Success) return e;
+ *
+ * e = NvDdkFuseSet(NvDdkFuseDataType_SecBootDeviceConfig,
+ * &BootDevConfig_Data, &BootDevConfig_Size);
+ * if (e != NvError_Success) return e;
+ *
+ * e = NvDdkFuseSet(NvDdkFuseDataType_SkipDevSelStraps,
+ * &skpDevSelStrap_data, &size);
+ * if (e != NvError_Success) return e;
+ *
+ *
+ * e = NvDdkFuseSet(NvDdkFuseDataType_ReservedOdm,
+ * &ResevOdm_Data, &ResevOdm_size);
+ * if (e != NvError_Success) return e;
+ *
+ * return e;
+ * }
+ *
+ *
+ * NvError NvTestMain(int argc, char *argv[])
+ * {
+ * NvTestApplication h;
+ * NvError err;
+ *
+ * NVTEST_INIT( &h );
+ * // Enable fuse clock and fuse voltage prior to programming fuses.
+ * err = PrepareFuseData();
+ * if( err != NvSuccess)
+ * return err;
+ *
+ * NvOdmOsWaitUS(10000);
+ *
+ * NVTEST_RUN(&h, NvddkFuseProgramTest);
+ *
+ * NVTEST_RESULT( &h );
+ * }
+ * @endcode
+ *
+ * @ingroup nvddk_modules
+ * @{
+ */
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+
+#include "nvcommon.h"
+#include "nverror.h"
+
+
+/* ----------- Program/Verify API's -------------- */
+
+/**
+ * Defines types of fuse data to set or query.
+ */
+typedef enum
+{
+ /// Specifies a default (unset) value.
+ NvDdkFuseDataType_None = 0,
+
+ /// Specifies a device key (DK).
+ NvDdkFuseDataType_DeviceKey,
+
+ /**
+ * Specifies a JTAG disable flag:
+ * - NV_TRUE specifies to permanently disable JTAG-based debugging.
+ * - NV_FALSE indicates that JTAG-based debugging is not permanently
+ * disabled.
+ */
+ NvDdkFuseDataType_JtagDisable,
+
+ /**
+ * Specifies a key programmed flag (read-only):
+ * - NV_TRUE indicates that either the SBK or the DK value is nonzero.
+ * - NV_FALSE indicates that both the SBK and DK values are zero (0).
+ *
+ * @note Once the ODM production fuse is set to NV_TRUE, applications
+ * can no longer read back the SBK or DK value; however, by using
+ * this \c KeyProgrammed query it is still possible to determine
+ * whether or not the SBK or DK has been programmed to a nonzero value.
+ */
+ NvDdkFuseDataType_KeyProgrammed,
+
+ /**
+ * Specifies an ODM production flag:
+ * - NV_TRUE specifies the chip is in ODM production mode.
+ * - NV_FALSE indicates that the chip is not in ODM production mode.
+ */
+ NvDdkFuseDataType_OdmProduction,
+
+ /**
+ * Specifies a secondary boot device configuration.
+ * This value is chip-dependent.
+ * For Tegra APX 2600, use the NVBOOT_FUSE_*_CONFIG_*
+ * defines from:
+ * <pre>
+ * /src/drivers/hwinc/ap15/nvboot_fuse.h
+ * </pre>
+ */
+ NvDdkFuseDataType_SecBootDeviceConfig,
+
+ /**
+ * Specifies a secondary boot device selection.
+ * This value is chip-independent and is described in \c nvddk_bootdevices.h.
+ * The chip-dependent version of this data is
+ * ::NvDdkFuseDataType_SecBootDeviceSelectRaw.
+ * For Tegra APX 2600, the values for \c SecBootDeviceSelect and
+ * \c SecBootDeviceSelectRaw are identical.
+ */
+ NvDdkFuseDataType_SecBootDeviceSelect,
+
+ /** Specifies a secure boot key (SBK). */
+ NvDdkFuseDataType_SecureBootKey,
+
+ /**
+ * Specifies a stock-keeping unit (read-only).
+ * This value is chip-dependent.
+ * See chip-specific documentation for legal values.
+ */
+ NvDdkFuseDataType_Sku,
+
+ /**
+ * Specifies spare fuse bits (read-only).
+ * Reserved for future use by NVIDIA.
+ */
+ NvDdkFuseDataType_SpareBits,
+
+ /**
+ * Specifies software reserved fuse bits (read-only).
+ * Reserved for future use by NVIDIA.
+ */
+ NvDdkFuseDataType_SwReserved,
+
+ /**
+ * Specifies skip device select straps (applies to Tegra 200 series only):
+ * - NV_TRUE specifies to ignore the device selection straps setting
+ * and that the boot device is specified via the
+ * \c SecBootDeviceSelect and \c SecBootDeviceConfig fuse settings.
+ * - NV_FALSE indicates that the boot device is specified via the device
+ * selection straps setting.
+ */
+ NvDdkFuseDataType_SkipDevSelStraps,
+
+ /**
+ * Specifies a secondary boot device selection.
+ * This value is chip-dependent.
+ * The chip-independent version of this data is
+ * ::NvDdkFuseDataType_SecBootDeviceSelect.
+ * For Tegra APX 2600, use the \c NvBootFuseBootDevice enum
+ * values found at:
+ * <pre>
+ * /src/drivers/hwinc/ap15/nvboot_fuse.h
+ * </pre>
+ */
+ NvDdkFuseDataType_SecBootDeviceSelectRaw,
+
+ /**
+ * Specifies raw field for reserved the ODM.
+ * This value is ODM-specific. Reserved for customers.
+ */
+ NvDdkFuseDataType_ReservedOdm,
+
+ /** The following must be last. */
+ NvDdkFuseDataType_Num,
+ /** Ignore -- Forces compilers to make 32-bit enums. */
+ NvDdkFuseDataType_Force32 = 0x7FFFFFFF
+} NvDdkFuseDataType;
+
+// Gets the base address for Fuse anc CAR modules.
+// Call this function before accessing any other API of Fuse.
+NvError NvDdkFuseOpen(NvRmDeviceHandle hRmDevice);
+
+// to free up all resources
+void NvDdkFuseClose(void);
+/**
+ * Gets a value from the fuse registers.
+ *
+ *@pre NvDdkFuseOpen should have been called before using this API
+ * @pre Do not call this function while the programming power is applied!
+ *
+ * After programming fuses and removing the programming power,
+ * NvDdkFuseSense() must be called to read the new values.
+ *
+ * By passing a size of 0, the caller is requesting to be told the
+ * expected size.
+ *
+ * Treatment of fuse data depends upon its size:
+ * - if \a *pSize == 1, treat \a *pData as an NvU8
+ * - if \a *pSize == 2, treat \a *pData as an NvU16
+ * - if \a *pSize == 4, treat \a *pData as an NvU32
+ * - else, treat \a *pData as an array of NvU8 values (i.e., NvU8[]).
+ */
+NvError NvDdkFuseGet(NvDdkFuseDataType Type, void *pData, NvU32 *pSize);
+
+/**
+ * Schedules fuses to be programmed to the specified values when the next
+ * NvDdkFuseProgram() operation is performed.
+ *
+ *@pre NvDdkFuseOpen should have been called before using this API
+ *
+ * @note Attempting to program the ODM production fuse at the same
+ * time as the SBK or DK causes an error, because it is not
+ * possible to verify that the SBK or DK were programmed correctly.
+ * After triggering this error, all further attempts to set fuse
+ * values will fail, as will \c NvDdkFuseProgram, until NvDdkFuseClear()
+ * has been called.
+ *
+ * By passing a size of 0, the caller is requesting to be told the
+ * expected size.
+ *
+ * Treatment of fuse data depends upon its size:
+ * - if \a *pSize == 1, treat \a *pData as an NvU8
+ * - if \a *pSize == 2, treat \a *pData as an NvU16
+ * - if \a *pSize == 4, treat \a *pData as an NvU32
+ * - else, treat \a *pData as an array of NvU8 values (i.e., NvU8[]).
+ *
+ * @retval NvError_BadValue If other than "reserved ODM fuse" is set in ODM
+ * production mode.
+ * @retval NvError_AccessDenied If programming to fuse registers is disabled.
+ */
+NvError NvDdkFuseSet(NvDdkFuseDataType Type, void *pData, NvU32 *pSize);
+
+/**
+ * Reads the current fuse data into the fuse registers.
+ *
+ *@pre NvDdkFuseOpen should have been called before using this API
+ *
+ * \c NvDdkFuseSense must be called at least once, either:
+ * - After programming fuses and removing the programming power,
+ * - Prior to calling NvDdkFuseVerify(), or
+ * - Prior to calling NvDdkFuseGet().
+ */
+void NvDdkFuseSense(void);
+
+/**
+ * Programs all fuses based on cache data changed via the NvDdkFuseSet() API.
+ *
+ *@pre NvDdkFuseOpen should have been called before using this API
+ *
+ * @pre Prior to invoking this routine, the caller is responsible for supplying
+ * valid fuse programming voltage.
+ *
+ * @retval NvError_AccessDenied If programming to fuse registers is disabled.
+ * @return An error if an invalid combination of fuse values was provided.
+ */
+NvError NvDdkFuseProgram(void);
+
+/**
+ * Verify all fuses scheduled via the NvDdkFuseSet() API.
+ *
+ *@pre NvDdkFuseOpen should have been called before using this API
+ *
+ * @pre Prior to invoking this routine, the caller is responsible for ensuring
+ * that fuse programming voltage is removed and subsequently calling
+ * NvDdkFuseSense().
+ */
+NvError NvDdkFuseVerify(void);
+
+/**
+ * Clears the cache of fuse data, once NvDdkFuseProgram() and NvDdkFuseVerify()
+ * API are called to clear all buffers.
+ *
+ *@pre NvDdkFuseOpen should have been called before using this API
+ */
+void NvDdkFuseClear(void);
+
+
+/**
+ * Disables further fuse programming until the next system reset.
+ *
+ *@pre NvDdkFuseOpen should have been called before using this API
+ */
+void NvDdkDisableFuseProgram(void);
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+/** @} */
+#endif // INCLUDED_NVDDK_FUSE_H
+
diff --git a/arch/arm/mach-tegra/include/nvddk_operatingmodes.h b/arch/arm/mach-tegra/include/nvddk_operatingmodes.h
new file mode 100644
index 000000000000..5cda2df6891b
--- /dev/null
+++ b/arch/arm/mach-tegra/include/nvddk_operatingmodes.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2010 NVIDIA Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NVIDIA Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef INCLUDED_NVDDK_OPERATINGMODES_H
+#define INCLUDED_NVDDK_OPERATINGMODES_H
+
+/**
+ * @defgroup nvddk_operatingmodes_group Operating Modes
+ *
+ * Provides operating mode information for NVIDIA Boot Loader functions.
+ *
+ * @ingroup nvddk_group
+ * @{
+ */
+
+/**
+ * Defines the supported operating modes.
+ */
+typedef enum
+{
+ // Specifies development mode; boot loader is validated using a fixed key of zeroes.
+ NvDdkOperatingMode_NvProduction = 3,
+
+ // Specifies production mode; boot loader is decrypted using the Secure Boot Key,
+ // then validated using the Secure Boot Key.
+ NvDdkOperatingMode_OdmProductionSecure,
+
+ // Specifies ODM production mode; boot loader is validated using the Secure Boot Key.
+ NvDdkOperatingMode_OdmProductionOpen,
+
+ // Undefined.
+ NvDdkOperatingMode_Undefined,
+
+ // Ignore -- Forces compilers to make 32-bit enums.
+ NvDdkOperatingMode_Force32 = 0x7FFFFFFF
+} NvDdkOperatingMode;
+
+/** @} */
+
+#endif // INCLUDED_NVDDK_OPERATINGMODES_H
+
diff --git a/arch/arm/mach-tegra/include/nvodm_query_discovery.h b/arch/arm/mach-tegra/include/nvodm_query_discovery.h
index 1a109fd8381e..74f8777616ee 100644
--- a/arch/arm/mach-tegra/include/nvodm_query_discovery.h
+++ b/arch/arm/mach-tegra/include/nvodm_query_discovery.h
@@ -55,7 +55,7 @@
* 64-bit value (8-character code) that uniquely identifies each peripheral,
* i.e., each peripheral will have exactly one GUID, and each GUID will refer
* to exactly one peripheral.
- *
+ *
* The implementation of this API is similar to a simple database: tables are
* provided by the ODMs that, for every peripheral, define the peripheral's
* GUID, and specify the bus, or set of buses, to which the peripheral is
@@ -140,6 +140,7 @@ extern "C"
#define NV_PMU_TRANSPORT_ODM_ID (NV_ODM_GUID('N','V','P','M','U','T','R','N'))
+#define NV_VDD_FUSE_ODM_ID (NV_ODM_GUID('N','V','D','D','F','U','S','E'))
/**
* Some of the NVIDIA driver libraries enumerate peripherals based on the
* logical functionality that the peripheral performs, rather than by the
@@ -172,10 +173,10 @@ typedef enum
NvOdmPeripheralClass_Force32 = 0x7fffffffUL
} NvOdmPeripheralClass;
-/**
+/**
* Defines the unique address on a bus where a peripheral is connected.
*/
-typedef struct
+typedef struct
{
/// Specifies the type of bus or I/O (I2C, DAP, GPIO) for this connection.
NvOdmIoModule Interface;
@@ -194,7 +195,7 @@ typedef struct
/**
* Some buses, such as I2C and SPI, support multiple slave devices on
- * a single bus, through the use of peripheral addresses and/or chip
+ * a single bus, through the use of peripheral addresses and/or chip
* select signals. This value specifies the appropriate address or chip
* select required to communicate with the peripheral.
*
@@ -212,7 +213,7 @@ typedef struct
* Defines the full bus connectivity for peripherals connected to the
* application processor.
*/
-typedef struct
+typedef struct
{
/// The ODM-defined 64-bit GUID that identifies this peripheral.
NvU64 Guid;
@@ -232,7 +233,7 @@ typedef struct
/// Defines different criteria for searching through the peripheral database.
-typedef enum
+typedef enum
{
/// Searches for peripherals that are members of the specified class.
NvOdmPeripheralSearch_PeripheralClass,
@@ -240,7 +241,7 @@ typedef enum
/// Searches for peripherals connected to the specified I/O module.
NvOdmPeripheralSearch_IoModule,
- /**
+ /**
* Searches for peripherals connected to the specified bus instance.
*
* @note This value will be compared against all entries in \a addressList.
@@ -259,7 +260,7 @@ typedef enum
NvOdmPeripheralSearch_Force32 = 0x7fffffffUL
} NvOdmPeripheralSearch;
-/**
+/**
* Defines the data structure that describes each sub-assembly of the
* development platform. This data is read from EEPROMs on each of the sub-
* assemblies, which is saved with the following format:
@@ -269,13 +270,13 @@ typedef enum
*
* Where:
*
- * - xxxx is the board ID number 0-9999 (2 byte number)
- * - yyyy is the SKU number 0-9999 (2 byte number)
- * - zz is the FAB number 0-99 (1 byte number)
+ * - xxxx is the board ID number 0-9999 (2 byte number)
+ * - yyyy is the SKU number 0-9999 (2 byte number)
+ * - zz is the FAB number 0-99 (1 byte number)
* - X is the major revision, (1 byte ASCII character), e.g., 'A', 'B', etc.
* - N is the minor revision, (1 byte number, 0 - 9)
*/
-typedef struct
+typedef struct
{
/// Specifies the board number.
NvU16 BoardID;
@@ -327,10 +328,10 @@ NvOdmPeripheralEnumerate(
/**
* Searches through the database of connected peripherals for the peripheral
- * matching the specified GUID and returns that peripheral's connectivity
+ * matching the specified GUID and returns that peripheral's connectivity
* structure.
*
- * @note If the ODM system supports hot-pluggable peripherals (e.g., an
+ * @note If the ODM system supports hot-pluggable peripherals (e.g., an
* external TV-out display), the connectivity structure should only be returned
* when the peripheral is useable by the NVIDIA driver libraries. If hot-plug
* detection is not supported, the peripheral's connectivity structure may
@@ -348,13 +349,13 @@ NvOdmPeripheralGetGuid(NvU64 searchGuid);
/**
* Gets the ::NvOdmBoardInfo data structure values for the given board ID.
- *
+ *
* @param BoardId Identifies the board for which the BoardInfo data is to be retrieved.
* @note The \a BoardId is in Binary Encoded Decimal (BCD) format. For example,
* E920 is identified by a \a BoardId of 0x0920 and E9820 would be 0x9820.
* @param pBoardInfo A pointer to the location where the requested \a BoardInfo data
* shall be saved.
- *
+ *
* @return NV_TRUE if successful, or NV_FALSE otherwise.
*/
NvBool
@@ -367,5 +368,4 @@ NvOdmPeripheralGetBoardInfo(
#endif
/** @} */
-
#endif // INCLUDED_NVODM_QUERY_DISCOVERY_H
diff --git a/arch/arm/mach-tegra/nvddk/Makefile b/arch/arm/mach-tegra/nvddk/Makefile
index f1b5da42d5c8..b839f6e2590e 100644
--- a/arch/arm/mach-tegra/nvddk/Makefile
+++ b/arch/arm/mach-tegra/nvddk/Makefile
@@ -16,6 +16,8 @@ obj-y += nvddk_usbphy_ap16.o
obj-y += nvddk_usbphy_ap20.o
endif
+obj-y += nvddk_fuse_ap20.o
+
obj-$(CONFIG_MTD_NAND_TEGRA) += nvddk_nand.o
obj-$(CONFIG_TEGRA_SNOR) += nvsnor_controller.o
diff --git a/arch/arm/mach-tegra/nvddk/nvddk_fuse_ap20.c b/arch/arm/mach-tegra/nvddk/nvddk_fuse_ap20.c
new file mode 100644
index 000000000000..804be01ddf89
--- /dev/null
+++ b/arch/arm/mach-tegra/nvddk/nvddk_fuse_ap20.c
@@ -0,0 +1,1642 @@
+/*
+ * Copyright (c) 2010 NVIDIA Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NVIDIA Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "fuse_bitmap.h"
+#include "ap20/arclk_rst.h"
+#include "ap20/arfuse.h"
+#include "nvddk_bootdevices.h"
+#include "nvddk_operatingmodes.h"
+#include "nvddk_fuse.h"
+#include "nvrm_hardware_access.h"
+#include "nvassert.h"
+#include "nvrm_drf.h"
+#include "nvos.h"
+#include "nvodm_query_discovery.h"
+#include "nvodm_services.h"
+#include "nvrm_pmu.h"
+
+// Set below macro to 0, to disable voltage required for Fuse programming.
+#define ENABLE_FUSE_VOLTAGE 1
+// By setting below macro to 1, a dummy interface of fuse is enabled for
+// verifying sysfs interface.
+#define FUSE_DUMMY_CODE 0
+// Set below macro to 1 to get prints during fuse read/ program operations.
+#define ENABLE_DEBUG_PRINTS 0
+
+#define FUSE_BOOT_DEVICE_INFO_0_BOOT_DEVICE_CONFIG_RANGE 13:0
+#define FUSE_RESERVED_SW_0_BOOT_DEVICE_SELECT_RANGE 2:0
+#define FUSE_RESERVED_SW_0_SKIP_DEV_SEL_STRAPS_RANGE 3:3
+#define FUSE_RESERVED_SW_0_SW_RESERVED_RANGE 7:4
+
+#define FLAGS_PROGRAM_SECURE_BOOT_KEY 0x001
+#define FLAGS_PROGRAM_DEVICE_KEY 0x002
+#define FLAGS_PROGRAM_JTAG_DISABLE 0x004
+#define FLAGS_PROGRAM_BOOT_DEV_SEL 0x008
+#define FLAGS_PROGRAM_BOOT_DEV_CONFIG 0x010
+#define FLAGS_PROGRAM_SW_RESERVED 0x020
+#define FLAGS_PROGRAM_ODM_PRODUCTION 0x040
+#define FLAGS_PROGRAM_SPARE_BITS 0x080
+#define FLAGS_PROGRAM_SKIP_DEV_SEL_STRAPS 0x100
+#define FLAGS_PROGRAM_RESERVED_ODM 0x200
+
+#define FLAGS_PROGRAM_ILLEGAL 0x80000000
+
+#define NVDDK_DEVICE_KEY_BYTES (4)
+#define NVDDK_SECURE_BOOT_KEY_BYTES (16)
+#define NVDDK_RESERVED_ODM_BYTES (32)
+
+#define NVDDK_TPROGRAM_VALUE_CORRECTED 0
+
+// Number of words of fuses as defined by the hardware.
+#define FUSE_WORDS 64
+
+/*
+ * Representation of the fuse data.
+ *
+ */
+typedef struct NvDdkFuseDataRec
+{
+ // Specifies the Secure Boot Key (SBK).
+ NvU8 SecureBootKey[NVDDK_SECURE_BOOT_KEY_BYTES];
+
+ // Specifies the Device Key (DK).
+ NvU8 DeviceKey[NVDDK_DEVICE_KEY_BYTES];
+
+ // Specifies the JTAG Disable fuse value.
+ NvBool JtagDisable;
+
+ // Specifies the device selection value in terms of the API.
+ NvU32 SecBootDeviceSelect;
+
+ // Specifies the device selection value in the actual fuses.
+ NvU32 SecBootDeviceSelectRaw;
+
+ // Specifies the device configuration value (right aligned).
+ NvU32 SecBootDeviceConfig;
+
+ // Specifies the SwReserved value.
+ NvU32 SwReserved;
+
+ // Specifies the ODM Production fuse value.
+ NvBool OdmProduction;
+
+ // Specifies the SkipDevSelStraps value.
+ NvU32 SkipDevSelStraps;
+
+ // Specifies the Reserved Odm value
+ NvU8 ReservedOdm[NVDDK_RESERVED_ODM_BYTES];
+
+ // Flags that indicate what to program.
+ NvU32 ProgramFlags;
+
+ // Flag indicates whether reservedodm fuses are setting or not
+ NvBool ReservedOdmFlag;
+} NvDdkFuseData;
+
+static NvDdkFuseData s_FuseData = {{0}};
+
+typedef enum
+{
+ FuseBootDev_Sdmmc,
+ FuseBootDev_SnorFlash,
+ FuseBootDev_SpiFlash,
+ FuseBootDev_NandFlash,
+ FuseBootDev_NandFlash_x8 = FuseBootDev_NandFlash,
+ FuseBootDev_NandFlash_x16 = FuseBootDev_NandFlash,
+ FuseBootDev_MobileLbaNand,
+ FuseBootDev_MuxOneNand,
+ FuseBootDev_Max, /* Must appear after the last legal item */
+ FuseBootDev_Force32 = 0x7fffffff
+} FuseBootDev;
+
+// Holds various params that are needed by Fuse module.
+typedef struct NvDdkFuseRec
+{
+ // Fuse registers physical base address
+ NvRmPhysAddr pBaseAddress;
+ // Holds the virtual address for accessing registers.
+ NvU32 *pVirtualAddress;
+ // Holds the register map size.
+ NvU32 BankSize;
+
+ // Fuse registers physical base address
+ NvRmPhysAddr pCarBaseAddress;
+ // Holds the virtual address for accessing registers.
+ NvU32 *pCarVirtualAddress;
+ // Holds the register map size.
+ NvU32 CarBankSize;
+
+ // Mutex for fuse
+ NvOsMutexHandle Mutex;
+}NvDdkFuse;
+
+static NvDdkFuse* s_pFuseRec = NULL;
+
+// Size of the data items, in bytes
+static NvU32 s_DataSize[] =
+{
+ 0, // FuseDataType_None
+ sizeof(NvU64), // FuseDataType_DeviceKey
+ sizeof(NvBool), // FuseDataType_JtagDisable
+ sizeof(NvBool), // FuseDataType_KeyProgrammed
+ sizeof(NvBool), // FuseDataType_OdmProductionEnable
+ sizeof(NvU32), // FuseDataType_SecBootDeviceConfig
+ sizeof(NvU32), // FuseDataType_SecBootDeviceSelect
+ NVDDK_SECURE_BOOT_KEY_BYTES, // FuseDataType_SecureBootKey
+ sizeof(NvU32), // FuseDataType_Sku
+ sizeof(NvU32), // FuseDataType_SpareBits
+ sizeof(NvU32), // FuseDataType_SwReserved
+ sizeof(NvBool), // FuseDataType_SkipDevSelStraps
+ sizeof(NvU32), // FuseDataType_SecBootDeviceSelectRaw
+ NVDDK_RESERVED_ODM_BYTES // NvDdkFuseDataType_ReservedOdm fuse
+};
+
+
+// Map NvDdkSecBootDeviceType enum onto AP20 Boot Device Selection values.
+static NvU32 NvDdkToFuseBootDeviceSel[] =
+{
+ FuseBootDev_Sdmmc, // None
+ FuseBootDev_NandFlash, // NvDdkSecBootDeviceType_Nand
+ FuseBootDev_SnorFlash, // NvDdkSecBootDeviceType_Nor
+ FuseBootDev_SpiFlash, // NvDdkSecBootDeviceType_Spi_Flash
+ FuseBootDev_Sdmmc, // NvDdkSecBootDeviceType_eMMC
+ FuseBootDev_NandFlash, // NvDdkSecBootDeviceType_Nand_x16
+ FuseBootDev_MobileLbaNand, // NvDdkSecBootDeviceType_MobileLbaNand
+ FuseBootDev_Sdmmc, // NvDdkSecBootDeviceType_eMMC
+ FuseBootDev_MuxOneNand, // NvDdkSecBootDeviceType_MuxOneNand
+};
+
+// Map AP20 fuse values onto NvDdkSecBootDeviceType enum values.
+static NvU32 FuseToNvDdkBootDeviceSel[] =
+{
+ NvDdkSecBootDeviceType_Sdmmc, // FuseBootDev_Sdmmc
+ NvDdkSecBootDeviceType_Nor, // FuseBootDev_SnorFlash
+ NvDdkSecBootDeviceType_Spi, // FuseBootDev_SpiFlash
+ NvDdkSecBootDeviceType_Nand, // FuseBootDev_NandFlash
+ NvDdkSecBootDeviceType_MobileLbaNand, // FuseBootDev_MobileLbaNand
+ NvDdkSecBootDeviceType_MuxOneNand, // FuseBootDev_MuxOneNand
+};
+
+// Storage for the array of fuse words & mask words.
+static NvU32 s_FuseArray [FUSE_WORDS] = { 0 };
+static NvU32 s_MaskArray [FUSE_WORDS] = { 0 };
+static NvU32 s_TempFuseData[FUSE_WORDS];
+
+
+#define FUSE_NV_READ32(offset) \
+ NV_READ32(s_pFuseRec->pVirtualAddress + (offset >> 2))
+
+#define FUSE_NV_WRITE32(offset, val) \
+ NV_WRITE32((s_pFuseRec->pVirtualAddress + (offset >> 2)), val)
+
+#define CLOCK_NV_READ32(offset) \
+ NV_READ32(s_pFuseRec->pCarVirtualAddress + (offset >> 2))
+
+#define CLOCK_NV_WRITE32(offset, val) \
+ NV_WRITE32((s_pFuseRec->pCarVirtualAddress + (offset >> 2)), val)
+
+// Macro to get the difference between two numbers T1 & T2 and T1 > T2.
+#define DIFF(T1, T2) \
+ (((T1) > (T2)) ? ((T1) - (T2)) : ((T2) - (T1)))
+// For rollover proof,
+// (((T1) > (T2)) ? ((T1) - (T2)) : ((T1) + ((NvU64)0xFFFFFFFFFFFFFFFF - (T2))))
+
+static void NvFuseUtilWaitUS(NvU32 usec)
+{
+ NvU64 t0;
+ NvU64 t1;
+
+ t0 = NvOsGetTimeUS();
+ t1 = t0;
+ // Use the difference for the comparison to be wraparound safe
+ while (DIFF(t1, t0) < usec)
+ {
+ t1 = NvOsGetTimeUS();
+ }
+}
+
+static void fusememset(void* Source, NvU8 val, NvU32 size)
+{
+ NvOsMemset(Source, val, size);
+}
+
+static void fusememcpy(void* Destination, void* Source, NvU32 size)
+{
+ NvOsMemcpy(Destination, Source, size);
+}
+/**
+ * Reports whether any of the SBK fuses are set (burned)
+ *
+ * @param none
+ *
+ * @return NV_TRUE if the SBK is non-zero
+ * @return NV_FALSE otherwise
+ */
+static NvBool NvDdkFuseIsSbkSet(void)
+{
+ NvU32 AllKeysOred;
+ AllKeysOred = FUSE_NV_READ32(FUSE_PRIVATE_KEY0_NONZERO_0);
+ AllKeysOred |= FUSE_NV_READ32(FUSE_PRIVATE_KEY1_NONZERO_0);
+ AllKeysOred |= FUSE_NV_READ32(FUSE_PRIVATE_KEY2_NONZERO_0);
+ AllKeysOred |= FUSE_NV_READ32(FUSE_PRIVATE_KEY3_NONZERO_0);
+ if (AllKeysOred)
+ return NV_TRUE;
+ else
+ return NV_FALSE;
+}
+
+/**
+ * Reports whether any of the SBK or DK fuses are set (burned)
+ *
+ * @param none
+ *
+ * @return NV_TRUE if the SBK or the DK is non-zero
+ * @return NV_FALSE otherwise
+ */
+static NvBool IsSbkOrDkSet(void)
+{
+ NvU32 AllKeysOred;
+
+ AllKeysOred = NvDdkFuseIsSbkSet();
+ AllKeysOred |= FUSE_NV_READ32(FUSE_PRIVATE_KEY4_NONZERO_0);
+
+ if (AllKeysOred)
+ return NV_TRUE;
+ else
+ return NV_FALSE;
+}
+
+
+/**
+ * Reports whether the ODM Production Mode fuse is set (burned)
+ *
+ * Note that this fuse by itself does not determine whether the chip is in
+ * ODM Production Mode.
+ *
+ * @param none
+ *
+ * @return NV_TRUE if ODM Production Mode fuse is set (burned); else NV_FALSE
+ */
+static NvBool NvDdkFuseIsOdmProductionModeFuseSet(void)
+{
+ NvU32 RegValue;
+ RegValue = FUSE_NV_READ32(FUSE_SECURITY_MODE_0);
+ if (RegValue)
+ {
+ return NV_TRUE;
+ }
+ else
+ {
+ return NV_FALSE;
+ }
+}
+
+
+/**
+ * Reports whether the Disable Register Program register is set.
+ *
+ * @param none
+ *
+ * @return NV_TRUE if Disable reg program is iset, else NV_FALSE
+ */
+
+static NvBool NvDdkPrivIsDisableRegProgramSet(void)
+{
+ NvU32 RegValue;
+ RegValue = FUSE_NV_READ32(FUSE_DISABLEREGPROGRAM_0);
+ if (RegValue)
+ {
+ return NV_TRUE;
+ }
+ else
+ {
+ return NV_FALSE;
+ }
+}
+
+static NvBool NvDdkFuseIsOdmProductionMode(void)
+{
+ if (NvDdkFuseIsOdmProductionModeFuseSet())
+ {
+ return NV_TRUE;
+ }
+ return NV_FALSE;
+}
+
+static NvU32 NvDdkFuseGetSecBootDeviceRaw(void)
+{
+ NvU32 RegData;
+
+ RegData = FUSE_NV_READ32(FUSE_RESERVED_SW_0);
+ RegData = NV_DRF_VAL(FUSE, RESERVED_SW, BOOT_DEVICE_SELECT, RegData);
+ if (RegData >= (NvU32) FuseBootDev_Max)
+ {
+ RegData = FuseBootDev_Sdmmc;
+ }
+
+ return RegData;
+}
+
+static NvDdkSecBootDeviceType NvDdkFuseGetSecBootDevice(void)
+{
+ NvU32 RegData;
+ NvDdkSecBootDeviceType SecBootDevice;
+
+ RegData = NvDdkFuseGetSecBootDeviceRaw();
+
+ // Map from AP20 definitions onto NvDdkSecBootDeviceType definitions.
+ SecBootDevice = FuseToNvDdkBootDeviceSel[RegData];
+
+ return SecBootDevice;
+}
+
+// p = prefix, c = copy, i = index, d = data
+
+#define FUSE_BASE(p, c, i) FUSE_##p##__##c##_ALIAS_##i
+#define FUSE_DATA(p, c, i) FUSE_##p##__##c##_ALIAS_##i##_DATA
+#define FUSE_WIDTH(p, c, i) FUSE_##p##__##c##_ALIAS_##i##_WIDTH
+
+#define SET_FUSE(p, c, i, d) \
+ s_FuseArray[FUSE_BASE(p, c, i)] = \
+ (s_FuseArray[FUSE_BASE(p, c, i)] & \
+ ~NV_FIELD_SHIFTMASK(FUSE_DATA(p, c, i))) | \
+ ((d & (NV_FIELD_MASK(FUSE_DATA(p, c, i)))) << \
+ (NV_FIELD_SHIFT(FUSE_DATA(p, c, i))))
+
+#define SET_MASK(p, c, i) \
+ s_MaskArray[FUSE_BASE(p,c,i)] |= NV_FIELD_SHIFTMASK(FUSE_DATA(p,c,i))
+
+#define SET_FUSE_DATA(p, c, i, d) \
+ SET_FUSE(p,c,i,d); \
+ SET_MASK(p,c,i);
+
+#define SET_FUSE_PRI(p, i, d) SET_FUSE_DATA(p, PRI, i, d);
+#define SET_FUSE_RED(p, i, d) SET_FUSE_DATA(p, RED, i, d);
+
+#define SET_FUSE_BOTH(p, i, d) \
+ SET_FUSE_PRI(p,i,d); \
+ SET_FUSE_RED(p,i,d);
+
+// Update fuses with an explicit mask.
+#define SET_FUSE_BOTH_WITH_MASK(p, i, d, md) \
+ SET_FUSE(p, PRI, i, d); \
+ SET_FUSE(p, RED, i, d); \
+ s_MaskArray[FUSE_BASE(p, PRI, i)] |= \
+ (md << NV_FIELD_SHIFT(FUSE_DATA(p, PRI, i))); \
+ s_MaskArray[FUSE_BASE(p, RED, i)] |= \
+ (md << NV_FIELD_SHIFT(FUSE_DATA(p, RED, i)));
+
+#define UPDATE_DATA(p,i,d) (d >>= FUSE_WIDTH(p,PRI,i));
+
+#define SET_SPARE_BIT(n) \
+ SET_FUSE_PRI(SPARE_BIT_##n, 0, Data); \
+ UPDATE_DATA (SPARE_BIT_##n, 0, Data);
+
+
+static void MapDataToFuseArrays(void)
+{
+ NvU32 *Src;
+ NvU32 Data = 0;
+ NvU32 MaskData;
+
+ // Start by clearing the arrays.
+ fusememset(s_FuseArray, 0, sizeof(s_FuseArray));
+ fusememset(s_MaskArray, 0, sizeof(s_MaskArray));
+ // Set ENABLE_FUSE_PROGRAM bit to 1
+ SET_FUSE_BOTH(ENABLE_FUSE_PROGRAM, 0, 1);
+
+ // Reserved Odm fuse
+ if (s_FuseData.ProgramFlags & FLAGS_PROGRAM_RESERVED_ODM)
+ {
+ Src = (NvU32*)(s_FuseData.ReservedOdm);
+ Data = Src[0];
+ SET_FUSE_BOTH(RESERVED_ODM0, 0, Data);
+ UPDATE_DATA (RESERVED_ODM0, 0, Data);
+ SET_FUSE_BOTH(RESERVED_ODM0, 1, Data);
+
+ Data = Src[1];
+ SET_FUSE_BOTH(RESERVED_ODM1, 0, Data);
+ UPDATE_DATA (RESERVED_ODM1, 0, Data);
+ SET_FUSE_BOTH(RESERVED_ODM1, 1, Data);
+
+ Data = Src[2];
+ SET_FUSE_BOTH(RESERVED_ODM2, 0, Data);
+ UPDATE_DATA (RESERVED_ODM2, 0, Data);
+ SET_FUSE_BOTH(RESERVED_ODM2, 1, Data);
+
+ Data = Src[3];
+ SET_FUSE_BOTH(RESERVED_ODM3, 0, Data);
+ UPDATE_DATA (RESERVED_ODM3, 0, Data);
+ SET_FUSE_BOTH(RESERVED_ODM3, 1, Data);
+
+ Data = Src[4];
+ SET_FUSE_BOTH(RESERVED_ODM4, 0, Data);
+ UPDATE_DATA (RESERVED_ODM4, 0, Data);
+ SET_FUSE_BOTH(RESERVED_ODM4, 1, Data);
+
+ Data = Src[5];
+ SET_FUSE_BOTH(RESERVED_ODM5, 0, Data);
+ UPDATE_DATA (RESERVED_ODM5, 0, Data);
+ SET_FUSE_BOTH(RESERVED_ODM5, 1, Data);
+
+ Data = Src[6];
+ SET_FUSE_BOTH(RESERVED_ODM6, 0, Data);
+ UPDATE_DATA (RESERVED_ODM6, 0, Data);
+ SET_FUSE_BOTH(RESERVED_ODM6, 1, Data);
+
+ Data = Src[7];
+ SET_FUSE_BOTH(RESERVED_ODM7, 0, Data);
+ UPDATE_DATA (RESERVED_ODM7, 0, Data);
+ SET_FUSE_BOTH(RESERVED_ODM7, 1, Data);
+ }
+
+ // If Secure mode is set, we can not burn any other fuses, so return.
+ if (NvDdkFuseIsOdmProductionModeFuseSet())
+ {
+ return;
+ }
+
+ if (s_FuseData.ProgramFlags & FLAGS_PROGRAM_JTAG_DISABLE)
+ {
+ Data = (NvU32)(s_FuseData.JtagDisable);
+ SET_FUSE_BOTH(ARM_DEBUG_DIS, 0, Data);
+ }
+
+ if (s_FuseData.ProgramFlags & FLAGS_PROGRAM_ODM_PRODUCTION)
+ {
+ Data = (NvU32)(s_FuseData.OdmProduction);
+ SET_FUSE_BOTH(SECURITY_MODE, 0, Data);
+ }
+
+ // SBK & DK
+ if (s_FuseData.ProgramFlags & FLAGS_PROGRAM_SECURE_BOOT_KEY)
+ {
+ Src = (NvU32*)(s_FuseData.SecureBootKey);
+ Data = Src[0];
+ SET_FUSE_BOTH(PRIVATE_KEY0, 0, Data);
+ UPDATE_DATA (PRIVATE_KEY0, 0, Data);
+ SET_FUSE_BOTH(PRIVATE_KEY0, 1, Data);
+
+ Data = Src[1];
+ SET_FUSE_BOTH(PRIVATE_KEY1, 0, Data);
+ UPDATE_DATA (PRIVATE_KEY1, 0, Data);
+ SET_FUSE_BOTH(PRIVATE_KEY1, 1, Data);
+
+ Data = Src[2];
+ SET_FUSE_BOTH(PRIVATE_KEY2, 0, Data);
+ UPDATE_DATA (PRIVATE_KEY2, 0, Data);
+ SET_FUSE_BOTH(PRIVATE_KEY2, 1, Data);
+
+ Data = Src[3];
+ SET_FUSE_BOTH(PRIVATE_KEY3, 0, Data);
+ UPDATE_DATA (PRIVATE_KEY3, 0, Data);
+ SET_FUSE_BOTH(PRIVATE_KEY3, 1, Data);
+ }
+
+ if (s_FuseData.ProgramFlags & FLAGS_PROGRAM_DEVICE_KEY)
+ {
+ Src = (NvU32*)(s_FuseData.DeviceKey);
+ Data = Src[0];
+ SET_FUSE_BOTH(PRIVATE_KEY4, 0, Data);
+ UPDATE_DATA (PRIVATE_KEY4, 0, Data);
+ SET_FUSE_BOTH(PRIVATE_KEY4, 1, Data);
+ }
+
+ if (s_FuseData.ProgramFlags & FLAGS_PROGRAM_BOOT_DEV_CONFIG)
+ {
+ // BootDeviceConfig is 14 bits so mask other bits
+ Data = (s_FuseData.SecBootDeviceConfig & 0x3FFF);
+ SET_FUSE_BOTH(BOOT_DEVICE_INFO, 0, Data);
+ }
+
+ // Assemble RESERVED_SW
+ if ((s_FuseData.ProgramFlags & FLAGS_PROGRAM_BOOT_DEV_SEL ) ||
+ (s_FuseData.ProgramFlags & FLAGS_PROGRAM_SKIP_DEV_SEL_STRAPS) ||
+ (s_FuseData.ProgramFlags & FLAGS_PROGRAM_SW_RESERVED ))
+ {
+ Data = 0;
+ MaskData = 0;
+
+ if (s_FuseData.ProgramFlags & FLAGS_PROGRAM_BOOT_DEV_SEL)
+ {
+ Data |= (s_FuseData.SecBootDeviceSelectRaw & 0x7);
+ MaskData |= 0x7;
+ }
+
+ if (s_FuseData.ProgramFlags & FLAGS_PROGRAM_SKIP_DEV_SEL_STRAPS)
+ {
+ Data |= ((s_FuseData.SkipDevSelStraps & 0x1) << 3);
+ MaskData |= (0x1 << 3);
+ }
+
+ if (s_FuseData.ProgramFlags & FLAGS_PROGRAM_SW_RESERVED)
+ {
+ Data |= ((s_FuseData.SwReserved & 0xF) << 4);
+ MaskData |= (0xF << 4);
+ }
+
+ SET_FUSE_BOTH_WITH_MASK(RESERVED_SW, 0, Data, MaskData);
+ }
+}
+
+
+static void FuseCopyBytes(NvU32 RegAddress, NvU8 *pByte, const NvU32 nBytes)
+{
+ NvU32 RegData;
+ NvU32 i;
+
+ NV_ASSERT((pByte != NULL) || (nBytes == 0));
+ NV_ASSERT (RegAddress != 0);
+
+ for (i = 0, RegData = 0; i < nBytes; i++)
+ {
+ if ((i&3) == 0)
+ {
+ RegData = FUSE_NV_READ32(RegAddress);
+ RegAddress += 4;
+ }
+ pByte[i] = RegData & 0xFF;
+ RegData >>= 8;
+ }
+}
+
+// Expose (Visibility = 1) or hide (Visibility = 0) the fuse registers.
+static void SetFuseRegVisibility(NvU32 Visibility)
+{
+ NvU32 RegData;
+
+ RegData = CLOCK_NV_READ32(CLK_RST_CONTROLLER_MISC_CLK_ENB_0);
+ RegData = NV_FLD_SET_DRF_NUM(CLK_RST_CONTROLLER,
+ MISC_CLK_ENB,
+ CFG_ALL_VISIBLE,
+ Visibility,
+ RegData);
+ CLOCK_NV_WRITE32(CLK_RST_CONTROLLER_MISC_CLK_ENB_0, RegData);
+}
+
+// Wait for completion (state machine goes idle).
+static void WaitForFuseIdle(void)
+{
+ NvU32 RegData;
+
+ do
+ {
+ RegData = FUSE_NV_READ32(FUSE_FUSECTRL_0);
+ } while (NV_DRF_VAL(FUSE, FUSECTRL, FUSECTRL_STATE, RegData) !=
+ FUSE_FUSECTRL_0_FUSECTRL_STATE_STATE_IDLE);
+}
+
+
+// Start the regulator and wait
+static void StartRegulator(void)
+{
+ NvU32 RegData;
+ RegData = NV_DRF_DEF(FUSE, PWR_GOOD_SW, PWR_GOOD_SW_VAL, PWR_GOOD_OK);
+ FUSE_NV_WRITE32(FUSE_PWR_GOOD_SW_0, RegData);
+ /*
+ * Wait for at least 150ns. In HDEFUSE_64X32_E2F2R2_L1_A.pdf,
+ * this is found on p.11 as TSUP_PWRGD.
+ */
+ NvFuseUtilWaitUS(1);
+}
+
+// Stop the regulator and wait
+static void StopRegulator(void)
+{
+ NvU32 RegData;
+
+ RegData = NV_DRF_DEF(FUSE, PWR_GOOD_SW, PWR_GOOD_SW_VAL, PWR_GOOD_NOT_OK);
+ FUSE_NV_WRITE32(FUSE_PWR_GOOD_SW_0, RegData);
+
+ /*
+ * Wait for at least 150ns. In HDEFUSE_64X32_E2F2R2_L1_A.pdf,
+ * this is found on p.11 as TSUP_PWRGD
+ */
+ NvFuseUtilWaitUS(1);
+}
+
+ /*
+ * Read a word from the fuses.
+ * Note: The fuses must already have been sensed, and
+ * the programming power should be off.
+ */
+static NvU32 ReadFuseWord(NvU32 Addr)
+{
+ NvU32 RegData;
+
+ // Prepare the data
+ FUSE_NV_WRITE32(FUSE_FUSEADDR_0, Addr);
+
+ // Trigger the read
+ RegData = FUSE_NV_READ32(FUSE_FUSECTRL_0);
+ RegData = NV_FLD_SET_DRF_DEF(FUSE, FUSECTRL, FUSECTRL_CMD, READ, RegData);
+ FUSE_NV_WRITE32(FUSE_FUSECTRL_0, RegData);
+
+ // Wait for completion (state machine goes idle).
+ WaitForFuseIdle();
+
+ RegData = FUSE_NV_READ32(FUSE_FUSERDATA_0);
+
+ return RegData;
+}
+
+/*
+ * Write a word to the fuses.
+ * Note: The programming power should be on, and the only non-zero
+ * bits should be fuses that have not yet been blown.
+ */
+static void WriteFuseWord(NvU32 Addr, NvU32 Data)
+{
+ NvU32 RegData;
+
+ if (Data == 0) return;
+
+ // Prepare the data
+ FUSE_NV_WRITE32(FUSE_FUSEADDR_0, Addr);
+ FUSE_NV_WRITE32(FUSE_FUSEWDATA_0, Data);
+
+ // Trigger the write
+ RegData = FUSE_NV_READ32(FUSE_FUSECTRL_0);
+ RegData = NV_FLD_SET_DRF_DEF(FUSE, FUSECTRL, FUSECTRL_CMD, WRITE, RegData);
+ FUSE_NV_WRITE32(FUSE_FUSECTRL_0, RegData);
+
+ // Wait for completion (state machine goes idle).
+ WaitForFuseIdle();
+}
+
+// Sense the fuse array & wait until done.
+static void SenseFuseArray(void)
+{
+ NvU32 RegData;
+
+ RegData = FUSE_NV_READ32(FUSE_FUSECTRL_0);
+ RegData = NV_FLD_SET_DRF_DEF(FUSE,
+ FUSECTRL,
+ FUSECTRL_CMD,
+ SENSE_CTRL,
+ RegData);
+ FUSE_NV_WRITE32(FUSE_FUSECTRL_0, RegData);
+
+ // Wait for completion (state machine goes idle).
+ WaitForFuseIdle();
+}
+
+
+// The following has not appeared in any netlist headers.
+#ifndef FUSE_ENABLE_FUSE_PROGRAM__PRI_ALIAS_0
+#define FUSE_ENABLE_FUSE_PROGRAM__PRI_ALIAS_0 0x0
+#define FUSE_ENABLE_FUSE_PROGRAM__PRI_ALIAS_0_DATA 0:0
+#define FUSE_ENABLE_FUSE_PROGRAM__PRI_ALIAS_0_WIDTH 1
+#define FUSE_ENABLE_FUSE_PROGRAM__RED_ALIAS_0 0x1
+#define FUSE_ENABLE_FUSE_PROGRAM__RED_ALIAS_0_DATA 0:0
+#define FUSE_ENABLE_FUSE_PROGRAM__RED_ALIAS_0_WIDTH 1
+#endif
+#ifndef FUSE_ENABLE_FUSE_PROGRAM__PRI_ALIAS_0_SHIFT
+#define FUSE_ENABLE_FUSE_PROGRAM__PRI_ALIAS_0_SHIFT 0
+#define FUSE_ENABLE_FUSE_PROGRAM__RED_ALIAS_0_SHIFT 0
+#endif
+
+static void
+NvDdkFuseProgramFuseArray(
+ NvU32 *FuseData,
+ NvU32 *MaskData,
+ NvU32 NumWords,
+ NvU32 TProgramCycles)
+{
+ NvU32 RegData;
+ NvU32 i;
+ NvU32 Addr = 0;
+ NvU32 *Data = NULL;
+ NvU32 *Mask = NULL;
+ NvU32 FuseWord0; // Needed for initially enabling fuse programming.
+ NvU32 FuseWord1; // Needed for initially enabling fuse programming.
+
+ // Make all registers visible first
+ SetFuseRegVisibility(1);
+ // Read the first two fuse words.
+ SenseFuseArray();
+ FuseWord0 = ReadFuseWord(FUSE_ENABLE_FUSE_PROGRAM__PRI_ALIAS_0);
+ FuseWord1 = ReadFuseWord(FUSE_ENABLE_FUSE_PROGRAM__RED_ALIAS_0);
+ // also indicate power good to start the regulator and wait (again)
+ StartRegulator();
+ /*
+ *In AP20, the fuse macro is a high density macro, with a completely
+ * different interface from the procedure used in AP15. Fuses are
+ * burned using an addressing mechanism, so no need to prepare
+ * the full list, but more write to control registers are needed, not
+ * a big deal
+ * The only bit that can be written at first is bit 0, a special write
+ * protection bit by assumptions all other bits are at 0
+ * Note that the bit definitions are no more part of arfuse.h
+ * (unfortunately). So we define them here
+ *
+ * Modify the fuse programming time.
+ *
+ * For AP20, the programming pulse must have a precise width of
+ * [9000, 11000] ns.
+ */
+ if (TProgramCycles > 0)
+ {
+ RegData = NV_DRF_NUM(FUSE,
+ FUSETIME_PGM2,
+ FUSETIME_PGM2_TWIDTH_PGM,
+ TProgramCycles);
+ FUSE_NV_WRITE32(FUSE_FUSETIME_PGM2_0, RegData);
+ }
+ /* FuseWord0 and FuseWord1 should be left with only the Fuse Enable fuse
+ * set to 1, and then only if this fuse has not yet been burned.
+ */
+ FuseWord0 = (0x1 << FUSE_ENABLE_FUSE_PROGRAM__PRI_ALIAS_0_SHIFT) &
+ ~FuseWord0;
+ FuseWord1 = (0x1 << FUSE_ENABLE_FUSE_PROGRAM__RED_ALIAS_0_SHIFT) &
+ ~FuseWord1;
+
+ WriteFuseWord(FUSE_ENABLE_FUSE_PROGRAM__PRI_ALIAS_0, FuseWord0);
+ WriteFuseWord(FUSE_ENABLE_FUSE_PROGRAM__RED_ALIAS_0, FuseWord1);
+ // Remove power good as we may toggle fuse_src in the model, wait
+ StopRegulator();
+ /*
+ * Sense the fuse macro, this will allow programming of other fuses
+ * and the reading of the existing fuse values
+ */
+ SenseFuseArray();
+ /*
+ * Clear out all bits in FuseData that have already been burned
+ * or that have been masked out.
+ */
+
+ fusememcpy(s_TempFuseData, FuseData, sizeof(NvU32) * 64);
+ Addr = 0;
+ Data = s_TempFuseData;
+ Mask = MaskData;
+ for (i = 0; i < NumWords; i++, Addr++, Data++, Mask++)
+ {
+ RegData = ReadFuseWord(Addr);
+ *Data = (*Data & ~RegData) & *Mask;
+ }
+
+ // Enable power good
+ StartRegulator();
+ /*
+ * Finally loop on all fuses, program the non zero ones
+ * Words 0 and 1 are written last and they contain control fuses and we
+ * need a sense after writing to a control word (with the exception of
+ * the master enable fuse) this is also the reason we write them last
+ */
+ Addr = 2;
+ Data = s_TempFuseData + Addr;
+ for (; Addr < NumWords; Addr++, Data++)
+ {
+ WriteFuseWord(Addr, *Data);
+ }
+ // write the two control words, we need a sense after each write
+ Addr = 0;
+ Data = s_TempFuseData;
+ for (; Addr < NV_MIN(2, NumWords); Addr++, Data++)
+ {
+ WriteFuseWord(Addr, *Data);
+ // Remove power good as we may toggle fuse_src in the model, wait
+ StopRegulator();
+ SenseFuseArray();
+ StartRegulator();
+ }
+ // Read all data into the chip options
+ RegData = NV_DRF_NUM(FUSE, PRIV2INTFC_START, PRIV2INTFC_START_DATA, 0x1);
+ FUSE_NV_WRITE32(FUSE_PRIV2INTFC_START_0, RegData);
+ /*
+ * Not sure if still needs to be set back to 0
+ * we wait a little bit, then set it back to 0, then loop on state
+ */
+
+ NvFuseUtilWaitUS(1);
+
+ RegData = NV_DRF_NUM(FUSE, PRIV2INTFC_START, PRIV2INTFC_START_DATA, 0x0);
+ FUSE_NV_WRITE32(FUSE_PRIV2INTFC_START_0, RegData);
+ /*
+ * Wait until done (polling)
+ * this one needs to use fuse_sense done, the FSM follows a periodic
+ * sequence that includes idle
+ */
+ do {
+ RegData = FUSE_NV_READ32(FUSE_FUSECTRL_0);
+ } while (NV_DRF_VAL(FUSE, FUSECTRL, FUSECTRL_FUSE_SENSE_DONE, RegData) != 0x1);
+}
+
+static NvError
+NvDdkFuseVerifyFuseArray(
+ NvU32 *FuseData,
+ NvU32 *MaskData,
+ NvU32 NumWords)
+{
+ NvU32 RegData;
+ NvU32 i;
+ NvU32 Addr = 0;
+ NvU32 *Data = NULL;
+ NvU32 *Mask = NULL;
+ NvError e = NvSuccess;
+
+ // Make all registers visible first
+ SetFuseRegVisibility(1);
+
+ // Sense the fuse array
+ SenseFuseArray();
+
+ // Loop over the data, checking fuse registers.
+ Addr = 0;
+ Data = FuseData;
+ Mask = MaskData;
+ for (i = 0; i < NumWords; i++, Addr++, Data++, Mask++)
+ {
+ RegData = (ReadFuseWord(Addr) & (*Mask));
+
+ /*
+ * Once Odm production mode fuse word(0th word) is set, it can
+ * not set any other fuse word in the fuse cell, including the
+ * redundent fuse word (1st word).
+ * Hence it makes no sense to verify it.
+ */
+ if ((i == 1) && NvDdkFuseIsOdmProductionMode())
+ {
+ continue;
+ }
+
+ // Check the results.
+ if (RegData != ((*Data) & (*Mask)))
+ {
+ // Abort with an error on a miscompare
+ e = NvError_BadValue;
+ goto fail;
+ }
+ }
+
+ // Fallthrough on sucessful completion.
+
+ fail:
+ // Hide back registers
+ SetFuseRegVisibility(0);
+ return e;
+}
+
+/*
+ *************************************
+ * PUBLIC API
+ *************************************
+ */
+
+/**
+ * Clears the cache of fuse data.
+ */
+void NvDdkFuseClear(void)
+{
+ if(!s_pFuseRec)
+ {
+ // NV_ASSERT(0);
+ NvOsDebugPrintf("\r\n Plz call NvDdkFuseOpen before using this API");
+ return;
+ }
+ NvOsMutexLock(s_pFuseRec->Mutex);
+ fusememset(&s_FuseData, 0, sizeof(NvDdkFuseData));
+ NvOsMutexUnlock(s_pFuseRec->Mutex);
+}
+
+/**
+ * Read the current fuse data into the fuse registers.
+ */
+void NvDdkFuseSense(void)
+{
+ if(!s_pFuseRec)
+ {
+ // NV_ASSERT(0);
+ NvOsDebugPrintf("\r\n Plz call NvDdkFuseOpen before using this API");
+ return;
+ }
+ NvOsMutexLock(s_pFuseRec->Mutex);
+ SetFuseRegVisibility(1);
+ SenseFuseArray();
+ SetFuseRegVisibility(0);
+ NvOsMutexUnlock(s_pFuseRec->Mutex);
+}
+
+/**
+ * Macro's to swap byte order for an NvU32
+ */
+
+#define EXTRACT_BYTE_NVU32(Data32, ByteNum) \
+ (((Data32) >> ((ByteNum)*8)) & 0xFF)
+
+#define SWAP_BYTES_NVU32(Data32) \
+ do { \
+ NV_ASSERT(sizeof(Data32)==4); \
+ (Data32) = \
+ (EXTRACT_BYTE_NVU32(Data32, 0) << 24) | \
+ (EXTRACT_BYTE_NVU32(Data32, 1) << 16) | \
+ (EXTRACT_BYTE_NVU32(Data32, 2) << 8) | \
+ (EXTRACT_BYTE_NVU32(Data32, 3) << 0); \
+ } while (0)
+
+#if FUSE_DUMMY_CODE
+// Sizes of different fuses in bytes.
+static NvU8 DeviceKey[4];
+static NvU8 JtagDisable[1];
+static NvU8 KeyProgrammed[1];
+static NvU8 OdmProduction[1];
+static NvU8 SecBootDeviceConfig[2];
+static NvU8 SecBootDeviceSelect[1];
+static NvU8 SecureBootKey[16];
+static NvU8 Sku[4];
+static NvU8 SpareBits[4];
+static NvU8 SwReserved[1];
+static NvU8 SkipDevSelStraps[1];
+static NvU8 SecBootDeviceSelectRaw[4];
+static NvU8 ReservedOdm[32];
+
+NvError NvDdkFuseGet(NvDdkFuseDataType Type, void *pData, NvU32 *pSize)
+{
+ switch (Type)
+ {
+ case NvDdkFuseDataType_DeviceKey:
+ fusememcpy(pData, DeviceKey, sizeof(DeviceKey));
+ break;
+ case NvDdkFuseDataType_JtagDisable:
+ fusememcpy(pData, JtagDisable, sizeof(JtagDisable));
+ break;
+ case NvDdkFuseDataType_KeyProgrammed:
+ fusememcpy(pData, KeyProgrammed, sizeof(KeyProgrammed));
+ break;
+ case NvDdkFuseDataType_OdmProduction:
+ fusememcpy(pData, OdmProduction, sizeof(OdmProduction));
+ break;
+ case NvDdkFuseDataType_SecBootDeviceConfig:
+ fusememcpy(pData, SecBootDeviceConfig, sizeof(SecBootDeviceConfig));
+ break;
+ case NvDdkFuseDataType_SecBootDeviceSelect:
+ fusememcpy(pData, SecBootDeviceSelect, sizeof(SecBootDeviceSelect));
+ break;
+ case NvDdkFuseDataType_SecureBootKey:
+ fusememcpy(pData, SecureBootKey, sizeof(SecureBootKey));
+ break;
+ case NvDdkFuseDataType_Sku:
+ fusememcpy(pData, Sku, sizeof(Sku));
+ break;
+ case NvDdkFuseDataType_SpareBits:
+ fusememcpy(pData, SpareBits, sizeof(SpareBits));
+ break;
+ case NvDdkFuseDataType_SwReserved:
+ fusememcpy(pData, SwReserved, sizeof(SwReserved));
+ break;
+ case NvDdkFuseDataType_SkipDevSelStraps:
+ fusememcpy(pData, SkipDevSelStraps, sizeof(SkipDevSelStraps));
+ break;
+ case NvDdkFuseDataType_SecBootDeviceSelectRaw:
+ fusememcpy(pData, SecBootDeviceSelectRaw, sizeof(SecBootDeviceSelectRaw));
+ break;
+ case NvDdkFuseDataType_ReservedOdm:
+ fusememcpy(pData, ReservedOdm, sizeof(ReservedOdm));
+ break;
+ default:
+ NvOsDebugPrintf("\r\n Invalid fuse type selected");
+ break;
+ }
+ return NvSuccess;
+}
+#else
+/**
+ * This gets value from the fuse cache.
+ *
+ * To read from the actual fuses, NvDdkFuseSense() must be called first.
+ * Note that NvDdkFuseSet() follwed by NvDdkFuseGet() for the same data will
+ * return the set data, not the actual fuse values.
+ *
+ * By passing a size of zero, the caller is requesting tfor the
+ * expected size.
+ */
+NvError NvDdkFuseGet(NvDdkFuseDataType Type, void *pData, NvU32 *pSize)
+{
+ NvU32 RegData;
+ NvU32 Size;
+ NvU32 DataSizeArrayLen;
+
+ if(!s_pFuseRec)
+ {
+ NvOsDebugPrintf("\r\n Plz call NvDdkFuseOpen before using this API");
+ return 1;
+ }
+ DataSizeArrayLen = ((sizeof(s_DataSize)) / (sizeof(NvU32)));
+ // Check the arguments
+ // NvDdkFuseDataType_Num is not ap20 specific as s_DataSize
+ if (Type == NvDdkFuseDataType_None ||
+ (Type > (NvDdkFuseDataType)DataSizeArrayLen))
+ return NvError_BadValue;
+ if (pSize == NULL) return NvError_BadParameter;
+
+ Size = s_DataSize[(NvU32)Type];
+
+ if (*pSize == 0)
+ {
+ *pSize = Size;
+ return NvError_Success;
+ }
+
+// if (*pSize > Size) return NvError_InsufficientMemory;
+ if (pData == NULL) return NvError_BadParameter;
+
+ NvOsMutexLock(s_pFuseRec->Mutex);
+ switch (Type)
+ {
+ case NvDdkFuseDataType_DeviceKey:
+ /*
+ * Boot ROM expects DK to be stored in big-endian byte order;
+ * since cpu is little-endian and client treats data as an NvU32,
+ * perform byte swapping here
+ */
+ RegData = FUSE_NV_READ32(FUSE_PRIVATE_KEY4_0);
+ SWAP_BYTES_NVU32(RegData);
+ *((NvU32*)pData) = RegData;
+ break;
+
+ case NvDdkFuseDataType_JtagDisable:
+ RegData = FUSE_NV_READ32(FUSE_ARM_DEBUG_DIS_0);
+ *((NvBool*)pData) = RegData ? NV_TRUE : NV_FALSE;
+ break;
+
+ case NvDdkFuseDataType_KeyProgrammed:
+ *((NvBool*)pData) = IsSbkOrDkSet();
+ break;
+
+ case NvDdkFuseDataType_OdmProduction:
+ *((NvBool*)pData) = NvDdkFuseIsOdmProductionModeFuseSet();
+ break;
+
+ case NvDdkFuseDataType_SecBootDeviceConfig:
+ RegData = FUSE_NV_READ32(FUSE_BOOT_DEVICE_INFO_0);
+ RegData = NV_DRF_VAL(FUSE,
+ BOOT_DEVICE_INFO,
+ BOOT_DEVICE_CONFIG,
+ RegData);
+
+ *((NvU32*)pData) = RegData;
+ break;
+
+ case NvDdkFuseDataType_SecBootDeviceSelect:
+ RegData = (NvU32)NvDdkFuseGetSecBootDevice();
+ *((NvU32*)pData) = RegData;
+ break;
+
+ case NvDdkFuseDataType_SecBootDeviceSelectRaw:
+ RegData = NvDdkFuseGetSecBootDeviceRaw();
+ *((NvU32*)pData) = RegData;
+ break;
+
+ case NvDdkFuseDataType_SecureBootKey:
+ FuseCopyBytes(FUSE_PRIVATE_KEY0_0,
+ pData,
+ NVDDK_SECURE_BOOT_KEY_BYTES);
+ break;
+
+ case NvDdkFuseDataType_Sku:
+ *((NvU32*)pData) = FUSE_NV_READ32(FUSE_SKU_INFO_0);
+ break;
+
+ case NvDdkFuseDataType_SwReserved:
+ RegData = FUSE_NV_READ32(FUSE_RESERVED_SW_0);
+ RegData = NV_DRF_VAL(FUSE, RESERVED_SW, SW_RESERVED, RegData);
+ *((NvU32*)pData) = RegData;
+ break;
+
+ case NvDdkFuseDataType_SkipDevSelStraps:
+ RegData = FUSE_NV_READ32(FUSE_RESERVED_SW_0);
+ RegData = NV_DRF_VAL(FUSE, RESERVED_SW, SKIP_DEV_SEL_STRAPS, RegData);
+ *((NvU32*)pData) = RegData;
+ break;
+
+ case NvDdkFuseDataType_ReservedOdm:
+ FuseCopyBytes(FUSE_RESERVED_ODM0_0,
+ pData,
+ NVDDK_RESERVED_ODM_BYTES);
+ break;
+
+ default:
+ NvOsMutexUnlock(s_pFuseRec->Mutex);
+ return(NvError_BadValue);
+ }
+ NvOsMutexUnlock(s_pFuseRec->Mutex);
+ return NvError_Success;
+}
+#endif
+
+#if ENABLE_FUSE_VOLTAGE
+static NvRmDeviceHandle *ps_hRmDevice = NULL;
+#endif
+NvError NvDdkFuseOpen(NvRmDeviceHandle hRmDevice)
+{
+ NvError e;
+
+ // Allocate memory for handle.
+ s_pFuseRec = NvOsAlloc(sizeof(NvDdkFuse));
+ if (s_pFuseRec == NULL)
+ {
+ e = NvError_InsufficientMemory;
+ NvOsDebugPrintf("\r\n NvDdkFuseOpen malloc failed");
+ return e;
+ }
+
+ e = NvOsMutexCreate(&s_pFuseRec->Mutex);
+ if (e)
+ {
+ NvOsDebugPrintf("\r\n NvDdkFuseOpen Mutex creation failed");
+ goto fail;
+ }
+
+#if ENABLE_FUSE_VOLTAGE
+ ps_hRmDevice = NvOsAlloc(sizeof(NvRmDeviceHandle));
+ if (ps_hRmDevice == NULL)
+ {
+ e = NvError_InsufficientMemory;
+ NvOsDebugPrintf("\r\n NvDdkFuseOpen malloc failed");
+ return e;
+ }
+
+ *ps_hRmDevice = hRmDevice;
+#endif
+ // Get the base address of the Fuse registers
+ NvRmModuleGetBaseAddress(hRmDevice,
+ NVRM_MODULE_ID(NvRmModuleID_Fuse, 0),
+ &(s_pFuseRec->pBaseAddress), &(s_pFuseRec->BankSize));
+ NV_CHECK_ERROR_CLEANUP(NvRmPhysicalMemMap(s_pFuseRec->pBaseAddress,
+ s_pFuseRec->BankSize, NVOS_MEM_READ_WRITE, NvOsMemAttribute_Uncached,
+ (void **)&(s_pFuseRec->pVirtualAddress)));
+
+ // Get the base address of the CAR registers
+ NvRmModuleGetBaseAddress(hRmDevice,
+ NVRM_MODULE_ID(NvRmPrivModuleID_ClockAndReset, 0),
+ &(s_pFuseRec->pCarBaseAddress), &(s_pFuseRec->CarBankSize));
+ NV_CHECK_ERROR_CLEANUP(NvRmPhysicalMemMap(s_pFuseRec->pCarBaseAddress,
+ s_pFuseRec->CarBankSize, NVOS_MEM_READ_WRITE, NvOsMemAttribute_Uncached,
+ (void **)&(s_pFuseRec->pCarVirtualAddress)));
+
+ return NvSuccess;
+fail:
+ NvOsFree(s_pFuseRec);
+ return e;
+}
+
+void NvDdkFuseClose()
+{
+ NvOsDebugPrintf("\r\n NvDdkFuseClose ");
+ NvOsMutexDestroy(s_pFuseRec->Mutex);
+ NvOsFree(s_pFuseRec);
+ s_pFuseRec = NULL;
+}
+
+#if FUSE_DUMMY_CODE
+NvError NvDdkFuseSet(NvDdkFuseDataType Type, void *pData, NvU32 *pSize)
+{
+#if ENABLE_DEBUG_PRINTS
+ NvU8 i;
+ NvOsDebugPrintf("\n data to be written:");
+ for(i = 0; i < *pSize; i++)
+ NvOsDebugPrintf("\t 0x%x", *((NvU8 *)pData + i));
+#endif
+ switch (Type)
+ {
+ case NvDdkFuseDataType_DeviceKey:
+ fusememcpy(DeviceKey, pData, sizeof(DeviceKey));
+ break;
+ case NvDdkFuseDataType_JtagDisable:
+ fusememcpy(JtagDisable, pData, sizeof(JtagDisable));
+ break;
+ case NvDdkFuseDataType_KeyProgrammed:
+ fusememcpy(KeyProgrammed, pData, sizeof(KeyProgrammed));
+ break;
+ case NvDdkFuseDataType_OdmProduction:
+ fusememcpy(OdmProduction, pData, sizeof(OdmProduction));
+ break;
+ case NvDdkFuseDataType_SecBootDeviceConfig:
+ fusememcpy(SecBootDeviceConfig, pData, sizeof(SecBootDeviceConfig));
+ break;
+ case NvDdkFuseDataType_SecBootDeviceSelect:
+ fusememcpy(SecBootDeviceSelect, pData, sizeof(SecBootDeviceSelect));
+ break;
+ case NvDdkFuseDataType_SecureBootKey:
+ fusememcpy(SecureBootKey, pData, sizeof(SecureBootKey));
+ break;
+ case NvDdkFuseDataType_Sku:
+ fusememcpy(Sku, pData, sizeof(Sku));
+ break;
+ case NvDdkFuseDataType_SpareBits:
+ fusememcpy(SpareBits, pData, sizeof(SpareBits));
+ break;
+ case NvDdkFuseDataType_SwReserved:
+ fusememcpy(SwReserved, pData, sizeof(SwReserved));
+ break;
+ case NvDdkFuseDataType_SkipDevSelStraps:
+ fusememcpy(SkipDevSelStraps, pData, sizeof(SkipDevSelStraps));
+ break;
+ case NvDdkFuseDataType_SecBootDeviceSelectRaw:
+ fusememcpy(SecBootDeviceSelectRaw, pData, sizeof(SecBootDeviceSelectRaw));
+ break;
+ case NvDdkFuseDataType_ReservedOdm:
+ fusememcpy(ReservedOdm, pData, sizeof(ReservedOdm));
+ break;
+ default:
+ NvOsDebugPrintf("\r\n Invalid fuse type selected");
+ break;
+ }
+ return NvSuccess;
+}
+
+#else
+
+/**
+ * Schedule fuses to be programmed to the specified values when the next
+ * NvDdkFuseProgram() operation is performed
+ *
+ * By passing a size of zero, the caller is requesting to be told the
+ * expected size.
+ */
+#define FUSE_SET(name, flag) \
+ case NvDdkFuseDataType_##name: \
+ { \
+ NvU8 *p = (NvU8 *)&(p_FuseData.name); \
+ NvU32 i; \
+ NvError e = NvSuccess; \
+ /* read existing fuse value */ \
+ e = NvDdkFuseGet(NvDdkFuseDataType_##name, p, &Size); \
+ if (e != NvSuccess) \
+ {\
+ NvOsDebugPrintf("\r\n Err returned from Fuse Get:0x%x in Set",e); \
+ return e; \
+ }\
+ /* check consistency between existing and desired fuse values. */ \
+ /* fuses cannot be unburned, so desired value cannot specify */ \
+ /* any unburned (0x0) bits where the existing value already */ \
+ /* contains burned (0x1) bits. */ \
+ for (i=0; i<Size; i++) \
+ if ((p[i] | pDataPtr[i]) != pDataPtr[i]) \
+ { \
+ e = NvError_InvalidState; \
+ NvOsDebugPrintf("\n p[%d] = 0x%x, pDataptr[%d] = 0x%x",i, p[i],i,*(NvU32*)pDataPtr); \
+ NvOsDebugPrintf("\r\n Consistency check failure in Fuse Set:0x%x",e); \
+ return e; \
+ } \
+ /* consistency check passed; schedule fuses to be burned */ \
+ fusememcpy(&(s_FuseData.name), (void *)pDataPtr, Size); \
+ s_FuseData.ProgramFlags |= FLAGS_PROGRAM_##flag; \
+ } \
+ break
+
+NvError NvDdkFuseSet(NvDdkFuseDataType Type, void *pData, NvU32 *pSize)
+{
+ NvError e = NvError_Success;
+ NvU32 Size;
+ NvU32 DataSizeArrayLen;
+ NvDdkFuseData p_FuseData;
+ volatile NvU8* pDataPtr = (volatile NvU8*)pData;
+ if(!s_pFuseRec)
+ {
+ // NV_ASSERT(0);
+ NvOsDebugPrintf("\r\n Plz call NvDdkFuseOpen before using this API");
+ return 1;
+ }
+ NvOsMutexLock(s_pFuseRec->Mutex);
+ DataSizeArrayLen = ((sizeof(s_DataSize)) / (sizeof(NvU32)));
+
+ if (Type == NvDdkFuseDataType_None ||
+ (Type > (NvDdkFuseDataType)DataSizeArrayLen))
+ {
+ e = NvError_BadValue;
+ NvOsDebugPrintf("\r\n NvDdkFuseDataType is incorrect");
+ goto fail;
+ }
+
+ if (pSize == NULL)
+ {
+ e = NvError_BadParameter;
+ goto fail;
+ }
+
+ Size = s_DataSize[(NvU32)Type];
+
+ // Return the required size, if requested.
+ if (*pSize == 0)
+ {
+ *pSize = Size;
+ e = NvError_Success;
+ goto fail;
+ }
+
+ if (*pSize > Size)
+ {
+ NvOsDebugPrintf("\n passed size = %d, fuse size = %d", *pSize, Size);
+ e = NvError_InsufficientMemory;
+ goto fail;
+ }
+
+ if (pData == NULL)
+ {
+ e = NvError_BadParameter;
+ goto fail;
+ }
+
+ /*
+ * If Disable Reg program is set, chip can not be fused, so return as
+ * "Access denied".
+ */
+ if (NvDdkPrivIsDisableRegProgramSet())
+ {
+ e = NvError_AccessDenied;
+ goto fail;
+ }
+
+
+ // Only reserved odm fuses are allowed to burn in secure mode
+ if (NvDdkFuseIsOdmProductionModeFuseSet() &&
+ (Type != NvDdkFuseDataType_ReservedOdm))
+ {
+ e = NvError_BadValue;
+ NvOsDebugPrintf("\r\n only reserved odm fuses are allowed to burn \
+ in secure mode");
+ goto fail;
+ }
+
+ switch (Type)
+ {
+ FUSE_SET(DeviceKey, DEVICE_KEY );
+ FUSE_SET(JtagDisable, JTAG_DISABLE );
+ FUSE_SET(OdmProduction, ODM_PRODUCTION );
+ FUSE_SET(SecBootDeviceConfig, BOOT_DEV_CONFIG );
+
+ case NvDdkFuseDataType_SecBootDeviceSelect:
+ case NvDdkFuseDataType_SecBootDeviceSelectRaw:
+ {
+ NvU8 *p = (NvU8 *)&(s_FuseData.SecBootDeviceSelectRaw);
+ NvU32 ApiData; // API symbolic value for device selection
+ NvU32 FuseData; // Raw fuse data for the device selection
+
+ if (Type == NvDdkFuseDataType_SecBootDeviceSelect)
+ {
+ /* Read out the argument. */
+
+ fusememcpy(&(ApiData), pData, Size);
+
+ if (ApiData == 0 || ApiData >= NvDdkSecBootDeviceType_Max)
+ {
+ e = NvError_BadValue;
+ NvOsDebugPrintf("\r\n ApiData is incorrect");
+ goto fail;
+ }
+
+ /* Map the symbolic value to a fuse value. */
+ FuseData = NvDdkToFuseBootDeviceSel[ApiData];
+ }
+ else
+ {
+ /*
+ * Type == NvDdkFuseDataType_SecBootDeviceSelectRaw
+ * Read out the argument.
+ */
+ fusememcpy(&(FuseData), pData, Size);
+ if (FuseData >= FuseBootDev_Max)
+ {
+ e = NvError_BadValue;
+ NvOsDebugPrintf("\r\n FuseData is incorrect");
+ goto fail;
+ }
+
+ /* Map the fuse value to a symbolic value */
+ ApiData = FuseToNvDdkBootDeviceSel[FuseData];
+ }
+
+ /* read existing fuse value */
+ NV_CHECK_ERROR(NvDdkFuseGet(NvDdkFuseDataType_SecBootDeviceSelectRaw,
+ p, &Size));
+
+ /*
+ * Check consistency between existing and desired fuse values.
+ * fuses cannot be unburned, so desired value cannot specify
+ * any unburned (0x0) bits where the existing value already
+ * contains burned (0x1) bits.
+ */
+ if ((s_FuseData.SecBootDeviceSelectRaw | FuseData) != FuseData)
+ {
+ e = NvError_InvalidState;
+ goto fail;
+ }
+
+
+ /* Consistency check passed; schedule fuses to be burned */
+ s_FuseData.SecBootDeviceSelect = ApiData;
+ s_FuseData.SecBootDeviceSelectRaw = FuseData;
+ s_FuseData.ProgramFlags |= FLAGS_PROGRAM_BOOT_DEV_SEL;
+ }
+ break;
+
+ FUSE_SET(SecureBootKey, SECURE_BOOT_KEY );
+ FUSE_SET(SwReserved, SW_RESERVED );
+ FUSE_SET(SkipDevSelStraps, SKIP_DEV_SEL_STRAPS );
+ FUSE_SET(ReservedOdm, RESERVED_ODM );
+
+ default:
+ {
+ e = NvError_BadValue;
+ NvOsDebugPrintf("\r\n Entered default case");
+ goto fail;
+ }
+ }
+ // Set the ReservOdm flag if it present
+ if (Type == NvDdkFuseDataType_ReservedOdm)
+ {
+ s_FuseData.ReservedOdmFlag = NV_TRUE;
+ }
+
+ // Check for invalid state combinations.
+ if ((s_FuseData.ProgramFlags & FLAGS_PROGRAM_ODM_PRODUCTION) &&
+ (s_FuseData.ProgramFlags & (FLAGS_PROGRAM_SECURE_BOOT_KEY |
+ FLAGS_PROGRAM_DEVICE_KEY)))
+ {
+ s_FuseData.ProgramFlags |= FLAGS_PROGRAM_ILLEGAL;
+ }
+
+ if (s_FuseData.ProgramFlags & FLAGS_PROGRAM_ILLEGAL)
+ {
+ e = NvError_InvalidState;
+ goto fail;
+ }
+
+fail:
+ NvOsMutexUnlock(s_pFuseRec->Mutex);
+ if (e != NvSuccess)
+ NvOsDebugPrintf("\r\n NvDdkFuseSet exit with err value e = 0x%x",e);
+ return e;
+}
+#endif
+
+#if FUSE_DUMMY_CODE
+NvError NvDdkFuseProgram(void)
+{
+
+}
+#else
+#if ENABLE_FUSE_VOLTAGE
+static void EnableFuseVoltage(void)
+{
+ const NvOdmPeripheralConnectivity *pConnectivity = NULL;
+ NvRmPmuVddRailCapabilities RailCaps;
+ NvU32 i;
+
+ pConnectivity = NvOdmPeripheralGetGuid(NV_VDD_FUSE_ODM_ID);
+ if (pConnectivity != NULL)
+ {
+ for (i = 0; i < pConnectivity->NumAddress; i++)
+ {
+ // Search for the vdd rail entry
+ if (pConnectivity->AddressList[i].Interface == NvOdmIoModule_Vdd)
+ {
+ NvRmPmuGetCapabilities((*ps_hRmDevice),
+ pConnectivity->AddressList[i].Address, &RailCaps);
+
+ NvRmPmuSetVoltage((*ps_hRmDevice),
+ pConnectivity->AddressList[i].Address,
+ RailCaps.requestMilliVolts, NULL);
+ }
+ }
+ }
+}
+#endif
+/**
+ * Program all fuses based on cache data changed via the NvDdkFuseSet() API.
+ *
+ * Caller is responsible for supplying valid fuse programming voltage prior to
+ * invoking this routine.
+ *
+ * NOTE: All values that are not intended to be programmed must have
+ * value 0. There is no need to conditionalize this code based on which
+ * logical values were actually set through the API.
+ */
+NvError NvDdkFuseProgram(void)
+{
+ if(!s_pFuseRec)
+ {
+ NvOsDebugPrintf("\r\n Plz call NvDdkFuseOpen before using this API");
+ return 1;
+ }
+#if ENABLE_FUSE_VOLTAGE
+ EnableFuseVoltage();
+#endif
+ NvOsMutexLock(s_pFuseRec->Mutex);
+ /*
+ * Validate the current state.
+ * If Secure mode is already burned, only reserved odm fuses are allowed to burn
+ */
+ if (NvDdkFuseIsOdmProductionModeFuseSet() && (!s_FuseData.ReservedOdmFlag))
+ {
+ NvOsDebugPrintf("\r\n NvDdkFuseProgram err - InvalidState");
+ return NvError_InvalidState;
+ }
+ /*
+ * If Disable Reg program is set, chip can not be fused, so return as
+ * "Access denied".
+ */
+ if (NvDdkPrivIsDisableRegProgramSet())
+ {
+ NvOsDebugPrintf("\r\n NvDdkFuseProgram err - AccessDenied");
+ return NvError_AccessDenied;
+ }
+
+ if (s_FuseData.ProgramFlags & FLAGS_PROGRAM_ILLEGAL)
+ {
+ NvOsDebugPrintf("\r\n NvDdkFuseProgram err - InvalidState");
+ return NvError_InvalidState;
+ }
+
+ // Map data onto a fuse array.
+ MapDataToFuseArrays();
+ NvDdkFuseProgramFuseArray(s_FuseArray, s_MaskArray, FUSE_WORDS,
+ NVDDK_TPROGRAM_VALUE_CORRECTED);
+ NvOsMutexUnlock(s_pFuseRec->Mutex);
+ // Clear reserved odm flag
+ s_FuseData.ReservedOdmFlag = NV_FALSE;
+ return NvError_Success;
+}
+#endif
+
+#if FUSE_DUMMY_CODE
+NvError NvDdkFuseVerify(void)
+{}
+#else
+/**
+ * Verify all fuses scheduled via the NvDdkFuseSet*() API's
+ */
+
+NvError NvDdkFuseVerify(void)
+{
+ NvError e = NvError_Success;
+ if(!s_pFuseRec)
+ {
+ NvOsDebugPrintf("\r\n Plz call NvDdkFuseOpen before using this API");
+ return 1;
+ }
+ NvOsMutexLock(s_pFuseRec->Mutex);
+ // Map data onto a fuse array.
+ MapDataToFuseArrays();
+ // Check to see if the data matches the real fuses.
+ e = NvDdkFuseVerifyFuseArray(s_FuseArray, s_MaskArray, FUSE_WORDS);
+ NvOsMutexUnlock(s_pFuseRec->Mutex);
+ if (e != NvError_Success)
+ {
+ e = NvError_InvalidState;
+ NvOsDebugPrintf("\r\n NvDdkFuseVerify returning modified err:0x%x",e);
+ }
+ return e;
+}
+#endif
+/*
+ * NvDdkDisableFuseProgram API disables the fuse programming until the next
+ * next system reset.
+ */
+
+void NvDdkDisableFuseProgram(void)
+{
+ NvU32 RegData;
+ if(!s_pFuseRec)
+ {
+ // NV_ASSERT(0);
+ NvOsDebugPrintf("\r\n Plz call NvDdkFuseOpen before using this API");
+ return;
+ }
+ NvOsMutexLock(s_pFuseRec->Mutex);
+ RegData = NV_DRF_DEF(FUSE, DISABLEREGPROGRAM, DISABLEREGPROGRAM_VAL, ENABLE);
+ FUSE_NV_WRITE32(FUSE_DISABLEREGPROGRAM_0, RegData);
+ NvOsMutexUnlock(s_pFuseRec->Mutex);
+}
+
+/** @} */
diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b.c
index 285044034f97..fdd3b3eeffa1 100644
--- a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b.c
+++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b.c
@@ -141,7 +141,7 @@ static const NvU32 VoltageTable_VOUT_02[] = {
// Specifies the time between each sequencer event.
// Disable temporarily to keep the compiler happy.
-//static const NvU32 SequencerPeriod[] = { 20, 40, 80, 160, 320, 640, 1280, 2560 };
+//static const NvU32 SequencerPeriod[] = {20, 40, 80, 160, 320, 640, 1280, 2560};
/*-- Voltage translation functions --*/
@@ -1055,6 +1055,25 @@ const Max8907bPmuSupplyInfo Max8907bSupplyInfoTable[] =
AD5258_VMAX,
MAX8907B_REQUESTVOLTAGE_LX_V1
},
+ },
+
+ // FUSE Vcc is wired from VBAT.
+ {
+ Max8907bPmuSupply_VBAT_FUSE,
+ TCA6416_CONFIG_PORT_0,
+ TCA6416_INVALID_PORT,
+ TCA6416_INVALID_PORT,
+ TCA6416_PORT_0,
+ TCA6416_PIN_2,
+ NULL,
+ NULL,
+ {
+ NV_FALSE,
+ FAN5355_MIN_OUTPUT_VOLTAGE_x10/10,
+ FAN5355_OUTPUT_VOLTAGE_INCREMENT_x10/10,
+ FAN5355_MAX_OUTPUT_VOLTAGE_x10/10,
+ MAX8907B_REQUESTVOLTAGE_EXT_DCDC_3
+ },
}
};
@@ -1786,6 +1805,39 @@ Tca6416UsbVbusControl(
return NV_TRUE;
}
+static NvBool
+Tca6416FuseControl(
+ NvOdmPmuDeviceHandle hDevice,
+ NvU32 vddRail,
+ NvU32 MilliVolts)
+{
+ const Max8907bPmuSupplyInfo *pSupplyInfo = &Max8907bSupplyInfoTable[vddRail];
+ NvU32 PortNo;
+ NvU32 PinNo;
+
+ // Get port number and pin number
+ PortNo = pSupplyInfo->OutputPort;
+ PinNo = pSupplyInfo->PmuGpio;
+
+ // Configure port pin as output
+ if (!Tca6416ConfigPortPin(hDevice, PortNo, PinNo, GpioPinMode_Output))
+ return NV_FALSE;
+
+ if (MilliVolts == ODM_VOLTAGE_OFF) // to disable FUSE voltage
+ {
+ // Set Low on pin
+ if (!Tca6416WritePortPin(hDevice, PortNo, PinNo, GpioPinState_Low))
+ return NV_FALSE;
+ }
+ else // to Enable FUSE voltage
+ {
+ // Set high on pin
+ if (!Tca6416WritePortPin(hDevice, PortNo, PinNo, GpioPinState_High))
+ return NV_FALSE;
+ }
+ return NV_TRUE;
+}
+
NvBool
Max8907bSetVoltage(
NvOdmPmuDeviceHandle hDevice,
@@ -1802,6 +1854,15 @@ Max8907bSetVoltage(
return NV_TRUE;
}
+ if (vddRail == Max8907bPmuSupply_VBAT_FUSE)
+ {
+ // Enable fuse voltage
+ if (!Tca6416FuseControl(hDevice, vddRail, MilliVolts))
+ return NV_FALSE;
+
+ return NV_TRUE;
+ }
+
if ((MilliVolts == ODM_VOLTAGE_ENABLE_EXT_ONOFF) ||
(MilliVolts == ODM_VOLTAGE_DISABLE_EXT_ONOFF))
{
diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_supply_info_table.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_supply_info_table.h
index 1b362aac43f4..77cf70bc32b5 100644
--- a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_supply_info_table.h
+++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_supply_info_table.h
@@ -29,7 +29,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*
*/
-
+
#ifndef INCLUDED_MAX8907B_SUPPLY_INFO_HEADER
#define INCLUDED_MAX8907B_SUPPLY_INFO_HEADER
@@ -86,7 +86,7 @@ extern "C"
// Defines common for all supplies I2C (s/w) sequencer selection
#define MAX8907B_SEQSEL_I2CEN_LXX 7 /* I2CEN (s/w) */
-// Defines sequencer count default values
+// Defines sequencer count default values
#define MAX8907B_SEQCNT_DEFAULT_LX_V1 0x1C
#define MAX8907B_SEQCNT_DEFAULT_LX_V2 0x1C
@@ -156,7 +156,7 @@ typedef enum
Max8907bPmuSupply_EXT_DCDC_3_USB1, //USB1 VBUS
Max8907bPmuSupply_EXT_DCDC_3_USB3, // USB3 VBUS
- /** Secondary PMU MIC2826 Rails **/
+ /** Secondary PMU MIC2826 Rails **/
MIC2826PmuSupply_BUCK,
MIC2826PmuSupply_LDO1,
MIC2826PmuSupply_LDO2,
@@ -166,6 +166,9 @@ typedef enum
// potentiometer (DPM) AD5258
Max8907bLxV1_Ad5258_DPM_EXT_DCDC_7,
+ //Temp for enabling fuse using p2 of i0 expander
+ Max8907bPmuSupply_VBAT_FUSE,
+
Max8907bPmuSupply_Num,
Max8907bPmuSupply_Force32 = 0x7FFFFFFF
} Max8907bPmuSupply;
@@ -192,6 +195,5 @@ typedef struct Max8907bPmuSupplyInfoRec
#if defined(__cplusplus)
}
#endif
-
#endif //INCLUDED_MAX8907B_SUPPLY_INFO_HEADER
diff --git a/arch/arm/mach-tegra/odm_kit/query/whistler/subboards/nvodm_query_discovery_e1116_addresses.h b/arch/arm/mach-tegra/odm_kit/query/whistler/subboards/nvodm_query_discovery_e1116_addresses.h
index 2b5ca7f8bacd..7c3d38f7c04d 100644
--- a/arch/arm/mach-tegra/odm_kit/query/whistler/subboards/nvodm_query_discovery_e1116_addresses.h
+++ b/arch/arm/mach-tegra/odm_kit/query/whistler/subboards/nvodm_query_discovery_e1116_addresses.h
@@ -30,13 +30,12 @@
*
*/
-
/**
* @file
* <b>NVIDIA APX ODM Kit::
* Implementation of the ODM Peripheral Discovery API</b>
*
- * @b Description: Specifies the peripheral connectivity
+ * @b Description: Specifies the peripheral connectivity
* database NvOdmIoAddress entries for the E1116
* Power module.
*/
@@ -44,227 +43,233 @@
#include "pmu/max8907b/max8907b_supply_info_table.h"
// Persistent voltage rail (ie, for RTC, Standby, etc...)
-static const NvOdmIoAddress s_ffaRtcAddresses[] =
+static const NvOdmIoAddress s_ffaRtcAddresses[] =
{
// On Maxim 8907B, the standby rail automatically follows V2
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LX_V2 } /* VDD_RTC -> RTC */
};
// Core voltage rail
-static const NvOdmIoAddress s_ffaCoreAddresses[] =
+static const NvOdmIoAddress s_ffaCoreAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LX_V2 } /* VDD_CORE -> V2 */
};
// PMU CPU voltage rail
-static const NvOdmIoAddress s_ffaCpuAddresses[] =
+static const NvOdmIoAddress s_ffaCpuAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LX_V1 } /* VDD_CPU_PMU -> V1 */
};
// External CPU DCDC voltage rail
-static const NvOdmIoAddress s_ffaCpuExtSupplyAddresses[] =
+static const NvOdmIoAddress s_ffaCpuExtSupplyAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bLxV1_Ad5258_DPM_EXT_DCDC_7 } /* VDD_CPU_PMU -> DCDC7 */
};
// PLLA voltage rail
-static const NvOdmIoAddress s_ffaPllAAddresses[] =
+static const NvOdmIoAddress s_ffaPllAAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LDO2 } /* AVDD_PLLA_P_C_S -> VOUT2 */
};
// PLLM voltage rail
-static const NvOdmIoAddress s_ffaPllMAddresses[] =
+static const NvOdmIoAddress s_ffaPllMAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LDO2 } /* AVDD_PLLM -> VOUT2 */
};
// PLLP voltage rail
-static const NvOdmIoAddress s_ffaPllPAddresses[] =
+static const NvOdmIoAddress s_ffaPllPAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LDO2 } /* AVDD_PLLA_P_C_S -> VOUT2 */
};
// PLLC voltage rail
-static const NvOdmIoAddress s_ffaPllCAddresses[] =
+static const NvOdmIoAddress s_ffaPllCAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LDO2 } /* AVDD_PLLA_P_C_S -> VOUT2 */
};
// PLLE voltage rail
-static const NvOdmIoAddress s_ffaPllEAddresses[] =
+static const NvOdmIoAddress s_ffaPllEAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LDO2 } /* AVDD_PLL_E -> VOUT2 */
};
// PLLU1 voltage rail
-static const NvOdmIoAddress s_ffaPllU1Addresses[] =
+static const NvOdmIoAddress s_ffaPllU1Addresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LDO2 } /* AVDD_PLLU -> VOUT2 */
};
// PLLS voltage rail
-static const NvOdmIoAddress s_ffaPllSAddresses[] =
+static const NvOdmIoAddress s_ffaPllSAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LDO2 } /* AVDD_PLLA_P_C_S -> VOUT2 */
};
// PLLHD voltage rail
-static const NvOdmIoAddress s_ffaPllHdmiAddresses[] =
+static const NvOdmIoAddress s_ffaPllHdmiAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LDO6 } /* AVDD_HDMI_PLL -> VOUT6 */
};
// OSC voltage rail
-static const NvOdmIoAddress s_ffaVddOscAddresses[] =
+static const NvOdmIoAddress s_ffaVddOscAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LX_V3 } /* AVDD_OSC -> V3 */
};
// PLLX voltage rail
-static const NvOdmIoAddress s_ffaPllXAddresses[] =
+static const NvOdmIoAddress s_ffaPllXAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LDO2 } /* AVDD_PLLX -> VOUT2 */
};
// PLL_USB voltage rail
-static const NvOdmIoAddress s_ffaPllUsbAddresses[] =
+static const NvOdmIoAddress s_ffaPllUsbAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LDO4 } /* AVDD_USB_PLL -> VOUT4 */
};
// SYS IO voltage rail
-static const NvOdmIoAddress s_ffaVddSysAddresses[] =
+static const NvOdmIoAddress s_ffaVddSysAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LX_V3 } /* VDDIO_SYS -> V3 */
};
// USB voltage rail
-static const NvOdmIoAddress s_ffaVddUsbAddresses[] =
+static const NvOdmIoAddress s_ffaVddUsbAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LDO4 } /* AVDD_USB -> VOUT4 */
};
// HDMI voltage rail
-static const NvOdmIoAddress s_ffaVddHdmiAddresses[] =
+static const NvOdmIoAddress s_ffaVddHdmiAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LDO11 } /* AVDD_HDMI -> VOUT11 */
};
// MIPI voltage rail
-static const NvOdmIoAddress s_ffaVddMipiAddresses[] =
+static const NvOdmIoAddress s_ffaVddMipiAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LDO17 } /* VDDIO_MIPI -> VOUT17 */
};
// LCD voltage rail
-static const NvOdmIoAddress s_ffaVddLcdAddresses[] =
+static const NvOdmIoAddress s_ffaVddLcdAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LX_V3 } /* VDDIO_LCD_PMU -> V3 */
};
// Audio voltage rail
-static const NvOdmIoAddress s_ffaVddAudAddresses[] =
+static const NvOdmIoAddress s_ffaVddAudAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LX_V3 } /* VDDIO_AUDIO -> V3 */
};
// LPDDR2 voltage rail (default)
-static const NvOdmIoAddress s_ffaVddDdrAddresses[] =
+static const NvOdmIoAddress s_ffaVddDdrAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LDO20 } /* VDDIO_DDR_1V2 -> VOUT20 */
};
// DDR2 voltage rail (on E1109 board ext 1.8V DCDC is controlled by LDO5)
-static const NvOdmIoAddress s_ffaVddDdr2Addresses[] =
+static const NvOdmIoAddress s_ffaVddDdr2Addresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LDO5 } /* VDDIO_DDR_1V8 -> VOUT05 */
};
// DDR_RX voltage rail
-static const NvOdmIoAddress s_ffaVddDdrRxAddresses[] =
+static const NvOdmIoAddress s_ffaVddDdrRxAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LDO1 } /* VDDIO_RX_DDR(2.7-3.3) -> VOUT1 */
};
// NAND voltage rail
-static const NvOdmIoAddress s_ffaVddNandAddresses[] =
+static const NvOdmIoAddress s_ffaVddNandAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LX_V3 } /* VDDIO_NAND_PMU -> V3 */
};
// UART voltage rail
-static const NvOdmIoAddress s_ffaVddUartAddresses[] =
+static const NvOdmIoAddress s_ffaVddUartAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LX_V3 } /* VDDIO_UART -> V3 */
};
// SDIO voltage rail
-static const NvOdmIoAddress s_ffaVddSdioAddresses[] =
+static const NvOdmIoAddress s_ffaVddSdioAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LDO12 } /* VDDIO_SDIO -> VOUT12 */
};
// VDAC voltage rail
-static const NvOdmIoAddress s_ffaVddVdacAddresses[] =
+static const NvOdmIoAddress s_ffaVddVdacAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LDO14 } /* AVDD_VDAC -> VOUT14 */
};
// VI voltage rail
-static const NvOdmIoAddress s_ffaVddViAddresses[] =
+static const NvOdmIoAddress s_ffaVddViAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LDO18 } /* VDDIO_VI -> VOUT18 */
};
// BB voltage rail
-static const NvOdmIoAddress s_ffaVddBbAddresses[] =
+static const NvOdmIoAddress s_ffaVddBbAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LX_V3 } /* VDDIO_BB -> V3 */
};
// HSIC voltage rail
-static const NvOdmIoAddress s_ffaVddHsicAddresses[] =
+static const NvOdmIoAddress s_ffaVddHsicAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LDO20 } /* VDDIO_HSIC -> VOUT20 */
};
// USB_IC voltage rail
-static const NvOdmIoAddress s_ffaVddUsbIcAddresses[] =
+static const NvOdmIoAddress s_ffaVddUsbIcAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LX_V3 } /* AVDD_USB_IC -> V3 */
};
// PEX_CLK voltage rail
-static const NvOdmIoAddress s_ffaVddPexClkAddresses[] =
+static const NvOdmIoAddress s_ffaVddPexClkAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LDO11 }, /* VDDIO_PEX_CLK -> VOUT11 */
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_LDO12 }, /* VDDIO_PEX_CLK -> VOUT12 */
- { NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_EXT_DCDC_3 }
+ { NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_EXT_DCDC_3 }
};
// PMU0
-static const NvOdmIoAddress s_Pmu0Addresses[] =
+static const NvOdmIoAddress s_Pmu0Addresses[] =
{
{ NvOdmIoModule_I2c_Pmu, 0x00, 0x78 },
};
// I2C IO Expander
-static const NvOdmIoAddress s_I2cioexpanderAddress[] =
+static const NvOdmIoAddress s_I2cioexpanderAddress[] =
{
{ NvOdmIoModule_I2c_Pmu, 0x00, 0x40 },
};
// USB1 VBus voltage rail
-static const NvOdmIoAddress s_ffaVddUsb1VBusAddresses[] =
+static const NvOdmIoAddress s_ffaVddUsb1VBusAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_EXT_DCDC_3_USB1 },
};
// USB3 VBus voltage rail
-static const NvOdmIoAddress s_ffaVddUsb3VBusAddresses[] =
+static const NvOdmIoAddress s_ffaVddUsb3VBusAddresses[] =
{
{ NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_EXT_DCDC_3_USB3 },
};
+// FUSE voltage enablel
+static const NvOdmIoAddress s_ffaVddFuseAddresses[] =
+{
+ { NvOdmIoModule_Vdd, 0x00, Max8907bPmuSupply_VBAT_FUSE },
+};
+
diff --git a/arch/arm/mach-tegra/odm_kit/query/whistler/subboards/nvodm_query_discovery_e1116_peripherals.h b/arch/arm/mach-tegra/odm_kit/query/whistler/subboards/nvodm_query_discovery_e1116_peripherals.h
index 5145bf5b0711..1fe3f615226b 100644
--- a/arch/arm/mach-tegra/odm_kit/query/whistler/subboards/nvodm_query_discovery_e1116_peripherals.h
+++ b/arch/arm/mach-tegra/odm_kit/query/whistler/subboards/nvodm_query_discovery_e1116_peripherals.h
@@ -35,7 +35,7 @@
* <b>NVIDIA APX ODM Kit::
* Implementation of the ODM Peripheral Discovery API</b>
*
- * @b Description: Specifies the peripheral connectivity
+ * @b Description: Specifies the peripheral connectivity
* database Peripheral entries for the E1116
* power module.
*/
@@ -51,8 +51,7 @@
NV_ARRAY_SIZE(s_ffaPllU1Addresses),
NvOdmPeripheralClass_Other
},
-// -------- END WHISTLER_AP16_ONLY --------
-
+// -------- END WHISTLER_AP16_ONLY --------
// RTC (NV reserved)
{
@@ -208,6 +207,13 @@
NvOdmPeripheralClass_Other
},
+// Fuse
+{
+ NV_VDD_FUSE_ODM_ID,
+ s_ffaVddFuseAddresses,
+ NV_ARRAY_SIZE(s_ffaVddFuseAddresses),
+ NvOdmPeripheralClass_Other
+},
// HDMI VDD (NV reserved)
{
diff --git a/arch/arm/mach-tegra/sysfs-fuse.c b/arch/arm/mach-tegra/sysfs-fuse.c
new file mode 100644
index 000000000000..d32d098972ab
--- /dev/null
+++ b/arch/arm/mach-tegra/sysfs-fuse.c
@@ -0,0 +1,481 @@
+/*
+ * Copyright (c) 2010 NVIDIA Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NVIDIA Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sysfs.h>
+#include <linux/kobject.h>
+#include "nvddk_fuse.h"
+#include "mach/nvrm_linux.h"
+
+#define SYSFS_FUSE_DEBUG_PRINTS 0
+
+#if SYSFS_FUSE_DEBUG_PRINTS
+#define PRINT_FUSE(x) printk x
+#else
+#define PRINT_FUSE(x)
+#endif
+
+#define BUF_SIZE 66 // Max_fuse_size(32) * AsciiCharsPerFuseByte(2) + \n\0 (2)
+
+static struct kobject *nvfuse_kobj;
+
+typedef enum
+{
+ TegraFuseSizeInBytes_DeviceKey = 4,
+ TegraFuseSizeInBytes_JtagDisable = 1, // 1 bit
+ TegraFuseSizeInBytes_KeyProgrammed = 1,
+ TegraFuseSizeInBytes_OdmProduction = 1, // 1 bit
+ TegraFuseSizeInBytes_SecBootDeviceConfig = 2, // 14 bits
+ TegraFuseSizeInBytes_SecBootDeviceSelect = 1, // 3 bits
+ TegraFuseSizeInBytes_SecureBootKey = 16,
+ TegraFuseSizeInBytes_Sku = 4,
+ TegraFuseSizeInBytes_SpareBits = 4,
+ TegraFuseSizeInBytes_SwReserved = 1, // 4 bit
+ TegraFuseSizeInBytes_SkipDevSelStraps = 1, // 1 bit
+ TegraFuseSizeInBytes_SecBootDeviceSelectRaw = 4,
+ TegraFuseSizeInBytes_ReservedOdm = 32
+} TegraFuseSizeInBytes;
+
+
+static ssize_t sysfsfuse_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf);
+
+static ssize_t sysfsfuse_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count);
+
+
+static struct kobj_attribute nvfuse_DeviceKey_attr =
+ __ATTR(DeviceKey, 0440, sysfsfuse_show, sysfsfuse_store);
+
+static struct kobj_attribute nvfuse_JtagDisable_attr =
+ __ATTR(JtagDisable, 0440, sysfsfuse_show, sysfsfuse_store);
+
+static struct kobj_attribute nvfuse_KeyProgrammed_attr =
+ __ATTR(KeyProgrammed, 0440, sysfsfuse_show, sysfsfuse_store);
+
+static struct kobj_attribute nvfuse_OdmProduction_attr =
+ __ATTR(OdmProduction, 0440, sysfsfuse_show, sysfsfuse_store);
+
+static struct kobj_attribute nvfuse_SecBootDeviceConfig_attr =
+ __ATTR(SecBootDeviceConfig, 0440, sysfsfuse_show, sysfsfuse_store);
+
+static struct kobj_attribute nvfuse_SecBootDeviceSelect_attr =
+ __ATTR(SecBootDeviceSelect, 0440, sysfsfuse_show, sysfsfuse_store);
+
+static struct kobj_attribute nvfuse_SecureBootKey_attr =
+ __ATTR(SecureBootKey, 0440, sysfsfuse_show, sysfsfuse_store);
+
+static struct kobj_attribute nvfuse_sku_attr =
+ __ATTR(sku, 0440, sysfsfuse_show, sysfsfuse_store);
+
+static struct kobj_attribute nvfuse_SpareBits_attr =
+ __ATTR(SpareBits, 0440, sysfsfuse_show, sysfsfuse_store);
+
+static struct kobj_attribute nvfuse_SwReserved_attr =
+ __ATTR(SwReserved, 0440, sysfsfuse_show, sysfsfuse_store);
+
+static struct kobj_attribute nvfuse_SkipDevSelStraps_attr =
+ __ATTR(SkipDevSelStraps, 0440, sysfsfuse_show, sysfsfuse_store);
+
+static struct kobj_attribute nvfuse_SecBootDeviceSelectRaw_attr =
+ __ATTR(SecBootDeviceSelectRaw, 0440, sysfsfuse_show, sysfsfuse_store);
+
+static struct kobj_attribute nvfuse_ReservedOdm_attr =
+ __ATTR(ReservedOdm, 0440, sysfsfuse_show, sysfsfuse_store);
+
+
+
+// return the fuse type based on the fuse name.
+NvDdkFuseDataType GetFuseType(const char *str, unsigned int* pSize)
+{
+ NvDdkFuseDataType type;
+
+ if(!strcmp(str, "DeviceKey"))
+ {
+ type = NvDdkFuseDataType_DeviceKey;
+ *pSize = TegraFuseSizeInBytes_DeviceKey;
+ }
+ else if (!strcmp(str, "JtagDisable"))
+ {
+ type = NvDdkFuseDataType_JtagDisable;
+ *pSize = TegraFuseSizeInBytes_JtagDisable;
+ }
+ else if (!strcmp(str, "KeyProgrammed"))
+ {
+ type = NvDdkFuseDataType_KeyProgrammed;
+ *pSize = TegraFuseSizeInBytes_KeyProgrammed;
+ }
+ else if (!strcmp(str, "OdmProduction"))
+ {
+ type = NvDdkFuseDataType_OdmProduction;
+ *pSize = TegraFuseSizeInBytes_OdmProduction;
+ }
+ else if (!strcmp(str, "SecBootDeviceConfig"))
+ {
+ type = NvDdkFuseDataType_SecBootDeviceConfig;
+ *pSize = TegraFuseSizeInBytes_SecBootDeviceConfig;
+ }
+ else if (!strcmp(str, "SecBootDeviceSelect"))
+ {
+ type = NvDdkFuseDataType_SecBootDeviceSelect;
+ *pSize = TegraFuseSizeInBytes_SecBootDeviceSelect;
+ }
+ else if (!strcmp(str, "SecureBootKey"))
+ {
+ type = NvDdkFuseDataType_SecureBootKey;
+ *pSize = TegraFuseSizeInBytes_SecureBootKey;
+ }
+ else if (!strcmp(str, "sku"))
+ {
+ type = NvDdkFuseDataType_Sku;
+ *pSize = TegraFuseSizeInBytes_Sku;
+ }
+ else if (!strcmp(str, "SpareBits"))
+ {
+ type = NvDdkFuseDataType_SpareBits;
+ *pSize = TegraFuseSizeInBytes_SpareBits;
+ }
+ else if (!strcmp(str, "SwReserved"))
+ {
+ type = NvDdkFuseDataType_SwReserved;
+ *pSize = TegraFuseSizeInBytes_SwReserved;
+ }
+ else if (!strcmp(str, "SkipDevSelStraps"))
+ {
+ type = NvDdkFuseDataType_SkipDevSelStraps;
+ *pSize = TegraFuseSizeInBytes_SkipDevSelStraps;
+ }
+ else if (!strcmp(str, "SecBootDeviceSelectRaw"))
+ {
+ type = NvDdkFuseDataType_SecBootDeviceSelectRaw;
+ *pSize = TegraFuseSizeInBytes_SecBootDeviceSelectRaw;
+ }
+ else if (!strcmp(str, "ReservedOdm"))
+ {
+ type = NvDdkFuseDataType_ReservedOdm;
+ *pSize = TegraFuseSizeInBytes_ReservedOdm;
+ }
+ else
+ {
+ type = NvDdkFuseDataType_None;
+ PRINT_FUSE(("\r\n Invalid Fuse type:%s... Find out reason\r",str));
+ }
+ return type;
+}
+
+/*
+ * return values:
+ * 0 - ODM production fuse is not blown
+ * 1 - ODM production fuse is blown
+ * 2 - Fuse Get API returned error
+ */
+static char OdmProductionFuseVal(void)
+{
+ NvU8 FuseVal = 0;
+ NvError Err;
+ NvU32 size = 1;
+
+ // check if ODM production fuse is burned already. If so, return here.
+ Err = NvDdkFuseGet(NvDdkFuseDataType_OdmProduction, &FuseVal, &size);
+ if (Err != NvSuccess)
+ {
+ PRINT_FUSE(("\r\n NvDdkFuseGet failed in sysfsfuse_store\n"));
+ return 2;
+ }
+ if (FuseVal)
+ {
+ PRINT_FUSE(("\r\n ODM production fuse is already blown\n"));
+ return 1;
+ }
+ else
+ return 0;
+}
+
+void IntToStr(char *arr, char *str, unsigned int MaxSize)
+{
+ int i = 0, j = 0;
+ char tmp[BUF_SIZE]={0};
+ strcpy(tmp,"0");
+
+ for(i = 0; i < MaxSize; i++)
+ {
+ if ((arr[i] == 0) && (j==0))
+ continue;
+
+ sprintf(&tmp[j*2],"%02X",arr[i]);
+ j++;
+ }
+ strcat(tmp,"\n");
+
+ // if first char contains 0, skip it.
+ if ((*tmp == '0') && (j != 0))
+ {
+ strcpy(str, &tmp[1]);
+ }
+ else
+ strcpy(str, &tmp[0]);
+
+ PRINT_FUSE(("\n string out: %s \n",str));
+}
+
+static ssize_t sysfsfuse_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+#if SYSFS_FUSE_DEBUG_PRINTS
+ unsigned char i = 0;
+#endif
+ unsigned int size = 0;
+ NvError Err;
+ NvDdkFuseDataType FuseType;
+ char ReadFuseBuf[BUF_SIZE];
+ char OdmProdFuseVal = 0;
+
+ FuseType = GetFuseType(attr->attr.name, &size);
+
+ // Reading SecureBootKey should be allowed only till ODM production is not blown
+ if (FuseType == NvDdkFuseDataType_SecureBootKey)
+ {
+ OdmProdFuseVal = OdmProductionFuseVal();
+ if(OdmProdFuseVal == 1)
+ {
+ PRINT_FUSE(("\r\n ODM production fuse is already blown\n"));
+ return 0;
+ }
+ }
+
+ NvDdkFuseSense();
+ NvDdkFuseClear();
+ Err = NvDdkFuseGet(FuseType, ReadFuseBuf, &size);
+ if (Err != NvSuccess)
+ {
+ PRINT_FUSE(("\r\n NvDdkFuseGet failed in sysfsfuse_show 2\n"));
+ return 0;
+ }
+ IntToStr(ReadFuseBuf, buf, size);
+#if SYSFS_FUSE_DEBUG_PRINTS
+ if (Err == NvSuccess)
+ PRINT_FUSE(("\n Fuse Get success \n"));
+ else
+ PRINT_FUSE(("\n Fuse Get failed Err: 0x%x \n",Err));
+ PRINT_FUSE(("\n\n Data read from Fuse:\n"));
+ for (i = 0; i < size; i++)
+ PRINT_FUSE((" 0x%x",ReadFuseBuf[i]));
+#endif
+ return (strlen(buf));
+}
+
+void StrToInt(const char *str,
+ char *arr, unsigned char NumChars, unsigned int MaxSize)
+{
+ int i = 0, j = 0;
+ char tmp[BUF_SIZE]={0};
+ unsigned char Iterations = (NumChars + 1)/2;
+ unsigned int t;
+ for(j = 0; j < (MaxSize - Iterations); j++)
+ {
+ arr[j] = 0;
+ }
+ for(i = 0; i < Iterations; i++)
+ {
+ if (NumChars & 1)
+ {
+ if (!i)
+ strncpy(tmp, &str[0], 1);
+ else
+ strncpy(tmp, &str[i*2 - 1], 2);
+ }
+ else
+ strncpy(tmp, &str[i*2], 2);
+ sscanf(tmp,"%02X",&t);
+ arr[j++]=(char)t;
+ }
+
+ PRINT_FUSE(("\r\n Input string after conversion to int: 0x%x", *arr));
+}
+
+static ssize_t sysfsfuse_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ ssize_t ret;
+ unsigned int size = 0;
+ NvDdkFuseDataType FuseType;
+ NvError Err;
+ char WriteFuseBuf[BUF_SIZE];
+#if SYSFS_FUSE_DEBUG_PRINTS
+ unsigned char i = 0;
+#endif
+ unsigned char OdmProdFuseVal = 0;
+
+ OdmProdFuseVal = OdmProductionFuseVal();
+ if(OdmProdFuseVal == 1)
+ {
+ PRINT_FUSE(("\r\n ODM production fuse is already blown\n"));
+ return 0;
+ }
+
+ FuseType = GetFuseType(attr->attr.name, &size);
+
+ // As count includes data bytes followed by 0xA (line feed character)
+ // and two chars can be stored in a fuse byte
+ if ((count - 1) > (2 * size))
+ {
+ PRINT_FUSE(("\r\n Requested data size[%d] > fuse size [%d]\n",count/2,size));
+ return 0;
+ }
+
+ if (buf != NULL)
+ {
+ StrToInt(buf, WriteFuseBuf, (count - 1), size);
+ }
+ else
+ printk("\r\n buf is NULL");
+
+ PRINT_FUSE(("\r\n Input string: %s", buf));
+ PRINT_FUSE(("\n Fuse data of size [%d] to write\n", size));
+#if SYSFS_FUSE_DEBUG_PRINTS
+ for (i = 0; i < size; i++)
+ PRINT_FUSE(("0x%x\n",WriteFuseBuf[i]));
+#endif
+ NvDdkFuseClear();
+ Err = NvDdkFuseSet(FuseType, WriteFuseBuf, &size);
+ if (Err == NvSuccess)
+ {
+ NvDdkFuseProgram();
+ NvDdkFuseSense();
+ NvDdkFuseVerify();
+ }
+ else
+ {
+ PRINT_FUSE(("\r\n Fuse programming failed with error 0x%x",Err));
+ }
+ if (Err == NvSuccess)
+ {
+ ret = count;
+ // if ODM production fuse is blown, change file permissions to 0440
+ if (FuseType == NvDdkFuseDataType_OdmProduction)
+ {
+ sysfs_chmod_file(kobj, &attr->attr, 0440);
+
+ sysfs_chmod_file(kobj, &nvfuse_DeviceKey_attr.attr, 0440);
+ sysfs_chmod_file(kobj, &nvfuse_JtagDisable_attr.attr, 0440);
+ sysfs_chmod_file(kobj, &nvfuse_OdmProduction_attr.attr, 0440);
+ sysfs_chmod_file(kobj, &nvfuse_SecBootDeviceConfig_attr.attr, 0440);
+ sysfs_chmod_file(kobj, &nvfuse_SecBootDeviceSelect_attr.attr, 0440);
+ sysfs_chmod_file(kobj, &nvfuse_SecureBootKey_attr.attr, 0440);
+ sysfs_chmod_file(kobj, &nvfuse_SwReserved_attr.attr, 0440);
+ sysfs_chmod_file(kobj, &nvfuse_SkipDevSelStraps_attr.attr, 0440);
+ sysfs_chmod_file(kobj, &nvfuse_SecBootDeviceSelectRaw_attr.attr, 0440);
+ sysfs_chmod_file(kobj, &nvfuse_ReservedOdm_attr.attr, 0440);
+ }
+ PRINT_FUSE(("\r\n fuse set success \n"));
+ }
+ else
+ {
+ ret = 0;
+ PRINT_FUSE(("\r\n fuse set failed Err: 0x%x\n", Err));
+ }
+
+ return ret;
+}
+
+#define CHK_ERR(x) \
+{ \
+ if(x) \
+ { \
+ PRINT_FUSE(("Fuse: sysfs_create_file failed!")); \
+ return x; \
+ } \
+}
+
+static int __init sysfsfuse_init(void)
+{
+ nvfuse_kobj = kobject_create_and_add("fuse", firmware_kobj);
+ PRINT_FUSE(("\n Fuse Init"));
+
+ CHK_ERR(NvDdkFuseOpen(s_hRmGlobal));
+ CHK_ERR(sysfs_create_file(nvfuse_kobj, &nvfuse_OdmProduction_attr.attr));
+
+ // change fuse file permissions, if ODM production fuse is not blown
+ if (OdmProductionFuseVal() == 0)
+ {
+ nvfuse_DeviceKey_attr.attr.mode = 0640;
+ nvfuse_JtagDisable_attr.attr.mode = 0640;
+ nvfuse_OdmProduction_attr.attr.mode = 0640;
+ nvfuse_SecBootDeviceConfig_attr.attr.mode = 0640;
+ nvfuse_SecBootDeviceSelect_attr.attr.mode = 0640;
+ nvfuse_SecureBootKey_attr.attr.mode = 0640;
+ nvfuse_SwReserved_attr.attr.mode = 0640;
+ nvfuse_SkipDevSelStraps_attr.attr.mode = 0640;
+ nvfuse_SecBootDeviceSelectRaw_attr.attr.mode = 0640;
+ nvfuse_ReservedOdm_attr.attr.mode = 0640;
+ sysfs_chmod_file(nvfuse_kobj, &nvfuse_OdmProduction_attr.attr, 0640);
+ }
+
+ CHK_ERR(sysfs_create_file(nvfuse_kobj, &nvfuse_DeviceKey_attr.attr));
+ CHK_ERR(sysfs_create_file(nvfuse_kobj, &nvfuse_JtagDisable_attr.attr));
+ CHK_ERR(sysfs_create_file(nvfuse_kobj, &nvfuse_KeyProgrammed_attr.attr));
+ CHK_ERR(sysfs_create_file(nvfuse_kobj, &nvfuse_SecBootDeviceConfig_attr.attr));
+ CHK_ERR(sysfs_create_file(nvfuse_kobj, &nvfuse_SecBootDeviceSelect_attr.attr));
+ CHK_ERR(sysfs_create_file(nvfuse_kobj, &nvfuse_SecureBootKey_attr.attr));
+ CHK_ERR(sysfs_create_file(nvfuse_kobj, &nvfuse_sku_attr.attr));
+ CHK_ERR(sysfs_create_file(nvfuse_kobj, &nvfuse_SpareBits_attr.attr));
+ CHK_ERR(sysfs_create_file(nvfuse_kobj, &nvfuse_SwReserved_attr.attr));
+ CHK_ERR(sysfs_create_file(nvfuse_kobj, &nvfuse_SkipDevSelStraps_attr.attr));
+ CHK_ERR(sysfs_create_file(nvfuse_kobj, &nvfuse_SecBootDeviceSelectRaw_attr.attr));
+ CHK_ERR(sysfs_create_file(nvfuse_kobj, &nvfuse_ReservedOdm_attr.attr));
+ PRINT_FUSE(("\n Fuse Init Exiting"));
+ return 0;
+}
+
+static void __exit sysfsfuse_exit(void)
+{
+ sysfs_remove_file(nvfuse_kobj, &nvfuse_DeviceKey_attr.attr);
+ sysfs_remove_file(nvfuse_kobj, &nvfuse_JtagDisable_attr.attr);
+ sysfs_remove_file(nvfuse_kobj, &nvfuse_KeyProgrammed_attr.attr);
+ sysfs_remove_file(nvfuse_kobj, &nvfuse_OdmProduction_attr.attr);
+ sysfs_remove_file(nvfuse_kobj, &nvfuse_SecBootDeviceConfig_attr.attr);
+ sysfs_remove_file(nvfuse_kobj, &nvfuse_SecBootDeviceSelect_attr.attr);
+ sysfs_remove_file(nvfuse_kobj, &nvfuse_SecureBootKey_attr.attr);
+ sysfs_remove_file(nvfuse_kobj, &nvfuse_sku_attr.attr);
+ sysfs_remove_file(nvfuse_kobj, &nvfuse_SpareBits_attr.attr);
+ sysfs_remove_file(nvfuse_kobj, &nvfuse_SwReserved_attr.attr);
+ sysfs_remove_file(nvfuse_kobj, &nvfuse_SkipDevSelStraps_attr.attr);
+ sysfs_remove_file(nvfuse_kobj, &nvfuse_SecBootDeviceSelectRaw_attr.attr);
+ sysfs_remove_file(nvfuse_kobj, &nvfuse_ReservedOdm_attr.attr);
+ kobject_del(nvfuse_kobj);
+ NvDdkFuseClose();
+}
+
+module_init(sysfsfuse_init);
+module_exit(sysfsfuse_exit);
+MODULE_LICENSE("GPL");