diff options
author | Varun Wadekar <vwadekar@nvidia.com> | 2011-06-09 18:53:30 +0530 |
---|---|---|
committer | Yuhao Ding <yding@nvidia.com> | 2011-06-13 12:09:55 -0700 |
commit | 9b4f35c9f77b614984707f4cf55afc8198b5a31f (patch) | |
tree | e7a83ccaaa2919d21ceba25a80475210bf4acc25 /arch | |
parent | 6eda0a50810b4b1f6cbeb921d32421632579392e (diff) |
arm: tegra: fuse: fix multiple issues
- handle scenarios when the number of fuses burnt
is a odd number
- wait for the fuse bock to be idle before issuing
any command
- burning of master_enb fuse is not required to be
done according to the guidelines
Bug 823552
Change-Id: I04477dcfae610aed3e2072adfc48ebd7212449ad
Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
Reviewed-on: http://git-master/r/35883
Reviewed-by: Andy Carman <acarman@nvidia.com>
Tested-by: Andy Carman <acarman@nvidia.com>
Reviewed-by: Venkata (Muni) Anda <vanda@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-tegra/tegra2_fuse.c | 38 |
1 files changed, 19 insertions, 19 deletions
diff --git a/arch/arm/mach-tegra/tegra2_fuse.c b/arch/arm/mach-tegra/tegra2_fuse.c index 97cf6e070f2b..4210b0d9ef33 100644 --- a/arch/arm/mach-tegra/tegra2_fuse.c +++ b/arch/arm/mach-tegra/tegra2_fuse.c @@ -206,13 +206,6 @@ static struct param_info fuse_info_tbl[] = { [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) @@ -233,6 +226,7 @@ static u32 fuse_cmd_read(u32 addr) { u32 reg; + wait_for_idle(); tegra_fuse_writel(addr, FUSE_REG_ADDR); reg = tegra_fuse_readl(FUSE_CTRL); reg &= ~FUSE_CMD_MASK; @@ -248,6 +242,7 @@ static void fuse_cmd_write(u32 value, u32 addr) { u32 reg; + wait_for_idle(); tegra_fuse_writel(addr, FUSE_REG_ADDR); tegra_fuse_writel(value, FUSE_REG_WRITE); @@ -262,6 +257,7 @@ static void fuse_cmd_sense(void) { u32 reg; + wait_for_idle(); reg = tegra_fuse_readl(FUSE_CTRL); reg &= ~FUSE_CMD_MASK; reg |= FUSE_SENSE; @@ -401,10 +397,6 @@ static void populate_fuse_arrs(struct fuse_data *info, u32 flags) 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; @@ -610,10 +602,6 @@ int tegra_fuse_program(struct fuse_data *pgm_data, u32 flags) pr_debug("%s: use %d programming cycles\n", __func__, fuse_pgm_cycles[index]); fuse_program_array(fuse_pgm_cycles[index]); - /* disable program bit */ - reg = 0; - set_fuse(MASTER_ENB, ®); - memset(&fuse_info, 0, sizeof(fuse_info)); regulator_disable(vdd_fuse); mutex_unlock(&fuse_lock); @@ -663,6 +651,7 @@ static ssize_t fuse_store(struct kobject *kobj, struct kobj_attribute *attr, { enum fuse_io_param param = fuse_name_to_param(attr->attr.name); int ret, i = 0; + int orig_count = count; struct fuse_data data = {0}; u32 *raw_data = ((u32 *)&data) + fuse_info_tbl[param].data_offset; u8 *raw_byte_data = (u8 *)raw_data; @@ -692,13 +681,24 @@ static ssize_t fuse_store(struct kobject *kobj, struct kobj_attribute *attr, wake_lock_init(&fuse_wk_lock, WAKE_LOCK_SUSPEND, "fuse_wk_lock"); wake_lock(&fuse_wk_lock); + /* we need to fit each character into a single nibble */ raw_byte_data += DIV_ROUND_UP(count, 2) - 1; - for (i = 0; i < DIV_ROUND_UP(count, 2); i++, buf++) { + + if (count % 2) { *raw_byte_data = char_to_xdigit(*buf); - *raw_byte_data <<= 4; buf++; - *raw_byte_data |= (char_to_xdigit(*buf) & 0xF); raw_byte_data--; + count--; + } + + for (i = 1; i <= count; i++, buf++) { + if (i % 2) { + *raw_byte_data = char_to_xdigit(*buf); + } else { + *raw_byte_data <<= 4; + *raw_byte_data |= char_to_xdigit(*buf); + raw_byte_data--; + } } ret = tegra_fuse_program(&data, BIT(param)); @@ -724,7 +724,7 @@ static ssize_t fuse_store(struct kobject *kobj, struct kobj_attribute *attr, wake_unlock(&fuse_wk_lock); wake_lock_destroy(&fuse_wk_lock); - return count; + return orig_count; } static ssize_t fuse_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) |