From 52f728b7ca02bdd3854821e432030e3fccc1768e Mon Sep 17 00:00:00 2001 From: Ramakrishna Pallala Date: Mon, 19 Dec 2011 13:48:39 +0530 Subject: [PATCH] [PORT FROM R2]max17042: block maxim registers reads during reboot BZ: 15870 This patch blocks the maxim register reads during reboot, as the chip cannot be recovered if the i2c transaction is broken. Change-Id: I2dceba9ba9d863e3b6cf36b46f821ec4d26cf5a7 R2-Change-Id: I889135b8e76717d1fcbb742eca2e9ecccc9ac086 Signed-off-by: Ramakrishna Pallala Reviewed-on: http://android.intel.com:8080/32753 Reviewed-by: Mendi, EduardoX Tested-by: Mendi, EduardoX Reviewed-by: buildbot Tested-by: buildbot --- drivers/power/max17042_battery.c | 67 ++++++++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 16 deletions(-) diff --git a/drivers/power/max17042_battery.c b/drivers/power/max17042_battery.c index 1442bf3..6703f7c 100644 --- a/drivers/power/max17042_battery.c +++ b/drivers/power/max17042_battery.c @@ -250,6 +250,8 @@ struct max17042_chip { int technology; int charge_full_des; struct delayed_work init_worker; + + bool plat_rebooting; }; #ifdef CONFIG_DEBUG_FS @@ -291,6 +293,16 @@ static enum power_supply_property max17042_battery_props[] = { static int max17042_write_reg(struct i2c_client *client, u8 reg, u16 value) { int ret, i; + struct max17042_chip *chip = i2c_get_clientdata(client); + + /* if the shutdown or reboot sequence started + * then block the access to maxim registers as chip + * cannot be recovered from broken i2c transactions + */ + if (chip->plat_rebooting) { + dev_warn(&client->dev, "rebooting is in progress\n"); + return -EINVAL; + } for (i = 0; i < NR_RETRY_CNT; i++) { ret = i2c_smbus_write_word_data(client, reg, value); @@ -309,6 +321,16 @@ static int max17042_write_reg(struct i2c_client *client, u8 reg, u16 value) static int max17042_read_reg(struct i2c_client *client, u8 reg) { int ret, i; + struct max17042_chip *chip = i2c_get_clientdata(client); + + /* if the shutdown or reboot sequence started + * then block the access to maxim registers as chip + * cannot be recovered from broken i2c transactions + */ + if (chip->plat_rebooting) { + dev_warn(&client->dev, "rebooting is in progress\n"); + return -EINVAL; + } for (i = 0; i < NR_RETRY_CNT; i++) { ret = i2c_smbus_read_word_data(client, reg); @@ -338,8 +360,12 @@ static int max17042_write_verify_reg(struct i2c_client *client, for (i = 0; i < NR_RETRY_CNT; i++) { /* Write the value to register */ ret = max17042_write_reg(client, reg, value); + if (ret < 0) + continue; /* Read the value from register */ ret = max17042_read_reg(client, reg); + if (ret < 0) + continue; /* compare the both the values */ if (value != ret) dev_err(&client->dev, @@ -354,17 +380,18 @@ static int max17042_write_verify_reg(struct i2c_client *client, static int max17042_reg_read_modify(struct i2c_client *client, u8 reg, u16 val, int bit_set) { - u16 data; int ret; - data = max17042_read_reg(client, reg); + ret = max17042_read_reg(client, reg); + if (ret < 0) + return ret; if (bit_set) - data |= val; + ret |= val; else - data &= (~val); + ret &= (~val); - ret = max17042_write_reg(client, reg, data); + ret = max17042_write_reg(client, reg, ret); return ret; } @@ -956,17 +983,6 @@ static void restore_runtime_params(struct max17042_chip *chip) fg_conf_data->cycles); } -static int max17042_reboot_callback(struct notifier_block *nfb, - unsigned long event, void *data) -{ - struct max17042_chip *chip = i2c_get_clientdata(max17042_client); - - if (chip->pdata->enable_current_sense) - save_runtime_params(chip); - - return NOTIFY_OK; -} - static int init_max17042_chip(struct max17042_chip *chip) { int ret = 0, val; @@ -1548,6 +1564,25 @@ static struct i2c_driver max17042_i2c_driver = { .id_table = max17042_id, }; +static int max17042_reboot_callback(struct notifier_block *nfb, + unsigned long event, void *data) +{ + struct max17042_chip *chip = i2c_get_clientdata(max17042_client); + + if (chip->pdata->enable_current_sense) + save_runtime_params(chip); + + /* if the shutdown or reboot sequence started + * then block the access to maxim registers as chip + * cannot be recovered from broken i2c transactions + */ + mutex_lock(&chip->batt_lock); + chip->plat_rebooting = true; + mutex_unlock(&chip->batt_lock); + + return NOTIFY_OK; +} + static int __init max17042_init(void) { return i2c_add_driver(&max17042_i2c_driver); -- 2.7.4