Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

power: supply: bq25890: Add new linux,iinlim-percentage property

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 the maximum current the external power-supply can deliver
to be divided over the chargers. The Android vendor kernel shipped
on the YT3-X90F divides this current with a 40/60 percent split so that
batteries are done charging at approx. the same time if both were fully
empty at the start.

Add support for a new "linux,iinlim-percentage" percentage property which
can be set to indicate that a bq25890 charger should only use that
percentage of the external power-supply's maximum current.

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.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Marek Vasut <marex@denx.de>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>

authored by

Hans de Goede and committed by
Sebastian Reichel
6adaa9a4 d54bf877

+28 -3
+28 -3
drivers/power/supply/bq25890_charger.c
··· 126 126 bool read_back_init_data; 127 127 bool force_hiz; 128 128 u32 pump_express_vbus_max; 129 + u32 iinlim_percentage; 129 130 enum bq25890_chip_version chip_version; 130 131 struct bq25890_init_data init_data; 131 132 struct bq25890_state state; ··· 728 727 } 729 728 } 730 729 730 + /* 731 + * If there are multiple chargers the maximum current the external power-supply 732 + * can deliver needs to be divided over the chargers. This is done according 733 + * to the bq->iinlim_percentage setting. 734 + */ 735 + static int bq25890_charger_get_scaled_iinlim_regval(struct bq25890_device *bq, 736 + int iinlim_ua) 737 + { 738 + iinlim_ua = iinlim_ua * bq->iinlim_percentage / 100; 739 + return bq25890_find_idx(iinlim_ua, TBL_IINLIM); 740 + } 741 + 731 742 /* On the BQ25892 try to get charger-type info from our supplier */ 732 743 static void bq25890_charger_external_power_changed(struct power_supply *psy) 733 744 { ··· 758 745 759 746 switch (val.intval) { 760 747 case POWER_SUPPLY_USB_TYPE_DCP: 761 - input_current_limit = bq25890_find_idx(2000000, TBL_IINLIM); 748 + input_current_limit = bq25890_charger_get_scaled_iinlim_regval(bq, 2000000); 762 749 if (bq->pump_express_vbus_max) { 763 750 queue_delayed_work(system_power_efficient_wq, 764 751 &bq->pump_express_work, ··· 767 754 break; 768 755 case POWER_SUPPLY_USB_TYPE_CDP: 769 756 case POWER_SUPPLY_USB_TYPE_ACA: 770 - input_current_limit = bq25890_find_idx(1500000, TBL_IINLIM); 757 + input_current_limit = bq25890_charger_get_scaled_iinlim_regval(bq, 1500000); 771 758 break; 772 759 case POWER_SUPPLY_USB_TYPE_SDP: 773 760 default: 774 - input_current_limit = bq25890_find_idx(500000, TBL_IINLIM); 761 + input_current_limit = bq25890_charger_get_scaled_iinlim_regval(bq, 500000); 775 762 } 776 763 777 764 bq25890_field_write(bq, F_IINLIM, input_current_limit); ··· 1391 1378 int ret; 1392 1379 struct bq25890_init_data *init = &bq->init_data; 1393 1380 const char *str; 1381 + u32 val; 1394 1382 1395 1383 ret = device_property_read_string(bq->dev, "linux,secondary-charger-name", &str); 1396 1384 if (ret == 0) { ··· 1403 1389 /* Optional, left at 0 if property is not present */ 1404 1390 device_property_read_u32(bq->dev, "linux,pump-express-vbus-max", 1405 1391 &bq->pump_express_vbus_max); 1392 + 1393 + ret = device_property_read_u32(bq->dev, "linux,iinlim-percentage", &val); 1394 + if (ret == 0) { 1395 + if (val > 100) { 1396 + dev_err(bq->dev, "Error linux,iinlim-percentage %u > 100\n", val); 1397 + return -EINVAL; 1398 + } 1399 + bq->iinlim_percentage = val; 1400 + } else { 1401 + bq->iinlim_percentage = 100; 1402 + } 1406 1403 1407 1404 bq->skip_reset = device_property_read_bool(bq->dev, "linux,skip-reset"); 1408 1405 bq->read_back_init_data = device_property_read_bool(bq->dev,