summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorVarun Wadekar <vwadekar@nvidia.com>2011-06-09 18:53:30 +0530
committerYuhao Ding <yding@nvidia.com>2011-06-13 12:09:55 -0700
commit9b4f35c9f77b614984707f4cf55afc8198b5a31f (patch)
treee7a83ccaaa2919d21ceba25a80475210bf4acc25 /arch
parent6eda0a50810b4b1f6cbeb921d32421632579392e (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.c38
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, &reg);
-
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)