diff --git a/drivers/power/bq27421_battery.c b/drivers/power/bq27421_battery.c
index 83438b026713972b8b18ad2e44c552f308aa109a..96b7dcbda54576f35852bbc4d4b2f8c25f1ab42d 100644
--- a/drivers/power/bq27421_battery.c
+++ b/drivers/power/bq27421_battery.c
@@ -1,258 +1,135 @@
 /*
- *  bq27421_battery.c
- *  fuel-gauge systems for lithium-ion (Li+) batteries
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
+* Fuel gauge driver for TI BQ27421
+*
+* Copyright(c) 2014, LGE Inc. All rights reserved.
+* ChoongRyeol Lee <choongryeol.lee@lge.com>
+*
+* This software is licensed under the terms of the GNU General Public
+* License version 2, as published by the Free Software Foundation, and
+* may be copied, distributed, and modified under those terms.
+*
+* 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.
+*
+*/
 
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/platform_device.h>
 #include <linux/err.h>
 #include <linux/i2c.h>
 #include <linux/delay.h>
 #include <linux/power_supply.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/fs.h>
 #include <linux/of.h>
 #include <linux/mod_devicetable.h>
 #include <linux/power/bq27421_battery.h>
-#include <asm/uaccess.h>
-#include <asm/unaligned.h>
 
-#ifdef BQ27421_DEBUG
-#define bq27421_dbg(x, ...) pr_info("bq27421: " x, ##__VA_ARGS__)
-#endif
+#define SOC_LOW_THRESHOLD  3
 
 struct bq27421_chip {
 	struct i2c_client *client;
 	struct power_supply battery;
 	struct bq27421_platform_data *pdata;
 	struct mutex mutex;
+	struct timespec next_update_time;
 	bool suspended;
 	bool power_supply_registered;
-	int status;
+	bool irq_wake_enabled;
 	int vcell;
-	int last_vcell;
 	int soc;
-	int last_soc;
-	int capacity_level;
-	int average_current;
-	int remaining_capacity;
-	int full_charge_capacity;
+	int current_now;
 	int temperature;
-	int soh;
-	struct delayed_work socint_work;
-#ifdef BQ27421_DEBUG
-	int PresentDOD;
-	int OCVCurrent;
-	int OCVVoltage;
-	int RemainingCapacityUnfiltered;
-	int FullChargeCapacityUnfiltered;
-	int DOD0;
-	int PassedCharge;
-	int Qstart;
-#endif
 };
 
-static int bq27421_read_word(struct i2c_client *client, int reg)
+static int bq27421_read_word(struct i2c_client *client, u8 reg)
 {
-	struct bq27421_chip *chip = i2c_get_clientdata(client);
 	int ret;
 
-	if (!client->adapter)
-		return -ENODEV;
-
-	mutex_lock(&chip->mutex);
 	ret = i2c_smbus_read_word_data(client, reg);
+	if (ret < 0)
+		dev_err(&client->dev, "%s: err %d\n", __func__, ret);
 
-	if (ret < 0) {
-		dev_err(&client->dev,
-			"%s(): Failed in reading register 0x%02x err %d\n",
-			__func__, reg, ret);
-	}
+	pr_debug("%s: [%x]=%x\n", __func__, reg, ret);
 
-	mutex_unlock(&chip->mutex);
 	return ret;
 }
 
-static int bq27421_read(struct i2c_client *client, u8 reg, int *rt_value, int b_single, int b_dataflash)
+static int bq27421_write_word(struct i2c_client *client, u8 reg, u16 value)
 {
-	struct bq27421_chip *chip = i2c_get_clientdata(client);
-	struct i2c_msg msg[1];
-	u8 data[2];
-	int err;
-
-	if (!client->adapter)
-		return -ENODEV;
-
-	mutex_lock(&chip->mutex);
-
-	msg->addr = client->addr;
-	msg->flags = 0;
-	msg->len = 1;
-	msg->buf = data;
-
-	data[0] = reg;
-
-	err = i2c_transfer(client->adapter, msg, 1);
-
-	if (err >= 0) {
-		if (!b_single)
-			msg->len = 2;
-		else
-			msg->len = 1;
-
-		msg->flags = I2C_M_RD;
-
-		err = i2c_transfer(client->adapter, msg, 1);
-		if (err >= 0) {
-			if (!b_single) {
-				if (unlikely(b_dataflash))
-					*rt_value = get_unaligned_be16(data);
-				else
-					*rt_value = get_unaligned_le16(data);
-			}
-			else {
-				*rt_value = data[0];
-			}
-
-			mutex_unlock(&chip->mutex);
-			return 0;
-		}
-		else {
-			pr_err("%s: err = %d\n", __func__, err);
-		}
-	}
+	int ret;
+
+	ret = i2c_smbus_write_word_data(client, reg, value);
+	if (ret < 0)
+		dev_err(&client->dev, "%s: err %d\n", __func__, ret);
+
+	pr_debug("%s: [%x]=%x\n", __func__, reg, value);
 
-	mutex_unlock(&chip->mutex);
-	return err;
+	return ret;
 }
 
-static int bq27421_i2c_txsubcmd(u8 reg, u16 subcmd,
-		struct i2c_client *client)
+static int bq27421_get_ctrl_status(struct bq27421_chip *chip)
 {
-	struct i2c_msg msg;
-	u8 data[3];
-	int ret;
+	struct i2c_client *client = chip->client;
 
-	if (!client)
-		return -ENODEV;
+	bq27421_write_word(client, BQ27421_CONTROL,
+					BQ27421_SCMD_CTRL_STAT);
+	udelay(66);
 
-	memset(data, 0, sizeof(data));
-	data[0] = reg;
-	data[1] = subcmd & 0x00FF;
-	data[2] = (subcmd & 0xFF00) >> 8;
+	return bq27421_read_word(client, BQ27421_CONTROL);
+}
 
-	msg.addr = client->addr;
-	msg.flags = 0;
-	msg.len = 3;
-	msg.buf = data;
+static bool bq27421_is_unsealed(struct bq27421_chip *chip)
+{
+	int status;
 
-	ret = i2c_transfer(client->adapter, &msg, 1);
-	if (ret < 0)
-		return -EIO;
+	status = bq27421_get_ctrl_status(chip);
+	if (status < 0) {
+		pr_err("%s: failed to get control status\n", __func__);
+		return false;
+	}
 
-	return 0;
+	return !(status & 0x2000);
 }
 
-static void bq27421_cntl_cmd(struct i2c_client *client, int subcmd)
+static bool bq27421_ctrl_sealed(struct bq27421_chip *chip)
 {
-	int ret;
+	bq27421_write_word(chip->client, BQ27421_CONTROL,
+					BQ27421_SCMD_SEALED);
 
-	ret = bq27421_i2c_txsubcmd(BQ27421_REG_CONTROL, subcmd, client);
+	msleep(100);
 
-	if (ret < 0)
-		pr_err("%s: err %d\n", __func__, ret);
+	return !bq27421_is_unsealed(chip);
 }
 
-static int bq27421_get_status(struct bq27421_chip *chip)
+/* Must call with mutex locked */
+static void bq27421_update(struct bq27421_chip *chip)
 {
 	struct i2c_client *client = chip->client;
 	int ret;
 
-	bq27421_cntl_cmd(client, BQ27421_SUBCMD_CTNL_STATUS);
-	udelay(66);
-
-	ret = bq27421_read(client, BQ27421_REG_CONTROL, &chip->status, 0, 0);
-
-	if (ret < 0) {
-		pr_err("%s: err %d\n", __func__, ret);
-		return ret;
-	}
-
-	return 0;
-}
+	ret = bq27421_read_word(client, BQ27421_TEMP);
+	if (ret >= 0)
+		chip->temperature = ret;
 
-static void bq27421_get_value(struct bq27421_chip *chip, int reg)
-{
-	struct i2c_client *client = chip->client;
-	int value;
+	ret = bq27421_read_word(client, BQ27421_VOLT);
+	if (ret >= 0)
+		chip->vcell = ret;
 
-	if (chip->suspended)
-		return;
+	ret = bq27421_read_word(client, BQ27421_SCURRENT);
+	if (ret >= 0)
+		chip->current_now = ret;
 
-	value = bq27421_read_word(client, reg);
-	if (value < 0) {
-		pr_err("%s: error reading values (%d)\n", __func__, value);
-		return;
-	}
+	ret = bq27421_read_word(client, BQ27421_SOC);
+	if (ret >= 0)
+		chip->soc = ret;
 
-	switch(reg) {
-		case BQ27421_REG_TEMP:
-			chip->temperature = value;
-			chip->temperature = (chip->temperature * 10) - 27315;
-			break;
-		case BQ27421_REG_VOLT:
-			chip->vcell = value;
-			break;
-		case BQ27421_REG_RC:
-			chip->remaining_capacity = value;
-			break;
-		case BQ27421_REG_FCC:
-			chip->full_charge_capacity = value;
-			break;
-		case BQ27421_REG_AC:
-			chip->average_current = value;
-			break;
-		case BQ27421_REG_SOC:
-			chip->soc = value;
-			break;
-		case BQ27421_REG_SOH:
-			chip->soh = value;
-			break;
-#ifdef BQ27421_DEBUG
-		case BQ27421_REG_P_DOD:
-			chip->PresentDOD = value;
-			break;
-		case BQ27421_REG_OCV_I:
-			chip->OCVCurrent = value;
-			break;
-		case BQ27421_REG_OCV_V:
-			chip->OCVVoltage = value;
-			break;
-		case BQ27421_REG_REMCAP_UNF:
-			chip->RemainingCapacityUnfiltered = value;
-			break;
-		case BQ27421_REG_FULLCAP_UNF:
-			chip->FullChargeCapacityUnfiltered = value;
-			break;
-		case BQ27421_REG_DOD0:
-			chip->DOD0 = value;
-			break;
-		case BQ27421_REG_PASSEDCHG:
-			chip->PassedCharge = value;
-			break;
-		case BQ27421_REG_QSTART:
-			chip->Qstart = value;
-			break;
-#endif
-		default:
-			return;
-	}
+	/* next update must be at least 1 second later */
+	ktime_get_ts(&chip->next_update_time);
+	monotonic_to_bootbased(&chip->next_update_time);
+	chip->next_update_time.tv_sec++;
 }
 
 static enum power_supply_property bq27421_battery_props[] = {
@@ -268,24 +145,32 @@ static int bq27421_get_property(struct power_supply *psy,
 {
 	struct bq27421_chip *chip = container_of(psy,
 				struct bq27421_chip, battery);
+	struct timespec now;
+
+	if (chip->suspended)
+		return -EAGAIN;
+
+	ktime_get_ts(&now);
+	monotonic_to_bootbased(&now);
+	if (timespec_compare(&now, &chip->next_update_time) >= 0) {
+		mutex_lock(&chip->mutex);
+		bq27421_update(chip);
+		mutex_unlock(&chip->mutex);
+	}
 
 	switch (psp) {
 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
-		bq27421_get_value(chip, BQ27421_REG_VOLT);
-		val->intval = chip->vcell;
-		val->intval *= 1000;
+		val->intval = chip->vcell * 1000;
 		break;
 	case POWER_SUPPLY_PROP_CAPACITY:
-		bq27421_get_value(chip, BQ27421_REG_SOC);
 		val->intval = chip->soc;
 		break;
 	case POWER_SUPPLY_PROP_TEMP:
-		bq27421_get_value(chip, BQ27421_REG_TEMP);
-		val->intval = chip->temperature;
+		/* Convert 0.1 Kelvin unit to 0.1 Celsius */
+		val->intval = chip->temperature - 2731;
 		break;
 	case POWER_SUPPLY_PROP_CURRENT_NOW:
-		bq27421_get_value(chip, BQ27421_REG_AC);
-		val->intval = (s16)chip->average_current;
+		val->intval = (s16)chip->current_now;
 		val->intval *= -1000;
 		break;
 	default:
@@ -295,22 +180,20 @@ static int bq27421_get_property(struct power_supply *psy,
 	return 0;
 }
 
-static irqreturn_t bq27421_interrupt_handler(int irq, void *data)
+static irqreturn_t bq27421_interrupt(int irq, void *data)
 {
 	struct bq27421_chip *chip = data;
 
 	pr_debug("%s : interupt occured\n", __func__);
-
 	power_supply_changed(&chip->battery);
+
 	return IRQ_HANDLED;
 }
 
-static struct bq27421_platform_data *
-bq27421_get_pdata(struct device *dev)
+static struct bq27421_platform_data *bq27421_get_pdata(struct device *dev)
 {
 	struct device_node *np = dev->of_node;
 	struct bq27421_platform_data *pdata;
-	u32 prop;
 
 	if (!np)
 		return dev->platform_data;
@@ -319,216 +202,12 @@ bq27421_get_pdata(struct device *dev)
 	if (!pdata)
 		return NULL;
 
-	pdata->ext_batt_psy = of_property_read_bool(np, "bq27421,ext_batt_psy");
-
-	if (of_property_read_u32(np, "bq27421,full_design", &prop) == 0)
-		pdata->full_design = prop;
+	pdata->ext_batt_psy =
+			of_property_read_bool(np, "bq27421,ext_batt_psy");
 
 	return pdata;
 }
 
-static void bq27421_socint_work(struct work_struct *work)
-{
-	struct bq27421_chip *chip = container_of(work, struct bq27421_chip, socint_work.work);
-	static struct power_supply *batt_psy;
-	union power_supply_propval batt_temp = {0, };
-	int ret;
-	int flags;
-
-	/* Update recently VCELL, SOC and CAPACITY */
-	bq27421_get_value(chip, BQ27421_REG_TEMP);
-	bq27421_get_value(chip, BQ27421_REG_VOLT);
-	bq27421_get_value(chip, BQ27421_REG_RC);
-	bq27421_get_value(chip, BQ27421_REG_FCC);
-	bq27421_get_value(chip, BQ27421_REG_AC);
-	bq27421_get_value(chip, BQ27421_REG_SOC);
-	bq27421_get_value(chip, BQ27421_REG_SOH);
-
-#ifdef BQ27421_DEBUG
-	bq27421_get_value(chip, BQ27421_REG_P_DOD);
-	bq27421_get_value(chip, BQ27421_REG_OCV_I);
-	bq27421_get_value(chip, BQ27421_REG_OCV_V);
-	bq27421_get_value(chip, BQ27421_REG_REMCAP_UNF);
-	bq27421_get_value(chip, BQ27421_REG_FULLCAP_UNF);
-	bq27421_get_value(chip, BQ27421_REG_DOD0);
-	bq27421_get_value(chip, BQ27421_REG_PASSEDCHG);
-	bq27421_get_value(chip, BQ27421_REG_QSTART);
-#endif
-
-	ret = bq27421_read(chip->client, BQ27421_REG_FLAGS, &flags, 0, 0);
-	if (ret < 0)
-		pr_err("%s: error reading flags\n", __func__);
-
-	ret = bq27421_get_status(chip);
-	if (ret < 0)
-		pr_err("%s: error get status register\n", __func__);
-
-#ifdef BQ27421_DEBUG
-	bq27421_dbg("Flags: 0x%04x, Status: 0x%04x T: %d, V: %d, RC: %d, FCC: %d, AC: %d, SOC: %d, SOH: %d\n", flags, chip->status, chip->temperature, chip->vcell,
-		chip->remaining_capacity, chip->full_charge_capacity, (s16)chip->average_current, chip->soc, chip->soh);
-
-	bq27421_dbg("PDOD: %d, OCVC: %d, OCVV:%d, RCU: %d, FCCU: %d, DOD0: %d, PassedCharge: %d, QS: %d\n",
-		chip->PresentDOD, (s16)chip->OCVCurrent, chip->OCVVoltage, chip->RemainingCapacityUnfiltered, chip->FullChargeCapacityUnfiltered, chip->DOD0, (s16)chip->PassedCharge, chip->Qstart);
-#endif
-
-	if (chip->soc != chip->last_soc &&
-		chip->vcell != chip->last_vcell) {
-		chip->last_vcell = chip->vcell;
-		chip->last_soc = chip->soc;
-
-		if (!batt_psy)
-			batt_psy = power_supply_get_by_name("battery");
-
-		if (batt_psy) {
-			batt_psy->get_property(batt_psy,
-				  POWER_SUPPLY_PROP_TEMP, &batt_temp);
-		}
-
-		power_supply_changed(&chip->battery);
-		pr_info("%s: battery l=%d v=%d t=%d.%d c=%d\n", __func__, chip->soc, chip->vcell, batt_temp.intval / 10, batt_temp.intval % 10, (s16)chip->average_current * -1);
-	}
-
-	schedule_delayed_work(&chip->socint_work, msecs_to_jiffies(SOC_WORK_PERIOD));
-
-	return;
-}
-
-#ifdef BQ27421_DEBUG
-static int bq27421_ext_cmd(struct i2c_client *client, u8 extcmd, u8 data)
-{
-	struct i2c_msg msg;
-	u8 i2c_data[2];
-	int ret;
-
-	if (!client)
-		return -ENODEV;
-
-	memset(i2c_data, 0, sizeof(i2c_data));
-	i2c_data[0] = extcmd;
-	i2c_data[1] = data;
-
-	msg.addr = client->addr;
-
-	msg.flags = 0;
-	msg.len = 2;
-	msg.buf = i2c_data;
-
-	ret = i2c_transfer(client->adapter, &msg, 1);
-	if (ret < 0)
-		pr_err("%s: i2c_transfer fails.\n", __func__);
-
-	return ret;
-}
-
-static bool bq27421_is_device_unsealed(struct i2c_client *client)
-{
-	struct bq27421_chip *chip = i2c_get_clientdata(client);
-	int ret;
-	bool is_unsealed = false;
-
-	ret = bq27421_get_status(chip);
-	if (ret < 0)
-		pr_err("%s: error get status register\n", __func__);
-
-	if ((chip->status & 0x2000) == 0)
-		is_unsealed = true;
-
-	return is_unsealed;
-}
-
-static bool bq27421_make_device_unsealed(struct i2c_client *client)
-{
-	bool is_unsealed;
-
-	bq27421_cntl_cmd(client, UNSEAL_KEY0);
-	bq27421_cntl_cmd(client, UNSEAL_KEY1);
-	mdelay(100);
-
-	is_unsealed = bq27421_is_device_unsealed(client);
-
-	return is_unsealed;
-}
-
-static bool bq27421_make_device_sealed(struct i2c_client *client)
-{
-	bool is_sealed;
-
-	bq27421_cntl_cmd(client, BQ27421_SUBCMD_SEALED);
-	mdelay(100);
-
-	is_sealed = !bq27421_is_device_unsealed(client);
-
-	return is_sealed;
-}
-
-static int bq27421_blockdata_read(struct i2c_client *client, char *read_buf, int count)
-{
-	struct bq27421_chip *chip = i2c_get_clientdata(client);
-	struct i2c_msg msg[1];
-	int err;
-	int i;
-
-	if (!client->adapter)
-		return -ENODEV;
-
-	mutex_lock(&chip->mutex);
-
-	msg->addr = client->addr;
-	msg->flags = I2C_M_RD;
-	msg->len = count;
-	msg->buf = read_buf;
-
-	read_buf[0] = BQ27421_EXTCMD_BLOCKDATA;
-
-	err = i2c_transfer(client->adapter, msg, 1);
-	if (err < 0)
-		pr_err("%s: i2c_transfer fails. err = %d\n", __func__, err);
-	else
-		for (i = 0; i < count; i++)
-			bq27421_dbg("%02d, 0x%02x\n", i, read_buf[i]);
-
-	mutex_unlock(&chip->mutex);
-	return err;
-}
-
-static void bq27421_check_blockdata(struct i2c_client *client)
-{
-	u8 DataRAM_RB[32] = {0, };
-
-	if (bq27421_make_device_unsealed(client) == false) {
-		pr_err("%s: unseal fails\n", __func__);
-		return;
-	}
-
-	bq27421_ext_cmd(client, BQ27421_EXTCMD_BLOCKDATACONTROL, 0x00);
-
-	bq27421_dbg("reading SubClass 64...\n");
-	bq27421_ext_cmd(client, BQ27421_EXTCMD_DATACLASS, 64);
-	bq27421_ext_cmd(client, BQ27421_EXTCMD_DATABLOCK, 0);
-	bq27421_blockdata_read(client, DataRAM_RB, 32);
-
-	bq27421_dbg("reading SubClass 82...\n");
-	bq27421_ext_cmd(client, BQ27421_EXTCMD_DATACLASS, 82);
-	bq27421_ext_cmd(client, BQ27421_EXTCMD_DATABLOCK, 0);
-	bq27421_blockdata_read(client, DataRAM_RB, 32);
-
-	bq27421_dbg("reading SubClass 82-1...\n");
-	bq27421_ext_cmd(client, BQ27421_EXTCMD_DATACLASS, 82);
-	bq27421_ext_cmd(client, BQ27421_EXTCMD_DATABLOCK, 1);
-	bq27421_blockdata_read(client, DataRAM_RB, 32);
-
-	bq27421_dbg("reading SubClass 89...\n");
-	bq27421_ext_cmd(client, BQ27421_EXTCMD_DATACLASS, 89);
-	bq27421_ext_cmd(client, BQ27421_EXTCMD_DATABLOCK, 0);
-	bq27421_blockdata_read(client, DataRAM_RB, 32);
-
-	if (bq27421_make_device_sealed(client) == false) {
-		pr_err("%s: seal fails\n", __func__);
-		return;
-	}
-}
-#endif
-
 static int bq27421_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
@@ -536,9 +215,9 @@ static int bq27421_probe(struct i2c_client *client,
 	struct bq27421_chip *chip;
 	int ret;
 
-	pr_info("%s: START\n", __func__);
-
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
+						I2C_FUNC_SMBUS_BYTE_DATA |
+						I2C_FUNC_SMBUS_I2C_BLOCK))
 		return -EIO;
 
 	chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
@@ -556,10 +235,6 @@ static int bq27421_probe(struct i2c_client *client,
 	mutex_init(&chip->mutex);
 	i2c_set_clientdata(client, chip);
 
-#ifdef BQ27421_DEBUG
-	bq27421_check_blockdata(chip->client);
-#endif
-
 	/*
 	 * If ext_batt_psy is true, then an external device publishes
 	 * a POWER_SUPPLY_TYPE_BATTERY, so this driver will publish its
@@ -577,28 +252,17 @@ static int bq27421_probe(struct i2c_client *client,
 	chip->battery.properties = bq27421_battery_props;
 	chip->battery.num_properties = ARRAY_SIZE(bq27421_battery_props);
 
-	/* check if BQ27421 Initialization is completed */
-	ret = bq27421_get_status(chip);
-	if (ret < 0) {
-		pr_err("%s: bq27421_get_status fails\n", __func__);
-		return -EIO;
-	}
-
-	if ((chip->status & 0x0080) == 0) {
-		pr_err("%s: init not completed yet\n", __func__);
-		return -EIO;
-	}
+	if (bq27421_is_unsealed(chip))
+		bq27421_ctrl_sealed(chip);
 
 	if (client->irq) {
 		ret = request_threaded_irq(client->irq, NULL,
-					bq27421_interrupt_handler,
+					bq27421_interrupt,
 					IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
 					chip->battery.name, chip);
 		if (ret) {
 			pr_err("%s: cannot enable irq\n", __func__);
 			return ret;
-		} else {
-			enable_irq_wake(client->irq);
 		}
 	}
 
@@ -607,11 +271,6 @@ static int bq27421_probe(struct i2c_client *client,
 	else
 		chip->power_supply_registered = true;
 
-	INIT_DELAYED_WORK(&chip->socint_work, bq27421_socint_work);
-	schedule_delayed_work(&chip->socint_work, msecs_to_jiffies(SOC_WORK_PERIOD));
-
-	pr_info("%s: DONE\n", __func__);
-
 	return ret;
 }
 
@@ -619,8 +278,6 @@ static int bq27421_remove(struct i2c_client *client)
 {
 	struct bq27421_chip *chip = i2c_get_clientdata(client);
 
-	cancel_delayed_work(&chip->socint_work);
-
 	if (client->irq)
 		disable_irq_wake(client->irq);
 
@@ -638,13 +295,14 @@ static int bq27421_pm_prepare(struct device *dev)
 	struct i2c_client *client = to_i2c_client(dev);
 	struct bq27421_chip *chip = i2c_get_clientdata(client);
 
-	cancel_delayed_work(&chip->socint_work);
-
 	chip->suspended = true;
 
 	if (chip->client->irq) {
 		disable_irq(chip->client->irq);
-		enable_irq_wake(chip->client->irq);
+		if (chip->soc < SOC_LOW_THRESHOLD) {
+			enable_irq_wake(chip->client->irq);
+			chip->irq_wake_enabled = true;
+		}
 	}
 
 	return 0;
@@ -658,11 +316,12 @@ static void bq27421_pm_complete(struct device *dev)
 	chip->suspended = false;
 
 	if (chip->client->irq) {
-		disable_irq_wake(chip->client->irq);
+		if (chip->irq_wake_enabled) {
+			disable_irq_wake(chip->client->irq);
+			chip->irq_wake_enabled = false;
+		}
 		enable_irq(chip->client->irq);
 	}
-
-	schedule_delayed_work(&chip->socint_work, msecs_to_jiffies(200));
 }
 
 static const struct dev_pm_ops bq27421_pm_ops = {
@@ -689,9 +348,9 @@ static struct i2c_driver bq27421_i2c_driver = {
 		.of_match_table = bq27421_match_table,
 		.pm = &bq27421_pm_ops,
 	},
-	.probe		= bq27421_probe,
-	.remove		= bq27421_remove,
-	.id_table	= bq27421_id,
+	.probe  = bq27421_probe,
+	.remove  = bq27421_remove,
+	.id_table  = bq27421_id,
 };
 
 module_i2c_driver(bq27421_i2c_driver);
diff --git a/include/linux/power/bq27421_battery.h b/include/linux/power/bq27421_battery.h
index 3c2d28163c774d3dcace7544cf8de29ac6277499..e74b6c3ea907d81880172476d43a84d2b5356b11 100644
--- a/include/linux/power/bq27421_battery.h
+++ b/include/linux/power/bq27421_battery.h
@@ -1,60 +1,74 @@
 /*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
+* Fuel gauge driver for TI BQ27421
+*
+* Copyright(c) 2014, LGE Inc. All rights reserved.
+* ChoongRyeol Lee <choongryeol.lee@lge.com>
+*
+* This software is licensed under the terms of the GNU General Public
+* License version 2, as published by the Free Software Foundation, and
+* may be copied, distributed, and modified under those terms.
+*
+* 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.
+*
+*/
 
-#ifndef __BQ27421_BATTERY_H_
-#define __BQ27421_BATTERY_H_
+#ifndef __BQ27421_BATTERY_H__
+#define __BQ27421_BATTERY_H__
 
-/* #define BQ27421_DEBUG */
 #define UNSEAL_KEY0 0x8000
 #define UNSEAL_KEY1 0x8000
-#define SOC_WORK_PERIOD 10000
+
+struct bq27421_dataram {
+	u8	data_class;
+	u8	data_block;
+	u8	data[2][1+16];
+	u8	checksum;
+};
 
 struct bq27421_platform_data {
 	bool ext_batt_psy;
-	int full_design;
 };
 
-/* BQ27541 standard data commands */
-#define BQ27421_REG_CONTROL		0x00
-#define BQ27421_REG_TEMP		0x02 /* TEMPERATURE */
-#define BQ27421_REG_VOLT		0x04 /* VOLTAGE */
-#define BQ27421_REG_FLAGS		0x06
-#define BQ27421_REG_RC			0x0C /* REMAINING CAPACITY */
-#define BQ27421_REG_FCC			0x0E /* FULL CHARGE CAPACITY */
-#define BQ27421_REG_AC			0x10 /* AVERAGE CURRENT */
-#define BQ27421_REG_SOC			0x1C /* STATE OF CHARGE */
-#define BQ27421_REG_SOH			0x20 /* STATE OF HEALTH */
-#ifdef BQ27421_DEBUG
-#define BQ27421_REG_P_DOD		0x1A /* Debug4() = PresentDOD() */
-#define BQ27421_REG_OCV_I		0X22 /* OCVCurrent() */
-#define BQ27421_REG_OCV_V		0x24 /* OCVVoltage() */
-#define BQ27421_REG_REMCAP_UNF		0x28 /* RemainingCapacityUnfiltered() */
-#define BQ27421_REG_FULLCAP_UNF		0x2C /* FullChargeCapacityUnfiltered() */
-#define BQ27421_REG_DOD0		0x66 /* DOD0() */
-#define BQ27421_REG_PASSEDCHG		0x6C /* PassedCharge */
-#define BQ27421_REG_QSTART		0x6E /* Qstart() */
-#endif
+/* Standard data commands */
+#define BQ27421_CONTROL	0x00
+#define BQ27421_TEMP		0x02 /* TEMPERATURE */
+#define BQ27421_VOLT		0x04 /* VOLTAGE */
+#define BQ27421_FLAGS		0x06
+#define BQ27421_RC		0x0C /* REMAINING CAPACITY */
+#define BQ27421_FCC		0x0E /* FULL CHARGE CAPACITY */
+#define BQ27421_AC		0x10 /* AVERAGE CURRENT */
+#define BQ27421_SOC		0x1C /* STATE OF CHARGE */
+#define BQ27421_SOH		0x20 /* STATE OF HEALTH */
+#define BQ27421_P_DOD		0x1A /* Debug4() = PresentDOD() */
+#define BQ27421_OCV_I		0X22 /* OCVCurrent() */
+#define BQ27421_OCV_V		0x24 /* OCVVoltage() */
+#define BQ27421_SCURRENT	0x26 /* Simultaneous Current */
+#define BQ27421_REMCAP_UNF	0x28 /* RemainingCapacityUnfiltered() */
+#define BQ27421_FULLCAP_UNF	0x2C /* FullChargeCapacityUnfiltered() */
+#define BQ27421_DOD0		0x66 /* DOD0() */
+#define BQ27421_PASSEDCHG	0x6C /* PassedCharge */
+#define BQ27421_QSTART		0x6E /* Qstart() */
 
 /* Control subcommands */
-#define BQ27421_SUBCMD_CTNL_STATUS		0x0000 /* OK */
-#define BQ27421_SUBCMD_BOARD_CAL		0x0009
-#define BQ27421_SUBCMD_SET_CFGUPDATE		0x0013
-#define BQ27421_SUBCMD_SEALED			0x0020
-#define BQ27421_SUBCMD_SOFT_RESET		0x0042
-#define BQ27421_SUBCMD_EXIT_CFGUPDATE		0x0043
-
-/* BQ27421 Extended Data Commands */
-#define BQ27421_EXTCMD_DESIGNCAPACITY		0x3C /* DesignCapacity() 0x3C ~ 0x3D */
-#define BQ27421_EXTCMD_DATACLASS		0x3E /* DataClass() */
-#define BQ27421_EXTCMD_DATABLOCK		0x3F /* DataBlock() */
-#define BQ27421_EXTCMD_BLOCKDATA		0x40 /* BlockData() 0x40 ~ 0x5F */
-#define BQ27421_EXTCMD_BLOCKDATACHECKSUM	0x60 /* BlockDataCheckSum() */
-#define BQ27421_EXTCMD_BLOCKDATACONTROL		0x61 /* BlockDataControl() */
-
-/* BQ27421 DataFlash Subclass ID */
-#define BQ27421_SUBCLASS_REGISTERS		0x40
-#define BQ27421_SUBCLASS_STATE			0x52
+#define BQ27421_SCMD_CTRL_STAT		0x0000
+#define BQ27421_SCMD_BOARD_CAL		0x0009
+#define BQ27421_SCMD_CFGUPDATE		0x0013
+#define BQ27421_SCMD_SEALED		0x0020
+#define BQ27421_SCMD_SOFT_RESET	0x0042
+#define BQ27421_SCMD_EXIT_CFGUPDATE	0x0043
+
+/* Extended data commands */
+#define BQ27421_ECMD_DESIGNCAP		0x3C /* DesignCapacity() 0x3C ~ 0x3D */
+#define BQ27421_ECMD_DATACLASS		0x3E /* DataClass() */
+#define BQ27421_ECMD_DATABLK		0x3F /* DataBlock() */
+#define BQ27421_ECMD_BLKDATA		0x40 /* BlockData() 0x40 ~ 0x5F */
+#define BQ27421_ECMD_BLKCHECKSUM	0x60 /* BlockDataCheckSum() */
+#define BQ27421_ECMD_BLKCTRL		0x61 /* BlockDataControl() */
+
+/* Data flash subclass ID */
+#define SUBCLASS_REGISTERS		0x40
+#define SUBCLASS_STATE			0x52
 #endif