Skip to content

Commit 37fe599

Browse files
author
Al Stone
committed
power: supply: ab8500: Standardize BTI resistance
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2071846 Tested: This is one of a series of patch sets to enable Arm SystemReady IR support in the kernel for NXP i.MX8 platforms. This set updates the power subsystem. This set has been tested via simple boot tests and the CI loop. Conflicts: drivers/power/supply/ab8500-bm.h drivers/power/supply/ab8500_bmdata.c drivers/power/supply/ab8500_btemp.c drivers/power/supply/ab8500_fg.c This is not a supported device so these parts of the patch have been dropped. commit 1f918e0 Author: Linus Walleij <linus.walleij@linaro.org> Date: Sat Feb 26 00:27:57 2022 +0100 power: supply: ab8500: Standardize BTI resistance The Battery Type Indicator (BTI) resistor is a resistor mounted between a special terminal on the battery and ground. By sending a fixed current (such as 7mA) through this resistor and measuring the voltage over it, the resistance can be determined, and this verifies the battery type. Typical side view of the battery: o o o GND BTI +3.8V Typical example of the electrical layout: +3.8 V BTI | | | + | _______ [ ] 7kOhm ___ | | | | | GND GND By verifying this resistance before attempting to charge the battery we add an additional level of security. In some systems this is used for plug-and-play of batteries with different capacity. In other cases, this is merely used to verify that the right type of battery is connected, if several batteries have the same physical shape and can be plugged into the same slot. Sometimes this is just a surplus security mechanism. Nokia and Samsung among many other vendors are known to use these BTI resistors. Add the BTI properties to struct power_supply_battery_info and switch the AB8500 charger code over to using it. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com> (cherry picked from commit 1f918e0) Signed-off-by: Al Stone <ahs3@redhat.com>
1 parent 92695b7 commit 37fe599

File tree

4 files changed

+44
-10
lines changed

4 files changed

+44
-10
lines changed

drivers/power/supply/ab8500_btemp.c

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
#include "ab8500-bm.h"
3232

3333
#define VTVOUT_V 1800
34-
3534
#define BTEMP_THERMAL_LOW_LIMIT -10
3635
#define BTEMP_THERMAL_MED_LIMIT 0
3736
#define BTEMP_THERMAL_HIGH_LIMIT_52 52
@@ -135,7 +134,6 @@ static int ab8500_btemp_batctrl_volt_to_res(struct ab8500_btemp *di,
135134
int v_batctrl, int inst_curr)
136135
{
137136
int rbs;
138-
139137
if (is_ab8500_1p1_or_earlier(di->parent)) {
140138
/*
141139
* For ABB cut1.0 and 1.1 BAT_CTRL is internally
@@ -153,10 +151,10 @@ static int ab8500_btemp_batctrl_volt_to_res(struct ab8500_btemp *di,
153151
- di->bm->gnd_lift_resistance * inst_curr)
154152
/ di->curr_source;
155153
} else {
156-
/*
157-
* BAT_CTRL is internally
158-
* connected to 1.8V through a 80k resistor
159-
*/
154+
/*
155+
* BAT_CTRL is internally
156+
* connected to 1.8V through a 80k resistor
157+
*/
160158
rbs = (80000 * (v_batctrl)) / (1800 - v_batctrl);
161159
}
162160

@@ -358,7 +356,6 @@ static int ab8500_btemp_get_batctrl_res(struct ab8500_btemp *di)
358356
dev_err(di->dev, "%s curr source enabled failed\n", __func__);
359357
return ret;
360358
}
361-
362359
if (!di->fg)
363360
di->fg = ab8500_fg_get();
364361
if (!di->fg) {
@@ -399,7 +396,6 @@ static int ab8500_btemp_get_batctrl_res(struct ab8500_btemp *di)
399396
dev_err(di->dev, "%s curr source disable failed\n", __func__);
400397
return ret;
401398
}
402-
403399
dev_dbg(di->dev, "%s batctrl: %d res: %d inst_curr: %d samples: %d\n",
404400
__func__, batctrl, res, inst_curr, i);
405401

@@ -574,6 +570,7 @@ static void ab8500_btemp_periodic_work(struct work_struct *work)
574570
}
575571

576572
bat_temp = ab8500_btemp_measure_temp(di);
573+
577574
/*
578575
* Filter battery temperature.
579576
* Allow direct updates on temperature only if two samples result in

drivers/power/supply/ab8500_fg.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1077,7 +1077,7 @@ static int ab8500_fg_calc_cap_discharge_voltage(struct ab8500_fg *di, bool comp)
10771077
int permille, mah;
10781078

10791079
if (comp)
1080-
permille = ab8500_fg_load_comp_volt_to_capacity(di);
1080+
permille = ab8500_fg_load_comp_volt_to_capacity(di);
10811081
else
10821082
permille = ab8500_fg_uncomp_volt_to_capacity(di);
10831083

drivers/power/supply/power_supply_core.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,9 @@ int power_supply_get_battery_info(struct power_supply *psy,
607607
info->temp_min = INT_MIN;
608608
info->temp_max = INT_MAX;
609609
info->factory_internal_resistance_uohm = -EINVAL;
610-
info->resist_table = NULL;
610+
info->resist_table = NULL;
611+
info->bti_resistance_ohm = -EINVAL;
612+
info->bti_resistance_tolerance = -EINVAL;
611613

612614
for (index = 0; index < POWER_SUPPLY_OCV_TEMP_MAX; index++) {
613615
info->ocv_table[index] = NULL;
@@ -938,6 +940,28 @@ int power_supply_batinfo_ocv2cap(struct power_supply_battery_info *info,
938940
}
939941
EXPORT_SYMBOL_GPL(power_supply_batinfo_ocv2cap);
940942

943+
bool power_supply_battery_bti_in_range(struct power_supply_battery_info *info,
944+
int resistance)
945+
{
946+
int low, high;
947+
948+
/* Nothing like this can be checked */
949+
if (info->bti_resistance_ohm <= 0)
950+
return false;
951+
952+
/* This will be extremely strict and unlikely to work */
953+
if (info->bti_resistance_tolerance <= 0)
954+
return (info->bti_resistance_ohm == resistance);
955+
956+
low = info->bti_resistance_ohm -
957+
(info->bti_resistance_ohm * info->bti_resistance_tolerance) / 100;
958+
high = info->bti_resistance_ohm +
959+
(info->bti_resistance_ohm * info->bti_resistance_tolerance) / 100;
960+
961+
return ((resistance >= low) && (resistance <= high));
962+
}
963+
EXPORT_SYMBOL_GPL(power_supply_battery_bti_in_range);
964+
941965
int power_supply_get_property(struct power_supply *psy,
942966
enum power_supply_property psp,
943967
union power_supply_propval *val)

include/linux/power_supply.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,14 @@ struct power_supply_maintenance_charge_table {
498498
* by temperature: highest temperature with lowest resistance first, lowest
499499
* temperature with highest resistance last.
500500
* @resist_table_size: the number of items in the resist_table.
501+
* @bti_resistance_ohm: The Battery Type Indicator (BIT) nominal resistance
502+
* in ohms for this battery, if an identification resistor is mounted
503+
* between a third battery terminal and ground. This scheme is used by a lot
504+
* of mobile device batteries.
505+
* @bti_resistance_tolerance: The tolerance in percent of the BTI resistance,
506+
* for example 10 for +/- 10%, if the bti_resistance is set to 7000 and the
507+
* tolerance is 10% we will detect a proper battery if the BTI resistance
508+
* is between 6300 and 7700 Ohm.
501509
*
502510
* This is the recommended struct to manage static battery parameters,
503511
* populated by power_supply_get_battery_info(). Most platform drivers should
@@ -624,6 +632,8 @@ struct power_supply_battery_info {
624632
int ocv_table_size[POWER_SUPPLY_OCV_TEMP_MAX];
625633
struct power_supply_resistance_temp_table *resist_table;
626634
int resist_table_size;
635+
int bti_resistance_ohm;
636+
int bti_resistance_tolerance;
627637
};
628638

629639
extern struct atomic_notifier_head power_supply_notifier;
@@ -667,6 +677,8 @@ power_supply_temp2resist_simple(struct power_supply_resistance_temp_table *table
667677
int table_len, int temp);
668678
extern struct power_supply_maintenance_charge_table *
669679
power_supply_get_maintenance_charging_setting(struct power_supply_battery_info *info, int index);
680+
extern bool power_supply_battery_bti_in_range(struct power_supply_battery_info *info,
681+
int resistance);
670682
extern void power_supply_changed(struct power_supply *psy);
671683
extern int power_supply_am_i_supplied(struct power_supply *psy);
672684
int power_supply_get_property_from_supplier(struct power_supply *psy,
@@ -684,6 +696,7 @@ power_supply_supports_maintenance_charging(struct power_supply_battery_info *inf
684696
return (mt != NULL);
685697
}
686698

699+
687700
#ifdef CONFIG_POWER_SUPPLY
688701
extern int power_supply_is_system_supplied(void);
689702
#else

0 commit comments

Comments
 (0)