]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
power: bq2419x:adjust input voltage limit based on battery SOC
authorVenkat Reddy Talla <vreddytalla@nvidia.com>
Fri, 30 May 2014 06:48:47 +0000 (12:18 +0530)
committerEmad Mir <emir@nvidia.com>
Fri, 13 Jun 2014 17:10:52 +0000 (10:10 -0700)
configure input voltage limit based on battery SOC,
get the battery soc from fuel gauge and adjust input voltage
as the battery soc rises when usb/NV charger cable connected.

Bug 1516392

Change-Id: I14e44852760f046884fd066ffcdfff86b36871c1
Signed-off-by: Venkat Reddy Talla <vreddytalla@nvidia.com>
Reviewed-on: http://git-master/r/416958
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
drivers/power/battery-charger-gauge-comm.c
drivers/power/bq2419x-charger.c
include/linux/power/battery-charger-gauge-comm.h
include/linux/power/bq2419x-charger.h

index 764fde8f2a36e640465c9015a61823fc825158f0..3603f2a55498656b5cd098f7a79b84f381e92dc0 100644 (file)
@@ -349,6 +349,33 @@ int battery_gauge_record_snapshot_values(struct battery_gauge_dev *bg_dev,
 }
 EXPORT_SYMBOL_GPL(battery_gauge_record_snapshot_values);
 
+int battery_gauge_report_battery_soc(struct battery_gauge_dev *bg_dev,
+                                       int battery_soc)
+{
+       struct battery_charger_dev *node;
+       int ret = 0;
+
+       if (!bg_dev)
+               return -EINVAL;
+
+       if (battery_soc < 90 || battery_soc > 100)
+               return -EINVAL;
+
+       mutex_lock(&charger_gauge_list_mutex);
+
+       list_for_each_entry(node, &charger_list, list) {
+               if (node->cell_id != bg_dev->cell_id)
+                       continue;
+               if (node->ops && node->ops->input_voltage_configure)
+                       ret = node->ops->input_voltage_configure(node,
+                               battery_soc);
+       }
+
+       mutex_unlock(&charger_gauge_list_mutex);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(battery_gauge_report_battery_soc);
+
 int battery_gauge_get_scaled_soc(struct battery_gauge_dev *bg_dev,
        int actual_soc_semi, int thresod_soc)
 {
index 7496699c86433372a2cabd43fdb73cac3e5d396b..dee44055136f6f07f7c11190f9ea392026ca80a8 100644 (file)
@@ -420,6 +420,14 @@ static int bq2419x_configure_charging_current(struct bq2419x_chip *bq2419x,
                }
        }
 
+       /* Configure input voltage limit*/
+       ret = regmap_update_bits(bq2419x->regmap, BQ2419X_INPUT_SRC_REG,
+                       bq2419x->input_src.mask, bq2419x->input_src.val);
+       if (ret < 0) {
+               dev_err(bq2419x->dev, "INPUT_SRC_REG update failed %d\n", ret);
+               return ret;
+       }
+
        /* Configure input current limit in steps */
        val = current_to_reg(iinlim, ARRAY_SIZE(iinlim), in_current_limit);
        floor = current_to_reg(iinlim, ARRAY_SIZE(iinlim), 500);
@@ -1368,11 +1376,51 @@ static int bq2419x_charging_restart(struct battery_charger_dev *bc_dev)
        return ret;
 }
 
+static int bq2419x_charger_input_voltage_configure(
+               struct battery_charger_dev *bc_dev, int battery_soc)
+{
+       struct bq2419x_chip *bq2419x = battery_charger_get_drvdata(bc_dev);
+       struct bq2419x_charger_platform_data *chg_pdata;
+       u32 input_voltage_limit = 0;
+       int ret;
+       int i;
+       int vreg;
+
+       chg_pdata = bq2419x->charger_pdata;
+       if (!bq2419x->cable_connected || !chg_pdata->n_soc_profile)
+               return 0;
+
+       for (i = 0; i < chg_pdata->n_soc_profile; ++i) {
+               if (battery_soc <= chg_pdata->soc_range[i]) {
+                       if (chg_pdata->input_voltage_soc_limit)
+                               input_voltage_limit =
+                                       chg_pdata->input_voltage_soc_limit[i];
+                       break;
+               }
+       }
+
+       if (!input_voltage_limit)
+               return 0;
+
+       /*Configure input voltage limit */
+       vreg = bq2419x_val_to_reg(input_voltage_limit,
+                       BQ2419X_INPUT_VINDPM_OFFSET, 80, 4, 0);
+       ret = regmap_update_bits(bq2419x->regmap, BQ2419X_INPUT_SRC_REG,
+                               BQ2419X_INPUT_VINDPM_MASK,
+                               (vreg << 3));
+       if (ret < 0) {
+               dev_err(bq2419x->dev, "INPUT_VOLTAGE update failed %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
 
 static struct battery_charging_ops bq2419x_charger_bci_ops = {
        .get_charging_status = bq2419x_charger_get_status,
        .restart_charging = bq2419x_charging_restart,
        .thermal_configure = bq2419x_charger_thermal_configure,
+       .input_voltage_configure = bq2419x_charger_input_voltage_configure,
 };
 
 static struct battery_charger_info bq2419x_charger_bci = {
@@ -1400,6 +1448,7 @@ static struct bq2419x_platform_data *bq2419x_dt_parse(struct i2c_client *client)
                int chg_restart_time;
                int auto_recharge_time_power_off;
                int temp_polling_time;
+               int soc_range_len, inut_volt_lim_len = 0;
                struct regulator_init_data *batt_init_data;
                struct bq2419x_charger_platform_data *chg_pdata;
                const char *status_str;
@@ -1512,6 +1561,43 @@ static struct bq2419x_platform_data *bq2419x_dt_parse(struct i2c_client *client)
                        bcharger_pdata->temp_polling_time_sec =
                                                temp_polling_time;
 
+               count = of_property_count_u32(batt_reg_node, "ti,soc-range");
+               soc_range_len = (count > 0) ? count : 0;
+
+               if (soc_range_len) {
+                       chg_pdata->n_soc_profile = soc_range_len;
+                       chg_pdata->soc_range = devm_kzalloc(&client->dev,
+                               sizeof(u32) * soc_range_len, GFP_KERNEL);
+                       if (!chg_pdata->soc_range)
+                               return ERR_PTR(-ENOMEM);
+
+                       ret = of_property_read_u32_array(batt_reg_node,
+                                       "ti,soc-range",
+                                       chg_pdata->soc_range, soc_range_len);
+                       if (ret < 0)
+                               return ERR_PTR(ret);
+
+                       count =  of_property_count_u32(batt_reg_node,
+                                       "ti,input-voltage-soc-limit");
+                       inut_volt_lim_len = (count > 0) ? count : 0;
+               }
+
+               if (inut_volt_lim_len) {
+                       chg_pdata->input_voltage_soc_limit =
+                                       devm_kzalloc(&client->dev,
+                                       sizeof(u32) * inut_volt_lim_len,
+                                       GFP_KERNEL);
+                       if (!chg_pdata->input_voltage_soc_limit)
+                               return ERR_PTR(-ENOMEM);
+
+                       ret = of_property_read_u32_array(batt_reg_node,
+                                       "ti,input-voltage-soc-limit",
+                                       chg_pdata->input_voltage_soc_limit,
+                                       inut_volt_lim_len);
+                       if (ret < 0)
+                               return ERR_PTR(ret);
+               }
+
                chg_pdata->tz_name = of_get_property(batt_reg_node,
                                                "ti,thermal-zone", NULL);
 
index f04ef645e57ff965de10fc0507f39d2a3b48a48f..cf0df7c4c2c843c2d1db62f2e976c3405389566e 100644 (file)
@@ -48,6 +48,8 @@ struct battery_charging_ops {
        int (*thermal_configure)(struct battery_charger_dev *bct_dev,
                int temp, bool enable_charger, bool enable_charg_half_current,
                int battery_voltage);
+       int (*input_voltage_configure)(struct battery_charger_dev *bc_dev,
+               int soc);
 };
 
 struct battery_charger_info {
@@ -108,5 +110,7 @@ int battery_gauge_get_scaled_soc(struct battery_gauge_dev *bg_dev,
                int actual_soc_semi, int thresod_soc);
 int battery_gauge_get_adjusted_soc(struct battery_gauge_dev *bg_dev,
                int min_soc, int max_soc, int actual_soc_semi);
+int battery_gauge_report_battery_soc(struct battery_gauge_dev *bg_dev,
+               int battery_soc);
 
 #endif /* _LINUX_POWER_BATTERY_CHARGER_GAUGE_COMM_H */
index ec74adcd2b87b94dd16f320e28fa85c264bbba7e..67d3531fc49600ad6b7589c0ecd4cebc53a69a07 100644 (file)
@@ -152,8 +152,11 @@ struct bq2419x_charger_platform_data {
        u32 *temp_range;
        u32 *chg_current_limit;
        u32 *chg_thermal_voltage_limit;
+       u32 *soc_range;
+       u32 *input_voltage_soc_limit;
        u32 auto_recharge_time_supend;
        int chg_status_gpio;
+       int n_soc_profile;
 };
 
 /*