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.18' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply

Pull power supply and reset updates from Sebastian Reichel:
"Power-supply core:

- Introduce "Bypass" charging type used by USB PPS standard

- Refactor power_supply_set_input_current_limit_from_supplier()

- Add fwnode support to power_supply_get_battery_info()

Drivers:

- ab8500: continue migrating towards using standard core APIs

- axp288 fuel-gauge: refactor driver to be fully resource managed

- battery-samsung-sdi: new in-kernel provider for (constant) Samsung
battery info

- bq24190: disable boost regulator on shutdown

- bq24190: add support for battery-info on ACPI based systems

- bq25890: prepare driver for usage on ACPI based systems

- bq25890: add boost regulator support

- cpcap-battery: add NVMEM based battery detection support

- injoinic ip5xxx: new driver for power bank IC

- upi ug3105: new battery driver

- misc small improvements and fixes"

* tag 'for-v5.18' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply: (94 commits)
power: ab8500_chargalg: Use CLOCK_MONOTONIC
power: supply: Add a driver for Injoinic power bank ICs
dt-bindings: trivial-devices: Add Injoinic power bank ICs
dt-bindings: vendor-prefixes: Add Injoinic
power: supply: ab8500: Remove unused variable
power: supply: da9150-fg: Remove unnecessary print function dev_err()
power: supply: ab8500: fix a handful of spelling mistakes
power: supply: ab8500_fg: Account for line impedance
dt-bindings: power: supply: ab8500_fg: Add line impedance
power: supply: axp20x_usb_power: fix platform_get_irq.cocci warnings
power: supply: axp20x_ac_power: fix platform_get_irq.cocci warning
power: supply: wm8350-power: Add missing free in free_charger_irq
power: supply: wm8350-power: Handle error for wm8350_register_irq
power: supply: Static data for Samsung batteries
power: supply: ab8500_fg: Use VBAT-to-Ri if possible
power: supply: Support VBAT-to-Ri lookup tables
power: supply: ab8500: Standardize BTI resistance
power: supply: ab8500: Standardize alert mode charging
power: supply: ab8500: Standardize maintenance charging
power: supply: bq24190_charger: Delay applying charge_type changes when OTG 5V Vbus boost is on
...

+4137 -1448
+6 -2
Documentation/ABI/testing/sysfs-class-power
··· 380 380 algorithm to adjust the charge rate dynamically, without 381 381 any user configuration required. "Custom" means that the charger 382 382 uses the charge_control_* properties as configuration for some 383 - different algorithm. 383 + different algorithm. "Long Life" means the charger reduces its 384 + charging rate in order to prolong the battery health. "Bypass" 385 + means the charger bypasses the charging path around the 386 + integrated converter allowing for a "smart" wall adaptor to 387 + perform the power conversion externally. 384 388 385 389 Access: Read, Write 386 390 387 391 Valid values: 388 392 "Unknown", "N/A", "Trickle", "Fast", "Standard", 389 - "Adaptive", "Custom" 393 + "Adaptive", "Custom", "Long Life", "Bypass" 390 394 391 395 What: /sys/class/power_supply/<supply_name>/charge_term_current 392 396 Date: July 2014
+5
Documentation/devicetree/bindings/power/supply/stericsson,ab8500-fg.yaml
··· 25 25 $ref: /schemas/types.yaml#/definitions/phandle 26 26 deprecated: true 27 27 28 + line-impedance-micro-ohms: 29 + description: The line impedance between the battery and the 30 + AB8500 inputs, to compensate for this when determining internal 31 + resistance. 32 + 28 33 interrupts: 29 34 maxItems: 5 30 35
+8
Documentation/devicetree/bindings/trivial-devices.yaml
··· 143 143 - infineon,xdpe12254 144 144 # Infineon Multi-phase Digital VR Controller xdpe12284 145 145 - infineon,xdpe12284 146 + # Injoinic IP5108 2.0A Power Bank IC with I2C 147 + - injoinic,ip5108 148 + # Injoinic IP5109 2.1A Power Bank IC with I2C 149 + - injoinic,ip5109 150 + # Injoinic IP5207 1.2A Power Bank IC with I2C 151 + - injoinic,ip5207 152 + # Injoinic IP5209 2.4A Power Bank IC with I2C 153 + - injoinic,ip5209 146 154 # Inspur Power System power supply unit version 1 147 155 - inspur,ipsps1 148 156 # Intersil ISL29028 Ambient Light and Proximity Sensor
+2
Documentation/devicetree/bindings/vendor-prefixes.yaml
··· 571 571 description: InfoVision Optoelectronics Kunshan Co. Ltd. 572 572 "^ingenic,.*": 573 573 description: Ingenic Semiconductor 574 + "^injoinic,.*": 575 + description: Injoinic Technology Corp. 574 576 "^innolux,.*": 575 577 description: Innolux Corporation 576 578 "^inside-secure,.*":
+5
MAINTAINERS
··· 9537 9537 F: sound/soc/codecs/jz47* 9538 9538 F: sound/soc/jz4740/ 9539 9539 9540 + INJOINIC IP5xxx POWER BANK IC DRIVER 9541 + M: Samuel Holland <samuel@sholland.org> 9542 + S: Maintained 9543 + F: drivers/power/supply/ip5xxx_power.c 9544 + 9540 9545 INOTIFY 9541 9546 M: Jan Kara <jack@suse.cz> 9542 9547 R: Amir Goldstein <amir73il@gmail.com>
+2
drivers/extcon/Kconfig
··· 61 61 config EXTCON_INTEL_CHT_WC 62 62 tristate "Intel Cherrytrail Whiskey Cove PMIC extcon driver" 63 63 depends on INTEL_SOC_PMIC_CHTWC 64 + depends on USB_SUPPORT 65 + select USB_ROLE_SWITCH 64 66 help 65 67 Say Y here to enable extcon support for charger detection / control 66 68 on the Intel Cherrytrail Whiskey Cove PMIC.
+214 -26
drivers/extcon/extcon-intel-cht-wc.c
··· 14 14 #include <linux/module.h> 15 15 #include <linux/mod_devicetable.h> 16 16 #include <linux/platform_device.h> 17 + #include <linux/power_supply.h> 18 + #include <linux/property.h> 17 19 #include <linux/regmap.h> 20 + #include <linux/regulator/consumer.h> 18 21 #include <linux/slab.h> 22 + #include <linux/usb/role.h> 19 23 20 24 #include "extcon-intel.h" 21 25 ··· 105 101 struct device *dev; 106 102 struct regmap *regmap; 107 103 struct extcon_dev *edev; 104 + struct usb_role_switch *role_sw; 105 + struct regulator *vbus_boost; 106 + struct power_supply *psy; 107 + enum power_supply_usb_type usb_type; 108 108 unsigned int previous_cable; 109 109 bool usb_host; 110 + bool vbus_boost_enabled; 110 111 }; 111 112 112 113 static int cht_wc_extcon_get_id(struct cht_wc_extcon_data *ext, int pwrsrc_sts) ··· 121 112 return INTEL_USB_ID_GND; 122 113 case CHT_WC_PWRSRC_RID_FLOAT: 123 114 return INTEL_USB_ID_FLOAT; 115 + /* 116 + * According to the spec. we should read the USB-ID pin ADC value here 117 + * to determine the resistance of the used pull-down resister and then 118 + * return RID_A / RID_B / RID_C based on this. But all "Accessory 119 + * Charger Adapter"s (ACAs) which users can actually buy always use 120 + * a combination of a charging port with one or more USB-A ports, so 121 + * they should always use a resistor indicating RID_A. But the spec 122 + * is hard to read / badly-worded so some of them actually indicate 123 + * they are a RID_B ACA evnen though they clearly are a RID_A ACA. 124 + * To workaround this simply always return INTEL_USB_RID_A, which 125 + * matches all the ACAs which users can actually buy. 126 + */ 124 127 case CHT_WC_PWRSRC_RID_ACA: 128 + return INTEL_USB_RID_A; 125 129 default: 126 - /* 127 - * Once we have IIO support for the GPADC we should read 128 - * the USBID GPADC channel here and determine ACA role 129 - * based on that. 130 - */ 131 130 return INTEL_USB_ID_FLOAT; 132 131 } 133 132 } ··· 164 147 } while (time_before(jiffies, timeout)); 165 148 166 149 if (status != CHT_WC_USBSRC_STS_SUCCESS) { 167 - if (ignore_errors) 168 - return EXTCON_CHG_USB_SDP; /* Save fallback */ 150 + if (!ignore_errors) { 151 + if (status == CHT_WC_USBSRC_STS_FAIL) 152 + dev_warn(ext->dev, "Could not detect charger type\n"); 153 + else 154 + dev_warn(ext->dev, "Timeout detecting charger type\n"); 155 + } 169 156 170 - if (status == CHT_WC_USBSRC_STS_FAIL) 171 - dev_warn(ext->dev, "Could not detect charger type\n"); 172 - else 173 - dev_warn(ext->dev, "Timeout detecting charger type\n"); 174 - return EXTCON_CHG_USB_SDP; /* Save fallback */ 157 + /* Safe fallback */ 158 + usbsrc = CHT_WC_USBSRC_TYPE_SDP << CHT_WC_USBSRC_TYPE_SHIFT; 175 159 } 176 160 177 161 usbsrc = (usbsrc & CHT_WC_USBSRC_TYPE_MASK) >> CHT_WC_USBSRC_TYPE_SHIFT; ··· 181 163 dev_warn(ext->dev, 182 164 "Unhandled charger type %d, defaulting to SDP\n", 183 165 ret); 166 + ext->usb_type = POWER_SUPPLY_USB_TYPE_SDP; 184 167 return EXTCON_CHG_USB_SDP; 185 168 case CHT_WC_USBSRC_TYPE_SDP: 186 169 case CHT_WC_USBSRC_TYPE_FLOATING: 187 170 case CHT_WC_USBSRC_TYPE_OTHER: 171 + ext->usb_type = POWER_SUPPLY_USB_TYPE_SDP; 188 172 return EXTCON_CHG_USB_SDP; 189 173 case CHT_WC_USBSRC_TYPE_CDP: 174 + ext->usb_type = POWER_SUPPLY_USB_TYPE_CDP; 190 175 return EXTCON_CHG_USB_CDP; 191 176 case CHT_WC_USBSRC_TYPE_DCP: 192 177 case CHT_WC_USBSRC_TYPE_DCP_EXTPHY: 193 178 case CHT_WC_USBSRC_TYPE_MHL: /* MHL2+ delivers upto 2A, treat as DCP */ 179 + ext->usb_type = POWER_SUPPLY_USB_TYPE_DCP; 194 180 return EXTCON_CHG_USB_DCP; 195 181 case CHT_WC_USBSRC_TYPE_ACA: 182 + ext->usb_type = POWER_SUPPLY_USB_TYPE_ACA; 196 183 return EXTCON_CHG_USB_ACA; 197 184 } 198 185 } ··· 239 216 CHT_WC_CHGRCTRL1_OTGMODE, val); 240 217 if (ret) 241 218 dev_err(ext->dev, "Error updating CHGRCTRL1 reg: %d\n", ret); 219 + 220 + if (ext->vbus_boost && ext->vbus_boost_enabled != enable) { 221 + if (enable) 222 + ret = regulator_enable(ext->vbus_boost); 223 + else 224 + ret = regulator_disable(ext->vbus_boost); 225 + 226 + if (ret) 227 + dev_err(ext->dev, "Error updating Vbus boost regulator: %d\n", ret); 228 + else 229 + ext->vbus_boost_enabled = enable; 230 + } 242 231 } 243 232 244 233 static void cht_wc_extcon_enable_charging(struct cht_wc_extcon_data *ext, ··· 280 245 unsigned int cable = EXTCON_NONE; 281 246 /* Ignore errors in host mode, as the 5v boost converter is on then */ 282 247 bool ignore_get_charger_errors = ext->usb_host; 248 + enum usb_role role; 249 + 250 + ext->usb_type = POWER_SUPPLY_USB_TYPE_UNKNOWN; 283 251 284 252 ret = regmap_read(ext->regmap, CHT_WC_PWRSRC_STS, &pwrsrc_sts); 285 253 if (ret) { ··· 326 288 327 289 ext->usb_host = ((id == INTEL_USB_ID_GND) || (id == INTEL_USB_RID_A)); 328 290 extcon_set_state_sync(ext->edev, EXTCON_USB_HOST, ext->usb_host); 291 + 292 + if (ext->usb_host) 293 + role = USB_ROLE_HOST; 294 + else if (pwrsrc_sts & CHT_WC_PWRSRC_VBUS) 295 + role = USB_ROLE_DEVICE; 296 + else 297 + role = USB_ROLE_NONE; 298 + 299 + /* Note: this is a no-op when ext->role_sw is NULL */ 300 + ret = usb_role_switch_set_role(ext->role_sw, role); 301 + if (ret) 302 + dev_err(ext->dev, "Error setting USB-role: %d\n", ret); 303 + 304 + if (ext->psy) 305 + power_supply_changed(ext->psy); 329 306 } 330 307 331 308 static irqreturn_t cht_wc_extcon_isr(int irq, void *data) ··· 386 333 return ret; 387 334 } 388 335 336 + static int cht_wc_extcon_find_role_sw(struct cht_wc_extcon_data *ext) 337 + { 338 + const struct software_node *swnode; 339 + struct fwnode_handle *fwnode; 340 + 341 + swnode = software_node_find_by_name(NULL, "intel-xhci-usb-sw"); 342 + if (!swnode) 343 + return -EPROBE_DEFER; 344 + 345 + fwnode = software_node_fwnode(swnode); 346 + ext->role_sw = usb_role_switch_find_by_fwnode(fwnode); 347 + fwnode_handle_put(fwnode); 348 + 349 + return ext->role_sw ? 0 : -EPROBE_DEFER; 350 + } 351 + 352 + static void cht_wc_extcon_put_role_sw(void *data) 353 + { 354 + struct cht_wc_extcon_data *ext = data; 355 + 356 + usb_role_switch_put(ext->role_sw); 357 + } 358 + 359 + /* Some boards require controlling the role-sw and Vbus based on the id-pin */ 360 + static int cht_wc_extcon_get_role_sw_and_regulator(struct cht_wc_extcon_data *ext) 361 + { 362 + int ret; 363 + 364 + ret = cht_wc_extcon_find_role_sw(ext); 365 + if (ret) 366 + return ret; 367 + 368 + ret = devm_add_action_or_reset(ext->dev, cht_wc_extcon_put_role_sw, ext); 369 + if (ret) 370 + return ret; 371 + 372 + /* 373 + * On x86/ACPI platforms the regulator <-> consumer link is provided 374 + * by platform_data passed to the regulator driver. This means that 375 + * this info is not available before the regulator driver has bound. 376 + * Use devm_regulator_get_optional() to avoid getting a dummy 377 + * regulator and wait for the regulator to show up if necessary. 378 + */ 379 + ext->vbus_boost = devm_regulator_get_optional(ext->dev, "vbus"); 380 + if (IS_ERR(ext->vbus_boost)) { 381 + ret = PTR_ERR(ext->vbus_boost); 382 + if (ret == -ENODEV) 383 + ret = -EPROBE_DEFER; 384 + 385 + return dev_err_probe(ext->dev, ret, "getting Vbus regulator"); 386 + } 387 + 388 + return 0; 389 + } 390 + 391 + static int cht_wc_extcon_psy_get_prop(struct power_supply *psy, 392 + enum power_supply_property psp, 393 + union power_supply_propval *val) 394 + { 395 + struct cht_wc_extcon_data *ext = power_supply_get_drvdata(psy); 396 + 397 + switch (psp) { 398 + case POWER_SUPPLY_PROP_USB_TYPE: 399 + val->intval = ext->usb_type; 400 + break; 401 + case POWER_SUPPLY_PROP_ONLINE: 402 + val->intval = ext->usb_type ? 1 : 0; 403 + break; 404 + default: 405 + return -EINVAL; 406 + } 407 + 408 + return 0; 409 + } 410 + 411 + static const enum power_supply_usb_type cht_wc_extcon_psy_usb_types[] = { 412 + POWER_SUPPLY_USB_TYPE_SDP, 413 + POWER_SUPPLY_USB_TYPE_CDP, 414 + POWER_SUPPLY_USB_TYPE_DCP, 415 + POWER_SUPPLY_USB_TYPE_ACA, 416 + POWER_SUPPLY_USB_TYPE_UNKNOWN, 417 + }; 418 + 419 + static const enum power_supply_property cht_wc_extcon_psy_props[] = { 420 + POWER_SUPPLY_PROP_USB_TYPE, 421 + POWER_SUPPLY_PROP_ONLINE, 422 + }; 423 + 424 + static const struct power_supply_desc cht_wc_extcon_psy_desc = { 425 + .name = "cht_wcove_pwrsrc", 426 + .type = POWER_SUPPLY_TYPE_USB, 427 + .usb_types = cht_wc_extcon_psy_usb_types, 428 + .num_usb_types = ARRAY_SIZE(cht_wc_extcon_psy_usb_types), 429 + .properties = cht_wc_extcon_psy_props, 430 + .num_properties = ARRAY_SIZE(cht_wc_extcon_psy_props), 431 + .get_property = cht_wc_extcon_psy_get_prop, 432 + }; 433 + 434 + static int cht_wc_extcon_register_psy(struct cht_wc_extcon_data *ext) 435 + { 436 + struct power_supply_config psy_cfg = { .drv_data = ext }; 437 + 438 + ext->psy = devm_power_supply_register(ext->dev, 439 + &cht_wc_extcon_psy_desc, 440 + &psy_cfg); 441 + return PTR_ERR_OR_ZERO(ext->psy); 442 + } 443 + 389 444 static int cht_wc_extcon_probe(struct platform_device *pdev) 390 445 { 391 446 struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent); ··· 519 358 if (IS_ERR(ext->edev)) 520 359 return PTR_ERR(ext->edev); 521 360 522 - /* 523 - * When a host-cable is detected the BIOS enables an external 5v boost 524 - * converter to power connected devices there are 2 problems with this: 525 - * 1) This gets seen by the external battery charger as a valid Vbus 526 - * supply and it then tries to feed Vsys from this creating a 527 - * feedback loop which causes aprox. 300 mA extra battery drain 528 - * (and unless we drive the external-charger-disable pin high it 529 - * also tries to charge the battery causing even more feedback). 530 - * 2) This gets seen by the pwrsrc block as a SDP USB Vbus supply 531 - * Since the external battery charger has its own 5v boost converter 532 - * which does not have these issues, we simply turn the separate 533 - * external 5v boost converter off and leave it off entirely. 534 - */ 535 - cht_wc_extcon_set_5v_boost(ext, false); 361 + switch (pmic->cht_wc_model) { 362 + case INTEL_CHT_WC_GPD_WIN_POCKET: 363 + /* 364 + * When a host-cable is detected the BIOS enables an external 5v boost 365 + * converter to power connected devices there are 2 problems with this: 366 + * 1) This gets seen by the external battery charger as a valid Vbus 367 + * supply and it then tries to feed Vsys from this creating a 368 + * feedback loop which causes aprox. 300 mA extra battery drain 369 + * (and unless we drive the external-charger-disable pin high it 370 + * also tries to charge the battery causing even more feedback). 371 + * 2) This gets seen by the pwrsrc block as a SDP USB Vbus supply 372 + * Since the external battery charger has its own 5v boost converter 373 + * which does not have these issues, we simply turn the separate 374 + * external 5v boost converter off and leave it off entirely. 375 + */ 376 + cht_wc_extcon_set_5v_boost(ext, false); 377 + break; 378 + case INTEL_CHT_WC_LENOVO_YOGABOOK1: 379 + /* Do this first, as it may very well return -EPROBE_DEFER. */ 380 + ret = cht_wc_extcon_get_role_sw_and_regulator(ext); 381 + if (ret) 382 + return ret; 383 + /* 384 + * The bq25890 used here relies on this driver's BC-1.2 charger 385 + * detection, and the bq25890 driver expect this info to be 386 + * available through a parent power_supply class device which 387 + * models the detected charger (idem to how the Type-C TCPM code 388 + * registers a power_supply classdev for the connected charger). 389 + */ 390 + ret = cht_wc_extcon_register_psy(ext); 391 + if (ret) 392 + return ret; 393 + break; 394 + case INTEL_CHT_WC_XIAOMI_MIPAD2: 395 + ret = cht_wc_extcon_get_role_sw_and_regulator(ext); 396 + if (ret) 397 + return ret; 398 + break; 399 + default: 400 + break; 401 + } 536 402 537 403 /* Enable sw control */ 538 404 ret = cht_wc_extcon_sw_control(ext, true);
+102 -18
drivers/i2c/busses/i2c-cht-wc.c
··· 18 18 #include <linux/module.h> 19 19 #include <linux/platform_device.h> 20 20 #include <linux/power/bq24190_charger.h> 21 + #include <linux/power/bq25890_charger.h> 21 22 #include <linux/slab.h> 22 23 23 24 #define CHT_WC_I2C_CTRL 0x5e24 ··· 271 270 .name = "cht_wc_ext_chrg_irq_chip", 272 271 }; 273 272 273 + /********** GPD Win / Pocket charger IC settings **********/ 274 274 static const char * const bq24190_suppliers[] = { 275 275 "tcpm-source-psy-i2c-fusb302" }; 276 276 ··· 306 304 .regulator_init_data = &bq24190_vbus_init_data, 307 305 }; 308 306 307 + static struct i2c_board_info gpd_win_board_info = { 308 + .type = "bq24190", 309 + .addr = 0x6b, 310 + .dev_name = "bq24190", 311 + .swnode = &bq24190_node, 312 + .platform_data = &bq24190_pdata, 313 + }; 314 + 315 + /********** Xiaomi Mi Pad 2 charger IC settings **********/ 316 + static struct regulator_consumer_supply bq2589x_vbus_consumer = { 317 + .supply = "vbus", 318 + .dev_name = "cht_wcove_pwrsrc", 319 + }; 320 + 321 + static const struct regulator_init_data bq2589x_vbus_init_data = { 322 + .constraints = { 323 + .valid_ops_mask = REGULATOR_CHANGE_STATUS, 324 + }, 325 + .consumer_supplies = &bq2589x_vbus_consumer, 326 + .num_consumer_supplies = 1, 327 + }; 328 + 329 + static struct bq25890_platform_data bq2589x_pdata = { 330 + .regulator_init_data = &bq2589x_vbus_init_data, 331 + }; 332 + 333 + static const struct property_entry xiaomi_mipad2_props[] = { 334 + PROPERTY_ENTRY_BOOL("linux,skip-reset"), 335 + PROPERTY_ENTRY_BOOL("linux,read-back-settings"), 336 + { } 337 + }; 338 + 339 + static const struct software_node xiaomi_mipad2_node = { 340 + .properties = xiaomi_mipad2_props, 341 + }; 342 + 343 + static struct i2c_board_info xiaomi_mipad2_board_info = { 344 + .type = "bq25890", 345 + .addr = 0x6a, 346 + .dev_name = "bq25890", 347 + .swnode = &xiaomi_mipad2_node, 348 + .platform_data = &bq2589x_pdata, 349 + }; 350 + 351 + /********** Lenovo Yogabook YB1-X90F/-X91F/-X91L charger settings **********/ 352 + static const char * const lenovo_yb1_bq25892_suppliers[] = { "cht_wcove_pwrsrc" }; 353 + 354 + static const struct property_entry lenovo_yb1_bq25892_props[] = { 355 + PROPERTY_ENTRY_STRING_ARRAY("supplied-from", 356 + lenovo_yb1_bq25892_suppliers), 357 + PROPERTY_ENTRY_U32("linux,pump-express-vbus-max", 12000000), 358 + PROPERTY_ENTRY_BOOL("linux,skip-reset"), 359 + /* 360 + * The firmware sets everything to the defaults, which leads to a 361 + * somewhat low charge-current of 2048mA and worse to a battery-voltage 362 + * of 4.2V instead of 4.35V (when booted without a charger connected). 363 + * Use our own values instead of "linux,read-back-settings" to fix this. 364 + */ 365 + PROPERTY_ENTRY_U32("ti,charge-current", 4224000), 366 + PROPERTY_ENTRY_U32("ti,battery-regulation-voltage", 4352000), 367 + PROPERTY_ENTRY_U32("ti,termination-current", 256000), 368 + PROPERTY_ENTRY_U32("ti,precharge-current", 128000), 369 + PROPERTY_ENTRY_U32("ti,minimum-sys-voltage", 3500000), 370 + PROPERTY_ENTRY_U32("ti,boost-voltage", 4998000), 371 + PROPERTY_ENTRY_U32("ti,boost-max-current", 1400000), 372 + PROPERTY_ENTRY_BOOL("ti,use-ilim-pin"), 373 + { } 374 + }; 375 + 376 + static const struct software_node lenovo_yb1_bq25892_node = { 377 + .properties = lenovo_yb1_bq25892_props, 378 + }; 379 + 380 + static struct i2c_board_info lenovo_yogabook1_board_info = { 381 + .type = "bq25892", 382 + .addr = 0x6b, 383 + .dev_name = "bq25892", 384 + .swnode = &lenovo_yb1_bq25892_node, 385 + .platform_data = &bq2589x_pdata, 386 + }; 387 + 309 388 static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev) 310 389 { 311 390 struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent); 391 + struct i2c_board_info *board_info = NULL; 312 392 struct cht_wc_i2c_adap *adap; 313 - struct i2c_board_info board_info = { 314 - .type = "bq24190", 315 - .addr = 0x6b, 316 - .dev_name = "bq24190", 317 - .swnode = &bq24190_node, 318 - .platform_data = &bq24190_pdata, 319 - }; 320 393 int ret, reg, irq; 321 394 322 395 irq = platform_get_irq(pdev, 0); ··· 456 379 if (ret) 457 380 goto remove_irq_domain; 458 381 459 - /* 460 - * Normally the Whiskey Cove PMIC is paired with a TI bq24292i charger, 461 - * connected to this i2c bus, and a max17047 fuel-gauge and a fusb302 462 - * USB Type-C controller connected to another i2c bus. In this setup 463 - * the max17047 and fusb302 devices are enumerated through an INT33FE 464 - * ACPI device. If this device is present register an i2c-client for 465 - * the TI bq24292i charger. 466 - */ 467 - if (acpi_dev_present("INT33FE", NULL, -1)) { 468 - board_info.irq = adap->client_irq; 469 - adap->client = i2c_new_client_device(&adap->adapter, &board_info); 382 + switch (pmic->cht_wc_model) { 383 + case INTEL_CHT_WC_GPD_WIN_POCKET: 384 + board_info = &gpd_win_board_info; 385 + break; 386 + case INTEL_CHT_WC_XIAOMI_MIPAD2: 387 + board_info = &xiaomi_mipad2_board_info; 388 + break; 389 + case INTEL_CHT_WC_LENOVO_YOGABOOK1: 390 + board_info = &lenovo_yogabook1_board_info; 391 + break; 392 + default: 393 + dev_warn(&pdev->dev, "Unknown model, not instantiating charger device\n"); 394 + break; 395 + } 396 + 397 + if (board_info) { 398 + board_info->irq = adap->client_irq; 399 + adap->client = i2c_new_client_device(&adap->adapter, board_info); 470 400 if (IS_ERR(adap->client)) { 471 401 ret = PTR_ERR(adap->client); 472 402 goto del_adapter;
+40
drivers/mfd/intel_soc_pmic_chtwc.c
··· 10 10 11 11 #include <linux/acpi.h> 12 12 #include <linux/delay.h> 13 + #include <linux/dmi.h> 13 14 #include <linux/err.h> 14 15 #include <linux/i2c.h> 15 16 #include <linux/interrupt.h> ··· 135 134 .num_regs = 1, 136 135 }; 137 136 137 + static const struct dmi_system_id cht_wc_model_dmi_ids[] = { 138 + { 139 + /* GPD win / GPD pocket mini laptops */ 140 + .driver_data = (void *)(long)INTEL_CHT_WC_GPD_WIN_POCKET, 141 + /* 142 + * This DMI match may not seem unique, but it is. In the 67000+ 143 + * DMI decode dumps from linux-hardware.org only 116 have 144 + * board_vendor set to "AMI Corporation" and of those 116 only 145 + * the GPD win's and pocket's board_name is "Default string". 146 + */ 147 + .matches = { 148 + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), 149 + DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"), 150 + DMI_EXACT_MATCH(DMI_BOARD_SERIAL, "Default string"), 151 + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"), 152 + }, 153 + }, { 154 + /* Xiaomi Mi Pad 2 */ 155 + .driver_data = (void *)(long)INTEL_CHT_WC_XIAOMI_MIPAD2, 156 + .matches = { 157 + DMI_MATCH(DMI_SYS_VENDOR, "Xiaomi Inc"), 158 + DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"), 159 + }, 160 + }, { 161 + /* Lenovo Yoga Book X90F / X91F / X91L */ 162 + .driver_data = (void *)(long)INTEL_CHT_WC_LENOVO_YOGABOOK1, 163 + .matches = { 164 + /* Non exact match to match all versions */ 165 + DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X9"), 166 + }, 167 + }, 168 + { } 169 + }; 170 + 138 171 static int cht_wc_probe(struct i2c_client *client) 139 172 { 140 173 struct device *dev = &client->dev; 174 + const struct dmi_system_id *id; 141 175 struct intel_soc_pmic *pmic; 142 176 acpi_status status; 143 177 unsigned long long hrv; ··· 195 159 pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL); 196 160 if (!pmic) 197 161 return -ENOMEM; 162 + 163 + id = dmi_first_match(cht_wc_model_dmi_ids); 164 + if (id) 165 + pmic->cht_wc_model = (long)id->driver_data; 198 166 199 167 pmic->irq = client->irq; 200 168 pmic->dev = dev;
+2 -2
drivers/power/reset/gemini-poweroff.c
··· 107 107 return PTR_ERR(gpw->base); 108 108 109 109 irq = platform_get_irq(pdev, 0); 110 - if (!irq) 111 - return -EINVAL; 110 + if (irq < 0) 111 + return irq; 112 112 113 113 gpw->dev = dev; 114 114
+33 -2
drivers/power/supply/Kconfig
··· 51 51 Say Y here to enable support for the generic battery driver 52 52 which uses IIO framework to read adc. 53 53 54 + config IP5XXX_POWER 55 + tristate "Injoinic IP5xxx power bank IC driver" 56 + depends on I2C 57 + select REGMAP_I2C 58 + help 59 + Say Y to include support for Injoinic IP5xxx power bank ICs, 60 + which include a battery charger and a boost converter. 61 + 54 62 config MAX8925_POWER 55 63 tristate "MAX8925 battery charger support" 56 64 depends on MFD_MAX8925 ··· 188 180 depends on OLPC_EC 189 181 help 190 182 Say Y to enable support for the battery on the OLPC laptop. 183 + 184 + config BATTERY_SAMSUNG_SDI 185 + bool "Samsung SDI batteries" 186 + help 187 + Say Y to enable support for Samsung SDI battery data. 188 + These batteries are used in Samsung mobile phones. 191 189 192 190 config BATTERY_TOSA 193 191 tristate "Sharp SL-6000 (tosa) battery" ··· 365 351 366 352 config AXP288_CHARGER 367 353 tristate "X-Powers AXP288 Charger" 368 - depends on MFD_AXP20X && EXTCON_AXP288 && IOSF_MBI 354 + depends on MFD_AXP20X && EXTCON_AXP288 && IOSF_MBI && ACPI 369 355 help 370 356 Say yes here to have support X-Power AXP288 power management IC (PMIC) 371 357 integrated charger. 372 358 373 359 config AXP288_FUEL_GAUGE 374 360 tristate "X-Powers AXP288 Fuel Gauge" 375 - depends on MFD_AXP20X && IIO && IOSF_MBI 361 + depends on MFD_AXP20X && IIO && IOSF_MBI && ACPI 376 362 help 377 363 Say yes here to have support for X-Power power management IC (PMIC) 378 364 Fuel Gauge. The device provides battery statistics and status ··· 742 728 config AB8500_BM 743 729 bool "AB8500 Battery Management Driver" 744 730 depends on AB8500_CORE && AB8500_GPADC && (IIO = y) && OF 731 + select THERMAL 732 + select THERMAL_OF 745 733 help 746 734 Say Y to include support for AB8500 battery management. 747 735 ··· 881 865 Say M or Y here to include AC status support for 7th-generation 882 866 Microsoft Surface devices, i.e. Surface Pro 7, Surface Laptop 3, 883 867 Surface Book 3, and Surface Laptop Go. 868 + 869 + config BATTERY_UG3105 870 + tristate "uPI uG3105 battery monitor driver" 871 + depends on I2C 872 + help 873 + Battery monitor driver for the uPI uG3105 battery monitor. 874 + 875 + Note the uG3105 is not a full-featured autonomous fuel-gauge. Instead 876 + it is expected to be use in combination with some always on 877 + microcontroller reading its coulomb-counter before it can wrap 878 + (it must be read every 400 seconds!). 879 + 880 + Since Linux does not monitor coulomb-counter changes while the 881 + device is off or suspended, the functionality of this driver is 882 + limited to reporting capacity only. 884 883 885 884 endif # POWER_SUPPLY
+3
drivers/power/supply/Makefile
··· 12 12 obj-$(CONFIG_PDA_POWER) += pda_power.o 13 13 obj-$(CONFIG_APM_POWER) += apm_power.o 14 14 obj-$(CONFIG_AXP20X_POWER) += axp20x_usb_power.o 15 + obj-$(CONFIG_IP5XXX_POWER) += ip5xxx_power.o 15 16 obj-$(CONFIG_MAX8925_POWER) += max8925_power.o 16 17 obj-$(CONFIG_WM831X_BACKUP) += wm831x_backup.o 17 18 obj-$(CONFIG_WM831X_POWER) += wm831x_power.o ··· 35 34 obj-$(CONFIG_BATTERY_LEGO_EV3) += lego_ev3_battery.o 36 35 obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o 37 36 obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o 37 + obj-$(CONFIG_BATTERY_SAMSUNG_SDI) += samsung-sdi-battery.o 38 38 obj-$(CONFIG_BATTERY_TOSA) += tosa_battery.o 39 39 obj-$(CONFIG_BATTERY_COLLIE) += collie_battery.o 40 40 obj-$(CONFIG_BATTERY_INGENIC) += ingenic-battery.o ··· 107 105 obj-$(CONFIG_BATTERY_ACER_A500) += acer_a500_battery.o 108 106 obj-$(CONFIG_BATTERY_SURFACE) += surface_battery.o 109 107 obj-$(CONFIG_CHARGER_SURFACE) += surface_charger.o 108 + obj-$(CONFIG_BATTERY_UG3105) += ug3105_battery.o
-79
drivers/power/supply/ab8500-bm.h
··· 260 260 #define BUS_PP_PRECHG_CURRENT_MASK 0x0E 261 261 #define BUS_POWER_PATH_PRECHG_ENA 0x01 262 262 263 - /* 264 - * ADC for the battery thermistor. 265 - * When using the AB8500_ADC_THERM_BATCTRL the battery ID resistor is combined 266 - * with a NTC resistor to both identify the battery and to measure its 267 - * temperature. Different phone manufactures uses different techniques to both 268 - * identify the battery and to read its temperature. 269 - */ 270 - enum ab8500_adc_therm { 271 - AB8500_ADC_THERM_BATCTRL, 272 - AB8500_ADC_THERM_BATTEMP, 273 - }; 274 - 275 - /** 276 - * struct ab8500_res_to_temp - defines one point in a temp to res curve. To 277 - * be used in battery packs that combines the identification resistor with a 278 - * NTC resistor. 279 - * @temp: battery pack temperature in Celsius 280 - * @resist: NTC resistor net total resistance 281 - */ 282 - struct ab8500_res_to_temp { 283 - int temp; 284 - int resist; 285 - }; 286 - 287 263 /* Forward declaration */ 288 264 struct ab8500_fg; 289 265 ··· 328 352 }; 329 353 330 354 /** 331 - * struct ab8500_battery_type - different batteries supported 332 - * @resis_high: battery upper resistance limit 333 - * @resis_low: battery lower resistance limit 334 - * @maint_a_cur_lvl: charger current in maintenance A state in mA 335 - * @maint_a_vol_lvl: charger voltage in maintenance A state in mV 336 - * @maint_a_chg_timer_h: charge time in maintenance A state 337 - * @maint_b_cur_lvl: charger current in maintenance B state in mA 338 - * @maint_b_vol_lvl: charger voltage in maintenance B state in mV 339 - * @maint_b_chg_timer_h: charge time in maintenance B state 340 - * @low_high_cur_lvl: charger current in temp low/high state in mA 341 - * @low_high_vol_lvl: charger voltage in temp low/high state in mV' 342 - * @n_r_t_tbl_elements: number of elements in r_to_t_tbl 343 - * @r_to_t_tbl: table containing resistance to temp points 344 - */ 345 - struct ab8500_battery_type { 346 - int resis_high; 347 - int resis_low; 348 - int maint_a_cur_lvl; 349 - int maint_a_vol_lvl; 350 - int maint_a_chg_timer_h; 351 - int maint_b_cur_lvl; 352 - int maint_b_vol_lvl; 353 - int maint_b_chg_timer_h; 354 - int low_high_cur_lvl; 355 - int low_high_vol_lvl; 356 - int n_temp_tbl_elements; 357 - const struct ab8500_res_to_temp *r_to_t_tbl; 358 - }; 359 - 360 - /** 361 355 * struct ab8500_bm_capacity_levels - ab8500 capacity level data 362 356 * @critical: critical capacity level in percent 363 357 * @low: low capacity level in percent ··· 367 421 * @usb_safety_tmr_h safety timer for usb charger 368 422 * @bkup_bat_v voltage which we charge the backup battery with 369 423 * @bkup_bat_i current which we charge the backup battery with 370 - * @no_maintenance indicates that maintenance charging is disabled 371 424 * @capacity_scaling indicates whether capacity scaling is to be used 372 - * @ab8500_adc_therm placement of thermistor, batctrl or battemp adc 373 425 * @chg_unknown_bat flag to enable charging of unknown batteries 374 426 * @enable_overshoot flag to enable VBAT overshoot control 375 427 * @auto_trig flag to enable auto adc trigger ··· 375 431 * @interval_charging charge alg cycle period time when charging (sec) 376 432 * @interval_not_charging charge alg cycle period time when not charging (sec) 377 433 * @temp_hysteresis temperature hysteresis 378 - * @gnd_lift_resistance Battery ground to phone ground resistance (mOhm) 379 434 * @maxi maximization parameters 380 435 * @cap_levels capacity in percent for the different capacity levels 381 - * @bat_type table of supported battery types 382 436 * @chg_params charger parameters 383 437 * @fg_params fuel gauge parameters 384 438 */ ··· 389 447 int usb_safety_tmr_h; 390 448 int bkup_bat_v; 391 449 int bkup_bat_i; 392 - bool no_maintenance; 393 450 bool capacity_scaling; 394 451 bool chg_unknown_bat; 395 452 bool enable_overshoot; 396 453 bool auto_trig; 397 - enum ab8500_adc_therm adc_therm; 398 454 int fg_res; 399 455 int interval_charging; 400 456 int interval_not_charging; 401 457 int temp_hysteresis; 402 - int gnd_lift_resistance; 403 458 const struct ab8500_maxim_parameters *maxi; 404 459 const struct ab8500_bm_capacity_levels *cap_levels; 405 - struct ab8500_battery_type *bat_type; 406 460 const struct ab8500_bm_charger_parameters *chg_params; 407 461 const struct ab8500_fg_parameters *fg_params; 408 - }; 409 - 410 - enum { 411 - NTC_EXTERNAL = 0, 412 - NTC_INTERNAL, 413 - }; 414 - 415 - /** 416 - * struct res_to_temp - defines one point in a temp to res curve. To 417 - * be used in battery packs that combines the identification resistor with a 418 - * NTC resistor. 419 - * @temp: battery pack temperature in Celsius 420 - * @resist: NTC resistor net total resistance 421 - */ 422 - struct res_to_temp { 423 - int temp; 424 - int resist; 425 462 }; 426 463 427 464 /* Forward declaration */
+41 -45
drivers/power/supply/ab8500_bmdata.c
··· 44 44 }; 45 45 46 46 /* 47 - * Note that the res_to_temp table must be strictly sorted by falling 48 - * resistance values to work. 49 - */ 50 - static const struct ab8500_res_to_temp temp_tbl[] = { 51 - {-5, 214834}, 52 - { 0, 162943}, 53 - { 5, 124820}, 54 - {10, 96520}, 55 - {15, 75306}, 56 - {20, 59254}, 57 - {25, 47000}, 58 - {30, 37566}, 59 - {35, 30245}, 60 - {40, 24520}, 61 - {45, 20010}, 62 - {50, 16432}, 63 - {55, 13576}, 64 - {60, 11280}, 65 - {65, 9425}, 66 - }; 67 - 68 - /* 69 47 * Note that the batres_vs_temp table must be strictly sorted by falling 70 48 * temperature values to work. Factory resistance is 300 mOhm and the 71 49 * resistance values to the right are percentages of 300 mOhm. ··· 58 80 { .temp = -20, .resistance = 198 /* 595 mOhm */ }, 59 81 }; 60 82 61 - /* Default battery type for reference designs is the unknown type */ 62 - static struct ab8500_battery_type bat_type_thermistor_unknown = { 63 - .resis_high = 0, 64 - .resis_low = 0, 65 - .maint_a_cur_lvl = 400, 66 - .maint_a_vol_lvl = 4050, 67 - .maint_a_chg_timer_h = 60, 68 - .maint_b_cur_lvl = 400, 69 - .maint_b_vol_lvl = 4000, 70 - .maint_b_chg_timer_h = 200, 71 - .low_high_cur_lvl = 300, 72 - .low_high_vol_lvl = 4000, 73 - .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), 74 - .r_to_t_tbl = temp_tbl, 83 + static struct power_supply_maintenance_charge_table ab8500_maint_charg_table[] = { 84 + { 85 + /* Maintenance charging phase A, 60 hours */ 86 + .charge_current_max_ua = 400000, 87 + .charge_voltage_max_uv = 4050000, 88 + .charge_safety_timer_minutes = 60*60, 89 + }, 90 + { 91 + /* Maintenance charging phase B, 200 hours */ 92 + .charge_current_max_ua = 400000, 93 + .charge_voltage_max_uv = 4000000, 94 + .charge_safety_timer_minutes = 200*60, 95 + } 75 96 }; 76 97 77 98 static const struct ab8500_bm_capacity_levels cap_levels = { ··· 125 148 .usb_safety_tmr_h = 4, 126 149 .bkup_bat_v = BUP_VCH_SEL_2P6V, 127 150 .bkup_bat_i = BUP_ICH_SEL_150UA, 128 - .no_maintenance = false, 129 151 .capacity_scaling = false, 130 - .adc_therm = AB8500_ADC_THERM_BATCTRL, 131 152 .chg_unknown_bat = false, 132 153 .enable_overshoot = false, 133 154 .fg_res = 100, 134 155 .cap_levels = &cap_levels, 135 - .bat_type = &bat_type_thermistor_unknown, 136 156 .interval_charging = 5, 137 157 .interval_not_charging = 120, 138 - .gnd_lift_resistance = 34, 139 158 .maxi = &ab8500_maxi_params, 140 159 .chg_params = &chg, 141 160 .fg_params = &fg, ··· 161 188 * fall back to safe defaults. 162 189 */ 163 190 if ((bi->voltage_min_design_uv < 0) || 164 - (bi->voltage_max_design_uv < 0) || 165 - (bi->overvoltage_limit_uv < 0)) { 191 + (bi->voltage_max_design_uv < 0)) { 166 192 /* Nominal voltage is 3.7V for unknown batteries */ 167 193 bi->voltage_min_design_uv = 3700000; 168 - bi->voltage_max_design_uv = 3700000; 169 - /* Termination voltage (overcharge limit) 4.05V */ 170 - bi->overvoltage_limit_uv = 4050000; 194 + /* Termination voltage 4.05V */ 195 + bi->voltage_max_design_uv = 4050000; 171 196 } 172 197 173 198 if (bi->constant_charge_current_max_ua < 0) ··· 178 207 /* Charging stops when we drop below this current */ 179 208 bi->charge_term_current_ua = 200000; 180 209 210 + if (!bi->maintenance_charge || !bi->maintenance_charge_size) { 211 + bi->maintenance_charge = ab8500_maint_charg_table; 212 + bi->maintenance_charge_size = ARRAY_SIZE(ab8500_maint_charg_table); 213 + } 214 + 215 + if (bi->alert_low_temp_charge_current_ua < 0 || 216 + bi->alert_low_temp_charge_voltage_uv < 0) 217 + { 218 + bi->alert_low_temp_charge_current_ua = 300000; 219 + bi->alert_low_temp_charge_voltage_uv = 4000000; 220 + } 221 + if (bi->alert_high_temp_charge_current_ua < 0 || 222 + bi->alert_high_temp_charge_voltage_uv < 0) 223 + { 224 + bi->alert_high_temp_charge_current_ua = 300000; 225 + bi->alert_high_temp_charge_voltage_uv = 4000000; 226 + } 227 + 181 228 /* 182 229 * Internal resistance and factory resistance are tightly coupled 183 230 * so both MUST be defined or we fall back to defaults. ··· 205 216 bi->factory_internal_resistance_uohm = 300000; 206 217 bi->resist_table = temp_to_batres_tbl_thermistor; 207 218 bi->resist_table_size = ARRAY_SIZE(temp_to_batres_tbl_thermistor); 219 + } 220 + 221 + /* The default battery is emulated by a resistor at 7K */ 222 + if (bi->bti_resistance_ohm < 0 || 223 + bi->bti_resistance_tolerance < 0) { 224 + bi->bti_resistance_ohm = 7000; 225 + bi->bti_resistance_tolerance = 20; 208 226 } 209 227 210 228 if (!bi->ocv_table[0]) {
+33 -309
drivers/power/supply/ab8500_btemp.c
··· 26 26 #include <linux/mfd/core.h> 27 27 #include <linux/mfd/abx500.h> 28 28 #include <linux/mfd/abx500/ab8500.h> 29 + #include <linux/thermal.h> 29 30 #include <linux/iio/consumer.h> 30 31 #include <linux/fixp-arith.h> 31 32 32 33 #include "ab8500-bm.h" 33 - 34 - #define VTVOUT_V 1800 35 34 36 35 #define BTEMP_THERMAL_LOW_LIMIT -10 37 36 #define BTEMP_THERMAL_MED_LIMIT 0 ··· 81 82 * @bat_temp: Dispatched battery temperature in degree Celsius 82 83 * @prev_bat_temp Last measured battery temperature in degree Celsius 83 84 * @parent: Pointer to the struct ab8500 84 - * @adc_btemp_ball: ADC channel for the battery ball temperature 85 + * @tz: Thermal zone for the battery 85 86 * @adc_bat_ctrl: ADC channel for the battery control 86 87 * @fg: Pointer to the struct fg 87 88 * @bm: Platform specific battery management information ··· 99 100 int bat_temp; 100 101 int prev_bat_temp; 101 102 struct ab8500 *parent; 102 - struct iio_channel *btemp_ball; 103 + struct thermal_zone_device *tz; 103 104 struct iio_channel *bat_ctrl; 104 105 struct ab8500_fg *fg; 105 106 struct ab8500_bm_data *bm; ··· 134 135 static int ab8500_btemp_batctrl_volt_to_res(struct ab8500_btemp *di, 135 136 int v_batctrl, int inst_curr) 136 137 { 137 - int rbs; 138 - 139 138 if (is_ab8500_1p1_or_earlier(di->parent)) { 140 139 /* 141 140 * For ABB cut1.0 and 1.1 BAT_CTRL is internally ··· 142 145 return (450000 * (v_batctrl)) / (1800 - v_batctrl); 143 146 } 144 147 145 - if (di->bm->adc_therm == AB8500_ADC_THERM_BATCTRL) { 146 - /* 147 - * If the battery has internal NTC, we use the current 148 - * source to calculate the resistance. 149 - */ 150 - rbs = (v_batctrl * 1000 151 - - di->bm->gnd_lift_resistance * inst_curr) 152 - / di->curr_source; 153 - } else { 154 - /* 155 - * BAT_CTRL is internally 156 - * connected to 1.8V through a 80k resistor 157 - */ 158 - rbs = (80000 * (v_batctrl)) / (1800 - v_batctrl); 159 - } 160 - 161 - return rbs; 148 + /* 149 + * BAT_CTRL is internally 150 + * connected to 1.8V through a 80k resistor 151 + */ 152 + return (80000 * (v_batctrl)) / (1800 - v_batctrl); 162 153 } 163 154 164 155 /** ··· 172 187 } 173 188 174 189 /** 175 - * ab8500_btemp_curr_source_enable() - enable/disable batctrl current source 176 - * @di: pointer to the ab8500_btemp structure 177 - * @enable: enable or disable the current source 178 - * 179 - * Enable or disable the current sources for the BatCtrl AD channel 180 - */ 181 - static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di, 182 - bool enable) 183 - { 184 - int curr; 185 - int ret = 0; 186 - 187 - /* 188 - * BATCTRL current sources are included on AB8500 cut2.0 189 - * and future versions 190 - */ 191 - if (is_ab8500_1p1_or_earlier(di->parent)) 192 - return 0; 193 - 194 - /* Only do this for batteries with internal NTC */ 195 - if (di->bm->adc_therm == AB8500_ADC_THERM_BATCTRL && enable) { 196 - 197 - if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_7UA) 198 - curr = BAT_CTRL_7U_ENA; 199 - else 200 - curr = BAT_CTRL_20U_ENA; 201 - 202 - dev_dbg(di->dev, "Set BATCTRL %duA\n", di->curr_source); 203 - 204 - ret = abx500_mask_and_set_register_interruptible(di->dev, 205 - AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, 206 - FORCE_BAT_CTRL_CMP_HIGH, FORCE_BAT_CTRL_CMP_HIGH); 207 - if (ret) { 208 - dev_err(di->dev, "%s failed setting cmp_force\n", 209 - __func__); 210 - return ret; 211 - } 212 - 213 - /* 214 - * We have to wait one 32kHz cycle before enabling 215 - * the current source, since ForceBatCtrlCmpHigh needs 216 - * to be written in a separate cycle 217 - */ 218 - udelay(32); 219 - 220 - ret = abx500_set_register_interruptible(di->dev, 221 - AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, 222 - FORCE_BAT_CTRL_CMP_HIGH | curr); 223 - if (ret) { 224 - dev_err(di->dev, "%s failed enabling current source\n", 225 - __func__); 226 - goto disable_curr_source; 227 - } 228 - } else if (di->bm->adc_therm == AB8500_ADC_THERM_BATCTRL && !enable) { 229 - dev_dbg(di->dev, "Disable BATCTRL curr source\n"); 230 - 231 - /* Write 0 to the curr bits */ 232 - ret = abx500_mask_and_set_register_interruptible( 233 - di->dev, 234 - AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, 235 - BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA, 236 - ~(BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA)); 237 - 238 - if (ret) { 239 - dev_err(di->dev, "%s failed disabling current source\n", 240 - __func__); 241 - goto disable_curr_source; 242 - } 243 - 244 - /* Enable Pull-Up and comparator */ 245 - ret = abx500_mask_and_set_register_interruptible(di->dev, 246 - AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, 247 - BAT_CTRL_PULL_UP_ENA | BAT_CTRL_CMP_ENA, 248 - BAT_CTRL_PULL_UP_ENA | BAT_CTRL_CMP_ENA); 249 - if (ret) { 250 - dev_err(di->dev, "%s failed enabling PU and comp\n", 251 - __func__); 252 - goto enable_pu_comp; 253 - } 254 - 255 - /* 256 - * We have to wait one 32kHz cycle before disabling 257 - * ForceBatCtrlCmpHigh since this needs to be written 258 - * in a separate cycle 259 - */ 260 - udelay(32); 261 - 262 - /* Disable 'force comparator' */ 263 - ret = abx500_mask_and_set_register_interruptible(di->dev, 264 - AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, 265 - FORCE_BAT_CTRL_CMP_HIGH, ~FORCE_BAT_CTRL_CMP_HIGH); 266 - if (ret) { 267 - dev_err(di->dev, "%s failed disabling force comp\n", 268 - __func__); 269 - goto disable_force_comp; 270 - } 271 - } 272 - return ret; 273 - 274 - /* 275 - * We have to try unsetting FORCE_BAT_CTRL_CMP_HIGH one more time 276 - * if we got an error above 277 - */ 278 - disable_curr_source: 279 - /* Write 0 to the curr bits */ 280 - ret = abx500_mask_and_set_register_interruptible(di->dev, 281 - AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, 282 - BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA, 283 - ~(BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA)); 284 - 285 - if (ret) { 286 - dev_err(di->dev, "%s failed disabling current source\n", 287 - __func__); 288 - return ret; 289 - } 290 - enable_pu_comp: 291 - /* Enable Pull-Up and comparator */ 292 - ret = abx500_mask_and_set_register_interruptible(di->dev, 293 - AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, 294 - BAT_CTRL_PULL_UP_ENA | BAT_CTRL_CMP_ENA, 295 - BAT_CTRL_PULL_UP_ENA | BAT_CTRL_CMP_ENA); 296 - if (ret) { 297 - dev_err(di->dev, "%s failed enabling PU and comp\n", 298 - __func__); 299 - return ret; 300 - } 301 - 302 - disable_force_comp: 303 - /* 304 - * We have to wait one 32kHz cycle before disabling 305 - * ForceBatCtrlCmpHigh since this needs to be written 306 - * in a separate cycle 307 - */ 308 - udelay(32); 309 - 310 - /* Disable 'force comparator' */ 311 - ret = abx500_mask_and_set_register_interruptible(di->dev, 312 - AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, 313 - FORCE_BAT_CTRL_CMP_HIGH, ~FORCE_BAT_CTRL_CMP_HIGH); 314 - if (ret) { 315 - dev_err(di->dev, "%s failed disabling force comp\n", 316 - __func__); 317 - return ret; 318 - } 319 - 320 - return ret; 321 - } 322 - 323 - /** 324 190 * ab8500_btemp_get_batctrl_res() - get battery resistance 325 191 * @di: pointer to the ab8500_btemp structure 326 192 * ··· 185 349 int res; 186 350 int inst_curr; 187 351 int i; 188 - 189 - /* 190 - * BATCTRL current sources are included on AB8500 cut2.0 191 - * and future versions 192 - */ 193 - ret = ab8500_btemp_curr_source_enable(di, true); 194 - if (ret) { 195 - dev_err(di->dev, "%s curr source enabled failed\n", __func__); 196 - return ret; 197 - } 198 352 199 353 if (!di->fg) 200 354 di->fg = ab8500_fg_get(); ··· 221 395 222 396 res = ab8500_btemp_batctrl_volt_to_res(di, batctrl, inst_curr); 223 397 224 - ret = ab8500_btemp_curr_source_enable(di, false); 225 - if (ret) { 226 - dev_err(di->dev, "%s curr source disable failed\n", __func__); 227 - return ret; 228 - } 229 - 230 398 dev_dbg(di->dev, "%s batctrl: %d res: %d inst_curr: %d samples: %d\n", 231 399 __func__, batctrl, res, inst_curr, i); 232 400 233 401 return res; 234 - } 235 - 236 - /** 237 - * ab8500_btemp_res_to_temp() - resistance to temperature 238 - * @di: pointer to the ab8500_btemp structure 239 - * @tbl: pointer to the resiatance to temperature table 240 - * @tbl_size: size of the resistance to temperature table 241 - * @res: resistance to calculate the temperature from 242 - * 243 - * This function returns the battery temperature in degrees Celsius 244 - * based on the NTC resistance. 245 - */ 246 - static int ab8500_btemp_res_to_temp(struct ab8500_btemp *di, 247 - const struct ab8500_res_to_temp *tbl, int tbl_size, int res) 248 - { 249 - int i; 250 - /* 251 - * Calculate the formula for the straight line 252 - * Simple interpolation if we are within 253 - * the resistance table limits, extrapolate 254 - * if resistance is outside the limits. 255 - */ 256 - if (res > tbl[0].resist) 257 - i = 0; 258 - else if (res <= tbl[tbl_size - 1].resist) 259 - i = tbl_size - 2; 260 - else { 261 - i = 0; 262 - while (!(res <= tbl[i].resist && 263 - res > tbl[i + 1].resist)) 264 - i++; 265 - } 266 - 267 - return fixp_linear_interpolate(tbl[i].resist, tbl[i].temp, 268 - tbl[i + 1].resist, tbl[i + 1].temp, 269 - res); 270 - } 271 - 272 - /** 273 - * ab8500_btemp_measure_temp() - measure battery temperature 274 - * @di: pointer to the ab8500_btemp structure 275 - * 276 - * Returns battery temperature (on success) else the previous temperature 277 - */ 278 - static int ab8500_btemp_measure_temp(struct ab8500_btemp *di) 279 - { 280 - struct power_supply_battery_info *bi = di->bm->bi; 281 - int temp, ret; 282 - static int prev; 283 - int rbat, rntc, vntc; 284 - 285 - if ((di->bm->adc_therm == AB8500_ADC_THERM_BATCTRL) && 286 - (bi && (bi->technology == POWER_SUPPLY_TECHNOLOGY_UNKNOWN))) { 287 - 288 - rbat = ab8500_btemp_get_batctrl_res(di); 289 - if (rbat < 0) { 290 - dev_err(di->dev, "%s get batctrl res failed\n", 291 - __func__); 292 - /* 293 - * Return out-of-range temperature so that 294 - * charging is stopped 295 - */ 296 - return BTEMP_THERMAL_LOW_LIMIT; 297 - } 298 - 299 - temp = ab8500_btemp_res_to_temp(di, 300 - di->bm->bat_type->r_to_t_tbl, 301 - di->bm->bat_type->n_temp_tbl_elements, rbat); 302 - } else { 303 - ret = iio_read_channel_processed(di->btemp_ball, &vntc); 304 - if (ret < 0) { 305 - dev_err(di->dev, 306 - "%s ADC conversion failed," 307 - " using previous value\n", __func__); 308 - return prev; 309 - } 310 - /* 311 - * The PCB NTC is sourced from VTVOUT via a 230kOhm 312 - * resistor. 313 - */ 314 - rntc = 230000 * vntc / (VTVOUT_V - vntc); 315 - 316 - temp = ab8500_btemp_res_to_temp(di, 317 - di->bm->bat_type->r_to_t_tbl, 318 - di->bm->bat_type->n_temp_tbl_elements, rntc); 319 - prev = temp; 320 - } 321 - dev_dbg(di->dev, "Battery temperature is %d\n", temp); 322 - return temp; 323 402 } 324 403 325 404 /** ··· 237 506 */ 238 507 static int ab8500_btemp_id(struct ab8500_btemp *di) 239 508 { 509 + struct power_supply_battery_info *bi = di->bm->bi; 240 510 int res; 241 - u8 i; 242 511 243 512 di->curr_source = BTEMP_BATCTRL_CURR_SRC_7UA; 244 513 ··· 248 517 return -ENXIO; 249 518 } 250 519 251 - if ((res <= di->bm->bat_type->resis_high) && 252 - (res >= di->bm->bat_type->resis_low)) { 253 - dev_info(di->dev, "Battery detected on %s" 254 - " low %d < res %d < high: %d" 255 - " index: %d\n", 256 - di->bm->adc_therm == AB8500_ADC_THERM_BATCTRL ? 257 - "BATCTRL" : "BATTEMP", 258 - di->bm->bat_type->resis_low, res, 259 - di->bm->bat_type->resis_high, i); 520 + if (power_supply_battery_bti_in_range(bi, res)) { 521 + dev_info(di->dev, "Battery detected on BATCTRL (pin C3)" 522 + " resistance %d Ohm = %d Ohm +/- %d%%\n", 523 + res, bi->bti_resistance_ohm, 524 + bi->bti_resistance_tolerance); 260 525 } else { 261 526 dev_warn(di->dev, "Battery identified as unknown" 262 527 ", resistance %d Ohm\n", res); 263 528 return -ENXIO; 264 - } 265 - 266 - /* 267 - * We only have to change current source if the 268 - * detected type is Type 1 (LIPO) resis_high = 53407, resis_low = 12500 269 - * if someone hacks this in. 270 - * 271 - * FIXME: make sure this is done automatically for the batteries 272 - * that need it. 273 - */ 274 - if ((di->bm->adc_therm == AB8500_ADC_THERM_BATCTRL) && 275 - (di->bm->bi && (di->bm->bi->technology == POWER_SUPPLY_TECHNOLOGY_LIPO)) && 276 - (res <= 53407) && (res >= 12500)) { 277 - dev_dbg(di->dev, "Set BATCTRL current source to 20uA\n"); 278 - di->curr_source = BTEMP_BATCTRL_CURR_SRC_20UA; 279 529 } 280 530 281 531 return 0; ··· 274 562 int bat_temp; 275 563 struct ab8500_btemp *di = container_of(work, 276 564 struct ab8500_btemp, btemp_periodic_work.work); 565 + /* Assume 25 degrees celsius as start temperature */ 566 + static int prev = 25; 567 + int ret; 277 568 278 569 if (!di->initialized) { 279 570 /* Identify the battery */ ··· 284 569 dev_warn(di->dev, "failed to identify the battery\n"); 285 570 } 286 571 287 - bat_temp = ab8500_btemp_measure_temp(di); 572 + /* Failover if a reading is erroneous, use last meausurement */ 573 + ret = thermal_zone_get_temp(di->tz, &bat_temp); 574 + if (ret) { 575 + dev_err(di->dev, "error reading temperature\n"); 576 + bat_temp = prev; 577 + } else { 578 + /* Convert from millicentigrades to centigrades */ 579 + bat_temp /= 1000; 580 + prev = bat_temp; 581 + } 582 + 288 583 /* 289 584 * Filter battery temperature. 290 585 * Allow direct updates on temperature only if two samples result in ··· 723 998 di->dev = dev; 724 999 di->parent = dev_get_drvdata(pdev->dev.parent); 725 1000 726 - /* Get ADC channels */ 727 - di->btemp_ball = devm_iio_channel_get(dev, "btemp_ball"); 728 - if (IS_ERR(di->btemp_ball)) { 729 - ret = dev_err_probe(dev, PTR_ERR(di->btemp_ball), 730 - "failed to get BTEMP BALL ADC channel\n"); 731 - return ret; 1001 + /* Get thermal zone and ADC */ 1002 + di->tz = thermal_zone_get_zone_by_name("battery-thermal"); 1003 + if (IS_ERR(di->tz)) { 1004 + return dev_err_probe(dev, PTR_ERR(di->tz), 1005 + "failed to get battery thermal zone\n"); 732 1006 } 733 1007 di->bat_ctrl = devm_iio_channel_get(dev, "bat_ctrl"); 734 1008 if (IS_ERR(di->bat_ctrl)) {
+80 -338
drivers/power/supply/ab8500_chargalg.c
··· 46 46 /* Five minutes expressed in seconds */ 47 47 #define FIVE_MINUTES_IN_SECONDS 300 48 48 49 - #define CHARGALG_CURR_STEP_LOW_UA 0 50 - #define CHARGALG_CURR_STEP_HIGH_UA 100000 51 - 52 49 /* 53 50 * This is the battery capacity limit that will trigger a new 54 51 * full charging cycle in the case where maintenance charging ··· 77 80 int ac_iset_ua; 78 81 }; 79 82 80 - struct ab8500_chargalg_suspension_status { 81 - bool suspended_change; 82 - bool ac_suspended; 83 - bool usb_suspended; 84 - }; 85 - 86 - struct ab8500_chargalg_current_step_status { 87 - bool curr_step_change; 88 - int curr_step_ua; 89 - }; 90 - 91 83 struct ab8500_chargalg_battery_data { 92 84 int temp; 93 85 int volt_uv; ··· 104 118 STATE_TEMP_UNDEROVER, 105 119 STATE_TEMP_LOWHIGH_INIT, 106 120 STATE_TEMP_LOWHIGH, 107 - STATE_SUSPENDED_INIT, 108 - STATE_SUSPENDED, 109 121 STATE_OVV_PROTECT_INIT, 110 122 STATE_OVV_PROTECT, 111 123 STATE_SAFETY_TIMER_EXPIRED_INIT, ··· 133 149 "TEMP_UNDEROVER", 134 150 "TEMP_LOWHIGH_INIT", 135 151 "TEMP_LOWHIGH", 136 - "SUSPENDED_INIT", 137 - "SUSPENDED", 138 152 "OVV_PROTECT_INIT", 139 153 "OVV_PROTECT", 140 154 "SAFETY_TIMER_EXPIRED_INIT", ··· 149 167 bool batt_ovv; 150 168 bool batt_rem; 151 169 bool btemp_underover; 152 - bool btemp_lowhigh; 170 + bool btemp_low; 171 + bool btemp_high; 153 172 bool main_thermal_prot; 154 173 bool usb_thermal_prot; 155 174 bool main_ovv; ··· 169 186 * struct ab8500_charge_curr_maximization - Charger maximization parameters 170 187 * @original_iset_ua: the non optimized/maximised charger current 171 188 * @current_iset_ua: the charging current used at this moment 172 - * @test_delta_i_ua: the delta between the current we want to charge and the 173 - current that is really going into the battery 174 189 * @condition_cnt: number of iterations needed before a new charger current 175 190 is set 176 191 * @max_current_ua: maximum charger current ··· 181 200 struct ab8500_charge_curr_maximization { 182 201 int original_iset_ua; 183 202 int current_iset_ua; 184 - int test_delta_i_ua; 185 203 int condition_cnt; 186 204 int max_current_ua; 187 205 int wait_cnt; ··· 207 227 * @ccm charging current maximization parameters 208 228 * @chg_info: information about connected charger types 209 229 * @batt_data: data of the battery 210 - * @susp_status: current charger suspension status 211 230 * @bm: Platform specific battery management information 212 - * @curr_status: Current step status for over-current protection 213 231 * @parent: pointer to the struct ab8500 214 232 * @chargalg_psy: structure that holds the battery properties exposed by 215 233 * the charging algorithm ··· 231 253 struct ab8500_charge_curr_maximization ccm; 232 254 struct ab8500_chargalg_charger_info chg_info; 233 255 struct ab8500_chargalg_battery_data batt_data; 234 - struct ab8500_chargalg_suspension_status susp_status; 235 256 struct ab8500 *parent; 236 - struct ab8500_chargalg_current_step_status curr_status; 237 257 struct ab8500_bm_data *bm; 238 258 struct power_supply *chargalg_psy; 239 259 struct ux500_charger *ac_chg; ··· 287 311 * the maintenance timer 288 312 * @timer: pointer to the timer structure 289 313 * 290 - * This function gets called when the maintenence timer 314 + * This function gets called when the maintenance timer 291 315 * expires 292 316 */ 293 317 static enum hrtimer_restart ··· 361 385 */ 362 386 static int ab8500_chargalg_check_charger_connection(struct ab8500_chargalg *di) 363 387 { 364 - if (di->chg_info.conn_chg != di->chg_info.prev_conn_chg || 365 - di->susp_status.suspended_change) { 366 - /* 367 - * Charger state changed or suspension 368 - * has changed since last update 369 - */ 370 - if ((di->chg_info.conn_chg & AC_CHG) && 371 - !di->susp_status.ac_suspended) { 372 - dev_dbg(di->dev, "Charging source is AC\n"); 388 + if (di->chg_info.conn_chg != di->chg_info.prev_conn_chg) { 389 + /* Charger state changed since last update */ 390 + if (di->chg_info.conn_chg & AC_CHG) { 391 + dev_info(di->dev, "Charging source is AC\n"); 373 392 if (di->chg_info.charger_type != AC_CHG) { 374 393 di->chg_info.charger_type = AC_CHG; 375 394 ab8500_chargalg_state_to(di, STATE_NORMAL_INIT); 376 395 } 377 - } else if ((di->chg_info.conn_chg & USB_CHG) && 378 - !di->susp_status.usb_suspended) { 379 - dev_dbg(di->dev, "Charging source is USB\n"); 396 + } else if (di->chg_info.conn_chg & USB_CHG) { 397 + dev_info(di->dev, "Charging source is USB\n"); 380 398 di->chg_info.charger_type = USB_CHG; 381 399 ab8500_chargalg_state_to(di, STATE_NORMAL_INIT); 382 - } else if (di->chg_info.conn_chg && 383 - (di->susp_status.ac_suspended || 384 - di->susp_status.usb_suspended)) { 385 - dev_dbg(di->dev, "Charging is suspended\n"); 386 - di->chg_info.charger_type = NO_CHG; 387 - ab8500_chargalg_state_to(di, STATE_SUSPENDED_INIT); 388 400 } else { 389 401 dev_dbg(di->dev, "Charging source is OFF\n"); 390 402 di->chg_info.charger_type = NO_CHG; 391 403 ab8500_chargalg_state_to(di, STATE_HANDHELD_INIT); 392 404 } 393 405 di->chg_info.prev_conn_chg = di->chg_info.conn_chg; 394 - di->susp_status.suspended_change = false; 395 406 } 396 407 return di->chg_info.conn_chg; 397 - } 398 - 399 - /** 400 - * ab8500_chargalg_check_current_step_status() - Check charging current 401 - * step status. 402 - * @di: pointer to the ab8500_chargalg structure 403 - * 404 - * This function will check if there is a change in the charging current step 405 - * and change charge state accordingly. 406 - */ 407 - static void ab8500_chargalg_check_current_step_status 408 - (struct ab8500_chargalg *di) 409 - { 410 - if (di->curr_status.curr_step_change) 411 - ab8500_chargalg_state_to(di, STATE_NORMAL_INIT); 412 - di->curr_status.curr_step_change = false; 413 408 } 414 409 415 410 /** ··· 431 484 /** 432 485 * ab8500_chargalg_start_maintenance_timer() - Start charging maintenance timer 433 486 * @di: pointer to the ab8500_chargalg structure 434 - * @duration: duration of ther maintenance timer in hours 487 + * @duration: duration of the maintenance timer in minutes 435 488 * 436 489 * The maintenance timer is used to maintain the charge in the battery once 437 490 * the battery is considered full. These timers are chosen to match the ··· 440 493 static void ab8500_chargalg_start_maintenance_timer(struct ab8500_chargalg *di, 441 494 int duration) 442 495 { 496 + /* Set a timer in minutes with a 30 second range */ 443 497 hrtimer_set_expires_range(&di->maintenance_timer, 444 - ktime_set(duration * ONE_HOUR_IN_SECONDS, 0), 445 - ktime_set(FIVE_MINUTES_IN_SECONDS, 0)); 498 + ktime_set(duration * 60, 0), 499 + ktime_set(30, 0)); 446 500 di->events.maintenance_timer_expired = false; 447 501 hrtimer_start_expires(&di->maintenance_timer, HRTIMER_MODE_REL); 448 502 } ··· 685 737 di->batt_data.temp < (bi->temp_alert_max - di->t_hyst_norm)) { 686 738 /* Temp OK! */ 687 739 di->events.btemp_underover = false; 688 - di->events.btemp_lowhigh = false; 740 + di->events.btemp_low = false; 741 + di->events.btemp_high = false; 689 742 di->t_hyst_norm = 0; 690 743 di->t_hyst_lowhigh = 0; 691 744 } else { 692 - if (((di->batt_data.temp >= bi->temp_alert_max) && 693 - (di->batt_data.temp < 694 - (bi->temp_max - di->t_hyst_lowhigh))) || 695 - ((di->batt_data.temp > 696 - (bi->temp_min + di->t_hyst_lowhigh)) && 697 - (di->batt_data.temp <= bi->temp_alert_min))) { 698 - /* TEMP minor!!!!! */ 745 + if ((di->batt_data.temp >= bi->temp_alert_max) && 746 + (di->batt_data.temp < (bi->temp_max - di->t_hyst_lowhigh))) { 747 + /* Alert zone for high temperature */ 699 748 di->events.btemp_underover = false; 700 - di->events.btemp_lowhigh = true; 749 + di->events.btemp_high = true; 750 + di->t_hyst_norm = di->bm->temp_hysteresis; 751 + di->t_hyst_lowhigh = 0; 752 + } else if ((di->batt_data.temp > (bi->temp_min + di->t_hyst_lowhigh)) && 753 + (di->batt_data.temp <= bi->temp_alert_min)) { 754 + /* Alert zone for low temperature */ 755 + di->events.btemp_underover = false; 756 + di->events.btemp_low = true; 701 757 di->t_hyst_norm = di->bm->temp_hysteresis; 702 758 di->t_hyst_lowhigh = 0; 703 759 } else if (di->batt_data.temp <= bi->temp_min || 704 760 di->batt_data.temp >= bi->temp_max) { 705 761 /* TEMP major!!!!! */ 706 762 di->events.btemp_underover = true; 707 - di->events.btemp_lowhigh = false; 763 + di->events.btemp_low = false; 764 + di->events.btemp_high = false; 708 765 di->t_hyst_norm = 0; 709 766 di->t_hyst_lowhigh = di->bm->temp_hysteresis; 710 767 } else { ··· 755 802 if (di->charge_status == POWER_SUPPLY_STATUS_CHARGING && 756 803 di->charge_state == STATE_NORMAL && 757 804 !di->maintenance_chg && (di->batt_data.volt_uv >= 758 - di->bm->bi->overvoltage_limit_uv || 805 + di->bm->bi->voltage_max_design_uv || 759 806 di->events.usb_cv_active || di->events.ac_cv_active) && 760 807 di->batt_data.avg_curr_ua < 761 808 di->bm->bi->charge_term_current_ua && ··· 784 831 785 832 di->ccm.original_iset_ua = bi->constant_charge_current_max_ua; 786 833 di->ccm.current_iset_ua = bi->constant_charge_current_max_ua; 787 - di->ccm.test_delta_i_ua = di->bm->maxi->charger_curr_step_ua; 788 834 di->ccm.max_current_ua = di->bm->maxi->chg_curr_ua; 789 835 di->ccm.condition_cnt = di->bm->maxi->wait_cycles; 790 836 di->ccm.level = 0; ··· 800 848 */ 801 849 static enum maxim_ret ab8500_chargalg_chg_curr_maxim(struct ab8500_chargalg *di) 802 850 { 803 - int delta_i_ua; 804 851 805 852 if (!di->bm->maxi->ena_maxi) 806 853 return MAXIM_RET_NOACTION; 807 - 808 - delta_i_ua = di->ccm.original_iset_ua - di->batt_data.inst_curr_ua; 809 854 810 855 if (di->events.vbus_collapsed) { 811 856 dev_dbg(di->dev, "Charger voltage has collapsed %d\n", ··· 811 862 dev_dbg(di->dev, "lowering current\n"); 812 863 di->ccm.wait_cnt++; 813 864 di->ccm.condition_cnt = di->bm->maxi->wait_cycles; 814 - di->ccm.max_current_ua = 815 - di->ccm.current_iset_ua - di->ccm.test_delta_i_ua; 865 + di->ccm.max_current_ua = di->ccm.current_iset_ua; 816 866 di->ccm.current_iset_ua = di->ccm.max_current_ua; 817 867 di->ccm.level--; 818 868 return MAXIM_RET_CHANGE; ··· 841 893 return MAXIM_RET_IBAT_TOO_HIGH; 842 894 } 843 895 844 - if (delta_i_ua > di->ccm.test_delta_i_ua && 845 - (di->ccm.current_iset_ua + di->ccm.test_delta_i_ua) < 846 - di->ccm.max_current_ua) { 847 - if (di->ccm.condition_cnt-- == 0) { 848 - /* Increse the iset with cco.test_delta_i */ 849 - di->ccm.condition_cnt = di->bm->maxi->wait_cycles; 850 - di->ccm.current_iset_ua += di->ccm.test_delta_i_ua; 851 - di->ccm.level++; 852 - dev_dbg(di->dev, " Maximization needed, increase" 853 - " with %d uA to %duA (Optimal ibat: %d uA)" 854 - " Level %d\n", 855 - di->ccm.test_delta_i_ua, 856 - di->ccm.current_iset_ua, 857 - di->ccm.original_iset_ua, 858 - di->ccm.level); 859 - return MAXIM_RET_CHANGE; 860 - } else { 861 - return MAXIM_RET_NOACTION; 862 - } 863 - } else { 864 - di->ccm.condition_cnt = di->bm->maxi->wait_cycles; 865 - return MAXIM_RET_NOACTION; 866 - } 896 + di->ccm.condition_cnt = di->bm->maxi->wait_cycles; 897 + return MAXIM_RET_NOACTION; 867 898 } 868 899 869 900 static void handle_maxim_chg_curr(struct ab8500_chargalg *di) ··· 1227 1300 static void ab8500_chargalg_algorithm(struct ab8500_chargalg *di) 1228 1301 { 1229 1302 struct power_supply_battery_info *bi = di->bm->bi; 1303 + struct power_supply_maintenance_charge_table *mt; 1230 1304 int charger_status; 1231 1305 int ret; 1232 - int curr_step_lvl_ua; 1233 1306 1234 1307 /* Collect data from all power_supply class devices */ 1235 1308 class_for_each_device(power_supply_class, NULL, ··· 1240 1313 ab8500_chargalg_check_charger_voltage(di); 1241 1314 1242 1315 charger_status = ab8500_chargalg_check_charger_connection(di); 1243 - ab8500_chargalg_check_current_step_status(di); 1244 1316 1245 1317 if (is_ab8500(di->parent)) { 1246 1318 ret = ab8500_chargalg_check_charger_enable(di); ··· 1261 1335 } 1262 1336 } 1263 1337 1264 - /* If suspended, we should not continue checking the flags */ 1265 - else if (di->charge_state == STATE_SUSPENDED_INIT || 1266 - di->charge_state == STATE_SUSPENDED) { 1267 - /* We don't do anything here, just don,t continue */ 1268 - } 1269 - 1270 1338 /* Safety timer expiration */ 1271 1339 else if (di->events.safety_timer_expired) { 1272 1340 if (di->charge_state != STATE_SAFETY_TIMER_EXPIRED) ··· 1268 1348 STATE_SAFETY_TIMER_EXPIRED_INIT); 1269 1349 } 1270 1350 /* 1271 - * Check if any interrupts has occured 1351 + * Check if any interrupts has occurred 1272 1352 * that will prevent us from charging 1273 1353 */ 1274 1354 ··· 1316 1396 ab8500_chargalg_state_to(di, STATE_WD_EXPIRED_INIT); 1317 1397 } 1318 1398 /* Battery temp high/low */ 1319 - else if (di->events.btemp_lowhigh) { 1399 + else if (di->events.btemp_low || di->events.btemp_high) { 1320 1400 if (di->charge_state != STATE_TEMP_LOWHIGH) 1321 1401 ab8500_chargalg_state_to(di, STATE_TEMP_LOWHIGH_INIT); 1322 1402 } ··· 1356 1436 fallthrough; 1357 1437 1358 1438 case STATE_HANDHELD: 1359 - break; 1360 - 1361 - case STATE_SUSPENDED_INIT: 1362 - if (di->susp_status.ac_suspended) 1363 - ab8500_chargalg_ac_en(di, false, 0, 0); 1364 - if (di->susp_status.usb_suspended) 1365 - ab8500_chargalg_usb_en(di, false, 0, 0); 1366 - ab8500_chargalg_stop_safety_timer(di); 1367 - ab8500_chargalg_stop_maintenance_timer(di); 1368 - di->charge_status = POWER_SUPPLY_STATUS_NOT_CHARGING; 1369 - di->maintenance_chg = false; 1370 - ab8500_chargalg_state_to(di, STATE_SUSPENDED); 1371 - power_supply_changed(di->chargalg_psy); 1372 - fallthrough; 1373 - 1374 - case STATE_SUSPENDED: 1375 - /* CHARGING is suspended */ 1376 1439 break; 1377 1440 1378 1441 case STATE_BATT_REMOVED_INIT: ··· 1414 1511 break; 1415 1512 1416 1513 case STATE_NORMAL_INIT: 1417 - if (di->curr_status.curr_step_ua == CHARGALG_CURR_STEP_LOW_UA) 1514 + if (bi->constant_charge_current_max_ua == 0) 1515 + /* "charging" with 0 uA */ 1418 1516 ab8500_chargalg_stop_charging(di); 1419 1517 else { 1420 - curr_step_lvl_ua = bi->constant_charge_current_max_ua 1421 - * di->curr_status.curr_step_ua 1422 - / CHARGALG_CURR_STEP_HIGH_UA; 1423 1518 ab8500_chargalg_start_charging(di, 1424 1519 bi->constant_charge_voltage_max_uv, 1425 - curr_step_lvl_ua); 1520 + bi->constant_charge_current_max_ua); 1426 1521 } 1427 1522 1428 1523 ab8500_chargalg_state_to(di, STATE_NORMAL); ··· 1438 1537 handle_maxim_chg_curr(di); 1439 1538 if (di->charge_status == POWER_SUPPLY_STATUS_FULL && 1440 1539 di->maintenance_chg) { 1441 - if (di->bm->no_maintenance) 1540 + /* 1541 + * The battery is fully charged, check if we support 1542 + * maintenance charging else go back to waiting for 1543 + * the recharge voltage limit. 1544 + */ 1545 + if (!power_supply_supports_maintenance_charging(bi)) 1442 1546 ab8500_chargalg_state_to(di, 1443 1547 STATE_WAIT_FOR_RECHARGE_INIT); 1444 1548 else ··· 1464 1558 break; 1465 1559 1466 1560 case STATE_MAINTENANCE_A_INIT: 1561 + mt = power_supply_get_maintenance_charging_setting(bi, 0); 1562 + if (!mt) { 1563 + /* No maintenance A state, go back to normal */ 1564 + ab8500_chargalg_state_to(di, STATE_NORMAL_INIT); 1565 + power_supply_changed(di->chargalg_psy); 1566 + break; 1567 + } 1467 1568 ab8500_chargalg_stop_safety_timer(di); 1468 1569 ab8500_chargalg_start_maintenance_timer(di, 1469 - di->bm->bat_type->maint_a_chg_timer_h); 1570 + mt->charge_safety_timer_minutes); 1470 1571 ab8500_chargalg_start_charging(di, 1471 - di->bm->bat_type->maint_a_vol_lvl, 1472 - di->bm->bat_type->maint_a_cur_lvl); 1572 + mt->charge_voltage_max_uv, 1573 + mt->charge_current_max_ua); 1473 1574 ab8500_chargalg_state_to(di, STATE_MAINTENANCE_A); 1474 1575 power_supply_changed(di->chargalg_psy); 1475 1576 fallthrough; ··· 1489 1576 break; 1490 1577 1491 1578 case STATE_MAINTENANCE_B_INIT: 1579 + mt = power_supply_get_maintenance_charging_setting(bi, 1); 1580 + if (!mt) { 1581 + /* No maintenance B state, go back to normal */ 1582 + ab8500_chargalg_state_to(di, STATE_NORMAL_INIT); 1583 + power_supply_changed(di->chargalg_psy); 1584 + break; 1585 + } 1492 1586 ab8500_chargalg_start_maintenance_timer(di, 1493 - di->bm->bat_type->maint_b_chg_timer_h); 1587 + mt->charge_safety_timer_minutes); 1494 1588 ab8500_chargalg_start_charging(di, 1495 - di->bm->bat_type->maint_b_vol_lvl, 1496 - di->bm->bat_type->maint_b_cur_lvl); 1589 + mt->charge_voltage_max_uv, 1590 + mt->charge_current_max_ua); 1497 1591 ab8500_chargalg_state_to(di, STATE_MAINTENANCE_B); 1498 1592 power_supply_changed(di->chargalg_psy); 1499 1593 fallthrough; ··· 1513 1593 break; 1514 1594 1515 1595 case STATE_TEMP_LOWHIGH_INIT: 1516 - ab8500_chargalg_start_charging(di, 1517 - di->bm->bat_type->low_high_vol_lvl, 1518 - di->bm->bat_type->low_high_cur_lvl); 1596 + if (di->events.btemp_low) { 1597 + ab8500_chargalg_start_charging(di, 1598 + bi->alert_low_temp_charge_voltage_uv, 1599 + bi->alert_low_temp_charge_current_ua); 1600 + } else if (di->events.btemp_high) { 1601 + ab8500_chargalg_start_charging(di, 1602 + bi->alert_high_temp_charge_voltage_uv, 1603 + bi->alert_high_temp_charge_current_ua); 1604 + } else { 1605 + dev_err(di->dev, "neither low or high temp event occurred\n"); 1606 + ab8500_chargalg_state_to(di, STATE_NORMAL_INIT); 1607 + break; 1608 + } 1519 1609 ab8500_chargalg_stop_maintenance_timer(di); 1520 1610 di->charge_status = POWER_SUPPLY_STATUS_CHARGING; 1521 1611 ab8500_chargalg_state_to(di, STATE_TEMP_LOWHIGH); ··· 1533 1603 fallthrough; 1534 1604 1535 1605 case STATE_TEMP_LOWHIGH: 1536 - if (!di->events.btemp_lowhigh) 1606 + if (!di->events.btemp_low && !di->events.btemp_high) 1537 1607 ab8500_chargalg_state_to(di, STATE_NORMAL_INIT); 1538 1608 break; 1539 1609 ··· 1670 1740 return 0; 1671 1741 } 1672 1742 1673 - /* Exposure to the sysfs interface */ 1674 - 1675 - static ssize_t ab8500_chargalg_curr_step_show(struct ab8500_chargalg *di, 1676 - char *buf) 1677 - { 1678 - return sprintf(buf, "%d\n", di->curr_status.curr_step_ua); 1679 - } 1680 - 1681 - static ssize_t ab8500_chargalg_curr_step_store(struct ab8500_chargalg *di, 1682 - const char *buf, size_t length) 1683 - { 1684 - long param; 1685 - int ret; 1686 - 1687 - ret = kstrtol(buf, 10, &param); 1688 - if (ret < 0) 1689 - return ret; 1690 - 1691 - di->curr_status.curr_step_ua = param; 1692 - if (di->curr_status.curr_step_ua >= CHARGALG_CURR_STEP_LOW_UA && 1693 - di->curr_status.curr_step_ua <= CHARGALG_CURR_STEP_HIGH_UA) { 1694 - di->curr_status.curr_step_change = true; 1695 - queue_work(di->chargalg_wq, &di->chargalg_work); 1696 - } else 1697 - dev_info(di->dev, "Wrong current step\n" 1698 - "Enter 0. Disable AC/USB Charging\n" 1699 - "1--100. Set AC/USB charging current step\n" 1700 - "100. Enable AC/USB Charging\n"); 1701 - 1702 - return strlen(buf); 1703 - } 1704 - 1705 - 1706 - static ssize_t ab8500_chargalg_en_show(struct ab8500_chargalg *di, 1707 - char *buf) 1708 - { 1709 - return sprintf(buf, "%d\n", 1710 - di->susp_status.ac_suspended && 1711 - di->susp_status.usb_suspended); 1712 - } 1713 - 1714 - static ssize_t ab8500_chargalg_en_store(struct ab8500_chargalg *di, 1715 - const char *buf, size_t length) 1716 - { 1717 - long param; 1718 - int ac_usb; 1719 - int ret; 1720 - 1721 - ret = kstrtol(buf, 10, &param); 1722 - if (ret < 0) 1723 - return ret; 1724 - 1725 - ac_usb = param; 1726 - switch (ac_usb) { 1727 - case 0: 1728 - /* Disable charging */ 1729 - di->susp_status.ac_suspended = true; 1730 - di->susp_status.usb_suspended = true; 1731 - di->susp_status.suspended_change = true; 1732 - /* Trigger a state change */ 1733 - queue_work(di->chargalg_wq, 1734 - &di->chargalg_work); 1735 - break; 1736 - case 1: 1737 - /* Enable AC Charging */ 1738 - di->susp_status.ac_suspended = false; 1739 - di->susp_status.suspended_change = true; 1740 - /* Trigger a state change */ 1741 - queue_work(di->chargalg_wq, 1742 - &di->chargalg_work); 1743 - break; 1744 - case 2: 1745 - /* Enable USB charging */ 1746 - di->susp_status.usb_suspended = false; 1747 - di->susp_status.suspended_change = true; 1748 - /* Trigger a state change */ 1749 - queue_work(di->chargalg_wq, 1750 - &di->chargalg_work); 1751 - break; 1752 - default: 1753 - dev_info(di->dev, "Wrong input\n" 1754 - "Enter 0. Disable AC/USB Charging\n" 1755 - "1. Enable AC charging\n" 1756 - "2. Enable USB Charging\n"); 1757 - } 1758 - return strlen(buf); 1759 - } 1760 - 1761 - static struct ab8500_chargalg_sysfs_entry ab8500_chargalg_en_charger = 1762 - __ATTR(chargalg, 0644, ab8500_chargalg_en_show, 1763 - ab8500_chargalg_en_store); 1764 - 1765 - static struct ab8500_chargalg_sysfs_entry ab8500_chargalg_curr_step = 1766 - __ATTR(chargalg_curr_step, 0644, ab8500_chargalg_curr_step_show, 1767 - ab8500_chargalg_curr_step_store); 1768 - 1769 - static ssize_t ab8500_chargalg_sysfs_show(struct kobject *kobj, 1770 - struct attribute *attr, char *buf) 1771 - { 1772 - struct ab8500_chargalg_sysfs_entry *entry = container_of(attr, 1773 - struct ab8500_chargalg_sysfs_entry, attr); 1774 - 1775 - struct ab8500_chargalg *di = container_of(kobj, 1776 - struct ab8500_chargalg, chargalg_kobject); 1777 - 1778 - if (!entry->show) 1779 - return -EIO; 1780 - 1781 - return entry->show(di, buf); 1782 - } 1783 - 1784 - static ssize_t ab8500_chargalg_sysfs_charger(struct kobject *kobj, 1785 - struct attribute *attr, const char *buf, size_t length) 1786 - { 1787 - struct ab8500_chargalg_sysfs_entry *entry = container_of(attr, 1788 - struct ab8500_chargalg_sysfs_entry, attr); 1789 - 1790 - struct ab8500_chargalg *di = container_of(kobj, 1791 - struct ab8500_chargalg, chargalg_kobject); 1792 - 1793 - if (!entry->store) 1794 - return -EIO; 1795 - 1796 - return entry->store(di, buf, length); 1797 - } 1798 - 1799 - static struct attribute *ab8500_chargalg_chg[] = { 1800 - &ab8500_chargalg_en_charger.attr, 1801 - &ab8500_chargalg_curr_step.attr, 1802 - NULL, 1803 - }; 1804 - 1805 - static const struct sysfs_ops ab8500_chargalg_sysfs_ops = { 1806 - .show = ab8500_chargalg_sysfs_show, 1807 - .store = ab8500_chargalg_sysfs_charger, 1808 - }; 1809 - 1810 - static struct kobj_type ab8500_chargalg_ktype = { 1811 - .sysfs_ops = &ab8500_chargalg_sysfs_ops, 1812 - .default_attrs = ab8500_chargalg_chg, 1813 - }; 1814 - 1815 - /** 1816 - * ab8500_chargalg_sysfs_exit() - de-init of sysfs entry 1817 - * @di: pointer to the struct ab8500_chargalg 1818 - * 1819 - * This function removes the entry in sysfs. 1820 - */ 1821 - static void ab8500_chargalg_sysfs_exit(struct ab8500_chargalg *di) 1822 - { 1823 - kobject_del(&di->chargalg_kobject); 1824 - } 1825 - 1826 - /** 1827 - * ab8500_chargalg_sysfs_init() - init of sysfs entry 1828 - * @di: pointer to the struct ab8500_chargalg 1829 - * 1830 - * This function adds an entry in sysfs. 1831 - * Returns error code in case of failure else 0(on success) 1832 - */ 1833 - static int ab8500_chargalg_sysfs_init(struct ab8500_chargalg *di) 1834 - { 1835 - int ret = 0; 1836 - 1837 - ret = kobject_init_and_add(&di->chargalg_kobject, 1838 - &ab8500_chargalg_ktype, 1839 - NULL, "ab8500_chargalg"); 1840 - if (ret < 0) 1841 - dev_err(di->dev, "failed to create sysfs entry\n"); 1842 - 1843 - return ret; 1844 - } 1845 - /* Exposure to the sysfs interface <<END>> */ 1846 - 1847 1743 static int __maybe_unused ab8500_chargalg_resume(struct device *dev) 1848 1744 { 1849 1745 struct ab8500_chargalg *di = dev_get_drvdata(dev); ··· 1759 2003 struct device *dev = &pdev->dev; 1760 2004 struct power_supply_config psy_cfg = {}; 1761 2005 struct ab8500_chargalg *di; 1762 - int ret = 0; 1763 2006 1764 2007 di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL); 1765 2008 if (!di) ··· 1775 2020 psy_cfg.drv_data = di; 1776 2021 1777 2022 /* Initilialize safety timer */ 1778 - hrtimer_init(&di->safety_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS); 2023 + hrtimer_init(&di->safety_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 1779 2024 di->safety_timer.function = ab8500_chargalg_safety_timer_expired; 1780 2025 1781 2026 /* Initilialize maintenance timer */ 1782 - hrtimer_init(&di->maintenance_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS); 2027 + hrtimer_init(&di->maintenance_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 1783 2028 di->maintenance_timer.function = 1784 2029 ab8500_chargalg_maintenance_timer_expired; 1785 2030 ··· 1806 2051 1807 2052 platform_set_drvdata(pdev, di); 1808 2053 1809 - /* sysfs interface to enable/disable charging from user space */ 1810 - ret = ab8500_chargalg_sysfs_init(di); 1811 - if (ret) { 1812 - dev_err(di->dev, "failed to create sysfs entry\n"); 1813 - return ret; 1814 - } 1815 - di->curr_status.curr_step_ua = CHARGALG_CURR_STEP_HIGH_UA; 1816 - 1817 2054 dev_info(di->dev, "probe success\n"); 1818 2055 return component_add(dev, &ab8500_chargalg_component_ops); 1819 2056 } 1820 2057 1821 2058 static int ab8500_chargalg_remove(struct platform_device *pdev) 1822 2059 { 1823 - struct ab8500_chargalg *di = platform_get_drvdata(pdev); 1824 - 1825 2060 component_del(&pdev->dev, &ab8500_chargalg_component_ops); 1826 - 1827 - /* sysfs interface to enable/disable charging from user space */ 1828 - ab8500_chargalg_sysfs_exit(di); 1829 2061 1830 2062 return 0; 1831 2063 }
+28 -19
drivers/power/supply/ab8500_charger.c
··· 163 163 #define USB_CH_IP_CUR_LVL_1P4 1400000 164 164 #define USB_CH_IP_CUR_LVL_1P5 1500000 165 165 166 - #define VBAT_TRESH_IP_CUR_RED 3800 166 + #define VBAT_TRESH_IP_CUR_RED 3800000 167 167 168 168 #define to_ab8500_charger_usb_device_info(x) container_of((x), \ 169 169 struct ab8500_charger, usb_chg) ··· 171 171 struct ab8500_charger, ac_chg) 172 172 173 173 /** 174 - * struct ab8500_charger_interrupts - ab8500 interupts 174 + * struct ab8500_charger_interrupts - ab8500 interrupts 175 175 * @name: name of the interrupt 176 176 * @isr function pointer to the isr 177 177 */ ··· 1083 1083 1084 1084 /** 1085 1085 * ab8500_charger_get_usb_cur() - get usb current 1086 - * @di: pointer to the ab8500_charger structre 1086 + * @di: pointer to the ab8500_charger structure 1087 1087 * 1088 1088 * The usb stack provides the maximum current that can be drawn from 1089 1089 * the standard usb host. This will be in uA. ··· 1920 1920 1921 1921 di = to_ab8500_charger_usb_device_info(usb_chg); 1922 1922 1923 - /* For all psy where the driver name appears in any supplied_to */ 1923 + /* 1924 + * For all psy where the driver name appears in any supplied_to 1925 + * in practice what we will find will always be "ab8500_fg" as 1926 + * the fuel gauge is responsible of keeping track of VBAT. 1927 + */ 1924 1928 j = match_string(supplicants, ext->num_supplicants, psy->desc->name); 1925 1929 if (j < 0) 1926 1930 return 0; ··· 1941 1937 case POWER_SUPPLY_PROP_VOLTAGE_NOW: 1942 1938 switch (ext->desc->type) { 1943 1939 case POWER_SUPPLY_TYPE_BATTERY: 1944 - di->vbat = ret.intval / 1000; 1940 + /* This will always be "ab8500_fg" */ 1941 + dev_dbg(di->dev, "get VBAT from %s\n", 1942 + dev_name(&ext->dev)); 1943 + di->vbat = ret.intval; 1945 1944 break; 1946 1945 default: 1947 1946 break; ··· 1973 1966 struct ab8500_charger, check_vbat_work.work); 1974 1967 1975 1968 class_for_each_device(power_supply_class, NULL, 1976 - di->usb_chg.psy, ab8500_charger_get_ext_psy_data); 1969 + &di->usb_chg, ab8500_charger_get_ext_psy_data); 1977 1970 1978 1971 /* First run old_vbat is 0. */ 1979 1972 if (di->old_vbat == 0) ··· 1998 1991 * No need to check the battery voltage every second when not close to 1999 1992 * the threshold. 2000 1993 */ 2001 - if (di->vbat < (VBAT_TRESH_IP_CUR_RED + 100) && 2002 - (di->vbat > (VBAT_TRESH_IP_CUR_RED - 100))) 1994 + if (di->vbat < (VBAT_TRESH_IP_CUR_RED + 100000) && 1995 + (di->vbat > (VBAT_TRESH_IP_CUR_RED - 100000))) 2003 1996 t = 1; 2004 1997 2005 1998 queue_delayed_work(di->charger_wq, &di->check_vbat_work, t * HZ); ··· 3450 3443 di->parent = dev_get_drvdata(pdev->dev.parent); 3451 3444 3452 3445 /* Get ADC channels */ 3453 - di->adc_main_charger_v = devm_iio_channel_get(dev, "main_charger_v"); 3454 - if (IS_ERR(di->adc_main_charger_v)) { 3455 - ret = dev_err_probe(dev, PTR_ERR(di->adc_main_charger_v), 3456 - "failed to get ADC main charger voltage\n"); 3457 - return ret; 3458 - } 3459 - di->adc_main_charger_c = devm_iio_channel_get(dev, "main_charger_c"); 3460 - if (IS_ERR(di->adc_main_charger_c)) { 3461 - ret = dev_err_probe(dev, PTR_ERR(di->adc_main_charger_c), 3462 - "failed to get ADC main charger current\n"); 3463 - return ret; 3446 + if (!is_ab8505(di->parent)) { 3447 + di->adc_main_charger_v = devm_iio_channel_get(dev, "main_charger_v"); 3448 + if (IS_ERR(di->adc_main_charger_v)) { 3449 + ret = dev_err_probe(dev, PTR_ERR(di->adc_main_charger_v), 3450 + "failed to get ADC main charger voltage\n"); 3451 + return ret; 3452 + } 3453 + di->adc_main_charger_c = devm_iio_channel_get(dev, "main_charger_c"); 3454 + if (IS_ERR(di->adc_main_charger_c)) { 3455 + ret = dev_err_probe(dev, PTR_ERR(di->adc_main_charger_c), 3456 + "failed to get ADC main charger current\n"); 3457 + return ret; 3458 + } 3464 3459 } 3465 3460 di->adc_vbus_v = devm_iio_channel_get(dev, "vbus_v"); 3466 3461 if (IS_ERR(di->adc_vbus_v)) {
+109 -56
drivers/power/supply/ab8500_fg.c
··· 45 45 #define SEC_TO_SAMPLE(S) (S * 4) 46 46 47 47 #define NBR_AVG_SAMPLES 20 48 + #define WAIT_FOR_INST_CURRENT_MAX 70 49 + /* Currents higher than -500mA (dissipating) will make compensation unstable */ 50 + #define IGNORE_VBAT_HIGHCUR -500000 48 51 49 52 #define LOW_BAT_CHECK_INTERVAL (HZ / 16) /* 62.5 ms */ 50 53 ··· 213 210 int init_cnt; 214 211 int low_bat_cnt; 215 212 int nbr_cceoc_irq_cnt; 213 + u32 line_impedance_uohm; 216 214 bool recovery_needed; 217 215 bool high_curr_mode; 218 216 bool init_capacity; ··· 878 874 /** 879 875 * ab8500_fg_battery_resistance() - Returns the battery inner resistance 880 876 * @di: pointer to the ab8500_fg structure 877 + * @vbat_uncomp_uv: Uncompensated VBAT voltage 881 878 * 882 879 * Returns battery inner resistance added with the fuel gauge resistor value 883 880 * to get the total resistance in the whole link from gnd to bat+ node 884 881 * in milliohm. 885 882 */ 886 - static int ab8500_fg_battery_resistance(struct ab8500_fg *di) 883 + static int ab8500_fg_battery_resistance(struct ab8500_fg *di, int vbat_uncomp_uv) 887 884 { 888 885 struct power_supply_battery_info *bi = di->bm->bi; 889 886 int resistance_percent = 0; 890 887 int resistance; 891 888 892 - resistance_percent = power_supply_temp2resist_simple(bi->resist_table, 893 - bi->resist_table_size, 894 - di->bat_temp / 10); 895 889 /* 896 - * We get a percentage of factory resistance here so first get 897 - * the factory resistance in milliohms then calculate how much 898 - * resistance we have at this temperature. 890 + * Determine the resistance at this voltage. First try VBAT-to-Ri else 891 + * just infer it from the surrounding temperature, if nothing works just 892 + * use the internal resistance. 899 893 */ 900 - resistance = (bi->factory_internal_resistance_uohm / 1000); 901 - resistance = resistance * resistance_percent / 100; 894 + if (power_supply_supports_vbat2ri(bi)) { 895 + resistance = power_supply_vbat2ri(bi, vbat_uncomp_uv, di->flags.charging); 896 + /* Convert to milliohm */ 897 + resistance = resistance / 1000; 898 + } else if (power_supply_supports_temp2ri(bi)) { 899 + resistance_percent = power_supply_temp2resist_simple(bi->resist_table, 900 + bi->resist_table_size, 901 + di->bat_temp / 10); 902 + /* Convert to milliohm */ 903 + resistance = bi->factory_internal_resistance_uohm / 1000; 904 + resistance = resistance * resistance_percent / 100; 905 + } else { 906 + /* Last fallback */ 907 + resistance = bi->factory_internal_resistance_uohm / 1000; 908 + } 909 + 910 + /* Compensate for line impedance */ 911 + resistance += (di->line_impedance_uohm / 1000); 902 912 903 913 dev_dbg(di->dev, "%s Temp: %d battery internal resistance: %d" 904 914 " fg resistance %d, total: %d (mOhm)\n", ··· 926 908 } 927 909 928 910 /** 911 + * ab8500_load_comp_fg_bat_voltage() - get load compensated battery voltage 912 + * @di: pointer to the ab8500_fg structure 913 + * @always: always return a voltage, also uncompensated 914 + * 915 + * Returns compensated battery voltage (on success) else error code. 916 + * If always is specified, we always return a voltage but it may be 917 + * uncompensated. 918 + */ 919 + static int ab8500_load_comp_fg_bat_voltage(struct ab8500_fg *di, bool always) 920 + { 921 + int i = 0; 922 + int vbat_uv = 0; 923 + int rcomp; 924 + 925 + /* Average the instant current to get a stable current measurement */ 926 + ab8500_fg_inst_curr_start(di); 927 + 928 + do { 929 + vbat_uv += ab8500_fg_bat_voltage(di); 930 + i++; 931 + usleep_range(5000, 6000); 932 + } while (!ab8500_fg_inst_curr_done(di) && 933 + i <= WAIT_FOR_INST_CURRENT_MAX); 934 + 935 + if (i > WAIT_FOR_INST_CURRENT_MAX) { 936 + dev_err(di->dev, 937 + "TIMEOUT: return uncompensated measurement of VBAT\n"); 938 + di->vbat_uv = vbat_uv / i; 939 + return di->vbat_uv; 940 + } 941 + 942 + ab8500_fg_inst_curr_finalize(di, &di->inst_curr_ua); 943 + 944 + /* 945 + * If there is too high current dissipation, the compensation cannot be 946 + * trusted so return an error unless we must return something here, as 947 + * enforced by the "always" parameter. 948 + */ 949 + if (!always && di->inst_curr_ua < IGNORE_VBAT_HIGHCUR) 950 + return -EINVAL; 951 + 952 + vbat_uv = vbat_uv / i; 953 + 954 + /* Next we apply voltage compensation from internal resistance */ 955 + rcomp = ab8500_fg_battery_resistance(di, vbat_uv); 956 + vbat_uv = vbat_uv - (di->inst_curr_ua * rcomp) / 1000; 957 + 958 + /* Always keep this state at latest measurement */ 959 + di->vbat_uv = vbat_uv; 960 + 961 + return vbat_uv; 962 + } 963 + 964 + /** 929 965 * ab8500_fg_load_comp_volt_to_capacity() - Load compensated voltage based capacity 930 966 * @di: pointer to the ab8500_fg structure 931 967 * ··· 988 916 */ 989 917 static int ab8500_fg_load_comp_volt_to_capacity(struct ab8500_fg *di) 990 918 { 991 - int vbat_comp_uv, res; 992 - int i = 0; 993 - int vbat_uv = 0; 919 + int vbat_comp_uv; 994 920 995 - ab8500_fg_inst_curr_start(di); 996 - 997 - do { 998 - vbat_uv += ab8500_fg_bat_voltage(di); 999 - i++; 1000 - usleep_range(5000, 6000); 1001 - } while (!ab8500_fg_inst_curr_done(di)); 1002 - 1003 - ab8500_fg_inst_curr_finalize(di, &di->inst_curr_ua); 1004 - 1005 - di->vbat_uv = vbat_uv / i; 1006 - res = ab8500_fg_battery_resistance(di); 1007 - 1008 - /* 1009 - * Use Ohms law to get the load compensated voltage. 1010 - * Divide by 1000 to get from milliohms to ohms. 1011 - */ 1012 - vbat_comp_uv = di->vbat_uv - (di->inst_curr_ua * res) / 1000; 1013 - 1014 - dev_dbg(di->dev, "%s Measured Vbat: %d uV,Compensated Vbat %d uV, " 1015 - "R: %d mOhm, Current: %d uA Vbat Samples: %d\n", 1016 - __func__, di->vbat_uv, vbat_comp_uv, res, di->inst_curr_ua, i); 921 + vbat_comp_uv = ab8500_load_comp_fg_bat_voltage(di, true); 1017 922 1018 923 return ab8500_fg_volt_to_capacity(di, vbat_comp_uv); 1019 924 } ··· 1088 1039 /** 1089 1040 * ab8500_fg_calc_cap_discharge_voltage() - Capacity in discharge with voltage 1090 1041 * @di: pointer to the ab8500_fg structure 1091 - * @comp: if voltage should be load compensated before capacity calc 1092 1042 * 1093 - * Return the capacity in mAh based on the battery voltage. The voltage can 1094 - * either be load compensated or not. This value is added to the filter and a 1095 - * new mean value is calculated and returned. 1043 + * Return the capacity in mAh based on the load compensated battery voltage. 1044 + * This value is added to the filter and a new mean value is calculated and 1045 + * returned. 1096 1046 */ 1097 - static int ab8500_fg_calc_cap_discharge_voltage(struct ab8500_fg *di, bool comp) 1047 + static int ab8500_fg_calc_cap_discharge_voltage(struct ab8500_fg *di) 1098 1048 { 1099 1049 int permille, mah; 1100 1050 1101 - if (comp) 1102 - permille = ab8500_fg_load_comp_volt_to_capacity(di); 1103 - else 1104 - permille = ab8500_fg_uncomp_volt_to_capacity(di); 1051 + permille = ab8500_fg_load_comp_volt_to_capacity(di); 1105 1052 1106 1053 mah = ab8500_fg_convert_permille_to_mah(di, permille); 1107 1054 ··· 1574 1529 1575 1530 /* Discard the first [x] seconds */ 1576 1531 if (di->init_cnt > di->bm->fg_params->init_discard_time) { 1577 - ab8500_fg_calc_cap_discharge_voltage(di, true); 1532 + ab8500_fg_calc_cap_discharge_voltage(di); 1578 1533 1579 1534 ab8500_fg_check_capacity_limits(di, true); 1580 1535 } ··· 1657 1612 break; 1658 1613 } 1659 1614 1660 - ab8500_fg_calc_cap_discharge_voltage(di, true); 1615 + ab8500_fg_calc_cap_discharge_voltage(di); 1661 1616 } else { 1662 1617 mutex_lock(&di->cc_lock); 1663 1618 if (!di->flags.conv_done) { ··· 1691 1646 break; 1692 1647 1693 1648 case AB8500_FG_DISCHARGE_WAKEUP: 1694 - ab8500_fg_calc_cap_discharge_voltage(di, true); 1649 + ab8500_fg_calc_cap_discharge_voltage(di); 1695 1650 1696 1651 di->fg_samples = SEC_TO_SAMPLE( 1697 1652 di->bm->fg_params->accu_high_curr); ··· 1810 1765 1811 1766 if (di->init_capacity) { 1812 1767 /* Get an initial capacity calculation */ 1813 - ab8500_fg_calc_cap_discharge_voltage(di, true); 1768 + ab8500_fg_calc_cap_discharge_voltage(di); 1814 1769 ab8500_fg_check_capacity_limits(di, true); 1815 1770 di->init_capacity = false; 1816 1771 ··· 2256 2211 if (!di->flags.batt_id_received && 2257 2212 (bi && (bi->technology != 2258 2213 POWER_SUPPLY_TECHNOLOGY_UNKNOWN))) { 2259 - const struct ab8500_battery_type *b; 2260 - 2261 - b = di->bm->bat_type; 2262 - 2263 2214 di->flags.batt_id_received = true; 2264 2215 2265 2216 di->bat_cap.max_mah_design = ··· 2304 2263 { 2305 2264 int ret; 2306 2265 2307 - /* Set VBAT OVV threshold */ 2266 + /* 2267 + * Set VBAT OVV (overvoltage) threshold to 4.75V (typ) this is what 2268 + * the hardware supports, nothing else can be configured in hardware. 2269 + * See this as an "outer limit" where the charger will certainly 2270 + * shut down. Other (lower) overvoltage levels need to be implemented 2271 + * in software. 2272 + */ 2308 2273 ret = abx500_mask_and_set_register_interruptible(di->dev, 2309 2274 AB8500_CHARGER, 2310 2275 AB8500_BATT_OVV, ··· 2429 2382 if (!di->flags.calibrate) { 2430 2383 dev_dbg(di->dev, "Resetting FG state machine to init.\n"); 2431 2384 ab8500_fg_clear_cap_samples(di); 2432 - ab8500_fg_calc_cap_discharge_voltage(di, true); 2385 + ab8500_fg_calc_cap_discharge_voltage(di); 2433 2386 ab8500_fg_charge_state_to(di, AB8500_FG_CHARGE_INIT); 2434 2387 ab8500_fg_discharge_state_to(di, AB8500_FG_DISCHARGE_INIT); 2435 2388 queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0); ··· 2568 2521 ret = kobject_init_and_add(&di->fg_kobject, 2569 2522 &ab8500_fg_ktype, 2570 2523 NULL, "battery"); 2571 - if (ret < 0) 2524 + if (ret < 0) { 2525 + kobject_put(&di->fg_kobject); 2572 2526 dev_err(di->dev, "failed to create sysfs entry\n"); 2527 + } 2573 2528 2574 2529 return ret; 2575 2530 } ··· 3102 3053 return ret; 3103 3054 } 3104 3055 3056 + if (!of_property_read_u32(dev->of_node, "line-impedance-micro-ohms", 3057 + &di->line_impedance_uohm)) 3058 + dev_info(dev, "line impedance: %u uOhm\n", 3059 + di->line_impedance_uohm); 3060 + 3105 3061 psy_cfg.supplied_to = supply_interface; 3106 3062 psy_cfg.num_supplicants = ARRAY_SIZE(supply_interface); 3107 3063 psy_cfg.drv_data = di; ··· 3224 3170 3225 3171 static int ab8500_fg_remove(struct platform_device *pdev) 3226 3172 { 3227 - int ret = 0; 3228 3173 struct ab8500_fg *di = platform_get_drvdata(pdev); 3229 3174 3230 3175 component_del(&pdev->dev, &ab8500_fg_component_ops); ··· 3231 3178 ab8500_fg_sysfs_exit(di); 3232 3179 ab8500_fg_sysfs_psy_remove_attrs(di); 3233 3180 3234 - return ret; 3181 + return 0; 3235 3182 } 3236 3183 3237 3184 static SIMPLE_DEV_PM_OPS(ab8500_fg_pm_ops, ab8500_fg_suspend, ab8500_fg_resume);
+2 -4
drivers/power/supply/axp20x_ac_power.c
··· 377 377 /* Request irqs after registering, as irqs may trigger immediately */ 378 378 for (i = 0; i < axp_data->num_irq_names; i++) { 379 379 irq = platform_get_irq_byname(pdev, axp_data->irq_names[i]); 380 - if (irq < 0) { 381 - dev_err(&pdev->dev, "No IRQ for %s: %d\n", 382 - axp_data->irq_names[i], irq); 380 + if (irq < 0) 383 381 return irq; 384 - } 382 + 385 383 power->irqs[i] = regmap_irq_get_virq(axp20x->regmap_irqc, irq); 386 384 ret = devm_request_any_context_irq(&pdev->dev, power->irqs[i], 387 385 axp20x_ac_power_irq, 0,
+6 -7
drivers/power/supply/axp20x_battery.c
··· 186 186 union power_supply_propval *val) 187 187 { 188 188 struct axp20x_batt_ps *axp20x_batt = power_supply_get_drvdata(psy); 189 - struct iio_channel *chan; 190 189 int ret = 0, reg, val1; 191 190 192 191 switch (psp) { ··· 265 266 if (ret) 266 267 return ret; 267 268 268 - if (reg & AXP20X_PWR_STATUS_BAT_CHARGING) 269 - chan = axp20x_batt->batt_chrg_i; 270 - else 271 - chan = axp20x_batt->batt_dischrg_i; 272 - 273 - ret = iio_read_channel_processed(chan, &val->intval); 269 + if (reg & AXP20X_PWR_STATUS_BAT_CHARGING) { 270 + ret = iio_read_channel_processed(axp20x_batt->batt_chrg_i, &val->intval); 271 + } else { 272 + ret = iio_read_channel_processed(axp20x_batt->batt_dischrg_i, &val1); 273 + val->intval = -val1; 274 + } 274 275 if (ret) 275 276 return ret; 276 277
+2 -4
drivers/power/supply/axp20x_usb_power.c
··· 637 637 /* Request irqs after registering, as irqs may trigger immediately */ 638 638 for (i = 0; i < axp_data->num_irq_names; i++) { 639 639 irq = platform_get_irq_byname(pdev, axp_data->irq_names[i]); 640 - if (irq < 0) { 641 - dev_err(&pdev->dev, "No IRQ for %s: %d\n", 642 - axp_data->irq_names[i], irq); 640 + if (irq < 0) 643 641 return irq; 644 - } 642 + 645 643 power->irqs[i] = regmap_irq_get_virq(axp20x->regmap_irqc, irq); 646 644 ret = devm_request_any_context_irq(&pdev->dev, power->irqs[i], 647 645 axp20x_usb_power_irq, 0,
+19 -2
drivers/power/supply/axp288_charger.c
··· 42 42 #define VBUS_ISPOUT_CUR_LIM_1500MA 0x1 /* 1500mA */ 43 43 #define VBUS_ISPOUT_CUR_LIM_2000MA 0x2 /* 2000mA */ 44 44 #define VBUS_ISPOUT_CUR_NO_LIM 0x3 /* 2500mA */ 45 - #define VBUS_ISPOUT_VHOLD_SET_MASK 0x31 45 + #define VBUS_ISPOUT_VHOLD_SET_MASK 0x38 46 46 #define VBUS_ISPOUT_VHOLD_SET_BIT_POS 0x3 47 47 #define VBUS_ISPOUT_VHOLD_SET_OFFSET 4000 /* 4000mV */ 48 48 #define VBUS_ISPOUT_VHOLD_SET_LSB_RES 100 /* 100mV */ 49 - #define VBUS_ISPOUT_VHOLD_SET_4300MV 0x3 /* 4300mV */ 49 + #define VBUS_ISPOUT_VHOLD_SET_4400MV 0x4 /* 4400mV */ 50 50 #define VBUS_ISPOUT_VBUS_PATH_DIS BIT(7) 51 51 52 52 #define CHRG_CCCV_CC_MASK 0xf /* 4 bits */ ··· 769 769 ret = axp288_charger_vbus_path_select(info, true); 770 770 if (ret < 0) 771 771 return ret; 772 + } else { 773 + /* Set Vhold to the factory default / recommended 4.4V */ 774 + val = VBUS_ISPOUT_VHOLD_SET_4400MV << VBUS_ISPOUT_VHOLD_SET_BIT_POS; 775 + ret = regmap_update_bits(info->regmap, AXP20X_VBUS_IPSOUT_MGMT, 776 + VBUS_ISPOUT_VHOLD_SET_MASK, val); 777 + if (ret < 0) { 778 + dev_err(&info->pdev->dev, "register(%x) write error(%d)\n", 779 + AXP20X_VBUS_IPSOUT_MGMT, ret); 780 + return ret; 781 + } 772 782 } 773 783 774 784 /* Read current charge voltage and current limit */ ··· 837 827 struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); 838 828 struct power_supply_config charger_cfg = {}; 839 829 unsigned int val; 830 + 831 + /* 832 + * Normally the native AXP288 fg/charger drivers are preferred but 833 + * on some devices the ACPI drivers should be used instead. 834 + */ 835 + if (!acpi_quirk_skip_acpi_ac_and_battery()) 836 + return -ENODEV; 840 837 841 838 /* 842 839 * On some devices the fuelgauge and charger parts of the axp288 are
+143 -148
drivers/power/supply/axp288_fuel_gauge.c
··· 9 9 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 10 10 */ 11 11 12 + #include <linux/acpi.h> 12 13 #include <linux/dmi.h> 13 14 #include <linux/module.h> 14 15 #include <linux/kernel.h> ··· 89 88 90 89 #define AXP288_REG_UPDATE_INTERVAL (60 * HZ) 91 90 #define AXP288_FG_INTR_NUM 6 91 + 92 + static bool no_current_sense_res; 93 + module_param(no_current_sense_res, bool, 0444); 94 + MODULE_PARM_DESC(no_current_sense_res, "No (or broken) current sense resistor"); 95 + 92 96 enum { 93 97 QWBTU_IRQ = 0, 94 98 WBTU_IRQ, ··· 113 107 struct axp288_fg_info { 114 108 struct device *dev; 115 109 struct regmap *regmap; 116 - struct regmap_irq_chip_data *regmap_irqc; 117 110 int irq[AXP288_FG_INTR_NUM]; 118 111 struct iio_channel *iio_channel[IIO_CHANNEL_NUM]; 119 112 struct power_supply *bat; ··· 143 138 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, 144 139 POWER_SUPPLY_PROP_VOLTAGE_NOW, 145 140 POWER_SUPPLY_PROP_VOLTAGE_OCV, 146 - POWER_SUPPLY_PROP_CURRENT_NOW, 147 141 POWER_SUPPLY_PROP_CAPACITY, 148 142 POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN, 149 143 POWER_SUPPLY_PROP_TECHNOLOGY, 144 + /* The 3 props below are not used when no_current_sense_res is set */ 150 145 POWER_SUPPLY_PROP_CHARGE_FULL, 151 146 POWER_SUPPLY_PROP_CHARGE_NOW, 147 + POWER_SUPPLY_PROP_CURRENT_NOW, 152 148 }; 153 149 154 150 static int fuel_gauge_reg_readb(struct axp288_fg_info *info, int reg) ··· 231 225 goto out; 232 226 info->pwr_stat = ret; 233 227 234 - ret = fuel_gauge_reg_readb(info, AXP20X_FG_RES); 228 + if (no_current_sense_res) 229 + ret = fuel_gauge_reg_readb(info, AXP288_FG_OCV_CAP_REG); 230 + else 231 + ret = fuel_gauge_reg_readb(info, AXP20X_FG_RES); 235 232 if (ret < 0) 236 233 goto out; 237 234 info->fg_res = ret; ··· 242 233 ret = iio_read_channel_raw(info->iio_channel[BAT_VOLT], &info->bat_volt); 243 234 if (ret < 0) 244 235 goto out; 236 + 237 + ret = fuel_gauge_read_12bit_word(info, AXP288_FG_OCVH_REG); 238 + if (ret < 0) 239 + goto out; 240 + info->ocv = ret; 241 + 242 + if (no_current_sense_res) 243 + goto out_no_current_sense_res; 245 244 246 245 if (info->pwr_stat & PS_STAT_BAT_CHRG_DIR) { 247 246 info->d_curr = 0; ··· 263 246 goto out; 264 247 } 265 248 266 - ret = fuel_gauge_read_12bit_word(info, AXP288_FG_OCVH_REG); 267 - if (ret < 0) 268 - goto out; 269 - info->ocv = ret; 270 - 271 249 ret = fuel_gauge_read_15bit_word(info, AXP288_FG_CC_MTR1_REG); 272 250 if (ret < 0) 273 251 goto out; ··· 273 261 goto out; 274 262 info->fg_des_cap1 = ret; 275 263 264 + out_no_current_sense_res: 276 265 info->last_updated = jiffies; 277 266 info->valid = 1; 278 267 ret = 0; ··· 306 293 * When this happens the AXP288 reports a not-charging status and 307 294 * 0 mA discharge current. 308 295 */ 309 - if (fg_res < 90 || (pwr_stat & PS_STAT_BAT_CHRG_DIR)) 296 + if (fg_res < 90 || (pwr_stat & PS_STAT_BAT_CHRG_DIR) || no_current_sense_res) 310 297 goto not_full; 311 298 312 299 if (curr == 0) { ··· 490 477 dev_warn(info->dev, "Spurious Interrupt!!!\n"); 491 478 } 492 479 480 + mutex_lock(&info->lock); 493 481 info->valid = 0; /* Force updating of the cached registers */ 482 + mutex_unlock(&info->lock); 494 483 495 484 power_supply_changed(info->bat); 496 485 return IRQ_HANDLED; ··· 502 487 { 503 488 struct axp288_fg_info *info = power_supply_get_drvdata(psy); 504 489 490 + mutex_lock(&info->lock); 505 491 info->valid = 0; /* Force updating of the cached registers */ 492 + mutex_unlock(&info->lock); 506 493 power_supply_changed(info->bat); 507 494 } 508 495 509 - static const struct power_supply_desc fuel_gauge_desc = { 496 + static struct power_supply_desc fuel_gauge_desc = { 510 497 .name = DEV_NAME, 511 498 .type = POWER_SUPPLY_TYPE_BATTERY, 512 499 .properties = fuel_gauge_props, ··· 518 501 .property_is_writeable = fuel_gauge_property_is_writeable, 519 502 .external_power_changed = fuel_gauge_external_power_changed, 520 503 }; 521 - 522 - static void fuel_gauge_init_irq(struct axp288_fg_info *info, struct platform_device *pdev) 523 - { 524 - int ret, i, pirq; 525 - 526 - for (i = 0; i < AXP288_FG_INTR_NUM; i++) { 527 - pirq = platform_get_irq(pdev, i); 528 - info->irq[i] = regmap_irq_get_virq(info->regmap_irqc, pirq); 529 - if (info->irq[i] < 0) { 530 - dev_warn(info->dev, "regmap_irq get virq failed for IRQ %d: %d\n", 531 - pirq, info->irq[i]); 532 - info->irq[i] = -1; 533 - goto intr_failed; 534 - } 535 - ret = request_threaded_irq(info->irq[i], 536 - NULL, fuel_gauge_thread_handler, 537 - IRQF_ONESHOT, DEV_NAME, info); 538 - if (ret) { 539 - dev_warn(info->dev, "request irq failed for IRQ %d: %d\n", 540 - pirq, info->irq[i]); 541 - info->irq[i] = -1; 542 - goto intr_failed; 543 - } 544 - } 545 - return; 546 - 547 - intr_failed: 548 - for (; i > 0; i--) { 549 - free_irq(info->irq[i - 1], info); 550 - info->irq[i - 1] = -1; 551 - } 552 - } 553 504 554 505 /* 555 506 * Some devices have no battery (HDMI sticks) and the axp288 battery's ··· 543 558 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "T11"), 544 559 /* also match on somewhat unique bios-version */ 545 560 DMI_EXACT_MATCH(DMI_BIOS_VERSION, "1.000"), 546 - }, 547 - }, 548 - { 549 - /* ECS EF20EA */ 550 - .matches = { 551 - DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"), 552 561 }, 553 562 }, 554 563 { ··· 590 611 {} 591 612 }; 592 613 593 - static int axp288_fuel_gauge_probe(struct platform_device *pdev) 614 + static int axp288_fuel_gauge_read_initial_regs(struct axp288_fg_info *info) 594 615 { 595 - int i, ret = 0; 596 - struct axp288_fg_info *info; 597 - struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); 598 - struct power_supply_config psy_cfg = {}; 599 - static const char * const iio_chan_name[] = { 600 - [BAT_CHRG_CURR] = "axp288-chrg-curr", 601 - [BAT_D_CURR] = "axp288-chrg-d-curr", 602 - [BAT_VOLT] = "axp288-batt-volt", 603 - }; 604 616 unsigned int val; 605 - 606 - if (dmi_check_system(axp288_no_battery_list)) 607 - return -ENODEV; 608 - 609 - info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); 610 - if (!info) 611 - return -ENOMEM; 612 - 613 - info->dev = &pdev->dev; 614 - info->regmap = axp20x->regmap; 615 - info->regmap_irqc = axp20x->regmap_irqc; 616 - info->status = POWER_SUPPLY_STATUS_UNKNOWN; 617 - info->valid = 0; 618 - 619 - platform_set_drvdata(pdev, info); 620 - 621 - mutex_init(&info->lock); 622 - 623 - for (i = 0; i < IIO_CHANNEL_NUM; i++) { 624 - /* 625 - * Note cannot use devm_iio_channel_get because x86 systems 626 - * lack the device<->channel maps which iio_channel_get will 627 - * try to use when passed a non NULL device pointer. 628 - */ 629 - info->iio_channel[i] = 630 - iio_channel_get(NULL, iio_chan_name[i]); 631 - if (IS_ERR(info->iio_channel[i])) { 632 - ret = PTR_ERR(info->iio_channel[i]); 633 - dev_dbg(&pdev->dev, "error getting iiochan %s: %d\n", 634 - iio_chan_name[i], ret); 635 - /* Wait for axp288_adc to load */ 636 - if (ret == -ENODEV) 637 - ret = -EPROBE_DEFER; 638 - 639 - goto out_free_iio_chan; 640 - } 641 - } 642 - 643 - ret = iosf_mbi_block_punit_i2c_access(); 644 - if (ret < 0) 645 - goto out_free_iio_chan; 617 + int ret; 646 618 647 619 /* 648 620 * On some devices the fuelgauge and charger parts of the axp288 are 649 621 * not used, check that the fuelgauge is enabled (CC_CTRL != 0). 650 622 */ 651 - ret = regmap_read(axp20x->regmap, AXP20X_CC_CTRL, &val); 623 + ret = regmap_read(info->regmap, AXP20X_CC_CTRL, &val); 652 624 if (ret < 0) 653 - goto unblock_punit_i2c_access; 654 - if (val == 0) { 655 - ret = -ENODEV; 656 - goto unblock_punit_i2c_access; 657 - } 625 + return ret; 626 + if (val == 0) 627 + return -ENODEV; 658 628 659 629 ret = fuel_gauge_reg_readb(info, AXP288_FG_DES_CAP1_REG); 660 630 if (ret < 0) 661 - goto unblock_punit_i2c_access; 631 + return ret; 662 632 663 633 if (!(ret & FG_DES_CAP1_VALID)) { 664 - dev_err(&pdev->dev, "axp288 not configured by firmware\n"); 665 - ret = -ENODEV; 666 - goto unblock_punit_i2c_access; 634 + dev_err(info->dev, "axp288 not configured by firmware\n"); 635 + return -ENODEV; 667 636 } 668 637 669 638 ret = fuel_gauge_reg_readb(info, AXP20X_CHRG_CTRL1); 670 639 if (ret < 0) 671 - goto unblock_punit_i2c_access; 640 + return ret; 672 641 switch ((ret & CHRG_CCCV_CV_MASK) >> CHRG_CCCV_CV_BIT_POS) { 673 642 case CHRG_CCCV_CV_4100MV: 674 643 info->max_volt = 4100; ··· 634 707 635 708 ret = fuel_gauge_reg_readb(info, AXP20X_PWR_OP_MODE); 636 709 if (ret < 0) 637 - goto unblock_punit_i2c_access; 710 + return ret; 638 711 info->pwr_op = ret; 639 712 640 713 ret = fuel_gauge_reg_readb(info, AXP288_FG_LOW_CAP_REG); 641 714 if (ret < 0) 642 - goto unblock_punit_i2c_access; 715 + return ret; 643 716 info->low_cap = ret; 644 717 645 - unblock_punit_i2c_access: 646 - iosf_mbi_unblock_punit_i2c_access(); 647 - /* In case we arrive here by goto because of a register access error */ 648 - if (ret < 0) 649 - goto out_free_iio_chan; 650 - 651 - psy_cfg.drv_data = info; 652 - info->bat = power_supply_register(&pdev->dev, &fuel_gauge_desc, &psy_cfg); 653 - if (IS_ERR(info->bat)) { 654 - ret = PTR_ERR(info->bat); 655 - dev_err(&pdev->dev, "failed to register battery: %d\n", ret); 656 - goto out_free_iio_chan; 657 - } 658 - 659 - fuel_gauge_init_irq(info, pdev); 660 - 661 718 return 0; 719 + } 662 720 663 - out_free_iio_chan: 721 + static void axp288_fuel_gauge_release_iio_chans(void *data) 722 + { 723 + struct axp288_fg_info *info = data; 724 + int i; 725 + 664 726 for (i = 0; i < IIO_CHANNEL_NUM; i++) 665 727 if (!IS_ERR_OR_NULL(info->iio_channel[i])) 666 728 iio_channel_release(info->iio_channel[i]); 729 + } 667 730 668 - return ret; 731 + static int axp288_fuel_gauge_probe(struct platform_device *pdev) 732 + { 733 + struct axp288_fg_info *info; 734 + struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); 735 + struct power_supply_config psy_cfg = {}; 736 + static const char * const iio_chan_name[] = { 737 + [BAT_CHRG_CURR] = "axp288-chrg-curr", 738 + [BAT_D_CURR] = "axp288-chrg-d-curr", 739 + [BAT_VOLT] = "axp288-batt-volt", 740 + }; 741 + struct device *dev = &pdev->dev; 742 + int i, pirq, ret; 743 + 744 + /* 745 + * Normally the native AXP288 fg/charger drivers are preferred but 746 + * on some devices the ACPI drivers should be used instead. 747 + */ 748 + if (!acpi_quirk_skip_acpi_ac_and_battery()) 749 + return -ENODEV; 750 + 751 + if (dmi_check_system(axp288_no_battery_list)) 752 + return -ENODEV; 753 + 754 + info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); 755 + if (!info) 756 + return -ENOMEM; 757 + 758 + info->dev = dev; 759 + info->regmap = axp20x->regmap; 760 + info->status = POWER_SUPPLY_STATUS_UNKNOWN; 761 + info->valid = 0; 762 + 763 + platform_set_drvdata(pdev, info); 764 + 765 + mutex_init(&info->lock); 766 + 767 + for (i = 0; i < AXP288_FG_INTR_NUM; i++) { 768 + pirq = platform_get_irq(pdev, i); 769 + ret = regmap_irq_get_virq(axp20x->regmap_irqc, pirq); 770 + if (ret < 0) 771 + return dev_err_probe(dev, ret, "getting vIRQ %d\n", pirq); 772 + 773 + info->irq[i] = ret; 774 + } 775 + 776 + for (i = 0; i < IIO_CHANNEL_NUM; i++) { 777 + /* 778 + * Note cannot use devm_iio_channel_get because x86 systems 779 + * lack the device<->channel maps which iio_channel_get will 780 + * try to use when passed a non NULL device pointer. 781 + */ 782 + info->iio_channel[i] = 783 + iio_channel_get(NULL, iio_chan_name[i]); 784 + if (IS_ERR(info->iio_channel[i])) { 785 + ret = PTR_ERR(info->iio_channel[i]); 786 + dev_dbg(dev, "error getting iiochan %s: %d\n", iio_chan_name[i], ret); 787 + /* Wait for axp288_adc to load */ 788 + if (ret == -ENODEV) 789 + ret = -EPROBE_DEFER; 790 + 791 + axp288_fuel_gauge_release_iio_chans(info); 792 + return ret; 793 + } 794 + } 795 + 796 + ret = devm_add_action_or_reset(dev, axp288_fuel_gauge_release_iio_chans, info); 797 + if (ret) 798 + return ret; 799 + 800 + ret = iosf_mbi_block_punit_i2c_access(); 801 + if (ret < 0) 802 + return ret; 803 + 804 + ret = axp288_fuel_gauge_read_initial_regs(info); 805 + iosf_mbi_unblock_punit_i2c_access(); 806 + if (ret < 0) 807 + return ret; 808 + 809 + psy_cfg.drv_data = info; 810 + if (no_current_sense_res) 811 + fuel_gauge_desc.num_properties = ARRAY_SIZE(fuel_gauge_props) - 3; 812 + info->bat = devm_power_supply_register(dev, &fuel_gauge_desc, &psy_cfg); 813 + if (IS_ERR(info->bat)) { 814 + ret = PTR_ERR(info->bat); 815 + dev_err(dev, "failed to register battery: %d\n", ret); 816 + return ret; 817 + } 818 + 819 + for (i = 0; i < AXP288_FG_INTR_NUM; i++) { 820 + ret = devm_request_threaded_irq(dev, info->irq[i], NULL, 821 + fuel_gauge_thread_handler, 822 + IRQF_ONESHOT, DEV_NAME, info); 823 + if (ret) 824 + return dev_err_probe(dev, ret, "requesting IRQ %d\n", info->irq[i]); 825 + } 826 + 827 + return 0; 669 828 } 670 829 671 830 static const struct platform_device_id axp288_fg_id_table[] = { ··· 760 747 }; 761 748 MODULE_DEVICE_TABLE(platform, axp288_fg_id_table); 762 749 763 - static int axp288_fuel_gauge_remove(struct platform_device *pdev) 764 - { 765 - struct axp288_fg_info *info = platform_get_drvdata(pdev); 766 - int i; 767 - 768 - power_supply_unregister(info->bat); 769 - 770 - for (i = 0; i < AXP288_FG_INTR_NUM; i++) 771 - if (info->irq[i] >= 0) 772 - free_irq(info->irq[i], info); 773 - 774 - for (i = 0; i < IIO_CHANNEL_NUM; i++) 775 - iio_channel_release(info->iio_channel[i]); 776 - 777 - return 0; 778 - } 779 - 780 750 static struct platform_driver axp288_fuel_gauge_driver = { 781 751 .probe = axp288_fuel_gauge_probe, 782 - .remove = axp288_fuel_gauge_remove, 783 752 .id_table = axp288_fg_id_table, 784 753 .driver = { 785 754 .name = DEV_NAME,
+123 -35
drivers/power/supply/bq24190_charger.c
··· 39 39 #define BQ24190_REG_POC_CHG_CONFIG_DISABLE 0x0 40 40 #define BQ24190_REG_POC_CHG_CONFIG_CHARGE 0x1 41 41 #define BQ24190_REG_POC_CHG_CONFIG_OTG 0x2 42 + #define BQ24190_REG_POC_CHG_CONFIG_OTG_ALT 0x3 42 43 #define BQ24190_REG_POC_SYS_MIN_MASK (BIT(3) | BIT(2) | BIT(1)) 43 44 #define BQ24190_REG_POC_SYS_MIN_SHIFT 1 44 45 #define BQ24190_REG_POC_SYS_MIN_MIN 3000 ··· 163 162 char model_name[I2C_NAME_SIZE]; 164 163 bool initialized; 165 164 bool irq_event; 165 + bool otg_vbus_enabled; 166 + int charge_type; 166 167 u16 sys_min; 167 168 u16 iprechg; 168 169 u16 iterm; 170 + u32 ichg; 171 + u32 ichg_max; 172 + u32 vreg; 173 + u32 vreg_max; 169 174 struct mutex f_reg_lock; 170 175 u8 f_reg; 171 176 u8 ss_reg; 172 177 u8 watchdog; 173 178 }; 179 + 180 + static int bq24190_charger_set_charge_type(struct bq24190_dev_info *bdi, 181 + const union power_supply_propval *val); 174 182 175 183 static const unsigned int bq24190_usb_extcon_cable[] = { 176 184 EXTCON_USB, ··· 507 497 } 508 498 #endif 509 499 510 - #ifdef CONFIG_REGULATOR 511 - static int bq24190_set_charge_mode(struct regulator_dev *dev, u8 val) 500 + static int bq24190_set_otg_vbus(struct bq24190_dev_info *bdi, bool enable) 512 501 { 513 - struct bq24190_dev_info *bdi = rdev_get_drvdata(dev); 502 + union power_supply_propval val = { .intval = bdi->charge_type }; 514 503 int ret; 515 504 516 505 ret = pm_runtime_get_sync(bdi->dev); ··· 519 510 return ret; 520 511 } 521 512 522 - ret = bq24190_write_mask(bdi, BQ24190_REG_POC, 523 - BQ24190_REG_POC_CHG_CONFIG_MASK, 524 - BQ24190_REG_POC_CHG_CONFIG_SHIFT, val); 513 + bdi->otg_vbus_enabled = enable; 514 + if (enable) 515 + ret = bq24190_write_mask(bdi, BQ24190_REG_POC, 516 + BQ24190_REG_POC_CHG_CONFIG_MASK, 517 + BQ24190_REG_POC_CHG_CONFIG_SHIFT, 518 + BQ24190_REG_POC_CHG_CONFIG_OTG); 519 + else 520 + ret = bq24190_charger_set_charge_type(bdi, &val); 525 521 526 522 pm_runtime_mark_last_busy(bdi->dev); 527 523 pm_runtime_put_autosuspend(bdi->dev); ··· 534 520 return ret; 535 521 } 536 522 523 + #ifdef CONFIG_REGULATOR 537 524 static int bq24190_vbus_enable(struct regulator_dev *dev) 538 525 { 539 - return bq24190_set_charge_mode(dev, BQ24190_REG_POC_CHG_CONFIG_OTG); 526 + return bq24190_set_otg_vbus(rdev_get_drvdata(dev), true); 540 527 } 541 528 542 529 static int bq24190_vbus_disable(struct regulator_dev *dev) 543 530 { 544 - return bq24190_set_charge_mode(dev, BQ24190_REG_POC_CHG_CONFIG_CHARGE); 531 + return bq24190_set_otg_vbus(rdev_get_drvdata(dev), false); 545 532 } 546 533 547 534 static int bq24190_vbus_is_enabled(struct regulator_dev *dev) ··· 565 550 pm_runtime_mark_last_busy(bdi->dev); 566 551 pm_runtime_put_autosuspend(bdi->dev); 567 552 568 - return ret ? ret : val == BQ24190_REG_POC_CHG_CONFIG_OTG; 553 + if (ret) 554 + return ret; 555 + 556 + bdi->otg_vbus_enabled = (val == BQ24190_REG_POC_CHG_CONFIG_OTG || 557 + val == BQ24190_REG_POC_CHG_CONFIG_OTG_ALT); 558 + return bdi->otg_vbus_enabled; 569 559 } 570 560 571 561 static const struct regulator_ops bq24190_vbus_ops = { ··· 675 655 BQ24190_REG_PCTCC_ITERM_MASK, 676 656 BQ24190_REG_PCTCC_ITERM_SHIFT, 677 657 v); 658 + if (ret < 0) 659 + return ret; 660 + } 661 + 662 + if (bdi->ichg) { 663 + ret = bq24190_set_field_val(bdi, BQ24190_REG_CCC, 664 + BQ24190_REG_CCC_ICHG_MASK, 665 + BQ24190_REG_CCC_ICHG_SHIFT, 666 + bq24190_ccc_ichg_values, 667 + ARRAY_SIZE(bq24190_ccc_ichg_values), 668 + bdi->ichg); 669 + if (ret < 0) 670 + return ret; 671 + } 672 + 673 + if (bdi->vreg) { 674 + ret = bq24190_set_field_val(bdi, BQ24190_REG_CVC, 675 + BQ24190_REG_CVC_VREG_MASK, 676 + BQ24190_REG_CVC_VREG_SHIFT, 677 + bq24190_cvc_vreg_values, 678 + ARRAY_SIZE(bq24190_cvc_vreg_values), 679 + bdi->vreg); 678 680 if (ret < 0) 679 681 return ret; 680 682 } ··· 816 774 default: 817 775 return -EINVAL; 818 776 } 777 + 778 + bdi->charge_type = val->intval; 779 + /* 780 + * If the 5V Vbus boost regulator is enabled delay setting 781 + * the charge-type until its gets disabled. 782 + */ 783 + if (bdi->otg_vbus_enabled) 784 + return 0; 819 785 820 786 if (chg_config) { /* Enabling the charger */ 821 787 ret = bq24190_write_mask(bdi, BQ24190_REG_CCC, ··· 1026 976 return 0; 1027 977 } 1028 978 1029 - static int bq24190_charger_get_current_max(struct bq24190_dev_info *bdi, 1030 - union power_supply_propval *val) 1031 - { 1032 - int idx = ARRAY_SIZE(bq24190_ccc_ichg_values) - 1; 1033 - 1034 - val->intval = bq24190_ccc_ichg_values[idx]; 1035 - return 0; 1036 - } 1037 - 1038 979 static int bq24190_charger_set_current(struct bq24190_dev_info *bdi, 1039 980 const union power_supply_propval *val) 1040 981 { ··· 1042 1001 if (v) 1043 1002 curr *= 5; 1044 1003 1045 - return bq24190_set_field_val(bdi, BQ24190_REG_CCC, 1004 + if (curr > bdi->ichg_max) 1005 + return -EINVAL; 1006 + 1007 + ret = bq24190_set_field_val(bdi, BQ24190_REG_CCC, 1046 1008 BQ24190_REG_CCC_ICHG_MASK, BQ24190_REG_CCC_ICHG_SHIFT, 1047 1009 bq24190_ccc_ichg_values, 1048 1010 ARRAY_SIZE(bq24190_ccc_ichg_values), curr); 1011 + if (ret < 0) 1012 + return ret; 1013 + 1014 + bdi->ichg = curr; 1015 + 1016 + return 0; 1049 1017 } 1050 1018 1051 1019 static int bq24190_charger_get_voltage(struct bq24190_dev_info *bdi, ··· 1073 1023 return 0; 1074 1024 } 1075 1025 1076 - static int bq24190_charger_get_voltage_max(struct bq24190_dev_info *bdi, 1077 - union power_supply_propval *val) 1078 - { 1079 - int idx = ARRAY_SIZE(bq24190_cvc_vreg_values) - 1; 1080 - 1081 - val->intval = bq24190_cvc_vreg_values[idx]; 1082 - return 0; 1083 - } 1084 - 1085 1026 static int bq24190_charger_set_voltage(struct bq24190_dev_info *bdi, 1086 1027 const union power_supply_propval *val) 1087 1028 { 1088 - return bq24190_set_field_val(bdi, BQ24190_REG_CVC, 1029 + int ret; 1030 + 1031 + if (val->intval > bdi->vreg_max) 1032 + return -EINVAL; 1033 + 1034 + ret = bq24190_set_field_val(bdi, BQ24190_REG_CVC, 1089 1035 BQ24190_REG_CVC_VREG_MASK, BQ24190_REG_CVC_VREG_SHIFT, 1090 1036 bq24190_cvc_vreg_values, 1091 1037 ARRAY_SIZE(bq24190_cvc_vreg_values), val->intval); 1038 + if (ret < 0) 1039 + return ret; 1040 + 1041 + bdi->vreg = val->intval; 1042 + 1043 + return 0; 1092 1044 } 1093 1045 1094 1046 static int bq24190_charger_get_iinlimit(struct bq24190_dev_info *bdi, ··· 1160 1108 ret = bq24190_charger_get_current(bdi, val); 1161 1109 break; 1162 1110 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: 1163 - ret = bq24190_charger_get_current_max(bdi, val); 1111 + val->intval = bdi->ichg_max; 1112 + ret = 0; 1164 1113 break; 1165 1114 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: 1166 1115 ret = bq24190_charger_get_voltage(bdi, val); 1167 1116 break; 1168 1117 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: 1169 - ret = bq24190_charger_get_voltage_max(bdi, val); 1118 + val->intval = bdi->vreg_max; 1119 + ret = 0; 1170 1120 break; 1171 1121 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: 1172 1122 ret = bq24190_charger_get_iinlimit(bdi, val); ··· 1260 1206 struct bq24190_dev_info *bdi = 1261 1207 container_of(work, struct bq24190_dev_info, 1262 1208 input_current_limit_work.work); 1209 + union power_supply_propval val; 1210 + int ret; 1263 1211 1264 - 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); 1265 1221 } 1266 1222 1267 1223 /* Sync the input-current-limit with our parent supply (if we have one) */ ··· 1735 1671 { 1736 1672 const char * const s = "ti,system-minimum-microvolt"; 1737 1673 struct power_supply_battery_info *info; 1738 - int v; 1674 + int v, idx; 1675 + 1676 + idx = ARRAY_SIZE(bq24190_ccc_ichg_values) - 1; 1677 + bdi->ichg_max = bq24190_ccc_ichg_values[idx]; 1678 + 1679 + idx = ARRAY_SIZE(bq24190_cvc_vreg_values) - 1; 1680 + bdi->vreg_max = bq24190_cvc_vreg_values[idx]; 1739 1681 1740 1682 if (device_property_read_u32(bdi->dev, s, &v) == 0) { 1741 1683 v /= 1000; ··· 1752 1682 dev_warn(bdi->dev, "invalid value for %s: %u\n", s, v); 1753 1683 } 1754 1684 1755 - if (bdi->dev->of_node && 1756 - !power_supply_get_battery_info(bdi->charger, &info)) { 1685 + if (!power_supply_get_battery_info(bdi->charger, &info)) { 1757 1686 v = info->precharge_current_ua / 1000; 1758 1687 if (v >= BQ24190_REG_PCTCC_IPRECHG_MIN 1759 1688 && v <= BQ24190_REG_PCTCC_IPRECHG_MAX) ··· 1768 1699 else 1769 1700 dev_warn(bdi->dev, "invalid value for battery:charge-term-current-microamp: %d\n", 1770 1701 v); 1702 + 1703 + /* These are optional, so no warning when not set */ 1704 + v = info->constant_charge_current_max_ua; 1705 + if (v >= bq24190_ccc_ichg_values[0] && v <= bdi->ichg_max) 1706 + bdi->ichg = bdi->ichg_max = v; 1707 + 1708 + v = info->constant_charge_voltage_max_uv; 1709 + if (v >= bq24190_cvc_vreg_values[0] && v <= bdi->vreg_max) 1710 + bdi->vreg = bdi->vreg_max = v; 1771 1711 } 1772 1712 1773 1713 return 0; ··· 1806 1728 bdi->dev = dev; 1807 1729 strncpy(bdi->model_name, id->name, I2C_NAME_SIZE); 1808 1730 mutex_init(&bdi->f_reg_lock); 1731 + bdi->charge_type = POWER_SUPPLY_CHARGE_TYPE_FAST; 1809 1732 bdi->f_reg = 0; 1810 1733 bdi->ss_reg = BQ24190_REG_SS_VBUS_STAT_MASK; /* impossible state */ 1811 1734 INIT_DELAYED_WORK(&bdi->input_current_limit_work, ··· 1939 1860 return 0; 1940 1861 } 1941 1862 1863 + static void bq24190_shutdown(struct i2c_client *client) 1864 + { 1865 + struct bq24190_dev_info *bdi = i2c_get_clientdata(client); 1866 + 1867 + /* Turn off 5V boost regulator on shutdown */ 1868 + bq24190_set_otg_vbus(bdi, false); 1869 + } 1870 + 1942 1871 static __maybe_unused int bq24190_runtime_suspend(struct device *dev) 1943 1872 { 1944 1873 struct i2c_client *client = to_i2c_client(dev); ··· 2057 1970 static struct i2c_driver bq24190_driver = { 2058 1971 .probe = bq24190_probe, 2059 1972 .remove = bq24190_remove, 1973 + .shutdown = bq24190_shutdown, 2060 1974 .id_table = bq24190_i2c_ids, 2061 1975 .driver = { 2062 1976 .name = "bq24190-charger",
+319 -77
drivers/power/supply/bq25890_charger.c
··· 8 8 #include <linux/module.h> 9 9 #include <linux/i2c.h> 10 10 #include <linux/power_supply.h> 11 + #include <linux/power/bq25890_charger.h> 11 12 #include <linux/regmap.h> 13 + #include <linux/regulator/driver.h> 12 14 #include <linux/types.h> 13 15 #include <linux/gpio/consumer.h> 14 16 #include <linux/interrupt.h> ··· 27 25 #define BQ25895_ID 7 28 26 #define BQ25896_ID 0 29 27 28 + #define PUMP_EXPRESS_START_DELAY (5 * HZ) 29 + #define PUMP_EXPRESS_MAX_TRIES 6 30 + #define PUMP_EXPRESS_VBUS_MARGIN_uV 1000000 31 + 30 32 enum bq25890_chip_version { 31 33 BQ25890, 32 34 BQ25892, ··· 46 40 }; 47 41 48 42 enum bq25890_fields { 49 - F_EN_HIZ, F_EN_ILIM, F_IILIM, /* Reg00 */ 43 + F_EN_HIZ, F_EN_ILIM, F_IINLIM, /* Reg00 */ 50 44 F_BHOT, F_BCOLD, F_VINDPM_OFS, /* Reg01 */ 51 45 F_CONV_START, F_CONV_RATE, F_BOOSTF, F_ICO_EN, 52 46 F_HVDCP_EN, F_MAXC_EN, F_FORCE_DPM, F_AUTO_DPDM_EN, /* Reg02 */ ··· 100 94 u8 vsys_status; 101 95 u8 boost_fault; 102 96 u8 bat_fault; 97 + u8 ntc_fault; 103 98 }; 104 99 105 100 struct bq25890_device { ··· 111 104 struct usb_phy *usb_phy; 112 105 struct notifier_block usb_nb; 113 106 struct work_struct usb_work; 107 + struct delayed_work pump_express_work; 114 108 unsigned long usb_event; 115 109 116 110 struct regmap *rmap; 117 111 struct regmap_field *rmap_fields[F_MAX_FIELDS]; 118 112 113 + bool skip_reset; 114 + bool read_back_init_data; 115 + u32 pump_express_vbus_max; 119 116 enum bq25890_chip_version chip_version; 120 117 struct bq25890_init_data init_data; 121 118 struct bq25890_state state; ··· 164 153 /* REG00 */ 165 154 [F_EN_HIZ] = REG_FIELD(0x00, 7, 7), 166 155 [F_EN_ILIM] = REG_FIELD(0x00, 6, 6), 167 - [F_IILIM] = REG_FIELD(0x00, 0, 5), 156 + [F_IINLIM] = REG_FIELD(0x00, 0, 5), 168 157 /* REG01 */ 169 158 [F_BHOT] = REG_FIELD(0x01, 6, 7), 170 159 [F_BCOLD] = REG_FIELD(0x01, 5, 5), ··· 267 256 /* range tables */ 268 257 TBL_ICHG, 269 258 TBL_ITERM, 270 - TBL_IILIM, 259 + TBL_IINLIM, 271 260 TBL_VREG, 272 261 TBL_BOOSTV, 273 262 TBL_SYSVMIN, 263 + TBL_VBUSV, 274 264 TBL_VBATCOMP, 275 265 TBL_RBATCOMP, 276 266 ··· 332 320 } bq25890_tables[] = { 333 321 /* range tables */ 334 322 /* TODO: BQ25896 has max ICHG 3008 mA */ 335 - [TBL_ICHG] = { .rt = {0, 5056000, 64000} }, /* uA */ 336 - [TBL_ITERM] = { .rt = {64000, 1024000, 64000} }, /* uA */ 337 - [TBL_IILIM] = { .rt = {100000, 3250000, 50000} }, /* uA */ 338 - [TBL_VREG] = { .rt = {3840000, 4608000, 16000} }, /* uV */ 339 - [TBL_BOOSTV] = { .rt = {4550000, 5510000, 64000} }, /* uV */ 340 - [TBL_SYSVMIN] = { .rt = {3000000, 3700000, 100000} }, /* uV */ 341 - [TBL_VBATCOMP] ={ .rt = {0, 224000, 32000} }, /* uV */ 342 - [TBL_RBATCOMP] ={ .rt = {0, 140000, 20000} }, /* uOhm */ 323 + [TBL_ICHG] = { .rt = {0, 5056000, 64000} }, /* uA */ 324 + [TBL_ITERM] = { .rt = {64000, 1024000, 64000} }, /* uA */ 325 + [TBL_IINLIM] = { .rt = {100000, 3250000, 50000} }, /* uA */ 326 + [TBL_VREG] = { .rt = {3840000, 4608000, 16000} }, /* uV */ 327 + [TBL_BOOSTV] = { .rt = {4550000, 5510000, 64000} }, /* uV */ 328 + [TBL_SYSVMIN] = { .rt = {3000000, 3700000, 100000} }, /* uV */ 329 + [TBL_VBUSV] = { .rt = {2600000, 15300000, 100000} }, /* uV */ 330 + [TBL_VBATCOMP] = { .rt = {0, 224000, 32000} }, /* uV */ 331 + [TBL_RBATCOMP] = { .rt = {0, 140000, 20000} }, /* uOhm */ 343 332 344 333 /* lookup tables */ 345 334 [TBL_TREG] = { .lt = {bq25890_treg_tbl, BQ25890_TREG_TBL_SIZE} }, ··· 420 407 CHRG_FAULT_TIMER_EXPIRED, 421 408 }; 422 409 410 + enum bq25890_ntc_fault { 411 + NTC_FAULT_NORMAL = 0, 412 + NTC_FAULT_WARM = 2, 413 + NTC_FAULT_COOL = 3, 414 + NTC_FAULT_COLD = 5, 415 + NTC_FAULT_HOT = 6, 416 + }; 417 + 423 418 static bool bq25890_is_adc_property(enum power_supply_property psp) 424 419 { 425 420 switch (psp) { ··· 442 421 } 443 422 444 423 static irqreturn_t __bq25890_handle_irq(struct bq25890_device *bq); 424 + 425 + static int bq25890_get_vbus_voltage(struct bq25890_device *bq) 426 + { 427 + int ret; 428 + 429 + ret = bq25890_field_read(bq, F_VBUSV); 430 + if (ret < 0) 431 + return ret; 432 + 433 + return bq25890_find_val(ret, TBL_VBUSV); 434 + } 445 435 446 436 static int bq25890_power_supply_get_property(struct power_supply *psy, 447 437 enum power_supply_property psp, ··· 531 499 532 500 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: 533 501 val->intval = bq25890_find_val(bq->init_data.ichg, TBL_ICHG); 502 + 503 + /* When temperature is too low, charge current is decreased */ 504 + if (bq->state.ntc_fault == NTC_FAULT_COOL) { 505 + ret = bq25890_field_read(bq, F_JEITA_ISET); 506 + if (ret < 0) 507 + return ret; 508 + 509 + if (ret) 510 + val->intval /= 5; 511 + else 512 + val->intval /= 2; 513 + } 534 514 break; 535 515 536 516 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: ··· 572 528 break; 573 529 574 530 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: 575 - ret = bq25890_field_read(bq, F_IILIM); 531 + ret = bq25890_field_read(bq, F_IINLIM); 576 532 if (ret < 0) 577 533 return ret; 578 534 579 - val->intval = bq25890_find_val(ret, TBL_IILIM); 535 + val->intval = bq25890_find_val(ret, TBL_IINLIM); 580 536 break; 581 537 582 538 case POWER_SUPPLY_PROP_VOLTAGE_NOW: ··· 613 569 return 0; 614 570 } 615 571 572 + /* On the BQ25892 try to get charger-type info from our supplier */ 573 + static void bq25890_charger_external_power_changed(struct power_supply *psy) 574 + { 575 + struct bq25890_device *bq = power_supply_get_drvdata(psy); 576 + union power_supply_propval val; 577 + int input_current_limit, ret; 578 + 579 + if (bq->chip_version != BQ25892) 580 + return; 581 + 582 + ret = power_supply_get_property_from_supplier(bq->charger, 583 + POWER_SUPPLY_PROP_USB_TYPE, 584 + &val); 585 + if (ret) 586 + return; 587 + 588 + switch (val.intval) { 589 + case POWER_SUPPLY_USB_TYPE_DCP: 590 + input_current_limit = bq25890_find_idx(2000000, TBL_IINLIM); 591 + if (bq->pump_express_vbus_max) { 592 + queue_delayed_work(system_power_efficient_wq, 593 + &bq->pump_express_work, 594 + PUMP_EXPRESS_START_DELAY); 595 + } 596 + break; 597 + case POWER_SUPPLY_USB_TYPE_CDP: 598 + case POWER_SUPPLY_USB_TYPE_ACA: 599 + input_current_limit = bq25890_find_idx(1500000, TBL_IINLIM); 600 + break; 601 + case POWER_SUPPLY_USB_TYPE_SDP: 602 + default: 603 + input_current_limit = bq25890_find_idx(500000, TBL_IINLIM); 604 + } 605 + 606 + bq25890_field_write(bq, F_IINLIM, input_current_limit); 607 + } 608 + 616 609 static int bq25890_get_chip_state(struct bq25890_device *bq, 617 610 struct bq25890_state *state) 618 611 { ··· 664 583 {F_VSYS_STAT, &state->vsys_status}, 665 584 {F_BOOST_FAULT, &state->boost_fault}, 666 585 {F_BAT_FAULT, &state->bat_fault}, 667 - {F_CHG_FAULT, &state->chrg_fault} 586 + {F_CHG_FAULT, &state->chrg_fault}, 587 + {F_NTC_FAULT, &state->ntc_fault} 668 588 }; 669 589 670 590 for (i = 0; i < ARRAY_SIZE(state_fields); i++) { ··· 676 594 *state_fields[i].data = ret; 677 595 } 678 596 679 - dev_dbg(bq->dev, "S:CHG/PG/VSYS=%d/%d/%d, F:CHG/BOOST/BAT=%d/%d/%d\n", 597 + dev_dbg(bq->dev, "S:CHG/PG/VSYS=%d/%d/%d, F:CHG/BOOST/BAT/NTC=%d/%d/%d/%d\n", 680 598 state->chrg_status, state->online, state->vsys_status, 681 - state->chrg_fault, state->boost_fault, state->bat_fault); 599 + state->chrg_fault, state->boost_fault, state->bat_fault, 600 + state->ntc_fault); 682 601 683 602 return 0; 684 603 } ··· 753 670 return 0; 754 671 } 755 672 756 - static int bq25890_hw_init(struct bq25890_device *bq) 673 + static int bq25890_rw_init_data(struct bq25890_device *bq) 757 674 { 675 + bool write = !bq->read_back_init_data; 758 676 int ret; 759 677 int i; 760 678 761 679 const struct { 762 680 enum bq25890_fields id; 763 - u32 value; 681 + u8 *value; 764 682 } init_data[] = { 765 - {F_ICHG, bq->init_data.ichg}, 766 - {F_VREG, bq->init_data.vreg}, 767 - {F_ITERM, bq->init_data.iterm}, 768 - {F_IPRECHG, bq->init_data.iprechg}, 769 - {F_SYSVMIN, bq->init_data.sysvmin}, 770 - {F_BOOSTV, bq->init_data.boostv}, 771 - {F_BOOSTI, bq->init_data.boosti}, 772 - {F_BOOSTF, bq->init_data.boostf}, 773 - {F_EN_ILIM, bq->init_data.ilim_en}, 774 - {F_TREG, bq->init_data.treg}, 775 - {F_BATCMP, bq->init_data.rbatcomp}, 776 - {F_VCLAMP, bq->init_data.vclamp}, 683 + {F_ICHG, &bq->init_data.ichg}, 684 + {F_VREG, &bq->init_data.vreg}, 685 + {F_ITERM, &bq->init_data.iterm}, 686 + {F_IPRECHG, &bq->init_data.iprechg}, 687 + {F_SYSVMIN, &bq->init_data.sysvmin}, 688 + {F_BOOSTV, &bq->init_data.boostv}, 689 + {F_BOOSTI, &bq->init_data.boosti}, 690 + {F_BOOSTF, &bq->init_data.boostf}, 691 + {F_EN_ILIM, &bq->init_data.ilim_en}, 692 + {F_TREG, &bq->init_data.treg}, 693 + {F_BATCMP, &bq->init_data.rbatcomp}, 694 + {F_VCLAMP, &bq->init_data.vclamp}, 777 695 }; 778 696 779 - ret = bq25890_chip_reset(bq); 780 - if (ret < 0) { 781 - dev_dbg(bq->dev, "Reset failed %d\n", ret); 782 - return ret; 697 + for (i = 0; i < ARRAY_SIZE(init_data); i++) { 698 + if (write) { 699 + ret = bq25890_field_write(bq, init_data[i].id, 700 + *init_data[i].value); 701 + } else { 702 + ret = bq25890_field_read(bq, init_data[i].id); 703 + if (ret >= 0) 704 + *init_data[i].value = ret; 705 + } 706 + if (ret < 0) { 707 + dev_dbg(bq->dev, "Accessing init data failed %d\n", ret); 708 + return ret; 709 + } 710 + } 711 + 712 + return 0; 713 + } 714 + 715 + static int bq25890_hw_init(struct bq25890_device *bq) 716 + { 717 + int ret; 718 + 719 + if (!bq->skip_reset) { 720 + ret = bq25890_chip_reset(bq); 721 + if (ret < 0) { 722 + dev_dbg(bq->dev, "Reset failed %d\n", ret); 723 + return ret; 724 + } 725 + } else { 726 + /* 727 + * Ensure charging is enabled, on some boards where the fw 728 + * takes care of initalizition F_CHG_CFG is set to 0 before 729 + * handing control over to the OS. 730 + */ 731 + ret = bq25890_field_write(bq, F_CHG_CFG, 1); 732 + if (ret < 0) { 733 + dev_dbg(bq->dev, "Enabling charging failed %d\n", ret); 734 + return ret; 735 + } 783 736 } 784 737 785 738 /* disable watchdog */ ··· 826 707 } 827 708 828 709 /* initialize currents/voltages and other parameters */ 829 - for (i = 0; i < ARRAY_SIZE(init_data); i++) { 830 - ret = bq25890_field_write(bq, init_data[i].id, 831 - init_data[i].value); 832 - if (ret < 0) { 833 - dev_dbg(bq->dev, "Writing init data failed %d\n", ret); 834 - return ret; 835 - } 836 - } 710 + ret = bq25890_rw_init_data(bq); 711 + if (ret) 712 + return ret; 837 713 838 714 ret = bq25890_get_chip_state(bq, &bq->state); 839 715 if (ret < 0) { ··· 874 760 .properties = bq25890_power_supply_props, 875 761 .num_properties = ARRAY_SIZE(bq25890_power_supply_props), 876 762 .get_property = bq25890_power_supply_get_property, 763 + .external_power_changed = bq25890_charger_external_power_changed, 877 764 }; 878 765 879 766 static int bq25890_power_supply_init(struct bq25890_device *bq) ··· 891 776 return PTR_ERR_OR_ZERO(bq->charger); 892 777 } 893 778 779 + static int bq25890_set_otg_cfg(struct bq25890_device *bq, u8 val) 780 + { 781 + int ret; 782 + 783 + ret = bq25890_field_write(bq, F_OTG_CFG, val); 784 + if (ret < 0) 785 + dev_err(bq->dev, "Error switching to boost/charger mode: %d\n", ret); 786 + 787 + return ret; 788 + } 789 + 790 + static void bq25890_pump_express_work(struct work_struct *data) 791 + { 792 + struct bq25890_device *bq = 793 + container_of(data, struct bq25890_device, pump_express_work.work); 794 + int voltage, i, ret; 795 + 796 + dev_dbg(bq->dev, "Start to request input voltage increasing\n"); 797 + 798 + /* Enable current pulse voltage control protocol */ 799 + ret = bq25890_field_write(bq, F_PUMPX_EN, 1); 800 + if (ret < 0) 801 + goto error_print; 802 + 803 + for (i = 0; i < PUMP_EXPRESS_MAX_TRIES; i++) { 804 + voltage = bq25890_get_vbus_voltage(bq); 805 + if (voltage < 0) 806 + goto error_print; 807 + dev_dbg(bq->dev, "input voltage = %d uV\n", voltage); 808 + 809 + if ((voltage + PUMP_EXPRESS_VBUS_MARGIN_uV) > 810 + bq->pump_express_vbus_max) 811 + break; 812 + 813 + ret = bq25890_field_write(bq, F_PUMPX_UP, 1); 814 + if (ret < 0) 815 + goto error_print; 816 + 817 + /* Note a single PUMPX up pulse-sequence takes 2.1s */ 818 + ret = regmap_field_read_poll_timeout(bq->rmap_fields[F_PUMPX_UP], 819 + ret, !ret, 100000, 3000000); 820 + if (ret < 0) 821 + goto error_print; 822 + 823 + /* Make sure ADC has sampled Vbus before checking again */ 824 + msleep(1000); 825 + } 826 + 827 + bq25890_field_write(bq, F_PUMPX_EN, 0); 828 + 829 + dev_info(bq->dev, "Hi-voltage charging requested, input voltage is %d mV\n", 830 + voltage); 831 + 832 + return; 833 + error_print: 834 + dev_err(bq->dev, "Failed to request hi-voltage charging\n"); 835 + } 836 + 894 837 static void bq25890_usb_work(struct work_struct *data) 895 838 { 896 839 int ret; ··· 958 785 switch (bq->usb_event) { 959 786 case USB_EVENT_ID: 960 787 /* Enable boost mode */ 961 - ret = bq25890_field_write(bq, F_OTG_CFG, 1); 962 - if (ret < 0) 963 - goto error; 788 + bq25890_set_otg_cfg(bq, 1); 964 789 break; 965 790 966 791 case USB_EVENT_NONE: 967 792 /* Disable boost mode */ 968 - ret = bq25890_field_write(bq, F_OTG_CFG, 0); 969 - if (ret < 0) 970 - goto error; 971 - 972 - power_supply_changed(bq->charger); 793 + ret = bq25890_set_otg_cfg(bq, 0); 794 + if (ret == 0) 795 + power_supply_changed(bq->charger); 973 796 break; 974 797 } 975 - 976 - return; 977 - 978 - error: 979 - dev_err(bq->dev, "Error switching to boost/charger mode.\n"); 980 798 } 981 799 982 800 static int bq25890_usb_notifier(struct notifier_block *nb, unsigned long val, ··· 981 817 982 818 return NOTIFY_OK; 983 819 } 820 + 821 + #ifdef CONFIG_REGULATOR 822 + static int bq25890_vbus_enable(struct regulator_dev *rdev) 823 + { 824 + struct bq25890_device *bq = rdev_get_drvdata(rdev); 825 + 826 + return bq25890_set_otg_cfg(bq, 1); 827 + } 828 + 829 + static int bq25890_vbus_disable(struct regulator_dev *rdev) 830 + { 831 + struct bq25890_device *bq = rdev_get_drvdata(rdev); 832 + 833 + return bq25890_set_otg_cfg(bq, 0); 834 + } 835 + 836 + static int bq25890_vbus_is_enabled(struct regulator_dev *rdev) 837 + { 838 + struct bq25890_device *bq = rdev_get_drvdata(rdev); 839 + 840 + return bq25890_field_read(bq, F_OTG_CFG); 841 + } 842 + 843 + static const struct regulator_ops bq25890_vbus_ops = { 844 + .enable = bq25890_vbus_enable, 845 + .disable = bq25890_vbus_disable, 846 + .is_enabled = bq25890_vbus_is_enabled, 847 + }; 848 + 849 + static const struct regulator_desc bq25890_vbus_desc = { 850 + .name = "usb_otg_vbus", 851 + .of_match = "usb-otg-vbus", 852 + .type = REGULATOR_VOLTAGE, 853 + .owner = THIS_MODULE, 854 + .ops = &bq25890_vbus_ops, 855 + .fixed_uV = 5000000, 856 + .n_voltages = 1, 857 + }; 858 + #endif 984 859 985 860 static int bq25890_get_chip_version(struct bq25890_device *bq) 986 861 { ··· 1139 936 int ret; 1140 937 struct bq25890_init_data *init = &bq->init_data; 1141 938 939 + /* Optional, left at 0 if property is not present */ 940 + device_property_read_u32(bq->dev, "linux,pump-express-vbus-max", 941 + &bq->pump_express_vbus_max); 942 + 943 + bq->skip_reset = device_property_read_bool(bq->dev, "linux,skip-reset"); 944 + bq->read_back_init_data = device_property_read_bool(bq->dev, 945 + "linux,read-back-settings"); 946 + if (bq->read_back_init_data) 947 + return 0; 948 + 1142 949 ret = bq25890_fw_read_u32_props(bq); 1143 950 if (ret < 0) 1144 951 return ret; ··· 1165 952 struct device *dev = &client->dev; 1166 953 struct bq25890_device *bq; 1167 954 int ret; 1168 - int i; 1169 955 1170 956 bq = devm_kzalloc(dev, sizeof(*bq), GFP_KERNEL); 1171 957 if (!bq) ··· 1174 962 bq->dev = dev; 1175 963 1176 964 mutex_init(&bq->lock); 965 + INIT_DELAYED_WORK(&bq->pump_express_work, bq25890_pump_express_work); 1177 966 1178 967 bq->rmap = devm_regmap_init_i2c(client, &bq25890_regmap_config); 1179 968 if (IS_ERR(bq->rmap)) 1180 969 return dev_err_probe(dev, PTR_ERR(bq->rmap), 1181 970 "failed to allocate register map\n"); 1182 971 1183 - for (i = 0; i < ARRAY_SIZE(bq25890_reg_fields); i++) { 1184 - const struct reg_field *reg_fields = bq25890_reg_fields; 1185 - 1186 - bq->rmap_fields[i] = devm_regmap_field_alloc(dev, bq->rmap, 1187 - reg_fields[i]); 1188 - if (IS_ERR(bq->rmap_fields[i])) 1189 - return dev_err_probe(dev, PTR_ERR(bq->rmap_fields[i]), 1190 - "cannot allocate regmap field\n"); 1191 - } 972 + ret = devm_regmap_field_bulk_alloc(dev, bq->rmap, bq->rmap_fields, 973 + bq25890_reg_fields, F_MAX_FIELDS); 974 + if (ret) 975 + return ret; 1192 976 1193 977 i2c_set_clientdata(client, bq); 1194 978 ··· 1194 986 return ret; 1195 987 } 1196 988 1197 - if (!dev->platform_data) { 1198 - ret = bq25890_fw_probe(bq); 1199 - if (ret < 0) { 1200 - dev_err(dev, "Cannot read device properties: %d\n", 1201 - ret); 1202 - return ret; 1203 - } 1204 - } else { 1205 - return -ENODEV; 1206 - } 989 + ret = bq25890_fw_probe(bq); 990 + if (ret < 0) 991 + return dev_err_probe(dev, ret, "reading device properties\n"); 1207 992 1208 993 ret = bq25890_hw_init(bq); 1209 994 if (ret < 0) { ··· 1219 1018 bq->usb_nb.notifier_call = bq25890_usb_notifier; 1220 1019 usb_register_notifier(bq->usb_phy, &bq->usb_nb); 1221 1020 } 1021 + #ifdef CONFIG_REGULATOR 1022 + else { 1023 + struct bq25890_platform_data *pdata = dev_get_platdata(dev); 1024 + struct regulator_config cfg = { }; 1025 + struct regulator_dev *reg; 1026 + 1027 + cfg.dev = dev; 1028 + cfg.driver_data = bq; 1029 + if (pdata) 1030 + cfg.init_data = pdata->regulator_init_data; 1031 + 1032 + reg = devm_regulator_register(dev, &bq25890_vbus_desc, &cfg); 1033 + if (IS_ERR(reg)) 1034 + return dev_err_probe(dev, PTR_ERR(reg), "registering regulator"); 1035 + } 1036 + #endif 1222 1037 1223 1038 ret = bq25890_power_supply_init(bq); 1224 1039 if (ret < 0) { ··· 1265 1048 if (!IS_ERR_OR_NULL(bq->usb_phy)) 1266 1049 usb_unregister_notifier(bq->usb_phy, &bq->usb_nb); 1267 1050 1268 - /* reset all registers to default values */ 1269 - bq25890_chip_reset(bq); 1051 + if (!bq->skip_reset) { 1052 + /* reset all registers to default values */ 1053 + bq25890_chip_reset(bq); 1054 + } 1270 1055 1271 1056 return 0; 1057 + } 1058 + 1059 + static void bq25890_shutdown(struct i2c_client *client) 1060 + { 1061 + struct bq25890_device *bq = i2c_get_clientdata(client); 1062 + 1063 + /* 1064 + * TODO this if + return should probably be removed, but that would 1065 + * introduce a function change for boards using the usb-phy framework. 1066 + * This needs to be tested on such a board before making this change. 1067 + */ 1068 + if (!IS_ERR_OR_NULL(bq->usb_phy)) 1069 + return; 1070 + 1071 + /* 1072 + * Turn off the 5v Boost regulator which outputs Vbus to the device's 1073 + * Micro-USB or Type-C USB port. Leaving this on drains power and 1074 + * this avoids the PMIC on some device-models seeing this as Vbus 1075 + * getting inserted after shutdown, causing the device to immediately 1076 + * power-up again. 1077 + */ 1078 + bq25890_set_otg_cfg(bq, 0); 1272 1079 } 1273 1080 1274 1081 #ifdef CONFIG_PM_SLEEP ··· 1374 1133 }, 1375 1134 .probe = bq25890_probe, 1376 1135 .remove = bq25890_remove, 1136 + .shutdown = bq25890_shutdown, 1377 1137 .id_table = bq25890_i2c_ids, 1378 1138 }; 1379 1139 module_i2c_driver(bq25890_driver);
+1 -1
drivers/power/supply/bq25980_charger.c
··· 764 764 if (!state.ce) 765 765 val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE; 766 766 else if (state.bypass) 767 - val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST; 767 + val->intval = POWER_SUPPLY_CHARGE_TYPE_BYPASS; 768 768 else if (!state.bypass) 769 769 val->intval = POWER_SUPPLY_CHARGE_TYPE_STANDARD; 770 770 break;
+92 -26
drivers/power/supply/cpcap-battery.c
··· 28 28 #include <linux/power_supply.h> 29 29 #include <linux/reboot.h> 30 30 #include <linux/regmap.h> 31 + #include <linux/nvmem-consumer.h> 31 32 #include <linux/moduleparam.h> 32 33 33 34 #include <linux/iio/consumer.h> ··· 73 72 #define CPCAP_REG_CCCC2_ENABLE BIT(3) 74 73 75 74 #define CPCAP_BATTERY_CC_SAMPLE_PERIOD_MS 250 75 + 76 + #define CPCAP_BATTERY_EB41_HW4X_ID 0x9E 77 + #define CPCAP_BATTERY_BW8X_ID 0x98 76 78 77 79 enum { 78 80 CPCAP_BATTERY_IIO_BATTDET, ··· 142 138 int charge_full; 143 139 int status; 144 140 u16 vendor; 141 + bool check_nvmem; 145 142 unsigned int is_full:1; 146 143 }; 147 144 ··· 357 352 ccd->sample, 358 353 ccd->accumulator, 359 354 ccd->offset); 355 + } 356 + 357 + 358 + /* 359 + * Based on the values from Motorola mapphone Linux kernel for the 360 + * stock Droid 4 battery eb41. In the Motorola mapphone Linux 361 + * kernel tree the value for pm_cd_factor is passed to the kernel 362 + * via device tree. If it turns out to be something device specific 363 + * we can consider that too later. These values are also fine for 364 + * Bionic's hw4x. 365 + * 366 + * And looking at the battery full and shutdown values for the stock 367 + * kernel on droid 4, full is 4351000 and software initiates shutdown 368 + * at 3078000. The device will die around 2743000. 369 + */ 370 + static const struct cpcap_battery_config cpcap_battery_eb41_data = { 371 + .cd_factor = 0x3cc, 372 + .info.technology = POWER_SUPPLY_TECHNOLOGY_LION, 373 + .info.voltage_max_design = 4351000, 374 + .info.voltage_min_design = 3100000, 375 + .info.charge_full_design = 1740000, 376 + .bat.constant_charge_voltage_max_uv = 4200000, 377 + }; 378 + 379 + /* Values for the extended Droid Bionic battery bw8x. */ 380 + static const struct cpcap_battery_config cpcap_battery_bw8x_data = { 381 + .cd_factor = 0x3cc, 382 + .info.technology = POWER_SUPPLY_TECHNOLOGY_LION, 383 + .info.voltage_max_design = 4200000, 384 + .info.voltage_min_design = 3200000, 385 + .info.charge_full_design = 2760000, 386 + .bat.constant_charge_voltage_max_uv = 4200000, 387 + }; 388 + 389 + /* 390 + * Safe values for any lipo battery likely to fit into a mapphone 391 + * battery bay. 392 + */ 393 + static const struct cpcap_battery_config cpcap_battery_unkown_data = { 394 + .cd_factor = 0x3cc, 395 + .info.technology = POWER_SUPPLY_TECHNOLOGY_LION, 396 + .info.voltage_max_design = 4200000, 397 + .info.voltage_min_design = 3200000, 398 + .info.charge_full_design = 3000000, 399 + .bat.constant_charge_voltage_max_uv = 4200000, 400 + }; 401 + 402 + static int cpcap_battery_match_nvmem(struct device *dev, const void *data) 403 + { 404 + if (strcmp(dev_name(dev), "89-500029ba0f73") == 0) 405 + return 1; 406 + else 407 + return 0; 408 + } 409 + 410 + static void cpcap_battery_detect_battery_type(struct cpcap_battery_ddata *ddata) 411 + { 412 + struct nvmem_device *nvmem; 413 + u8 battery_id = 0; 414 + 415 + ddata->check_nvmem = false; 416 + 417 + nvmem = nvmem_device_find(NULL, &cpcap_battery_match_nvmem); 418 + if (IS_ERR_OR_NULL(nvmem)) { 419 + ddata->check_nvmem = true; 420 + dev_info_once(ddata->dev, "Can not find battery nvmem device. Assuming generic lipo battery\n"); 421 + } else if (nvmem_device_read(nvmem, 2, 1, &battery_id) < 0) { 422 + battery_id = 0; 423 + ddata->check_nvmem = true; 424 + dev_warn(ddata->dev, "Can not read battery nvmem device. Assuming generic lipo battery\n"); 425 + } 426 + 427 + switch (battery_id) { 428 + case CPCAP_BATTERY_EB41_HW4X_ID: 429 + ddata->config = cpcap_battery_eb41_data; 430 + break; 431 + case CPCAP_BATTERY_BW8X_ID: 432 + ddata->config = cpcap_battery_bw8x_data; 433 + break; 434 + default: 435 + ddata->config = cpcap_battery_unkown_data; 436 + } 360 437 } 361 438 362 439 /** ··· 657 570 658 571 latest = cpcap_battery_latest(ddata); 659 572 previous = cpcap_battery_previous(ddata); 573 + 574 + if (ddata->check_nvmem) 575 + cpcap_battery_detect_battery_type(ddata); 660 576 661 577 switch (psp) { 662 578 case POWER_SUPPLY_PROP_PRESENT: ··· 1072 982 return error; 1073 983 } 1074 984 1075 - /* 1076 - * Based on the values from Motorola mapphone Linux kernel. In the 1077 - * the Motorola mapphone Linux kernel tree the value for pm_cd_factor 1078 - * is passed to the kernel via device tree. If it turns out to be 1079 - * something device specific we can consider that too later. 1080 - * 1081 - * And looking at the battery full and shutdown values for the stock 1082 - * kernel on droid 4, full is 4351000 and software initiates shutdown 1083 - * at 3078000. The device will die around 2743000. 1084 - */ 1085 - static const struct cpcap_battery_config cpcap_battery_default_data = { 1086 - .cd_factor = 0x3cc, 1087 - .info.technology = POWER_SUPPLY_TECHNOLOGY_LION, 1088 - .info.voltage_max_design = 4351000, 1089 - .info.voltage_min_design = 3100000, 1090 - .info.charge_full_design = 1740000, 1091 - .bat.constant_charge_voltage_max_uv = 4200000, 1092 - }; 1093 - 1094 985 #ifdef CONFIG_OF 1095 986 static const struct of_device_id cpcap_battery_id_table[] = { 1096 987 { 1097 988 .compatible = "motorola,cpcap-battery", 1098 - .data = &cpcap_battery_default_data, 1099 989 }, 1100 990 {}, 1101 991 }; ··· 1098 1028 struct cpcap_battery_ddata *ddata; 1099 1029 struct power_supply_config psy_cfg = {}; 1100 1030 int error; 1101 - const struct cpcap_battery_config *cfg; 1102 - 1103 - cfg = device_get_match_data(&pdev->dev); 1104 - if (!cfg) 1105 - return -ENODEV; 1106 1031 1107 1032 ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL); 1108 1033 if (!ddata) 1109 1034 return -ENOMEM; 1110 1035 1036 + cpcap_battery_detect_battery_type(ddata); 1037 + 1111 1038 INIT_LIST_HEAD(&ddata->irq_list); 1112 1039 ddata->dev = &pdev->dev; 1113 - memcpy(&ddata->config, cfg, sizeof(ddata->config)); 1114 1040 1115 1041 ddata->reg = dev_get_regmap(ddata->dev->parent, NULL); 1116 1042 if (!ddata->reg)
+7 -30
drivers/power/supply/cros_peripheral_charger.c
··· 14 14 #include <linux/slab.h> 15 15 #include <linux/stringify.h> 16 16 #include <linux/types.h> 17 + #include <asm/unaligned.h> 17 18 18 19 #define DRV_NAME "cros-ec-pchg" 19 20 #define PCHG_DIR_PREFIX "peripheral" ··· 238 237 return NOTIFY_OK; 239 238 } 240 239 241 - static u32 cros_get_device_event(const struct charger_data *charger) 242 - { 243 - struct ec_params_device_event req; 244 - struct ec_response_device_event rsp; 245 - struct device *dev = charger->dev; 246 - int ret; 247 - 248 - req.param = EC_DEVICE_EVENT_PARAM_GET_CURRENT_EVENTS; 249 - ret = cros_pchg_ec_command(charger, 0, EC_CMD_DEVICE_EVENT, 250 - &req, sizeof(req), &rsp, sizeof(rsp)); 251 - if (ret < 0) { 252 - dev_warn(dev, "Unable to get device events (err:%d)\n", ret); 253 - return 0; 254 - } 255 - 256 - return rsp.event_mask; 257 - } 258 - 259 240 static int cros_ec_notify(struct notifier_block *nb, 260 241 unsigned long queued_during_suspend, 261 242 void *data) 262 243 { 263 - struct cros_ec_device *ec_dev = (struct cros_ec_device *)data; 264 - u32 host_event = cros_ec_get_host_event(ec_dev); 244 + struct cros_ec_device *ec_dev = data; 265 245 struct charger_data *charger = 266 246 container_of(nb, struct charger_data, notifier); 267 - u32 device_event_mask; 247 + u32 host_event; 268 248 269 - if (!host_event) 249 + if (ec_dev->event_data.event_type != EC_MKBP_EVENT_PCHG || 250 + ec_dev->event_size != sizeof(host_event)) 270 251 return NOTIFY_DONE; 271 252 272 - if (!(host_event & EC_HOST_EVENT_MASK(EC_HOST_EVENT_DEVICE))) 273 - return NOTIFY_DONE; 253 + host_event = get_unaligned_le32(&ec_dev->event_data.data.host_event); 274 254 275 - /* 276 - * todo: Retrieve device event mask in common place 277 - * (e.g. cros_ec_proto.c). 278 - */ 279 - device_event_mask = cros_get_device_event(charger); 280 - if (!(device_event_mask & EC_DEVICE_EVENT_MASK(EC_DEVICE_EVENT_WLC))) 255 + if (!(host_event & EC_MKBP_PCHG_DEVICE_EVENT)) 281 256 return NOTIFY_DONE; 282 257 283 258 return cros_pchg_event(charger, host_event);
+1 -1
drivers/power/supply/cros_usbpd-charger.c
··· 104 104 struct cros_ec_command *msg; 105 105 int ret; 106 106 107 - msg = kzalloc(sizeof(*msg) + max(outsize, insize), GFP_KERNEL); 107 + msg = kzalloc(struct_size(msg, data, max(outsize, insize)), GFP_KERNEL); 108 108 if (!msg) 109 109 return -ENOMEM; 110 110
+11 -24
drivers/power/supply/da9150-fg.c
··· 20 20 #include <asm/div64.h> 21 21 #include <linux/mfd/da9150/core.h> 22 22 #include <linux/mfd/da9150/registers.h> 23 + #include <linux/devm-helpers.h> 23 24 24 25 /* Core2Wire */ 25 26 #define DA9150_QIF_READ (0x0 << 7) ··· 507 506 * work for reporting data updates. 508 507 */ 509 508 if (fg->interval) { 510 - INIT_DELAYED_WORK(&fg->work, da9150_fg_work); 509 + ret = devm_delayed_work_autocancel(dev, &fg->work, 510 + da9150_fg_work); 511 + if (ret) { 512 + dev_err(dev, "Failed to init work\n"); 513 + return ret; 514 + } 515 + 511 516 schedule_delayed_work(&fg->work, 512 517 msecs_to_jiffies(fg->interval)); 513 518 } 514 519 515 520 /* Register IRQ */ 516 521 irq = platform_get_irq_byname(pdev, "FG"); 517 - if (irq < 0) { 518 - dev_err(dev, "Failed to get IRQ FG: %d\n", irq); 519 - ret = irq; 520 - goto irq_fail; 521 - } 522 + if (irq < 0) 523 + return irq; 522 524 523 525 ret = devm_request_threaded_irq(dev, irq, NULL, da9150_fg_irq, 524 526 IRQF_ONESHOT, "FG", fg); 525 527 if (ret) { 526 528 dev_err(dev, "Failed to request IRQ %d: %d\n", irq, ret); 527 - goto irq_fail; 529 + return ret; 528 530 } 529 - 530 - return 0; 531 - 532 - irq_fail: 533 - if (fg->interval) 534 - cancel_delayed_work(&fg->work); 535 - 536 - return ret; 537 - } 538 - 539 - static int da9150_fg_remove(struct platform_device *pdev) 540 - { 541 - struct da9150_fg *fg = platform_get_drvdata(pdev); 542 - 543 - if (fg->interval) 544 - cancel_delayed_work(&fg->work); 545 531 546 532 return 0; 547 533 } ··· 552 564 .name = "da9150-fuel-gauge", 553 565 }, 554 566 .probe = da9150_fg_probe, 555 - .remove = da9150_fg_remove, 556 567 .resume = da9150_fg_resume, 557 568 }; 558 569
+638
drivers/power/supply/ip5xxx_power.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // 3 + // Copyright (C) 2021 Samuel Holland <samuel@sholland.org> 4 + 5 + #include <linux/i2c.h> 6 + #include <linux/module.h> 7 + #include <linux/power_supply.h> 8 + #include <linux/regmap.h> 9 + 10 + #define IP5XXX_SYS_CTL0 0x01 11 + #define IP5XXX_SYS_CTL0_WLED_DET_EN BIT(4) 12 + #define IP5XXX_SYS_CTL0_WLED_EN BIT(3) 13 + #define IP5XXX_SYS_CTL0_BOOST_EN BIT(2) 14 + #define IP5XXX_SYS_CTL0_CHARGER_EN BIT(1) 15 + #define IP5XXX_SYS_CTL1 0x02 16 + #define IP5XXX_SYS_CTL1_LIGHT_SHDN_EN BIT(1) 17 + #define IP5XXX_SYS_CTL1_LOAD_PWRUP_EN BIT(0) 18 + #define IP5XXX_SYS_CTL2 0x0c 19 + #define IP5XXX_SYS_CTL2_LIGHT_SHDN_TH GENMASK(7, 3) 20 + #define IP5XXX_SYS_CTL3 0x03 21 + #define IP5XXX_SYS_CTL3_LONG_PRESS_TIME_SEL GENMASK(7, 6) 22 + #define IP5XXX_SYS_CTL3_BTN_SHDN_EN BIT(5) 23 + #define IP5XXX_SYS_CTL4 0x04 24 + #define IP5XXX_SYS_CTL4_SHDN_TIME_SEL GENMASK(7, 6) 25 + #define IP5XXX_SYS_CTL4_VIN_PULLOUT_BOOST_EN BIT(5) 26 + #define IP5XXX_SYS_CTL5 0x07 27 + #define IP5XXX_SYS_CTL5_NTC_DIS BIT(6) 28 + #define IP5XXX_SYS_CTL5_WLED_MODE_SEL BIT(1) 29 + #define IP5XXX_SYS_CTL5_BTN_SHDN_SEL BIT(0) 30 + #define IP5XXX_CHG_CTL1 0x22 31 + #define IP5XXX_CHG_CTL1_BOOST_UVP_SEL GENMASK(3, 2) 32 + #define IP5XXX_CHG_CTL2 0x24 33 + #define IP5XXX_CHG_CTL2_BAT_TYPE_SEL GENMASK(6, 5) 34 + #define IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_2V (0x0 << 5) 35 + #define IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_3V (0x1 << 5) 36 + #define IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_35V (0x2 << 5) 37 + #define IP5XXX_CHG_CTL2_CONST_VOLT_SEL GENMASK(2, 1) 38 + #define IP5XXX_CHG_CTL4 0x26 39 + #define IP5XXX_CHG_CTL4_BAT_TYPE_SEL_EN BIT(6) 40 + #define IP5XXX_CHG_CTL4A 0x25 41 + #define IP5XXX_CHG_CTL4A_CONST_CUR_SEL GENMASK(4, 0) 42 + #define IP5XXX_MFP_CTL0 0x51 43 + #define IP5XXX_MFP_CTL1 0x52 44 + #define IP5XXX_GPIO_CTL2 0x53 45 + #define IP5XXX_GPIO_CTL2A 0x54 46 + #define IP5XXX_GPIO_CTL3 0x55 47 + #define IP5XXX_READ0 0x71 48 + #define IP5XXX_READ0_CHG_STAT GENMASK(7, 5) 49 + #define IP5XXX_READ0_CHG_STAT_IDLE (0x0 << 5) 50 + #define IP5XXX_READ0_CHG_STAT_TRICKLE (0x1 << 5) 51 + #define IP5XXX_READ0_CHG_STAT_CONST_VOLT (0x2 << 5) 52 + #define IP5XXX_READ0_CHG_STAT_CONST_CUR (0x3 << 5) 53 + #define IP5XXX_READ0_CHG_STAT_CONST_VOLT_STOP (0x4 << 5) 54 + #define IP5XXX_READ0_CHG_STAT_FULL (0x5 << 5) 55 + #define IP5XXX_READ0_CHG_STAT_TIMEOUT (0x6 << 5) 56 + #define IP5XXX_READ0_CHG_OP BIT(4) 57 + #define IP5XXX_READ0_CHG_END BIT(3) 58 + #define IP5XXX_READ0_CONST_VOLT_TIMEOUT BIT(2) 59 + #define IP5XXX_READ0_CHG_TIMEOUT BIT(1) 60 + #define IP5XXX_READ0_TRICKLE_TIMEOUT BIT(0) 61 + #define IP5XXX_READ0_TIMEOUT GENMASK(2, 0) 62 + #define IP5XXX_READ1 0x72 63 + #define IP5XXX_READ1_WLED_PRESENT BIT(7) 64 + #define IP5XXX_READ1_LIGHT_LOAD BIT(6) 65 + #define IP5XXX_READ1_VIN_OVERVOLT BIT(5) 66 + #define IP5XXX_READ2 0x77 67 + #define IP5XXX_READ2_BTN_PRESS BIT(3) 68 + #define IP5XXX_READ2_BTN_LONG_PRESS BIT(1) 69 + #define IP5XXX_READ2_BTN_SHORT_PRESS BIT(0) 70 + #define IP5XXX_BATVADC_DAT0 0xa2 71 + #define IP5XXX_BATVADC_DAT1 0xa3 72 + #define IP5XXX_BATIADC_DAT0 0xa4 73 + #define IP5XXX_BATIADC_DAT1 0xa5 74 + #define IP5XXX_BATOCV_DAT0 0xa8 75 + #define IP5XXX_BATOCV_DAT1 0xa9 76 + 77 + struct ip5xxx { 78 + struct regmap *regmap; 79 + bool initialized; 80 + }; 81 + 82 + /* 83 + * The IP5xxx charger only responds on I2C when it is "awake". The charger is 84 + * generally only awake when VIN is powered or when its boost converter is 85 + * enabled. Going into shutdown resets all register values. To handle this: 86 + * 1) When any bus error occurs, assume the charger has gone into shutdown. 87 + * 2) Attempt the initialization sequence on each subsequent register access 88 + * until it succeeds. 89 + */ 90 + static int ip5xxx_read(struct ip5xxx *ip5xxx, unsigned int reg, 91 + unsigned int *val) 92 + { 93 + int ret; 94 + 95 + ret = regmap_read(ip5xxx->regmap, reg, val); 96 + if (ret) 97 + ip5xxx->initialized = false; 98 + 99 + return ret; 100 + } 101 + 102 + static int ip5xxx_update_bits(struct ip5xxx *ip5xxx, unsigned int reg, 103 + unsigned int mask, unsigned int val) 104 + { 105 + int ret; 106 + 107 + ret = regmap_update_bits(ip5xxx->regmap, reg, mask, val); 108 + if (ret) 109 + ip5xxx->initialized = false; 110 + 111 + return ret; 112 + } 113 + 114 + static int ip5xxx_initialize(struct power_supply *psy) 115 + { 116 + struct ip5xxx *ip5xxx = power_supply_get_drvdata(psy); 117 + int ret; 118 + 119 + if (ip5xxx->initialized) 120 + return 0; 121 + 122 + /* 123 + * Disable shutdown under light load. 124 + * Enable power on when under load. 125 + */ 126 + ret = ip5xxx_update_bits(ip5xxx, IP5XXX_SYS_CTL1, 127 + IP5XXX_SYS_CTL1_LIGHT_SHDN_EN | 128 + IP5XXX_SYS_CTL1_LOAD_PWRUP_EN, 129 + IP5XXX_SYS_CTL1_LOAD_PWRUP_EN); 130 + if (ret) 131 + return ret; 132 + 133 + /* 134 + * Enable shutdown after a long button press (as configured below). 135 + */ 136 + ret = ip5xxx_update_bits(ip5xxx, IP5XXX_SYS_CTL3, 137 + IP5XXX_SYS_CTL3_BTN_SHDN_EN, 138 + IP5XXX_SYS_CTL3_BTN_SHDN_EN); 139 + if (ret) 140 + return ret; 141 + 142 + /* 143 + * Power on automatically when VIN is removed. 144 + */ 145 + ret = ip5xxx_update_bits(ip5xxx, IP5XXX_SYS_CTL4, 146 + IP5XXX_SYS_CTL4_VIN_PULLOUT_BOOST_EN, 147 + IP5XXX_SYS_CTL4_VIN_PULLOUT_BOOST_EN); 148 + if (ret) 149 + return ret; 150 + 151 + /* 152 + * Enable the NTC. 153 + * Configure the button for two presses => LED, long press => shutdown. 154 + */ 155 + ret = ip5xxx_update_bits(ip5xxx, IP5XXX_SYS_CTL5, 156 + IP5XXX_SYS_CTL5_NTC_DIS | 157 + IP5XXX_SYS_CTL5_WLED_MODE_SEL | 158 + IP5XXX_SYS_CTL5_BTN_SHDN_SEL, 159 + IP5XXX_SYS_CTL5_WLED_MODE_SEL | 160 + IP5XXX_SYS_CTL5_BTN_SHDN_SEL); 161 + if (ret) 162 + return ret; 163 + 164 + ip5xxx->initialized = true; 165 + dev_dbg(psy->dev.parent, "Initialized after power on\n"); 166 + 167 + return 0; 168 + } 169 + 170 + static const enum power_supply_property ip5xxx_battery_properties[] = { 171 + POWER_SUPPLY_PROP_STATUS, 172 + POWER_SUPPLY_PROP_CHARGE_TYPE, 173 + POWER_SUPPLY_PROP_HEALTH, 174 + POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, 175 + POWER_SUPPLY_PROP_VOLTAGE_NOW, 176 + POWER_SUPPLY_PROP_VOLTAGE_OCV, 177 + POWER_SUPPLY_PROP_CURRENT_NOW, 178 + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, 179 + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, 180 + POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, 181 + POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX, 182 + }; 183 + 184 + static int ip5xxx_battery_get_status(struct ip5xxx *ip5xxx, int *val) 185 + { 186 + unsigned int rval; 187 + int ret; 188 + 189 + ret = ip5xxx_read(ip5xxx, IP5XXX_READ0, &rval); 190 + if (ret) 191 + return ret; 192 + 193 + switch (rval & IP5XXX_READ0_CHG_STAT) { 194 + case IP5XXX_READ0_CHG_STAT_IDLE: 195 + *val = POWER_SUPPLY_STATUS_DISCHARGING; 196 + break; 197 + case IP5XXX_READ0_CHG_STAT_TRICKLE: 198 + case IP5XXX_READ0_CHG_STAT_CONST_CUR: 199 + case IP5XXX_READ0_CHG_STAT_CONST_VOLT: 200 + *val = POWER_SUPPLY_STATUS_CHARGING; 201 + break; 202 + case IP5XXX_READ0_CHG_STAT_CONST_VOLT_STOP: 203 + case IP5XXX_READ0_CHG_STAT_FULL: 204 + *val = POWER_SUPPLY_STATUS_FULL; 205 + break; 206 + case IP5XXX_READ0_CHG_STAT_TIMEOUT: 207 + *val = POWER_SUPPLY_STATUS_NOT_CHARGING; 208 + break; 209 + default: 210 + return -EINVAL; 211 + } 212 + 213 + return 0; 214 + } 215 + 216 + static int ip5xxx_battery_get_charge_type(struct ip5xxx *ip5xxx, int *val) 217 + { 218 + unsigned int rval; 219 + int ret; 220 + 221 + ret = ip5xxx_read(ip5xxx, IP5XXX_READ0, &rval); 222 + if (ret) 223 + return ret; 224 + 225 + switch (rval & IP5XXX_READ0_CHG_STAT) { 226 + case IP5XXX_READ0_CHG_STAT_IDLE: 227 + case IP5XXX_READ0_CHG_STAT_CONST_VOLT_STOP: 228 + case IP5XXX_READ0_CHG_STAT_FULL: 229 + case IP5XXX_READ0_CHG_STAT_TIMEOUT: 230 + *val = POWER_SUPPLY_CHARGE_TYPE_NONE; 231 + break; 232 + case IP5XXX_READ0_CHG_STAT_TRICKLE: 233 + *val = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; 234 + break; 235 + case IP5XXX_READ0_CHG_STAT_CONST_CUR: 236 + case IP5XXX_READ0_CHG_STAT_CONST_VOLT: 237 + *val = POWER_SUPPLY_CHARGE_TYPE_STANDARD; 238 + break; 239 + default: 240 + return -EINVAL; 241 + } 242 + 243 + return 0; 244 + } 245 + 246 + static int ip5xxx_battery_get_health(struct ip5xxx *ip5xxx, int *val) 247 + { 248 + unsigned int rval; 249 + int ret; 250 + 251 + ret = ip5xxx_read(ip5xxx, IP5XXX_READ0, &rval); 252 + if (ret) 253 + return ret; 254 + 255 + if (rval & IP5XXX_READ0_TIMEOUT) 256 + *val = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE; 257 + else 258 + *val = POWER_SUPPLY_HEALTH_GOOD; 259 + 260 + return 0; 261 + } 262 + 263 + static int ip5xxx_battery_get_voltage_max(struct ip5xxx *ip5xxx, int *val) 264 + { 265 + unsigned int rval; 266 + int ret; 267 + 268 + ret = ip5xxx_read(ip5xxx, IP5XXX_CHG_CTL2, &rval); 269 + if (ret) 270 + return ret; 271 + 272 + /* 273 + * It is not clear what this will return if 274 + * IP5XXX_CHG_CTL4_BAT_TYPE_SEL_EN is not set... 275 + */ 276 + switch (rval & IP5XXX_CHG_CTL2_BAT_TYPE_SEL) { 277 + case IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_2V: 278 + *val = 4200000; 279 + break; 280 + case IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_3V: 281 + *val = 4300000; 282 + break; 283 + case IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_35V: 284 + *val = 4350000; 285 + break; 286 + default: 287 + return -EINVAL; 288 + } 289 + 290 + return 0; 291 + } 292 + 293 + static int ip5xxx_battery_read_adc(struct ip5xxx *ip5xxx, 294 + u8 lo_reg, u8 hi_reg, int *val) 295 + { 296 + unsigned int hi, lo; 297 + int ret; 298 + 299 + ret = ip5xxx_read(ip5xxx, lo_reg, &lo); 300 + if (ret) 301 + return ret; 302 + 303 + ret = ip5xxx_read(ip5xxx, hi_reg, &hi); 304 + if (ret) 305 + return ret; 306 + 307 + *val = sign_extend32(hi << 8 | lo, 13); 308 + 309 + return 0; 310 + } 311 + 312 + static int ip5xxx_battery_get_property(struct power_supply *psy, 313 + enum power_supply_property psp, 314 + union power_supply_propval *val) 315 + { 316 + struct ip5xxx *ip5xxx = power_supply_get_drvdata(psy); 317 + int raw, ret, vmax; 318 + unsigned int rval; 319 + 320 + ret = ip5xxx_initialize(psy); 321 + if (ret) 322 + return ret; 323 + 324 + switch (psp) { 325 + case POWER_SUPPLY_PROP_STATUS: 326 + return ip5xxx_battery_get_status(ip5xxx, &val->intval); 327 + 328 + case POWER_SUPPLY_PROP_CHARGE_TYPE: 329 + return ip5xxx_battery_get_charge_type(ip5xxx, &val->intval); 330 + 331 + case POWER_SUPPLY_PROP_HEALTH: 332 + return ip5xxx_battery_get_health(ip5xxx, &val->intval); 333 + 334 + case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: 335 + return ip5xxx_battery_get_voltage_max(ip5xxx, &val->intval); 336 + 337 + case POWER_SUPPLY_PROP_VOLTAGE_NOW: 338 + ret = ip5xxx_battery_read_adc(ip5xxx, IP5XXX_BATVADC_DAT0, 339 + IP5XXX_BATVADC_DAT1, &raw); 340 + 341 + val->intval = 2600000 + DIV_ROUND_CLOSEST(raw * 26855, 100); 342 + return 0; 343 + 344 + case POWER_SUPPLY_PROP_VOLTAGE_OCV: 345 + ret = ip5xxx_battery_read_adc(ip5xxx, IP5XXX_BATOCV_DAT0, 346 + IP5XXX_BATOCV_DAT1, &raw); 347 + 348 + val->intval = 2600000 + DIV_ROUND_CLOSEST(raw * 26855, 100); 349 + return 0; 350 + 351 + case POWER_SUPPLY_PROP_CURRENT_NOW: 352 + ret = ip5xxx_battery_read_adc(ip5xxx, IP5XXX_BATIADC_DAT0, 353 + IP5XXX_BATIADC_DAT1, &raw); 354 + 355 + val->intval = DIV_ROUND_CLOSEST(raw * 745985, 1000); 356 + return 0; 357 + 358 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: 359 + ret = ip5xxx_read(ip5xxx, IP5XXX_CHG_CTL4A, &rval); 360 + if (ret) 361 + return ret; 362 + 363 + rval &= IP5XXX_CHG_CTL4A_CONST_CUR_SEL; 364 + val->intval = 100000 * rval; 365 + return 0; 366 + 367 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: 368 + val->intval = 100000 * 0x1f; 369 + return 0; 370 + 371 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: 372 + ret = ip5xxx_battery_get_voltage_max(ip5xxx, &vmax); 373 + if (ret) 374 + return ret; 375 + 376 + ret = ip5xxx_read(ip5xxx, IP5XXX_CHG_CTL2, &rval); 377 + if (ret) 378 + return ret; 379 + 380 + rval &= IP5XXX_CHG_CTL2_CONST_VOLT_SEL; 381 + val->intval = vmax + 14000 * (rval >> 1); 382 + return 0; 383 + 384 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: 385 + ret = ip5xxx_battery_get_voltage_max(ip5xxx, &vmax); 386 + if (ret) 387 + return ret; 388 + 389 + val->intval = vmax + 14000 * 3; 390 + return 0; 391 + 392 + default: 393 + return -EINVAL; 394 + } 395 + } 396 + 397 + static int ip5xxx_battery_set_voltage_max(struct ip5xxx *ip5xxx, int val) 398 + { 399 + unsigned int rval; 400 + int ret; 401 + 402 + switch (val) { 403 + case 4200000: 404 + rval = IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_2V; 405 + break; 406 + case 4300000: 407 + rval = IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_3V; 408 + break; 409 + case 4350000: 410 + rval = IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_35V; 411 + break; 412 + default: 413 + return -EINVAL; 414 + } 415 + 416 + ret = ip5xxx_update_bits(ip5xxx, IP5XXX_CHG_CTL2, 417 + IP5XXX_CHG_CTL2_BAT_TYPE_SEL, rval); 418 + if (ret) 419 + return ret; 420 + 421 + ret = ip5xxx_update_bits(ip5xxx, IP5XXX_CHG_CTL4, 422 + IP5XXX_CHG_CTL4_BAT_TYPE_SEL_EN, 423 + IP5XXX_CHG_CTL4_BAT_TYPE_SEL_EN); 424 + if (ret) 425 + return ret; 426 + 427 + return 0; 428 + } 429 + 430 + static int ip5xxx_battery_set_property(struct power_supply *psy, 431 + enum power_supply_property psp, 432 + const union power_supply_propval *val) 433 + { 434 + struct ip5xxx *ip5xxx = power_supply_get_drvdata(psy); 435 + unsigned int rval; 436 + int ret, vmax; 437 + 438 + ret = ip5xxx_initialize(psy); 439 + if (ret) 440 + return ret; 441 + 442 + switch (psp) { 443 + case POWER_SUPPLY_PROP_STATUS: 444 + switch (val->intval) { 445 + case POWER_SUPPLY_STATUS_CHARGING: 446 + rval = IP5XXX_SYS_CTL0_CHARGER_EN; 447 + break; 448 + case POWER_SUPPLY_STATUS_DISCHARGING: 449 + case POWER_SUPPLY_STATUS_NOT_CHARGING: 450 + rval = 0; 451 + break; 452 + default: 453 + return -EINVAL; 454 + } 455 + return ip5xxx_update_bits(ip5xxx, IP5XXX_SYS_CTL0, 456 + IP5XXX_SYS_CTL0_CHARGER_EN, rval); 457 + 458 + case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: 459 + return ip5xxx_battery_set_voltage_max(ip5xxx, val->intval); 460 + 461 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: 462 + rval = val->intval / 100000; 463 + return ip5xxx_update_bits(ip5xxx, IP5XXX_CHG_CTL4A, 464 + IP5XXX_CHG_CTL4A_CONST_CUR_SEL, rval); 465 + 466 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: 467 + ret = ip5xxx_battery_get_voltage_max(ip5xxx, &vmax); 468 + if (ret) 469 + return ret; 470 + 471 + rval = ((val->intval - vmax) / 14000) << 1; 472 + return ip5xxx_update_bits(ip5xxx, IP5XXX_CHG_CTL2, 473 + IP5XXX_CHG_CTL2_CONST_VOLT_SEL, rval); 474 + 475 + default: 476 + return -EINVAL; 477 + } 478 + } 479 + 480 + static int ip5xxx_battery_property_is_writeable(struct power_supply *psy, 481 + enum power_supply_property psp) 482 + { 483 + return psp == POWER_SUPPLY_PROP_STATUS || 484 + psp == POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN || 485 + psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT || 486 + psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE; 487 + } 488 + 489 + static const struct power_supply_desc ip5xxx_battery_desc = { 490 + .name = "ip5xxx-battery", 491 + .type = POWER_SUPPLY_TYPE_BATTERY, 492 + .properties = ip5xxx_battery_properties, 493 + .num_properties = ARRAY_SIZE(ip5xxx_battery_properties), 494 + .get_property = ip5xxx_battery_get_property, 495 + .set_property = ip5xxx_battery_set_property, 496 + .property_is_writeable = ip5xxx_battery_property_is_writeable, 497 + }; 498 + 499 + static const enum power_supply_property ip5xxx_boost_properties[] = { 500 + POWER_SUPPLY_PROP_ONLINE, 501 + POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, 502 + }; 503 + 504 + static int ip5xxx_boost_get_property(struct power_supply *psy, 505 + enum power_supply_property psp, 506 + union power_supply_propval *val) 507 + { 508 + struct ip5xxx *ip5xxx = power_supply_get_drvdata(psy); 509 + unsigned int rval; 510 + int ret; 511 + 512 + ret = ip5xxx_initialize(psy); 513 + if (ret) 514 + return ret; 515 + 516 + switch (psp) { 517 + case POWER_SUPPLY_PROP_ONLINE: 518 + ret = ip5xxx_read(ip5xxx, IP5XXX_SYS_CTL0, &rval); 519 + if (ret) 520 + return ret; 521 + 522 + val->intval = !!(rval & IP5XXX_SYS_CTL0_BOOST_EN); 523 + return 0; 524 + 525 + case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: 526 + ret = ip5xxx_read(ip5xxx, IP5XXX_CHG_CTL1, &rval); 527 + if (ret) 528 + return ret; 529 + 530 + rval &= IP5XXX_CHG_CTL1_BOOST_UVP_SEL; 531 + val->intval = 4530000 + 100000 * (rval >> 2); 532 + return 0; 533 + 534 + default: 535 + return -EINVAL; 536 + } 537 + } 538 + 539 + static int ip5xxx_boost_set_property(struct power_supply *psy, 540 + enum power_supply_property psp, 541 + const union power_supply_propval *val) 542 + { 543 + struct ip5xxx *ip5xxx = power_supply_get_drvdata(psy); 544 + unsigned int rval; 545 + int ret; 546 + 547 + ret = ip5xxx_initialize(psy); 548 + if (ret) 549 + return ret; 550 + 551 + switch (psp) { 552 + case POWER_SUPPLY_PROP_ONLINE: 553 + rval = val->intval ? IP5XXX_SYS_CTL0_BOOST_EN : 0; 554 + return ip5xxx_update_bits(ip5xxx, IP5XXX_SYS_CTL0, 555 + IP5XXX_SYS_CTL0_BOOST_EN, rval); 556 + 557 + case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: 558 + rval = ((val->intval - 4530000) / 100000) << 2; 559 + return ip5xxx_update_bits(ip5xxx, IP5XXX_CHG_CTL1, 560 + IP5XXX_CHG_CTL1_BOOST_UVP_SEL, rval); 561 + 562 + default: 563 + return -EINVAL; 564 + } 565 + } 566 + 567 + static int ip5xxx_boost_property_is_writeable(struct power_supply *psy, 568 + enum power_supply_property psp) 569 + { 570 + return true; 571 + } 572 + 573 + static const struct power_supply_desc ip5xxx_boost_desc = { 574 + .name = "ip5xxx-boost", 575 + .type = POWER_SUPPLY_TYPE_USB, 576 + .properties = ip5xxx_boost_properties, 577 + .num_properties = ARRAY_SIZE(ip5xxx_boost_properties), 578 + .get_property = ip5xxx_boost_get_property, 579 + .set_property = ip5xxx_boost_set_property, 580 + .property_is_writeable = ip5xxx_boost_property_is_writeable, 581 + }; 582 + 583 + static const struct regmap_config ip5xxx_regmap_config = { 584 + .reg_bits = 8, 585 + .val_bits = 8, 586 + .max_register = IP5XXX_BATOCV_DAT1, 587 + }; 588 + 589 + static int ip5xxx_power_probe(struct i2c_client *client) 590 + { 591 + struct power_supply_config psy_cfg = {}; 592 + struct device *dev = &client->dev; 593 + struct power_supply *psy; 594 + struct ip5xxx *ip5xxx; 595 + 596 + ip5xxx = devm_kzalloc(dev, sizeof(*ip5xxx), GFP_KERNEL); 597 + if (!ip5xxx) 598 + return -ENOMEM; 599 + 600 + ip5xxx->regmap = devm_regmap_init_i2c(client, &ip5xxx_regmap_config); 601 + if (IS_ERR(ip5xxx->regmap)) 602 + return PTR_ERR(ip5xxx->regmap); 603 + 604 + psy_cfg.of_node = dev->of_node; 605 + psy_cfg.drv_data = ip5xxx; 606 + 607 + psy = devm_power_supply_register(dev, &ip5xxx_battery_desc, &psy_cfg); 608 + if (IS_ERR(psy)) 609 + return PTR_ERR(psy); 610 + 611 + psy = devm_power_supply_register(dev, &ip5xxx_boost_desc, &psy_cfg); 612 + if (IS_ERR(psy)) 613 + return PTR_ERR(psy); 614 + 615 + return 0; 616 + } 617 + 618 + static const struct of_device_id ip5xxx_power_of_match[] = { 619 + { .compatible = "injoinic,ip5108" }, 620 + { .compatible = "injoinic,ip5109" }, 621 + { .compatible = "injoinic,ip5207" }, 622 + { .compatible = "injoinic,ip5209" }, 623 + { } 624 + }; 625 + MODULE_DEVICE_TABLE(of, ip5xxx_power_of_match); 626 + 627 + static struct i2c_driver ip5xxx_power_driver = { 628 + .probe_new = ip5xxx_power_probe, 629 + .driver = { 630 + .name = "ip5xxx-power", 631 + .of_match_table = ip5xxx_power_of_match, 632 + } 633 + }; 634 + module_i2c_driver(ip5xxx_power_driver); 635 + 636 + MODULE_AUTHOR("Samuel Holland <samuel@sholland.org>"); 637 + MODULE_DESCRIPTION("Injoinic IP5xxx power bank IC driver"); 638 + MODULE_LICENSE("GPL");
+24 -37
drivers/power/supply/ltc2941-battery-gauge.c
··· 112 112 113 113 ret = i2c_transfer(client->adapter, &msgs[0], 2); 114 114 if (ret < 0) { 115 - dev_err(&client->dev, "ltc2941 read_reg failed!\n"); 115 + dev_err(&client->dev, "ltc2941 read_reg(0x%x[%d]) failed: %pe\n", 116 + reg, num_regs, ERR_PTR(ret)); 116 117 return ret; 117 118 } 118 119 ··· 131 130 132 131 ret = i2c_smbus_write_i2c_block_data(client, reg_start, num_regs, buf); 133 132 if (ret < 0) { 134 - dev_err(&client->dev, "ltc2941 write_reg failed!\n"); 133 + dev_err(&client->dev, "ltc2941 write_reg(0x%x[%d]) failed: %pe\n", 134 + reg, num_regs, ERR_PTR(ret)); 135 135 return ret; 136 136 } 137 137 ··· 150 148 151 149 /* Read status and control registers */ 152 150 ret = ltc294x_read_regs(info->client, LTC294X_REG_CONTROL, &value, 1); 153 - if (ret < 0) { 154 - dev_err(&info->client->dev, 155 - "Could not read registers from device\n"); 156 - goto error_exit; 157 - } 151 + if (ret < 0) 152 + return ret; 158 153 159 154 control = LTC294X_REG_CONTROL_PRESCALER_SET(prescaler_exp) | 160 155 LTC294X_REG_CONTROL_ALCC_CONFIG_DISABLED; ··· 171 172 if (value != control) { 172 173 ret = ltc294x_write_regs(info->client, 173 174 LTC294X_REG_CONTROL, &control, 1); 174 - if (ret < 0) { 175 - dev_err(&info->client->dev, 176 - "Could not write register\n"); 177 - goto error_exit; 178 - } 175 + if (ret < 0) 176 + return ret; 179 177 } 180 178 181 179 return 0; 182 - 183 - error_exit: 184 - return ret; 185 180 } 186 181 187 182 static int ltc294x_read_charge_register(const struct ltc294x_info *info, ··· 465 472 /* r_sense can be negative, when sense+ is connected to the battery 466 473 * instead of the sense-. This results in reversed measurements. */ 467 474 ret = of_property_read_u32(np, "lltc,resistor-sense", &r_sense); 468 - if (ret < 0) { 469 - dev_err(&client->dev, 475 + if (ret < 0) 476 + return dev_err_probe(&client->dev, ret, 470 477 "Could not find lltc,resistor-sense in devicetree\n"); 471 - return ret; 472 - } 473 478 info->r_sense = r_sense; 474 479 475 480 ret = of_property_read_u32(np, "lltc,prescaler-exponent", ··· 481 490 if (info->id == LTC2943_ID) { 482 491 if (prescaler_exp > LTC2943_MAX_PRESCALER_EXP) 483 492 prescaler_exp = LTC2943_MAX_PRESCALER_EXP; 484 - info->Qlsb = ((340 * 50000) / r_sense) / 485 - (4096 / (1 << (2*prescaler_exp))); 493 + info->Qlsb = ((340 * 50000) / r_sense) >> 494 + (12 - 2*prescaler_exp); 486 495 } else { 487 496 if (prescaler_exp > LTC2941_MAX_PRESCALER_EXP) 488 497 prescaler_exp = LTC2941_MAX_PRESCALER_EXP; 489 - info->Qlsb = ((85 * 50000) / r_sense) / 490 - (128 / (1 << prescaler_exp)); 498 + info->Qlsb = ((85 * 50000) / r_sense) >> 499 + (7 - prescaler_exp); 491 500 } 492 501 493 502 /* Read status register to check for LTC2942 */ 494 503 if (info->id == LTC2941_ID || info->id == LTC2942_ID) { 495 504 ret = ltc294x_read_regs(client, LTC294X_REG_STATUS, &status, 1); 496 - if (ret < 0) { 497 - dev_err(&client->dev, 505 + if (ret < 0) 506 + return dev_err_probe(&client->dev, ret, 498 507 "Could not read status register\n"); 499 - return ret; 500 - } 501 508 if (status & LTC2941_REG_STATUS_CHIP_ID) 502 509 info->id = LTC2941_ID; 503 510 else ··· 534 545 return ret; 535 546 536 547 ret = ltc294x_reset(info, prescaler_exp); 537 - if (ret < 0) { 538 - dev_err(&client->dev, "Communication with chip failed\n"); 539 - return ret; 540 - } 548 + if (ret < 0) 549 + return dev_err_probe(&client->dev, ret, 550 + "Communication with chip failed\n"); 541 551 542 552 info->supply = devm_power_supply_register(&client->dev, 543 553 &info->supply_desc, &psy_cfg); 544 - if (IS_ERR(info->supply)) { 545 - dev_err(&client->dev, "failed to register ltc2941\n"); 546 - return PTR_ERR(info->supply); 547 - } else { 548 - schedule_delayed_work(&info->work, LTC294X_WORK_DELAY * HZ); 549 - } 554 + if (IS_ERR(info->supply)) 555 + return dev_err_probe(&client->dev, PTR_ERR(info->supply), 556 + "failed to register ltc2941\n"); 557 + 558 + schedule_delayed_work(&info->work, LTC294X_WORK_DELAY * HZ); 550 559 551 560 return 0; 552 561 }
+4 -11
drivers/power/supply/max14656_charger_detector.c
··· 18 18 #include <linux/of_device.h> 19 19 #include <linux/workqueue.h> 20 20 #include <linux/power_supply.h> 21 + #include <linux/devm-helpers.h> 21 22 22 23 #define MAX14656_MANUFACTURER "Maxim Integrated" 23 24 #define MAX14656_NAME "max14656" ··· 234 233 POWER_SUPPLY_PROP_MANUFACTURER, 235 234 }; 236 235 237 - static void stop_irq_work(void *data) 238 - { 239 - struct max14656_chip *chip = data; 240 - 241 - cancel_delayed_work_sync(&chip->irq_work); 242 - } 243 - 244 - 245 236 static int max14656_probe(struct i2c_client *client, 246 237 const struct i2c_device_id *id) 247 238 { ··· 279 286 return -EINVAL; 280 287 } 281 288 282 - INIT_DELAYED_WORK(&chip->irq_work, max14656_irq_worker); 283 - ret = devm_add_action(dev, stop_irq_work, chip); 289 + ret = devm_delayed_work_autocancel(dev, &chip->irq_work, 290 + max14656_irq_worker); 284 291 if (ret) { 285 - dev_err(dev, "devm_add_action %d failed\n", ret); 292 + dev_err(dev, "devm_delayed_work_autocancel %d failed\n", ret); 286 293 return ret; 287 294 } 288 295
+3 -9
drivers/power/supply/max17042_battery.c
··· 9 9 // This driver is based on max17040_battery.c 10 10 11 11 #include <linux/acpi.h> 12 + #include <linux/devm-helpers.h> 12 13 #include <linux/init.h> 13 14 #include <linux/module.h> 14 15 #include <linux/slab.h> ··· 1031 1030 .num_properties = ARRAY_SIZE(max17042_battery_props) - 2, 1032 1031 }; 1033 1032 1034 - static void max17042_stop_work(void *data) 1035 - { 1036 - struct max17042_chip *chip = data; 1037 - 1038 - cancel_work_sync(&chip->work); 1039 - } 1040 - 1041 1033 static int max17042_probe(struct i2c_client *client, 1042 1034 const struct i2c_device_id *id) 1043 1035 { ··· 1136 1142 1137 1143 regmap_read(chip->regmap, MAX17042_STATUS, &val); 1138 1144 if (val & STATUS_POR_BIT) { 1139 - INIT_WORK(&chip->work, max17042_init_worker); 1140 - ret = devm_add_action(&client->dev, max17042_stop_work, chip); 1145 + ret = devm_work_autocancel(&client->dev, &chip->work, 1146 + max17042_init_worker); 1141 1147 if (ret) 1142 1148 return ret; 1143 1149 schedule_work(&chip->work);
+3 -9
drivers/power/supply/max8997_charger.c
··· 14 14 #include <linux/mfd/max8997.h> 15 15 #include <linux/mfd/max8997-private.h> 16 16 #include <linux/regulator/consumer.h> 17 + #include <linux/devm-helpers.h> 17 18 18 19 /* MAX8997_REG_STATUS4 */ 19 20 #define DCINOK_SHIFT 1 ··· 93 92 } 94 93 95 94 return 0; 96 - } 97 - 98 - static void max8997_battery_extcon_evt_stop_work(void *data) 99 - { 100 - struct charger_data *charger = data; 101 - 102 - cancel_work_sync(&charger->extcon_work); 103 95 } 104 96 105 97 static void max8997_battery_extcon_evt_worker(struct work_struct *work) ··· 249 255 } 250 256 251 257 if (!IS_ERR(charger->reg) && !IS_ERR_OR_NULL(charger->edev)) { 252 - INIT_WORK(&charger->extcon_work, max8997_battery_extcon_evt_worker); 253 - ret = devm_add_action(&pdev->dev, max8997_battery_extcon_evt_stop_work, charger); 258 + ret = devm_work_autocancel(&pdev->dev, &charger->extcon_work, 259 + max8997_battery_extcon_evt_worker); 254 260 if (ret) { 255 261 dev_err(&pdev->dev, "failed to add extcon evt stop action: %d\n", ret); 256 262 return ret;
+2 -4
drivers/power/supply/mp2629_charger.c
··· 580 580 charger->dev = dev; 581 581 platform_set_drvdata(pdev, charger); 582 582 583 - irq = platform_get_irq_optional(to_platform_device(dev->parent), 0); 584 - if (irq < 0) { 585 - dev_err(dev, "get irq fail: %d\n", irq); 583 + irq = platform_get_irq(to_platform_device(dev->parent), 0); 584 + if (irq < 0) 586 585 return irq; 587 - } 588 586 589 587 for (i = 0; i < MP2629_MAX_FIELD; i++) { 590 588 charger->regmap_fields[i] = devm_regmap_field_alloc(dev,
+215 -79
drivers/power/supply/power_supply_core.c
··· 23 23 #include <linux/thermal.h> 24 24 #include <linux/fixp-arith.h> 25 25 #include "power_supply.h" 26 + #include "samsung-sdi-battery.h" 26 27 27 28 /* exported for the APM Power driver, APM emulation */ 28 29 struct class *power_supply_class; ··· 284 283 if (!psy->dev.parent) 285 284 return 0; 286 285 287 - nval = device_property_read_string_array(psy->dev.parent, 288 - "supplied-from", NULL, 0); 286 + nval = device_property_string_array_count(psy->dev.parent, "supplied-from"); 289 287 if (nval <= 0) 290 288 return 0; 291 289 ··· 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 { ··· 571 568 { 572 569 struct power_supply_resistance_temp_table *resist_table; 573 570 struct power_supply_battery_info *info; 574 - struct device_node *battery_np; 571 + struct device_node *battery_np = NULL; 572 + struct fwnode_reference_args args; 573 + struct fwnode_handle *fwnode; 575 574 const char *value; 576 575 int err, len, index; 577 576 const __be32 *list; 577 + u32 min_max[2]; 578 + 579 + if (psy->of_node) { 580 + battery_np = of_parse_phandle(psy->of_node, "monitored-battery", 0); 581 + if (!battery_np) 582 + return -ENODEV; 583 + 584 + fwnode = fwnode_handle_get(of_fwnode_handle(battery_np)); 585 + } else { 586 + err = fwnode_property_get_reference_args( 587 + dev_fwnode(psy->dev.parent), 588 + "monitored-battery", NULL, 0, 0, &args); 589 + if (err) 590 + return err; 591 + 592 + fwnode = args.fwnode; 593 + } 594 + 595 + err = fwnode_property_read_string(fwnode, "compatible", &value); 596 + if (err) 597 + goto out_put_node; 598 + 599 + 600 + /* Try static batteries first */ 601 + err = samsung_sdi_battery_get_info(&psy->dev, value, &info); 602 + if (!err) 603 + goto out_ret_pointer; 604 + 605 + if (strcmp("simple-battery", value)) { 606 + err = -ENODEV; 607 + goto out_put_node; 608 + } 578 609 579 610 info = devm_kmalloc(&psy->dev, sizeof(*info), GFP_KERNEL); 580 - if (!info) 581 - return -ENOMEM; 611 + if (!info) { 612 + err = -ENOMEM; 613 + goto out_put_node; 614 + } 582 615 583 616 info->technology = POWER_SUPPLY_TECHNOLOGY_UNKNOWN; 584 617 info->energy_full_design_uwh = -EINVAL; ··· 629 590 info->precharge_voltage_max_uv = -EINVAL; 630 591 info->charge_restart_voltage_uv = -EINVAL; 631 592 info->overvoltage_limit_uv = -EINVAL; 593 + info->maintenance_charge = NULL; 594 + info->alert_low_temp_charge_current_ua = -EINVAL; 595 + info->alert_low_temp_charge_voltage_uv = -EINVAL; 596 + info->alert_high_temp_charge_current_ua = -EINVAL; 597 + info->alert_high_temp_charge_voltage_uv = -EINVAL; 632 598 info->temp_ambient_alert_min = INT_MIN; 633 599 info->temp_ambient_alert_max = INT_MAX; 634 600 info->temp_alert_min = INT_MIN; ··· 641 597 info->temp_min = INT_MIN; 642 598 info->temp_max = INT_MAX; 643 599 info->factory_internal_resistance_uohm = -EINVAL; 644 - info->resist_table = NULL; 600 + info->resist_table = NULL; 601 + info->bti_resistance_ohm = -EINVAL; 602 + info->bti_resistance_tolerance = -EINVAL; 645 603 646 604 for (index = 0; index < POWER_SUPPLY_OCV_TEMP_MAX; index++) { 647 605 info->ocv_table[index] = NULL; ··· 651 605 info->ocv_table_size[index] = -EINVAL; 652 606 } 653 607 654 - if (!psy->of_node) { 655 - dev_warn(&psy->dev, "%s currently only supports devicetree\n", 656 - __func__); 657 - return -ENXIO; 658 - } 659 - 660 - battery_np = of_parse_phandle(psy->of_node, "monitored-battery", 0); 661 - if (!battery_np) 662 - return -ENODEV; 663 - 664 - err = of_property_read_string(battery_np, "compatible", &value); 665 - if (err) 666 - goto out_put_node; 667 - 668 - if (strcmp("simple-battery", value)) { 669 - err = -ENODEV; 670 - goto out_put_node; 671 - } 672 - 673 608 /* The property and field names below must correspond to elements 674 609 * in enum power_supply_property. For reasoning, see 675 610 * Documentation/power/power_supply_class.rst. 676 611 */ 677 612 678 - if (!of_property_read_string(battery_np, "device-chemistry", &value)) { 613 + if (!fwnode_property_read_string(fwnode, "device-chemistry", &value)) { 679 614 if (!strcmp("nickel-cadmium", value)) 680 615 info->technology = POWER_SUPPLY_TECHNOLOGY_NiCd; 681 616 else if (!strcmp("nickel-metal-hydride", value)) ··· 674 647 dev_warn(&psy->dev, "%s unknown battery type\n", value); 675 648 } 676 649 677 - of_property_read_u32(battery_np, "energy-full-design-microwatt-hours", 650 + fwnode_property_read_u32(fwnode, "energy-full-design-microwatt-hours", 678 651 &info->energy_full_design_uwh); 679 - of_property_read_u32(battery_np, "charge-full-design-microamp-hours", 652 + fwnode_property_read_u32(fwnode, "charge-full-design-microamp-hours", 680 653 &info->charge_full_design_uah); 681 - of_property_read_u32(battery_np, "voltage-min-design-microvolt", 654 + fwnode_property_read_u32(fwnode, "voltage-min-design-microvolt", 682 655 &info->voltage_min_design_uv); 683 - of_property_read_u32(battery_np, "voltage-max-design-microvolt", 656 + fwnode_property_read_u32(fwnode, "voltage-max-design-microvolt", 684 657 &info->voltage_max_design_uv); 685 - of_property_read_u32(battery_np, "trickle-charge-current-microamp", 658 + fwnode_property_read_u32(fwnode, "trickle-charge-current-microamp", 686 659 &info->tricklecharge_current_ua); 687 - of_property_read_u32(battery_np, "precharge-current-microamp", 660 + fwnode_property_read_u32(fwnode, "precharge-current-microamp", 688 661 &info->precharge_current_ua); 689 - of_property_read_u32(battery_np, "precharge-upper-limit-microvolt", 662 + fwnode_property_read_u32(fwnode, "precharge-upper-limit-microvolt", 690 663 &info->precharge_voltage_max_uv); 691 - of_property_read_u32(battery_np, "charge-term-current-microamp", 664 + fwnode_property_read_u32(fwnode, "charge-term-current-microamp", 692 665 &info->charge_term_current_ua); 693 - of_property_read_u32(battery_np, "re-charge-voltage-microvolt", 666 + fwnode_property_read_u32(fwnode, "re-charge-voltage-microvolt", 694 667 &info->charge_restart_voltage_uv); 695 - of_property_read_u32(battery_np, "over-voltage-threshold-microvolt", 668 + fwnode_property_read_u32(fwnode, "over-voltage-threshold-microvolt", 696 669 &info->overvoltage_limit_uv); 697 - of_property_read_u32(battery_np, "constant-charge-current-max-microamp", 670 + fwnode_property_read_u32(fwnode, "constant-charge-current-max-microamp", 698 671 &info->constant_charge_current_max_ua); 699 - of_property_read_u32(battery_np, "constant-charge-voltage-max-microvolt", 672 + fwnode_property_read_u32(fwnode, "constant-charge-voltage-max-microvolt", 700 673 &info->constant_charge_voltage_max_uv); 701 - of_property_read_u32(battery_np, "factory-internal-resistance-micro-ohms", 674 + fwnode_property_read_u32(fwnode, "factory-internal-resistance-micro-ohms", 702 675 &info->factory_internal_resistance_uohm); 703 676 704 - of_property_read_u32_index(battery_np, "ambient-celsius", 705 - 0, &info->temp_ambient_alert_min); 706 - of_property_read_u32_index(battery_np, "ambient-celsius", 707 - 1, &info->temp_ambient_alert_max); 708 - of_property_read_u32_index(battery_np, "alert-celsius", 709 - 0, &info->temp_alert_min); 710 - of_property_read_u32_index(battery_np, "alert-celsius", 711 - 1, &info->temp_alert_max); 712 - of_property_read_u32_index(battery_np, "operating-range-celsius", 713 - 0, &info->temp_min); 714 - of_property_read_u32_index(battery_np, "operating-range-celsius", 715 - 1, &info->temp_max); 677 + if (!fwnode_property_read_u32_array(fwnode, "ambient-celsius", 678 + min_max, ARRAY_SIZE(min_max))) { 679 + info->temp_ambient_alert_min = min_max[0]; 680 + info->temp_ambient_alert_max = min_max[1]; 681 + } 682 + if (!fwnode_property_read_u32_array(fwnode, "alert-celsius", 683 + min_max, ARRAY_SIZE(min_max))) { 684 + info->temp_alert_min = min_max[0]; 685 + info->temp_alert_max = min_max[1]; 686 + } 687 + if (!fwnode_property_read_u32_array(fwnode, "operating-range-celsius", 688 + min_max, ARRAY_SIZE(min_max))) { 689 + info->temp_min = min_max[0]; 690 + info->temp_max = min_max[1]; 691 + } 692 + 693 + /* 694 + * The below code uses raw of-data parsing to parse 695 + * /schemas/types.yaml#/definitions/uint32-matrix 696 + * data, so for now this is only support with of. 697 + */ 698 + if (!battery_np) 699 + goto out_ret_pointer; 716 700 717 701 len = of_property_count_u32_elems(battery_np, "ocv-capacity-celsius"); 718 702 if (len < 0 && len != -EINVAL) { ··· 798 760 *info_out = info; 799 761 800 762 out_put_node: 763 + fwnode_handle_put(fwnode); 801 764 of_node_put(battery_np); 802 765 return err; 803 766 } ··· 823 784 824 785 /** 825 786 * power_supply_temp2resist_simple() - find the battery internal resistance 826 - * percent 787 + * percent from temperature 827 788 * @table: Pointer to battery resistance temperature table 828 789 * @table_len: The table length 829 790 * @temp: Current temperature ··· 859 820 temp); 860 821 } 861 822 EXPORT_SYMBOL_GPL(power_supply_temp2resist_simple); 823 + 824 + /** 825 + * power_supply_vbat2ri() - find the battery internal resistance 826 + * from the battery voltage 827 + * @info: The battery information container 828 + * @table: Pointer to battery resistance temperature table 829 + * @vbat_uv: The battery voltage in microvolt 830 + * @charging: If we are charging (true) or not (false) 831 + * 832 + * This helper function is used to look up battery internal resistance 833 + * according to current battery voltage. Depending on whether the battery 834 + * is currently charging or not, different resistance will be returned. 835 + * 836 + * Returns the internal resistance in microohm or negative error code. 837 + */ 838 + int power_supply_vbat2ri(struct power_supply_battery_info *info, 839 + int vbat_uv, bool charging) 840 + { 841 + struct power_supply_vbat_ri_table *vbat2ri; 842 + int table_len; 843 + int i, high, low; 844 + 845 + /* 846 + * If we are charging, and the battery supplies a separate table 847 + * for this state, we use that in order to compensate for the 848 + * charging voltage. Otherwise we use the main table. 849 + */ 850 + if (charging && info->vbat2ri_charging) { 851 + vbat2ri = info->vbat2ri_charging; 852 + table_len = info->vbat2ri_charging_size; 853 + } else { 854 + vbat2ri = info->vbat2ri_discharging; 855 + table_len = info->vbat2ri_discharging_size; 856 + } 857 + 858 + /* 859 + * If no tables are specified, or if we are above the highest voltage in 860 + * the voltage table, just return the factory specified internal resistance. 861 + */ 862 + if (!vbat2ri || (table_len <= 0) || (vbat_uv > vbat2ri[0].vbat_uv)) { 863 + if (charging && (info->factory_internal_resistance_charging_uohm > 0)) 864 + return info->factory_internal_resistance_charging_uohm; 865 + else 866 + return info->factory_internal_resistance_uohm; 867 + } 868 + 869 + /* Break loop at table_len - 1 because that is the highest index */ 870 + for (i = 0; i < table_len - 1; i++) 871 + if (vbat_uv > vbat2ri[i].vbat_uv) 872 + break; 873 + 874 + /* The library function will deal with high == low */ 875 + if ((i == 0) || (i == (table_len - 1))) 876 + high = i; 877 + else 878 + high = i - 1; 879 + low = i; 880 + 881 + return fixp_linear_interpolate(vbat2ri[low].vbat_uv, 882 + vbat2ri[low].ri_uohm, 883 + vbat2ri[high].vbat_uv, 884 + vbat2ri[high].ri_uohm, 885 + vbat_uv); 886 + } 887 + EXPORT_SYMBOL_GPL(power_supply_vbat2ri); 888 + 889 + struct power_supply_maintenance_charge_table * 890 + power_supply_get_maintenance_charging_setting(struct power_supply_battery_info *info, 891 + int index) 892 + { 893 + if (index >= info->maintenance_charge_size) 894 + return NULL; 895 + return &info->maintenance_charge[index]; 896 + } 897 + EXPORT_SYMBOL_GPL(power_supply_get_maintenance_charging_setting); 862 898 863 899 /** 864 900 * power_supply_ocv2cap_simple() - find the battery capacity ··· 1013 899 return power_supply_ocv2cap_simple(table, table_len, ocv); 1014 900 } 1015 901 EXPORT_SYMBOL_GPL(power_supply_batinfo_ocv2cap); 902 + 903 + bool power_supply_battery_bti_in_range(struct power_supply_battery_info *info, 904 + int resistance) 905 + { 906 + int low, high; 907 + 908 + /* Nothing like this can be checked */ 909 + if (info->bti_resistance_ohm <= 0) 910 + return false; 911 + 912 + /* This will be extremely strict and unlikely to work */ 913 + if (info->bti_resistance_tolerance <= 0) 914 + return (info->bti_resistance_ohm == resistance); 915 + 916 + low = info->bti_resistance_ohm - 917 + (info->bti_resistance_ohm * info->bti_resistance_tolerance) / 100; 918 + high = info->bti_resistance_ohm + 919 + (info->bti_resistance_ohm * info->bti_resistance_tolerance) / 100; 920 + 921 + return ((resistance >= low) && (resistance <= high)); 922 + } 923 + EXPORT_SYMBOL_GPL(power_supply_battery_bti_in_range); 1016 924 1017 925 int power_supply_get_property(struct power_supply *psy, 1018 926 enum power_supply_property psp,
+3 -12
drivers/power/supply/power_supply_hwmon.c
··· 324 324 .info = power_supply_hwmon_info, 325 325 }; 326 326 327 - static void power_supply_hwmon_bitmap_free(void *data) 328 - { 329 - bitmap_free(data); 330 - } 331 - 332 327 int power_supply_add_hwmon_sysfs(struct power_supply *psy) 333 328 { 334 329 const struct power_supply_desc *desc = psy->desc; ··· 344 349 } 345 350 346 351 psyhw->psy = psy; 347 - psyhw->props = bitmap_zalloc(POWER_SUPPLY_PROP_TIME_TO_FULL_AVG + 1, 348 - GFP_KERNEL); 352 + psyhw->props = devm_bitmap_zalloc(dev, 353 + POWER_SUPPLY_PROP_TIME_TO_FULL_AVG + 1, 354 + GFP_KERNEL); 349 355 if (!psyhw->props) { 350 356 ret = -ENOMEM; 351 357 goto error; 352 358 } 353 - 354 - ret = devm_add_action_or_reset(dev, power_supply_hwmon_bitmap_free, 355 - psyhw->props); 356 - if (ret) 357 - goto error; 358 359 359 360 for (i = 0; i < desc->num_properties; i++) { 360 361 const enum power_supply_property prop = desc->properties[i];
+1
drivers/power/supply/power_supply_sysfs.c
··· 89 89 [POWER_SUPPLY_CHARGE_TYPE_ADAPTIVE] = "Adaptive", 90 90 [POWER_SUPPLY_CHARGE_TYPE_CUSTOM] = "Custom", 91 91 [POWER_SUPPLY_CHARGE_TYPE_LONGLIFE] = "Long Life", 92 + [POWER_SUPPLY_CHARGE_TYPE_BYPASS] = "Bypass", 92 93 }; 93 94 94 95 static const char * const POWER_SUPPLY_HEALTH_TEXT[] = {
+1 -1
drivers/power/supply/rt9455_charger.c
··· 1716 1716 cancel_delayed_work_sync(&info->max_charging_time_work); 1717 1717 cancel_delayed_work_sync(&info->batt_presence_work); 1718 1718 1719 - return ret; 1719 + return 0; 1720 1720 } 1721 1721 1722 1722 static const struct i2c_device_id rt9455_i2c_id_table[] = {
+918
drivers/power/supply/samsung-sdi-battery.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + /* 4 + * Battery data and characteristics for Samsung SDI (Samsung Digital Interface) 5 + * batteries. The data is retrieved automatically into drivers using 6 + * the power_supply_get_battery_info() call. 7 + * 8 + * The BTI (battery type indicator) resistance in the code drops was very 9 + * unreliable. The resistance listed here was obtained by simply measuring 10 + * the BTI resistance with a multimeter on the battery. 11 + */ 12 + #include <linux/module.h> 13 + #include <linux/power_supply.h> 14 + #include "samsung-sdi-battery.h" 15 + 16 + struct samsung_sdi_battery { 17 + char *compatible; 18 + char *name; 19 + struct power_supply_battery_info info; 20 + }; 21 + 22 + /* 23 + * Voltage to internal resistance tables. The internal resistance varies 24 + * depending on the VBAT voltage, so look this up from a table. Different 25 + * tables apply depending on whether we are charging or not. 26 + */ 27 + 28 + static struct power_supply_vbat_ri_table samsung_vbat2res_discharging_eb_l1m7flu[] = { 29 + { .vbat_uv = 4240000, .ri_uohm = 160000 }, 30 + { .vbat_uv = 4210000, .ri_uohm = 179000 }, 31 + { .vbat_uv = 4180000, .ri_uohm = 183000 }, 32 + { .vbat_uv = 4160000, .ri_uohm = 184000 }, 33 + { .vbat_uv = 4140000, .ri_uohm = 191000 }, 34 + { .vbat_uv = 4120000, .ri_uohm = 204000 }, 35 + { .vbat_uv = 4076000, .ri_uohm = 220000 }, 36 + { .vbat_uv = 4030000, .ri_uohm = 227000 }, 37 + { .vbat_uv = 3986000, .ri_uohm = 215000 }, 38 + { .vbat_uv = 3916000, .ri_uohm = 221000 }, 39 + { .vbat_uv = 3842000, .ri_uohm = 259000 }, 40 + { .vbat_uv = 3773000, .ri_uohm = 287000 }, 41 + { .vbat_uv = 3742000, .ri_uohm = 283000 }, 42 + { .vbat_uv = 3709000, .ri_uohm = 277000 }, 43 + { .vbat_uv = 3685000, .ri_uohm = 297000 }, 44 + { .vbat_uv = 3646000, .ri_uohm = 310000 }, 45 + { .vbat_uv = 3616000, .ri_uohm = 331000 }, 46 + { .vbat_uv = 3602000, .ri_uohm = 370000 }, 47 + { .vbat_uv = 3578000, .ri_uohm = 350000 }, 48 + { .vbat_uv = 3553000, .ri_uohm = 321000 }, 49 + { .vbat_uv = 3503000, .ri_uohm = 322000 }, 50 + { .vbat_uv = 3400000, .ri_uohm = 269000 }, 51 + { .vbat_uv = 3360000, .ri_uohm = 328000 }, 52 + { .vbat_uv = 3330000, .ri_uohm = 305000 }, 53 + { .vbat_uv = 3300000, .ri_uohm = 339000 }, 54 + }; 55 + 56 + static struct power_supply_vbat_ri_table samsung_vbat2res_charging_eb_l1m7flu[] = { 57 + { .vbat_uv = 4302000, .ri_uohm = 230000 }, 58 + { .vbat_uv = 4276000, .ri_uohm = 345000 }, 59 + { .vbat_uv = 4227000, .ri_uohm = 345000 }, 60 + { .vbat_uv = 4171000, .ri_uohm = 346000 }, 61 + { .vbat_uv = 4134000, .ri_uohm = 311000 }, 62 + { .vbat_uv = 4084000, .ri_uohm = 299000 }, 63 + { .vbat_uv = 4052000, .ri_uohm = 316000 }, 64 + { .vbat_uv = 4012000, .ri_uohm = 309000 }, 65 + { .vbat_uv = 3961000, .ri_uohm = 303000 }, 66 + { .vbat_uv = 3939000, .ri_uohm = 280000 }, 67 + { .vbat_uv = 3904000, .ri_uohm = 261000 }, 68 + { .vbat_uv = 3850000, .ri_uohm = 212000 }, 69 + { .vbat_uv = 3800000, .ri_uohm = 232000 }, 70 + { .vbat_uv = 3750000, .ri_uohm = 177000 }, 71 + { .vbat_uv = 3712000, .ri_uohm = 164000 }, 72 + { .vbat_uv = 3674000, .ri_uohm = 161000 }, 73 + { .vbat_uv = 3590000, .ri_uohm = 164000 }, 74 + }; 75 + 76 + static struct power_supply_vbat_ri_table samsung_vbat2res_discharging_eb425161la[] = { 77 + { .vbat_uv = 4240000, .ri_uohm = 160000 }, 78 + { .vbat_uv = 4210000, .ri_uohm = 179000 }, 79 + { .vbat_uv = 4180000, .ri_uohm = 183000 }, 80 + { .vbat_uv = 4160000, .ri_uohm = 184000 }, 81 + { .vbat_uv = 4140000, .ri_uohm = 191000 }, 82 + { .vbat_uv = 4120000, .ri_uohm = 204000 }, 83 + { .vbat_uv = 4080000, .ri_uohm = 200000 }, 84 + { .vbat_uv = 4027000, .ri_uohm = 202000 }, 85 + { .vbat_uv = 3916000, .ri_uohm = 221000 }, 86 + { .vbat_uv = 3842000, .ri_uohm = 259000 }, 87 + { .vbat_uv = 3800000, .ri_uohm = 262000 }, 88 + { .vbat_uv = 3742000, .ri_uohm = 263000 }, 89 + { .vbat_uv = 3709000, .ri_uohm = 277000 }, 90 + { .vbat_uv = 3685000, .ri_uohm = 312000 }, 91 + { .vbat_uv = 3668000, .ri_uohm = 258000 }, 92 + { .vbat_uv = 3660000, .ri_uohm = 247000 }, 93 + { .vbat_uv = 3636000, .ri_uohm = 293000 }, 94 + { .vbat_uv = 3616000, .ri_uohm = 331000 }, 95 + { .vbat_uv = 3600000, .ri_uohm = 349000 }, 96 + { .vbat_uv = 3593000, .ri_uohm = 345000 }, 97 + { .vbat_uv = 3585000, .ri_uohm = 344000 }, 98 + { .vbat_uv = 3572000, .ri_uohm = 336000 }, 99 + { .vbat_uv = 3553000, .ri_uohm = 321000 }, 100 + { .vbat_uv = 3517000, .ri_uohm = 336000 }, 101 + { .vbat_uv = 3503000, .ri_uohm = 322000 }, 102 + { .vbat_uv = 3400000, .ri_uohm = 269000 }, 103 + { .vbat_uv = 3360000, .ri_uohm = 328000 }, 104 + { .vbat_uv = 3330000, .ri_uohm = 305000 }, 105 + { .vbat_uv = 3300000, .ri_uohm = 339000 }, 106 + }; 107 + 108 + static struct power_supply_vbat_ri_table samsung_vbat2res_charging_eb425161la[] = { 109 + { .vbat_uv = 4345000, .ri_uohm = 230000 }, 110 + { .vbat_uv = 4329000, .ri_uohm = 238000 }, 111 + { .vbat_uv = 4314000, .ri_uohm = 225000 }, 112 + { .vbat_uv = 4311000, .ri_uohm = 239000 }, 113 + { .vbat_uv = 4294000, .ri_uohm = 235000 }, 114 + { .vbat_uv = 4264000, .ri_uohm = 229000 }, 115 + { .vbat_uv = 4262000, .ri_uohm = 228000 }, 116 + { .vbat_uv = 4252000, .ri_uohm = 236000 }, 117 + { .vbat_uv = 4244000, .ri_uohm = 234000 }, 118 + { .vbat_uv = 4235000, .ri_uohm = 234000 }, 119 + { .vbat_uv = 4227000, .ri_uohm = 238000 }, 120 + { .vbat_uv = 4219000, .ri_uohm = 242000 }, 121 + { .vbat_uv = 4212000, .ri_uohm = 239000 }, 122 + { .vbat_uv = 4206000, .ri_uohm = 231000 }, 123 + { .vbat_uv = 4201000, .ri_uohm = 231000 }, 124 + { .vbat_uv = 4192000, .ri_uohm = 224000 }, 125 + { .vbat_uv = 4184000, .ri_uohm = 238000 }, 126 + { .vbat_uv = 4173000, .ri_uohm = 245000 }, 127 + { .vbat_uv = 4161000, .ri_uohm = 244000 }, 128 + { .vbat_uv = 4146000, .ri_uohm = 244000 }, 129 + { .vbat_uv = 4127000, .ri_uohm = 228000 }, 130 + { .vbat_uv = 4119000, .ri_uohm = 218000 }, 131 + { .vbat_uv = 4112000, .ri_uohm = 215000 }, 132 + { .vbat_uv = 4108000, .ri_uohm = 209000 }, 133 + { .vbat_uv = 4102000, .ri_uohm = 214000 }, 134 + { .vbat_uv = 4096000, .ri_uohm = 215000 }, 135 + { .vbat_uv = 4090000, .ri_uohm = 215000 }, 136 + { .vbat_uv = 4083000, .ri_uohm = 219000 }, 137 + { .vbat_uv = 4078000, .ri_uohm = 208000 }, 138 + { .vbat_uv = 4071000, .ri_uohm = 205000 }, 139 + { .vbat_uv = 4066000, .ri_uohm = 208000 }, 140 + { .vbat_uv = 4061000, .ri_uohm = 210000 }, 141 + { .vbat_uv = 4055000, .ri_uohm = 212000 }, 142 + { .vbat_uv = 4049000, .ri_uohm = 215000 }, 143 + { .vbat_uv = 4042000, .ri_uohm = 212000 }, 144 + { .vbat_uv = 4032000, .ri_uohm = 217000 }, 145 + { .vbat_uv = 4027000, .ri_uohm = 220000 }, 146 + { .vbat_uv = 4020000, .ri_uohm = 210000 }, 147 + { .vbat_uv = 4013000, .ri_uohm = 214000 }, 148 + { .vbat_uv = 4007000, .ri_uohm = 219000 }, 149 + { .vbat_uv = 4003000, .ri_uohm = 229000 }, 150 + { .vbat_uv = 3996000, .ri_uohm = 246000 }, 151 + { .vbat_uv = 3990000, .ri_uohm = 245000 }, 152 + { .vbat_uv = 3984000, .ri_uohm = 242000 }, 153 + { .vbat_uv = 3977000, .ri_uohm = 236000 }, 154 + { .vbat_uv = 3971000, .ri_uohm = 231000 }, 155 + { .vbat_uv = 3966000, .ri_uohm = 229000 }, 156 + { .vbat_uv = 3952000, .ri_uohm = 226000 }, 157 + { .vbat_uv = 3946000, .ri_uohm = 222000 }, 158 + { .vbat_uv = 3941000, .ri_uohm = 222000 }, 159 + { .vbat_uv = 3936000, .ri_uohm = 217000 }, 160 + { .vbat_uv = 3932000, .ri_uohm = 217000 }, 161 + { .vbat_uv = 3928000, .ri_uohm = 212000 }, 162 + { .vbat_uv = 3926000, .ri_uohm = 214000 }, 163 + { .vbat_uv = 3922000, .ri_uohm = 209000 }, 164 + { .vbat_uv = 3917000, .ri_uohm = 215000 }, 165 + { .vbat_uv = 3914000, .ri_uohm = 212000 }, 166 + { .vbat_uv = 3912000, .ri_uohm = 220000 }, 167 + { .vbat_uv = 3910000, .ri_uohm = 226000 }, 168 + { .vbat_uv = 3903000, .ri_uohm = 226000 }, 169 + { .vbat_uv = 3891000, .ri_uohm = 222000 }, 170 + { .vbat_uv = 3871000, .ri_uohm = 221000 }, 171 + { .vbat_uv = 3857000, .ri_uohm = 219000 }, 172 + { .vbat_uv = 3850000, .ri_uohm = 216000 }, 173 + { .vbat_uv = 3843000, .ri_uohm = 212000 }, 174 + { .vbat_uv = 3835000, .ri_uohm = 206000 }, 175 + { .vbat_uv = 3825000, .ri_uohm = 217000 }, 176 + { .vbat_uv = 3824000, .ri_uohm = 220000 }, 177 + { .vbat_uv = 3820000, .ri_uohm = 237000 }, 178 + { .vbat_uv = 3800000, .ri_uohm = 232000 }, 179 + { .vbat_uv = 3750000, .ri_uohm = 177000 }, 180 + { .vbat_uv = 3712000, .ri_uohm = 164000 }, 181 + { .vbat_uv = 3674000, .ri_uohm = 161000 }, 182 + { .vbat_uv = 3590000, .ri_uohm = 164000 }, 183 + }; 184 + 185 + static struct power_supply_vbat_ri_table samsung_vbat2res_discharging_eb425161lu[] = { 186 + { .vbat_uv = 4240000, .ri_uohm = 160000 }, 187 + { .vbat_uv = 4210000, .ri_uohm = 179000 }, 188 + { .vbat_uv = 4180000, .ri_uohm = 183000 }, 189 + { .vbat_uv = 4160000, .ri_uohm = 184000 }, 190 + { .vbat_uv = 4140000, .ri_uohm = 191000 }, 191 + { .vbat_uv = 4120000, .ri_uohm = 204000 }, 192 + { .vbat_uv = 4080000, .ri_uohm = 200000 }, 193 + { .vbat_uv = 4027000, .ri_uohm = 202000 }, 194 + { .vbat_uv = 3916000, .ri_uohm = 221000 }, 195 + { .vbat_uv = 3842000, .ri_uohm = 259000 }, 196 + { .vbat_uv = 3800000, .ri_uohm = 262000 }, 197 + { .vbat_uv = 3742000, .ri_uohm = 263000 }, 198 + { .vbat_uv = 3708000, .ri_uohm = 277000 }, 199 + { .vbat_uv = 3684000, .ri_uohm = 272000 }, 200 + { .vbat_uv = 3664000, .ri_uohm = 278000 }, 201 + { .vbat_uv = 3655000, .ri_uohm = 285000 }, 202 + { .vbat_uv = 3638000, .ri_uohm = 261000 }, 203 + { .vbat_uv = 3624000, .ri_uohm = 259000 }, 204 + { .vbat_uv = 3616000, .ri_uohm = 266000 }, 205 + { .vbat_uv = 3597000, .ri_uohm = 278000 }, 206 + { .vbat_uv = 3581000, .ri_uohm = 281000 }, 207 + { .vbat_uv = 3560000, .ri_uohm = 287000 }, 208 + { .vbat_uv = 3527000, .ri_uohm = 289000 }, 209 + { .vbat_uv = 3512000, .ri_uohm = 286000 }, 210 + { .vbat_uv = 3494000, .ri_uohm = 282000 }, 211 + { .vbat_uv = 3400000, .ri_uohm = 269000 }, 212 + { .vbat_uv = 3360000, .ri_uohm = 328000 }, 213 + { .vbat_uv = 3330000, .ri_uohm = 305000 }, 214 + { .vbat_uv = 3300000, .ri_uohm = 339000 }, 215 + }; 216 + 217 + static struct power_supply_vbat_ri_table samsung_vbat2res_charging_eb425161lu[] = { 218 + { .vbat_uv = 4346000, .ri_uohm = 293000 }, 219 + { .vbat_uv = 4336000, .ri_uohm = 290000 }, 220 + { .vbat_uv = 4315000, .ri_uohm = 274000 }, 221 + { .vbat_uv = 4310000, .ri_uohm = 264000 }, 222 + { .vbat_uv = 4275000, .ri_uohm = 275000 }, 223 + { .vbat_uv = 4267000, .ri_uohm = 274000 }, 224 + { .vbat_uv = 4227000, .ri_uohm = 262000 }, 225 + { .vbat_uv = 4186000, .ri_uohm = 282000 }, 226 + { .vbat_uv = 4136000, .ri_uohm = 246000 }, 227 + { .vbat_uv = 4110000, .ri_uohm = 242000 }, 228 + { .vbat_uv = 4077000, .ri_uohm = 249000 }, 229 + { .vbat_uv = 4049000, .ri_uohm = 238000 }, 230 + { .vbat_uv = 4017000, .ri_uohm = 268000 }, 231 + { .vbat_uv = 3986000, .ri_uohm = 261000 }, 232 + { .vbat_uv = 3962000, .ri_uohm = 252000 }, 233 + { .vbat_uv = 3940000, .ri_uohm = 235000 }, 234 + { .vbat_uv = 3930000, .ri_uohm = 237000 }, 235 + { .vbat_uv = 3924000, .ri_uohm = 255000 }, 236 + { .vbat_uv = 3910000, .ri_uohm = 244000 }, 237 + { .vbat_uv = 3889000, .ri_uohm = 231000 }, 238 + { .vbat_uv = 3875000, .ri_uohm = 249000 }, 239 + { .vbat_uv = 3850000, .ri_uohm = 212000 }, 240 + { .vbat_uv = 3800000, .ri_uohm = 232000 }, 241 + { .vbat_uv = 3750000, .ri_uohm = 177000 }, 242 + { .vbat_uv = 3712000, .ri_uohm = 164000 }, 243 + { .vbat_uv = 3674000, .ri_uohm = 161000 }, 244 + { .vbat_uv = 3590000, .ri_uohm = 164000 }, 245 + }; 246 + 247 + static struct power_supply_vbat_ri_table samsung_vbat2res_discharging_eb485159lu[] = { 248 + { .vbat_uv = 4240000, .ri_uohm = 160000 }, 249 + { .vbat_uv = 4210000, .ri_uohm = 179000 }, 250 + { .vbat_uv = 4180000, .ri_uohm = 183000 }, 251 + { .vbat_uv = 4160000, .ri_uohm = 184000 }, 252 + { .vbat_uv = 4140000, .ri_uohm = 191000 }, 253 + { .vbat_uv = 4120000, .ri_uohm = 204000 }, 254 + { .vbat_uv = 4080000, .ri_uohm = 200000 }, 255 + { .vbat_uv = 4027000, .ri_uohm = 202000 }, 256 + { .vbat_uv = 3916000, .ri_uohm = 221000 }, 257 + { .vbat_uv = 3842000, .ri_uohm = 259000 }, 258 + { .vbat_uv = 3800000, .ri_uohm = 262000 }, 259 + { .vbat_uv = 3715000, .ri_uohm = 340000 }, 260 + { .vbat_uv = 3700000, .ri_uohm = 300000 }, 261 + { .vbat_uv = 3682000, .ri_uohm = 233000 }, 262 + { .vbat_uv = 3655000, .ri_uohm = 246000 }, 263 + { .vbat_uv = 3639000, .ri_uohm = 260000 }, 264 + { .vbat_uv = 3621000, .ri_uohm = 254000 }, 265 + { .vbat_uv = 3583000, .ri_uohm = 266000 }, 266 + { .vbat_uv = 3536000, .ri_uohm = 274000 }, 267 + { .vbat_uv = 3502000, .ri_uohm = 300000 }, 268 + { .vbat_uv = 3465000, .ri_uohm = 245000 }, 269 + { .vbat_uv = 3438000, .ri_uohm = 225000 }, 270 + { .vbat_uv = 3330000, .ri_uohm = 305000 }, 271 + { .vbat_uv = 3300000, .ri_uohm = 339000 }, 272 + }; 273 + 274 + static struct power_supply_vbat_ri_table samsung_vbat2res_charging_eb485159lu[] = { 275 + { .vbat_uv = 4302000, .ri_uohm = 200000 }, 276 + { .vbat_uv = 4258000, .ri_uohm = 206000 }, 277 + { .vbat_uv = 4200000, .ri_uohm = 231000 }, 278 + { .vbat_uv = 4150000, .ri_uohm = 198000 }, 279 + { .vbat_uv = 4134000, .ri_uohm = 268000 }, 280 + { .vbat_uv = 4058000, .ri_uohm = 172000 }, 281 + { .vbat_uv = 4003000, .ri_uohm = 227000 }, 282 + { .vbat_uv = 3972000, .ri_uohm = 241000 }, 283 + { .vbat_uv = 3953000, .ri_uohm = 244000 }, 284 + { .vbat_uv = 3950000, .ri_uohm = 213000 }, 285 + { .vbat_uv = 3900000, .ri_uohm = 225000 }, 286 + { .vbat_uv = 3850000, .ri_uohm = 212000 }, 287 + { .vbat_uv = 3800000, .ri_uohm = 232000 }, 288 + { .vbat_uv = 3750000, .ri_uohm = 177000 }, 289 + { .vbat_uv = 3712000, .ri_uohm = 164000 }, 290 + { .vbat_uv = 3674000, .ri_uohm = 161000 }, 291 + { .vbat_uv = 3590000, .ri_uohm = 164000 }, 292 + }; 293 + 294 + static struct power_supply_vbat_ri_table samsung_vbat2res_discharging_eb535151vu[] = { 295 + { .vbat_uv = 4071000, .ri_uohm = 158000 }, 296 + { .vbat_uv = 4019000, .ri_uohm = 187000 }, 297 + { .vbat_uv = 3951000, .ri_uohm = 191000 }, 298 + { .vbat_uv = 3901000, .ri_uohm = 193000 }, 299 + { .vbat_uv = 3850000, .ri_uohm = 273000 }, 300 + { .vbat_uv = 3800000, .ri_uohm = 305000 }, 301 + { .vbat_uv = 3750000, .ri_uohm = 205000 }, 302 + { .vbat_uv = 3700000, .ri_uohm = 290000 }, 303 + { .vbat_uv = 3650000, .ri_uohm = 262000 }, 304 + { .vbat_uv = 3618000, .ri_uohm = 290000 }, 305 + { .vbat_uv = 3505000, .ri_uohm = 235000 }, 306 + { .vbat_uv = 3484000, .ri_uohm = 253000 }, 307 + { .vbat_uv = 3413000, .ri_uohm = 243000 }, 308 + { .vbat_uv = 3393000, .ri_uohm = 285000 }, 309 + { .vbat_uv = 3361000, .ri_uohm = 281000 }, 310 + { .vbat_uv = 3302000, .ri_uohm = 286000 }, 311 + { .vbat_uv = 3280000, .ri_uohm = 250000 }, 312 + }; 313 + 314 + static struct power_supply_vbat_ri_table samsung_vbat2res_charging_eb535151vu[] = { 315 + { .vbat_uv = 4190000, .ri_uohm = 214000 }, 316 + { .vbat_uv = 4159000, .ri_uohm = 252000 }, 317 + { .vbat_uv = 4121000, .ri_uohm = 245000 }, 318 + { .vbat_uv = 4069000, .ri_uohm = 228000 }, 319 + { .vbat_uv = 4046000, .ri_uohm = 229000 }, 320 + { .vbat_uv = 4026000, .ri_uohm = 233000 }, 321 + { .vbat_uv = 4007000, .ri_uohm = 240000 }, 322 + { .vbat_uv = 3982000, .ri_uohm = 291000 }, 323 + { .vbat_uv = 3945000, .ri_uohm = 276000 }, 324 + { .vbat_uv = 3924000, .ri_uohm = 266000 }, 325 + { .vbat_uv = 3910000, .ri_uohm = 258000 }, 326 + { .vbat_uv = 3900000, .ri_uohm = 271000 }, 327 + { .vbat_uv = 3844000, .ri_uohm = 279000 }, 328 + { .vbat_uv = 3772000, .ri_uohm = 217000 }, 329 + { .vbat_uv = 3673000, .ri_uohm = 208000 }, 330 + { .vbat_uv = 3571000, .ri_uohm = 208000 }, 331 + { .vbat_uv = 3510000, .ri_uohm = 228000 }, 332 + }; 333 + 334 + static struct power_supply_vbat_ri_table samsung_vbat2res_discharging_eb585157lu[] = { 335 + { .vbat_uv = 4194000, .ri_uohm = 121000 }, 336 + { .vbat_uv = 4169000, .ri_uohm = 188000 }, 337 + { .vbat_uv = 4136000, .ri_uohm = 173000 }, 338 + { .vbat_uv = 4108000, .ri_uohm = 158000 }, 339 + { .vbat_uv = 4064000, .ri_uohm = 143000 }, 340 + { .vbat_uv = 3956000, .ri_uohm = 160000 }, 341 + { .vbat_uv = 3847000, .ri_uohm = 262000 }, 342 + { .vbat_uv = 3806000, .ri_uohm = 280000 }, 343 + { .vbat_uv = 3801000, .ri_uohm = 266000 }, 344 + { .vbat_uv = 3794000, .ri_uohm = 259000 }, 345 + { .vbat_uv = 3785000, .ri_uohm = 234000 }, 346 + { .vbat_uv = 3779000, .ri_uohm = 227000 }, 347 + { .vbat_uv = 3772000, .ri_uohm = 222000 }, 348 + { .vbat_uv = 3765000, .ri_uohm = 221000 }, 349 + { .vbat_uv = 3759000, .ri_uohm = 216000 }, 350 + { .vbat_uv = 3754000, .ri_uohm = 206000 }, 351 + { .vbat_uv = 3747000, .ri_uohm = 212000 }, 352 + { .vbat_uv = 3743000, .ri_uohm = 208000 }, 353 + { .vbat_uv = 3737000, .ri_uohm = 212000 }, 354 + { .vbat_uv = 3733000, .ri_uohm = 200000 }, 355 + { .vbat_uv = 3728000, .ri_uohm = 203000 }, 356 + { .vbat_uv = 3722000, .ri_uohm = 207000 }, 357 + { .vbat_uv = 3719000, .ri_uohm = 208000 }, 358 + { .vbat_uv = 3715000, .ri_uohm = 209000 }, 359 + { .vbat_uv = 3712000, .ri_uohm = 211000 }, 360 + { .vbat_uv = 3709000, .ri_uohm = 210000 }, 361 + { .vbat_uv = 3704000, .ri_uohm = 216000 }, 362 + { .vbat_uv = 3701000, .ri_uohm = 218000 }, 363 + { .vbat_uv = 3698000, .ri_uohm = 222000 }, 364 + { .vbat_uv = 3694000, .ri_uohm = 218000 }, 365 + { .vbat_uv = 3692000, .ri_uohm = 215000 }, 366 + { .vbat_uv = 3688000, .ri_uohm = 224000 }, 367 + { .vbat_uv = 3686000, .ri_uohm = 224000 }, 368 + { .vbat_uv = 3683000, .ri_uohm = 228000 }, 369 + { .vbat_uv = 3681000, .ri_uohm = 228000 }, 370 + { .vbat_uv = 3679000, .ri_uohm = 229000 }, 371 + { .vbat_uv = 3676000, .ri_uohm = 232000 }, 372 + { .vbat_uv = 3675000, .ri_uohm = 229000 }, 373 + { .vbat_uv = 3673000, .ri_uohm = 229000 }, 374 + { .vbat_uv = 3672000, .ri_uohm = 223000 }, 375 + { .vbat_uv = 3669000, .ri_uohm = 224000 }, 376 + { .vbat_uv = 3666000, .ri_uohm = 224000 }, 377 + { .vbat_uv = 3663000, .ri_uohm = 221000 }, 378 + { .vbat_uv = 3660000, .ri_uohm = 218000 }, 379 + { .vbat_uv = 3657000, .ri_uohm = 215000 }, 380 + { .vbat_uv = 3654000, .ri_uohm = 212000 }, 381 + { .vbat_uv = 3649000, .ri_uohm = 215000 }, 382 + { .vbat_uv = 3644000, .ri_uohm = 215000 }, 383 + { .vbat_uv = 3636000, .ri_uohm = 215000 }, 384 + { .vbat_uv = 3631000, .ri_uohm = 206000 }, 385 + { .vbat_uv = 3623000, .ri_uohm = 205000 }, 386 + { .vbat_uv = 3616000, .ri_uohm = 193000 }, 387 + { .vbat_uv = 3605000, .ri_uohm = 193000 }, 388 + { .vbat_uv = 3600000, .ri_uohm = 198000 }, 389 + { .vbat_uv = 3597000, .ri_uohm = 198000 }, 390 + { .vbat_uv = 3592000, .ri_uohm = 203000 }, 391 + { .vbat_uv = 3591000, .ri_uohm = 188000 }, 392 + { .vbat_uv = 3587000, .ri_uohm = 188000 }, 393 + { .vbat_uv = 3583000, .ri_uohm = 177000 }, 394 + { .vbat_uv = 3577000, .ri_uohm = 170000 }, 395 + { .vbat_uv = 3568000, .ri_uohm = 135000 }, 396 + { .vbat_uv = 3552000, .ri_uohm = 54000 }, 397 + { .vbat_uv = 3526000, .ri_uohm = 130000 }, 398 + { .vbat_uv = 3501000, .ri_uohm = 48000 }, 399 + { .vbat_uv = 3442000, .ri_uohm = 183000 }, 400 + { .vbat_uv = 3326000, .ri_uohm = 372000 }, 401 + { .vbat_uv = 3161000, .ri_uohm = 452000 }, 402 + }; 403 + 404 + static struct power_supply_vbat_ri_table samsung_vbat2res_charging_eb585157lu[] = { 405 + { .vbat_uv = 4360000, .ri_uohm = 128000 }, 406 + { .vbat_uv = 4325000, .ri_uohm = 130000 }, 407 + { .vbat_uv = 4316000, .ri_uohm = 148000 }, 408 + { .vbat_uv = 4308000, .ri_uohm = 162000 }, 409 + { .vbat_uv = 4301000, .ri_uohm = 162000 }, 410 + { .vbat_uv = 4250000, .ri_uohm = 162000 }, 411 + { .vbat_uv = 4230000, .ri_uohm = 164000 }, 412 + { .vbat_uv = 4030000, .ri_uohm = 164000 }, 413 + { .vbat_uv = 4000000, .ri_uohm = 193000 }, 414 + { .vbat_uv = 3950000, .ri_uohm = 204000 }, 415 + { .vbat_uv = 3850000, .ri_uohm = 210000 }, 416 + { .vbat_uv = 3800000, .ri_uohm = 230000 }, 417 + { .vbat_uv = 3790000, .ri_uohm = 240000 }, 418 + { .vbat_uv = 3780000, .ri_uohm = 311000 }, 419 + { .vbat_uv = 3760000, .ri_uohm = 420000 }, 420 + { .vbat_uv = 3700000, .ri_uohm = 504000 }, 421 + { .vbat_uv = 3600000, .ri_uohm = 565000 }, 422 + }; 423 + 424 + /* 425 + * Temperature to internal resistance scaling tables. 426 + * 427 + * "resistance" is the percentage of the resistance determined from the voltage 428 + * so this represents the capacity ratio at different temperatures. 429 + * 430 + * FIXME: the proper table is missing: Samsung does not provide the necessary 431 + * temperature compensation tables so we just state 100% for every temperature. 432 + * If you have the datasheets, please provide these tables. 433 + */ 434 + static struct power_supply_resistance_temp_table samsung_temp2res[] = { 435 + { .temp = 50, .resistance = 100 }, 436 + { .temp = 40, .resistance = 100 }, 437 + { .temp = 30, .resistance = 100 }, 438 + { .temp = 20, .resistance = 100 }, 439 + { .temp = 10, .resistance = 100 }, 440 + { .temp = 00, .resistance = 100 }, 441 + { .temp = -10, .resistance = 100 }, 442 + { .temp = -20, .resistance = 100 }, 443 + }; 444 + 445 + /* 446 + * Capacity tables for different Open Circuit Voltages (OCV). 447 + * These must be sorted by falling OCV value. 448 + */ 449 + 450 + static struct power_supply_battery_ocv_table samsung_ocv_cap_eb485159lu[] = { 451 + { .ocv = 4330000, .capacity = 100}, 452 + { .ocv = 4320000, .capacity = 99}, 453 + { .ocv = 4283000, .capacity = 95}, 454 + { .ocv = 4246000, .capacity = 92}, 455 + { .ocv = 4211000, .capacity = 89}, 456 + { .ocv = 4167000, .capacity = 85}, 457 + { .ocv = 4146000, .capacity = 83}, 458 + { .ocv = 4124000, .capacity = 81}, 459 + { .ocv = 4062000, .capacity = 75}, 460 + { .ocv = 4013000, .capacity = 70}, 461 + { .ocv = 3977000, .capacity = 66}, 462 + { .ocv = 3931000, .capacity = 60}, 463 + { .ocv = 3914000, .capacity = 58}, 464 + { .ocv = 3901000, .capacity = 57}, 465 + { .ocv = 3884000, .capacity = 56}, 466 + { .ocv = 3870000, .capacity = 55}, 467 + { .ocv = 3862000, .capacity = 54}, 468 + { .ocv = 3854000, .capacity = 53}, 469 + { .ocv = 3838000, .capacity = 50}, 470 + { .ocv = 3823000, .capacity = 47}, 471 + { .ocv = 3813000, .capacity = 45}, 472 + { .ocv = 3807000, .capacity = 43}, 473 + { .ocv = 3800000, .capacity = 41}, 474 + { .ocv = 3795000, .capacity = 40}, 475 + { .ocv = 3786000, .capacity = 37}, 476 + { .ocv = 3783000, .capacity = 35}, 477 + { .ocv = 3773000, .capacity = 30}, 478 + { .ocv = 3758000, .capacity = 25}, 479 + { .ocv = 3745000, .capacity = 22}, 480 + { .ocv = 3738000, .capacity = 20}, 481 + { .ocv = 3733000, .capacity = 19}, 482 + { .ocv = 3716000, .capacity = 17}, 483 + { .ocv = 3709000, .capacity = 16}, 484 + { .ocv = 3698000, .capacity = 15}, 485 + { .ocv = 3687000, .capacity = 14}, 486 + { .ocv = 3684000, .capacity = 13}, 487 + { .ocv = 3684000, .capacity = 12}, 488 + { .ocv = 3678000, .capacity = 10}, 489 + { .ocv = 3671000, .capacity = 9}, 490 + { .ocv = 3665000, .capacity = 8}, 491 + { .ocv = 3651000, .capacity = 7}, 492 + { .ocv = 3634000, .capacity = 6}, 493 + { .ocv = 3601000, .capacity = 5}, 494 + { .ocv = 3564000, .capacity = 4}, 495 + { .ocv = 3516000, .capacity = 3}, 496 + { .ocv = 3456000, .capacity = 2}, 497 + { .ocv = 3381000, .capacity = 1}, 498 + { .ocv = 3300000, .capacity = 0}, 499 + }; 500 + 501 + /* Same capacity table is used by eb-l1m7flu, eb425161la, eb425161lu */ 502 + static struct power_supply_battery_ocv_table samsung_ocv_cap_1500mah[] = { 503 + { .ocv = 4328000, .capacity = 100}, 504 + { .ocv = 4299000, .capacity = 99}, 505 + { .ocv = 4281000, .capacity = 98}, 506 + { .ocv = 4241000, .capacity = 95}, 507 + { .ocv = 4183000, .capacity = 90}, 508 + { .ocv = 4150000, .capacity = 87}, 509 + { .ocv = 4116000, .capacity = 84}, 510 + { .ocv = 4077000, .capacity = 80}, 511 + { .ocv = 4068000, .capacity = 79}, 512 + { .ocv = 4058000, .capacity = 77}, 513 + { .ocv = 4026000, .capacity = 75}, 514 + { .ocv = 3987000, .capacity = 72}, 515 + { .ocv = 3974000, .capacity = 69}, 516 + { .ocv = 3953000, .capacity = 66}, 517 + { .ocv = 3933000, .capacity = 63}, 518 + { .ocv = 3911000, .capacity = 60}, 519 + { .ocv = 3900000, .capacity = 58}, 520 + { .ocv = 3873000, .capacity = 55}, 521 + { .ocv = 3842000, .capacity = 52}, 522 + { .ocv = 3829000, .capacity = 50}, 523 + { .ocv = 3810000, .capacity = 45}, 524 + { .ocv = 3793000, .capacity = 40}, 525 + { .ocv = 3783000, .capacity = 35}, 526 + { .ocv = 3776000, .capacity = 30}, 527 + { .ocv = 3762000, .capacity = 25}, 528 + { .ocv = 3746000, .capacity = 20}, 529 + { .ocv = 3739000, .capacity = 18}, 530 + { .ocv = 3715000, .capacity = 15}, 531 + { .ocv = 3700000, .capacity = 12}, 532 + { .ocv = 3690000, .capacity = 10}, 533 + { .ocv = 3680000, .capacity = 9}, 534 + { .ocv = 3670000, .capacity = 7}, 535 + { .ocv = 3656000, .capacity = 5}, 536 + { .ocv = 3634000, .capacity = 4}, 537 + { .ocv = 3614000, .capacity = 3}, 538 + { .ocv = 3551000, .capacity = 2}, 539 + { .ocv = 3458000, .capacity = 1}, 540 + { .ocv = 3300000, .capacity = 0}, 541 + }; 542 + 543 + static struct power_supply_battery_ocv_table samsung_ocv_cap_eb535151vu[] = { 544 + { .ocv = 4178000, .capacity = 100}, 545 + { .ocv = 4148000, .capacity = 99}, 546 + { .ocv = 4105000, .capacity = 95}, 547 + { .ocv = 4078000, .capacity = 92}, 548 + { .ocv = 4057000, .capacity = 89}, 549 + { .ocv = 4013000, .capacity = 85}, 550 + { .ocv = 3988000, .capacity = 82}, 551 + { .ocv = 3962000, .capacity = 77}, 552 + { .ocv = 3920000, .capacity = 70}, 553 + { .ocv = 3891000, .capacity = 65}, 554 + { .ocv = 3874000, .capacity = 62}, 555 + { .ocv = 3839000, .capacity = 59}, 556 + { .ocv = 3816000, .capacity = 55}, 557 + { .ocv = 3798000, .capacity = 50}, 558 + { .ocv = 3778000, .capacity = 40}, 559 + { .ocv = 3764000, .capacity = 30}, 560 + { .ocv = 3743000, .capacity = 25}, 561 + { .ocv = 3711000, .capacity = 20}, 562 + { .ocv = 3691000, .capacity = 18}, 563 + { .ocv = 3685000, .capacity = 15}, 564 + { .ocv = 3680000, .capacity = 12}, 565 + { .ocv = 3662000, .capacity = 10}, 566 + { .ocv = 3638000, .capacity = 9}, 567 + { .ocv = 3593000, .capacity = 7}, 568 + { .ocv = 3566000, .capacity = 6}, 569 + { .ocv = 3497000, .capacity = 4}, 570 + { .ocv = 3405000, .capacity = 2}, 571 + { .ocv = 3352000, .capacity = 1}, 572 + { .ocv = 3300000, .capacity = 0}, 573 + }; 574 + 575 + static struct power_supply_battery_ocv_table samsung_ocv_cap_eb585157lu[] = { 576 + { .ocv = 4320000, .capacity = 100}, 577 + { .ocv = 4296000, .capacity = 99}, 578 + { .ocv = 4283000, .capacity = 98}, 579 + { .ocv = 4245000, .capacity = 95}, 580 + { .ocv = 4185000, .capacity = 90}, 581 + { .ocv = 4152000, .capacity = 87}, 582 + { .ocv = 4119000, .capacity = 84}, 583 + { .ocv = 4077000, .capacity = 80}, 584 + { .ocv = 4057000, .capacity = 78}, 585 + { .ocv = 4048000, .capacity = 77}, 586 + { .ocv = 4020000, .capacity = 74}, 587 + { .ocv = 4003000, .capacity = 72}, 588 + { .ocv = 3978000, .capacity = 69}, 589 + { .ocv = 3955000, .capacity = 66}, 590 + { .ocv = 3934000, .capacity = 63}, 591 + { .ocv = 3912000, .capacity = 60}, 592 + { .ocv = 3894000, .capacity = 58}, 593 + { .ocv = 3860000, .capacity = 55}, 594 + { .ocv = 3837000, .capacity = 52}, 595 + { .ocv = 3827000, .capacity = 50}, 596 + { .ocv = 3806000, .capacity = 45}, 597 + { .ocv = 3791000, .capacity = 40}, 598 + { .ocv = 3779000, .capacity = 35}, 599 + { .ocv = 3770000, .capacity = 30}, 600 + { .ocv = 3758000, .capacity = 25}, 601 + { .ocv = 3739000, .capacity = 20}, 602 + { .ocv = 3730000, .capacity = 18}, 603 + { .ocv = 3706000, .capacity = 15}, 604 + { .ocv = 3684000, .capacity = 13}, 605 + { .ocv = 3675000, .capacity = 10}, 606 + { .ocv = 3673000, .capacity = 9}, 607 + { .ocv = 3665000, .capacity = 7}, 608 + { .ocv = 3649000, .capacity = 5}, 609 + { .ocv = 3628000, .capacity = 4}, 610 + { .ocv = 3585000, .capacity = 3}, 611 + { .ocv = 3525000, .capacity = 2}, 612 + { .ocv = 3441000, .capacity = 1}, 613 + { .ocv = 3300000, .capacity = 0}, 614 + }; 615 + 616 + static struct power_supply_maintenance_charge_table samsung_maint_charge_table[] = { 617 + { 618 + /* Maintenance charging phase A, 60 hours */ 619 + .charge_current_max_ua = 600000, 620 + .charge_voltage_max_uv = 4150000, 621 + .charge_safety_timer_minutes = 60*60, 622 + }, 623 + { 624 + /* Maintenance charging phase B, 200 hours */ 625 + .charge_current_max_ua = 600000, 626 + .charge_voltage_max_uv = 4100000, 627 + .charge_safety_timer_minutes = 200*60, 628 + } 629 + }; 630 + 631 + static struct samsung_sdi_battery samsung_sdi_batteries[] = { 632 + { 633 + /* 634 + * Used in Samsung GT-I8190 "Golden" 635 + * Data from vendor boardfile board-golden-[bm|battery].c 636 + */ 637 + .compatible = "samsung,eb-l1m7flu", 638 + .name = "EB-L1M7FLU", 639 + .info = { 640 + .charge_full_design_uah = 1500000, 641 + .technology = POWER_SUPPLY_TECHNOLOGY_LION, 642 + .factory_internal_resistance_uohm = 100000, 643 + .factory_internal_resistance_charging_uohm = 200000, 644 + /* If you have data on this fix the min_design_uv */ 645 + .voltage_min_design_uv = 3320000, 646 + .voltage_max_design_uv = 4340000, 647 + .overvoltage_limit_uv = 4500000, 648 + .constant_charge_current_max_ua = 900000, 649 + .constant_charge_voltage_max_uv = 4320000, 650 + .charge_term_current_ua = 200000, 651 + .charge_restart_voltage_uv = 4300000, 652 + .maintenance_charge = samsung_maint_charge_table, 653 + .maintenance_charge_size = ARRAY_SIZE(samsung_maint_charge_table), 654 + .alert_low_temp_charge_current_ua = 300000, 655 + .alert_low_temp_charge_voltage_uv = 4000000, 656 + .alert_high_temp_charge_current_ua = 300000, 657 + .alert_high_temp_charge_voltage_uv = 4000000, 658 + .temp_min = -50, 659 + .temp_alert_min = 0, 660 + .temp_alert_max = 40, 661 + .temp_max = 60, 662 + .resist_table = samsung_temp2res, 663 + .resist_table_size = ARRAY_SIZE(samsung_temp2res), 664 + /* If you have tables for more temperatures, add them */ 665 + .ocv_temp[0] = 25, 666 + .ocv_table[0] = samsung_ocv_cap_1500mah, 667 + .ocv_table_size[0] = ARRAY_SIZE(samsung_ocv_cap_1500mah), 668 + .vbat2ri_discharging = samsung_vbat2res_discharging_eb_l1m7flu, 669 + .vbat2ri_discharging_size = ARRAY_SIZE(samsung_vbat2res_discharging_eb_l1m7flu), 670 + .vbat2ri_charging = samsung_vbat2res_charging_eb_l1m7flu, 671 + .vbat2ri_charging_size = ARRAY_SIZE(samsung_vbat2res_charging_eb_l1m7flu), 672 + .bti_resistance_ohm = 2400, 673 + .bti_resistance_tolerance = 40, 674 + }, 675 + }, 676 + { 677 + /* 678 + * Used in Samsung SGH-T599 "Codina TMO" and SGH-I407 "Kyle" 679 + * Data from vendor boardfile board-kyle-[bm|battery].c 680 + */ 681 + .compatible = "samsung,eb425161la", 682 + .name = "EB425161LA", 683 + .info = { 684 + .charge_full_design_uah = 1500000, 685 + .technology = POWER_SUPPLY_TECHNOLOGY_LION, 686 + .factory_internal_resistance_uohm = 136000, 687 + .factory_internal_resistance_charging_uohm = 200000, 688 + /* If you have data on this fix the min_design_uv */ 689 + .voltage_min_design_uv = 3320000, 690 + .voltage_max_design_uv = 4340000, 691 + .overvoltage_limit_uv = 4500000, 692 + .constant_charge_current_max_ua = 900000, 693 + .constant_charge_voltage_max_uv = 4320000, 694 + .charge_term_current_ua = 200000, 695 + .charge_restart_voltage_uv = 4270000, 696 + .maintenance_charge = samsung_maint_charge_table, 697 + .maintenance_charge_size = ARRAY_SIZE(samsung_maint_charge_table), 698 + .alert_low_temp_charge_current_ua = 300000, 699 + .alert_low_temp_charge_voltage_uv = 4000000, 700 + .alert_high_temp_charge_current_ua = 300000, 701 + .alert_high_temp_charge_voltage_uv = 4000000, 702 + .temp_min = -30, 703 + .temp_alert_min = 0, 704 + .temp_alert_max = 40, 705 + .temp_max = 47, 706 + .resist_table = samsung_temp2res, 707 + .resist_table_size = ARRAY_SIZE(samsung_temp2res), 708 + /* If you have tables for more temperatures, add them */ 709 + .ocv_temp[0] = 25, 710 + .ocv_table[0] = samsung_ocv_cap_1500mah, 711 + .ocv_table_size[0] = ARRAY_SIZE(samsung_ocv_cap_1500mah), 712 + .vbat2ri_discharging = samsung_vbat2res_discharging_eb425161la, 713 + .vbat2ri_discharging_size = ARRAY_SIZE(samsung_vbat2res_discharging_eb425161la), 714 + .vbat2ri_charging = samsung_vbat2res_charging_eb425161la, 715 + .vbat2ri_charging_size = ARRAY_SIZE(samsung_vbat2res_charging_eb425161la), 716 + .bti_resistance_ohm = 2400, 717 + .bti_resistance_tolerance = 40, 718 + }, 719 + }, 720 + { 721 + /* 722 + * Used in Samsung GT-I8160 "Codina" 723 + * Data from vendor boardfile board-codina-[bm|battery].c 724 + */ 725 + .compatible = "samsung,eb425161lu", 726 + .name = "EB425161LU", 727 + .info = { 728 + .charge_full_design_uah = 1500000, 729 + .technology = POWER_SUPPLY_TECHNOLOGY_LION, 730 + .factory_internal_resistance_uohm = 100000, 731 + .factory_internal_resistance_charging_uohm = 200000, 732 + /* If you have data on this fix the min_design_uv */ 733 + .voltage_min_design_uv = 3320000, 734 + .voltage_max_design_uv = 4350000, 735 + .overvoltage_limit_uv = 4500000, 736 + .constant_charge_current_max_ua = 900000, 737 + .constant_charge_voltage_max_uv = 4340000, 738 + .charge_term_current_ua = 200000, 739 + .charge_restart_voltage_uv = 4280000, 740 + .maintenance_charge = samsung_maint_charge_table, 741 + .maintenance_charge_size = ARRAY_SIZE(samsung_maint_charge_table), 742 + .alert_low_temp_charge_current_ua = 300000, 743 + .alert_low_temp_charge_voltage_uv = 4000000, 744 + .alert_high_temp_charge_current_ua = 300000, 745 + .alert_high_temp_charge_voltage_uv = 4000000, 746 + .temp_min = -50, 747 + .temp_alert_min = 0, 748 + .temp_alert_max = 43, 749 + .temp_max = 49, 750 + .resist_table = samsung_temp2res, 751 + .resist_table_size = ARRAY_SIZE(samsung_temp2res), 752 + /* If you have tables for more temperatures, add them */ 753 + .ocv_temp[0] = 25, 754 + .ocv_table[0] = samsung_ocv_cap_1500mah, 755 + .ocv_table_size[0] = ARRAY_SIZE(samsung_ocv_cap_1500mah), 756 + .vbat2ri_discharging = samsung_vbat2res_discharging_eb425161lu, 757 + .vbat2ri_discharging_size = ARRAY_SIZE(samsung_vbat2res_discharging_eb425161lu), 758 + .vbat2ri_charging = samsung_vbat2res_charging_eb425161lu, 759 + .vbat2ri_charging_size = ARRAY_SIZE(samsung_vbat2res_charging_eb425161lu), 760 + .bti_resistance_ohm = 2400, 761 + .bti_resistance_tolerance = 40, 762 + }, 763 + }, 764 + { 765 + /* 766 + * Used in Samsung GT-S7710 "Skomer" 767 + * Data from vendor boardfile board-skomer-[bm|battery].c 768 + */ 769 + .compatible = "samsung,eb485159lu", 770 + .name = "EB485159LU", 771 + .info = { 772 + .charge_full_design_uah = 1700000, 773 + .technology = POWER_SUPPLY_TECHNOLOGY_LION, 774 + .factory_internal_resistance_uohm = 100000, 775 + .factory_internal_resistance_charging_uohm = 200000, 776 + .voltage_min_design_uv = 3320000, 777 + .voltage_max_design_uv = 4350000, 778 + .overvoltage_limit_uv = 4500000, 779 + .constant_charge_current_max_ua = 900000, 780 + .constant_charge_voltage_max_uv = 4340000, 781 + .charge_term_current_ua = 200000, 782 + .charge_restart_voltage_uv = 4300000, 783 + .maintenance_charge = samsung_maint_charge_table, 784 + .maintenance_charge_size = ARRAY_SIZE(samsung_maint_charge_table), 785 + .alert_low_temp_charge_current_ua = 300000, 786 + .alert_low_temp_charge_voltage_uv = 4000000, 787 + .alert_high_temp_charge_current_ua = 300000, 788 + .alert_high_temp_charge_voltage_uv = 4000000, 789 + .temp_min = -50, 790 + .temp_alert_min = 0, 791 + .temp_alert_max = 40, 792 + .temp_max = 60, 793 + .resist_table = samsung_temp2res, 794 + .resist_table_size = ARRAY_SIZE(samsung_temp2res), 795 + /* If you have tables for more temperatures, add them */ 796 + .ocv_temp[0] = 25, 797 + .ocv_table[0] = samsung_ocv_cap_eb485159lu, 798 + .ocv_table_size[0] = ARRAY_SIZE(samsung_ocv_cap_eb485159lu), 799 + /* CHECKME: vendor uses the 1500 mAh table, check against datasheet */ 800 + .vbat2ri_discharging = samsung_vbat2res_discharging_eb485159lu, 801 + .vbat2ri_discharging_size = ARRAY_SIZE(samsung_vbat2res_discharging_eb485159lu), 802 + .vbat2ri_charging = samsung_vbat2res_charging_eb485159lu, 803 + .vbat2ri_charging_size = ARRAY_SIZE(samsung_vbat2res_charging_eb485159lu), 804 + .bti_resistance_ohm = 2400, 805 + .bti_resistance_tolerance = 40, 806 + }, 807 + }, 808 + { 809 + /* 810 + * Used in Samsung GT-I9070 "Janice" 811 + * Data from vendor boardfile board-janice-bm.c 812 + */ 813 + .compatible = "samsung,eb535151vu", 814 + .name = "EB535151VU", 815 + .info = { 816 + .charge_full_design_uah = 1500000, 817 + .technology = POWER_SUPPLY_TECHNOLOGY_LION, 818 + .factory_internal_resistance_uohm = 100000, 819 + .factory_internal_resistance_charging_uohm = 200000, 820 + /* If you have data on this fix the min_design_uv */ 821 + .voltage_min_design_uv = 3300000, 822 + .voltage_max_design_uv = 4180000, 823 + .overvoltage_limit_uv = 4500000, 824 + .constant_charge_current_max_ua = 900000, 825 + .constant_charge_voltage_max_uv = 4200000, 826 + .charge_term_current_ua = 200000, 827 + .maintenance_charge = samsung_maint_charge_table, 828 + .maintenance_charge_size = ARRAY_SIZE(samsung_maint_charge_table), 829 + .alert_low_temp_charge_current_ua = 300000, 830 + .alert_low_temp_charge_voltage_uv = 4000000, 831 + .alert_high_temp_charge_current_ua = 300000, 832 + .alert_high_temp_charge_voltage_uv = 4000000, 833 + .temp_min = -5, 834 + .temp_alert_min = 0, 835 + .temp_alert_max = 40, 836 + .temp_max = 60, 837 + .resist_table = samsung_temp2res, 838 + .resist_table_size = ARRAY_SIZE(samsung_temp2res), 839 + /* If you have tables for more temperatures, add them */ 840 + .ocv_temp[0] = 25, 841 + .ocv_table[0] = samsung_ocv_cap_eb535151vu, 842 + .ocv_table_size[0] = ARRAY_SIZE(samsung_ocv_cap_eb535151vu), 843 + .vbat2ri_discharging = samsung_vbat2res_discharging_eb535151vu, 844 + .vbat2ri_discharging_size = ARRAY_SIZE(samsung_vbat2res_discharging_eb535151vu), 845 + .vbat2ri_charging = samsung_vbat2res_charging_eb535151vu, 846 + .vbat2ri_charging_size = ARRAY_SIZE(samsung_vbat2res_charging_eb535151vu), 847 + .bti_resistance_ohm = 1500, 848 + .bti_resistance_tolerance = 40, 849 + }, 850 + }, 851 + { 852 + /* 853 + * Used in Samsung GT-I8530 "Gavini" 854 + * Data from vendor boardfile board-gavini-bm.c 855 + */ 856 + .compatible = "samsung,eb585157lu", 857 + .name = "EB585157LU", 858 + .info = { 859 + .charge_full_design_uah = 2000000, 860 + .technology = POWER_SUPPLY_TECHNOLOGY_LION, 861 + .factory_internal_resistance_uohm = 105000, 862 + .factory_internal_resistance_charging_uohm = 160000, 863 + /* If you have data on this fix the min_design_uv */ 864 + .voltage_min_design_uv = 3300000, 865 + .voltage_max_design_uv = 4320000, 866 + .overvoltage_limit_uv = 4500000, 867 + .constant_charge_current_max_ua = 1500000, 868 + .constant_charge_voltage_max_uv = 4350000, 869 + .charge_term_current_ua = 120000, 870 + .maintenance_charge = samsung_maint_charge_table, 871 + .maintenance_charge_size = ARRAY_SIZE(samsung_maint_charge_table), 872 + .alert_low_temp_charge_current_ua = 300000, 873 + .alert_low_temp_charge_voltage_uv = 4000000, 874 + .alert_high_temp_charge_current_ua = 300000, 875 + .alert_high_temp_charge_voltage_uv = 4000000, 876 + .temp_min = -5, 877 + .temp_alert_min = 0, 878 + .temp_alert_max = 40, 879 + .temp_max = 60, 880 + .resist_table = samsung_temp2res, 881 + .resist_table_size = ARRAY_SIZE(samsung_temp2res), 882 + /* If you have tables for more temperatures, add them */ 883 + .ocv_temp[0] = 25, 884 + .ocv_table[0] = samsung_ocv_cap_eb585157lu, 885 + .ocv_table_size[0] = ARRAY_SIZE(samsung_ocv_cap_eb585157lu), 886 + .vbat2ri_discharging = samsung_vbat2res_discharging_eb585157lu, 887 + .vbat2ri_discharging_size = ARRAY_SIZE(samsung_vbat2res_discharging_eb585157lu), 888 + .vbat2ri_charging = samsung_vbat2res_charging_eb585157lu, 889 + .vbat2ri_charging_size = ARRAY_SIZE(samsung_vbat2res_charging_eb585157lu), 890 + .bti_resistance_ohm = 2400, 891 + .bti_resistance_tolerance = 40, 892 + }, 893 + }, 894 + }; 895 + 896 + int samsung_sdi_battery_get_info(struct device *dev, 897 + const char *compatible, 898 + struct power_supply_battery_info **info) 899 + { 900 + struct samsung_sdi_battery *batt; 901 + int i; 902 + 903 + for (i = 0; i < ARRAY_SIZE(samsung_sdi_batteries); i++) { 904 + batt = &samsung_sdi_batteries[i]; 905 + if (!strcmp(compatible, batt->compatible)) 906 + break; 907 + } 908 + 909 + if (i == ARRAY_SIZE(samsung_sdi_batteries)) 910 + return -ENODEV; 911 + 912 + *info = &batt->info; 913 + dev_info(dev, "Samsung SDI %s battery %d mAh\n", 914 + batt->name, batt->info.charge_full_design_uah / 1000); 915 + 916 + return 0; 917 + } 918 + EXPORT_SYMBOL_GPL(samsung_sdi_battery_get_info);
+13
drivers/power/supply/samsung-sdi-battery.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #if IS_ENABLED(CONFIG_BATTERY_SAMSUNG_SDI) 3 + extern int samsung_sdi_battery_get_info(struct device *dev, 4 + const char *compatible, 5 + struct power_supply_battery_info **info); 6 + #else 7 + static inline int samsung_sdi_battery_get_info(struct device *dev, 8 + const char *compatible, 9 + struct power_supply_battery_info **info) 10 + { 11 + return -ENODEV; 12 + } 13 + #endif
+7 -11
drivers/power/supply/sbs-charger.c
··· 18 18 #include <linux/interrupt.h> 19 19 #include <linux/regmap.h> 20 20 #include <linux/bitops.h> 21 + #include <linux/devm-helpers.h> 21 22 22 23 #define SBS_CHARGER_REG_SPEC_INFO 0x11 23 24 #define SBS_CHARGER_REG_STATUS 0x13 ··· 210 209 if (ret) 211 210 return dev_err_probe(&client->dev, ret, "Failed to request irq\n"); 212 211 } else { 213 - INIT_DELAYED_WORK(&chip->work, sbs_delayed_work); 212 + ret = devm_delayed_work_autocancel(&client->dev, &chip->work, 213 + sbs_delayed_work); 214 + if (ret) 215 + return dev_err_probe(&client->dev, ret, 216 + "Failed to init work for polling\n"); 217 + 214 218 schedule_delayed_work(&chip->work, 215 219 msecs_to_jiffies(SBS_CHARGER_POLL_TIME)); 216 220 } 217 221 218 222 dev_info(&client->dev, 219 223 "%s: smart charger device registered\n", client->name); 220 - 221 - return 0; 222 - } 223 - 224 - static int sbs_remove(struct i2c_client *client) 225 - { 226 - struct sbs_info *chip = i2c_get_clientdata(client); 227 - 228 - cancel_delayed_work_sync(&chip->work); 229 224 230 225 return 0; 231 226 } ··· 242 245 243 246 static struct i2c_driver sbs_driver = { 244 247 .probe = sbs_probe, 245 - .remove = sbs_remove, 246 248 .id_table = sbs_id, 247 249 .driver = { 248 250 .name = "sbs-charger",
+1 -2
drivers/power/supply/smb347-charger.c
··· 1488 1488 .max_register = SMB347_MAX_REGISTER, 1489 1489 .volatile_reg = smb347_volatile_reg, 1490 1490 .readable_reg = smb347_readable_reg, 1491 - .cache_type = REGCACHE_FLAT, 1492 - .num_reg_defaults_raw = SMB347_MAX_REGISTER, 1491 + .cache_type = REGCACHE_RBTREE, 1493 1492 }; 1494 1493 1495 1494 static const struct regulator_ops smb347_usb_vbus_regulator_ops = {
+486
drivers/power/supply/ug3105_battery.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Battery monitor driver for the uPI uG3105 battery monitor 4 + * 5 + * Note the uG3105 is not a full-featured autonomous fuel-gauge. Instead it is 6 + * expected to be use in combination with some always on microcontroller reading 7 + * its coulomb-counter before it can wrap (must be read every 400 seconds!). 8 + * 9 + * Since Linux does not monitor coulomb-counter changes while the device 10 + * is off or suspended, the coulomb counter is not used atm. 11 + * 12 + * Possible improvements: 13 + * 1. Activate commented out total_coulomb_count code 14 + * 2. Reset total_coulomb_count val to 0 when the battery is as good as empty 15 + * and remember that we did this (and clear the flag for this on susp/resume) 16 + * 3. When the battery is full check if the flag that we set total_coulomb_count 17 + * to when the battery was empty is set. If so we now know the capacity, 18 + * not the design, but actual capacity, of the battery 19 + * 4. Add some mechanism (needs userspace help, or maybe use efivar?) to remember 20 + * the actual capacity of the battery over reboots 21 + * 5. When we know the actual capacity at probe time, add energy_now and 22 + * energy_full attributes. Guess boot + resume energy_now value based on ocv 23 + * and then use total_coulomb_count to report energy_now over time, resetting 24 + * things to adjust for drift when empty/full. This should give more accurate 25 + * readings, esp. in the 30-70% range and allow userspace to estimate time 26 + * remaining till empty/full 27 + * 6. Maybe unregister + reregister the psy device when we learn the actual 28 + * capacity during run-time ? 29 + * 30 + * The above will also require some sort of mwh_per_unit calculation. Testing 31 + * has shown that an estimated 7404mWh increase of the battery's energy results 32 + * in a total_coulomb_count increase of 3277 units with a 5 milli-ohm sense R. 33 + * 34 + * Copyright (C) 2021 Hans de Goede <hdegoede@redhat.com> 35 + */ 36 + 37 + #include <linux/devm-helpers.h> 38 + #include <linux/module.h> 39 + #include <linux/mutex.h> 40 + #include <linux/slab.h> 41 + #include <linux/i2c.h> 42 + #include <linux/mod_devicetable.h> 43 + #include <linux/power_supply.h> 44 + #include <linux/workqueue.h> 45 + 46 + #define UG3105_MOV_AVG_WINDOW 8 47 + #define UG3105_INIT_POLL_TIME (5 * HZ) 48 + #define UG3105_POLL_TIME (30 * HZ) 49 + #define UG3105_SETTLE_TIME (1 * HZ) 50 + 51 + #define UG3105_INIT_POLL_COUNT 30 52 + 53 + #define UG3105_REG_MODE 0x00 54 + #define UG3105_REG_CTRL1 0x01 55 + #define UG3105_REG_COULOMB_CNT 0x02 56 + #define UG3105_REG_BAT_VOLT 0x08 57 + #define UG3105_REG_BAT_CURR 0x0c 58 + 59 + #define UG3105_MODE_STANDBY 0x00 60 + #define UG3105_MODE_RUN 0x10 61 + 62 + #define UG3105_CTRL1_RESET_COULOMB_CNT 0x03 63 + 64 + #define UG3105_CURR_HYST_UA 65000 65 + 66 + #define UG3105_LOW_BAT_UV 3700000 67 + #define UG3105_FULL_BAT_HYST_UV 38000 68 + 69 + struct ug3105_chip { 70 + struct i2c_client *client; 71 + struct power_supply *psy; 72 + struct power_supply_battery_info *info; 73 + struct delayed_work work; 74 + struct mutex lock; 75 + int ocv[UG3105_MOV_AVG_WINDOW]; /* micro-volt */ 76 + int intern_res[UG3105_MOV_AVG_WINDOW]; /* milli-ohm */ 77 + int poll_count; 78 + int ocv_avg_index; 79 + int ocv_avg; /* micro-volt */ 80 + int intern_res_poll_count; 81 + int intern_res_avg_index; 82 + int intern_res_avg; /* milli-ohm */ 83 + int volt; /* micro-volt */ 84 + int curr; /* micro-ampere */ 85 + int total_coulomb_count; 86 + int uv_per_unit; 87 + int ua_per_unit; 88 + int status; 89 + int capacity; 90 + bool supplied; 91 + }; 92 + 93 + static int ug3105_read_word(struct i2c_client *client, u8 reg) 94 + { 95 + int val; 96 + 97 + val = i2c_smbus_read_word_data(client, reg); 98 + if (val < 0) 99 + dev_err(&client->dev, "Error reading reg 0x%02x\n", reg); 100 + 101 + return val; 102 + } 103 + 104 + static int ug3105_get_status(struct ug3105_chip *chip) 105 + { 106 + int full = chip->info->constant_charge_voltage_max_uv - UG3105_FULL_BAT_HYST_UV; 107 + 108 + if (chip->curr > UG3105_CURR_HYST_UA) 109 + return POWER_SUPPLY_STATUS_CHARGING; 110 + 111 + if (chip->curr < -UG3105_CURR_HYST_UA) 112 + return POWER_SUPPLY_STATUS_DISCHARGING; 113 + 114 + if (chip->supplied && chip->ocv_avg > full) 115 + return POWER_SUPPLY_STATUS_FULL; 116 + 117 + return POWER_SUPPLY_STATUS_NOT_CHARGING; 118 + } 119 + 120 + static int ug3105_get_capacity(struct ug3105_chip *chip) 121 + { 122 + /* 123 + * OCV voltages in uV for 0-110% in 5% increments, the 100-110% is 124 + * for LiPo HV (High-Voltage) bateries which can go up to 4.35V 125 + * instead of the usual 4.2V. 126 + */ 127 + static const int ocv_capacity_tbl[23] = { 128 + 3350000, 129 + 3610000, 130 + 3690000, 131 + 3710000, 132 + 3730000, 133 + 3750000, 134 + 3770000, 135 + 3786667, 136 + 3803333, 137 + 3820000, 138 + 3836667, 139 + 3853333, 140 + 3870000, 141 + 3907500, 142 + 3945000, 143 + 3982500, 144 + 4020000, 145 + 4075000, 146 + 4110000, 147 + 4150000, 148 + 4200000, 149 + 4250000, 150 + 4300000, 151 + }; 152 + int i, ocv_diff, ocv_step; 153 + 154 + if (chip->ocv_avg < ocv_capacity_tbl[0]) 155 + return 0; 156 + 157 + if (chip->status == POWER_SUPPLY_STATUS_FULL) 158 + return 100; 159 + 160 + for (i = 1; i < ARRAY_SIZE(ocv_capacity_tbl); i++) { 161 + if (chip->ocv_avg > ocv_capacity_tbl[i]) 162 + continue; 163 + 164 + ocv_diff = ocv_capacity_tbl[i] - chip->ocv_avg; 165 + ocv_step = ocv_capacity_tbl[i] - ocv_capacity_tbl[i - 1]; 166 + /* scale 0-110% down to 0-100% for LiPo HV */ 167 + if (chip->info->constant_charge_voltage_max_uv >= 4300000) 168 + return (i * 500 - ocv_diff * 500 / ocv_step) / 110; 169 + else 170 + return i * 5 - ocv_diff * 5 / ocv_step; 171 + } 172 + 173 + return 100; 174 + } 175 + 176 + static void ug3105_work(struct work_struct *work) 177 + { 178 + struct ug3105_chip *chip = container_of(work, struct ug3105_chip, 179 + work.work); 180 + int i, val, curr_diff, volt_diff, res, win_size; 181 + bool prev_supplied = chip->supplied; 182 + int prev_status = chip->status; 183 + int prev_volt = chip->volt; 184 + int prev_curr = chip->curr; 185 + struct power_supply *psy; 186 + 187 + mutex_lock(&chip->lock); 188 + 189 + psy = chip->psy; 190 + if (!psy) 191 + goto out; 192 + 193 + val = ug3105_read_word(chip->client, UG3105_REG_BAT_VOLT); 194 + if (val < 0) 195 + goto out; 196 + chip->volt = val * chip->uv_per_unit; 197 + 198 + val = ug3105_read_word(chip->client, UG3105_REG_BAT_CURR); 199 + if (val < 0) 200 + goto out; 201 + chip->curr = (s16)val * chip->ua_per_unit; 202 + 203 + chip->ocv[chip->ocv_avg_index] = 204 + chip->volt - chip->curr * chip->intern_res_avg / 1000; 205 + chip->ocv_avg_index = (chip->ocv_avg_index + 1) % UG3105_MOV_AVG_WINDOW; 206 + chip->poll_count++; 207 + 208 + /* 209 + * See possible improvements comment above. 210 + * 211 + * Read + reset coulomb counter every 10 polls (every 300 seconds) 212 + * if ((chip->poll_count % 10) == 0) { 213 + * val = ug3105_read_word(chip->client, UG3105_REG_COULOMB_CNT); 214 + * if (val < 0) 215 + * goto out; 216 + * 217 + * i2c_smbus_write_byte_data(chip->client, UG3105_REG_CTRL1, 218 + * UG3105_CTRL1_RESET_COULOMB_CNT); 219 + * 220 + * chip->total_coulomb_count += (s16)val; 221 + * dev_dbg(&chip->client->dev, "coulomb count %d total %d\n", 222 + * (s16)val, chip->total_coulomb_count); 223 + * } 224 + */ 225 + 226 + chip->ocv_avg = 0; 227 + win_size = min(chip->poll_count, UG3105_MOV_AVG_WINDOW); 228 + for (i = 0; i < win_size; i++) 229 + chip->ocv_avg += chip->ocv[i]; 230 + chip->ocv_avg /= win_size; 231 + 232 + chip->supplied = power_supply_am_i_supplied(psy); 233 + chip->status = ug3105_get_status(chip); 234 + chip->capacity = ug3105_get_capacity(chip); 235 + 236 + /* 237 + * Skip internal resistance calc on charger [un]plug and 238 + * when the battery is almost empty (voltage low). 239 + */ 240 + if (chip->supplied != prev_supplied || 241 + chip->volt < UG3105_LOW_BAT_UV || 242 + chip->poll_count < 2) 243 + goto out; 244 + 245 + /* 246 + * Assuming that the OCV voltage does not change significantly 247 + * between 2 polls, then we can calculate the internal resistance 248 + * on a significant current change by attributing all voltage 249 + * change between the 2 readings to the internal resistance. 250 + */ 251 + curr_diff = abs(chip->curr - prev_curr); 252 + if (curr_diff < UG3105_CURR_HYST_UA) 253 + goto out; 254 + 255 + volt_diff = abs(chip->volt - prev_volt); 256 + res = volt_diff * 1000 / curr_diff; 257 + 258 + if ((res < (chip->intern_res_avg * 2 / 3)) || 259 + (res > (chip->intern_res_avg * 4 / 3))) { 260 + dev_dbg(&chip->client->dev, "Ignoring outlier internal resistance %d mOhm\n", res); 261 + goto out; 262 + } 263 + 264 + dev_dbg(&chip->client->dev, "Internal resistance %d mOhm\n", res); 265 + 266 + chip->intern_res[chip->intern_res_avg_index] = res; 267 + chip->intern_res_avg_index = (chip->intern_res_avg_index + 1) % UG3105_MOV_AVG_WINDOW; 268 + chip->intern_res_poll_count++; 269 + 270 + chip->intern_res_avg = 0; 271 + win_size = min(chip->intern_res_poll_count, UG3105_MOV_AVG_WINDOW); 272 + for (i = 0; i < win_size; i++) 273 + chip->intern_res_avg += chip->intern_res[i]; 274 + chip->intern_res_avg /= win_size; 275 + 276 + out: 277 + mutex_unlock(&chip->lock); 278 + 279 + queue_delayed_work(system_wq, &chip->work, 280 + (chip->poll_count <= UG3105_INIT_POLL_COUNT) ? 281 + UG3105_INIT_POLL_TIME : UG3105_POLL_TIME); 282 + 283 + if (chip->status != prev_status && psy) 284 + power_supply_changed(psy); 285 + } 286 + 287 + static enum power_supply_property ug3105_battery_props[] = { 288 + POWER_SUPPLY_PROP_STATUS, 289 + POWER_SUPPLY_PROP_PRESENT, 290 + POWER_SUPPLY_PROP_TECHNOLOGY, 291 + POWER_SUPPLY_PROP_SCOPE, 292 + POWER_SUPPLY_PROP_VOLTAGE_NOW, 293 + POWER_SUPPLY_PROP_VOLTAGE_OCV, 294 + POWER_SUPPLY_PROP_CURRENT_NOW, 295 + POWER_SUPPLY_PROP_CAPACITY, 296 + }; 297 + 298 + static int ug3105_get_property(struct power_supply *psy, 299 + enum power_supply_property psp, 300 + union power_supply_propval *val) 301 + { 302 + struct ug3105_chip *chip = power_supply_get_drvdata(psy); 303 + int ret = 0; 304 + 305 + mutex_lock(&chip->lock); 306 + 307 + if (!chip->psy) { 308 + ret = -EAGAIN; 309 + goto out; 310 + } 311 + 312 + switch (psp) { 313 + case POWER_SUPPLY_PROP_STATUS: 314 + val->intval = chip->status; 315 + break; 316 + case POWER_SUPPLY_PROP_PRESENT: 317 + val->intval = 1; 318 + break; 319 + case POWER_SUPPLY_PROP_TECHNOLOGY: 320 + val->intval = chip->info->technology; 321 + break; 322 + case POWER_SUPPLY_PROP_SCOPE: 323 + val->intval = POWER_SUPPLY_SCOPE_SYSTEM; 324 + break; 325 + case POWER_SUPPLY_PROP_VOLTAGE_NOW: 326 + ret = ug3105_read_word(chip->client, UG3105_REG_BAT_VOLT); 327 + if (ret < 0) 328 + break; 329 + val->intval = ret * chip->uv_per_unit; 330 + ret = 0; 331 + break; 332 + case POWER_SUPPLY_PROP_VOLTAGE_OCV: 333 + val->intval = chip->ocv_avg; 334 + break; 335 + case POWER_SUPPLY_PROP_CURRENT_NOW: 336 + ret = ug3105_read_word(chip->client, UG3105_REG_BAT_CURR); 337 + if (ret < 0) 338 + break; 339 + val->intval = (s16)ret * chip->ua_per_unit; 340 + ret = 0; 341 + break; 342 + case POWER_SUPPLY_PROP_CAPACITY: 343 + val->intval = chip->capacity; 344 + break; 345 + default: 346 + ret = -EINVAL; 347 + } 348 + 349 + out: 350 + mutex_unlock(&chip->lock); 351 + return ret; 352 + } 353 + 354 + static void ug3105_external_power_changed(struct power_supply *psy) 355 + { 356 + struct ug3105_chip *chip = power_supply_get_drvdata(psy); 357 + 358 + dev_dbg(&chip->client->dev, "external power changed\n"); 359 + mod_delayed_work(system_wq, &chip->work, UG3105_SETTLE_TIME); 360 + } 361 + 362 + static const struct power_supply_desc ug3105_psy_desc = { 363 + .name = "ug3105_battery", 364 + .type = POWER_SUPPLY_TYPE_BATTERY, 365 + .get_property = ug3105_get_property, 366 + .external_power_changed = ug3105_external_power_changed, 367 + .properties = ug3105_battery_props, 368 + .num_properties = ARRAY_SIZE(ug3105_battery_props), 369 + }; 370 + 371 + static void ug3105_init(struct ug3105_chip *chip) 372 + { 373 + chip->poll_count = 0; 374 + chip->ocv_avg_index = 0; 375 + chip->total_coulomb_count = 0; 376 + i2c_smbus_write_byte_data(chip->client, UG3105_REG_MODE, 377 + UG3105_MODE_RUN); 378 + i2c_smbus_write_byte_data(chip->client, UG3105_REG_CTRL1, 379 + UG3105_CTRL1_RESET_COULOMB_CNT); 380 + queue_delayed_work(system_wq, &chip->work, 0); 381 + flush_delayed_work(&chip->work); 382 + } 383 + 384 + static int ug3105_probe(struct i2c_client *client) 385 + { 386 + struct power_supply_config psy_cfg = {}; 387 + struct device *dev = &client->dev; 388 + u32 curr_sense_res_uohm = 10000; 389 + struct power_supply *psy; 390 + struct ug3105_chip *chip; 391 + int ret; 392 + 393 + chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); 394 + if (!chip) 395 + return -ENOMEM; 396 + 397 + chip->client = client; 398 + mutex_init(&chip->lock); 399 + ret = devm_delayed_work_autocancel(dev, &chip->work, ug3105_work); 400 + if (ret) 401 + return ret; 402 + 403 + psy_cfg.drv_data = chip; 404 + psy = devm_power_supply_register(dev, &ug3105_psy_desc, &psy_cfg); 405 + if (IS_ERR(psy)) 406 + return PTR_ERR(psy); 407 + 408 + ret = power_supply_get_battery_info(psy, &chip->info); 409 + if (ret) 410 + return ret; 411 + 412 + if (chip->info->factory_internal_resistance_uohm == -EINVAL || 413 + chip->info->constant_charge_voltage_max_uv == -EINVAL) { 414 + dev_err(dev, "error required properties are missing\n"); 415 + return -ENODEV; 416 + } 417 + 418 + device_property_read_u32(dev, "upisemi,rsns-microohm", &curr_sense_res_uohm); 419 + 420 + /* 421 + * DAC maximum is 4.5V divided by 65536 steps + an unknown factor of 10 422 + * coming from somewhere for some reason (verified with a volt-meter). 423 + */ 424 + chip->uv_per_unit = 45000000/65536; 425 + /* Datasheet says 8.1 uV per unit for the current ADC */ 426 + chip->ua_per_unit = 8100000 / curr_sense_res_uohm; 427 + 428 + /* Use provided internal resistance as start point (in milli-ohm) */ 429 + chip->intern_res_avg = chip->info->factory_internal_resistance_uohm / 1000; 430 + /* Also add it to the internal resistance moving average window */ 431 + chip->intern_res[0] = chip->intern_res_avg; 432 + chip->intern_res_avg_index = 1; 433 + chip->intern_res_poll_count = 1; 434 + 435 + mutex_lock(&chip->lock); 436 + chip->psy = psy; 437 + mutex_unlock(&chip->lock); 438 + 439 + ug3105_init(chip); 440 + 441 + i2c_set_clientdata(client, chip); 442 + return 0; 443 + } 444 + 445 + static int __maybe_unused ug3105_suspend(struct device *dev) 446 + { 447 + struct ug3105_chip *chip = dev_get_drvdata(dev); 448 + 449 + cancel_delayed_work_sync(&chip->work); 450 + i2c_smbus_write_byte_data(chip->client, UG3105_REG_MODE, 451 + UG3105_MODE_STANDBY); 452 + 453 + return 0; 454 + } 455 + 456 + static int __maybe_unused ug3105_resume(struct device *dev) 457 + { 458 + struct ug3105_chip *chip = dev_get_drvdata(dev); 459 + 460 + ug3105_init(chip); 461 + 462 + return 0; 463 + } 464 + 465 + static SIMPLE_DEV_PM_OPS(ug3105_pm_ops, ug3105_suspend, 466 + ug3105_resume); 467 + 468 + static const struct i2c_device_id ug3105_id[] = { 469 + { "ug3105" }, 470 + { } 471 + }; 472 + MODULE_DEVICE_TABLE(i2c, ug3105_id); 473 + 474 + static struct i2c_driver ug3105_i2c_driver = { 475 + .driver = { 476 + .name = "ug3105", 477 + .pm = &ug3105_pm_ops, 478 + }, 479 + .probe_new = ug3105_probe, 480 + .id_table = ug3105_id, 481 + }; 482 + module_i2c_driver(ug3105_i2c_driver); 483 + 484 + MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com"); 485 + MODULE_DESCRIPTION("uPI uG3105 battery monitor driver"); 486 + MODULE_LICENSE("GPL");
+83 -14
drivers/power/supply/wm8350_power.c
··· 408 408 * Initialisation 409 409 *********************************************************************/ 410 410 411 - static void wm8350_init_charger(struct wm8350 *wm8350) 411 + static int wm8350_init_charger(struct wm8350 *wm8350) 412 412 { 413 + int ret; 414 + 413 415 /* register our interest in charger events */ 414 - wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT, 416 + ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT, 415 417 wm8350_charger_handler, 0, "Battery hot", wm8350); 416 - wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD, 418 + if (ret) 419 + goto err; 420 + 421 + ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD, 417 422 wm8350_charger_handler, 0, "Battery cold", wm8350); 418 - wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL, 423 + if (ret) 424 + goto free_chg_bat_hot; 425 + 426 + ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL, 419 427 wm8350_charger_handler, 0, "Battery fail", wm8350); 420 - wm8350_register_irq(wm8350, WM8350_IRQ_CHG_TO, 428 + if (ret) 429 + goto free_chg_bat_cold; 430 + 431 + ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_TO, 421 432 wm8350_charger_handler, 0, 422 433 "Charger timeout", wm8350); 423 - wm8350_register_irq(wm8350, WM8350_IRQ_CHG_END, 434 + if (ret) 435 + goto free_chg_bat_fail; 436 + 437 + ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_END, 424 438 wm8350_charger_handler, 0, 425 439 "Charge end", wm8350); 426 - wm8350_register_irq(wm8350, WM8350_IRQ_CHG_START, 440 + if (ret) 441 + goto free_chg_to; 442 + 443 + ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_START, 427 444 wm8350_charger_handler, 0, 428 445 "Charge start", wm8350); 429 - wm8350_register_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY, 446 + if (ret) 447 + goto free_chg_end; 448 + 449 + ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY, 430 450 wm8350_charger_handler, 0, 431 451 "Fast charge ready", wm8350); 432 - wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9, 452 + if (ret) 453 + goto free_chg_start; 454 + 455 + ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9, 433 456 wm8350_charger_handler, 0, 434 457 "Battery <3.9V", wm8350); 435 - wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1, 458 + if (ret) 459 + goto free_chg_fast_rdy; 460 + 461 + ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1, 436 462 wm8350_charger_handler, 0, 437 463 "Battery <3.1V", wm8350); 438 - wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85, 464 + if (ret) 465 + goto free_chg_vbatt_lt_3p9; 466 + 467 + ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85, 439 468 wm8350_charger_handler, 0, 440 469 "Battery <2.85V", wm8350); 470 + if (ret) 471 + goto free_chg_vbatt_lt_3p1; 441 472 442 473 /* and supply change events */ 443 - wm8350_register_irq(wm8350, WM8350_IRQ_EXT_USB_FB, 474 + ret = wm8350_register_irq(wm8350, WM8350_IRQ_EXT_USB_FB, 444 475 wm8350_charger_handler, 0, "USB", wm8350); 445 - wm8350_register_irq(wm8350, WM8350_IRQ_EXT_WALL_FB, 476 + if (ret) 477 + goto free_chg_vbatt_lt_2p85; 478 + 479 + ret = wm8350_register_irq(wm8350, WM8350_IRQ_EXT_WALL_FB, 446 480 wm8350_charger_handler, 0, "Wall", wm8350); 447 - wm8350_register_irq(wm8350, WM8350_IRQ_EXT_BAT_FB, 481 + if (ret) 482 + goto free_ext_usb_fb; 483 + 484 + ret = wm8350_register_irq(wm8350, WM8350_IRQ_EXT_BAT_FB, 448 485 wm8350_charger_handler, 0, "Battery", wm8350); 486 + if (ret) 487 + goto free_ext_wall_fb; 488 + 489 + return 0; 490 + 491 + free_ext_wall_fb: 492 + wm8350_free_irq(wm8350, WM8350_IRQ_EXT_WALL_FB, wm8350); 493 + free_ext_usb_fb: 494 + wm8350_free_irq(wm8350, WM8350_IRQ_EXT_USB_FB, wm8350); 495 + free_chg_vbatt_lt_2p85: 496 + wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85, wm8350); 497 + free_chg_vbatt_lt_3p1: 498 + wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1, wm8350); 499 + free_chg_vbatt_lt_3p9: 500 + wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9, wm8350); 501 + free_chg_fast_rdy: 502 + wm8350_free_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY, wm8350); 503 + free_chg_start: 504 + wm8350_free_irq(wm8350, WM8350_IRQ_CHG_START, wm8350); 505 + free_chg_end: 506 + wm8350_free_irq(wm8350, WM8350_IRQ_CHG_END, wm8350); 507 + free_chg_to: 508 + wm8350_free_irq(wm8350, WM8350_IRQ_CHG_TO, wm8350); 509 + free_chg_bat_fail: 510 + wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL, wm8350); 511 + free_chg_bat_cold: 512 + wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD, wm8350); 513 + free_chg_bat_hot: 514 + wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT, wm8350); 515 + err: 516 + return ret; 449 517 } 450 518 451 519 static void free_charger_irq(struct wm8350 *wm8350) ··· 524 456 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_TO, wm8350); 525 457 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_END, wm8350); 526 458 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_START, wm8350); 459 + wm8350_free_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY, wm8350); 527 460 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9, wm8350); 528 461 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1, wm8350); 529 462 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85, wm8350);
+8
include/linux/mfd/intel_soc_pmic.h
··· 13 13 14 14 #include <linux/regmap.h> 15 15 16 + enum intel_cht_wc_models { 17 + INTEL_CHT_WC_UNKNOWN, 18 + INTEL_CHT_WC_GPD_WIN_POCKET, 19 + INTEL_CHT_WC_XIAOMI_MIPAD2, 20 + INTEL_CHT_WC_LENOVO_YOGABOOK1, 21 + }; 22 + 16 23 /** 17 24 * struct intel_soc_pmic - Intel SoC PMIC data 18 25 * @irq: Master interrupt number of the parent PMIC device ··· 46 39 struct regmap_irq_chip_data *irq_chip_data_crit; 47 40 struct device *dev; 48 41 struct intel_scu_ipc_dev *scu; 42 + enum intel_cht_wc_models cht_wc_model; 49 43 }; 50 44 51 45 int intel_soc_pmic_exec_mipi_pmic_seq_element(u16 i2c_address, u32 reg_address,
+64
include/linux/platform_data/cros_ec_commands.h
··· 3386 3386 /* Send an incoming CEC message to the AP */ 3387 3387 EC_MKBP_EVENT_CEC_MESSAGE = 9, 3388 3388 3389 + /* Peripheral device charger event */ 3390 + EC_MKBP_EVENT_PCHG = 12, 3391 + 3389 3392 /* Number of MKBP events */ 3390 3393 EC_MKBP_EVENT_COUNT, 3391 3394 }; ··· 5529 5526 [PCHG_STATE_DOWNLOADING] = "DOWNLOADING", \ 5530 5527 [PCHG_STATE_CONNECTED] = "CONNECTED", \ 5531 5528 } 5529 + 5530 + /* 5531 + * Update firmware of peripheral chip 5532 + */ 5533 + #define EC_CMD_PCHG_UPDATE 0x0136 5534 + 5535 + /* Port number is encoded in bit[28:31]. */ 5536 + #define EC_MKBP_PCHG_PORT_SHIFT 28 5537 + /* Utility macro for converting MKBP event to port number. */ 5538 + #define EC_MKBP_PCHG_EVENT_TO_PORT(e) (((e) >> EC_MKBP_PCHG_PORT_SHIFT) & 0xf) 5539 + /* Utility macro for extracting event bits. */ 5540 + #define EC_MKBP_PCHG_EVENT_MASK(e) ((e) \ 5541 + & GENMASK(EC_MKBP_PCHG_PORT_SHIFT-1, 0)) 5542 + 5543 + #define EC_MKBP_PCHG_UPDATE_OPENED BIT(0) 5544 + #define EC_MKBP_PCHG_WRITE_COMPLETE BIT(1) 5545 + #define EC_MKBP_PCHG_UPDATE_CLOSED BIT(2) 5546 + #define EC_MKBP_PCHG_UPDATE_ERROR BIT(3) 5547 + #define EC_MKBP_PCHG_DEVICE_EVENT BIT(4) 5548 + 5549 + enum ec_pchg_update_cmd { 5550 + /* Reset chip to normal mode. */ 5551 + EC_PCHG_UPDATE_CMD_RESET_TO_NORMAL = 0, 5552 + /* Reset and put a chip in update (a.k.a. download) mode. */ 5553 + EC_PCHG_UPDATE_CMD_OPEN, 5554 + /* Write a block of data containing FW image. */ 5555 + EC_PCHG_UPDATE_CMD_WRITE, 5556 + /* Close update session. */ 5557 + EC_PCHG_UPDATE_CMD_CLOSE, 5558 + /* End of commands */ 5559 + EC_PCHG_UPDATE_CMD_COUNT, 5560 + }; 5561 + 5562 + struct ec_params_pchg_update { 5563 + /* PCHG port number */ 5564 + uint8_t port; 5565 + /* enum ec_pchg_update_cmd */ 5566 + uint8_t cmd; 5567 + /* Padding */ 5568 + uint8_t reserved0; 5569 + uint8_t reserved1; 5570 + /* Version of new firmware */ 5571 + uint32_t version; 5572 + /* CRC32 of new firmware */ 5573 + uint32_t crc32; 5574 + /* Address in chip memory where <data> is written to */ 5575 + uint32_t addr; 5576 + /* Size of <data> */ 5577 + uint32_t size; 5578 + /* Partial data of new firmware */ 5579 + uint8_t data[]; 5580 + } __ec_align4; 5581 + 5582 + BUILD_ASSERT(EC_PCHG_UPDATE_CMD_COUNT 5583 + < BIT(sizeof(((struct ec_params_pchg_update *)0)->cmd)*8)); 5584 + 5585 + struct ec_response_pchg_update { 5586 + /* Block size */ 5587 + uint32_t block_size; 5588 + } __ec_align4; 5589 + 5532 5590 5533 5591 /*****************************************************************************/ 5534 5592 /* Voltage regulator controls */
+15
include/linux/power/bq25890_charger.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Platform data for the TI bq25890 battery charger driver. 4 + */ 5 + 6 + #ifndef _BQ25890_CHARGER_H_ 7 + #define _BQ25890_CHARGER_H_ 8 + 9 + struct regulator_init_data; 10 + 11 + struct bq25890_platform_data { 12 + const struct regulator_init_data *regulator_init_data; 13 + }; 14 + 15 + #endif
+209 -4
include/linux/power_supply.h
··· 49 49 POWER_SUPPLY_CHARGE_TYPE_ADAPTIVE, /* dynamically adjusted speed */ 50 50 POWER_SUPPLY_CHARGE_TYPE_CUSTOM, /* use CHARGE_CONTROL_* props */ 51 51 POWER_SUPPLY_CHARGE_TYPE_LONGLIFE, /* slow speed, longer life */ 52 + POWER_SUPPLY_CHARGE_TYPE_BYPASS, /* bypassing the charger */ 52 53 }; 53 54 54 55 enum { ··· 349 348 int resistance; /* internal resistance percent */ 350 349 }; 351 350 351 + struct power_supply_vbat_ri_table { 352 + int vbat_uv; /* Battery voltage in microvolt */ 353 + int ri_uohm; /* Internal resistance in microohm */ 354 + }; 355 + 356 + /** 357 + * struct power_supply_maintenance_charge_table - setting for maintenace charging 358 + * @charge_current_max_ua: maintenance charging current that is used to keep 359 + * the charge of the battery full as current is consumed after full charging. 360 + * The corresponding charge_voltage_max_uv is used as a safeguard: when we 361 + * reach this voltage the maintenance charging current is turned off. It is 362 + * turned back on if we fall below this voltage. 363 + * @charge_voltage_max_uv: maintenance charging voltage that is usually a bit 364 + * lower than the constant_charge_voltage_max_uv. We can apply this settings 365 + * charge_current_max_ua until we get back up to this voltage. 366 + * @safety_timer_minutes: maintenance charging safety timer, with an expiry 367 + * time in minutes. We will only use maintenance charging in this setting 368 + * for a certain amount of time, then we will first move to the next 369 + * maintenance charge current and voltage pair in respective array and wait 370 + * for the next safety timer timeout, or, if we reached the last maintencance 371 + * charging setting, disable charging until we reach 372 + * charge_restart_voltage_uv and restart ordinary CC/CV charging from there. 373 + * These timers should be chosen to align with the typical discharge curve 374 + * for the battery. 375 + * 376 + * When the main CC/CV charging is complete the battery can optionally be 377 + * maintenance charged at the voltages from this table: a table of settings is 378 + * traversed using a slightly lower current and voltage than what is used for 379 + * CC/CV charging. The maintenance charging will for safety reasons not go on 380 + * indefinately: we lower the current and voltage with successive maintenance 381 + * settings, then disable charging completely after we reach the last one, 382 + * and after that we do not restart charging until we reach 383 + * charge_restart_voltage_uv (see struct power_supply_battery_info) and restart 384 + * ordinary CC/CV charging from there. 385 + * 386 + * As an example, a Samsung EB425161LA Lithium-Ion battery is CC/CV charged 387 + * at 900mA to 4340mV, then maintenance charged at 600mA and 4150mV for 388 + * 60 hours, then maintenance charged at 600mA and 4100mV for 200 hours. 389 + * After this the charge cycle is restarted waiting for 390 + * charge_restart_voltage_uv. 391 + * 392 + * For most mobile electronics this type of maintenance charging is enough for 393 + * the user to disconnect the device and make use of it before both maintenance 394 + * charging cycles are complete. 395 + */ 396 + struct power_supply_maintenance_charge_table { 397 + int charge_current_max_ua; 398 + int charge_voltage_max_uv; 399 + int charge_safety_timer_minutes; 400 + }; 401 + 352 402 #define POWER_SUPPLY_OCV_TEMP_MAX 20 353 403 354 404 /** ··· 445 393 * @constant_charge_voltage_max_uv: voltage in microvolts signifying the end of 446 394 * the CC (constant current) charging phase and the beginning of the CV 447 395 * (constant voltage) charging phase. 396 + * @maintenance_charge: an array of maintenance charging settings to be used 397 + * after the main CC/CV charging phase is complete. 398 + * @maintenance_charge_size: the number of maintenance charging settings in 399 + * maintenance_charge. 400 + * @alert_low_temp_charge_current_ua: The charging current to use if the battery 401 + * enters low alert temperature, i.e. if the internal temperature is between 402 + * temp_alert_min and temp_min. No matter the charging phase, this 403 + * and alert_high_temp_charge_voltage_uv will be applied. 404 + * @alert_low_temp_charge_voltage_uv: Same as alert_low_temp_charge_current_ua, 405 + * but for the charging voltage. 406 + * @alert_high_temp_charge_current_ua: The charging current to use if the 407 + * battery enters high alert temperature, i.e. if the internal temperature is 408 + * between temp_alert_max and temp_max. No matter the charging phase, this 409 + * and alert_high_temp_charge_voltage_uv will be applied, usually lowering 410 + * the charging current as an evasive manouver. 411 + * @alert_high_temp_charge_voltage_uv: Same as 412 + * alert_high_temp_charge_current_ua, but for the charging voltage. 448 413 * @factory_internal_resistance_uohm: the internal resistance of the battery 449 414 * at fabrication time, expressed in microohms. This resistance will vary 450 415 * depending on the lifetime and charge of the battery, so this is just a 451 - * nominal ballpark figure. 416 + * nominal ballpark figure. This internal resistance is given for the state 417 + * when the battery is discharging. 418 + * @factory_internal_resistance_charging_uohm: the internal resistance of the 419 + * battery at fabrication time while charging, expressed in microohms. 420 + * The charging process will affect the internal resistance of the battery 421 + * so this value provides a better resistance under these circumstances. 422 + * This resistance will vary depending on the lifetime and charge of the 423 + * battery, so this is just a nominal ballpark figure. 452 424 * @ocv_temp: array indicating the open circuit voltage (OCV) capacity 453 425 * temperature indices. This is an array of temperatures in degrees Celsius 454 426 * indicating which capacity table to use for a certain temperature, since ··· 510 434 * by temperature: highest temperature with lowest resistance first, lowest 511 435 * temperature with highest resistance last. 512 436 * @resist_table_size: the number of items in the resist_table. 437 + * @vbat2ri_discharging: this is a table that correlates Battery voltage (VBAT) 438 + * to internal resistance (Ri). The resistance is given in microohm for the 439 + * corresponding voltage in microvolts. The internal resistance is used to 440 + * determine the open circuit voltage so that we can determine the capacity 441 + * of the battery. These voltages to resistance tables apply when the battery 442 + * is discharging. The table must be ordered descending by voltage: highest 443 + * voltage first. 444 + * @vbat2ri_discharging_size: the number of items in the vbat2ri_discharging 445 + * table. 446 + * @vbat2ri_charging: same function as vbat2ri_discharging but for the state 447 + * when the battery is charging. Being under charge changes the battery's 448 + * internal resistance characteristics so a separate table is needed.* 449 + * The table must be ordered descending by voltage: highest voltage first. 450 + * @vbat2ri_charging_size: the number of items in the vbat2ri_charging 451 + * table. 452 + * @bti_resistance_ohm: The Battery Type Indicator (BIT) nominal resistance 453 + * in ohms for this battery, if an identification resistor is mounted 454 + * between a third battery terminal and ground. This scheme is used by a lot 455 + * of mobile device batteries. 456 + * @bti_resistance_tolerance: The tolerance in percent of the BTI resistance, 457 + * for example 10 for +/- 10%, if the bti_resistance is set to 7000 and the 458 + * tolerance is 10% we will detect a proper battery if the BTI resistance 459 + * is between 6300 and 7700 Ohm. 513 460 * 514 461 * This is the recommended struct to manage static battery parameters, 515 462 * populated by power_supply_get_battery_info(). Most platform drivers should 516 463 * use these for consistency. 517 464 * 518 465 * Its field names must correspond to elements in enum power_supply_property. 519 - * The default field value is -EINVAL. 466 + * The default field value is -EINVAL or NULL for pointers. 467 + * 468 + * CC/CV CHARGING: 520 469 * 521 470 * The charging parameters here assume a CC/CV charging scheme. This method 522 471 * is most common with Lithium Ion batteries (other methods are possible) and ··· 626 525 * Overcharging Lithium Ion cells can be DANGEROUS and lead to fire or 627 526 * explosions. 628 527 * 528 + * DETERMINING BATTERY CAPACITY: 529 + * 530 + * Several members of the struct deal with trying to determine the remaining 531 + * capacity in the battery, usually as a percentage of charge. In practice 532 + * many chargers uses a so-called fuel gauge or coloumb counter that measure 533 + * how much charge goes into the battery and how much goes out (+/- leak 534 + * consumption). This does not help if we do not know how much capacity the 535 + * battery has to begin with, such as when it is first used or was taken out 536 + * and charged in a separate charger. Therefore many capacity algorithms use 537 + * the open circuit voltage with a look-up table to determine the rough 538 + * capacity of the battery. The open circuit voltage can be conceptualized 539 + * with an ideal voltage source (V) in series with an internal resistance (Ri) 540 + * like this: 541 + * 542 + * +-------> IBAT >----------------+ 543 + * | ^ | 544 + * [ ] Ri | | 545 + * | | VBAT | 546 + * o <---------- | | 547 + * +| ^ | [ ] Rload 548 + * .---. | | | 549 + * | V | | OCV | | 550 + * '---' | | | 551 + * | | | | 552 + * GND +-------------------------------+ 553 + * 554 + * If we disconnect the load (here simplified as a fixed resistance Rload) 555 + * and measure VBAT with a infinite impedance voltage meter we will get 556 + * VBAT = OCV and this assumption is sometimes made even under load, assuming 557 + * Rload is insignificant. However this will be of dubious quality because the 558 + * load is rarely that small and Ri is strongly nonlinear depending on 559 + * temperature and how much capacity is left in the battery due to the 560 + * chemistry involved. 561 + * 562 + * In many practical applications we cannot just disconnect the battery from 563 + * the load, so instead we often try to measure the instantaneous IBAT (the 564 + * current out from the battery), estimate the Ri and thus calculate the 565 + * voltage drop over Ri and compensate like this: 566 + * 567 + * OCV = VBAT - (IBAT * Ri) 568 + * 569 + * The tables vbat2ri_discharging and vbat2ri_charging are used to determine 570 + * (by interpolation) the Ri from the VBAT under load. These curves are highly 571 + * nonlinear and may need many datapoints but can be found in datasheets for 572 + * some batteries. This gives the compensated open circuit voltage (OCV) for 573 + * the battery even under load. Using this method will also compensate for 574 + * temperature changes in the environment: this will also make the internal 575 + * resistance change, and it will affect the VBAT under load, so correlating 576 + * VBAT to Ri takes both remaining capacity and temperature into consideration. 577 + * 578 + * Alternatively a manufacturer can specify how the capacity of the battery 579 + * is dependent on the battery temperature which is the main factor affecting 580 + * Ri. As we know all checmical reactions are faster when it is warm and slower 581 + * when it is cold. You can put in 1500mAh and only get 800mAh out before the 582 + * voltage drops too low for example. This effect is also highly nonlinear and 583 + * the purpose of the table resist_table: this will take a temperature and 584 + * tell us how big percentage of Ri the specified temperature correlates to. 585 + * Usually we have 100% of the factory_internal_resistance_uohm at 25 degrees 586 + * Celsius. 587 + * 629 588 * The power supply class itself doesn't use this struct as of now. 630 589 */ 631 590 ··· 703 542 int overvoltage_limit_uv; 704 543 int constant_charge_current_max_ua; 705 544 int constant_charge_voltage_max_uv; 545 + struct power_supply_maintenance_charge_table *maintenance_charge; 546 + int maintenance_charge_size; 547 + int alert_low_temp_charge_current_ua; 548 + int alert_low_temp_charge_voltage_uv; 549 + int alert_high_temp_charge_current_ua; 550 + int alert_high_temp_charge_voltage_uv; 706 551 int factory_internal_resistance_uohm; 552 + int factory_internal_resistance_charging_uohm; 707 553 int ocv_temp[POWER_SUPPLY_OCV_TEMP_MAX]; 708 554 int temp_ambient_alert_min; 709 555 int temp_ambient_alert_max; ··· 722 554 int ocv_table_size[POWER_SUPPLY_OCV_TEMP_MAX]; 723 555 struct power_supply_resistance_temp_table *resist_table; 724 556 int resist_table_size; 557 + struct power_supply_vbat_ri_table *vbat2ri_discharging; 558 + int vbat2ri_discharging_size; 559 + struct power_supply_vbat_ri_table *vbat2ri_charging; 560 + int vbat2ri_charging_size; 561 + int bti_resistance_ohm; 562 + int bti_resistance_tolerance; 725 563 }; 726 564 727 565 extern struct atomic_notifier_head power_supply_notifier; ··· 769 595 extern int 770 596 power_supply_temp2resist_simple(struct power_supply_resistance_temp_table *table, 771 597 int table_len, int temp); 598 + extern int power_supply_vbat2ri(struct power_supply_battery_info *info, 599 + int vbat_uv, bool charging); 600 + extern struct power_supply_maintenance_charge_table * 601 + power_supply_get_maintenance_charging_setting(struct power_supply_battery_info *info, int index); 602 + extern bool power_supply_battery_bti_in_range(struct power_supply_battery_info *info, 603 + int resistance); 772 604 extern void power_supply_changed(struct power_supply *psy); 773 605 extern int power_supply_am_i_supplied(struct power_supply *psy); 774 - extern int power_supply_set_input_current_limit_from_supplier( 775 - struct power_supply *psy); 606 + int power_supply_get_property_from_supplier(struct power_supply *psy, 607 + enum power_supply_property psp, 608 + union power_supply_propval *val); 776 609 extern int power_supply_set_battery_charged(struct power_supply *psy); 610 + 611 + static inline bool 612 + power_supply_supports_maintenance_charging(struct power_supply_battery_info *info) 613 + { 614 + struct power_supply_maintenance_charge_table *mt; 615 + 616 + mt = power_supply_get_maintenance_charging_setting(info, 0); 617 + 618 + return (mt != NULL); 619 + } 620 + 621 + static inline bool 622 + power_supply_supports_vbat2ri(struct power_supply_battery_info *info) 623 + { 624 + return ((info->vbat2ri_discharging != NULL) && 625 + info->vbat2ri_discharging_size > 0); 626 + } 627 + 628 + static inline bool 629 + power_supply_supports_temp2ri(struct power_supply_battery_info *info) 630 + { 631 + return ((info->resist_table != NULL) && 632 + info->resist_table_size > 0); 633 + } 777 634 778 635 #ifdef CONFIG_POWER_SUPPLY 779 636 extern int power_supply_is_system_supplied(void);