summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorVarun Wadekar <vwadekar@nvidia.com>2011-06-09 18:53:30 +0530
committerManish Tuteja <mtuteja@nvidia.com>2011-07-25 02:31:52 -0700
commit047c82473b70803b21566f43bbabe9b7bf7423be (patch)
tree434f888f1b4b0a24f29ffd4afd3f304ae238bc15 /arch
parent212dbd9fc2a293ee095cb214fe1d110956fcab7f (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 Reviewed-on: http://git-master/r/35883 Bug 836963 Change-Id: I645da7e5ffbce10e3492c7e1bfe14be14e65b789 Signed-off-by: Varun Wadekar <vwadekar@nvidia.com> Reviewed-on: http://git-master/r/42313 Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-tegra/tegra2_fuse.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/arch/arm/mach-tegra/tegra2_fuse.c b/arch/arm/mach-tegra/tegra2_fuse.c
index 028b984f1890..b8fcd2371a5b 100644
--- a/arch/arm/mach-tegra/tegra2_fuse.c
+++ b/arch/arm/mach-tegra/tegra2_fuse.c
@@ -229,6 +229,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;
@@ -244,6 +245,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);
@@ -258,6 +260,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;
@@ -707,7 +710,8 @@ static ssize_t fuse_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t count)
{
enum fuse_io_param param = fuse_name_to_param(attr->attr.name);
- int ret, orig_count = count;
+ 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;
@@ -743,15 +747,25 @@ 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;
/* in case of odd number of writes, write the first one here */
if (count & 0x1) {
*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));
@@ -777,7 +791,7 @@ static ssize_t fuse_store(struct kobject *kobj, struct kobj_attribute *attr,
done:
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)