ARM: tegra: fuse: Remove carriage returns in fuse files
authorColin Cross <ccross@android.com>
Wed, 24 Nov 2010 22:28:50 +0000 (14:28 -0800)
committerColin Cross <ccross@android.com>
Thu, 25 Nov 2010 05:49:11 +0000 (21:49 -0800)
Change-Id: If3675c8ee7a0e0a5d3f7bd0c147054bc3796deef
Signed-off-by: Colin Cross <ccross@android.com>
arch/arm/mach-tegra/include/mach/tegra2_fuse.h
arch/arm/mach-tegra/tegra2_fuse.c

index 510a16069a5505b60a210b20071143fc2e093052..b5341b77a3601c21da81f9df759f2bca3769b90b 100644 (file)
-/*\r
- * arch/arm/mach-tegra/include/mach/tegra2_fuse.h\r
- *\r
- * Copyright (c) 2010, NVIDIA Corporation.\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful, but WITHOUT\r
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\r
- * more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
- */\r
-\r
-#ifndef __MACH_TEGRA2_FUSE_H\r
-#define __MACH_TEGRA2_FUSE_H\r
-\r
-#define SBK_DEVKEY_STATUS_SZ   sizeof(u32)\r
-\r
-/* fuse io parameters */\r
-enum fuse_io_param {\r
-       DEVKEY,\r
-       JTAG_DIS,\r
-       /*\r
-        * Programming the odm production fuse at the same\r
-        * time as the sbk or dev_key is not allowed as it is not possible to\r
-        * verify that the sbk or dev_key were programmed correctly.\r
-        */\r
-       ODM_PROD_MODE,\r
-       SEC_BOOT_DEV_CFG,\r
-       SEC_BOOT_DEV_SEL,\r
-       SBK,\r
-       SW_RSVD,\r
-       IGNORE_DEV_SEL_STRAPS,\r
-       ODM_RSVD,\r
-       SBK_DEVKEY_STATUS,\r
-       MASTER_ENB,\r
-       _PARAMS_U32 = 0x7FFFFFFF\r
-};\r
-\r
-#define MAX_PARAMS ODM_RSVD\r
-\r
-/* the order of the members is pre-decided. please do not change */\r
-struct fuse_data {\r
-       u32 devkey;\r
-       u32 jtag_dis;\r
-       u32 odm_prod_mode;\r
-       u32 bootdev_cfg;\r
-       u32 bootdev_sel;\r
-       u32 sbk[4];\r
-       u32 sw_rsvd;\r
-       u32 ignore_devsel_straps;\r
-       u32 odm_rsvd[8];\r
-};\r
-\r
-/* secondary boot device options */\r
-enum {\r
-       SECBOOTDEV_SDMMC,\r
-       SECBOOTDEV_NOR,\r
-       SECBOOTDEV_SPI,\r
-       SECBOOTDEV_NAND,\r
-       SECBOOTDEV_LBANAND,\r
-       SECBOOTDEV_MUXONENAND,\r
-       _SECBOOTDEV_MAX,\r
-       _SECBOOTDEV_U32 = 0x7FFFFFFF\r
-};\r
-\r
-/*\r
- * read the fuse settings\r
- * @param: io_param_type - param type enum\r
- * @param: size - read size in bytes\r
- */\r
-int tegra_fuse_read(u32 io_param_type, u32 *data, int size);\r
-\r
-#define FLAGS_DEVKEY                   BIT(DEVKEY)\r
-#define FLAGS_JTAG_DIS                 BIT(JTAG_DIS)\r
-#define FLAGS_SBK_DEVKEY_STATUS        BIT(SBK_DEVKEY_STATUS)\r
-#define FLAGS_ODM_PROD_MODE            BIT(ODM_PROD_MODE)\r
-#define FLAGS_SEC_BOOT_DEV_CFG BIT(SEC_BOOT_DEV_CFG)\r
-#define FLAGS_SEC_BOOT_DEV_SEL BIT(SEC_BOOT_DEV_SEL)\r
-#define FLAGS_SBK                      BIT(SBK)\r
-#define FLAGS_SW_RSVD          BIT(SW_RSVD)\r
-#define FLAGS_IGNORE_DEV_SEL_STRAPS    BIT(IGNORE_DEV_SEL_STRAPS)\r
-#define FLAGS_ODMRSVD                  BIT(ODM_RSVD)\r
-\r
-/*\r
- * Prior to invoking this routine, the caller is responsible for supplying\r
- * valid fuse programming voltage.\r
- *\r
- * @param: pgm_data - entire data to be programmed\r
- * @flags: program flags (e.g. FLAGS_DEVKEY)\r
- */\r
-int tegra_fuse_program(struct fuse_data *pgm_data, u32 flags);\r
-\r
-/* Disables the fuse programming until the next system reset */\r
-void tegra_fuse_program_disable(void);\r
-\r
-#endif\r
+/*
+ * arch/arm/mach-tegra/include/mach/tegra2_fuse.h
+ *
+ * Copyright (c) 2010, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __MACH_TEGRA2_FUSE_H
+#define __MACH_TEGRA2_FUSE_H
+
+#define SBK_DEVKEY_STATUS_SZ   sizeof(u32)
+
+/* fuse io parameters */
+enum fuse_io_param {
+       DEVKEY,
+       JTAG_DIS,
+       /*
+        * Programming the odm production fuse at the same
+        * time as the sbk or dev_key is not allowed as it is not possible to
+        * verify that the sbk or dev_key were programmed correctly.
+        */
+       ODM_PROD_MODE,
+       SEC_BOOT_DEV_CFG,
+       SEC_BOOT_DEV_SEL,
+       SBK,
+       SW_RSVD,
+       IGNORE_DEV_SEL_STRAPS,
+       ODM_RSVD,
+       SBK_DEVKEY_STATUS,
+       MASTER_ENB,
+       _PARAMS_U32 = 0x7FFFFFFF
+};
+
+#define MAX_PARAMS ODM_RSVD
+
+/* the order of the members is pre-decided. please do not change */
+struct fuse_data {
+       u32 devkey;
+       u32 jtag_dis;
+       u32 odm_prod_mode;
+       u32 bootdev_cfg;
+       u32 bootdev_sel;
+       u32 sbk[4];
+       u32 sw_rsvd;
+       u32 ignore_devsel_straps;
+       u32 odm_rsvd[8];
+};
+
+/* secondary boot device options */
+enum {
+       SECBOOTDEV_SDMMC,
+       SECBOOTDEV_NOR,
+       SECBOOTDEV_SPI,
+       SECBOOTDEV_NAND,
+       SECBOOTDEV_LBANAND,
+       SECBOOTDEV_MUXONENAND,
+       _SECBOOTDEV_MAX,
+       _SECBOOTDEV_U32 = 0x7FFFFFFF
+};
+
+/*
+ * read the fuse settings
+ * @param: io_param_type - param type enum
+ * @param: size - read size in bytes
+ */
+int tegra_fuse_read(u32 io_param_type, u32 *data, int size);
+
+#define FLAGS_DEVKEY                   BIT(DEVKEY)
+#define FLAGS_JTAG_DIS                 BIT(JTAG_DIS)
+#define FLAGS_SBK_DEVKEY_STATUS        BIT(SBK_DEVKEY_STATUS)
+#define FLAGS_ODM_PROD_MODE            BIT(ODM_PROD_MODE)
+#define FLAGS_SEC_BOOT_DEV_CFG BIT(SEC_BOOT_DEV_CFG)
+#define FLAGS_SEC_BOOT_DEV_SEL BIT(SEC_BOOT_DEV_SEL)
+#define FLAGS_SBK                      BIT(SBK)
+#define FLAGS_SW_RSVD          BIT(SW_RSVD)
+#define FLAGS_IGNORE_DEV_SEL_STRAPS    BIT(IGNORE_DEV_SEL_STRAPS)
+#define FLAGS_ODMRSVD                  BIT(ODM_RSVD)
+
+/*
+ * Prior to invoking this routine, the caller is responsible for supplying
+ * valid fuse programming voltage.
+ *
+ * @param: pgm_data - entire data to be programmed
+ * @flags: program flags (e.g. FLAGS_DEVKEY)
+ */
+int tegra_fuse_program(struct fuse_data *pgm_data, u32 flags);
+
+/* Disables the fuse programming until the next system reset */
+void tegra_fuse_program_disable(void);
+
+#endif
index 4af4a526c33a383cde6b9266676b752ff2fd5e0a..c2c8ef5356c898b290d1e9b6447414ce992e3581 100644 (file)
-/*\r
- * arch/arm/mach-tegra/tegra2_fuse.c\r
- *\r
- * Copyright (c) 2010, NVIDIA Corporation.\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful, but WITHOUT\r
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\r
- * more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
- */\r
-\r
-/*\r
- * Fuses are one time programmable bits on the chip which are used by\r
- * the chip manufacturer and device manufacturers to store chip/device\r
- * configurations. The fuse bits are encapsulated in a 32 x 64 array.\r
- * If a fuse bit is programmed to 1, it cannot be reverted to 0. Either\r
- * another fuse bit has to be used for the same purpose or a new chip\r
- * needs to be used.\r
- *\r
- * Each and every fuse word has its own shadow word which resides adjacent to\r
- * a particular fuse word. e.g. Fuse words 0-1 form a fuse-shadow pair.\r
- * So in theory we have only 32 fuse words to work with.\r
- * The shadow fuse word is a mirror of the actual fuse word at all times\r
- * and this is maintained while programming a particular fuse.\r
- */\r
-\r
-#include <linux/kernel.h>\r
-#include <linux/io.h>\r
-#include <linux/mutex.h>\r
-#include <linux/err.h>\r
-#include <linux/delay.h>\r
-#include <linux/slab.h>\r
-\r
-#include <mach/tegra2_fuse.h>\r
-\r
-#include "fuse.h"\r
-\r
-#define NFUSES 64\r
-#define STATE_IDLE     (0x4 << 16)\r
-\r
-/* since fuse burning is irreversible, use this for testing */\r
-#define ENABLE_FUSE_BURNING 1\r
-\r
-/* fuse registers */\r
-#define FUSE_CTRL              0x000\r
-#define FUSE_REG_ADDR          0x004\r
-#define FUSE_REG_READ          0x008\r
-#define FUSE_REG_WRITE         0x00C\r
-#define FUSE_TIME_PGM          0x01C\r
-#define FUSE_PRIV2INTFC                0x020\r
-#define FUSE_DIS_PGM           0x02C\r
-#define FUSE_PWR_GOOD_SW       0x034\r
-\r
-static u32 fuse_pgm_data[NFUSES / 2];\r
-static u32 fuse_pgm_mask[NFUSES / 2];\r
-static u32 tmp_fuse_pgm_data[NFUSES / 2];\r
-static u8 master_enable;\r
-\r
-DEFINE_MUTEX(fuse_lock);\r
-\r
-static struct fuse_data fuse_info;\r
-\r
-struct param_info {\r
-       u32 *addr;\r
-       int sz;\r
-       u32 start_off;\r
-       int start_bit;\r
-       int nbits;\r
-       int data_offset;\r
-};\r
-\r
-static struct param_info fuse_info_tbl[] = {\r
-       [DEVKEY] = {\r
-               .addr = &fuse_info.devkey,\r
-               .sz = sizeof(fuse_info.devkey),\r
-               .start_off = 0x12,\r
-               .start_bit = 8,\r
-               .nbits = 32,\r
-               .data_offset = 0,\r
-       },\r
-       [JTAG_DIS] = {\r
-               .addr = &fuse_info.jtag_dis,\r
-               .sz = sizeof(fuse_info.jtag_dis),\r
-               .start_off = 0x0,\r
-               .start_bit = 24,\r
-               .nbits = 1,\r
-               .data_offset = 1,\r
-       },\r
-       [ODM_PROD_MODE] = {\r
-               .addr = &fuse_info.odm_prod_mode,\r
-               .sz = sizeof(fuse_info.odm_prod_mode),\r
-               .start_off = 0x0,\r
-               .start_bit = 23,\r
-               .nbits = 1,\r
-               .data_offset = 2,\r
-       },\r
-       [SEC_BOOT_DEV_CFG] = {\r
-               .addr = &fuse_info.bootdev_cfg,\r
-               .sz = sizeof(fuse_info.bootdev_cfg),\r
-               .start_off = 0x14,\r
-               .start_bit = 8,\r
-               .nbits = 16,\r
-               .data_offset = 3,\r
-       },\r
-       [SEC_BOOT_DEV_SEL] = {\r
-               .addr = &fuse_info.bootdev_sel,\r
-               .sz = sizeof(fuse_info.bootdev_sel),\r
-               .start_off = 0x14,\r
-               .start_bit = 24,\r
-               .nbits = 3,\r
-               .data_offset = 4,\r
-       },\r
-       [SBK] = {\r
-               .addr = fuse_info.sbk,\r
-               .sz = sizeof(fuse_info.sbk),\r
-               .start_off = 0x0A,\r
-               .start_bit = 8,\r
-               .nbits = 128,\r
-               .data_offset = 5,\r
-       },\r
-       [SW_RSVD] = {\r
-               .addr = &fuse_info.sw_rsvd,\r
-               .sz = sizeof(fuse_info.sw_rsvd),\r
-               .start_off = 0x14,\r
-               .start_bit = 28,\r
-               .nbits = 4,\r
-               .data_offset = 9,\r
-       },\r
-       [IGNORE_DEV_SEL_STRAPS] = {\r
-               .addr = &fuse_info.ignore_devsel_straps,\r
-               .sz = sizeof(fuse_info.ignore_devsel_straps),\r
-               .start_off = 0x14,\r
-               .start_bit = 27,\r
-               .nbits = 1,\r
-               .data_offset = 10,\r
-       },\r
-       [ODM_RSVD] = {\r
-               .addr = &fuse_info.odm_rsvd,\r
-               .sz = sizeof(fuse_info.odm_rsvd),\r
-               .start_off = 0x16,\r
-               .start_bit = 4,\r
-               .nbits = 256,\r
-               .data_offset = 11,\r
-       },\r
-       [SBK_DEVKEY_STATUS] = {\r
-               .sz = SBK_DEVKEY_STATUS_SZ,\r
-       },\r
-       [MASTER_ENB] = {\r
-               .addr = &master_enable,\r
-               .sz = sizeof(u8),\r
-               .start_off = 0x0,\r
-               .start_bit = 0,\r
-               .nbits = 1,\r
-       },\r
-};\r
-\r
-static void wait_for_idle(void)\r
-{\r
-       u32 reg;\r
-\r
-       do {\r
-               reg = tegra_fuse_readl(FUSE_CTRL);\r
-       } while ((reg & (0xF << 16)) != STATE_IDLE);\r
-}\r
-\r
-#define FUSE_READ      0x1\r
-#define FUSE_WRITE     0x2\r
-#define FUSE_SENSE     0x3\r
-#define FUSE_CMD_MASK  0x3\r
-\r
-static u32 fuse_cmd_read(u32 addr)\r
-{\r
-       u32 reg;\r
-\r
-       tegra_fuse_writel(addr, FUSE_REG_ADDR);\r
-       reg = tegra_fuse_readl(FUSE_CTRL);\r
-       reg &= ~FUSE_CMD_MASK;\r
-       reg |= FUSE_READ;\r
-       tegra_fuse_writel(reg, FUSE_CTRL);\r
-       wait_for_idle();\r
-\r
-       reg = tegra_fuse_readl(FUSE_REG_READ);\r
-       return reg;\r
-}\r
-\r
-static void fuse_cmd_write(u32 value, u32 addr)\r
-{\r
-       u32 reg;\r
-\r
-       tegra_fuse_writel(addr, FUSE_REG_ADDR);\r
-       tegra_fuse_writel(value, FUSE_REG_WRITE);\r
-\r
-       reg = tegra_fuse_readl(FUSE_CTRL);\r
-       reg &= ~FUSE_CMD_MASK;\r
-       reg |= FUSE_WRITE;\r
-       tegra_fuse_writel(reg, FUSE_CTRL);\r
-       wait_for_idle();\r
-}\r
-\r
-static void fuse_cmd_sense(void)\r
-{\r
-       u32 reg;\r
-\r
-       reg = tegra_fuse_readl(FUSE_CTRL);\r
-       reg &= ~FUSE_CMD_MASK;\r
-       reg |= FUSE_SENSE;\r
-       tegra_fuse_writel(reg, FUSE_CTRL);\r
-       wait_for_idle();\r
-}\r
-\r
-static void fuse_reg_hide(void)\r
-{\r
-       u32 reg = tegra_fuse_readl(0x48);\r
-       reg &= ~(1 << 28);\r
-       tegra_fuse_writel(reg, 0x48);\r
-}\r
-\r
-static void fuse_reg_unhide(void)\r
-{\r
-       u32 reg = tegra_fuse_readl(0x48);\r
-       reg |= (1 << 28);\r
-       tegra_fuse_writel(reg, 0x48);\r
-}\r
-\r
-static void get_fuse(enum fuse_io_param io_param, u32 *out)\r
-{\r
-       int start_bit = fuse_info_tbl[io_param].start_bit;\r
-       int nbits = fuse_info_tbl[io_param].nbits;\r
-       int offset = fuse_info_tbl[io_param].start_off;\r
-       u32 *dst = fuse_info_tbl[io_param].addr;\r
-       int dst_bit = 0;\r
-       int i;\r
-       u32 val;\r
-       int loops;\r
-\r
-       if (out)\r
-               dst = out;\r
-\r
-       do {\r
-               val = fuse_cmd_read(offset);\r
-               loops = min(nbits, 32 - start_bit);\r
-               for (i = 0; i < loops; i++) {\r
-                       if (val & (BIT(start_bit + i)))\r
-                               *dst |= BIT(dst_bit);\r
-                       else\r
-                               *dst &= ~BIT(dst_bit);\r
-                       dst_bit++;\r
-                       if (dst_bit == 32) {\r
-                               dst++;\r
-                               dst_bit = 0;\r
-                       }\r
-               }\r
-               nbits -= loops;\r
-               offset += 2;\r
-               start_bit = 0;\r
-       } while (nbits > 0);\r
-}\r
-\r
-int tegra_fuse_read(enum fuse_io_param io_param, u32 *data, int size)\r
-{\r
-       int ret = 0, nbits;\r
-       u32 sbk[4], devkey = 0;\r
-\r
-       if (!data)\r
-               return -EINVAL;\r
-\r
-       if (size != fuse_info_tbl[io_param].sz) {\r
-               pr_err("%s: size mismatch(%d), %d vs %d\n", __func__,\r
-                       (int)io_param, size, fuse_info_tbl[io_param].sz);\r
-               return -EINVAL;\r
-       }\r
-\r
-       mutex_lock(&fuse_lock);\r
-       fuse_reg_unhide();\r
-       fuse_cmd_sense();\r
-\r
-       if (io_param == SBK_DEVKEY_STATUS) {\r
-               *data = 0;\r
-\r
-               get_fuse(SBK, sbk);\r
-               get_fuse(DEVKEY, &devkey);\r
-               nbits = sizeof(sbk) * BITS_PER_BYTE;\r
-               if (find_first_bit((unsigned long *)sbk, nbits) != nbits)\r
-                       *data = 1;\r
-               else if (devkey)\r
-                       *data = 1;\r
-       } else {\r
-               get_fuse(io_param, data);\r
-       }\r
-\r
-       fuse_reg_hide();\r
-       mutex_unlock(&fuse_lock);\r
-       return ret;\r
-}\r
-\r
-static bool fuse_odm_prod_mode(void)\r
-{\r
-       u32 odm_prod_mode = 0;\r
-\r
-       get_fuse(ODM_PROD_MODE, &odm_prod_mode);\r
-       return (odm_prod_mode ? true : false);\r
-}\r
-\r
-static void set_fuse(enum fuse_io_param io_param, u32 *data)\r
-{\r
-       int i, start_bit = fuse_info_tbl[io_param].start_bit;\r
-       int nbits = fuse_info_tbl[io_param].nbits, loops;\r
-       int offset = fuse_info_tbl[io_param].start_off >> 1;\r
-       int src_bit = 0;\r
-       u32 val;\r
-\r
-       do {\r
-               val = *data;\r
-               loops = min(nbits, 32 - start_bit);\r
-               for (i = 0; i < loops; i++) {\r
-                       fuse_pgm_mask[offset] |= BIT(start_bit + i);\r
-                       if (val & BIT(src_bit))\r
-                               fuse_pgm_data[offset] |= BIT(start_bit + i);\r
-                       else\r
-                               fuse_pgm_data[offset] &= ~BIT(start_bit + i);\r
-                       src_bit++;\r
-                       if (src_bit == 32) {\r
-                               data++;\r
-                               val = *data;\r
-                               src_bit = 0;\r
-                       }\r
-               }\r
-               nbits -= loops;\r
-               offset++;\r
-               start_bit = 0;\r
-       } while (nbits > 0);\r
-}\r
-\r
-static void populate_fuse_arrs(struct fuse_data *info, u32 flags)\r
-{\r
-       u32 data = 0;\r
-       u32 *src = (u32 *)info;\r
-       int i;\r
-\r
-       memset(fuse_pgm_data, 0, sizeof(fuse_pgm_data));\r
-       memset(fuse_pgm_mask, 0, sizeof(fuse_pgm_mask));\r
-\r
-       /* enable program bit */\r
-       data = 1;\r
-       set_fuse(MASTER_ENB, &data);\r
-\r
-       if ((flags & FLAGS_ODMRSVD)) {\r
-               set_fuse(ODM_RSVD, info->odm_rsvd);\r
-               flags &= ~FLAGS_ODMRSVD;\r
-       }\r
-\r
-       /* do not burn any more if secure mode is set */\r
-       if (fuse_odm_prod_mode())\r
-               goto out;\r
-\r
-       for_each_set_bit(i, (unsigned long *)&flags, MAX_PARAMS)\r
-               set_fuse(i, src + fuse_info_tbl[i].data_offset);\r
-\r
-out:\r
-       pr_debug("ready to program");\r
-}\r
-\r
-static void fuse_power_enable(void)\r
-{\r
-#if ENABLE_FUSE_BURNING\r
-       tegra_fuse_writel(0x1, FUSE_PWR_GOOD_SW);\r
-       udelay(1);\r
-#endif\r
-}\r
-\r
-static void fuse_power_disable(void)\r
-{\r
-#if ENABLE_FUSE_BURNING\r
-       tegra_fuse_writel(0, FUSE_PWR_GOOD_SW);\r
-       udelay(1);\r
-#endif\r
-}\r
-\r
-static void fuse_program_array(int pgm_cycles)\r
-{\r
-       u32 reg, fuse_val[2];\r
-       u32 *data = tmp_fuse_pgm_data, addr = 0, *mask = fuse_pgm_mask;\r
-       int i = 0;\r
-\r
-       fuse_reg_unhide();\r
-       fuse_cmd_sense();\r
-\r
-       /* get the first 2 fuse bytes */\r
-       fuse_val[0] = fuse_cmd_read(0);\r
-       fuse_val[1] = fuse_cmd_read(1);\r
-\r
-       fuse_power_enable();\r
-\r
-       /*\r
-        * The fuse macro is a high density macro. Fuses are\r
-        * burned using an addressing mechanism, so no need to prepare\r
-        * the full list, but more write to control registers are needed.\r
-        * The only bit that can be written at first is bit 0, a special write\r
-        * protection bit by assumptions all other bits are at 0\r
-        *\r
-        * The programming pulse must have a precise width of\r
-        * [9000, 11000] ns.\r
-        */\r
-       if (pgm_cycles > 0) {\r
-               reg = pgm_cycles;\r
-               tegra_fuse_writel(reg, FUSE_TIME_PGM);\r
-       }\r
-       fuse_val[0] = (0x1 & ~fuse_val[0]);\r
-       fuse_val[1] = (0x1 & ~fuse_val[1]);\r
-       fuse_cmd_write(fuse_val[0], 0);\r
-       fuse_cmd_write(fuse_val[1], 1);\r
-\r
-       fuse_power_disable();\r
-\r
-       /*\r
-        * this will allow programming of other fuses\r
-        * and the reading of the existing fuse values\r
-        */\r
-       fuse_cmd_sense();\r
-\r
-       /* Clear out all bits that have already been burned or masked out */\r
-       memcpy(data, fuse_pgm_data, sizeof(fuse_pgm_data));\r
-\r
-       for (addr = 0; addr < NFUSES; addr += 2, data++, mask++) {\r
-               reg = fuse_cmd_read(addr);\r
-               pr_debug("%d: 0x%x 0x%x 0x%x\n", addr, (u32)(*data),\r
-                       ~reg, (u32)(*mask));\r
-               *data = (*data & ~reg) & *mask;\r
-       }\r
-\r
-       fuse_power_enable();\r
-\r
-       /*\r
-        * Finally loop on all fuses, program the non zero ones.\r
-        * Words 0 and 1 are written last and they contain control fuses. We\r
-        * need to invalidate after writing to a control word (with the exception\r
-        * of the master enable). This is also the reason we write them last.\r
-        */\r
-       for (i = ARRAY_SIZE(fuse_pgm_data) - 1; i >= 0; i--) {\r
-               if (tmp_fuse_pgm_data[i]) {\r
-                       fuse_cmd_write(tmp_fuse_pgm_data[i], i * 2);\r
-                       fuse_cmd_write(tmp_fuse_pgm_data[i], (i * 2) + 1);\r
-               }\r
-\r
-               if (i < 2) {\r
-                       fuse_power_disable();\r
-                       fuse_cmd_sense();\r
-                       fuse_power_enable();\r
-               }\r
-       }\r
-\r
-       /* Read all data into the chip options */\r
-       tegra_fuse_writel(0x1, FUSE_PRIV2INTFC);\r
-       udelay(1);\r
-       tegra_fuse_writel(0, FUSE_PRIV2INTFC);\r
-\r
-       while (!(tegra_fuse_readl(FUSE_CTRL) & (1 << 30)));\r
-\r
-       fuse_reg_hide();\r
-       fuse_power_disable();\r
-}\r
-\r
-static int fuse_set(enum fuse_io_param io_param, u32 *param, int size)\r
-{\r
-       int i, nwords = size / sizeof(u32);\r
-       u32 *data;\r
-\r
-       if (io_param > MAX_PARAMS)\r
-               return -EINVAL;\r
-\r
-       data = (u32*)kzalloc(size, GFP_KERNEL);\r
-       if (!data) {\r
-               pr_err("failed to alloc %d bytes\n", nwords);\r
-               return -ENOMEM;\r
-       }\r
-\r
-       get_fuse(io_param, data);\r
-\r
-       for (i = 0; i < nwords; i++) {\r
-               if ((data[i] | param[i]) != param[i]) {\r
-                       pr_info("hw_val: 0x%x, sw_val: 0x%x, final: 0x%x\n",\r
-                               data[i], param[i], (data[i] | param[i]));\r
-                       param[i] = (data[i] | param[i]);\r
-               }\r
-       }\r
-       kfree(data);\r
-       return 0;\r
-}\r
-\r
-int tegra_fuse_program(struct fuse_data *pgm_data, u32 flags)\r
-{\r
-       u32 reg;\r
-       int i = 0;\r
-\r
-       mutex_lock(&fuse_lock);\r
-       reg = tegra_fuse_readl(FUSE_DIS_PGM);\r
-       mutex_unlock(&fuse_lock);\r
-       if (reg) {\r
-               pr_err("fuse programming disabled");\r
-               return -EACCES;\r
-       }\r
-\r
-       if (fuse_odm_prod_mode() && (flags != FLAGS_ODMRSVD)) {\r
-               pr_err("reserved odm fuses are allowed in secure mode");\r
-               return -EPERM;\r
-       }\r
-\r
-       if ((flags & FLAGS_ODM_PROD_MODE) &&\r
-               (flags & (FLAGS_SBK | FLAGS_DEVKEY))) {\r
-               pr_err("odm production mode and sbk/devkey not allowed");\r
-               return -EPERM;\r
-       }\r
-\r
-       mutex_lock(&fuse_lock);\r
-       memcpy(&fuse_info, pgm_data, sizeof(fuse_info));\r
-       for_each_set_bit(i, (unsigned long *)&flags, MAX_PARAMS) {\r
-               fuse_set((u32)i, fuse_info_tbl[i].addr,\r
-                       fuse_info_tbl[i].sz);\r
-       }\r
-\r
-       populate_fuse_arrs(&fuse_info, flags);\r
-       fuse_program_array(0);\r
-\r
-       /* disable program bit */\r
-       reg = 0;\r
-       set_fuse(MASTER_ENB, &reg);\r
-\r
-       memset(&fuse_info, 0, sizeof(fuse_info));\r
-       mutex_unlock(&fuse_lock);\r
-\r
-       return 0;\r
-}\r
-\r
-void tegra_fuse_program_disable(void)\r
-{\r
-       mutex_lock(&fuse_lock);\r
-       tegra_fuse_writel(0x1, FUSE_DIS_PGM);\r
-       mutex_unlock(&fuse_lock);\r
-}\r
-
-static int __init tegra_fuse_program_init(void)\r
-{\r
-       mutex_init(&fuse_lock);\r
-       return 0;\r
-}\r
-\r
-module_init(tegra_fuse_program_init);\r
+/*
+ * arch/arm/mach-tegra/tegra2_fuse.c
+ *
+ * Copyright (c) 2010, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/*
+ * Fuses are one time programmable bits on the chip which are used by
+ * the chip manufacturer and device manufacturers to store chip/device
+ * configurations. The fuse bits are encapsulated in a 32 x 64 array.
+ * If a fuse bit is programmed to 1, it cannot be reverted to 0. Either
+ * another fuse bit has to be used for the same purpose or a new chip
+ * needs to be used.
+ *
+ * Each and every fuse word has its own shadow word which resides adjacent to
+ * a particular fuse word. e.g. Fuse words 0-1 form a fuse-shadow pair.
+ * So in theory we have only 32 fuse words to work with.
+ * The shadow fuse word is a mirror of the actual fuse word at all times
+ * and this is maintained while programming a particular fuse.
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+
+#include <mach/tegra2_fuse.h>
+
+#include "fuse.h"
+
+#define NFUSES 64
+#define STATE_IDLE     (0x4 << 16)
+
+/* since fuse burning is irreversible, use this for testing */
+#define ENABLE_FUSE_BURNING 1
+
+/* fuse registers */
+#define FUSE_CTRL              0x000
+#define FUSE_REG_ADDR          0x004
+#define FUSE_REG_READ          0x008
+#define FUSE_REG_WRITE         0x00C
+#define FUSE_TIME_PGM          0x01C
+#define FUSE_PRIV2INTFC                0x020
+#define FUSE_DIS_PGM           0x02C
+#define FUSE_PWR_GOOD_SW       0x034
+
+static u32 fuse_pgm_data[NFUSES / 2];
+static u32 fuse_pgm_mask[NFUSES / 2];
+static u32 tmp_fuse_pgm_data[NFUSES / 2];
+static u8 master_enable;
+
+DEFINE_MUTEX(fuse_lock);
+
+static struct fuse_data fuse_info;
+
+struct param_info {
+       u32 *addr;
+       int sz;
+       u32 start_off;
+       int start_bit;
+       int nbits;
+       int data_offset;
+};
+
+static struct param_info fuse_info_tbl[] = {
+       [DEVKEY] = {
+               .addr = &fuse_info.devkey,
+               .sz = sizeof(fuse_info.devkey),
+               .start_off = 0x12,
+               .start_bit = 8,
+               .nbits = 32,
+               .data_offset = 0,
+       },
+       [JTAG_DIS] = {
+               .addr = &fuse_info.jtag_dis,
+               .sz = sizeof(fuse_info.jtag_dis),
+               .start_off = 0x0,
+               .start_bit = 24,
+               .nbits = 1,
+               .data_offset = 1,
+       },
+       [ODM_PROD_MODE] = {
+               .addr = &fuse_info.odm_prod_mode,
+               .sz = sizeof(fuse_info.odm_prod_mode),
+               .start_off = 0x0,
+               .start_bit = 23,
+               .nbits = 1,
+               .data_offset = 2,
+       },
+       [SEC_BOOT_DEV_CFG] = {
+               .addr = &fuse_info.bootdev_cfg,
+               .sz = sizeof(fuse_info.bootdev_cfg),
+               .start_off = 0x14,
+               .start_bit = 8,
+               .nbits = 16,
+               .data_offset = 3,
+       },
+       [SEC_BOOT_DEV_SEL] = {
+               .addr = &fuse_info.bootdev_sel,
+               .sz = sizeof(fuse_info.bootdev_sel),
+               .start_off = 0x14,
+               .start_bit = 24,
+               .nbits = 3,
+               .data_offset = 4,
+       },
+       [SBK] = {
+               .addr = fuse_info.sbk,
+               .sz = sizeof(fuse_info.sbk),
+               .start_off = 0x0A,
+               .start_bit = 8,
+               .nbits = 128,
+               .data_offset = 5,
+       },
+       [SW_RSVD] = {
+               .addr = &fuse_info.sw_rsvd,
+               .sz = sizeof(fuse_info.sw_rsvd),
+               .start_off = 0x14,
+               .start_bit = 28,
+               .nbits = 4,
+               .data_offset = 9,
+       },
+       [IGNORE_DEV_SEL_STRAPS] = {
+               .addr = &fuse_info.ignore_devsel_straps,
+               .sz = sizeof(fuse_info.ignore_devsel_straps),
+               .start_off = 0x14,
+               .start_bit = 27,
+               .nbits = 1,
+               .data_offset = 10,
+       },
+       [ODM_RSVD] = {
+               .addr = &fuse_info.odm_rsvd,
+               .sz = sizeof(fuse_info.odm_rsvd),
+               .start_off = 0x16,
+               .start_bit = 4,
+               .nbits = 256,
+               .data_offset = 11,
+       },
+       [SBK_DEVKEY_STATUS] = {
+               .sz = SBK_DEVKEY_STATUS_SZ,
+       },
+       [MASTER_ENB] = {
+               .addr = &master_enable,
+               .sz = sizeof(u8),
+               .start_off = 0x0,
+               .start_bit = 0,
+               .nbits = 1,
+       },
+};
+
+static void wait_for_idle(void)
+{
+       u32 reg;
+
+       do {
+               reg = tegra_fuse_readl(FUSE_CTRL);
+       } while ((reg & (0xF << 16)) != STATE_IDLE);
+}
+
+#define FUSE_READ      0x1
+#define FUSE_WRITE     0x2
+#define FUSE_SENSE     0x3
+#define FUSE_CMD_MASK  0x3
+
+static u32 fuse_cmd_read(u32 addr)
+{
+       u32 reg;
+
+       tegra_fuse_writel(addr, FUSE_REG_ADDR);
+       reg = tegra_fuse_readl(FUSE_CTRL);
+       reg &= ~FUSE_CMD_MASK;
+       reg |= FUSE_READ;
+       tegra_fuse_writel(reg, FUSE_CTRL);
+       wait_for_idle();
+
+       reg = tegra_fuse_readl(FUSE_REG_READ);
+       return reg;
+}
+
+static void fuse_cmd_write(u32 value, u32 addr)
+{
+       u32 reg;
+
+       tegra_fuse_writel(addr, FUSE_REG_ADDR);
+       tegra_fuse_writel(value, FUSE_REG_WRITE);
+
+       reg = tegra_fuse_readl(FUSE_CTRL);
+       reg &= ~FUSE_CMD_MASK;
+       reg |= FUSE_WRITE;
+       tegra_fuse_writel(reg, FUSE_CTRL);
+       wait_for_idle();
+}
+
+static void fuse_cmd_sense(void)
+{
+       u32 reg;
+
+       reg = tegra_fuse_readl(FUSE_CTRL);
+       reg &= ~FUSE_CMD_MASK;
+       reg |= FUSE_SENSE;
+       tegra_fuse_writel(reg, FUSE_CTRL);
+       wait_for_idle();
+}
+
+static void fuse_reg_hide(void)
+{
+       u32 reg = tegra_fuse_readl(0x48);
+       reg &= ~(1 << 28);
+       tegra_fuse_writel(reg, 0x48);
+}
+
+static void fuse_reg_unhide(void)
+{
+       u32 reg = tegra_fuse_readl(0x48);
+       reg |= (1 << 28);
+       tegra_fuse_writel(reg, 0x48);
+}
+
+static void get_fuse(enum fuse_io_param io_param, u32 *out)
+{
+       int start_bit = fuse_info_tbl[io_param].start_bit;
+       int nbits = fuse_info_tbl[io_param].nbits;
+       int offset = fuse_info_tbl[io_param].start_off;
+       u32 *dst = fuse_info_tbl[io_param].addr;
+       int dst_bit = 0;
+       int i;
+       u32 val;
+       int loops;
+
+       if (out)
+               dst = out;
+
+       do {
+               val = fuse_cmd_read(offset);
+               loops = min(nbits, 32 - start_bit);
+               for (i = 0; i < loops; i++) {
+                       if (val & (BIT(start_bit + i)))
+                               *dst |= BIT(dst_bit);
+                       else
+                               *dst &= ~BIT(dst_bit);
+                       dst_bit++;
+                       if (dst_bit == 32) {
+                               dst++;
+                               dst_bit = 0;
+                       }
+               }
+               nbits -= loops;
+               offset += 2;
+               start_bit = 0;
+       } while (nbits > 0);
+}
+
+int tegra_fuse_read(enum fuse_io_param io_param, u32 *data, int size)
+{
+       int ret = 0, nbits;
+       u32 sbk[4], devkey = 0;
+
+       if (!data)
+               return -EINVAL;
+
+       if (size != fuse_info_tbl[io_param].sz) {
+               pr_err("%s: size mismatch(%d), %d vs %d\n", __func__,
+                       (int)io_param, size, fuse_info_tbl[io_param].sz);
+               return -EINVAL;
+       }
+
+       mutex_lock(&fuse_lock);
+       fuse_reg_unhide();
+       fuse_cmd_sense();
+
+       if (io_param == SBK_DEVKEY_STATUS) {
+               *data = 0;
+
+               get_fuse(SBK, sbk);
+               get_fuse(DEVKEY, &devkey);
+               nbits = sizeof(sbk) * BITS_PER_BYTE;
+               if (find_first_bit((unsigned long *)sbk, nbits) != nbits)
+                       *data = 1;
+               else if (devkey)
+                       *data = 1;
+       } else {
+               get_fuse(io_param, data);
+       }
+
+       fuse_reg_hide();
+       mutex_unlock(&fuse_lock);
+       return ret;
+}
+
+static bool fuse_odm_prod_mode(void)
+{
+       u32 odm_prod_mode = 0;
+
+       get_fuse(ODM_PROD_MODE, &odm_prod_mode);
+       return (odm_prod_mode ? true : false);
+}
+
+static void set_fuse(enum fuse_io_param io_param, u32 *data)
+{
+       int i, start_bit = fuse_info_tbl[io_param].start_bit;
+       int nbits = fuse_info_tbl[io_param].nbits, loops;
+       int offset = fuse_info_tbl[io_param].start_off >> 1;
+       int src_bit = 0;
+       u32 val;
+
+       do {
+               val = *data;
+               loops = min(nbits, 32 - start_bit);
+               for (i = 0; i < loops; i++) {
+                       fuse_pgm_mask[offset] |= BIT(start_bit + i);
+                       if (val & BIT(src_bit))
+                               fuse_pgm_data[offset] |= BIT(start_bit + i);
+                       else
+                               fuse_pgm_data[offset] &= ~BIT(start_bit + i);
+                       src_bit++;
+                       if (src_bit == 32) {
+                               data++;
+                               val = *data;
+                               src_bit = 0;
+                       }
+               }
+               nbits -= loops;
+               offset++;
+               start_bit = 0;
+       } while (nbits > 0);
+}
+
+static void populate_fuse_arrs(struct fuse_data *info, u32 flags)
+{
+       u32 data = 0;
+       u32 *src = (u32 *)info;
+       int i;
+
+       memset(fuse_pgm_data, 0, sizeof(fuse_pgm_data));
+       memset(fuse_pgm_mask, 0, sizeof(fuse_pgm_mask));
+
+       /* enable program bit */
+       data = 1;
+       set_fuse(MASTER_ENB, &data);
+
+       if ((flags & FLAGS_ODMRSVD)) {
+               set_fuse(ODM_RSVD, info->odm_rsvd);
+               flags &= ~FLAGS_ODMRSVD;
+       }
+
+       /* do not burn any more if secure mode is set */
+       if (fuse_odm_prod_mode())
+               goto out;
+
+       for_each_set_bit(i, (unsigned long *)&flags, MAX_PARAMS)
+               set_fuse(i, src + fuse_info_tbl[i].data_offset);
+
+out:
+       pr_debug("ready to program");
+}
+
+static void fuse_power_enable(void)
+{
+#if ENABLE_FUSE_BURNING
+       tegra_fuse_writel(0x1, FUSE_PWR_GOOD_SW);
+       udelay(1);
+#endif
+}
+
+static void fuse_power_disable(void)
+{
+#if ENABLE_FUSE_BURNING
+       tegra_fuse_writel(0, FUSE_PWR_GOOD_SW);
+       udelay(1);
+#endif
+}
+
+static void fuse_program_array(int pgm_cycles)
+{
+       u32 reg, fuse_val[2];
+       u32 *data = tmp_fuse_pgm_data, addr = 0, *mask = fuse_pgm_mask;
+       int i = 0;
+
+       fuse_reg_unhide();
+       fuse_cmd_sense();
+
+       /* get the first 2 fuse bytes */
+       fuse_val[0] = fuse_cmd_read(0);
+       fuse_val[1] = fuse_cmd_read(1);
+
+       fuse_power_enable();
+
+       /*
+        * The fuse macro is a high density macro. Fuses are
+        * burned using an addressing mechanism, so no need to prepare
+        * the full list, but more write to control registers are needed.
+        * 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
+        *
+        * The programming pulse must have a precise width of
+        * [9000, 11000] ns.
+        */
+       if (pgm_cycles > 0) {
+               reg = pgm_cycles;
+               tegra_fuse_writel(reg, FUSE_TIME_PGM);
+       }
+       fuse_val[0] = (0x1 & ~fuse_val[0]);
+       fuse_val[1] = (0x1 & ~fuse_val[1]);
+       fuse_cmd_write(fuse_val[0], 0);
+       fuse_cmd_write(fuse_val[1], 1);
+
+       fuse_power_disable();
+
+       /*
+        * this will allow programming of other fuses
+        * and the reading of the existing fuse values
+        */
+       fuse_cmd_sense();
+
+       /* Clear out all bits that have already been burned or masked out */
+       memcpy(data, fuse_pgm_data, sizeof(fuse_pgm_data));
+
+       for (addr = 0; addr < NFUSES; addr += 2, data++, mask++) {
+               reg = fuse_cmd_read(addr);
+               pr_debug("%d: 0x%x 0x%x 0x%x\n", addr, (u32)(*data),
+                       ~reg, (u32)(*mask));
+               *data = (*data & ~reg) & *mask;
+       }
+
+       fuse_power_enable();
+
+       /*
+        * Finally loop on all fuses, program the non zero ones.
+        * Words 0 and 1 are written last and they contain control fuses. We
+        * need to invalidate after writing to a control word (with the exception
+        * of the master enable). This is also the reason we write them last.
+        */
+       for (i = ARRAY_SIZE(fuse_pgm_data) - 1; i >= 0; i--) {
+               if (tmp_fuse_pgm_data[i]) {
+                       fuse_cmd_write(tmp_fuse_pgm_data[i], i * 2);
+                       fuse_cmd_write(tmp_fuse_pgm_data[i], (i * 2) + 1);
+               }
+
+               if (i < 2) {
+                       fuse_power_disable();
+                       fuse_cmd_sense();
+                       fuse_power_enable();
+               }
+       }
+
+       /* Read all data into the chip options */
+       tegra_fuse_writel(0x1, FUSE_PRIV2INTFC);
+       udelay(1);
+       tegra_fuse_writel(0, FUSE_PRIV2INTFC);
+
+       while (!(tegra_fuse_readl(FUSE_CTRL) & (1 << 30)));
+
+       fuse_reg_hide();
+       fuse_power_disable();
+}
+
+static int fuse_set(enum fuse_io_param io_param, u32 *param, int size)
+{
+       int i, nwords = size / sizeof(u32);
+       u32 *data;
+
+       if (io_param > MAX_PARAMS)
+               return -EINVAL;
+
+       data = (u32*)kzalloc(size, GFP_KERNEL);
+       if (!data) {
+               pr_err("failed to alloc %d bytes\n", nwords);
+               return -ENOMEM;
+       }
+
+       get_fuse(io_param, data);
+
+       for (i = 0; i < nwords; i++) {
+               if ((data[i] | param[i]) != param[i]) {
+                       pr_info("hw_val: 0x%x, sw_val: 0x%x, final: 0x%x\n",
+                               data[i], param[i], (data[i] | param[i]));
+                       param[i] = (data[i] | param[i]);
+               }
+       }
+       kfree(data);
+       return 0;
+}
+
+int tegra_fuse_program(struct fuse_data *pgm_data, u32 flags)
+{
+       u32 reg;
+       int i = 0;
+
+       mutex_lock(&fuse_lock);
+       reg = tegra_fuse_readl(FUSE_DIS_PGM);
+       mutex_unlock(&fuse_lock);
+       if (reg) {
+               pr_err("fuse programming disabled");
+               return -EACCES;
+       }
+
+       if (fuse_odm_prod_mode() && (flags != FLAGS_ODMRSVD)) {
+               pr_err("reserved odm fuses are allowed in secure mode");
+               return -EPERM;
+       }
+
+       if ((flags & FLAGS_ODM_PROD_MODE) &&
+               (flags & (FLAGS_SBK | FLAGS_DEVKEY))) {
+               pr_err("odm production mode and sbk/devkey not allowed");
+               return -EPERM;
+       }
+
+       mutex_lock(&fuse_lock);
+       memcpy(&fuse_info, pgm_data, sizeof(fuse_info));
+       for_each_set_bit(i, (unsigned long *)&flags, MAX_PARAMS) {
+               fuse_set((u32)i, fuse_info_tbl[i].addr,
+                       fuse_info_tbl[i].sz);
+       }
+
+       populate_fuse_arrs(&fuse_info, flags);
+       fuse_program_array(0);
+
+       /* disable program bit */
+       reg = 0;
+       set_fuse(MASTER_ENB, &reg);
+
+       memset(&fuse_info, 0, sizeof(fuse_info));
+       mutex_unlock(&fuse_lock);
+
+       return 0;
+}
+
+void tegra_fuse_program_disable(void)
+{
+       mutex_lock(&fuse_lock);
+       tegra_fuse_writel(0x1, FUSE_DIS_PGM);
+       mutex_unlock(&fuse_lock);
+}
+
+static int __init tegra_fuse_program_init(void)
+{
+       mutex_init(&fuse_lock);
+       return 0;
+}
+
+module_init(tegra_fuse_program_init);