Skip to content

Commit d54bf87

Browse files
jwrdegoedesre
authored andcommitted
power: supply: bq25890: Add support for having a secondary charger IC
Some devices, such as the Lenovo Yoga Tab 3 Pro (YT3-X90F) have multiple batteries with a separate bq25890 charger for each battery. This requires some coordination between the chargers specifically the main charger needs to put the secondary charger in Hi-Z mode when: 1. Enabling its 5V boost (OTG) output to power an external USB device, to avoid the secondary charger IC seeing this as external Vbus and then trying to charge the secondary battery from this. 2. Talking the Pump Express protocol to increase the external Vbus voltage. Having the secondary charger drawing current when the main charger is trying to talk the Pump Express protocol results in the external Vbus voltage not being raised. Add a new "linux,secondary-charger-name" string device-property, which can be set to the power_supply class device's name of the secondary charger when there is a secondary charger; and make the Vbus regulator and Pump Express code put the secondary charger in Hi-Z mode when necessary. So far this new property is only used on x86/ACPI (non devicetree) devs, IOW it is not used in actual devicetree files. The devicetree-bindings maintainers have requested properties like these to not be added to the devicetree-bindings, so the new property is deliberately not added to the existing devicetree-bindings. Reviewed-by: Marek Vasut <marex@denx.de> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
1 parent 4e9498b commit d54bf87

1 file changed

Lines changed: 44 additions & 1 deletion

File tree

drivers/power/supply/bq25890_charger.c

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ struct bq25890_device {
108108
struct i2c_client *client;
109109
struct device *dev;
110110
struct power_supply *charger;
111+
struct power_supply *secondary_chrg;
111112
struct power_supply_desc desc;
112113
char name[28]; /* "bq25890-charger-%d" */
113114
int id;
@@ -1042,10 +1043,17 @@ static void bq25890_pump_express_work(struct work_struct *data)
10421043
{
10431044
struct bq25890_device *bq =
10441045
container_of(data, struct bq25890_device, pump_express_work.work);
1046+
union power_supply_propval value;
10451047
int voltage, i, ret;
10461048

10471049
dev_dbg(bq->dev, "Start to request input voltage increasing\n");
10481050

1051+
/* If there is a second charger put in Hi-Z mode */
1052+
if (bq->secondary_chrg) {
1053+
value.intval = 0;
1054+
power_supply_set_property(bq->secondary_chrg, POWER_SUPPLY_PROP_ONLINE, &value);
1055+
}
1056+
10491057
/* Enable current pulse voltage control protocol */
10501058
ret = bq25890_field_write(bq, F_PUMPX_EN, 1);
10511059
if (ret < 0)
@@ -1077,6 +1085,11 @@ static void bq25890_pump_express_work(struct work_struct *data)
10771085

10781086
bq25890_field_write(bq, F_PUMPX_EN, 0);
10791087

1088+
if (bq->secondary_chrg) {
1089+
value.intval = 1;
1090+
power_supply_set_property(bq->secondary_chrg, POWER_SUPPLY_PROP_ONLINE, &value);
1091+
}
1092+
10801093
dev_info(bq->dev, "Hi-voltage charging requested, input voltage is %d mV\n",
10811094
voltage);
10821095

@@ -1123,15 +1136,37 @@ static int bq25890_usb_notifier(struct notifier_block *nb, unsigned long val,
11231136
static int bq25890_vbus_enable(struct regulator_dev *rdev)
11241137
{
11251138
struct bq25890_device *bq = rdev_get_drvdata(rdev);
1139+
union power_supply_propval val = {
1140+
.intval = 0,
1141+
};
1142+
1143+
/*
1144+
* When enabling 5V boost / Vbus output, we need to put the secondary
1145+
* charger in Hi-Z mode to avoid it trying to charge the secondary
1146+
* battery from the 5V boost output.
1147+
*/
1148+
if (bq->secondary_chrg)
1149+
power_supply_set_property(bq->secondary_chrg, POWER_SUPPLY_PROP_ONLINE, &val);
11261150

11271151
return bq25890_set_otg_cfg(bq, 1);
11281152
}
11291153

11301154
static int bq25890_vbus_disable(struct regulator_dev *rdev)
11311155
{
11321156
struct bq25890_device *bq = rdev_get_drvdata(rdev);
1157+
union power_supply_propval val = {
1158+
.intval = 1,
1159+
};
1160+
int ret;
1161+
1162+
ret = bq25890_set_otg_cfg(bq, 0);
1163+
if (ret)
1164+
return ret;
11331165

1134-
return bq25890_set_otg_cfg(bq, 0);
1166+
if (bq->secondary_chrg)
1167+
power_supply_set_property(bq->secondary_chrg, POWER_SUPPLY_PROP_ONLINE, &val);
1168+
1169+
return 0;
11351170
}
11361171

11371172
static int bq25890_vbus_is_enabled(struct regulator_dev *rdev)
@@ -1342,6 +1377,14 @@ static int bq25890_fw_probe(struct bq25890_device *bq)
13421377
{
13431378
int ret;
13441379
struct bq25890_init_data *init = &bq->init_data;
1380+
const char *str;
1381+
1382+
ret = device_property_read_string(bq->dev, "linux,secondary-charger-name", &str);
1383+
if (ret == 0) {
1384+
bq->secondary_chrg = power_supply_get_by_name(str);
1385+
if (!bq->secondary_chrg)
1386+
return -EPROBE_DEFER;
1387+
}
13451388

13461389
/* Optional, left at 0 if property is not present */
13471390
device_property_read_u32(bq->dev, "linux,pump-express-vbus-max",

0 commit comments

Comments
 (0)