summaryrefslogtreecommitdiff
path: root/drivers/power
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/power')
-rw-r--r--drivers/power/supply/power_supply_core.c67
1 files changed, 66 insertions, 1 deletions
diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c
index 3d5047d3fe99..fb0b3870566e 100644
--- a/drivers/power/supply/power_supply_core.c
+++ b/drivers/power/supply/power_supply_core.c
@@ -814,7 +814,7 @@ EXPORT_SYMBOL_GPL(power_supply_put_battery_info);
/**
* power_supply_temp2resist_simple() - find the battery internal resistance
- * percent
+ * percent from temperature
* @table: Pointer to battery resistance temperature table
* @table_len: The table length
* @temp: Current temperature
@@ -851,6 +851,71 @@ int power_supply_temp2resist_simple(struct power_supply_resistance_temp_table *t
}
EXPORT_SYMBOL_GPL(power_supply_temp2resist_simple);
+/**
+ * power_supply_vbat2ri() - find the battery internal resistance
+ * from the battery voltage
+ * @info: The battery information container
+ * @table: Pointer to battery resistance temperature table
+ * @vbat_uv: The battery voltage in microvolt
+ * @charging: If we are charging (true) or not (false)
+ *
+ * This helper function is used to look up battery internal resistance
+ * according to current battery voltage. Depending on whether the battery
+ * is currently charging or not, different resistance will be returned.
+ *
+ * Returns the internal resistance in microohm or negative error code.
+ */
+int power_supply_vbat2ri(struct power_supply_battery_info *info,
+ int vbat_uv, bool charging)
+{
+ struct power_supply_vbat_ri_table *vbat2ri;
+ int table_len;
+ int i, high, low;
+
+ /*
+ * If we are charging, and the battery supplies a separate table
+ * for this state, we use that in order to compensate for the
+ * charging voltage. Otherwise we use the main table.
+ */
+ if (charging && info->vbat2ri_charging) {
+ vbat2ri = info->vbat2ri_charging;
+ table_len = info->vbat2ri_charging_size;
+ } else {
+ vbat2ri = info->vbat2ri_discharging;
+ table_len = info->vbat2ri_discharging_size;
+ }
+
+ /*
+ * If no tables are specified, or if we are above the highest voltage in
+ * the voltage table, just return the factory specified internal resistance.
+ */
+ if (!vbat2ri || (table_len <= 0) || (vbat_uv > vbat2ri[0].vbat_uv)) {
+ if (charging && (info->factory_internal_resistance_charging_uohm > 0))
+ return info->factory_internal_resistance_charging_uohm;
+ else
+ return info->factory_internal_resistance_uohm;
+ }
+
+ /* Break loop at table_len - 1 because that is the highest index */
+ for (i = 0; i < table_len - 1; i++)
+ if (vbat_uv > vbat2ri[i].vbat_uv)
+ break;
+
+ /* The library function will deal with high == low */
+ if ((i == 0) || (i == (table_len - 1)))
+ high = i;
+ else
+ high = i - 1;
+ low = i;
+
+ return fixp_linear_interpolate(vbat2ri[low].vbat_uv,
+ vbat2ri[low].ri_uohm,
+ vbat2ri[high].vbat_uv,
+ vbat2ri[high].ri_uohm,
+ vbat_uv);
+}
+EXPORT_SYMBOL_GPL(power_supply_vbat2ri);
+
struct power_supply_maintenance_charge_table *
power_supply_get_maintenance_charging_setting(struct power_supply_battery_info *info,
int index)