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

Configure Feed

Select the types of activity you want to include in your feed.

power: supply: core: Refactor power_supply_set_input_current_limit_from_supplier()

Some (USB) charger ICs have variants with USB D+ and D- pins to do their
own builtin charger-type detection, like e.g. the bq24190 and bq25890 and
also variants which lack this functionality, e.g. the bq24192 and bq25892.

In case the charger-type; and thus the input-current-limit detection is
done outside the charger IC then we need some way to communicate this to
the charger IC. In the past extcon was used for this, but if the external
detection does e.g. full USB PD negotiation then the extcon cable-types do
not convey enough information.

For these setups it was decided to model the external charging "brick"
and the parameters negotiated with it as a power_supply class-device
itself; and power_supply_set_input_current_limit_from_supplier() was
introduced to allow drivers to get the input-current-limit this way.

But in some cases psy drivers may want to know other properties, e.g. the
bq25892 can do "quick-charge" negotiation by pulsing its current draw,
but this should only be done if the usb_type psy-property of its supplier
is set to DCP (and device-properties indicate the board allows higher
voltages).

Instead of adding extra helper functions for each property which
a psy-driver wants to query from its supplier, refactor
power_supply_set_input_current_limit_from_supplier() into a
more generic power_supply_get_property_from_supplier() function.

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>

authored by

Hans de Goede and committed by
Sebastian Reichel
2220af8c e783362e

+44 -30
+11 -1
drivers/power/supply/bq24190_charger.c
··· 1206 1206 struct bq24190_dev_info *bdi = 1207 1207 container_of(work, struct bq24190_dev_info, 1208 1208 input_current_limit_work.work); 1209 + union power_supply_propval val; 1210 + int ret; 1209 1211 1210 - power_supply_set_input_current_limit_from_supplier(bdi->charger); 1212 + ret = power_supply_get_property_from_supplier(bdi->charger, 1213 + POWER_SUPPLY_PROP_CURRENT_MAX, 1214 + &val); 1215 + if (ret) 1216 + return; 1217 + 1218 + bq24190_charger_set_property(bdi->charger, 1219 + POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, 1220 + &val); 1211 1221 } 1212 1222 1213 1223 /* Sync the input-current-limit with our parent supply (if we have one) */
+30 -27
drivers/power/supply/power_supply_core.c
··· 376 376 } 377 377 EXPORT_SYMBOL_GPL(power_supply_is_system_supplied); 378 378 379 - static int __power_supply_get_supplier_max_current(struct device *dev, 380 - void *data) 379 + struct psy_get_supplier_prop_data { 380 + struct power_supply *psy; 381 + enum power_supply_property psp; 382 + union power_supply_propval *val; 383 + }; 384 + 385 + static int __power_supply_get_supplier_property(struct device *dev, void *_data) 381 386 { 382 - union power_supply_propval ret = {0,}; 383 387 struct power_supply *epsy = dev_get_drvdata(dev); 384 - struct power_supply *psy = data; 388 + struct psy_get_supplier_prop_data *data = _data; 385 389 386 - if (__power_supply_is_supplied_by(epsy, psy)) 387 - if (!epsy->desc->get_property(epsy, 388 - POWER_SUPPLY_PROP_CURRENT_MAX, 389 - &ret)) 390 - return ret.intval; 390 + if (__power_supply_is_supplied_by(epsy, data->psy)) 391 + if (!epsy->desc->get_property(epsy, data->psp, data->val)) 392 + return 1; /* Success */ 391 393 392 - return 0; 394 + return 0; /* Continue iterating */ 393 395 } 394 396 395 - int power_supply_set_input_current_limit_from_supplier(struct power_supply *psy) 397 + int power_supply_get_property_from_supplier(struct power_supply *psy, 398 + enum power_supply_property psp, 399 + union power_supply_propval *val) 396 400 { 397 - union power_supply_propval val = {0,}; 398 - int curr; 399 - 400 - if (!psy->desc->set_property) 401 - return -EINVAL; 401 + struct psy_get_supplier_prop_data data = { 402 + .psy = psy, 403 + .psp = psp, 404 + .val = val, 405 + }; 406 + int ret; 402 407 403 408 /* 404 409 * This function is not intended for use with a supply with multiple 405 - * suppliers, we simply pick the first supply to report a non 0 406 - * max-current. 410 + * suppliers, we simply pick the first supply to report the psp. 407 411 */ 408 - curr = class_for_each_device(power_supply_class, NULL, psy, 409 - __power_supply_get_supplier_max_current); 410 - if (curr <= 0) 411 - return (curr == 0) ? -ENODEV : curr; 412 + ret = class_for_each_device(power_supply_class, NULL, &data, 413 + __power_supply_get_supplier_property); 414 + if (ret < 0) 415 + return ret; 416 + if (ret == 0) 417 + return -ENODEV; 412 418 413 - val.intval = curr; 414 - 415 - return psy->desc->set_property(psy, 416 - POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, &val); 419 + return 0; 417 420 } 418 - EXPORT_SYMBOL_GPL(power_supply_set_input_current_limit_from_supplier); 421 + EXPORT_SYMBOL_GPL(power_supply_get_property_from_supplier); 419 422 420 423 int power_supply_set_battery_charged(struct power_supply *psy) 421 424 {
+3 -2
include/linux/power_supply.h
··· 597 597 int table_len, int temp); 598 598 extern void power_supply_changed(struct power_supply *psy); 599 599 extern int power_supply_am_i_supplied(struct power_supply *psy); 600 - extern int power_supply_set_input_current_limit_from_supplier( 601 - struct power_supply *psy); 600 + int power_supply_get_property_from_supplier(struct power_supply *psy, 601 + enum power_supply_property psp, 602 + union power_supply_propval *val); 602 603 extern int power_supply_set_battery_charged(struct power_supply *psy); 603 604 604 605 #ifdef CONFIG_POWER_SUPPLY