Commit 039053c1 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-v5.17' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply

Pull power supply and reset updates from Sebastian Reichel:
 "Power-supply core:

   - introduce "No Battery" health status

   - use library interpolation

   - add power_supply_battery_info documentation

   - migrate power_supply_battery_info to be fully heap allocated making
     it more obvious that it needs to be free'd manually

  Drivers:

   - max77976-charger: new driver

   - qcom-smbb: add pm8226 charger support

   - bq25890-charger: support battery temperature readings

   - ab8500: continue migrating towards using standard core APIs"

* tag 'for-v5.17' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply: (28 commits)
  power: supply_core: Pass pointer to battery info
  power: supply: ab8500: Fix the error handling path of ab8500_charger_probe()
  power: reset: mt6397: Check for null res pointer
  power: bq25890: add POWER_SUPPLY_PROP_TEMP
  power: supply: qcom_smbb: support pm8226
  dt-bindings: power: supply: pm8941-charger: add pm8226
  power: supply: ab8500: Standardize capacity lookup
  power: supply: ab8500: Standardize temp res lookup
  power: supply: ab8500: Standardize CV voltage
  power: supply: ab8500: Standardize CC current
  power: supply: ab8500: Make recharge capacity a constant
  power: supply: ab8500: Standardize termination current
  power: supply: ab8500: Standardize internal resistance
  power: supply: ab8500_fg: Init battery data in bind()
  power: supply: ab8500: Standardize voltages
  power: supply: ab8500: Standardize technology
  power: supply: ab8500: Standardize design capacity
  power: supply: ab8500: Use only one battery type
  power: supply: ab8500: Drop unused battery types
  power: supply: ab8500: Standardize operating temperature
  ...
parents 7db48b6b 25fd3303
......@@ -413,7 +413,7 @@ Description:
"Over voltage", "Unspecified failure", "Cold",
"Watchdog timer expire", "Safety timer expire",
"Over current", "Calibration required", "Warm",
"Cool", "Hot"
"Cool", "Hot", "No battery"
What: /sys/class/power_supply/<supply_name>/precharge_current
Date: June 2017
......
Driver a GPIO line that can be used to turn the power off.
The driver supports both level triggered and edge triggered power off.
At driver load time, the driver will request the given gpio line and
install a handler to power off the system. If the optional properties
'input' is not found, the GPIO line will be driven in the inactive
state. Otherwise its configured as an input.
When the power-off handler is called, the gpio is configured as an
output, and drive active, so triggering a level triggered power off
condition. This will also cause an inactive->active edge condition, so
triggering positive edge triggered power off. After a delay of 100ms,
the GPIO is set to inactive, thus causing an active->inactive edge,
triggering negative edge triggered power off. After another 100ms
delay the GPIO is driver active again. If the power is still on and
the CPU still running after a 3000ms delay, a WARN_ON(1) is emitted.
Required properties:
- compatible : should be "gpio-poweroff".
- gpios : The GPIO to set high/low, see "gpios property" in
Documentation/devicetree/bindings/gpio/gpio.txt. If the pin should be
low to power down the board set it to "Active Low", otherwise set
gpio to "Active High".
Optional properties:
- input : Initially configure the GPIO line as an input. Only reconfigure
it to an output when the power-off handler is called. If this optional
property is not specified, the GPIO is initialized as an output in its
inactive state.
- active-delay-ms: Delay (default 100) to wait after driving gpio active
- inactive-delay-ms: Delay (default 100) to wait after driving gpio inactive
- timeout-ms: Time to wait before asserting a WARN_ON(1). If nothing is
specified, 3000 ms is used.
Examples:
gpio-poweroff {
compatible = "gpio-poweroff";
gpios = <&gpio 4 0>;
timeout-ms = <3000>;
};
# SPDX-License-Identifier: (GPL-2.0-only or BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/power/reset/gpio-poweroff.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: GPIO controlled power off
maintainers:
- Sebastian Reichel <sre@kernel.org>
description: >
System power off support via a GPIO line. When a shutdown is
executed the operating system is expected to switch the GPIO
from inactive to active. After a delay (active-delay-ms) it
is expected to be switched back to inactive. After another
delay (inactive-delay-ms) it is configured as active again.
Finally the operating system assumes the power off failed if
the system is still running after waiting some time (timeout-ms).
properties:
compatible:
const: gpio-poweroff
gpios:
maxItems: 1
input:
type: boolean
description: >
Initially configure the GPIO line as an input. Only reconfigure
it to an output when the power-off sequence is initiated. If this optional
property is not specified, the GPIO is initialized as an output in its inactive state.
active-delay-ms:
default: 100
description: Delay to wait after driving gpio active
inactive-delay-ms:
default: 100
description: Delay to wait after driving gpio inactive
timeout-ms:
default: 3000
description: Time to wait before assuming the power off sequence failed.
required:
- compatible
- gpios
additionalProperties: false
examples:
- |
gpio-poweroff {
compatible = "gpio-poweroff";
gpios = <&gpio 4 0>;
timeout-ms = <3000>;
};
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/power/supply/maxim,max77976.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Maxim Integrated MAX77976 Battery charger
maintainers:
- Luca Ceresoli <luca@lucaceresoli.net>
description: |
The Maxim MAX77976 is a 19Vin / 5.5A, 1-Cell Li+ battery charger
configured via I2C.
allOf:
- $ref: power-supply.yaml#
properties:
compatible:
const: maxim,max77976
reg:
maxItems: 1
required:
- compatible
- reg
unevaluatedProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
charger@6b {
compatible = "maxim,max77976";
reg = <0x6b>;
};
};
...
......@@ -11,7 +11,9 @@ maintainers:
properties:
compatible:
const: qcom,pm8941-charger
enum:
- qcom,pm8226-charger
- qcom,pm8941-charger
reg:
maxItems: 1
......
......@@ -11668,6 +11668,12 @@ F: Documentation/devicetree/bindings/*/*max77802.txt
F: drivers/regulator/max77802-regulator.c
F: include/dt-bindings/*/*max77802.h
MAXIM MAX77976 BATTERY CHARGER
M: Luca Ceresoli <luca@lucaceresoli.net>
S: Supported
F: Documentation/devicetree/bindings/power/supply/maxim,max77976.yaml
F: drivers/power/supply/max77976_charger.c
MAXIM MUIC CHARGER DRIVERS FOR EXYNOS BASED BOARDS
M: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
M: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
......
......@@ -57,6 +57,9 @@ static int mt6323_pwrc_probe(struct platform_device *pdev)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -EINVAL;
pwrc->base = res->start;
pwrc->regmap = mt6397_chip->regmap;
pwrc->dev = &pdev->dev;
......
......@@ -557,6 +557,18 @@ config CHARGER_MAX77693
help
Say Y to enable support for the Maxim MAX77693 battery charger.
config CHARGER_MAX77976
tristate "Maxim MAX77976 battery charger driver"
depends on I2C
select REGMAP_I2C
help
The Maxim MAX77976 is a 19 Vin, 5.5A 1-Cell Li+ Battery Charger
USB OTG support. It has an I2C interface for configuration.
Say Y to enable support for the Maxim MAX77976 battery charger.
This driver can also be built as a module. If so, the module will be
called max77976_charger.
config CHARGER_MAX8997
tristate "Maxim MAX8997/MAX8966 PMIC battery charger driver"
depends on MFD_MAX8997 && REGULATOR_MAX8997
......
......@@ -75,6 +75,7 @@ obj-$(CONFIG_CHARGER_MAX14577) += max14577_charger.o
obj-$(CONFIG_CHARGER_DETECTOR_MAX14656) += max14656_charger_detector.o
obj-$(CONFIG_CHARGER_MAX77650) += max77650-charger.o
obj-$(CONFIG_CHARGER_MAX77693) += max77693_charger.o
obj-$(CONFIG_CHARGER_MAX77976) += max77976_charger.o
obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o
obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o
obj-$(CONFIG_CHARGER_MP2629) += mp2629_charger.o
......
......@@ -160,13 +160,6 @@
#define BTEMP_HIGH_TH_57_1 0x02
#define BTEMP_HIGH_TH_62 0x03
/* current is mA */
#define USB_0P1A 100
#define USB_0P2A 200
#define USB_0P3A 300
#define USB_0P4A 400
#define USB_0P5A 500
#define LOW_BAT_3P1V 0x20
#define LOW_BAT_2P3V 0x00
#define LOW_BAT_RESET 0x01
......@@ -203,8 +196,8 @@ enum bup_vch_sel {
#define BATT_OVV_TH_3P7 0x00
#define BATT_OVV_TH_4P75 0x01
/* A value to indicate over voltage */
#define BATT_OVV_VALUE 4750
/* A value to indicate over voltage (microvolts) */
#define BATT_OVV_VALUE 4750000
/* VBUS OVV constants */
#define VBUS_OVV_SELECT_MASK 0x78
......@@ -291,16 +284,6 @@ struct ab8500_res_to_temp {
int resist;
};
/**
* struct ab8500_v_to_cap - Table for translating voltage to capacity
* @voltage: Voltage in mV
* @capacity: Capacity in percent
*/
struct ab8500_v_to_cap {
int voltage;
int capacity;
};
/* Forward declaration */
struct ab8500_fg;
......@@ -314,10 +297,9 @@ struct ab8500_fg;
* @init_total_time: Total init time during startup
* @high_curr_time: Time current has to be high to go to recovery
* @accu_charging: FG accumulation time while charging
* @accu_high_curr: FG accumulation time in high current mode
* @high_curr_threshold: High current threshold, in mA
* @lowbat_threshold: Low battery threshold, in mV
* @overbat_threshold: Over battery threshold, in mV
* @accu_high_curr_ua: FG accumulation time in high current mode
* @high_curr_threshold_ua: High current threshold, in uA
* @lowbat_threshold_uv: Low battery threshold, in uV
* @battok_falling_th_sel0 Threshold in mV for battOk signal sel0
* Resolution in 50 mV step.
* @battok_raising_th_sel1 Threshold in mV for battOk signal sel1
......@@ -342,9 +324,8 @@ struct ab8500_fg_parameters {
int high_curr_time;
int accu_charging;
int accu_high_curr;
int high_curr_threshold;
int lowbat_threshold;
int overbat_threshold;
int high_curr_threshold_ua;
int lowbat_threshold_uv;
int battok_falling_th_sel0;
int battok_raising_th_sel1;
int user_cap_limit;
......@@ -359,31 +340,21 @@ struct ab8500_fg_parameters {
/**
* struct ab8500_charger_maximization - struct used by the board config.
* @use_maxi: Enable maximization for this battery type
* @maxi_chg_curr: Maximum charger current allowed
* @maxi_chg_curr_ua: Maximum charger current allowed in microampere
* @maxi_wait_cycles: cycles to wait before setting charger current
* @charger_curr_step delta between two charger current settings (mA)
* @charger_curr_step_ua: delta between two charger current settings (uA)
*/
struct ab8500_maxim_parameters {
bool ena_maxi;
int chg_curr;
int chg_curr_ua;
int wait_cycles;
int charger_curr_step;
int charger_curr_step_ua;
};
/**
* struct ab8500_battery_type - different batteries supported
* @name: battery technology
* @resis_high: battery upper resistance limit
* @resis_low: battery lower resistance limit
* @charge_full_design: Maximum battery capacity in mAh
* @nominal_voltage: Nominal voltage of the battery in mV
* @termination_vol: max voltage upto which battery can be charged
* @termination_curr battery charging termination current in mA
* @recharge_cap battery capacity limit that will trigger a new
* full charging cycle in the case where maintenan-
* -ce charging has been disabled
* @normal_cur_lvl: charger current in normal state in mA
* @normal_vol_lvl: charger voltage in normal state in mV
* @maint_a_cur_lvl: charger current in maintenance A state in mA
* @maint_a_vol_lvl: charger voltage in maintenance A state in mV
* @maint_a_chg_timer_h: charge time in maintenance A state
......@@ -392,25 +363,12 @@ struct ab8500_maxim_parameters {
* @maint_b_chg_timer_h: charge time in maintenance B state
* @low_high_cur_lvl: charger current in temp low/high state in mA
* @low_high_vol_lvl: charger voltage in temp low/high state in mV'
* @battery_resistance: battery inner resistance in mOhm.
* @n_r_t_tbl_elements: number of elements in r_to_t_tbl
* @r_to_t_tbl: table containing resistance to temp points
* @n_v_cap_tbl_elements: number of elements in v_to_cap_tbl
* @v_to_cap_tbl: Voltage to capacity (in %) table
* @n_batres_tbl_elements number of elements in the batres_tbl
* @batres_tbl battery internal resistance vs temperature table
*/
struct ab8500_battery_type {
int name;
int resis_high;
int resis_low;
int charge_full_design;
int nominal_voltage;
int termination_vol;
int termination_curr;
int recharge_cap;
int normal_cur_lvl;
int normal_vol_lvl;
int maint_a_cur_lvl;
int maint_a_vol_lvl;
int maint_a_chg_timer_h;
......@@ -419,13 +377,8 @@ struct ab8500_battery_type {
int maint_b_chg_timer_h;
int low_high_cur_lvl;
int low_high_vol_lvl;
int battery_resistance;
int n_temp_tbl_elements;
const struct ab8500_res_to_temp *r_to_t_tbl;
int n_v_cap_tbl_elements;
const struct ab8500_v_to_cap *v_to_cap_tbl;
int n_batres_tbl_elements;
const struct batres_vs_temp *batres_tbl;
};
/**
......@@ -446,24 +399,21 @@ struct ab8500_bm_capacity_levels {
/**
* struct ab8500_bm_charger_parameters - Charger specific parameters
* @usb_volt_max: maximum allowed USB charger voltage in mV
* @usb_curr_max: maximum allowed USB charger current in mA
* @ac_volt_max: maximum allowed AC charger voltage in mV
* @ac_curr_max: maximum allowed AC charger current in mA
* @usb_volt_max_uv: maximum allowed USB charger voltage in uV
* @usb_curr_max_ua: maximum allowed USB charger current in uA
* @ac_volt_max_uv: maximum allowed AC charger voltage in uV
* @ac_curr_max_ua: maximum allowed AC charger current in uA
*/
struct ab8500_bm_charger_parameters {
int usb_volt_max;
int usb_curr_max;
int ac_volt_max;
int ac_curr_max;
int usb_volt_max_uv;
int usb_curr_max_ua;
int ac_volt_max_uv;
int ac_curr_max_ua;
};
/**
* struct ab8500_bm_data - ab8500 battery management data
* @temp_under under this temp, charging is stopped
* @temp_low between this temp and temp_under charging is reduced
* @temp_high between this temp and temp_over charging is reduced
* @temp_over over this temp, charging is stopped
* @bi battery info from device tree
* @temp_now present battery temperature
* @temp_interval_chg temperature measurement interval in s when charging
* @temp_interval_nochg temperature measurement interval in s when not charging
......@@ -478,16 +428,10 @@ struct ab8500_bm_charger_parameters {
* @enable_overshoot flag to enable VBAT overshoot control
* @auto_trig flag to enable auto adc trigger
* @fg_res resistance of FG resistor in 0.1mOhm
* @n_btypes number of elements in array bat_type
* @batt_id index of the identified battery in array bat_type
* @interval_charging charge alg cycle period time when charging (sec)
* @interval_not_charging charge alg cycle period time when not charging (sec)
* @temp_hysteresis temperature hysteresis
* @gnd_lift_resistance Battery ground to phone ground resistance (mOhm)
* @n_chg_out_curr number of elements in array chg_output_curr
* @n_chg_in_curr number of elements in array chg_input_curr
* @chg_output_curr charger output current level map
* @chg_input_curr charger input current level map
* @maxi maximization parameters
* @cap_levels capacity in percent for the different capacity levels
* @bat_type table of supported battery types
......@@ -495,10 +439,7 @@ struct ab8500_bm_charger_parameters {
* @fg_params fuel gauge parameters
*/
struct ab8500_bm_data {
int temp_under;
int temp_low;
int temp_high;
int temp_over;
struct power_supply_battery_info *bi;
int temp_now;
int temp_interval_chg;
int temp_interval_nochg;
......@@ -513,16 +454,10 @@ struct ab8500_bm_data {
bool auto_trig;
enum ab8500_adc_therm adc_therm;
int fg_res;
int n_btypes;
int batt_id;
int interval_charging;
int interval_not_charging;
int temp_hysteresis;
int gnd_lift_resistance;
int n_chg_out_curr;
int n_chg_in_curr;
int *chg_output_curr;
int *chg_input_curr;
const struct ab8500_maxim_parameters *maxi;
const struct ab8500_bm_capacity_levels *cap_levels;
struct ab8500_battery_type *bat_type;
......@@ -547,17 +482,6 @@ struct res_to_temp {
int resist;
};
/**
* struct batres_vs_temp - defines one point in a temp vs battery internal
* resistance curve.
* @temp: battery pack temperature in Celsius
* @resist: battery internal reistance in mOhm
*/
struct batres_vs_temp {
int temp;
int resist;
};
/* Forward declaration */
struct ab8500_fg;
......@@ -570,9 +494,10 @@ int ab8500_fg_inst_curr_start(struct ab8500_fg *di);
int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res);
int ab8500_fg_inst_curr_started(struct ab8500_fg *di);
int ab8500_fg_inst_curr_done(struct ab8500_fg *di);
int ab8500_bm_of_probe(struct device *dev,
struct device_node *np,
int ab8500_bm_of_probe(struct power_supply *psy,
struct ab8500_bm_data *bm);
void ab8500_bm_of_remove(struct power_supply *psy,
struct ab8500_bm_data *bm);
extern struct platform_driver ab8500_fg_driver;
extern struct platform_driver ab8500_btemp_driver;
......
......@@ -31,16 +31,16 @@ struct ux500_charger_ops {
* struct ux500_charger - power supply ux500 charger sub class
* @psy power supply base class
* @ops ux500 charger operations
* @max_out_volt maximum output charger voltage in mV
* @max_out_curr maximum output charger current in mA
* @max_out_volt_uv maximum output charger voltage in uV
* @max_out_curr_ua maximum output charger current in uA
* @enabled indicates if this charger is used or not
* @external external charger unit (pm2xxx)
*/
struct ux500_charger {
struct power_supply *psy;
struct ux500_charger_ops ops;
int max_out_volt;
int max_out_curr;
int max_out_volt_uv;
int max_out_curr_ua;
int wdt_refresh;
bool enabled;
bool external;
......
This diff is collapsed.
......@@ -451,15 +451,13 @@ static int ab8500_btemp_res_to_temp(struct ab8500_btemp *di,
*/
static int ab8500_btemp_measure_temp(struct ab8500_btemp *di)
{
struct power_supply_battery_info *bi = di->bm->bi;
int temp, ret;
static int prev;
int rbat, rntc, vntc;
u8 id;
id = di->bm->batt_id;
if (di->bm->adc_therm == AB8500_ADC_THERM_BATCTRL &&
id != BATTERY_UNKNOWN) {
if ((di->bm->adc_therm == AB8500_ADC_THERM_BATCTRL) &&
(bi && (bi->technology == POWER_SUPPLY_TECHNOLOGY_UNKNOWN))) {
rbat = ab8500_btemp_get_batctrl_res(di);
if (rbat < 0) {
......@@ -473,8 +471,8 @@ static int ab8500_btemp_measure_temp(struct ab8500_btemp *di)
}
temp = ab8500_btemp_res_to_temp(di,
di->bm->bat_type[id].r_to_t_tbl,
di->bm->bat_type[id].n_temp_tbl_elements, rbat);
di->bm->bat_type->r_to_t_tbl,
di->bm->bat_type->n_temp_tbl_elements, rbat);
} else {
ret = iio_read_channel_processed(di->btemp_ball, &vntc);
if (ret < 0) {
......@@ -490,8 +488,8 @@ static int ab8500_btemp_measure_temp(struct ab8500_btemp *di)
rntc = 230000 * vntc / (VTVOUT_V - vntc);
temp = ab8500_btemp_res_to_temp(di,
di->bm->bat_type[id].r_to_t_tbl,
di->bm->bat_type[id].n_temp_tbl_elements, rntc);
di->bm->bat_type->r_to_t_tbl,
di->bm->bat_type->n_temp_tbl_elements, rntc);
prev = temp;
}
dev_dbg(di->dev, "Battery temperature is %d\n", temp);
......@@ -512,7 +510,6 @@ static int ab8500_btemp_id(struct ab8500_btemp *di)
u8 i;
di->curr_source = BTEMP_BATCTRL_CURR_SRC_7UA;
di->bm->batt_id = BATTERY_UNKNOWN;
res = ab8500_btemp_get_batctrl_res(di);
if (res < 0) {
......@@ -520,40 +517,37 @@ static int ab8500_btemp_id(struct ab8500_btemp *di)
return -ENXIO;
}
/* BATTERY_UNKNOWN is defined on position 0, skip it! */
for (i = BATTERY_UNKNOWN + 1; i < di->bm->n_btypes; i++) {
if ((res <= di->bm->bat_type[i].resis_high) &&
(res >= di->bm->bat_type[i].resis_low)) {
dev_dbg(di->dev, "Battery detected on %s"
" low %d < res %d < high: %d"
" index: %d\n",
di->bm->adc_therm == AB8500_ADC_THERM_BATCTRL ?
"BATCTRL" : "BATTEMP",
di->bm->bat_type[i].resis_low, res,
di->bm->bat_type[i].resis_high, i);
di->bm->batt_id = i;
break;
}
}
if (di->bm->batt_id == BATTERY_UNKNOWN) {
if ((res <= di->bm->bat_type->resis_high) &&
(res >= di->bm->bat_type->resis_low)) {
dev_info(di->dev, "Battery detected on %s"
" low %d < res %d < high: %d"
" index: %d\n",
di->bm->adc_therm == AB8500_ADC_THERM_BATCTRL ?
"BATCTRL" : "BATTEMP",
di->bm->bat_type->resis_low, res,
di->bm->bat_type->resis_high, i);
} else {
dev_warn(di->dev, "Battery identified as unknown"
", resistance %d Ohm\n", res);
", resistance %d Ohm\n", res);
return -ENXIO;
}
/*
* We only have to change current source if the
* detected type is Type 1.
* detected type is Type 1 (LIPO) resis_high = 53407, resis_low = 12500
* if someone hacks this in.
*
* FIXME: make sure this is done automatically for the batteries
* that need it.
*/
if (di->bm->adc_therm == AB8500_ADC_THERM_BATCTRL &&
di->bm->batt_id == 1) {
if ((di->bm->adc_therm == AB8500_ADC_THERM_BATCTRL) &&
(di->bm->bi && (di->bm->bi->technology == POWER_SUPPLY_TECHNOLOGY_LIPO)) &&
(res <= 53407) && (res >= 12500)) {
dev_dbg(di->dev, "Set BATCTRL current source to 20uA\n");
di->curr_source = BTEMP_BATCTRL_CURR_SRC_20UA;
}
return di->bm->batt_id;
return 0;
}
/**
......@@ -814,7 +808,10 @@ static int ab8500_btemp_get_property(struct power_supply *psy,
val->intval = 1;
break;
case POWER_SUPPLY_PROP_TECHNOLOGY:
val->intval = di->bm->bat_type[di->bm->batt_id].name;
if (di->bm->bi)
val->intval = di->bm->bi->technology;
else
val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
break;
case POWER_SUPPLY_PROP_TEMP:
val->intval = ab8500_btemp_get_temp(di);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -561,7 +561,7 @@ static int axp20x_power_probe(struct platform_device *pdev)
{
struct axp20x_batt_ps *axp20x_batt;
struct power_supply_config psy_cfg = {};
struct power_supply_battery_info info;
struct power_supply_battery_info *info;
struct device *dev = &pdev->dev;
if (!of_device_is_available(pdev->dev.of_node))
......@@ -615,8 +615,8 @@ static int axp20x_power_probe(struct platform_device *pdev)
}
if (!power_supply_get_battery_info(axp20x_batt->batt, &info)) {
int vmin = info.voltage_min_design_uv;
int ccc = info.constant_charge_current_max_ua;
int vmin = info->voltage_min_design_uv;
int ccc = info->constant_charge_current_max_ua;
if (vmin > 0 && axp20x_set_voltage_min_design(axp20x_batt,
vmin))
......
......@@ -882,7 +882,7 @@ struct dt_init {
static int bd9995x_fw_probe(struct bd9995x_device *bd)
{
int ret;
struct power_supply_battery_info info;
struct power_supply_battery_info *info;
u32 property;
int i;
int regval;
......@@ -891,49 +891,41 @@ static int bd9995x_fw_probe(struct bd9995x_device *bd)
struct battery_init battery_inits[] = {
{
.name = "trickle-charging current",
.info_data = &info.tricklecharge_current_ua,
.range = &charging_current_ranges[0],
.ranges = 2,
.data = &init->itrich_set,
}, {
.name = "pre-charging current",
.info_data = &info.precharge_current_ua,
.range = &charging_current_ranges[0],
.ranges = 2,
.data = &init->iprech_set,
}, {
.name = "pre-to-trickle charge voltage threshold",
.info_data = &info.precharge_voltage_max_uv,
.range = &trickle_to_pre_threshold_ranges[0],
.ranges = 2,
.data = &init->vprechg_th_set,
}, {
.name = "charging termination current",
.info_data = &info.charge_term_current_ua,
.range = &charging_current_ranges[0],
.ranges = 2,
.data = &init->iterm_set,
}, {
.name = "charging re-start voltage",
.info_data = &info.charge_restart_voltage_uv,
.range = &charge_voltage_regulation_ranges[0],
.ranges = 2,
.data = &init->vrechg_set,
}, {
.name = "battery overvoltage limit",
.info_data = &info.overvoltage_limit_uv,
.range = &charge_voltage_regulation_ranges[0],
.ranges = 2,
.data = &init->vbatovp_set,
}, {
.name = "fast-charging max current",
.info_data = &info.constant_charge_current_max_ua,
.range = &fast_charge_current_ranges[0],
.ranges = 1,
.data = &init->ichg_set,
}, {
.name = "fast-charging voltage",
.info_data = &info.constant_charge_voltage_max_uv,
.range = &charge_voltage_regulation_ranges[0],
.ranges = 2,
.data = &init->vfastchg_reg_set1,
......@@ -966,6 +958,16 @@ static int bd9995x_fw_probe(struct bd9995x_device *bd)
if (ret < 0)
return ret;
/* Put pointers to the generic battery info */
battery_inits[0].info_data = &info->tricklecharge_current_ua;
battery_inits[1].info_data = &info->precharge_current_ua;
battery_inits[2].info_data = &info->precharge_voltage_max_uv;
battery_inits[3].info_data = &info->charge_term_current_ua;
battery_inits[4].info_data = &info->charge_restart_voltage_uv;
battery_inits[5].info_data = &info->overvoltage_limit_uv;
battery_inits[6].info_data = &info->constant_charge_current_max_ua;
battery_inits[7].info_data = &info->constant_charge_voltage_max_uv;
for (i = 0; i < ARRAY_SIZE(battery_inits); i++) {
int val = *battery_inits[i].info_data;
const struct linear_range *range = battery_inits[i].range;
......@@ -980,7 +982,7 @@ static int bd9995x_fw_probe(struct bd9995x_device *bd)
dev_err(bd->dev, "Unsupported value for %s\n",
battery_inits[i].name);
power_supply_put_battery_info(bd->charger, &info);
power_supply_put_battery_info(bd->charger, info);
return -EINVAL;
}
if (!found) {
......@@ -991,7 +993,7 @@ static int bd9995x_fw_probe(struct bd9995x_device *bd)
*(battery_inits[i].data) = regval;
}
power_supply_put_battery_info(bd->charger, &info);
power_supply_put_battery_info(bd->charger, info);
for (i = 0; i < ARRAY_SIZE(props); i++) {
ret = device_property_read_u32(bd->dev, props[i].prop,
......
......@@ -1670,7 +1670,7 @@ static int bq24190_hw_init(struct bq24190_dev_info *bdi)
static int bq24190_get_config(struct bq24190_dev_info *bdi)
{
const char * const s = "ti,system-minimum-microvolt";
struct power_supply_battery_info info = {};
struct power_supply_battery_info *info;
int v;
if (device_property_read_u32(bdi->dev, s, &v) == 0) {
......@@ -1684,7 +1684,7 @@ static int bq24190_get_config(struct bq24190_dev_info *bdi)
if (bdi->dev->of_node &&
!power_supply_get_battery_info(bdi->charger, &info)) {
v = info.precharge_current_ua / 1000;
v = info->precharge_current_ua / 1000;
if (v >= BQ24190_REG_PCTCC_IPRECHG_MIN
&& v <= BQ24190_REG_PCTCC_IPRECHG_MAX)
bdi->iprechg = v;
......@@ -1692,7 +1692,7 @@ static int bq24190_get_config(struct bq24190_dev_info *bdi)
dev_warn(bdi->dev, "invalid value for battery:precharge-current-microamp: %d\n",
v);
v = info.charge_term_current_ua / 1000;
v = info->charge_term_current_ua / 1000;
if (v >= BQ24190_REG_PCTCC_ITERM_MIN
&& v <= BQ24190_REG_PCTCC_ITERM_MAX)
bdi->iterm = v;
......
......@@ -945,7 +945,7 @@ static int bq2515x_power_supply_register(struct bq2515x_device *bq2515x,
static int bq2515x_hw_init(struct bq2515x_device *bq2515x)
{
int ret;
struct power_supply_battery_info bat_info = { };
struct power_supply_battery_info *bat_info;
ret = bq2515x_disable_watchdog_timers(bq2515x);
if (ret)
......@@ -969,13 +969,13 @@ static int bq2515x_hw_init(struct bq2515x_device *bq2515x)
} else {
bq2515x->init_data.ichg =
bat_info.constant_charge_current_max_ua;
bat_info->constant_charge_current_max_ua;
bq2515x->init_data.vbatreg =
bat_info.constant_charge_voltage_max_uv;
bat_info->constant_charge_voltage_max_uv;
bq2515x->init_data.iprechg =
bat_info.precharge_current_ua;
bat_info->precharge_current_ua;
}
ret = bq2515x_set_const_charge_current(bq2515x,
......
......@@ -1504,7 +1504,7 @@ static int bq256xx_power_supply_init(struct bq256xx_device *bq,
static int bq256xx_hw_init(struct bq256xx_device *bq)
{
struct power_supply_battery_info bat_info = { };
struct power_supply_battery_info *bat_info;
int wd_reg_val = BQ256XX_WATCHDOG_DIS;
int ret = 0;
int i;
......@@ -1526,16 +1526,16 @@ static int bq256xx_hw_init(struct bq256xx_device *bq)
if (ret) {
dev_warn(bq->dev, "battery info missing, default values will be applied\n");
bat_info.constant_charge_current_max_ua =
bat_info->constant_charge_current_max_ua =
bq->chip_info->bq256xx_def_ichg;
bat_info.constant_charge_voltage_max_uv =
bat_info->constant_charge_voltage_max_uv =
bq->chip_info->bq256xx_def_vbatreg;
bat_info.precharge_current_ua =
bat_info->precharge_current_ua =
bq->chip_info->bq256xx_def_iprechg;
bat_info.charge_term_current_ua =
bat_info->charge_term_current_ua =
bq->chip_info->bq256xx_def_iterm;
bq->init_data.ichg_max =
......@@ -1545,10 +1545,10 @@ static int bq256xx_hw_init(struct bq256xx_device *bq)
bq->chip_info->bq256xx_max_vbatreg;
} else {
bq->init_data.ichg_max =
bat_info.constant_charge_current_max_ua;
bat_info->constant_charge_current_max_ua;
bq->init_data.vbatreg_max =
bat_info.constant_charge_voltage_max_uv;
bat_info->constant_charge_voltage_max_uv;
}
ret = bq->chip_info->bq256xx_set_vindpm(bq, bq->init_data.vindpm);
......@@ -1560,26 +1560,26 @@ static int bq256xx_hw_init(struct bq256xx_device *bq)
return ret;
ret = bq->chip_info->bq256xx_set_ichg(bq,
bat_info.constant_charge_current_max_ua);
bat_info->constant_charge_current_max_ua);
if (ret)
return ret;
ret = bq->chip_info->bq256xx_set_iprechg(bq,
bat_info.precharge_current_ua);
bat_info->precharge_current_ua);
if (ret)
return ret;
ret = bq->chip_info->bq256xx_set_vbatreg(bq,
bat_info.constant_charge_voltage_max_uv);
bat_info->constant_charge_voltage_max_uv);
if (ret)
return ret;
ret = bq->chip_info->bq256xx_set_iterm(bq,
bat_info.charge_term_current_ua);
bat_info->charge_term_current_ua);
if (ret)
return ret;
power_supply_put_battery_info(bq->charger, &bat_info);
power_supply_put_battery_info(bq->charger, bat_info);
return 0;
}
......
......@@ -266,6 +266,7 @@ enum bq25890_table_ids {
/* lookup tables */
TBL_TREG,
TBL_BOOSTI,
TBL_TSPCT,
};
/* Thermal Regulation Threshold lookup table, in degrees Celsius */
......@@ -280,6 +281,28 @@ static const u32 bq25890_boosti_tbl[] = {
#define BQ25890_BOOSTI_TBL_SIZE ARRAY_SIZE(bq25890_boosti_tbl)
/* NTC 10K temperature lookup table in tenths of a degree */
static const u32 bq25890_tspct_tbl[] = {
850, 840, 830, 820, 810, 800, 790, 780,
770, 760, 750, 740, 730, 720, 710, 700,
690, 685, 680, 675, 670, 660, 650, 645,
640, 630, 620, 615, 610, 600, 590, 585,
580, 570, 565, 560, 550, 540, 535, 530,
520, 515, 510, 500, 495, 490, 480, 475,
470, 460, 455, 450, 440, 435, 430, 425,
420, 410, 405, 400, 390, 385, 380, 370,
365, 360, 355, 350, 340, 335, 330, 320,
310, 305, 300, 290, 285, 280, 275, 270,
260, 250, 245, 240, 230, 225, 220, 210,
205, 200, 190, 180, 175, 170, 160, 150,
145, 140, 130, 120, 115, 110, 100, 90,
80, 70, 60, 50, 40, 30, 20, 10,
0, -10, -20, -30, -40, -60, -70, -80,
-90, -10, -120, -140, -150, -170, -190, -210,
};
#define BQ25890_TSPCT_TBL_SIZE ARRAY_SIZE(bq25890_tspct_tbl)
struct bq25890_range {
u32 min;
u32 max;
......@@ -308,7 +331,8 @@ static const union {
/* lookup tables */
[TBL_TREG] = { .lt = {bq25890_treg_tbl, BQ25890_TREG_TBL_SIZE} },
[TBL_BOOSTI] = { .lt = {bq25890_boosti_tbl, BQ25890_BOOSTI_TBL_SIZE} }
[TBL_BOOSTI] = { .lt = {bq25890_boosti_tbl, BQ25890_BOOSTI_TBL_SIZE} },
[TBL_TSPCT] = { .lt = {bq25890_tspct_tbl, BQ25890_TSPCT_TBL_SIZE} }
};
static int bq25890_field_read(struct bq25890_device *bq,
......@@ -388,6 +412,7 @@ static bool bq25890_is_adc_property(enum power_supply_property psp)
switch (psp) {
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
case POWER_SUPPLY_PROP_CURRENT_NOW:
case POWER_SUPPLY_PROP_TEMP:
return true;
default:
......@@ -528,6 +553,15 @@ static int bq25890_power_supply_get_property(struct power_supply *psy,
val->intval = ret * -50000;
break;
case POWER_SUPPLY_PROP_TEMP:
ret = bq25890_field_read(bq, F_TSPCT);
if (ret < 0)
return ret;
/* convert TS percentage into rough temperature */
val->intval = bq25890_find_val(ret, TBL_TSPCT);
break;
default:
return -EINVAL;
}
......@@ -713,6 +747,7 @@ static const enum power_supply_property bq25890_power_supply_props[] = {
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_CURRENT_NOW,
POWER_SUPPLY_PROP_TEMP,
};
static char *bq25890_charger_supplied_to[] = {
......
......@@ -1079,7 +1079,7 @@ static int bq25980_power_supply_init(struct bq25980_device *bq,
static int bq25980_hw_init(struct bq25980_device *bq)
{
struct power_supply_battery_info bat_info = { };
struct power_supply_battery_info *bat_info;
int wd_reg_val = BQ25980_WATCHDOG_DIS;
int wd_max_val = BQ25980_NUM_WD_VAL - 1;
int ret = 0;
......@@ -1112,8 +1112,8 @@ static int bq25980_hw_init(struct bq25980_device *bq)
return -EINVAL;
}
bq->init_data.ichg_max = bat_info.constant_charge_current_max_ua;
bq->init_data.vreg_max = bat_info.constant_charge_voltage_max_uv;
bq->init_data.ichg_max = bat_info->constant_charge_current_max_ua;
bq->init_data.vreg_max = bat_info->constant_charge_voltage_max_uv;
if (bq->state.bypass) {
ret = regmap_update_bits(bq->regmap, BQ25980_CHRGR_CTRL_2,
......
......@@ -1474,7 +1474,7 @@ static void bq27xxx_battery_set_config(struct bq27xxx_device_info *di,
static void bq27xxx_battery_settings(struct bq27xxx_device_info *di)
{
struct power_supply_battery_info info = {};
struct power_supply_battery_info *info;
unsigned int min, max;
if (power_supply_get_battery_info(di->bat, &info) < 0)
......@@ -1485,43 +1485,43 @@ static void bq27xxx_battery_settings(struct bq27xxx_device_info *di)
return;
}
if (info.energy_full_design_uwh != info.charge_full_design_uah) {
if (info.energy_full_design_uwh == -EINVAL)
if (info->energy_full_design_uwh != info->charge_full_design_uah) {
if (info->energy_full_design_uwh == -EINVAL)
dev_warn(di->dev, "missing battery:energy-full-design-microwatt-hours\n");
else if (info.charge_full_design_uah == -EINVAL)
else if (info->charge_full_design_uah == -EINVAL)
dev_warn(di->dev, "missing battery:charge-full-design-microamp-hours\n");
}
/* assume min == 0 */
max = di->dm_regs[BQ27XXX_DM_DESIGN_ENERGY].max;
if (info.energy_full_design_uwh > max * 1000) {
if (info->energy_full_design_uwh > max * 1000) {
dev_err(di->dev, "invalid battery:energy-full-design-microwatt-hours %d\n",
info.energy_full_design_uwh);
info.energy_full_design_uwh = -EINVAL;
info->energy_full_design_uwh);
info->energy_full_design_uwh = -EINVAL;
}
/* assume min == 0 */
max = di->dm_regs[BQ27XXX_DM_DESIGN_CAPACITY].max;
if (info.charge_full_design_uah > max * 1000) {
if (info->charge_full_design_uah > max * 1000) {
dev_err(di->dev, "invalid battery:charge-full-design-microamp-hours %d\n",
info.charge_full_design_uah);
info.charge_full_design_uah = -EINVAL;
info->charge_full_design_uah);
info->charge_full_design_uah = -EINVAL;
}
min = di->dm_regs[BQ27XXX_DM_TERMINATE_VOLTAGE].min;
max = di->dm_regs[BQ27XXX_DM_TERMINATE_VOLTAGE].max;
if ((info.voltage_min_design_uv < min * 1000 ||
info.voltage_min_design_uv > max * 1000) &&
info.voltage_min_design_uv != -EINVAL) {
if ((info->voltage_min_design_uv < min * 1000 ||
info->voltage_min_design_uv > max * 1000) &&
info->voltage_min_design_uv != -EINVAL) {
dev_err(di->dev, "invalid battery:voltage-min-design-microvolt %d\n",
info.voltage_min_design_uv);
info.voltage_min_design_uv = -EINVAL;
info->voltage_min_design_uv);
info->voltage_min_design_uv = -EINVAL;
}
if ((info.energy_full_design_uwh != -EINVAL &&
info.charge_full_design_uah != -EINVAL) ||
info.voltage_min_design_uv != -EINVAL)
bq27xxx_battery_set_config(di, &info);
if ((info->energy_full_design_uwh != -EINVAL &&
info->charge_full_design_uah != -EINVAL) ||
info->voltage_min_design_uv != -EINVAL)
bq27xxx_battery_set_config(di, info);
}
/*
......
......@@ -61,7 +61,7 @@ struct cw_battery {
struct delayed_work battery_delay_work;
struct regmap *regmap;
struct power_supply *rk_bat;
struct power_supply_battery_info battery;
struct power_supply_battery_info *battery;
u8 *bat_profile;
bool charger_attached;
......@@ -505,22 +505,22 @@ static int cw_battery_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_CHARGE_FULL:
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
if (cw_bat->battery.charge_full_design_uah > 0)
val->intval = cw_bat->battery.charge_full_design_uah;
if (cw_bat->battery->charge_full_design_uah > 0)
val->intval = cw_bat->battery->charge_full_design_uah;
else
val->intval = 0;
break;
case POWER_SUPPLY_PROP_CHARGE_NOW:
val->intval = cw_bat->battery.charge_full_design_uah;
val->intval = cw_bat->battery->charge_full_design_uah;
val->intval = val->intval * cw_bat->soc / 100;
break;
case POWER_SUPPLY_PROP_CURRENT_NOW:
if (cw_battery_valid_time_to_empty(cw_bat) &&
cw_bat->battery.charge_full_design_uah > 0) {
cw_bat->battery->charge_full_design_uah > 0) {
/* calculate remaining capacity */
val->intval = cw_bat->battery.charge_full_design_uah;
val->intval = cw_bat->battery->charge_full_design_uah;
val->intval = val->intval * cw_bat->soc / 100;
/* estimate current based on time to empty */
......@@ -687,6 +687,12 @@ static int cw_bat_probe(struct i2c_client *client)
ret = power_supply_get_battery_info(cw_bat->rk_bat, &cw_bat->battery);
if (ret) {
/* Allocate an empty battery */
cw_bat->battery = devm_kzalloc(&client->dev,
sizeof(cw_bat->battery),
GFP_KERNEL);
if (!cw_bat->battery)
return -ENOMEM;
dev_warn(cw_bat->dev,
"No monitored battery, some properties will be missing\n");
}
......@@ -724,7 +730,7 @@ static int cw_bat_remove(struct i2c_client *client)
struct cw_battery *cw_bat = i2c_get_clientdata(client);
cancel_delayed_work_sync(&cw_bat->battery_delay_work);
power_supply_put_battery_info(cw_bat->rk_bat, &cw_bat->battery);
power_supply_put_battery_info(cw_bat->rk_bat, cw_bat->battery);
return 0;
}
......
......@@ -18,7 +18,7 @@ struct ingenic_battery {
struct iio_channel *channel;
struct power_supply_desc desc;
struct power_supply *battery;
struct power_supply_battery_info info;
struct power_supply_battery_info *info;
};
static int ingenic_battery_get_property(struct power_supply *psy,
......@@ -26,7 +26,7 @@ static int ingenic_battery_get_property(struct power_supply *psy,
union power_supply_propval *val)
{
struct ingenic_battery *bat = power_supply_get_drvdata(psy);
struct power_supply_battery_info *info = &bat->info;
struct power_supply_battery_info *info = bat->info;
int ret;
switch (psp) {
......@@ -80,7 +80,7 @@ static int ingenic_battery_set_scale(struct ingenic_battery *bat)
if (ret != IIO_AVAIL_LIST || scale_type != IIO_VAL_FRACTIONAL_LOG2)
return -EINVAL;
max_mV = bat->info.voltage_max_design_uv / 1000;
max_mV = bat->info->voltage_max_design_uv / 1000;
for (i = 0; i < scale_len; i += 2) {
u64 scale_mV = (max_raw * scale_raw[i]) >> scale_raw[i + 1];
......@@ -156,13 +156,13 @@ static int ingenic_battery_probe(struct platform_device *pdev)
dev_err(dev, "Unable to get battery info: %d\n", ret);
return ret;
}
if (bat->info.voltage_min_design_uv < 0) {
if (bat->info->voltage_min_design_uv < 0) {
dev_err(dev, "Unable to get voltage min design\n");
return bat->info.voltage_min_design_uv;
return bat->info->voltage_min_design_uv;
}
if (bat->info.voltage_max_design_uv < 0) {
if (bat->info->voltage_max_design_uv < 0) {
dev_err(dev, "Unable to get voltage max design\n");
return bat->info.voltage_max_design_uv;
return bat->info->voltage_max_design_uv;
}
return ingenic_battery_set_scale(bat);
......
This diff is collapsed.
......@@ -21,6 +21,7 @@
#include <linux/power_supply.h>
#include <linux/property.h>
#include <linux/thermal.h>
#include <linux/fixp-arith.h>
#include "power_supply.h"
/* exported for the APM Power driver, APM emulation */
......@@ -563,14 +564,19 @@ EXPORT_SYMBOL_GPL(devm_power_supply_get_by_phandle);
#endif /* CONFIG_OF */
int power_supply_get_battery_info(struct power_supply *psy,
struct power_supply_battery_info *info)
struct power_supply_battery_info **info_out)
{
struct power_supply_resistance_temp_table *resist_table;
struct power_supply_battery_info *info;
struct device_node *battery_np;
const char *value;
int err, len, index;
const __be32 *list;
info = devm_kmalloc(&psy->dev, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
info->technology = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
info->energy_full_design_uwh = -EINVAL;
info->charge_full_design_uah = -EINVAL;
......@@ -580,6 +586,10 @@ int power_supply_get_battery_info(struct power_supply *psy,
info->charge_term_current_ua = -EINVAL;
info->constant_charge_current_max_ua = -EINVAL;
info->constant_charge_voltage_max_uv = -EINVAL;
info->tricklecharge_current_ua = -EINVAL;
info->precharge_voltage_max_uv = -EINVAL;
info->charge_restart_voltage_uv = -EINVAL;
info->overvoltage_limit_uv = -EINVAL;
info->temp_ambient_alert_min = INT_MIN;
info->temp_ambient_alert_max = INT_MAX;
info->temp_alert_min = INT_MIN;
......@@ -727,7 +737,7 @@ int power_supply_get_battery_info(struct power_supply *psy,
list = of_get_property(battery_np, "resistance-temp-table", &len);
if (!list || !len)
goto out_put_node;
goto out_ret_pointer;
info->resist_table_size = len / (2 * sizeof(__be32));
resist_table = info->resist_table = devm_kcalloc(&psy->dev,
......@@ -745,6 +755,10 @@ int power_supply_get_battery_info(struct power_supply *psy,
resist_table[index].resistance = be32_to_cpu(*list++);
}
out_ret_pointer:
/* Finally return the whole thing */
*info_out = info;
out_put_node:
of_node_put(battery_np);
return err;
......@@ -763,6 +777,8 @@ void power_supply_put_battery_info(struct power_supply *psy,
if (info->resist_table)
devm_kfree(&psy->dev, info->resist_table);
devm_kfree(&psy->dev, info);
}
EXPORT_SYMBOL_GPL(power_supply_put_battery_info);
......@@ -783,26 +799,25 @@ EXPORT_SYMBOL_GPL(power_supply_put_battery_info);
int power_supply_temp2resist_simple(struct power_supply_resistance_temp_table *table,
int table_len, int temp)
{
int i, resist;
int i, high, low;
for (i = 0; i < table_len; i++)
/* Break loop at table_len - 1 because that is the highest index */
for (i = 0; i < table_len - 1; i++)
if (temp > table[i].temp)
break;
if (i > 0 && i < table_len) {
int tmp;
tmp = (table[i - 1].resistance - table[i].resistance) *
(temp - table[i].temp);
tmp /= table[i - 1].temp - table[i].temp;
resist = tmp + table[i].resistance;
} else if (i == 0) {
resist = table[0].resistance;
} else {
resist = table[table_len - 1].resistance;
}
return resist;
/* 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(table[low].temp,
table[low].resistance,
table[high].temp,
table[high].resistance,
temp);
}
EXPORT_SYMBOL_GPL(power_supply_temp2resist_simple);
......@@ -821,24 +836,25 @@ EXPORT_SYMBOL_GPL(power_supply_temp2resist_simple);
int power_supply_ocv2cap_simple(struct power_supply_battery_ocv_table *table,
int table_len, int ocv)
{
int i, cap, tmp;
int i, high, low;
for (i = 0; i < table_len; i++)
/* Break loop at table_len - 1 because that is the highest index */
for (i = 0; i < table_len - 1; i++)
if (ocv > table[i].ocv)
break;
if (i > 0 && i < table_len) {
tmp = (table[i - 1].capacity - table[i].capacity) *
(ocv - table[i].ocv);
tmp /= table[i - 1].ocv - table[i].ocv;
cap = tmp + table[i].capacity;
} else if (i == 0) {
cap = table[0].capacity;
} else {
cap = table[table_len - 1].capacity;
}
return cap;
/* The library function will deal with high == low */
if ((i == 0) || (i == (table_len - 1)))
high = i - 1;
else
high = i; /* i.e. i == 0 */
low = i;
return fixp_linear_interpolate(table[low].ocv,
table[low].capacity,
table[high].ocv,
table[high].capacity,
ocv);
}
EXPORT_SYMBOL_GPL(power_supply_ocv2cap_simple);
......
......@@ -106,6 +106,7 @@ static const char * const POWER_SUPPLY_HEALTH_TEXT[] = {
[POWER_SUPPLY_HEALTH_WARM] = "Warm",
[POWER_SUPPLY_HEALTH_COOL] = "Cool",
[POWER_SUPPLY_HEALTH_HOT] = "Hot",
[POWER_SUPPLY_HEALTH_NO_BATTERY] = "No battery",
};
static const char * const POWER_SUPPLY_TECHNOLOGY_TEXT[] = {
......
......@@ -863,8 +863,8 @@ static int smbb_charger_probe(struct platform_device *pdev)
}
chg->revision += 1;
if (chg->revision != 2 && chg->revision != 3) {
dev_err(&pdev->dev, "v1 hardware not supported\n");
if (chg->revision != 1 && chg->revision != 2 && chg->revision != 3) {
dev_err(&pdev->dev, "v%d hardware not supported\n", chg->revision);
return -ENODEV;
}
dev_info(&pdev->dev, "Initializing SMBB rev %u", chg->revision);
......@@ -1012,6 +1012,7 @@ static int smbb_charger_remove(struct platform_device *pdev)
}
static const struct of_device_id smbb_charger_id_table[] = {
{ .compatible = "qcom,pm8226-charger" },
{ .compatible = "qcom,pm8941-charger" },
{ }
};
......
......@@ -368,7 +368,7 @@ static int sc2731_charger_usb_change(struct notifier_block *nb,
static int sc2731_charger_hw_init(struct sc2731_charger_info *info)
{
struct power_supply_battery_info bat_info = { };
struct power_supply_battery_info *bat_info;
u32 term_currrent, term_voltage, cur_val, vol_val;
int ret;
......@@ -390,7 +390,7 @@ static int sc2731_charger_hw_init(struct sc2731_charger_info *info)
cur_val = 0x2;
vol_val = 0x1;
} else {
term_currrent = bat_info.charge_term_current_ua / 1000;
term_currrent = bat_info->charge_term_current_ua / 1000;
if (term_currrent <= 90)
cur_val = 0;
......@@ -399,7 +399,7 @@ static int sc2731_charger_hw_init(struct sc2731_charger_info *info)
else
cur_val = ((term_currrent - 90) / 25) + 1;
term_voltage = bat_info.constant_charge_voltage_max_uv / 1000;
term_voltage = bat_info->constant_charge_voltage_max_uv / 1000;
if (term_voltage > 4500)
term_voltage = 4500;
......@@ -409,7 +409,7 @@ static int sc2731_charger_hw_init(struct sc2731_charger_info *info)
else
vol_val = 0;
power_supply_put_battery_info(info->psy_usb, &bat_info);
power_supply_put_battery_info(info->psy_usb, bat_info);
}
/* Set charge termination current */
......
......@@ -998,7 +998,7 @@ static int sc27xx_fgu_calibration(struct sc27xx_fgu_data *data)
static int sc27xx_fgu_hw_init(struct sc27xx_fgu_data *data)
{
struct power_supply_battery_info info = { };
struct power_supply_battery_info *info;
struct power_supply_battery_ocv_table *table;
int ret, delta_clbcnt, alarm_adc;
......@@ -1008,16 +1008,16 @@ static int sc27xx_fgu_hw_init(struct sc27xx_fgu_data *data)
return ret;
}
data->total_cap = info.charge_full_design_uah / 1000;
data->max_volt = info.constant_charge_voltage_max_uv / 1000;
data->internal_resist = info.factory_internal_resistance_uohm / 1000;
data->min_volt = info.voltage_min_design_uv;
data->total_cap = info->charge_full_design_uah / 1000;
data->max_volt = info->constant_charge_voltage_max_uv / 1000;
data->internal_resist = info->factory_internal_resistance_uohm / 1000;
data->min_volt = info->voltage_min_design_uv;
/*
* For SC27XX fuel gauge device, we only use one ocv-capacity
* table in normal temperature 20 Celsius.
*/
table = power_supply_find_ocv2cap_table(&info, 20, &data->table_len);
table = power_supply_find_ocv2cap_table(info, 20, &data->table_len);
if (!table)
return -EINVAL;
......@@ -1025,7 +1025,7 @@ static int sc27xx_fgu_hw_init(struct sc27xx_fgu_data *data)
data->table_len * sizeof(*table),
GFP_KERNEL);
if (!data->cap_table) {
power_supply_put_battery_info(data->battery, &info);
power_supply_put_battery_info(data->battery, info);
return -ENOMEM;
}
......@@ -1035,19 +1035,19 @@ static int sc27xx_fgu_hw_init(struct sc27xx_fgu_data *data)
if (!data->alarm_cap)
data->alarm_cap += 1;
data->resist_table_len = info.resist_table_size;
data->resist_table_len = info->resist_table_size;
if (data->resist_table_len > 0) {
data->resist_table = devm_kmemdup(data->dev, info.resist_table,
data->resist_table = devm_kmemdup(data->dev, info->resist_table,
data->resist_table_len *
sizeof(struct power_supply_resistance_temp_table),
GFP_KERNEL);
if (!data->resist_table) {
power_supply_put_battery_info(data->battery, &info);
power_supply_put_battery_info(data->battery, info);
return -ENOMEM;
}
}
power_supply_put_battery_info(data->battery, &info);
power_supply_put_battery_info(data->battery, info);
ret = sc27xx_fgu_calibration(data);
if (ret)
......
......@@ -1281,7 +1281,7 @@ static void smb347_dt_parse_dev_info(struct smb347_charger *smb)
static int smb347_get_battery_info(struct smb347_charger *smb)
{
struct power_supply_battery_info info = {};
struct power_supply_battery_info *info;
struct power_supply *supply;
int err;
......@@ -1296,29 +1296,29 @@ static int smb347_get_battery_info(struct smb347_charger *smb)
if (err)
return err;
if (info.constant_charge_current_max_ua != -EINVAL)
smb->max_charge_current = info.constant_charge_current_max_ua;
if (info->constant_charge_current_max_ua != -EINVAL)
smb->max_charge_current = info->constant_charge_current_max_ua;
if (info.constant_charge_voltage_max_uv != -EINVAL)
smb->max_charge_voltage = info.constant_charge_voltage_max_uv;
if (info->constant_charge_voltage_max_uv != -EINVAL)
smb->max_charge_voltage = info->constant_charge_voltage_max_uv;
if (info.precharge_current_ua != -EINVAL)
smb->pre_charge_current = info.precharge_current_ua;
if (info->precharge_current_ua != -EINVAL)
smb->pre_charge_current = info->precharge_current_ua;
if (info.charge_term_current_ua != -EINVAL)
smb->termination_current = info.charge_term_current_ua;
if (info->charge_term_current_ua != -EINVAL)
smb->termination_current = info->charge_term_current_ua;
if (info.temp_alert_min != INT_MIN)
smb->soft_cold_temp_limit = info.temp_alert_min;
if (info->temp_alert_min != INT_MIN)
smb->soft_cold_temp_limit = info->temp_alert_min;
if (info.temp_alert_max != INT_MAX)
smb->soft_hot_temp_limit = info.temp_alert_max;
if (info->temp_alert_max != INT_MAX)
smb->soft_hot_temp_limit = info->temp_alert_max;
if (info.temp_min != INT_MIN)
smb->hard_cold_temp_limit = info.temp_min;
if (info->temp_min != INT_MIN)
smb->hard_cold_temp_limit = info->temp_min;
if (info.temp_max != INT_MAX)
smb->hard_hot_temp_limit = info.temp_max;
if (info->temp_max != INT_MAX)
smb->hard_hot_temp_limit = info->temp_max;
/* Suspend when battery temperature is outside hard limits */
if (smb->hard_cold_temp_limit != SMB3XX_TEMP_USE_DEFAULT ||
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment