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.

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

Pull power supply and reset updates from Sebastian Reichel:
"Core:
- add HWMON compat layer
- new properties:
- input power limit
- input voltage limit

Drivers:
- qcom-pon: add gen2 support
- new driver for storing reboot move in NVMEM
- new driver for Wilco EC charger configuration
- simplify getting the adapter of a client"

* tag 'for-v5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply:
power: reset: nvmem-reboot-mode: add CONFIG_OF dependency
power_supply: wilco_ec: Add charging config driver
power: supply: cros: allow to set input voltage and current limit
power: supply: add input power and voltage limit properties
power: supply: fix semicolon.cocci warnings
power: reset: nvmem-reboot-mode: use NVMEM as reboot mode write interface
dt-bindings: power: reset: add document for NVMEM based reboot-mode
reset: qcom-pon: Add support for gen2 pon
dt-bindings: power: reset: qcom: Add qcom,pm8998-pon compatibility line
power: supply: Add HWMON compatibility layer
power: supply: sbs-manager: simplify getting the adapter of a client
power: supply: rt9455_charger: simplify getting the adapter of a client
power: supply: rt5033_battery: simplify getting the adapter of a client
power: supply: max17042_battery: simplify getting the adapter of a client
power: supply: max17040_battery: simplify getting the adapter of a client
power: supply: max14656_charger_detector: simplify getting the adapter of a client
power: supply: bq25890_charger: simplify getting the adapter of a client
power: supply: bq24257_charger: simplify getting the adapter of a client
power: supply: bq24190_charger: simplify getting the adapter of a client

+908 -13
+32
Documentation/ABI/testing/sysfs-class-power
··· 376 376 supply. Normally this is configured based on the type of 377 377 connection made (e.g. A configured SDP should output a maximum 378 378 of 500mA so the input current limit is set to the same value). 379 + Use preferably input_power_limit, and for problems that can be 380 + solved using power limit use input_current_limit. 379 381 380 382 Access: Read, Write 381 383 Valid values: Represented in microamps 384 + 385 + What: /sys/class/power_supply/<supply_name>/input_voltage_limit 386 + Date: May 2019 387 + Contact: linux-pm@vger.kernel.org 388 + Description: 389 + This entry configures the incoming VBUS voltage limit currently 390 + set in the supply. Normally this is configured based on 391 + system-level knowledge or user input (e.g. This is part of the 392 + Pixel C's thermal management strategy to effectively limit the 393 + input power to 5V when the screen is on to meet Google's skin 394 + temperature targets). Note that this feature should not be 395 + used for safety critical things. 396 + Use preferably input_power_limit, and for problems that can be 397 + solved using power limit use input_voltage_limit. 398 + 399 + Access: Read, Write 400 + Valid values: Represented in microvolts 401 + 402 + What: /sys/class/power_supply/<supply_name>/input_power_limit 403 + Date: May 2019 404 + Contact: linux-pm@vger.kernel.org 405 + Description: 406 + This entry configures the incoming power limit currently set 407 + in the supply. Normally this is configured based on 408 + system-level knowledge or user input. Use preferably this 409 + feature to limit the incoming power and use current/voltage 410 + limit only for problems that can be solved using power limit. 411 + 412 + Access: Read, Write 413 + Valid values: Represented in microwatts 382 414 383 415 What: /sys/class/power_supply/<supply_name>/online, 384 416 Date: May 2007
+30
Documentation/ABI/testing/sysfs-class-power-wilco
··· 1 + What: /sys/class/power_supply/wilco-charger/charge_type 2 + Date: April 2019 3 + KernelVersion: 5.2 4 + Description: 5 + What charging algorithm to use: 6 + 7 + Standard: Fully charges battery at a standard rate. 8 + Adaptive: Battery settings adaptively optimized based on 9 + typical battery usage pattern. 10 + Fast: Battery charges over a shorter period. 11 + Trickle: Extends battery lifespan, intended for users who 12 + primarily use their Chromebook while connected to AC. 13 + Custom: A low and high threshold percentage is specified. 14 + Charging begins when level drops below 15 + charge_control_start_threshold, and ceases when 16 + level is above charge_control_end_threshold. 17 + 18 + What: /sys/class/power_supply/wilco-charger/charge_control_start_threshold 19 + Date: April 2019 20 + KernelVersion: 5.2 21 + Description: 22 + Used when charge_type="Custom", as described above. Measured in 23 + percentages. The valid range is [50, 95]. 24 + 25 + What: /sys/class/power_supply/wilco-charger/charge_control_end_threshold 26 + Date: April 2019 27 + KernelVersion: 5.2 28 + Description: 29 + Used when charge_type="Custom", as described above. Measured in 30 + percentages. The valid range is [55, 100].
+26
Documentation/devicetree/bindings/power/reset/nvmem-reboot-mode.txt
··· 1 + NVMEM reboot mode driver 2 + 3 + This driver gets reboot mode magic value from reboot-mode driver 4 + and stores it in a NVMEM cell named "reboot-mode". Then the bootloader 5 + can read it and take different action according to the magic 6 + value stored. 7 + 8 + Required properties: 9 + - compatible: should be "nvmem-reboot-mode". 10 + - nvmem-cells: A phandle to the reboot mode provided by a nvmem device. 11 + - nvmem-cell-names: Should be "reboot-mode". 12 + 13 + The rest of the properties should follow the generic reboot-mode description 14 + found in reboot-mode.txt 15 + 16 + Example: 17 + reboot-mode { 18 + compatible = "nvmem-reboot-mode"; 19 + nvmem-cells = <&reboot_mode>; 20 + nvmem-cell-names = "reboot-mode"; 21 + 22 + mode-normal = <0xAAAA5501>; 23 + mode-bootloader = <0xBBBB5500>; 24 + mode-recovery = <0xCCCC5502>; 25 + mode-test = <0xDDDD5503>; 26 + };
+1
Documentation/devicetree/bindings/power/reset/qcom,pon.txt
··· 9 9 -compatible: Must be one of: 10 10 "qcom,pm8916-pon" 11 11 "qcom,pms405-pon" 12 + "qcom,pm8998-pon" 12 13 13 14 -reg: Specifies the physical address of the pon register 14 15
+6
Documentation/power/power_supply_class.rst
··· 165 165 INPUT_CURRENT_LIMIT 166 166 input current limit programmed by charger. Indicates 167 167 the current drawn from a charging source. 168 + INPUT_VOLTAGE_LIMIT 169 + input voltage limit programmed by charger. Indicates 170 + the voltage limit from a charging source. 171 + INPUT_POWER_LIMIT 172 + input power limit programmed by charger. Indicates 173 + the power limit from a charging source. 168 174 169 175 CHARGE_CONTROL_LIMIT 170 176 current charge control limit setting
+10
drivers/power/reset/Kconfig
··· 246 246 PMICs includes the SC2720, SC2721, SC2723, SC2730 247 247 and SC2731 chips. 248 248 249 + config NVMEM_REBOOT_MODE 250 + tristate "Generic NVMEM reboot mode driver" 251 + depends on OF 252 + select REBOOT_MODE 253 + help 254 + Say y here will enable reboot mode driver. This will 255 + get reboot mode arguments and store it in a NVMEM cell, 256 + then the bootloader can read it and take different 257 + action according to the mode. 258 + 249 259 endif 250 260
+1
drivers/power/reset/Makefile
··· 29 29 obj-$(CONFIG_REBOOT_MODE) += reboot-mode.o 30 30 obj-$(CONFIG_SYSCON_REBOOT_MODE) += syscon-reboot-mode.o 31 31 obj-$(CONFIG_POWER_RESET_SC27XX) += sc27xx-poweroff.o 32 + obj-$(CONFIG_NVMEM_REBOOT_MODE) += nvmem-reboot-mode.o
+76
drivers/power/reset/nvmem-reboot-mode.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Copyright (c) Vaisala Oyj. All rights reserved. 4 + */ 5 + 6 + #include <linux/init.h> 7 + #include <linux/module.h> 8 + #include <linux/kernel.h> 9 + #include <linux/of.h> 10 + #include <linux/nvmem-consumer.h> 11 + #include <linux/platform_device.h> 12 + #include <linux/reboot-mode.h> 13 + 14 + struct nvmem_reboot_mode { 15 + struct reboot_mode_driver reboot; 16 + struct nvmem_cell *cell; 17 + }; 18 + 19 + static int nvmem_reboot_mode_write(struct reboot_mode_driver *reboot, 20 + unsigned int magic) 21 + { 22 + int ret; 23 + struct nvmem_reboot_mode *nvmem_rbm; 24 + 25 + nvmem_rbm = container_of(reboot, struct nvmem_reboot_mode, reboot); 26 + 27 + ret = nvmem_cell_write(nvmem_rbm->cell, &magic, sizeof(magic)); 28 + if (ret < 0) 29 + dev_err(reboot->dev, "update reboot mode bits failed\n"); 30 + 31 + return ret; 32 + } 33 + 34 + static int nvmem_reboot_mode_probe(struct platform_device *pdev) 35 + { 36 + int ret; 37 + struct nvmem_reboot_mode *nvmem_rbm; 38 + 39 + nvmem_rbm = devm_kzalloc(&pdev->dev, sizeof(*nvmem_rbm), GFP_KERNEL); 40 + if (!nvmem_rbm) 41 + return -ENOMEM; 42 + 43 + nvmem_rbm->reboot.dev = &pdev->dev; 44 + nvmem_rbm->reboot.write = nvmem_reboot_mode_write; 45 + 46 + nvmem_rbm->cell = devm_nvmem_cell_get(&pdev->dev, "reboot-mode"); 47 + if (IS_ERR(nvmem_rbm->cell)) { 48 + dev_err(&pdev->dev, "failed to get the nvmem cell reboot-mode\n"); 49 + return PTR_ERR(nvmem_rbm->cell); 50 + } 51 + 52 + ret = devm_reboot_mode_register(&pdev->dev, &nvmem_rbm->reboot); 53 + if (ret) 54 + dev_err(&pdev->dev, "can't register reboot mode\n"); 55 + 56 + return ret; 57 + } 58 + 59 + static const struct of_device_id nvmem_reboot_mode_of_match[] = { 60 + { .compatible = "nvmem-reboot-mode" }, 61 + {} 62 + }; 63 + MODULE_DEVICE_TABLE(of, nvmem_reboot_mode_of_match); 64 + 65 + static struct platform_driver nvmem_reboot_mode_driver = { 66 + .probe = nvmem_reboot_mode_probe, 67 + .driver = { 68 + .name = "nvmem-reboot-mode", 69 + .of_match_table = nvmem_reboot_mode_of_match, 70 + }, 71 + }; 72 + module_platform_driver(nvmem_reboot_mode_driver); 73 + 74 + MODULE_AUTHOR("Nandor Han <nandor.han@vaisala.com>"); 75 + MODULE_DESCRIPTION("NVMEM reboot mode driver"); 76 + MODULE_LICENSE("GPL");
+9 -3
drivers/power/reset/qcom-pon.c
··· 14 14 15 15 #define PON_SOFT_RB_SPARE 0x8f 16 16 17 + #define GEN1_REASON_SHIFT 2 18 + #define GEN2_REASON_SHIFT 1 19 + 17 20 struct pm8916_pon { 18 21 struct device *dev; 19 22 struct regmap *regmap; 20 23 u32 baseaddr; 21 24 struct reboot_mode_driver reboot_mode; 25 + long reason_shift; 22 26 }; 23 27 24 28 static int pm8916_reboot_mode_write(struct reboot_mode_driver *reboot, ··· 34 30 35 31 ret = regmap_update_bits(pon->regmap, 36 32 pon->baseaddr + PON_SOFT_RB_SPARE, 37 - 0xfc, magic << 2); 33 + 0xfc, magic << pon->reason_shift); 38 34 if (ret < 0) 39 35 dev_err(pon->dev, "update reboot mode bits failed\n"); 40 36 ··· 64 60 return error; 65 61 66 62 pon->reboot_mode.dev = &pdev->dev; 63 + pon->reason_shift = (long)of_device_get_match_data(&pdev->dev); 67 64 pon->reboot_mode.write = pm8916_reboot_mode_write; 68 65 error = devm_reboot_mode_register(&pdev->dev, &pon->reboot_mode); 69 66 if (error) { ··· 78 73 } 79 74 80 75 static const struct of_device_id pm8916_pon_id_table[] = { 81 - { .compatible = "qcom,pm8916-pon" }, 82 - { .compatible = "qcom,pms405-pon" }, 76 + { .compatible = "qcom,pm8916-pon", .data = (void *)GEN1_REASON_SHIFT }, 77 + { .compatible = "qcom,pms405-pon", .data = (void *)GEN1_REASON_SHIFT }, 78 + { .compatible = "qcom,pm8998-pon", .data = (void *)GEN2_REASON_SHIFT }, 83 79 { } 84 80 }; 85 81 MODULE_DEVICE_TABLE(of, pm8916_pon_id_table);
+23
drivers/power/supply/Kconfig
··· 15 15 Say Y here to enable debugging messages for power supply class 16 16 and drivers. 17 17 18 + config POWER_SUPPLY_HWMON 19 + bool 20 + prompt "Expose power supply sensors as hwmon device" 21 + depends on HWMON=y || HWMON=POWER_SUPPLY 22 + default y 23 + help 24 + This options enables API that allows sensors found on a 25 + power supply device (current, voltage, temperature) to be 26 + exposed as a hwmon device. 27 + 28 + Say 'Y' here if you want power supplies to 29 + have hwmon sysfs interface too. 30 + 31 + 18 32 config PDA_POWER 19 33 tristate "Generic PDA/phone power driver" 20 34 depends on !S390 ··· 711 697 Say Y here to enable support for getting battery status 712 698 information and altering charger configurations from charger 713 699 block of the ROHM BD70528 Power Management IC. 700 + 701 + config CHARGER_WILCO 702 + tristate "Wilco EC based charger for ChromeOS" 703 + depends on WILCO_EC 704 + help 705 + Say Y here to enable control of the charging routines performed 706 + by the Embedded Controller on the Chromebook named Wilco. Further 707 + information can be found in 708 + Documentation/ABI/testing/sysfs-class-power-wilco 714 709 715 710 endif # POWER_SUPPLY
+2
drivers/power/supply/Makefile
··· 6 6 power_supply-$(CONFIG_LEDS_TRIGGERS) += power_supply_leds.o 7 7 8 8 obj-$(CONFIG_POWER_SUPPLY) += power_supply.o 9 + obj-$(CONFIG_POWER_SUPPLY_HWMON) += power_supply_hwmon.o 9 10 obj-$(CONFIG_GENERIC_ADC_BATTERY) += generic-adc-battery.o 10 11 11 12 obj-$(CONFIG_PDA_POWER) += pda_power.o ··· 92 91 obj-$(CONFIG_FUEL_GAUGE_SC27XX) += sc27xx_fuel_gauge.o 93 92 obj-$(CONFIG_CHARGER_UCS1002) += ucs1002_power.o 94 93 obj-$(CONFIG_CHARGER_BD70528) += bd70528-charger.o 94 + obj-$(CONFIG_CHARGER_WILCO) += wilco-charger.o
+1 -1
drivers/power/supply/bq24190_charger.c
··· 1697 1697 static int bq24190_probe(struct i2c_client *client, 1698 1698 const struct i2c_device_id *id) 1699 1699 { 1700 - struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); 1700 + struct i2c_adapter *adapter = client->adapter; 1701 1701 struct device *dev = &client->dev; 1702 1702 struct power_supply_config charger_cfg = {}, battery_cfg = {}; 1703 1703 struct bq24190_dev_info *bdi;
+1 -1
drivers/power/supply/bq24257_charger.c
··· 950 950 static int bq24257_probe(struct i2c_client *client, 951 951 const struct i2c_device_id *id) 952 952 { 953 - struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); 953 + struct i2c_adapter *adapter = client->adapter; 954 954 struct device *dev = &client->dev; 955 955 const struct acpi_device_id *acpi_id; 956 956 struct bq24257_device *bq;
+1 -1
drivers/power/supply/bq25890_charger.c
··· 817 817 static int bq25890_probe(struct i2c_client *client, 818 818 const struct i2c_device_id *id) 819 819 { 820 - struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); 820 + struct i2c_adapter *adapter = client->adapter; 821 821 struct device *dev = &client->dev; 822 822 struct bq25890_device *bq; 823 823 int ret;
+116
drivers/power/supply/cros_usbpd-charger.c
··· 53 53 }; 54 54 55 55 static enum power_supply_property cros_usbpd_charger_props[] = { 56 + POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, 57 + POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT, 56 58 POWER_SUPPLY_PROP_ONLINE, 57 59 POWER_SUPPLY_PROP_STATUS, 58 60 POWER_SUPPLY_PROP_CURRENT_MAX, ··· 81 79 POWER_SUPPLY_USB_TYPE_PD_DRP, 82 80 POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID 83 81 }; 82 + 83 + /* Input voltage/current limit in mV/mA. Default to none. */ 84 + static u16 input_voltage_limit = EC_POWER_LIMIT_NONE; 85 + static u16 input_current_limit = EC_POWER_LIMIT_NONE; 84 86 85 87 static bool cros_usbpd_charger_port_is_dedicated(struct port_data *port) 86 88 { ··· 330 324 return ret; 331 325 } 332 326 327 + static int cros_usbpd_charger_set_ext_power_limit(struct charger_data *charger, 328 + u16 current_lim, 329 + u16 voltage_lim) 330 + { 331 + struct ec_params_external_power_limit_v1 req; 332 + int ret; 333 + 334 + req.current_lim = current_lim; 335 + req.voltage_lim = voltage_lim; 336 + 337 + ret = cros_usbpd_charger_ec_command(charger, 0, 338 + EC_CMD_EXTERNAL_POWER_LIMIT, 339 + &req, sizeof(req), NULL, 0); 340 + if (ret < 0) 341 + dev_err(charger->dev, 342 + "Unable to set the 'External Power Limit': %d\n", ret); 343 + 344 + return ret; 345 + } 346 + 333 347 static void cros_usbpd_charger_power_changed(struct power_supply *psy) 334 348 { 335 349 struct port_data *port = power_supply_get_drvdata(psy); ··· 422 396 case POWER_SUPPLY_PROP_USB_TYPE: 423 397 val->intval = port->psy_usb_type; 424 398 break; 399 + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: 400 + if (input_current_limit == EC_POWER_LIMIT_NONE) 401 + val->intval = -1; 402 + else 403 + val->intval = input_current_limit * 1000; 404 + break; 405 + case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT: 406 + if (input_voltage_limit == EC_POWER_LIMIT_NONE) 407 + val->intval = -1; 408 + else 409 + val->intval = input_voltage_limit * 1000; 410 + break; 425 411 case POWER_SUPPLY_PROP_MODEL_NAME: 426 412 val->strval = port->model_name; 427 413 break; ··· 445 407 } 446 408 447 409 return 0; 410 + } 411 + 412 + static int cros_usbpd_charger_set_prop(struct power_supply *psy, 413 + enum power_supply_property psp, 414 + const union power_supply_propval *val) 415 + { 416 + struct port_data *port = power_supply_get_drvdata(psy); 417 + struct charger_data *charger = port->charger; 418 + struct device *dev = charger->dev; 419 + u16 intval; 420 + int ret; 421 + 422 + /* U16_MAX in mV/mA is the maximum supported value */ 423 + if (val->intval >= U16_MAX * 1000) 424 + return -EINVAL; 425 + /* A negative number is used to clear the limit */ 426 + if (val->intval < 0) 427 + intval = EC_POWER_LIMIT_NONE; 428 + else /* Convert from uA/uV to mA/mV */ 429 + intval = val->intval / 1000; 430 + 431 + switch (psp) { 432 + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: 433 + ret = cros_usbpd_charger_set_ext_power_limit(charger, intval, 434 + input_voltage_limit); 435 + if (ret < 0) 436 + break; 437 + 438 + input_current_limit = intval; 439 + if (input_current_limit == EC_POWER_LIMIT_NONE) 440 + dev_info(dev, 441 + "External Current Limit cleared for all ports\n"); 442 + else 443 + dev_info(dev, 444 + "External Current Limit set to %dmA for all ports\n", 445 + input_current_limit); 446 + break; 447 + case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT: 448 + ret = cros_usbpd_charger_set_ext_power_limit(charger, 449 + input_current_limit, 450 + intval); 451 + if (ret < 0) 452 + break; 453 + 454 + input_voltage_limit = intval; 455 + if (input_voltage_limit == EC_POWER_LIMIT_NONE) 456 + dev_info(dev, 457 + "External Voltage Limit cleared for all ports\n"); 458 + else 459 + dev_info(dev, 460 + "External Voltage Limit set to %dmV for all ports\n", 461 + input_voltage_limit); 462 + break; 463 + default: 464 + ret = -EINVAL; 465 + } 466 + 467 + return ret; 468 + } 469 + 470 + static int cros_usbpd_charger_property_is_writeable(struct power_supply *psy, 471 + enum power_supply_property psp) 472 + { 473 + int ret; 474 + 475 + switch (psp) { 476 + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: 477 + case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT: 478 + ret = 1; 479 + break; 480 + default: 481 + ret = 0; 482 + } 483 + 484 + return ret; 448 485 } 449 486 450 487 static int cros_usbpd_charger_ec_event(struct notifier_block *nb, ··· 638 525 639 526 psy_desc = &port->psy_desc; 640 527 psy_desc->get_property = cros_usbpd_charger_get_prop; 528 + psy_desc->set_property = cros_usbpd_charger_set_prop; 529 + psy_desc->property_is_writeable = 530 + cros_usbpd_charger_property_is_writeable; 641 531 psy_desc->external_power_changed = 642 532 cros_usbpd_charger_power_changed; 643 533 psy_cfg.drv_data = port;
+1 -1
drivers/power/supply/max14656_charger_detector.c
··· 247 247 static int max14656_probe(struct i2c_client *client, 248 248 const struct i2c_device_id *id) 249 249 { 250 - struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); 250 + struct i2c_adapter *adapter = client->adapter; 251 251 struct device *dev = &client->dev; 252 252 struct power_supply_config psy_cfg = {}; 253 253 struct max14656_chip *chip;
+1 -1
drivers/power/supply/max17040_battery.c
··· 193 193 static int max17040_probe(struct i2c_client *client, 194 194 const struct i2c_device_id *id) 195 195 { 196 - struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); 196 + struct i2c_adapter *adapter = client->adapter; 197 197 struct power_supply_config psy_cfg = {}; 198 198 struct max17040_chip *chip; 199 199
+1 -1
drivers/power/supply/max17042_battery.c
··· 1005 1005 static int max17042_probe(struct i2c_client *client, 1006 1006 const struct i2c_device_id *id) 1007 1007 { 1008 - struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); 1008 + struct i2c_adapter *adapter = client->adapter; 1009 1009 const struct power_supply_desc *max17042_desc = &max17042_psy_desc; 1010 1010 struct power_supply_config psy_cfg = {}; 1011 1011 const struct acpi_device_id *acpi_id = NULL;
+7
drivers/power/supply/power_supply_core.c
··· 1071 1071 if (rc) 1072 1072 goto create_triggers_failed; 1073 1073 1074 + rc = power_supply_add_hwmon_sysfs(psy); 1075 + if (rc) 1076 + goto add_hwmon_sysfs_failed; 1077 + 1074 1078 /* 1075 1079 * Update use_cnt after any uevents (most notably from device_add()). 1076 1080 * We are here still during driver's probe but ··· 1093 1089 1094 1090 return psy; 1095 1091 1092 + add_hwmon_sysfs_failed: 1093 + power_supply_remove_triggers(psy); 1096 1094 create_triggers_failed: 1097 1095 psy_unregister_cooler(psy); 1098 1096 register_cooler_failed: ··· 1247 1241 cancel_work_sync(&psy->changed_work); 1248 1242 cancel_delayed_work_sync(&psy->deferred_register_work); 1249 1243 sysfs_remove_link(&psy->dev.kobj, "powers"); 1244 + power_supply_remove_hwmon_sysfs(psy); 1250 1245 power_supply_remove_triggers(psy); 1251 1246 psy_unregister_cooler(psy); 1252 1247 psy_unregister_thermal(psy);
+355
drivers/power/supply/power_supply_hwmon.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * power_supply_hwmon.c - power supply hwmon support. 4 + */ 5 + 6 + #include <linux/err.h> 7 + #include <linux/hwmon.h> 8 + #include <linux/power_supply.h> 9 + #include <linux/slab.h> 10 + 11 + struct power_supply_hwmon { 12 + struct power_supply *psy; 13 + unsigned long *props; 14 + }; 15 + 16 + static int power_supply_hwmon_in_to_property(u32 attr) 17 + { 18 + switch (attr) { 19 + case hwmon_in_average: 20 + return POWER_SUPPLY_PROP_VOLTAGE_AVG; 21 + case hwmon_in_min: 22 + return POWER_SUPPLY_PROP_VOLTAGE_MIN; 23 + case hwmon_in_max: 24 + return POWER_SUPPLY_PROP_VOLTAGE_MAX; 25 + case hwmon_in_input: 26 + return POWER_SUPPLY_PROP_VOLTAGE_NOW; 27 + default: 28 + return -EINVAL; 29 + } 30 + } 31 + 32 + static int power_supply_hwmon_curr_to_property(u32 attr) 33 + { 34 + switch (attr) { 35 + case hwmon_curr_average: 36 + return POWER_SUPPLY_PROP_CURRENT_AVG; 37 + case hwmon_curr_max: 38 + return POWER_SUPPLY_PROP_CURRENT_MAX; 39 + case hwmon_curr_input: 40 + return POWER_SUPPLY_PROP_CURRENT_NOW; 41 + default: 42 + return -EINVAL; 43 + } 44 + } 45 + 46 + static int power_supply_hwmon_temp_to_property(u32 attr, int channel) 47 + { 48 + if (channel) { 49 + switch (attr) { 50 + case hwmon_temp_input: 51 + return POWER_SUPPLY_PROP_TEMP_AMBIENT; 52 + case hwmon_temp_min_alarm: 53 + return POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MIN; 54 + case hwmon_temp_max_alarm: 55 + return POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MAX; 56 + default: 57 + break; 58 + } 59 + } else { 60 + switch (attr) { 61 + case hwmon_temp_input: 62 + return POWER_SUPPLY_PROP_TEMP; 63 + case hwmon_temp_max: 64 + return POWER_SUPPLY_PROP_TEMP_MAX; 65 + case hwmon_temp_min: 66 + return POWER_SUPPLY_PROP_TEMP_MIN; 67 + case hwmon_temp_min_alarm: 68 + return POWER_SUPPLY_PROP_TEMP_ALERT_MIN; 69 + case hwmon_temp_max_alarm: 70 + return POWER_SUPPLY_PROP_TEMP_ALERT_MAX; 71 + default: 72 + break; 73 + } 74 + } 75 + 76 + return -EINVAL; 77 + } 78 + 79 + static int 80 + power_supply_hwmon_to_property(enum hwmon_sensor_types type, 81 + u32 attr, int channel) 82 + { 83 + switch (type) { 84 + case hwmon_in: 85 + return power_supply_hwmon_in_to_property(attr); 86 + case hwmon_curr: 87 + return power_supply_hwmon_curr_to_property(attr); 88 + case hwmon_temp: 89 + return power_supply_hwmon_temp_to_property(attr, channel); 90 + default: 91 + return -EINVAL; 92 + } 93 + } 94 + 95 + static bool power_supply_hwmon_is_a_label(enum hwmon_sensor_types type, 96 + u32 attr) 97 + { 98 + return type == hwmon_temp && attr == hwmon_temp_label; 99 + } 100 + 101 + static bool power_supply_hwmon_is_writable(enum hwmon_sensor_types type, 102 + u32 attr) 103 + { 104 + switch (type) { 105 + case hwmon_in: 106 + return attr == hwmon_in_min || 107 + attr == hwmon_in_max; 108 + case hwmon_curr: 109 + return attr == hwmon_curr_max; 110 + case hwmon_temp: 111 + return attr == hwmon_temp_max || 112 + attr == hwmon_temp_min || 113 + attr == hwmon_temp_min_alarm || 114 + attr == hwmon_temp_max_alarm; 115 + default: 116 + return false; 117 + } 118 + } 119 + 120 + static umode_t power_supply_hwmon_is_visible(const void *data, 121 + enum hwmon_sensor_types type, 122 + u32 attr, int channel) 123 + { 124 + const struct power_supply_hwmon *psyhw = data; 125 + int prop; 126 + 127 + 128 + if (power_supply_hwmon_is_a_label(type, attr)) 129 + return 0444; 130 + 131 + prop = power_supply_hwmon_to_property(type, attr, channel); 132 + if (prop < 0 || !test_bit(prop, psyhw->props)) 133 + return 0; 134 + 135 + if (power_supply_property_is_writeable(psyhw->psy, prop) > 0 && 136 + power_supply_hwmon_is_writable(type, attr)) 137 + return 0644; 138 + 139 + return 0444; 140 + } 141 + 142 + static int power_supply_hwmon_read_string(struct device *dev, 143 + enum hwmon_sensor_types type, 144 + u32 attr, int channel, 145 + const char **str) 146 + { 147 + *str = channel ? "temp" : "temp ambient"; 148 + return 0; 149 + } 150 + 151 + static int 152 + power_supply_hwmon_read(struct device *dev, enum hwmon_sensor_types type, 153 + u32 attr, int channel, long *val) 154 + { 155 + struct power_supply_hwmon *psyhw = dev_get_drvdata(dev); 156 + struct power_supply *psy = psyhw->psy; 157 + union power_supply_propval pspval; 158 + int ret, prop; 159 + 160 + prop = power_supply_hwmon_to_property(type, attr, channel); 161 + if (prop < 0) 162 + return prop; 163 + 164 + ret = power_supply_get_property(psy, prop, &pspval); 165 + if (ret) 166 + return ret; 167 + 168 + switch (type) { 169 + /* 170 + * Both voltage and current is reported in units of 171 + * microvolts/microamps, so we need to adjust it to 172 + * milliamps(volts) 173 + */ 174 + case hwmon_curr: 175 + case hwmon_in: 176 + pspval.intval = DIV_ROUND_CLOSEST(pspval.intval, 1000); 177 + break; 178 + /* 179 + * Temp needs to be converted from 1/10 C to milli-C 180 + */ 181 + case hwmon_temp: 182 + if (check_mul_overflow(pspval.intval, 100, 183 + &pspval.intval)) 184 + return -EOVERFLOW; 185 + break; 186 + default: 187 + return -EINVAL; 188 + } 189 + 190 + *val = pspval.intval; 191 + 192 + return 0; 193 + } 194 + 195 + static int 196 + power_supply_hwmon_write(struct device *dev, enum hwmon_sensor_types type, 197 + u32 attr, int channel, long val) 198 + { 199 + struct power_supply_hwmon *psyhw = dev_get_drvdata(dev); 200 + struct power_supply *psy = psyhw->psy; 201 + union power_supply_propval pspval; 202 + int prop; 203 + 204 + prop = power_supply_hwmon_to_property(type, attr, channel); 205 + if (prop < 0) 206 + return prop; 207 + 208 + pspval.intval = val; 209 + 210 + switch (type) { 211 + /* 212 + * Both voltage and current is reported in units of 213 + * microvolts/microamps, so we need to adjust it to 214 + * milliamps(volts) 215 + */ 216 + case hwmon_curr: 217 + case hwmon_in: 218 + if (check_mul_overflow(pspval.intval, 1000, 219 + &pspval.intval)) 220 + return -EOVERFLOW; 221 + break; 222 + /* 223 + * Temp needs to be converted from 1/10 C to milli-C 224 + */ 225 + case hwmon_temp: 226 + pspval.intval = DIV_ROUND_CLOSEST(pspval.intval, 100); 227 + break; 228 + default: 229 + return -EINVAL; 230 + } 231 + 232 + return power_supply_set_property(psy, prop, &pspval); 233 + } 234 + 235 + static const struct hwmon_ops power_supply_hwmon_ops = { 236 + .is_visible = power_supply_hwmon_is_visible, 237 + .read = power_supply_hwmon_read, 238 + .write = power_supply_hwmon_write, 239 + .read_string = power_supply_hwmon_read_string, 240 + }; 241 + 242 + static const struct hwmon_channel_info *power_supply_hwmon_info[] = { 243 + HWMON_CHANNEL_INFO(temp, 244 + HWMON_T_LABEL | 245 + HWMON_T_INPUT | 246 + HWMON_T_MAX | 247 + HWMON_T_MIN | 248 + HWMON_T_MIN_ALARM | 249 + HWMON_T_MIN_ALARM, 250 + 251 + HWMON_T_LABEL | 252 + HWMON_T_INPUT | 253 + HWMON_T_MIN_ALARM | 254 + HWMON_T_LABEL | 255 + HWMON_T_MAX_ALARM), 256 + 257 + HWMON_CHANNEL_INFO(curr, 258 + HWMON_C_AVERAGE | 259 + HWMON_C_MAX | 260 + HWMON_C_INPUT), 261 + 262 + HWMON_CHANNEL_INFO(in, 263 + HWMON_I_AVERAGE | 264 + HWMON_I_MIN | 265 + HWMON_I_MAX | 266 + HWMON_I_INPUT), 267 + NULL 268 + }; 269 + 270 + static const struct hwmon_chip_info power_supply_hwmon_chip_info = { 271 + .ops = &power_supply_hwmon_ops, 272 + .info = power_supply_hwmon_info, 273 + }; 274 + 275 + static void power_supply_hwmon_bitmap_free(void *data) 276 + { 277 + bitmap_free(data); 278 + } 279 + 280 + int power_supply_add_hwmon_sysfs(struct power_supply *psy) 281 + { 282 + const struct power_supply_desc *desc = psy->desc; 283 + struct power_supply_hwmon *psyhw; 284 + struct device *dev = &psy->dev; 285 + struct device *hwmon; 286 + int ret, i; 287 + 288 + if (!devres_open_group(dev, power_supply_add_hwmon_sysfs, 289 + GFP_KERNEL)) 290 + return -ENOMEM; 291 + 292 + psyhw = devm_kzalloc(dev, sizeof(*psyhw), GFP_KERNEL); 293 + if (!psyhw) { 294 + ret = -ENOMEM; 295 + goto error; 296 + } 297 + 298 + psyhw->psy = psy; 299 + psyhw->props = bitmap_zalloc(POWER_SUPPLY_PROP_TIME_TO_FULL_AVG + 1, 300 + GFP_KERNEL); 301 + if (!psyhw->props) { 302 + ret = -ENOMEM; 303 + goto error; 304 + } 305 + 306 + ret = devm_add_action(dev, power_supply_hwmon_bitmap_free, 307 + psyhw->props); 308 + if (ret) 309 + goto error; 310 + 311 + for (i = 0; i < desc->num_properties; i++) { 312 + const enum power_supply_property prop = desc->properties[i]; 313 + 314 + switch (prop) { 315 + case POWER_SUPPLY_PROP_CURRENT_AVG: 316 + case POWER_SUPPLY_PROP_CURRENT_MAX: 317 + case POWER_SUPPLY_PROP_CURRENT_NOW: 318 + case POWER_SUPPLY_PROP_TEMP: 319 + case POWER_SUPPLY_PROP_TEMP_MAX: 320 + case POWER_SUPPLY_PROP_TEMP_MIN: 321 + case POWER_SUPPLY_PROP_TEMP_ALERT_MIN: 322 + case POWER_SUPPLY_PROP_TEMP_ALERT_MAX: 323 + case POWER_SUPPLY_PROP_TEMP_AMBIENT: 324 + case POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MIN: 325 + case POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MAX: 326 + case POWER_SUPPLY_PROP_VOLTAGE_AVG: 327 + case POWER_SUPPLY_PROP_VOLTAGE_MIN: 328 + case POWER_SUPPLY_PROP_VOLTAGE_MAX: 329 + case POWER_SUPPLY_PROP_VOLTAGE_NOW: 330 + set_bit(prop, psyhw->props); 331 + break; 332 + default: 333 + break; 334 + } 335 + } 336 + 337 + hwmon = devm_hwmon_device_register_with_info(dev, psy->desc->name, 338 + psyhw, 339 + &power_supply_hwmon_chip_info, 340 + NULL); 341 + ret = PTR_ERR_OR_ZERO(hwmon); 342 + if (ret) 343 + goto error; 344 + 345 + devres_close_group(dev, power_supply_add_hwmon_sysfs); 346 + return 0; 347 + error: 348 + devres_release_group(dev, NULL); 349 + return ret; 350 + } 351 + 352 + void power_supply_remove_hwmon_sysfs(struct power_supply *psy) 353 + { 354 + devres_release_group(&psy->dev, power_supply_add_hwmon_sysfs); 355 + }
+2
drivers/power/supply/power_supply_sysfs.c
··· 276 276 POWER_SUPPLY_ATTR(charge_control_start_threshold), 277 277 POWER_SUPPLY_ATTR(charge_control_end_threshold), 278 278 POWER_SUPPLY_ATTR(input_current_limit), 279 + POWER_SUPPLY_ATTR(input_voltage_limit), 280 + POWER_SUPPLY_ATTR(input_power_limit), 279 281 POWER_SUPPLY_ATTR(energy_full_design), 280 282 POWER_SUPPLY_ATTR(energy_empty_design), 281 283 POWER_SUPPLY_ATTR(energy_full),
+1 -1
drivers/power/supply/rt5033_battery.c
··· 115 115 static int rt5033_battery_probe(struct i2c_client *client, 116 116 const struct i2c_device_id *id) 117 117 { 118 - struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); 118 + struct i2c_adapter *adapter = client->adapter; 119 119 struct power_supply_config psy_cfg = {}; 120 120 struct rt5033_battery *battery; 121 121 u32 ret;
+1 -1
drivers/power/supply/rt9455_charger.c
··· 1584 1584 static int rt9455_probe(struct i2c_client *client, 1585 1585 const struct i2c_device_id *id) 1586 1586 { 1587 - struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); 1587 + struct i2c_adapter *adapter = client->adapter; 1588 1588 struct device *dev = &client->dev; 1589 1589 struct rt9455_info *info; 1590 1590 struct power_supply_config rt9455_charger_config = {};
+1 -1
drivers/power/supply/sbs-manager.c
··· 314 314 static int sbsm_probe(struct i2c_client *client, 315 315 const struct i2c_device_id *id) 316 316 { 317 - struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); 317 + struct i2c_adapter *adapter = client->adapter; 318 318 struct sbsm_data *data; 319 319 struct device *dev = &client->dev; 320 320 struct power_supply_desc *psy_desc;
+1 -1
drivers/power/supply/ucs1002_power.c
··· 336 336 case F_ACTIVE_MODE_BC12_CDP: 337 337 type = POWER_SUPPLY_USB_TYPE_CDP; 338 338 break; 339 - }; 339 + } 340 340 341 341 val->intval = type; 342 342
+187
drivers/power/supply/wilco-charger.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Charging control driver for the Wilco EC 4 + * 5 + * Copyright 2019 Google LLC 6 + * 7 + * See Documentation/ABI/testing/sysfs-class-power and 8 + * Documentation/ABI/testing/sysfs-class-power-wilco for userspace interface 9 + * and other info. 10 + */ 11 + 12 + #include <linux/module.h> 13 + #include <linux/platform_device.h> 14 + #include <linux/platform_data/wilco-ec.h> 15 + #include <linux/power_supply.h> 16 + 17 + #define DRV_NAME "wilco-charger" 18 + 19 + /* Property IDs and related EC constants */ 20 + #define PID_CHARGE_MODE 0x0710 21 + #define PID_CHARGE_LOWER_LIMIT 0x0711 22 + #define PID_CHARGE_UPPER_LIMIT 0x0712 23 + 24 + enum charge_mode { 25 + CHARGE_MODE_STD = 1, /* Used for Standard */ 26 + CHARGE_MODE_EXP = 2, /* Express Charge, used for Fast */ 27 + CHARGE_MODE_AC = 3, /* Mostly AC use, used for Trickle */ 28 + CHARGE_MODE_AUTO = 4, /* Used for Adaptive */ 29 + CHARGE_MODE_CUSTOM = 5, /* Used for Custom */ 30 + }; 31 + 32 + #define CHARGE_LOWER_LIMIT_MIN 50 33 + #define CHARGE_LOWER_LIMIT_MAX 95 34 + #define CHARGE_UPPER_LIMIT_MIN 55 35 + #define CHARGE_UPPER_LIMIT_MAX 100 36 + 37 + /* Convert from POWER_SUPPLY_PROP_CHARGE_TYPE value to the EC's charge mode */ 38 + static int psp_val_to_charge_mode(int psp_val) 39 + { 40 + switch (psp_val) { 41 + case POWER_SUPPLY_CHARGE_TYPE_TRICKLE: 42 + return CHARGE_MODE_AC; 43 + case POWER_SUPPLY_CHARGE_TYPE_FAST: 44 + return CHARGE_MODE_EXP; 45 + case POWER_SUPPLY_CHARGE_TYPE_STANDARD: 46 + return CHARGE_MODE_STD; 47 + case POWER_SUPPLY_CHARGE_TYPE_ADAPTIVE: 48 + return CHARGE_MODE_AUTO; 49 + case POWER_SUPPLY_CHARGE_TYPE_CUSTOM: 50 + return CHARGE_MODE_CUSTOM; 51 + default: 52 + return -EINVAL; 53 + } 54 + } 55 + 56 + /* Convert from EC's charge mode to POWER_SUPPLY_PROP_CHARGE_TYPE value */ 57 + static int charge_mode_to_psp_val(enum charge_mode mode) 58 + { 59 + switch (mode) { 60 + case CHARGE_MODE_AC: 61 + return POWER_SUPPLY_CHARGE_TYPE_TRICKLE; 62 + case CHARGE_MODE_EXP: 63 + return POWER_SUPPLY_CHARGE_TYPE_FAST; 64 + case CHARGE_MODE_STD: 65 + return POWER_SUPPLY_CHARGE_TYPE_STANDARD; 66 + case CHARGE_MODE_AUTO: 67 + return POWER_SUPPLY_CHARGE_TYPE_ADAPTIVE; 68 + case CHARGE_MODE_CUSTOM: 69 + return POWER_SUPPLY_CHARGE_TYPE_CUSTOM; 70 + default: 71 + return -EINVAL; 72 + } 73 + } 74 + 75 + static enum power_supply_property wilco_charge_props[] = { 76 + POWER_SUPPLY_PROP_CHARGE_TYPE, 77 + POWER_SUPPLY_PROP_CHARGE_CONTROL_START_THRESHOLD, 78 + POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD, 79 + }; 80 + 81 + static int wilco_charge_get_property(struct power_supply *psy, 82 + enum power_supply_property psp, 83 + union power_supply_propval *val) 84 + { 85 + struct wilco_ec_device *ec = power_supply_get_drvdata(psy); 86 + u32 property_id; 87 + int ret; 88 + u8 raw; 89 + 90 + switch (psp) { 91 + case POWER_SUPPLY_PROP_CHARGE_TYPE: 92 + property_id = PID_CHARGE_MODE; 93 + break; 94 + case POWER_SUPPLY_PROP_CHARGE_CONTROL_START_THRESHOLD: 95 + property_id = PID_CHARGE_LOWER_LIMIT; 96 + break; 97 + case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD: 98 + property_id = PID_CHARGE_UPPER_LIMIT; 99 + break; 100 + default: 101 + return -EINVAL; 102 + } 103 + 104 + ret = wilco_ec_get_byte_property(ec, property_id, &raw); 105 + if (ret < 0) 106 + return ret; 107 + if (property_id == PID_CHARGE_MODE) { 108 + ret = charge_mode_to_psp_val(raw); 109 + if (ret < 0) 110 + return -EBADMSG; 111 + raw = ret; 112 + } 113 + val->intval = raw; 114 + 115 + return 0; 116 + } 117 + 118 + static int wilco_charge_set_property(struct power_supply *psy, 119 + enum power_supply_property psp, 120 + const union power_supply_propval *val) 121 + { 122 + struct wilco_ec_device *ec = power_supply_get_drvdata(psy); 123 + int mode; 124 + 125 + switch (psp) { 126 + case POWER_SUPPLY_PROP_CHARGE_TYPE: 127 + mode = psp_val_to_charge_mode(val->intval); 128 + if (mode < 0) 129 + return -EINVAL; 130 + return wilco_ec_set_byte_property(ec, PID_CHARGE_MODE, mode); 131 + case POWER_SUPPLY_PROP_CHARGE_CONTROL_START_THRESHOLD: 132 + if (val->intval < CHARGE_LOWER_LIMIT_MIN || 133 + val->intval > CHARGE_LOWER_LIMIT_MAX) 134 + return -EINVAL; 135 + return wilco_ec_set_byte_property(ec, PID_CHARGE_LOWER_LIMIT, 136 + val->intval); 137 + case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD: 138 + if (val->intval < CHARGE_UPPER_LIMIT_MIN || 139 + val->intval > CHARGE_UPPER_LIMIT_MAX) 140 + return -EINVAL; 141 + return wilco_ec_set_byte_property(ec, PID_CHARGE_UPPER_LIMIT, 142 + val->intval); 143 + default: 144 + return -EINVAL; 145 + } 146 + } 147 + 148 + static int wilco_charge_property_is_writeable(struct power_supply *psy, 149 + enum power_supply_property psp) 150 + { 151 + return 1; 152 + } 153 + 154 + static const struct power_supply_desc wilco_ps_desc = { 155 + .properties = wilco_charge_props, 156 + .num_properties = ARRAY_SIZE(wilco_charge_props), 157 + .get_property = wilco_charge_get_property, 158 + .set_property = wilco_charge_set_property, 159 + .property_is_writeable = wilco_charge_property_is_writeable, 160 + .name = DRV_NAME, 161 + .type = POWER_SUPPLY_TYPE_MAINS, 162 + }; 163 + 164 + static int wilco_charge_probe(struct platform_device *pdev) 165 + { 166 + struct wilco_ec_device *ec = dev_get_drvdata(pdev->dev.parent); 167 + struct power_supply_config psy_cfg = {}; 168 + struct power_supply *psy; 169 + 170 + psy_cfg.drv_data = ec; 171 + psy = devm_power_supply_register(&pdev->dev, &wilco_ps_desc, &psy_cfg); 172 + 173 + return PTR_ERR_OR_ZERO(psy); 174 + } 175 + 176 + static struct platform_driver wilco_charge_driver = { 177 + .probe = wilco_charge_probe, 178 + .driver = { 179 + .name = DRV_NAME, 180 + } 181 + }; 182 + module_platform_driver(wilco_charge_driver); 183 + 184 + MODULE_ALIAS("platform:" DRV_NAME); 185 + MODULE_AUTHOR("Nick Crews <ncrews@chromium.org>"); 186 + MODULE_LICENSE("GPL v2"); 187 + MODULE_DESCRIPTION("Wilco EC charge control driver");
+15
include/linux/power_supply.h
··· 128 128 POWER_SUPPLY_PROP_CHARGE_CONTROL_START_THRESHOLD, /* in percents! */ 129 129 POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD, /* in percents! */ 130 130 POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, 131 + POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT, 132 + POWER_SUPPLY_PROP_INPUT_POWER_LIMIT, 131 133 POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, 132 134 POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN, 133 135 POWER_SUPPLY_PROP_ENERGY_FULL, ··· 481 479 482 480 return 0; 483 481 } 482 + 483 + #ifdef CONFIG_POWER_SUPPLY_HWMON 484 + int power_supply_add_hwmon_sysfs(struct power_supply *psy); 485 + void power_supply_remove_hwmon_sysfs(struct power_supply *psy); 486 + #else 487 + static inline int power_supply_add_hwmon_sysfs(struct power_supply *psy) 488 + { 489 + return 0; 490 + } 491 + 492 + static inline 493 + void power_supply_remove_hwmon_sysfs(struct power_supply *psy) {} 494 + #endif 484 495 485 496 #endif /* __LINUX_POWER_SUPPLY_H__ */