diff options
author | Venkat Reddy Talla <vreddytalla@nvidia.com> | 2014-03-19 17:10:52 +0530 |
---|---|---|
committer | Laxman Dewangan <ldewangan@nvidia.com> | 2014-03-21 07:10:35 -0700 |
commit | 40ad39bb1e3bd8c62e4ee3a506650c1aa5a354b8 (patch) | |
tree | d3f1768f5f58b4a3dcb3326766c14f9156d94ed5 | |
parent | a0dbe14a94f159e9c2e49c5116008ad7f55f97a6 (diff) |
power: lc709203f:implement interrupt feature
implement interrupt support to generate low voltage/soc
events when battery voltage measured below threshold value.
update binding doc with lc709203f parameters.
Bug 1474634
Change-Id: I89f3b009548132d1e00bc28fb202e1f6babdfab1
Signed-off-by: Venkat Reddy Talla <vreddytalla@nvidia.com>
Reviewed-on: http://git-master/r/383844
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
Tested-by: Laxman Dewangan <ldewangan@nvidia.com>
-rw-r--r-- | Documentation/devicetree/bindings/power_supply/lc709203f_battery.txt | 4 | ||||
-rw-r--r-- | drivers/power/lc709203f_battery.c | 67 |
2 files changed, 71 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/power_supply/lc709203f_battery.txt b/Documentation/devicetree/bindings/power_supply/lc709203f_battery.txt index 0a2d75200a90..cab288316776 100644 --- a/Documentation/devicetree/bindings/power_supply/lc709203f_battery.txt +++ b/Documentation/devicetree/bindings/power_supply/lc709203f_battery.txt @@ -17,6 +17,8 @@ Optional properties: Kernel read maximum SoC from device for given battery. Kernel translate the SoC to 100% before reporting to framework if it reads equal/more than this value. + - onsemi,alert-low-rsoc : Alarm low RSOC programed to generate event + - onsemi,alert-low-voltage : Alarm low Voltage programed to generate event Note: The device has capabilty to read battery temp through thermistor. This also calulate SoC based on temperature of battery. If thermistor @@ -41,4 +43,6 @@ Example: onsemi,initial-rsoc = 0xAA55; onsemi,kernel-threshold-soc = <5>; onsemi,kernel-maximum-soc = <99>; + onsemi,alert-low-rsoc = <0x0>; + onsemi,alert-low-voltage = <0x0>; }; diff --git a/drivers/power/lc709203f_battery.c b/drivers/power/lc709203f_battery.c index b13e730b319d..75c946a4e14d 100644 --- a/drivers/power/lc709203f_battery.c +++ b/drivers/power/lc709203f_battery.c @@ -27,6 +27,7 @@ #include <linux/power/battery-charger-gauge-comm.h> #include <linux/pm.h> #include <linux/jiffies.h> +#include <linux/interrupt.h> #define LC709203F_THERMISTOR_B 0x06 #define LC709203F_INITIAL_RSOC 0x07 @@ -60,6 +61,8 @@ struct lc709203f_platform_data { u32 therm_adjustment; u32 threshold_soc; u32 maximum_soc; + u32 alert_low_rsoc; + u32 alert_low_voltage; }; struct lc709203f_chip { @@ -293,6 +296,23 @@ static struct battery_gauge_info lc709203f_bgi = { .bg_ops = &lc709203f_bg_ops, }; +static irqreturn_t lc709203f_irq(int id, void *dev) +{ + struct lc709203f_chip *chip = dev; + struct i2c_client *client = chip->client; + + dev_info(&client->dev, "%s(): STATUS_VL\n", __func__); + /* Forced set SOC 0 to power off */ + chip->soc = 0; + chip->lasttime_soc = chip->soc; + chip->status = chip->lasttime_status; + chip->health = POWER_SUPPLY_HEALTH_DEAD; + chip->capacity_level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL; + power_supply_changed(&chip->battery); + + return IRQ_HANDLED; +} + static void of_lc709203f_parse_platform_data(struct i2c_client *client, struct lc709203f_platform_data *pdata) { @@ -340,6 +360,14 @@ static void of_lc709203f_parse_platform_data(struct i2c_client *client, pdata->maximum_soc = pval; else pdata->maximum_soc = 100; + + ret = of_property_read_u32(np, "onsemi,alert-low-rsoc", &pval); + if (!ret) + pdata->alert_low_rsoc = pval; + + ret = of_property_read_u32(np, "onsemi,alert-low-voltage", &pval); + if (!ret) + pdata->alert_low_voltage = pval; } #ifdef CONFIG_DEBUG_FS @@ -446,6 +474,20 @@ static int lc709203f_probe(struct i2c_client *client, dev_info(&client->dev, "initial-rsoc: 0x%04x\n", chip->pdata->initial_rsoc); + ret = lc709203f_write_word(chip->client, + LC709203F_ALARM_LOW_CELL_RSOC, chip->pdata->alert_low_rsoc); + if (ret < 0) { + dev_err(&client->dev, "LOW_RSOC write failed: %d\n", ret); + return ret; + } + + ret = lc709203f_write_word(chip->client, + LC709203F_ALARM_LOW_CELL_VOLT, chip->pdata->alert_low_voltage); + if (ret < 0) { + dev_err(&client->dev, "LOW_VOLT write failed: %d\n", ret); + return ret; + } + if (chip->pdata->appli_adjustment) { ret = lc709203f_write_word(chip->client, LC709203F_ADJUSTMENT_PACK_APPLI, @@ -515,7 +557,24 @@ skip_thermistor_config: lc709203f_debugfs_init(client); + if (client->irq) { + ret = devm_request_threaded_irq(&client->dev, client->irq, + NULL, lc709203f_irq, + IRQF_ONESHOT | IRQF_TRIGGER_FALLING, + dev_name(&client->dev), chip); + if (ret < 0) { + dev_err(&client->dev, + "%s: request IRQ %d fail, err = %d\n", + __func__, client->irq, ret); + client->irq = 0; + goto irq_reg_error; + } + } + device_set_wakeup_capable(&client->dev, 1); + return 0; +irq_reg_error: + cancel_delayed_work_sync(&chip->work); bg_err: power_supply_unregister(&chip->battery); error: @@ -552,12 +611,20 @@ static int lc709203f_suspend(struct device *dev) { struct lc709203f_chip *chip = dev_get_drvdata(dev); cancel_delayed_work_sync(&chip->work); + + if (device_may_wakeup(&chip->client->dev)) + enable_irq_wake(chip->client->irq); + return 0; } static int lc709203f_resume(struct device *dev) { struct lc709203f_chip *chip = dev_get_drvdata(dev); + + if (device_may_wakeup(&chip->client->dev)) + disable_irq_wake(chip->client->irq); + schedule_delayed_work(&chip->work, LC709203F_DELAY); return 0; } |