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-v6.19' 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:
- documentation fixes

power-supply drivers:
- add BD71828 charger driver
- add Richtek RT9756 driver
- max77705: add adaptive input current support
- max77705: add support for multiple devices
- misc small fixes

reset drivers:
- add spacemit-p1 poweroff/reboot driver"

* tag 'for-v6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply:
Revert "power: supply: qcom_battmgr: support disabling charge control"
Documentation: power: rt9756: Document exported sysfs entries
power: supply: rt9756: Add Richtek RT9756 smart cap divider charger
dt-bindings: power: supply: Add Richtek RT9756 smart cap divider charger
driver: reset: spacemit-p1: add driver for poweroff/reboot
power: supply: apm_power: only unset own apm_get_power_status
power: supply: use ktime_divns() to avoid 64-bit division
docs: power: clean up power_supply_class.rst
power: supply: qcom_battmgr: support disabling charge control
power: supply: qcom_battmgr: clamp charge control thresholds
power: supply: wm831x: Check wm831x_set_bits() return value
power: supply: rt9467: Prevent using uninitialized local variable in rt9467_set_value_from_ranges()
power: supply: rt9467: Return error on failure in rt9467_set_value_from_ranges()
power: supply: max17040: Check iio_read_channel_processed() return code
power: supply: cw2015: Check devm_delayed_work_autocancel() return code
power: supply: rt5033_charger: Fix device node reference leaks
power: supply: max77705: Fix potential IRQ chip conflict when probing two devices
power: supply: max77705_charger: implement aicl feature
MAINTAINERS: Add entry for BD71828 charger
power: supply: Add bd718(15/28/78) charger driver

+2363 -64
+30
Documentation/ABI/testing/sysfs-class-power-rt9756
··· 1 + What: /sys/class/power_supply/rt9756-*/watchdog_timer 2 + Date: Dec 2025 3 + KernelVersion: 6.19 4 + Contact: ChiYuan Huang <cy_huang@richtek.com> 5 + Description: 6 + This entry shows and sets the watchdog timer when rt9756 charger 7 + operates in charging mode. When the timer expires, the device 8 + will disable the charging. To prevent the timer expires, any 9 + host communication can make the timer restarted. 10 + 11 + Access: Read, Write 12 + 13 + Valid values: 14 + - 500, 1000, 5000, 30000, 40000, 80000, 128000 or 255000 (milliseconds), 15 + - 0: disabled 16 + 17 + What: /sys/class/power_supply/rt9756-*/operation_mode 18 + Date: Dec 2025 19 + KernelVersion: 6.19 20 + Contact: ChiYuan Huang <cy_huang@richtek.com> 21 + Description: 22 + This entry shows and set the operation mode when rt9756 charger 23 + operates in charging phase. If 'bypass' mode is used, internal 24 + path will connect vbus directly to vbat. Else, default 'div2' 25 + mode for the switch-cap charging. 26 + 27 + Access: Read, Write 28 + 29 + Valid values: 30 + - 'bypass' or 'div2'
+72
Documentation/devicetree/bindings/power/supply/richtek,rt9756.yaml
··· 1 + # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/power/supply/richtek,rt9756.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Richtek RT9756 Smart Cap Divider Charger 8 + 9 + maintainers: 10 + - ChiYuan Huang <cy_huang@richtek.com> 11 + 12 + description: | 13 + The RT9756/RT9757 is a high efficiency and high charge current charger. 14 + 15 + The efficiency is up to 98.2% when VBAT = 4V, IBAT = 2A in DIV2 mode and 99.1% 16 + when VBAT=4V, IBAT=1A in bypass mode. The maximum charger current is up to 8A 17 + in DIV2 mode and 5A in bypass mode. The device integrates smart cap divider 18 + topology, direct charging mode, external over-voltage protection control, an 19 + input reverse blocking NFET and 2-way regulation, a dual phase charge pump 20 + core, 8-Channel high speed ADCs and USB BC 1.2 detection. 21 + 22 + RT9770 is almost the same with RT9756/57, only BC 1.2 detection function is 23 + removed to shrink the die size. 24 + 25 + allOf: 26 + - $ref: power-supply.yaml# 27 + 28 + properties: 29 + compatible: 30 + oneOf: 31 + - enum: 32 + - richtek,rt9756 33 + - richtek,rt9770 34 + - items: 35 + - enum: 36 + - richtek,rt9757 37 + - const: richtek,rt9756 38 + 39 + reg: 40 + maxItems: 1 41 + 42 + wakeup-source: true 43 + 44 + interrupts: 45 + maxItems: 1 46 + 47 + shunt-resistor-micro-ohms: 48 + description: Battery current sense resistor mounted. 49 + default: 2000 50 + 51 + required: 52 + - compatible 53 + - reg 54 + - interrupts 55 + 56 + unevaluatedProperties: false 57 + 58 + examples: 59 + - | 60 + #include <dt-bindings/interrupt-controller/irq.h> 61 + i2c { 62 + #address-cells = <1>; 63 + #size-cells = <0>; 64 + 65 + charger@6f { 66 + compatible = "richtek,rt9756"; 67 + reg = <0x6f>; 68 + wakeup-source; 69 + interrupts-extended = <&gpio_intc 32 IRQ_TYPE_EDGE_FALLING>; 70 + shunt-resistor-micro-ohms = <5000>; 71 + }; 72 + };
+42 -42
Documentation/power/power_supply_class.rst
··· 7 7 Power supply class used to represent battery, UPS, AC or DC power supply 8 8 properties to user-space. 9 9 10 - It defines core set of attributes, which should be applicable to (almost) 10 + It defines a core set of attributes which should be applicable to (almost) 11 11 every power supply out there. Attributes are available via sysfs and uevent 12 12 interfaces. 13 13 14 - Each attribute has well defined meaning, up to unit of measure used. While 14 + Each attribute has a well-defined meaning, up to the unit of measure used. While 15 15 the attributes provided are believed to be universally applicable to any 16 16 power supply, specific monitoring hardware may not be able to provide them 17 17 all, so any of them may be skipped. 18 18 19 - Power supply class is extensible, and allows to define drivers own attributes. 20 - The core attribute set is subject to the standard Linux evolution (i.e. 21 - if it will be found that some attribute is applicable to many power supply 22 - types or their drivers, it can be added to the core set). 19 + The power supply class is extensible and allows drivers to define their own 20 + attributes. The core attribute set is subject to the standard Linux evolution 21 + (i.e., if some attribute is found to be applicable to many power 22 + supply types or their drivers, it can be added to the core set). 23 23 24 - It also integrates with LED framework, for the purpose of providing 24 + It also integrates with the LED framework, for the purpose of providing 25 25 typically expected feedback of battery charging/fully charged status and 26 26 AC/USB power supply online status. (Note that specific details of the 27 27 indication (including whether to use it at all) are fully controllable by 28 - user and/or specific machine defaults, per design principles of LED 29 - framework). 28 + user and/or specific machine defaults, per design principles of the LED 29 + framework.) 30 30 31 31 32 32 Attributes/properties 33 33 ~~~~~~~~~~~~~~~~~~~~~ 34 - Power supply class has predefined set of attributes, this eliminates code 35 - duplication across drivers. Power supply class insist on reusing its 34 + The power supply class has a predefined set of attributes. This eliminates code 35 + duplication across drivers. The power supply class insists on reusing its 36 36 predefined attributes *and* their units. 37 37 38 - So, userspace gets predictable set of attributes and their units for any 38 + So, userspace gets a predictable set of attributes and their units for any 39 39 kind of power supply, and can process/present them to a user in consistent 40 40 manner. Results for different power supplies and machines are also directly 41 41 comparable. ··· 61 61 | **Charge/Energy/Capacity - how to not confuse** | 62 62 +--------------------------------------------------------------------------+ 63 63 | **Because both "charge" (µAh) and "energy" (µWh) represents "capacity" | 64 - | of battery, this class distinguish these terms. Don't mix them!** | 64 + | of battery, this class distinguishes these terms. Don't mix them!** | 65 65 | | 66 66 | - `CHARGE_*` | 67 67 | attributes represents capacity in µAh only. | ··· 81 81 82 82 STATUS 83 83 this attribute represents operating status (charging, full, 84 - discharging (i.e. powering a load), etc.). This corresponds to 84 + discharging (i.e., powering a load), etc.). This corresponds to 85 85 `BATTERY_STATUS_*` values, as defined in battery.h. 86 86 87 87 CHARGE_TYPE ··· 92 92 93 93 AUTHENTIC 94 94 indicates the power supply (battery or charger) connected 95 - to the platform is authentic(1) or non authentic(0). 95 + to the platform is authentic(1) or non-authentic(0). 96 96 97 97 HEALTH 98 - represents health of the battery, values corresponds to 98 + represents health of the battery. Values corresponds to 99 99 POWER_SUPPLY_HEALTH_*, defined in battery.h. 100 100 101 101 VOLTAGE_OCV ··· 103 103 104 104 VOLTAGE_MAX_DESIGN, VOLTAGE_MIN_DESIGN 105 105 design values for maximal and minimal power supply voltages. 106 - Maximal/minimal means values of voltages when battery considered 106 + Maximal/minimal means values of voltages when battery is considered 107 107 "full"/"empty" at normal conditions. Yes, there is no direct relation 108 108 between voltage and battery capacity, but some dumb 109 109 batteries use voltage for very approximated calculation of capacity. 110 - Battery driver also can use this attribute just to inform userspace 110 + A battery driver also can use this attribute just to inform userspace 111 111 about maximal and minimal voltage thresholds of a given battery. 112 112 113 113 VOLTAGE_MAX, VOLTAGE_MIN ··· 122 122 Reports the current measured during boot 123 123 124 124 CHARGE_FULL_DESIGN, CHARGE_EMPTY_DESIGN 125 - design charge values, when battery considered full/empty. 125 + design charge values, when battery is considered full/empty. 126 126 127 127 ENERGY_FULL_DESIGN, ENERGY_EMPTY_DESIGN 128 128 same as above but for energy. 129 129 130 130 CHARGE_FULL, CHARGE_EMPTY 131 - These attributes means "last remembered value of charge when battery 132 - became full/empty". It also could mean "value of charge when battery 131 + These attributes mean "last remembered value of charge when battery 132 + became full/empty". They also could mean "value of charge when battery is 133 133 considered full/empty at given conditions (temperature, age)". 134 - I.e. these attributes represents real thresholds, not design values. 134 + I.e., these attributes represents real thresholds, not design values. 135 135 136 136 ENERGY_FULL, ENERGY_EMPTY 137 137 same as above but for energy. ··· 153 153 CONSTANT_CHARGE_CURRENT 154 154 constant charge current programmed by charger. 155 155 156 - 157 156 CONSTANT_CHARGE_CURRENT_MAX 158 157 maximum charge current supported by the power supply object. 159 158 160 159 CONSTANT_CHARGE_VOLTAGE 161 160 constant charge voltage programmed by charger. 161 + 162 162 CONSTANT_CHARGE_VOLTAGE_MAX 163 163 maximum charge voltage supported by the power supply object. 164 164 ··· 208 208 209 209 TIME_TO_EMPTY 210 210 seconds left for battery to be considered empty 211 - (i.e. while battery powers a load) 211 + (i.e., while battery powers a load) 212 212 TIME_TO_FULL 213 213 seconds left for battery to be considered full 214 - (i.e. while battery is charging) 214 + (i.e., while battery is charging) 215 215 216 216 217 217 Battery <-> external power supply interaction ··· 220 220 time. Batteries are good example. So, batteries usually care if they're 221 221 externally powered or not. 222 222 223 - For that case, power supply class implements notification mechanism for 223 + For that case, the power supply class implements a notification mechanism for 224 224 batteries. 225 225 226 - External power supply (AC) lists supplicants (batteries) names in 226 + An external power supply (AC) lists supplicants (batteries) names in 227 227 "supplied_to" struct member, and each power_supply_changed() call 228 - issued by external power supply will notify supplicants via 229 - external_power_changed callback. 228 + issued by an external power supply will notify supplicants via 229 + the external_power_changed callback. 230 230 231 231 232 232 Devicetree battery characteristics ··· 241 241 for naming consistency between sysfs attributes and battery node properties. 242 242 243 243 244 - QA 245 - ~~ 244 + Q&A 245 + ~~~ 246 246 247 247 Q: 248 248 Where is POWER_SUPPLY_PROP_XYZ attribute? 249 249 A: 250 - If you cannot find attribute suitable for your driver needs, feel free 251 - to add it and send patch along with your driver. 250 + If you cannot find an attribute suitable for your driver needs, feel free 251 + to add it and send a patch along with your driver. 252 252 253 253 The attributes available currently are the ones currently provided by the 254 254 drivers written. ··· 258 258 259 259 260 260 Q: 261 - I have some very specific attribute (e.g. battery color), should I add 261 + I have some very specific attribute (e.g., battery color). Should I add 262 262 this attribute to standard ones? 263 263 A: 264 264 Most likely, no. Such attribute can be placed in the driver itself, if 265 - it is useful. Of course, if the attribute in question applicable to 266 - large set of batteries, provided by many drivers, and/or comes from 265 + it is useful. Of course, if the attribute in question is applicable to 266 + a large set of batteries, provided by many drivers, and/or comes from 267 267 some general battery specification/standard, it may be a candidate to 268 268 be added to the core attribute set. 269 269 270 270 271 271 Q: 272 - Suppose, my battery monitoring chip/firmware does not provides capacity 272 + Suppose my battery monitoring chip/firmware does not provide capacity 273 273 in percents, but provides charge_{now,full,empty}. Should I calculate 274 274 percentage capacity manually, inside the driver, and register CAPACITY 275 275 attribute? The same question about time_to_empty/time_to_full. ··· 278 278 directly measurable by the specific hardware available. 279 279 280 280 Inferring not available properties using some heuristics or mathematical 281 - model is not subject of work for a battery driver. Such functionality 281 + model is not a subject of work for a battery driver. Such functionality 282 282 should be factored out, and in fact, apm_power, the driver to serve 283 - legacy APM API on top of power supply class, uses a simple heuristic of 283 + legacy APM API on top of the power supply class, uses a simple heuristic of 284 284 approximating remaining battery capacity based on its charge, current, 285 - voltage and so on. But full-fledged battery model is likely not subject 286 - for kernel at all, as it would require floating point calculation to deal 287 - with things like differential equations and Kalman filters. This is 285 + voltage and so on. But a full-fledged battery model is likely not a subject 286 + for the kernel at all, as it would require floating point calculations to 287 + deal with things like differential equations and Kalman filters. This is 288 288 better be handled by batteryd/libbattery, yet to be written.
+6
MAINTAINERS
··· 22479 22479 S: Odd Fixes 22480 22480 F: drivers/tty/serial/rp2.* 22481 22481 22482 + ROHM BD71828 CHARGER 22483 + M: Andreas Kemnade <andreas@kemnade.info> 22484 + M: Matti Vaittinen <mazziesaccount@gmail.com> 22485 + S: Maintained 22486 + F: drivers/power/supply/bd71828-charger.c 22487 + 22482 22488 ROHM BD79703 DAC 22483 22489 M: Matti Vaittinen <mazziesaccount@gmail.com> 22484 22490 S: Supported
+9
drivers/power/reset/Kconfig
··· 283 283 help 284 284 Reboot support for the KEYSTONE SoCs. 285 285 286 + config POWER_RESET_SPACEMIT_P1 287 + tristate "SpacemiT P1 poweroff and reset driver" 288 + depends on ARCH_SPACEMIT || COMPILE_TEST 289 + depends on MFD_SPACEMIT_P1 290 + default MFD_SPACEMIT_P1 291 + help 292 + This driver supports power-off and reset operations for the SpacemiT 293 + P1 PMIC. 294 + 286 295 config POWER_RESET_SYSCON 287 296 bool "Generic SYSCON regmap reset driver" 288 297 depends on OF
+1
drivers/power/reset/Makefile
··· 24 24 obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o 25 25 obj-$(CONFIG_POWER_RESET_REGULATOR) += regulator-poweroff.o 26 26 obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o 27 + obj-$(CONFIG_POWER_RESET_SPACEMIT_P1) += spacemit-p1-reboot.o 27 28 obj-$(CONFIG_POWER_RESET_ST) += st-poweroff.o 28 29 obj-$(CONFIG_POWER_RESET_TH1520_AON) += th1520-aon-reboot.o 29 30 obj-$(CONFIG_POWER_RESET_TORADEX_EC) += tdx-ec-poweroff.o
+88
drivers/power/reset/spacemit-p1-reboot.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (C) 2025 by Aurelien Jarno 4 + */ 5 + 6 + #include <linux/bits.h> 7 + #include <linux/mod_devicetable.h> 8 + #include <linux/platform_device.h> 9 + #include <linux/regmap.h> 10 + #include <linux/reboot.h> 11 + 12 + /* Power Control Register 2 */ 13 + #define PWR_CTRL2 0x7e 14 + #define PWR_CTRL2_SHUTDOWN BIT(2) /* Shutdown request */ 15 + #define PWR_CTRL2_RST BIT(1) /* Reset request */ 16 + 17 + static int spacemit_p1_pwroff_handler(struct sys_off_data *data) 18 + { 19 + struct regmap *regmap = data->cb_data; 20 + int ret; 21 + 22 + /* Put the PMIC into shutdown state */ 23 + ret = regmap_set_bits(regmap, PWR_CTRL2, PWR_CTRL2_SHUTDOWN); 24 + if (ret) { 25 + dev_err(data->dev, "shutdown failed: %d\n", ret); 26 + return notifier_from_errno(ret); 27 + } 28 + 29 + return NOTIFY_DONE; 30 + } 31 + 32 + static int spacemit_p1_restart_handler(struct sys_off_data *data) 33 + { 34 + struct regmap *regmap = data->cb_data; 35 + int ret; 36 + 37 + /* Put the PMIC into reset state */ 38 + ret = regmap_set_bits(regmap, PWR_CTRL2, PWR_CTRL2_RST); 39 + if (ret) { 40 + dev_err(data->dev, "restart failed: %d\n", ret); 41 + return notifier_from_errno(ret); 42 + } 43 + 44 + return NOTIFY_DONE; 45 + } 46 + 47 + static int spacemit_p1_reboot_probe(struct platform_device *pdev) 48 + { 49 + struct device *dev = &pdev->dev; 50 + struct regmap *regmap; 51 + int ret; 52 + 53 + regmap = dev_get_regmap(dev->parent, NULL); 54 + if (!regmap) 55 + return -ENODEV; 56 + 57 + ret = devm_register_power_off_handler(dev, &spacemit_p1_pwroff_handler, 58 + regmap); 59 + if (ret) 60 + return dev_err_probe(dev, ret, 61 + "Failed to register power off handler\n"); 62 + 63 + ret = devm_register_restart_handler(dev, spacemit_p1_restart_handler, 64 + regmap); 65 + if (ret) 66 + return dev_err_probe(dev, ret, 67 + "Failed to register restart handler\n"); 68 + 69 + return 0; 70 + } 71 + 72 + static const struct platform_device_id spacemit_p1_reboot_id_table[] = { 73 + { "spacemit-p1-reboot", }, 74 + { /* sentinel */ }, 75 + }; 76 + MODULE_DEVICE_TABLE(platform, spacemit_p1_reboot_id_table); 77 + 78 + static struct platform_driver spacemit_p1_reboot_driver = { 79 + .driver = { 80 + .name = "spacemit-p1-reboot", 81 + }, 82 + .probe = spacemit_p1_reboot_probe, 83 + .id_table = spacemit_p1_reboot_id_table, 84 + }; 85 + module_platform_driver(spacemit_p1_reboot_driver); 86 + 87 + MODULE_DESCRIPTION("SpacemiT P1 reboot/poweroff driver"); 88 + MODULE_LICENSE("GPL");
+24
drivers/power/supply/Kconfig
··· 942 942 This driver can also be built as a module. If so, the module will be 943 943 called rt9471. 944 944 945 + config CHARGER_RT9756 946 + tristate "Richtek RT9756 smart cap divider charger driver" 947 + depends on I2C 948 + select REGMAP_I2C 949 + select LINEAR_RANGES 950 + help 951 + This adds support for Richtek RT9756 smart cap divider charger driver. 952 + It's a high efficiency and high charge current charger. the device 953 + integrates smart cap divider topology with 9-channel high speed 954 + ADCs that can provide input and output voltage, current and 955 + temperature monitoring. 956 + 957 + This driver can also be built as a module. If so, the module will be 958 + called rt9756. 959 + 945 960 config CHARGER_CROS_USBPD 946 961 tristate "ChromeOS EC based USBPD charger" 947 962 depends on CROS_USBPD_NOTIFY ··· 1021 1006 help 1022 1007 Say Y to enable support for Microchip UCS1002 Programmable 1023 1008 USB Port Power Controller with Charger Emulation. 1009 + 1010 + config CHARGER_BD71828 1011 + tristate "Power-supply driver for ROHM BD71828 and BD71815 PMIC" 1012 + depends on MFD_ROHM_BD71828 1013 + help 1014 + Say Y here to enable support for charger and battery 1015 + in ROHM BD71815, BD71817, ROHM BD71828 power management 1016 + ICs. This driver gets various bits of information about battery 1017 + and charger states. 1024 1018 1025 1019 config CHARGER_BD99954 1026 1020 tristate "ROHM bd99954 charger driver"
+2
drivers/power/supply/Makefile
··· 64 64 obj-$(CONFIG_CHARGER_RT9455) += rt9455_charger.o 65 65 obj-$(CONFIG_CHARGER_RT9467) += rt9467-charger.o 66 66 obj-$(CONFIG_CHARGER_RT9471) += rt9471.o 67 + obj-$(CONFIG_CHARGER_RT9756) += rt9756.o 67 68 obj-$(CONFIG_BATTERY_TWL4030_MADC) += twl4030_madc_battery.o 68 69 obj-$(CONFIG_CHARGER_88PM860X) += 88pm860x_charger.o 69 70 obj-$(CONFIG_CHARGER_PF1550) += pf1550-charger.o ··· 118 117 obj-$(CONFIG_FUEL_GAUGE_SC27XX) += sc27xx_fuel_gauge.o 119 118 obj-$(CONFIG_FUEL_GAUGE_STC3117) += stc3117_fuel_gauge.o 120 119 obj-$(CONFIG_CHARGER_UCS1002) += ucs1002_power.o 120 + obj-$(CONFIG_CHARGER_BD71828) += bd71828-power.o 121 121 obj-$(CONFIG_CHARGER_BD99954) += bd99954-charger.o 122 122 obj-$(CONFIG_CHARGER_WILCO) += wilco-charger.o 123 123 obj-$(CONFIG_RN5T618_POWER) += rn5t618_power.o
+2 -1
drivers/power/supply/apm_power.c
··· 364 364 365 365 static void __exit apm_battery_exit(void) 366 366 { 367 - apm_get_power_status = NULL; 367 + if (apm_get_power_status == apm_battery_apm_get_power_status) 368 + apm_get_power_status = NULL; 368 369 } 369 370 370 371 module_init(apm_battery_init);
+1049
drivers/power/supply/bd71828-power.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* ROHM BD71815, BD71828 and BD71878 Charger driver */ 3 + 4 + #include <linux/interrupt.h> 5 + #include <linux/kernel.h> 6 + #include <linux/mfd/rohm-bd71815.h> 7 + #include <linux/mfd/rohm-bd71828.h> 8 + #include <linux/module.h> 9 + #include <linux/mod_devicetable.h> 10 + #include <linux/platform_device.h> 11 + #include <linux/property.h> 12 + #include <linux/power_supply.h> 13 + #include <linux/slab.h> 14 + 15 + /* common defines */ 16 + #define BD7182x_MASK_VBAT_U 0x1f 17 + #define BD7182x_MASK_VDCIN_U 0x0f 18 + #define BD7182x_MASK_IBAT_U 0x3f 19 + #define BD7182x_MASK_CURDIR_DISCHG 0x80 20 + #define BD7182x_MASK_CHG_STATE 0x7f 21 + #define BD7182x_MASK_BAT_TEMP 0x07 22 + #define BD7182x_MASK_DCIN_DET BIT(0) 23 + #define BD7182x_MASK_CONF_PON BIT(0) 24 + #define BD71815_MASK_CONF_XSTB BIT(1) 25 + #define BD7182x_MASK_BAT_STAT 0x3f 26 + #define BD7182x_MASK_DCIN_STAT 0x07 27 + 28 + #define BD7182x_MASK_WDT_AUTO 0x40 29 + #define BD7182x_MASK_VBAT_ALM_LIMIT_U 0x01 30 + #define BD7182x_MASK_CHG_EN 0x01 31 + 32 + #define BD7182x_DCIN_COLLAPSE_DEFAULT 0x36 33 + 34 + #define MAX_CURRENT_DEFAULT 890000 /* uA */ 35 + #define AC_NAME "bd71828_ac" 36 + #define BAT_NAME "bd71828_bat" 37 + 38 + #define BAT_OPEN 0x7 39 + 40 + /* 41 + * VBAT Low voltage detection Threshold 42 + * 0x00D4*16mV = 212*0.016 = 3.392v 43 + */ 44 + #define VBAT_LOW_TH 0x00D4 45 + 46 + struct pwr_regs { 47 + u8 vbat_avg; 48 + u8 ibat; 49 + u8 ibat_avg; 50 + u8 btemp_vth; 51 + u8 chg_state; 52 + u8 bat_temp; 53 + u8 dcin_stat; 54 + u8 dcin_collapse_limit; 55 + u8 chg_set1; 56 + u8 chg_en; 57 + u8 vbat_alm_limit_u; 58 + u8 conf; 59 + u8 vdcin; 60 + }; 61 + 62 + static const struct pwr_regs pwr_regs_bd71828 = { 63 + .vbat_avg = BD71828_REG_VBAT_U, 64 + .ibat = BD71828_REG_IBAT_U, 65 + .ibat_avg = BD71828_REG_IBAT_AVG_U, 66 + .btemp_vth = BD71828_REG_VM_BTMP_U, 67 + .chg_state = BD71828_REG_CHG_STATE, 68 + .bat_temp = BD71828_REG_BAT_TEMP, 69 + .dcin_stat = BD71828_REG_DCIN_STAT, 70 + .dcin_collapse_limit = BD71828_REG_DCIN_CLPS, 71 + .chg_set1 = BD71828_REG_CHG_SET1, 72 + .chg_en = BD71828_REG_CHG_EN, 73 + .vbat_alm_limit_u = BD71828_REG_ALM_VBAT_LIMIT_U, 74 + .conf = BD71828_REG_CONF, 75 + .vdcin = BD71828_REG_VDCIN_U, 76 + }; 77 + 78 + static const struct pwr_regs pwr_regs_bd71815 = { 79 + .vbat_avg = BD71815_REG_VM_SA_VBAT_U, 80 + /* BD71815 does not have separate current and current avg */ 81 + .ibat = BD71815_REG_CC_CURCD_U, 82 + .ibat_avg = BD71815_REG_CC_CURCD_U, 83 + 84 + .btemp_vth = BD71815_REG_VM_BTMP, 85 + .chg_state = BD71815_REG_CHG_STATE, 86 + .bat_temp = BD71815_REG_BAT_TEMP, 87 + .dcin_stat = BD71815_REG_DCIN_STAT, 88 + .dcin_collapse_limit = BD71815_REG_DCIN_CLPS, 89 + .chg_set1 = BD71815_REG_CHG_SET1, 90 + .chg_en = BD71815_REG_CHG_SET1, 91 + .vbat_alm_limit_u = BD71815_REG_ALM_VBAT_TH_U, 92 + .conf = BD71815_REG_CONF, 93 + 94 + .vdcin = BD71815_REG_VM_DCIN_U, 95 + }; 96 + 97 + struct bd71828_power { 98 + struct regmap *regmap; 99 + enum rohm_chip_type chip_type; 100 + struct device *dev; 101 + struct power_supply *ac; 102 + struct power_supply *bat; 103 + 104 + const struct pwr_regs *regs; 105 + /* Reg val to uA */ 106 + int curr_factor; 107 + int rsens; 108 + int (*get_temp)(struct bd71828_power *pwr, int *temp); 109 + int (*bat_inserted)(struct bd71828_power *pwr); 110 + }; 111 + 112 + static int bd7182x_write16(struct bd71828_power *pwr, int reg, u16 val) 113 + { 114 + __be16 tmp; 115 + 116 + tmp = cpu_to_be16(val); 117 + 118 + return regmap_bulk_write(pwr->regmap, reg, &tmp, sizeof(tmp)); 119 + } 120 + 121 + static int bd7182x_read16_himask(struct bd71828_power *pwr, int reg, int himask, 122 + u16 *val) 123 + { 124 + struct regmap *regmap = pwr->regmap; 125 + int ret; 126 + __be16 rvals; 127 + u8 *tmp = (u8 *)&rvals; 128 + 129 + ret = regmap_bulk_read(regmap, reg, &rvals, sizeof(*val)); 130 + if (!ret) { 131 + *tmp &= himask; 132 + *val = be16_to_cpu(rvals); 133 + } 134 + 135 + return ret; 136 + } 137 + 138 + static int bd71828_get_vbat(struct bd71828_power *pwr, int *vcell) 139 + { 140 + u16 tmp_vcell; 141 + int ret; 142 + 143 + ret = bd7182x_read16_himask(pwr, pwr->regs->vbat_avg, 144 + BD7182x_MASK_VBAT_U, &tmp_vcell); 145 + if (ret) 146 + dev_err(pwr->dev, "Failed to read battery average voltage\n"); 147 + else 148 + *vcell = ((int)tmp_vcell) * 1000; 149 + 150 + return ret; 151 + } 152 + 153 + static int bd71828_get_current_ds_adc(struct bd71828_power *pwr, int *curr, int *curr_avg) 154 + { 155 + __be16 tmp_curr; 156 + char *tmp = (char *)&tmp_curr; 157 + int dir = 1; 158 + int regs[] = { pwr->regs->ibat, pwr->regs->ibat_avg }; 159 + int *vals[] = { curr, curr_avg }; 160 + int ret, i; 161 + 162 + for (dir = 1, i = 0; i < ARRAY_SIZE(regs); i++) { 163 + ret = regmap_bulk_read(pwr->regmap, regs[i], &tmp_curr, 164 + sizeof(tmp_curr)); 165 + if (ret) 166 + break; 167 + 168 + if (*tmp & BD7182x_MASK_CURDIR_DISCHG) 169 + dir = -1; 170 + 171 + *tmp &= BD7182x_MASK_IBAT_U; 172 + 173 + *vals[i] = dir * ((int)be16_to_cpu(tmp_curr)) * pwr->curr_factor; 174 + } 175 + 176 + return ret; 177 + } 178 + 179 + /* Unit is tenths of degree C */ 180 + static int bd71815_get_temp(struct bd71828_power *pwr, int *temp) 181 + { 182 + struct regmap *regmap = pwr->regmap; 183 + int ret; 184 + int t; 185 + 186 + ret = regmap_read(regmap, pwr->regs->btemp_vth, &t); 187 + if (ret) 188 + return ret; 189 + 190 + t = 200 - t; 191 + 192 + if (t > 200) { 193 + dev_err(pwr->dev, "Failed to read battery temperature\n"); 194 + return -ENODATA; 195 + } 196 + 197 + return 0; 198 + } 199 + 200 + /* Unit is tenths of degree C */ 201 + static int bd71828_get_temp(struct bd71828_power *pwr, int *temp) 202 + { 203 + u16 t; 204 + int ret; 205 + int tmp = 200 * 10000; 206 + 207 + ret = bd7182x_read16_himask(pwr, pwr->regs->btemp_vth, 208 + BD71828_MASK_VM_BTMP_U, &t); 209 + if (ret) 210 + return ret; 211 + 212 + if (t > 3200) { 213 + dev_err(pwr->dev, 214 + "Failed to read battery temperature\n"); 215 + return -ENODATA; 216 + } 217 + 218 + tmp -= 625ULL * (unsigned int)t; 219 + *temp = tmp / 1000; 220 + 221 + return ret; 222 + } 223 + 224 + static int bd71828_charge_status(struct bd71828_power *pwr, 225 + int *s, int *h) 226 + { 227 + unsigned int state; 228 + int status, health; 229 + int ret = 1; 230 + 231 + ret = regmap_read(pwr->regmap, pwr->regs->chg_state, &state); 232 + if (ret) { 233 + dev_err(pwr->dev, "charger status reading failed (%d)\n", ret); 234 + return ret; 235 + } 236 + 237 + state &= BD7182x_MASK_CHG_STATE; 238 + 239 + dev_dbg(pwr->dev, "CHG_STATE %d\n", state); 240 + 241 + switch (state) { 242 + case 0x00: 243 + status = POWER_SUPPLY_STATUS_DISCHARGING; 244 + health = POWER_SUPPLY_HEALTH_GOOD; 245 + break; 246 + case 0x01: 247 + case 0x02: 248 + case 0x03: 249 + case 0x0E: 250 + status = POWER_SUPPLY_STATUS_CHARGING; 251 + health = POWER_SUPPLY_HEALTH_GOOD; 252 + break; 253 + case 0x0F: 254 + status = POWER_SUPPLY_STATUS_FULL; 255 + health = POWER_SUPPLY_HEALTH_GOOD; 256 + break; 257 + case 0x10: 258 + case 0x11: 259 + case 0x12: 260 + case 0x13: 261 + case 0x14: 262 + case 0x20: 263 + case 0x21: 264 + case 0x22: 265 + case 0x23: 266 + case 0x24: 267 + status = POWER_SUPPLY_STATUS_NOT_CHARGING; 268 + health = POWER_SUPPLY_HEALTH_OVERHEAT; 269 + break; 270 + case 0x30: 271 + case 0x31: 272 + case 0x32: 273 + case 0x40: 274 + status = POWER_SUPPLY_STATUS_DISCHARGING; 275 + health = POWER_SUPPLY_HEALTH_GOOD; 276 + break; 277 + case 0x7f: 278 + default: 279 + status = POWER_SUPPLY_STATUS_NOT_CHARGING; 280 + health = POWER_SUPPLY_HEALTH_DEAD; 281 + break; 282 + } 283 + 284 + if (s) 285 + *s = status; 286 + if (h) 287 + *h = health; 288 + 289 + return ret; 290 + } 291 + 292 + static int get_chg_online(struct bd71828_power *pwr, int *chg_online) 293 + { 294 + int r, ret; 295 + 296 + ret = regmap_read(pwr->regmap, pwr->regs->dcin_stat, &r); 297 + if (ret) { 298 + dev_err(pwr->dev, "Failed to read DCIN status\n"); 299 + return ret; 300 + } 301 + *chg_online = ((r & BD7182x_MASK_DCIN_DET) != 0); 302 + 303 + return 0; 304 + } 305 + 306 + static int get_bat_online(struct bd71828_power *pwr, int *bat_online) 307 + { 308 + int r, ret; 309 + 310 + ret = regmap_read(pwr->regmap, pwr->regs->bat_temp, &r); 311 + if (ret) { 312 + dev_err(pwr->dev, "Failed to read battery temperature\n"); 313 + return ret; 314 + } 315 + *bat_online = ((r & BD7182x_MASK_BAT_TEMP) != BAT_OPEN); 316 + 317 + return 0; 318 + } 319 + 320 + static int bd71828_bat_inserted(struct bd71828_power *pwr) 321 + { 322 + int ret, val; 323 + 324 + ret = regmap_read(pwr->regmap, pwr->regs->conf, &val); 325 + if (ret) { 326 + dev_err(pwr->dev, "Failed to read CONF register\n"); 327 + return 0; 328 + } 329 + ret = val & BD7182x_MASK_CONF_PON; 330 + 331 + if (ret) 332 + regmap_update_bits(pwr->regmap, pwr->regs->conf, 333 + BD7182x_MASK_CONF_PON, 0); 334 + 335 + return ret; 336 + } 337 + 338 + static int bd71815_bat_inserted(struct bd71828_power *pwr) 339 + { 340 + int ret, val; 341 + 342 + ret = regmap_read(pwr->regmap, pwr->regs->conf, &val); 343 + if (ret) { 344 + dev_err(pwr->dev, "Failed to read CONF register\n"); 345 + return ret; 346 + } 347 + 348 + ret = !(val & BD71815_MASK_CONF_XSTB); 349 + if (ret) 350 + regmap_write(pwr->regmap, pwr->regs->conf, val | 351 + BD71815_MASK_CONF_XSTB); 352 + 353 + return ret; 354 + } 355 + 356 + static int bd71828_init_hardware(struct bd71828_power *pwr) 357 + { 358 + int ret; 359 + 360 + /* TODO: Collapse limit should come from device-tree ? */ 361 + ret = regmap_write(pwr->regmap, pwr->regs->dcin_collapse_limit, 362 + BD7182x_DCIN_COLLAPSE_DEFAULT); 363 + if (ret) { 364 + dev_err(pwr->dev, "Failed to write DCIN collapse limit\n"); 365 + return ret; 366 + } 367 + 368 + ret = pwr->bat_inserted(pwr); 369 + if (ret < 0) 370 + return ret; 371 + 372 + if (ret) { 373 + /* WDT_FST auto set */ 374 + ret = regmap_update_bits(pwr->regmap, pwr->regs->chg_set1, 375 + BD7182x_MASK_WDT_AUTO, 376 + BD7182x_MASK_WDT_AUTO); 377 + if (ret) 378 + return ret; 379 + 380 + ret = bd7182x_write16(pwr, pwr->regs->vbat_alm_limit_u, 381 + VBAT_LOW_TH); 382 + if (ret) 383 + return ret; 384 + 385 + /* 386 + * On BD71815 "we mask the power-state" from relax detection. 387 + * I am unsure what the impact of the power-state would be if 388 + * we didn't - but this is what the vendor driver did - and 389 + * that driver has been used in few projects so I just assume 390 + * this is needed. 391 + */ 392 + if (pwr->chip_type == ROHM_CHIP_TYPE_BD71815) { 393 + ret = regmap_set_bits(pwr->regmap, 394 + BD71815_REG_REX_CTRL_1, 395 + REX_PMU_STATE_MASK); 396 + if (ret) 397 + return ret; 398 + } 399 + } 400 + 401 + return 0; 402 + } 403 + 404 + static int bd71828_charger_get_property(struct power_supply *psy, 405 + enum power_supply_property psp, 406 + union power_supply_propval *val) 407 + { 408 + struct bd71828_power *pwr = dev_get_drvdata(psy->dev.parent); 409 + u32 vot; 410 + u16 tmp; 411 + int online; 412 + int ret; 413 + 414 + switch (psp) { 415 + case POWER_SUPPLY_PROP_ONLINE: 416 + ret = get_chg_online(pwr, &online); 417 + if (!ret) 418 + val->intval = online; 419 + break; 420 + case POWER_SUPPLY_PROP_VOLTAGE_NOW: 421 + ret = bd7182x_read16_himask(pwr, pwr->regs->vdcin, 422 + BD7182x_MASK_VDCIN_U, &tmp); 423 + if (ret) 424 + return ret; 425 + 426 + vot = tmp; 427 + /* 5 milli volt steps */ 428 + val->intval = 5000 * vot; 429 + break; 430 + default: 431 + return -EINVAL; 432 + } 433 + 434 + return 0; 435 + } 436 + 437 + static int bd71828_battery_get_property(struct power_supply *psy, 438 + enum power_supply_property psp, 439 + union power_supply_propval *val) 440 + { 441 + struct bd71828_power *pwr = dev_get_drvdata(psy->dev.parent); 442 + int ret = 0; 443 + int status, health, tmp, curr, curr_avg, chg_en; 444 + 445 + if (psp == POWER_SUPPLY_PROP_STATUS || 446 + psp == POWER_SUPPLY_PROP_HEALTH || 447 + psp == POWER_SUPPLY_PROP_CHARGE_TYPE) 448 + ret = bd71828_charge_status(pwr, &status, &health); 449 + else if (psp == POWER_SUPPLY_PROP_CURRENT_AVG || 450 + psp == POWER_SUPPLY_PROP_CURRENT_NOW) 451 + ret = bd71828_get_current_ds_adc(pwr, &curr, &curr_avg); 452 + if (ret) 453 + return ret; 454 + 455 + switch (psp) { 456 + case POWER_SUPPLY_PROP_STATUS: 457 + val->intval = status; 458 + break; 459 + case POWER_SUPPLY_PROP_HEALTH: 460 + val->intval = health; 461 + break; 462 + case POWER_SUPPLY_PROP_PRESENT: 463 + ret = get_bat_online(pwr, &tmp); 464 + if (!ret) 465 + val->intval = tmp; 466 + break; 467 + case POWER_SUPPLY_PROP_VOLTAGE_NOW: 468 + ret = bd71828_get_vbat(pwr, &tmp); 469 + val->intval = tmp; 470 + break; 471 + case POWER_SUPPLY_PROP_TECHNOLOGY: 472 + val->intval = POWER_SUPPLY_TECHNOLOGY_LION; 473 + break; 474 + case POWER_SUPPLY_PROP_CURRENT_AVG: 475 + val->intval = curr_avg; 476 + break; 477 + case POWER_SUPPLY_PROP_CURRENT_NOW: 478 + val->intval = curr; 479 + break; 480 + case POWER_SUPPLY_PROP_CURRENT_MAX: 481 + val->intval = MAX_CURRENT_DEFAULT; 482 + break; 483 + case POWER_SUPPLY_PROP_TEMP: 484 + ret = pwr->get_temp(pwr, &val->intval); 485 + break; 486 + case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR: 487 + ret = regmap_read(pwr->regmap, pwr->regs->chg_en, &chg_en); 488 + if (ret) 489 + return ret; 490 + 491 + val->intval = (chg_en & BD7182x_MASK_CHG_EN) ? 492 + POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO : 493 + POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE; 494 + break; 495 + default: 496 + ret = -EINVAL; 497 + break; 498 + } 499 + 500 + return ret; 501 + } 502 + 503 + static int bd71828_battery_set_property(struct power_supply *psy, 504 + enum power_supply_property psp, 505 + const union power_supply_propval *val) 506 + { 507 + struct bd71828_power *pwr = dev_get_drvdata(psy->dev.parent); 508 + int ret = 0; 509 + 510 + switch (psp) { 511 + case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR: 512 + if (val->intval == POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO) 513 + ret = regmap_update_bits(pwr->regmap, pwr->regs->chg_en, 514 + BD7182x_MASK_CHG_EN, 515 + BD7182x_MASK_CHG_EN); 516 + else 517 + ret = regmap_update_bits(pwr->regmap, pwr->regs->chg_en, 518 + BD7182x_MASK_CHG_EN, 519 + 0); 520 + break; 521 + default: 522 + return -EINVAL; 523 + } 524 + 525 + return ret; 526 + } 527 + 528 + static int bd71828_battery_property_is_writeable(struct power_supply *psy, 529 + enum power_supply_property psp) 530 + { 531 + switch (psp) { 532 + case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR: 533 + return true; 534 + default: 535 + return false; 536 + } 537 + } 538 + 539 + /** @brief ac properties */ 540 + static const enum power_supply_property bd71828_charger_props[] = { 541 + POWER_SUPPLY_PROP_ONLINE, 542 + POWER_SUPPLY_PROP_VOLTAGE_NOW, 543 + }; 544 + 545 + static const enum power_supply_property bd71828_battery_props[] = { 546 + POWER_SUPPLY_PROP_STATUS, 547 + POWER_SUPPLY_PROP_HEALTH, 548 + POWER_SUPPLY_PROP_VOLTAGE_NOW, 549 + POWER_SUPPLY_PROP_HEALTH, 550 + POWER_SUPPLY_PROP_PRESENT, 551 + POWER_SUPPLY_PROP_TECHNOLOGY, 552 + POWER_SUPPLY_PROP_TEMP, 553 + POWER_SUPPLY_PROP_CURRENT_AVG, 554 + POWER_SUPPLY_PROP_CURRENT_NOW, 555 + POWER_SUPPLY_PROP_CURRENT_MAX, 556 + POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR, 557 + }; 558 + 559 + /** @brief powers supplied by bd71828_ac */ 560 + static char *bd71828_ac_supplied_to[] = { 561 + BAT_NAME, 562 + }; 563 + 564 + static const struct power_supply_desc bd71828_ac_desc = { 565 + .name = AC_NAME, 566 + .type = POWER_SUPPLY_TYPE_MAINS, 567 + .properties = bd71828_charger_props, 568 + .num_properties = ARRAY_SIZE(bd71828_charger_props), 569 + .get_property = bd71828_charger_get_property, 570 + }; 571 + 572 + static const struct power_supply_desc bd71828_bat_desc = { 573 + .name = BAT_NAME, 574 + .type = POWER_SUPPLY_TYPE_BATTERY, 575 + .charge_behaviours = BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO) | 576 + BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE), 577 + .properties = bd71828_battery_props, 578 + .num_properties = ARRAY_SIZE(bd71828_battery_props), 579 + .get_property = bd71828_battery_get_property, 580 + .set_property = bd71828_battery_set_property, 581 + .property_is_writeable = bd71828_battery_property_is_writeable, 582 + }; 583 + 584 + #define RSENS_CURR 10000000LLU 585 + 586 + #define BD_ISR_NAME(name) \ 587 + bd7181x_##name##_isr 588 + 589 + #define BD_ISR_BAT(name, print, run_gauge) \ 590 + static irqreturn_t BD_ISR_NAME(name)(int irq, void *data) \ 591 + { \ 592 + struct bd71828_power *pwr = (struct bd71828_power *)data; \ 593 + \ 594 + dev_dbg(pwr->dev, "%s\n", print); \ 595 + power_supply_changed(pwr->bat); \ 596 + \ 597 + return IRQ_HANDLED; \ 598 + } 599 + 600 + #define BD_ISR_AC(name, print, run_gauge) \ 601 + static irqreturn_t BD_ISR_NAME(name)(int irq, void *data) \ 602 + { \ 603 + struct bd71828_power *pwr = (struct bd71828_power *)data; \ 604 + \ 605 + power_supply_changed(pwr->ac); \ 606 + dev_dbg(pwr->dev, "%s\n", print); \ 607 + power_supply_changed(pwr->bat); \ 608 + \ 609 + return IRQ_HANDLED; \ 610 + } 611 + 612 + #define BD_ISR_DUMMY(name, print) \ 613 + static irqreturn_t BD_ISR_NAME(name)(int irq, void *data) \ 614 + { \ 615 + struct bd71828_power *pwr = (struct bd71828_power *)data; \ 616 + \ 617 + dev_dbg(pwr->dev, "%s\n", print); \ 618 + \ 619 + return IRQ_HANDLED; \ 620 + } 621 + 622 + BD_ISR_BAT(chg_state_changed, "CHG state changed", true) 623 + /* DCIN voltage changes */ 624 + BD_ISR_AC(dcin_removed, "DCIN removed", true) 625 + BD_ISR_AC(clps_out, "DCIN voltage back to normal", true) 626 + BD_ISR_AC(clps_in, "DCIN voltage collapsed", false) 627 + BD_ISR_AC(dcin_ovp_res, "DCIN voltage normal", true) 628 + BD_ISR_AC(dcin_ovp_det, "DCIN OVER VOLTAGE", true) 629 + 630 + BD_ISR_DUMMY(dcin_mon_det, "DCIN voltage below threshold") 631 + BD_ISR_DUMMY(dcin_mon_res, "DCIN voltage above threshold") 632 + 633 + BD_ISR_DUMMY(vsys_uv_res, "VSYS under-voltage cleared") 634 + BD_ISR_DUMMY(vsys_uv_det, "VSYS under-voltage") 635 + BD_ISR_DUMMY(vsys_low_res, "'VSYS low' cleared") 636 + BD_ISR_DUMMY(vsys_low_det, "VSYS low") 637 + BD_ISR_DUMMY(vsys_mon_res, "VSYS mon - resumed") 638 + BD_ISR_DUMMY(vsys_mon_det, "VSYS mon - detected") 639 + BD_ISR_BAT(chg_wdg_temp, "charger temperature watchdog triggered", true) 640 + BD_ISR_BAT(chg_wdg, "charging watchdog triggered", true) 641 + BD_ISR_BAT(bat_removed, "Battery removed", true) 642 + BD_ISR_BAT(bat_det, "Battery detected", true) 643 + /* TODO: Verify the meaning of these interrupts */ 644 + BD_ISR_BAT(rechg_det, "Recharging", true) 645 + BD_ISR_BAT(rechg_res, "Recharge ending", true) 646 + BD_ISR_DUMMY(temp_transit, "Temperature transition") 647 + BD_ISR_BAT(therm_rmv, "bd71815-therm-rmv", false) 648 + BD_ISR_BAT(therm_det, "bd71815-therm-det", true) 649 + BD_ISR_BAT(bat_dead, "bd71815-bat-dead", false) 650 + BD_ISR_BAT(bat_short_res, "bd71815-bat-short-res", true) 651 + BD_ISR_BAT(bat_short, "bd71815-bat-short-det", false) 652 + BD_ISR_BAT(bat_low_res, "bd71815-bat-low-res", true) 653 + BD_ISR_BAT(bat_low, "bd71815-bat-low-det", true) 654 + BD_ISR_BAT(bat_ov_res, "bd71815-bat-over-res", true) 655 + /* What should we do here? */ 656 + BD_ISR_BAT(bat_ov, "bd71815-bat-over-det", false) 657 + BD_ISR_BAT(bat_mon_res, "bd71815-bat-mon-res", true) 658 + BD_ISR_BAT(bat_mon, "bd71815-bat-mon-det", true) 659 + BD_ISR_BAT(bat_cc_mon, "bd71815-bat-cc-mon2", false) 660 + BD_ISR_BAT(bat_oc1_res, "bd71815-bat-oc1-res", true) 661 + BD_ISR_BAT(bat_oc1, "bd71815-bat-oc1-det", false) 662 + BD_ISR_BAT(bat_oc2_res, "bd71815-bat-oc2-res", true) 663 + BD_ISR_BAT(bat_oc2, "bd71815-bat-oc2-det", false) 664 + BD_ISR_BAT(bat_oc3_res, "bd71815-bat-oc3-res", true) 665 + BD_ISR_BAT(bat_oc3, "bd71815-bat-oc3-det", false) 666 + BD_ISR_BAT(temp_bat_low_res, "bd71815-temp-bat-low-res", true) 667 + BD_ISR_BAT(temp_bat_low, "bd71815-temp-bat-low-det", true) 668 + BD_ISR_BAT(temp_bat_hi_res, "bd71815-temp-bat-hi-res", true) 669 + BD_ISR_BAT(temp_bat_hi, "bd71815-temp-bat-hi-det", true) 670 + 671 + static irqreturn_t bd7182x_dcin_removed(int irq, void *data) 672 + { 673 + struct bd71828_power *pwr = (struct bd71828_power *)data; 674 + 675 + power_supply_changed(pwr->ac); 676 + dev_dbg(pwr->dev, "DCIN removed\n"); 677 + 678 + return IRQ_HANDLED; 679 + } 680 + 681 + static irqreturn_t bd718x7_chg_done(int irq, void *data) 682 + { 683 + struct bd71828_power *pwr = (struct bd71828_power *)data; 684 + 685 + power_supply_changed(pwr->bat); 686 + 687 + return IRQ_HANDLED; 688 + } 689 + 690 + static irqreturn_t bd7182x_dcin_detected(int irq, void *data) 691 + { 692 + struct bd71828_power *pwr = (struct bd71828_power *)data; 693 + 694 + dev_dbg(pwr->dev, "DCIN inserted\n"); 695 + power_supply_changed(pwr->ac); 696 + 697 + return IRQ_HANDLED; 698 + } 699 + 700 + static irqreturn_t bd71828_vbat_low_res(int irq, void *data) 701 + { 702 + struct bd71828_power *pwr = (struct bd71828_power *)data; 703 + 704 + dev_dbg(pwr->dev, "VBAT LOW Resumed\n"); 705 + 706 + return IRQ_HANDLED; 707 + } 708 + 709 + static irqreturn_t bd71828_vbat_low_det(int irq, void *data) 710 + { 711 + struct bd71828_power *pwr = (struct bd71828_power *)data; 712 + 713 + dev_dbg(pwr->dev, "VBAT LOW Detected\n"); 714 + 715 + return IRQ_HANDLED; 716 + } 717 + 718 + static irqreturn_t bd71828_temp_bat_hi_det(int irq, void *data) 719 + { 720 + struct bd71828_power *pwr = (struct bd71828_power *)data; 721 + 722 + dev_warn(pwr->dev, "Overtemp Detected\n"); 723 + power_supply_changed(pwr->bat); 724 + 725 + return IRQ_HANDLED; 726 + } 727 + 728 + static irqreturn_t bd71828_temp_bat_hi_res(int irq, void *data) 729 + { 730 + struct bd71828_power *pwr = (struct bd71828_power *)data; 731 + 732 + dev_dbg(pwr->dev, "Overtemp Resumed\n"); 733 + power_supply_changed(pwr->bat); 734 + 735 + return IRQ_HANDLED; 736 + } 737 + 738 + static irqreturn_t bd71828_temp_bat_low_det(int irq, void *data) 739 + { 740 + struct bd71828_power *pwr = (struct bd71828_power *)data; 741 + 742 + dev_dbg(pwr->dev, "Lowtemp Detected\n"); 743 + power_supply_changed(pwr->bat); 744 + 745 + return IRQ_HANDLED; 746 + } 747 + 748 + static irqreturn_t bd71828_temp_bat_low_res(int irq, void *data) 749 + { 750 + struct bd71828_power *pwr = (struct bd71828_power *)data; 751 + 752 + dev_dbg(pwr->dev, "Lowtemp Resumed\n"); 753 + power_supply_changed(pwr->bat); 754 + 755 + return IRQ_HANDLED; 756 + } 757 + 758 + static irqreturn_t bd71828_temp_vf_det(int irq, void *data) 759 + { 760 + struct bd71828_power *pwr = (struct bd71828_power *)data; 761 + 762 + dev_dbg(pwr->dev, "VF Detected\n"); 763 + power_supply_changed(pwr->bat); 764 + 765 + return IRQ_HANDLED; 766 + } 767 + 768 + static irqreturn_t bd71828_temp_vf_res(int irq, void *data) 769 + { 770 + struct bd71828_power *pwr = (struct bd71828_power *)data; 771 + 772 + dev_dbg(pwr->dev, "VF Resumed\n"); 773 + power_supply_changed(pwr->bat); 774 + 775 + return IRQ_HANDLED; 776 + } 777 + 778 + static irqreturn_t bd71828_temp_vf125_det(int irq, void *data) 779 + { 780 + struct bd71828_power *pwr = (struct bd71828_power *)data; 781 + 782 + dev_dbg(pwr->dev, "VF125 Detected\n"); 783 + power_supply_changed(pwr->bat); 784 + 785 + return IRQ_HANDLED; 786 + } 787 + 788 + static irqreturn_t bd71828_temp_vf125_res(int irq, void *data) 789 + { 790 + struct bd71828_power *pwr = (struct bd71828_power *)data; 791 + 792 + dev_dbg(pwr->dev, "VF125 Resumed\n"); 793 + power_supply_changed(pwr->bat); 794 + 795 + return IRQ_HANDLED; 796 + } 797 + 798 + struct bd7182x_irq_res { 799 + const char *name; 800 + irq_handler_t handler; 801 + }; 802 + 803 + #define BDIRQ(na, hn) { .name = (na), .handler = (hn) } 804 + 805 + static int bd7182x_get_irqs(struct platform_device *pdev, 806 + struct bd71828_power *pwr) 807 + { 808 + int i, irq, ret; 809 + static const struct bd7182x_irq_res bd71815_irqs[] = { 810 + BDIRQ("bd71815-dcin-rmv", BD_ISR_NAME(dcin_removed)), 811 + BDIRQ("bd71815-dcin-clps-out", BD_ISR_NAME(clps_out)), 812 + BDIRQ("bd71815-dcin-clps-in", BD_ISR_NAME(clps_in)), 813 + BDIRQ("bd71815-dcin-ovp-res", BD_ISR_NAME(dcin_ovp_res)), 814 + BDIRQ("bd71815-dcin-ovp-det", BD_ISR_NAME(dcin_ovp_det)), 815 + BDIRQ("bd71815-dcin-mon-res", BD_ISR_NAME(dcin_mon_res)), 816 + BDIRQ("bd71815-dcin-mon-det", BD_ISR_NAME(dcin_mon_det)), 817 + 818 + BDIRQ("bd71815-vsys-uv-res", BD_ISR_NAME(vsys_uv_res)), 819 + BDIRQ("bd71815-vsys-uv-det", BD_ISR_NAME(vsys_uv_det)), 820 + BDIRQ("bd71815-vsys-low-res", BD_ISR_NAME(vsys_low_res)), 821 + BDIRQ("bd71815-vsys-low-det", BD_ISR_NAME(vsys_low_det)), 822 + BDIRQ("bd71815-vsys-mon-res", BD_ISR_NAME(vsys_mon_res)), 823 + BDIRQ("bd71815-vsys-mon-det", BD_ISR_NAME(vsys_mon_det)), 824 + BDIRQ("bd71815-chg-wdg-temp", BD_ISR_NAME(chg_wdg_temp)), 825 + BDIRQ("bd71815-chg-wdg", BD_ISR_NAME(chg_wdg)), 826 + BDIRQ("bd71815-rechg-det", BD_ISR_NAME(rechg_det)), 827 + BDIRQ("bd71815-rechg-res", BD_ISR_NAME(rechg_res)), 828 + BDIRQ("bd71815-ranged-temp-transit", BD_ISR_NAME(temp_transit)), 829 + BDIRQ("bd71815-chg-state-change", BD_ISR_NAME(chg_state_changed)), 830 + BDIRQ("bd71815-bat-temp-normal", bd71828_temp_bat_hi_res), 831 + BDIRQ("bd71815-bat-temp-erange", bd71828_temp_bat_hi_det), 832 + BDIRQ("bd71815-bat-rmv", BD_ISR_NAME(bat_removed)), 833 + BDIRQ("bd71815-bat-det", BD_ISR_NAME(bat_det)), 834 + 835 + /* Add ISRs for these */ 836 + BDIRQ("bd71815-therm-rmv", BD_ISR_NAME(therm_rmv)), 837 + BDIRQ("bd71815-therm-det", BD_ISR_NAME(therm_det)), 838 + BDIRQ("bd71815-bat-dead", BD_ISR_NAME(bat_dead)), 839 + BDIRQ("bd71815-bat-short-res", BD_ISR_NAME(bat_short_res)), 840 + BDIRQ("bd71815-bat-short-det", BD_ISR_NAME(bat_short)), 841 + BDIRQ("bd71815-bat-low-res", BD_ISR_NAME(bat_low_res)), 842 + BDIRQ("bd71815-bat-low-det", BD_ISR_NAME(bat_low)), 843 + BDIRQ("bd71815-bat-over-res", BD_ISR_NAME(bat_ov_res)), 844 + BDIRQ("bd71815-bat-over-det", BD_ISR_NAME(bat_ov)), 845 + BDIRQ("bd71815-bat-mon-res", BD_ISR_NAME(bat_mon_res)), 846 + BDIRQ("bd71815-bat-mon-det", BD_ISR_NAME(bat_mon)), 847 + /* cc-mon 1 & 3 ? */ 848 + BDIRQ("bd71815-bat-cc-mon2", BD_ISR_NAME(bat_cc_mon)), 849 + BDIRQ("bd71815-bat-oc1-res", BD_ISR_NAME(bat_oc1_res)), 850 + BDIRQ("bd71815-bat-oc1-det", BD_ISR_NAME(bat_oc1)), 851 + BDIRQ("bd71815-bat-oc2-res", BD_ISR_NAME(bat_oc2_res)), 852 + BDIRQ("bd71815-bat-oc2-det", BD_ISR_NAME(bat_oc2)), 853 + BDIRQ("bd71815-bat-oc3-res", BD_ISR_NAME(bat_oc3_res)), 854 + BDIRQ("bd71815-bat-oc3-det", BD_ISR_NAME(bat_oc3)), 855 + BDIRQ("bd71815-temp-bat-low-res", BD_ISR_NAME(temp_bat_low_res)), 856 + BDIRQ("bd71815-temp-bat-low-det", BD_ISR_NAME(temp_bat_low)), 857 + BDIRQ("bd71815-temp-bat-hi-res", BD_ISR_NAME(temp_bat_hi_res)), 858 + BDIRQ("bd71815-temp-bat-hi-det", BD_ISR_NAME(temp_bat_hi)), 859 + /* 860 + * TODO: add rest of the IRQs and re-check the handling. 861 + * Check the bd71815-bat-cc-mon1, bd71815-bat-cc-mon3, 862 + * bd71815-bat-low-res, bd71815-bat-low-det, 863 + * bd71815-bat-hi-res, bd71815-bat-hi-det. 864 + */ 865 + }; 866 + static const struct bd7182x_irq_res bd71828_irqs[] = { 867 + BDIRQ("bd71828-chg-done", bd718x7_chg_done), 868 + BDIRQ("bd71828-pwr-dcin-in", bd7182x_dcin_detected), 869 + BDIRQ("bd71828-pwr-dcin-out", bd7182x_dcin_removed), 870 + BDIRQ("bd71828-vbat-normal", bd71828_vbat_low_res), 871 + BDIRQ("bd71828-vbat-low", bd71828_vbat_low_det), 872 + BDIRQ("bd71828-btemp-hi", bd71828_temp_bat_hi_det), 873 + BDIRQ("bd71828-btemp-cool", bd71828_temp_bat_hi_res), 874 + BDIRQ("bd71828-btemp-lo", bd71828_temp_bat_low_det), 875 + BDIRQ("bd71828-btemp-warm", bd71828_temp_bat_low_res), 876 + BDIRQ("bd71828-temp-hi", bd71828_temp_vf_det), 877 + BDIRQ("bd71828-temp-norm", bd71828_temp_vf_res), 878 + BDIRQ("bd71828-temp-125-over", bd71828_temp_vf125_det), 879 + BDIRQ("bd71828-temp-125-under", bd71828_temp_vf125_res), 880 + }; 881 + int num_irqs; 882 + const struct bd7182x_irq_res *irqs; 883 + 884 + switch (pwr->chip_type) { 885 + case ROHM_CHIP_TYPE_BD71828: 886 + irqs = &bd71828_irqs[0]; 887 + num_irqs = ARRAY_SIZE(bd71828_irqs); 888 + break; 889 + case ROHM_CHIP_TYPE_BD71815: 890 + irqs = &bd71815_irqs[0]; 891 + num_irqs = ARRAY_SIZE(bd71815_irqs); 892 + break; 893 + default: 894 + return -EINVAL; 895 + } 896 + 897 + for (i = 0; i < num_irqs; i++) { 898 + irq = platform_get_irq_byname(pdev, irqs[i].name); 899 + 900 + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, 901 + irqs[i].handler, 0, 902 + irqs[i].name, pwr); 903 + if (ret) 904 + break; 905 + } 906 + 907 + return ret; 908 + } 909 + 910 + #define RSENS_DEFAULT_30MOHM 30000 /* 30 mOhm in uOhms*/ 911 + 912 + static int bd7182x_get_rsens(struct bd71828_power *pwr) 913 + { 914 + u64 tmp = RSENS_CURR; 915 + int rsens_ohm = RSENS_DEFAULT_30MOHM; 916 + struct fwnode_handle *node = NULL; 917 + 918 + if (pwr->dev->parent) 919 + node = dev_fwnode(pwr->dev->parent); 920 + 921 + if (node) { 922 + int ret; 923 + u32 rs; 924 + 925 + ret = fwnode_property_read_u32(node, 926 + "rohm,charger-sense-resistor-micro-ohms", 927 + &rs); 928 + if (ret) { 929 + if (ret == -EINVAL) { 930 + rs = RSENS_DEFAULT_30MOHM; 931 + } else { 932 + dev_err(pwr->dev, "Bad RSENS dt property\n"); 933 + return ret; 934 + } 935 + } 936 + if (!rs) { 937 + dev_err(pwr->dev, "Bad RSENS value\n"); 938 + return -EINVAL; 939 + } 940 + 941 + rsens_ohm = (int)rs; 942 + } 943 + 944 + /* Reg val to uA */ 945 + do_div(tmp, rsens_ohm); 946 + 947 + pwr->curr_factor = tmp; 948 + pwr->rsens = rsens_ohm; 949 + dev_dbg(pwr->dev, "Setting rsens to %u micro ohm\n", pwr->rsens); 950 + dev_dbg(pwr->dev, "Setting curr-factor to %u\n", pwr->curr_factor); 951 + 952 + return 0; 953 + } 954 + 955 + static int bd71828_power_probe(struct platform_device *pdev) 956 + { 957 + struct bd71828_power *pwr; 958 + struct power_supply_config ac_cfg = {}; 959 + struct power_supply_config bat_cfg = {}; 960 + int ret; 961 + struct regmap *regmap; 962 + 963 + regmap = dev_get_regmap(pdev->dev.parent, NULL); 964 + if (!regmap) { 965 + dev_err(&pdev->dev, "No parent regmap\n"); 966 + return -EINVAL; 967 + } 968 + 969 + pwr = devm_kzalloc(&pdev->dev, sizeof(*pwr), GFP_KERNEL); 970 + if (!pwr) 971 + return -ENOMEM; 972 + 973 + pwr->regmap = regmap; 974 + pwr->dev = &pdev->dev; 975 + pwr->chip_type = platform_get_device_id(pdev)->driver_data; 976 + 977 + switch (pwr->chip_type) { 978 + case ROHM_CHIP_TYPE_BD71828: 979 + pwr->bat_inserted = bd71828_bat_inserted; 980 + pwr->get_temp = bd71828_get_temp; 981 + pwr->regs = &pwr_regs_bd71828; 982 + break; 983 + case ROHM_CHIP_TYPE_BD71815: 984 + pwr->bat_inserted = bd71815_bat_inserted; 985 + pwr->get_temp = bd71815_get_temp; 986 + pwr->regs = &pwr_regs_bd71815; 987 + break; 988 + default: 989 + dev_err(pwr->dev, "Unknown PMIC\n"); 990 + return -EINVAL; 991 + } 992 + 993 + ret = bd7182x_get_rsens(pwr); 994 + if (ret) 995 + return dev_err_probe(&pdev->dev, ret, "sense resistor missing\n"); 996 + 997 + dev_set_drvdata(&pdev->dev, pwr); 998 + bd71828_init_hardware(pwr); 999 + 1000 + bat_cfg.drv_data = pwr; 1001 + bat_cfg.fwnode = dev_fwnode(&pdev->dev); 1002 + 1003 + ac_cfg.supplied_to = bd71828_ac_supplied_to; 1004 + ac_cfg.num_supplicants = ARRAY_SIZE(bd71828_ac_supplied_to); 1005 + ac_cfg.drv_data = pwr; 1006 + 1007 + pwr->ac = devm_power_supply_register(&pdev->dev, &bd71828_ac_desc, 1008 + &ac_cfg); 1009 + if (IS_ERR(pwr->ac)) 1010 + return dev_err_probe(&pdev->dev, PTR_ERR(pwr->ac), 1011 + "failed to register ac\n"); 1012 + 1013 + pwr->bat = devm_power_supply_register(&pdev->dev, &bd71828_bat_desc, 1014 + &bat_cfg); 1015 + if (IS_ERR(pwr->bat)) 1016 + return dev_err_probe(&pdev->dev, PTR_ERR(pwr->bat), 1017 + "failed to register bat\n"); 1018 + 1019 + ret = bd7182x_get_irqs(pdev, pwr); 1020 + if (ret) 1021 + return dev_err_probe(&pdev->dev, ret, "failed to request IRQs"); 1022 + 1023 + /* Configure wakeup capable */ 1024 + device_set_wakeup_capable(pwr->dev, 1); 1025 + device_set_wakeup_enable(pwr->dev, 1); 1026 + 1027 + return 0; 1028 + } 1029 + 1030 + static const struct platform_device_id bd71828_charger_id[] = { 1031 + { "bd71815-power", ROHM_CHIP_TYPE_BD71815 }, 1032 + { "bd71828-power", ROHM_CHIP_TYPE_BD71828 }, 1033 + { }, 1034 + }; 1035 + MODULE_DEVICE_TABLE(platform, bd71828_charger_id); 1036 + 1037 + static struct platform_driver bd71828_power_driver = { 1038 + .driver = { 1039 + .name = "bd718xx-power", 1040 + }, 1041 + .probe = bd71828_power_probe, 1042 + .id_table = bd71828_charger_id, 1043 + }; 1044 + 1045 + module_platform_driver(bd71828_power_driver); 1046 + 1047 + MODULE_AUTHOR("Cong Pham <cpham2403@gmail.com>"); 1048 + MODULE_DESCRIPTION("ROHM BD718(15/28/78) PMIC Battery Charger driver"); 1049 + MODULE_LICENSE("GPL");
+7 -1
drivers/power/supply/cw2015_battery.c
··· 699 699 if (!cw_bat->battery_workqueue) 700 700 return -ENOMEM; 701 701 702 - devm_delayed_work_autocancel(&client->dev, &cw_bat->battery_delay_work, cw_bat_work); 702 + ret = devm_delayed_work_autocancel(&client->dev, &cw_bat->battery_delay_work, cw_bat_work); 703 + if (ret) { 704 + dev_err_probe(&client->dev, ret, 705 + "Failed to register delayed work\n"); 706 + return ret; 707 + } 708 + 703 709 queue_delayed_work(cw_bat->battery_workqueue, 704 710 &cw_bat->battery_delay_work, msecs_to_jiffies(10)); 705 711 return 0;
+5 -1
drivers/power/supply/max17040_battery.c
··· 388 388 union power_supply_propval *val) 389 389 { 390 390 struct max17040_chip *chip = power_supply_get_drvdata(psy); 391 + int ret; 391 392 392 393 switch (psp) { 393 394 case POWER_SUPPLY_PROP_ONLINE: ··· 411 410 if (!chip->channel_temp) 412 411 return -ENODATA; 413 412 414 - iio_read_channel_processed(chip->channel_temp, &val->intval); 413 + ret = iio_read_channel_processed(chip->channel_temp, &val->intval); 414 + if (ret) 415 + return ret; 416 + 415 417 val->intval /= 100; /* Convert from milli- to deci-degree */ 416 418 417 419 break;
+52 -4
drivers/power/supply/max77705_charger.c
··· 40 40 POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, 41 41 }; 42 42 43 + static irqreturn_t max77705_aicl_irq(int irq, void *irq_drv_data) 44 + { 45 + struct max77705_charger_data *chg = irq_drv_data; 46 + unsigned int regval, irq_status; 47 + int err; 48 + 49 + err = regmap_read(chg->regmap, MAX77705_CHG_REG_INT_OK, &irq_status); 50 + if (err < 0) 51 + return IRQ_HANDLED; 52 + 53 + // irq is fiered at the end of current decrease sequence too 54 + // early check AICL_I bit to guard against that excess irq call 55 + while (!(irq_status & BIT(MAX77705_AICL_I))) { 56 + err = regmap_field_read(chg->rfield[MAX77705_CHG_CHGIN_LIM], &regval); 57 + if (err < 0) 58 + return IRQ_HANDLED; 59 + 60 + regval--; 61 + 62 + err = regmap_field_write(chg->rfield[MAX77705_CHG_CHGIN_LIM], regval); 63 + if (err < 0) 64 + return IRQ_HANDLED; 65 + 66 + msleep(AICL_WORK_DELAY_MS); 67 + 68 + err = regmap_read(chg->regmap, MAX77705_CHG_REG_INT_OK, &irq_status); 69 + if (err < 0) 70 + return IRQ_HANDLED; 71 + } 72 + 73 + return IRQ_HANDLED; 74 + } 75 + 43 76 static irqreturn_t max77705_chgin_irq(int irq, void *irq_drv_data) 44 77 { 45 78 struct max77705_charger_data *chg = irq_drv_data; ··· 93 60 REGMAP_IRQ_REG_LINE(MAX77705_AICL_I, BITS_PER_BYTE), 94 61 }; 95 62 96 - static struct regmap_irq_chip max77705_charger_irq_chip = { 63 + static const struct regmap_irq_chip max77705_charger_irq_chip = { 97 64 .name = "max77705-charger", 98 65 .status_base = MAX77705_CHG_REG_INT, 99 66 .mask_base = MAX77705_CHG_REG_INT_MASK, ··· 600 567 { 601 568 struct power_supply_config pscfg = {}; 602 569 struct max77705_charger_data *chg; 570 + struct regmap_irq_chip *chip_desc; 603 571 struct device *dev; 604 572 struct regmap_irq_chip_data *irq_data; 605 573 int ret; ··· 613 579 614 580 chg->dev = dev; 615 581 i2c_set_clientdata(i2c, chg); 582 + 583 + chip_desc = devm_kmemdup(dev, &max77705_charger_irq_chip, 584 + sizeof(max77705_charger_irq_chip), 585 + GFP_KERNEL); 586 + if (!chip_desc) 587 + return -ENOMEM; 588 + chip_desc->irq_drv_data = chg; 616 589 617 590 chg->regmap = devm_regmap_init_i2c(i2c, &max77705_chg_regmap_config); 618 591 if (IS_ERR(chg->regmap)) ··· 640 599 if (IS_ERR(chg->psy_chg)) 641 600 return PTR_ERR(chg->psy_chg); 642 601 643 - max77705_charger_irq_chip.irq_drv_data = chg; 644 602 ret = devm_regmap_add_irq_chip(chg->dev, chg->regmap, i2c->irq, 645 603 IRQF_ONESHOT, 0, 646 - &max77705_charger_irq_chip, 647 - &irq_data); 604 + chip_desc, &irq_data); 648 605 if (ret) 649 606 return dev_err_probe(dev, ret, "failed to add irq chip\n"); 650 607 ··· 668 629 "chgin-irq", chg); 669 630 if (ret) { 670 631 dev_err_probe(dev, ret, "Failed to Request chgin IRQ\n"); 632 + goto destroy_wq; 633 + } 634 + 635 + ret = devm_request_threaded_irq(dev, regmap_irq_get_virq(irq_data, MAX77705_AICL_I), 636 + NULL, max77705_aicl_irq, 637 + IRQF_TRIGGER_NONE, 638 + "aicl-irq", chg); 639 + if (ret) { 640 + dev_err_probe(dev, ret, "Failed to Request aicl IRQ\n"); 671 641 goto destroy_wq; 672 642 } 673 643
+2 -12
drivers/power/supply/qcom_battmgr.c
··· 678 678 u32 target_soc, delta_soc; 679 679 int ret; 680 680 681 - if (start_soc < CHARGE_CTRL_START_THR_MIN || 682 - start_soc > CHARGE_CTRL_START_THR_MAX) { 683 - dev_err(battmgr->dev, "charge control start threshold exceed range: [%u - %u]\n", 684 - CHARGE_CTRL_START_THR_MIN, CHARGE_CTRL_START_THR_MAX); 685 - return -EINVAL; 686 - } 681 + start_soc = clamp(start_soc, CHARGE_CTRL_START_THR_MIN, CHARGE_CTRL_START_THR_MAX); 687 682 688 683 /* 689 684 * If the new start threshold is larger than the old end threshold, ··· 711 716 u32 delta_soc = CHARGE_CTRL_DELTA_SOC; 712 717 int ret; 713 718 714 - if (end_soc < CHARGE_CTRL_END_THR_MIN || 715 - end_soc > CHARGE_CTRL_END_THR_MAX) { 716 - dev_err(battmgr->dev, "charge control end threshold exceed range: [%u - %u]\n", 717 - CHARGE_CTRL_END_THR_MIN, CHARGE_CTRL_END_THR_MAX); 718 - return -EINVAL; 719 - } 719 + end_soc = clamp(end_soc, CHARGE_CTRL_END_THR_MIN, CHARGE_CTRL_END_THR_MAX); 720 720 721 721 if (battmgr->info.charge_ctrl_start && end_soc > battmgr->info.charge_ctrl_start) 722 722 delta_soc = end_soc - battmgr->info.charge_ctrl_start;
+2
drivers/power/supply/rt5033_charger.c
··· 701 701 np_conn = of_parse_phandle(pdev->dev.of_node, "richtek,usb-connector", 0); 702 702 np_edev = of_get_parent(np_conn); 703 703 charger->edev = extcon_find_edev_by_node(np_edev); 704 + of_node_put(np_edev); 705 + of_node_put(np_conn); 704 706 if (IS_ERR(charger->edev)) { 705 707 dev_warn(charger->dev, "no extcon device found in device-tree\n"); 706 708 goto out;
+5 -1
drivers/power/supply/rt9467-charger.c
··· 376 376 if (rsel == RT9467_RANGE_VMIVR) { 377 377 ret = linear_range_get_selector_high(range, value, &sel, &found); 378 378 if (ret) 379 - value = range->max_sel; 379 + sel = range->max_sel; 380 380 } else { 381 381 linear_range_get_selector_within(range, value, &sel); 382 382 } ··· 588 588 aicl_vth = mivr_vth + RT9467_AICLVTH_GAP_uV; 589 589 ret = rt9467_set_value_from_ranges(data, F_AICL_VTH, 590 590 RT9467_RANGE_AICL_VTH, aicl_vth); 591 + if (ret) { 592 + dev_err(data->dev, "Failed to set AICL VTH\n"); 593 + return ret; 594 + } 591 595 592 596 /* Trigger AICL function */ 593 597 ret = regmap_field_write(data->rm_field[F_AICL_MEAS], 1);
+955
drivers/power/supply/rt9756.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + // 3 + // Copyright (C) 2025 Richtek Technology Corp. 4 + // 5 + // Authors: ChiYuan Huang <cy_huang@richtek.com> 6 + 7 + #include <linux/atomic.h> 8 + #include <linux/cleanup.h> 9 + #include <linux/i2c.h> 10 + #include <linux/kernel.h> 11 + #include <linux/linear_range.h> 12 + #include <linux/interrupt.h> 13 + #include <linux/mod_devicetable.h> 14 + #include <linux/module.h> 15 + #include <linux/mutex.h> 16 + #include <linux/power_supply.h> 17 + #include <linux/property.h> 18 + #include <linux/regmap.h> 19 + #include <linux/sysfs.h> 20 + #include <linux/util_macros.h> 21 + 22 + #define RT9756_REG_INTFLAG1 0x0B 23 + #define RT9756_REG_INTFLAG2 0x0D 24 + #define RT9756_REG_INTFLAG3 0x0F 25 + #define RT9756_REG_ADCCTL 0x11 26 + #define RT9756_REG_VBUSADC 0x12 27 + #define RT9756_REG_BC12FLAG 0x45 28 + #define RT9756_REG_INTFLAG4 0x49 29 + 30 + /* Flag1 */ 31 + #define RT9756_EVT_BUSOVP BIT(3) 32 + #define RT9756_EVT_BUSOCP BIT(2) 33 + #define RT9756_EVT_BUSUCP BIT(0) 34 + /* Flag2 */ 35 + #define RT9756_EVT_BATOVP BIT(7) 36 + #define RT9756_EVT_BATOCP BIT(6) 37 + #define RT9756_EVT_TDIEOTP BIT(3) 38 + #define RT9756_EVT_VBUSLOW_ERR BIT(2) 39 + #define RT9756_EVT_VAC_INSERT BIT(0) 40 + /* Flag3 */ 41 + #define RT9756_EVT_WDT BIT(5) 42 + #define RT9756_EVT_VAC_UVLO BIT(4) 43 + /* ADCCTL */ 44 + #define RT9756_ADCEN_MASK BIT(7) 45 + #define RT9756_ADCONCE_MASK BIT(6) 46 + /* Bc12_flag */ 47 + #define RT9756_EVT_BC12_DONE BIT(3) 48 + /* Flag4 */ 49 + #define RT9756_EVT_OUTOVP BIT(0) 50 + 51 + #define RICHTEK_DEVID 7 52 + #define RT9756_REVID 0 53 + #define RT9756A_REVID 1 54 + #define RT9757_REVID 2 55 + #define RT9757A_REVID 3 56 + #define RT9756_ADC_CONVTIME 1200 57 + #define RT9756_ADC_MAXWAIT 16000 58 + 59 + enum rt9756_model { 60 + MODEL_RT9756 = 0, 61 + MODEL_RT9757, 62 + MODEL_RT9770, 63 + MODEL_MAX 64 + }; 65 + 66 + enum rt9756_adc_chan { 67 + ADC_VBUS = 0, 68 + ADC_IBUS, 69 + ADC_VBAT, 70 + ADC_IBAT, 71 + ADC_TDIE, 72 + ADC_MAX_CHANNEL 73 + }; 74 + 75 + enum rt9756_usb_type { 76 + USB_NO_VBUS = 0, 77 + USB_SDP = 2, 78 + USB_NSTD, 79 + USB_DCP, 80 + USB_CDP, 81 + MAX_USB_TYPE 82 + }; 83 + 84 + enum rt9756_fields { 85 + F_VBATOVP = 0, 86 + F_VBATOVP_EN, 87 + F_IBATOCP, 88 + F_IBATOCP_EN, 89 + F_VBUSOVP, 90 + F_VBUSOVP_EN, 91 + F_IBUSOCP, 92 + F_IBUSOCP_EN, 93 + F_SWITCHING, 94 + F_REG_RST, 95 + F_CHG_EN, 96 + F_OP_MODE, 97 + F_WDT_DIS, 98 + F_WDT_TMR, 99 + F_DEV_ID, 100 + F_BC12_EN, 101 + F_USB_STATE, 102 + F_VBUS_STATE, 103 + F_IBAT_RSEN, 104 + F_REVISION, 105 + F_MAX_FIELD 106 + }; 107 + 108 + enum rt9756_ranges { 109 + R_VBATOVP = 0, 110 + R_IBATOCP, 111 + R_VBUSOVP, 112 + R_IBUSOCP, 113 + R_MAX_RANGE 114 + }; 115 + 116 + static const struct reg_field rt9756_chg_fields[F_MAX_FIELD] = { 117 + [F_VBATOVP] = REG_FIELD(0x08, 0, 4), 118 + [F_VBATOVP_EN] = REG_FIELD(0x08, 7, 7), 119 + [F_IBATOCP] = REG_FIELD(0x09, 0, 5), 120 + [F_IBATOCP_EN] = REG_FIELD(0x09, 7, 7), 121 + [F_VBUSOVP] = REG_FIELD(0x06, 0, 5), 122 + [F_VBUSOVP_EN] = REG_FIELD(0x06, 7, 7), 123 + [F_IBUSOCP] = REG_FIELD(0x07, 0, 4), 124 + [F_IBUSOCP_EN] = REG_FIELD(0x07, 5, 5), 125 + [F_SWITCHING] = REG_FIELD(0x5c, 7, 7), 126 + [F_REG_RST] = REG_FIELD(0x00, 7, 7), 127 + [F_CHG_EN] = REG_FIELD(0x00, 6, 6), 128 + [F_OP_MODE] = REG_FIELD(0x00, 5, 5), 129 + [F_WDT_DIS] = REG_FIELD(0x00, 3, 3), 130 + [F_WDT_TMR] = REG_FIELD(0x00, 0, 2), 131 + [F_DEV_ID] = REG_FIELD(0x03, 0, 3), 132 + [F_BC12_EN] = REG_FIELD(0x44, 7, 7), 133 + [F_USB_STATE] = REG_FIELD(0x46, 5, 7), 134 + [F_VBUS_STATE] = REG_FIELD(0x4c, 0, 0), 135 + [F_IBAT_RSEN] = REG_FIELD(0x5e, 0, 1), 136 + [F_REVISION] = REG_FIELD(0x62, 0, 1), 137 + }; 138 + 139 + static const struct reg_field rt9770_chg_fields[F_MAX_FIELD] = { 140 + [F_VBATOVP] = REG_FIELD(0x08, 0, 4), 141 + [F_VBATOVP_EN] = REG_FIELD(0x08, 7, 7), 142 + [F_IBATOCP] = REG_FIELD(0x09, 0, 5), 143 + [F_IBATOCP_EN] = REG_FIELD(0x09, 7, 7), 144 + [F_VBUSOVP] = REG_FIELD(0x06, 0, 5), 145 + [F_VBUSOVP_EN] = REG_FIELD(0x06, 7, 7), 146 + [F_IBUSOCP] = REG_FIELD(0x07, 0, 4), 147 + [F_IBUSOCP_EN] = REG_FIELD(0x07, 5, 5), 148 + [F_SWITCHING] = REG_FIELD(0x5c, 7, 7), 149 + [F_REG_RST] = REG_FIELD(0x00, 7, 7), 150 + [F_CHG_EN] = REG_FIELD(0x00, 6, 6), 151 + [F_OP_MODE] = REG_FIELD(0x00, 5, 5), 152 + [F_WDT_DIS] = REG_FIELD(0x00, 3, 3), 153 + [F_WDT_TMR] = REG_FIELD(0x00, 0, 2), 154 + [F_DEV_ID] = REG_FIELD(0x60, 0, 3), 155 + [F_BC12_EN] = REG_FIELD(0x03, 7, 7), 156 + [F_USB_STATE] = REG_FIELD(0x02, 5, 7), 157 + [F_VBUS_STATE] = REG_FIELD(0x4c, 0, 0), 158 + [F_IBAT_RSEN] = REG_FIELD(0x5e, 0, 1), 159 + [F_REVISION] = REG_FIELD(0x62, 3, 7), 160 + }; 161 + 162 + /* All converted to microvolt or microamp */ 163 + static const struct linear_range rt9756_chg_ranges[R_MAX_RANGE] = { 164 + LINEAR_RANGE_IDX(R_VBATOVP, 4200000, 0, 31, 25000), 165 + LINEAR_RANGE_IDX(R_IBATOCP, 2000000, 0, 63, 100000), 166 + LINEAR_RANGE_IDX(R_VBUSOVP, 3000000, 0, 63, 50000), 167 + LINEAR_RANGE_IDX(R_IBUSOCP, 1000000, 0, 31, 250000), 168 + }; 169 + 170 + struct charger_event { 171 + unsigned int flag1; 172 + unsigned int flag2; 173 + unsigned int flag3; 174 + unsigned int flag4; 175 + }; 176 + 177 + struct rt9756_data { 178 + struct device *dev; 179 + struct regmap *regmap; 180 + struct regmap_field *rm_fields[F_MAX_FIELD]; 181 + struct power_supply *psy; 182 + struct power_supply *bat_psy; 183 + struct mutex adc_lock; 184 + struct power_supply_desc psy_desc; 185 + struct power_supply_desc bat_psy_desc; 186 + struct charger_event chg_evt; 187 + unsigned int rg_resistor; 188 + unsigned int real_resistor; 189 + enum rt9756_model model; 190 + atomic_t usb_type; 191 + }; 192 + 193 + struct rt975x_dev_data { 194 + const struct regmap_config *regmap_config; 195 + const struct reg_field *reg_fields; 196 + const struct reg_sequence *init_regs; 197 + size_t num_init_regs; 198 + int (*check_device_model)(struct rt9756_data *data); 199 + }; 200 + 201 + static int rt9756_get_value_field_range(struct rt9756_data *data, enum rt9756_fields en_field, 202 + enum rt9756_fields field, enum rt9756_ranges rsel, int *val) 203 + { 204 + const struct linear_range *range = rt9756_chg_ranges + rsel; 205 + unsigned int enable, selector, value; 206 + int ret; 207 + 208 + ret = regmap_field_read(data->rm_fields[en_field], &enable); 209 + if (ret) 210 + return ret; 211 + 212 + if (!enable) { 213 + *val = 0; 214 + return 0; 215 + } 216 + 217 + ret = regmap_field_read(data->rm_fields[field], &selector); 218 + if (ret) 219 + return ret; 220 + 221 + ret = linear_range_get_value(range, selector, &value); 222 + if (ret) 223 + return ret; 224 + 225 + *val = (int)value; 226 + 227 + return 0; 228 + } 229 + 230 + static int rt9756_set_value_field_range(struct rt9756_data *data, enum rt9756_fields en_field, 231 + enum rt9756_fields field, enum rt9756_ranges rsel, int val) 232 + { 233 + const struct linear_range *range = rt9756_chg_ranges + rsel; 234 + unsigned int selector, value; 235 + int ret; 236 + 237 + if (!val) 238 + return regmap_field_write(data->rm_fields[en_field], 0); 239 + 240 + value = (unsigned int)val; 241 + linear_range_get_selector_within(range, value, &selector); 242 + ret = regmap_field_write(data->rm_fields[field], selector); 243 + if (ret) 244 + return ret; 245 + 246 + return regmap_field_write(data->rm_fields[en_field], 1); 247 + } 248 + 249 + static int rt9756_get_adc(struct rt9756_data *data, enum rt9756_adc_chan chan, 250 + int *val) 251 + { 252 + struct regmap *regmap = data->regmap; 253 + unsigned int reg_addr = RT9756_REG_VBUSADC + chan * 2; 254 + unsigned int mask = RT9756_ADCEN_MASK | RT9756_ADCONCE_MASK; 255 + unsigned int shift = 0, adc_cntl; 256 + __be16 raws; 257 + int scale, offset = 0, ret; 258 + 259 + guard(mutex)(&data->adc_lock); 260 + 261 + ret = regmap_update_bits(regmap, RT9756_REG_ADCCTL, mask, mask); 262 + if (ret) 263 + return ret; 264 + 265 + ret = regmap_read_poll_timeout(regmap, RT9756_REG_ADCCTL, adc_cntl, 266 + !(adc_cntl & RT9756_ADCEN_MASK), 267 + RT9756_ADC_CONVTIME, RT9756_ADC_MAXWAIT); 268 + if (ret && ret != -ETIMEDOUT) 269 + return ret; 270 + 271 + ret = regmap_raw_read(regmap, reg_addr, &raws, sizeof(raws)); 272 + if (ret) 273 + return ret; 274 + 275 + /* 276 + * TDIE LSB 1'c, others LSB 1000uV or 1000uA. 277 + * Rsense ratio is needed for IBAT channel 278 + */ 279 + if (chan == ADC_TDIE) { 280 + scale = 10; 281 + shift = 8; 282 + offset = -40; 283 + } else if (chan == ADC_IBAT) 284 + scale = 1000 * data->rg_resistor / data->real_resistor; 285 + else 286 + scale = 1000; 287 + 288 + *val = ((be16_to_cpu(raws) >> shift) + offset) * scale; 289 + 290 + return regmap_update_bits(regmap, RT9756_REG_ADCCTL, mask, 0); 291 + } 292 + 293 + static int rt9756_get_switching_state(struct rt9756_data *data, int *status) 294 + { 295 + unsigned int switching_state; 296 + int ret; 297 + 298 + ret = regmap_field_read(data->rm_fields[F_SWITCHING], &switching_state); 299 + if (ret) 300 + return ret; 301 + 302 + if (switching_state) 303 + *status = POWER_SUPPLY_STATUS_CHARGING; 304 + else 305 + *status = POWER_SUPPLY_STATUS_NOT_CHARGING; 306 + 307 + return 0; 308 + } 309 + 310 + static int rt9756_get_charger_health(struct rt9756_data *data) 311 + { 312 + struct charger_event *evt = &data->chg_evt; 313 + 314 + if (evt->flag2 & RT9756_EVT_VBUSLOW_ERR) 315 + return POWER_SUPPLY_HEALTH_UNDERVOLTAGE; 316 + 317 + if (evt->flag1 & RT9756_EVT_BUSOVP || evt->flag2 & RT9756_EVT_BATOVP || 318 + evt->flag4 & RT9756_EVT_OUTOVP) 319 + return POWER_SUPPLY_HEALTH_OVERVOLTAGE; 320 + 321 + if (evt->flag1 & RT9756_EVT_BUSOCP || evt->flag2 & RT9756_EVT_BATOCP) 322 + return POWER_SUPPLY_HEALTH_OVERCURRENT; 323 + 324 + if (evt->flag1 & RT9756_EVT_BUSUCP) 325 + return POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; 326 + 327 + if (evt->flag2 & RT9756_EVT_TDIEOTP) 328 + return POWER_SUPPLY_HEALTH_OVERHEAT; 329 + 330 + if (evt->flag3 & RT9756_EVT_WDT) 331 + return POWER_SUPPLY_HEALTH_WATCHDOG_TIMER_EXPIRE; 332 + 333 + return POWER_SUPPLY_HEALTH_GOOD; 334 + } 335 + 336 + static int rt9756_get_charger_online(struct rt9756_data *data, int *val) 337 + { 338 + unsigned int online; 339 + int ret; 340 + 341 + ret = regmap_field_read(data->rm_fields[F_VBUS_STATE], &online); 342 + if (ret) 343 + return ret; 344 + 345 + *val = !!online; 346 + return 0; 347 + } 348 + 349 + static int rt9756_get_vbus_ovp(struct rt9756_data *data, int *val) 350 + { 351 + unsigned int opmode; 352 + int ovpval, ret; 353 + 354 + /* operating mode -> 0 bypass, 1 div2 */ 355 + ret = regmap_field_read(data->rm_fields[F_OP_MODE], &opmode); 356 + if (ret) 357 + return ret; 358 + 359 + ret = rt9756_get_value_field_range(data, F_VBUSOVP_EN, F_VBUSOVP, R_VBUSOVP, &ovpval); 360 + if (ret) 361 + return ret; 362 + 363 + *val = opmode ? ovpval * 2 : ovpval; 364 + return 0; 365 + } 366 + 367 + static int rt9756_set_vbus_ovp(struct rt9756_data *data, int val) 368 + { 369 + unsigned int opmode; 370 + int ret; 371 + 372 + /* operating mode -> 0 bypass, 1 div2 */ 373 + ret = regmap_field_read(data->rm_fields[F_OP_MODE], &opmode); 374 + if (ret) 375 + return ret; 376 + 377 + return rt9756_set_value_field_range(data, F_VBUSOVP_EN, F_VBUSOVP, R_VBUSOVP, 378 + opmode ? val / 2 : val); 379 + } 380 + 381 + static const char * const rt9756_manufacturer = "Richtek Technology Corp."; 382 + static const char * const rt9756_model[MODEL_MAX] = { "RT9756", "RT9757", "RT9770" }; 383 + 384 + static int rt9756_psy_get_property(struct power_supply *psy, 385 + enum power_supply_property psp, 386 + union power_supply_propval *val) 387 + { 388 + struct rt9756_data *data = power_supply_get_drvdata(psy); 389 + int *pval = &val->intval; 390 + 391 + switch (psp) { 392 + case POWER_SUPPLY_PROP_STATUS: 393 + return rt9756_get_switching_state(data, pval); 394 + case POWER_SUPPLY_PROP_HEALTH: 395 + *pval = rt9756_get_charger_health(data); 396 + return 0; 397 + case POWER_SUPPLY_PROP_ONLINE: 398 + return rt9756_get_charger_online(data, pval); 399 + case POWER_SUPPLY_PROP_VOLTAGE_MAX: 400 + return rt9756_get_vbus_ovp(data, pval); 401 + case POWER_SUPPLY_PROP_VOLTAGE_NOW: 402 + return rt9756_get_adc(data, ADC_VBUS, pval); 403 + case POWER_SUPPLY_PROP_CURRENT_MAX: 404 + return rt9756_get_value_field_range(data, F_IBUSOCP_EN, F_IBUSOCP, R_IBUSOCP, pval); 405 + case POWER_SUPPLY_PROP_CURRENT_NOW: 406 + return rt9756_get_adc(data, ADC_IBUS, pval); 407 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: 408 + return rt9756_get_value_field_range(data, F_VBATOVP_EN, F_VBATOVP, R_VBATOVP, pval); 409 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: 410 + return rt9756_get_value_field_range(data, F_IBATOCP_EN, F_IBATOCP, R_IBATOCP, pval); 411 + case POWER_SUPPLY_PROP_TEMP: 412 + return rt9756_get_adc(data, ADC_TDIE, pval); 413 + case POWER_SUPPLY_PROP_USB_TYPE: 414 + *pval = atomic_read(&data->usb_type); 415 + return 0; 416 + case POWER_SUPPLY_PROP_MODEL_NAME: 417 + val->strval = rt9756_model[data->model]; 418 + return 0; 419 + case POWER_SUPPLY_PROP_MANUFACTURER: 420 + val->strval = rt9756_manufacturer; 421 + return 0; 422 + default: 423 + return -ENODATA; 424 + } 425 + } 426 + 427 + static int rt9756_psy_set_property(struct power_supply *psy, 428 + enum power_supply_property psp, 429 + const union power_supply_propval *val) 430 + { 431 + struct rt9756_data *data = power_supply_get_drvdata(psy); 432 + int intval = val->intval; 433 + 434 + switch (psp) { 435 + case POWER_SUPPLY_PROP_STATUS: 436 + memset(&data->chg_evt, 0, sizeof(data->chg_evt)); 437 + return regmap_field_write(data->rm_fields[F_CHG_EN], !!intval); 438 + case POWER_SUPPLY_PROP_VOLTAGE_MAX: 439 + return rt9756_set_vbus_ovp(data, intval); 440 + case POWER_SUPPLY_PROP_CURRENT_MAX: 441 + return rt9756_set_value_field_range(data, F_IBUSOCP_EN, F_IBUSOCP, R_IBUSOCP, 442 + intval); 443 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: 444 + return rt9756_set_value_field_range(data, F_VBATOVP_EN, F_VBATOVP, R_VBATOVP, 445 + intval); 446 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: 447 + return rt9756_set_value_field_range(data, F_IBATOCP_EN, F_IBATOCP, R_IBATOCP, 448 + intval); 449 + case POWER_SUPPLY_PROP_USB_TYPE: 450 + return regmap_field_write(data->rm_fields[F_BC12_EN], !!intval); 451 + default: 452 + return -EINVAL; 453 + } 454 + } 455 + 456 + static const enum power_supply_property rt9756_psy_properties[] = { 457 + POWER_SUPPLY_PROP_STATUS, 458 + POWER_SUPPLY_PROP_ONLINE, 459 + POWER_SUPPLY_PROP_HEALTH, 460 + POWER_SUPPLY_PROP_ONLINE, 461 + POWER_SUPPLY_PROP_VOLTAGE_MAX, 462 + POWER_SUPPLY_PROP_VOLTAGE_NOW, 463 + POWER_SUPPLY_PROP_CURRENT_MAX, 464 + POWER_SUPPLY_PROP_CURRENT_NOW, 465 + POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX, 466 + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, 467 + POWER_SUPPLY_PROP_TEMP, 468 + POWER_SUPPLY_PROP_USB_TYPE, 469 + POWER_SUPPLY_PROP_MODEL_NAME, 470 + POWER_SUPPLY_PROP_MANUFACTURER, 471 + }; 472 + 473 + static int rt9756_bat_psy_get_property(struct power_supply *psy, 474 + enum power_supply_property psp, 475 + union power_supply_propval *val) 476 + { 477 + struct rt9756_data *data = power_supply_get_drvdata(psy); 478 + int *pval = &val->intval; 479 + 480 + switch (psp) { 481 + case POWER_SUPPLY_PROP_TECHNOLOGY: 482 + *pval = POWER_SUPPLY_TECHNOLOGY_LION; 483 + return 0; 484 + case POWER_SUPPLY_PROP_VOLTAGE_NOW: 485 + return rt9756_get_adc(data, ADC_VBAT, pval); 486 + case POWER_SUPPLY_PROP_CURRENT_NOW: 487 + return rt9756_get_adc(data, ADC_IBAT, pval); 488 + default: 489 + return -ENODATA; 490 + } 491 + } 492 + 493 + static const enum power_supply_property rt9756_bat_psy_properties[] = { 494 + POWER_SUPPLY_PROP_TECHNOLOGY, 495 + POWER_SUPPLY_PROP_VOLTAGE_NOW, 496 + POWER_SUPPLY_PROP_CURRENT_NOW, 497 + }; 498 + 499 + static int rt9756_psy_property_is_writeable(struct power_supply *psy, 500 + enum power_supply_property psp) 501 + { 502 + switch (psp) { 503 + case POWER_SUPPLY_PROP_STATUS: 504 + case POWER_SUPPLY_PROP_ONLINE: 505 + case POWER_SUPPLY_PROP_VOLTAGE_MAX: 506 + case POWER_SUPPLY_PROP_CURRENT_MAX: 507 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: 508 + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: 509 + case POWER_SUPPLY_PROP_USB_TYPE: 510 + return 1; 511 + default: 512 + return 0; 513 + } 514 + } 515 + 516 + static const unsigned int rt9756_wdt_millisecond[] = { 517 + 500, 1000, 5000, 30000, 40000, 80000, 128000, 255000 518 + }; 519 + 520 + static ssize_t watchdog_timer_show(struct device *dev, 521 + struct device_attribute *attr, char *buf) 522 + { 523 + struct power_supply *psy = to_power_supply(dev); 524 + struct rt9756_data *data = power_supply_get_drvdata(psy); 525 + unsigned int wdt_tmr_now = 0, wdt_sel, wdt_dis; 526 + int ret; 527 + 528 + ret = regmap_field_read(data->rm_fields[F_WDT_DIS], &wdt_dis); 529 + if (ret) 530 + return ret; 531 + 532 + if (!wdt_dis) { 533 + ret = regmap_field_read(data->rm_fields[F_WDT_TMR], &wdt_sel); 534 + if (ret) 535 + return ret; 536 + 537 + wdt_tmr_now = rt9756_wdt_millisecond[wdt_sel]; 538 + } 539 + 540 + return sysfs_emit(buf, "%d\n", wdt_tmr_now); 541 + } 542 + 543 + static ssize_t watchdog_timer_store(struct device *dev, 544 + struct device_attribute *attr, 545 + const char *buf, size_t count) 546 + { 547 + struct power_supply *psy = to_power_supply(dev); 548 + struct rt9756_data *data = power_supply_get_drvdata(psy); 549 + unsigned int wdt_set, wdt_sel; 550 + int ret; 551 + 552 + ret = kstrtouint(buf, 10, &wdt_set); 553 + if (ret) 554 + return ret; 555 + 556 + ret = regmap_field_write(data->rm_fields[F_WDT_DIS], 1); 557 + if (ret) 558 + return ret; 559 + 560 + wdt_sel = find_closest(wdt_set, rt9756_wdt_millisecond, 561 + ARRAY_SIZE(rt9756_wdt_millisecond)); 562 + 563 + ret = regmap_field_write(data->rm_fields[F_WDT_TMR], wdt_sel); 564 + if (ret) 565 + return ret; 566 + 567 + if (wdt_set) { 568 + ret = regmap_field_write(data->rm_fields[F_WDT_DIS], 0); 569 + if (ret) 570 + return ret; 571 + } 572 + 573 + return count; 574 + } 575 + 576 + static const char * const rt9756_opmode_str[] = { "bypass", "div2" }; 577 + 578 + static ssize_t operation_mode_show(struct device *dev, 579 + struct device_attribute *attr, char *buf) 580 + { 581 + struct power_supply *psy = to_power_supply(dev); 582 + struct rt9756_data *data = power_supply_get_drvdata(psy); 583 + unsigned int opmode; 584 + int ret; 585 + 586 + ret = regmap_field_read(data->rm_fields[F_OP_MODE], &opmode); 587 + if (ret) 588 + return ret; 589 + 590 + return sysfs_emit(buf, "%s\n", rt9756_opmode_str[opmode]); 591 + } 592 + 593 + static ssize_t operation_mode_store(struct device *dev, 594 + struct device_attribute *attr, 595 + const char *buf, size_t count) 596 + { 597 + struct power_supply *psy = to_power_supply(dev); 598 + struct rt9756_data *data = power_supply_get_drvdata(psy); 599 + int index, ret; 600 + 601 + index = sysfs_match_string(rt9756_opmode_str, buf); 602 + if (index < 0) 603 + return index; 604 + 605 + ret = regmap_field_write(data->rm_fields[F_OP_MODE], index); 606 + 607 + return ret ?: count; 608 + } 609 + 610 + static DEVICE_ATTR_RW(watchdog_timer); 611 + static DEVICE_ATTR_RW(operation_mode); 612 + 613 + static struct attribute *rt9756_sysfs_attrs[] = { 614 + &dev_attr_watchdog_timer.attr, 615 + &dev_attr_operation_mode.attr, 616 + NULL 617 + }; 618 + ATTRIBUTE_GROUPS(rt9756_sysfs); 619 + 620 + static int rt9756_register_psy(struct rt9756_data *data) 621 + { 622 + struct power_supply_desc *desc = &data->psy_desc; 623 + struct power_supply_desc *bat_desc = &data->bat_psy_desc; 624 + struct power_supply_config cfg = {}, bat_cfg = {}; 625 + struct device *dev = data->dev; 626 + char *psy_name, *bat_psy_name, **supplied_to; 627 + 628 + bat_cfg.drv_data = data; 629 + bat_cfg.fwnode = dev_fwnode(dev); 630 + 631 + bat_psy_name = devm_kasprintf(dev, GFP_KERNEL, "rt9756-%s-battery", dev_name(dev)); 632 + if (!bat_psy_name) 633 + return -ENOMEM; 634 + 635 + bat_desc->name = bat_psy_name; 636 + bat_desc->type = POWER_SUPPLY_TYPE_BATTERY; 637 + bat_desc->properties = rt9756_bat_psy_properties; 638 + bat_desc->num_properties = ARRAY_SIZE(rt9756_bat_psy_properties); 639 + bat_desc->get_property = rt9756_bat_psy_get_property; 640 + 641 + data->bat_psy = devm_power_supply_register(dev, bat_desc, &bat_cfg); 642 + if (IS_ERR(data->bat_psy)) 643 + return dev_err_probe(dev, PTR_ERR(data->bat_psy), "Failed to register battery\n"); 644 + 645 + supplied_to = devm_kzalloc(dev, sizeof(*supplied_to), GFP_KERNEL); 646 + if (!supplied_to) 647 + return -ENOMEM; 648 + 649 + /* Link charger psy to battery psy */ 650 + supplied_to[0] = bat_psy_name; 651 + 652 + cfg.drv_data = data; 653 + cfg.fwnode = dev_fwnode(dev); 654 + cfg.attr_grp = rt9756_sysfs_groups; 655 + cfg.supplied_to = supplied_to; 656 + cfg.num_supplicants = 1; 657 + 658 + psy_name = devm_kasprintf(dev, GFP_KERNEL, "rt9756-%s", dev_name(dev)); 659 + if (!psy_name) 660 + return -ENOMEM; 661 + 662 + desc->name = psy_name; 663 + desc->type = POWER_SUPPLY_TYPE_USB; 664 + desc->usb_types = BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN) | BIT(POWER_SUPPLY_USB_TYPE_SDP) | 665 + BIT(POWER_SUPPLY_USB_TYPE_DCP) | BIT(POWER_SUPPLY_USB_TYPE_CDP); 666 + desc->properties = rt9756_psy_properties; 667 + desc->num_properties = ARRAY_SIZE(rt9756_psy_properties); 668 + desc->property_is_writeable = rt9756_psy_property_is_writeable; 669 + desc->get_property = rt9756_psy_get_property; 670 + desc->set_property = rt9756_psy_set_property; 671 + 672 + data->psy = devm_power_supply_register(dev, desc, &cfg); 673 + 674 + return PTR_ERR_OR_ZERO(data->psy); 675 + } 676 + 677 + static int rt9756_get_usb_type(struct rt9756_data *data) 678 + { 679 + unsigned int type; 680 + int report_type, ret; 681 + 682 + ret = regmap_field_read(data->rm_fields[F_USB_STATE], &type); 683 + if (ret) 684 + return ret; 685 + 686 + switch (type) { 687 + case USB_SDP: 688 + case USB_NSTD: 689 + report_type = POWER_SUPPLY_USB_TYPE_SDP; 690 + break; 691 + case USB_DCP: 692 + report_type = POWER_SUPPLY_USB_TYPE_DCP; 693 + break; 694 + case USB_CDP: 695 + report_type = POWER_SUPPLY_USB_TYPE_CDP; 696 + break; 697 + case USB_NO_VBUS: 698 + default: 699 + report_type = POWER_SUPPLY_USB_TYPE_UNKNOWN; 700 + break; 701 + } 702 + 703 + atomic_set(&data->usb_type, report_type); 704 + return 0; 705 + } 706 + 707 + static irqreturn_t rt9756_irq_handler(int irq, void *devid) 708 + { 709 + struct rt9756_data *data = devid; 710 + struct regmap *regmap = data->regmap; 711 + struct charger_event *evt = &data->chg_evt; 712 + unsigned int bc12_flag = 0; 713 + int ret; 714 + 715 + ret = regmap_read(regmap, RT9756_REG_INTFLAG1, &evt->flag1); 716 + if (ret) 717 + return IRQ_NONE; 718 + 719 + ret = regmap_read(regmap, RT9756_REG_INTFLAG2, &evt->flag2); 720 + if (ret) 721 + return IRQ_NONE; 722 + 723 + ret = regmap_read(regmap, RT9756_REG_INTFLAG3, &evt->flag3); 724 + if (ret) 725 + return IRQ_NONE; 726 + 727 + if (data->model != MODEL_RT9770) { 728 + ret = regmap_read(regmap, RT9756_REG_INTFLAG4, &evt->flag4); 729 + if (ret) 730 + return IRQ_NONE; 731 + 732 + ret = regmap_read(regmap, RT9756_REG_BC12FLAG, &bc12_flag); 733 + if (ret) 734 + return IRQ_NONE; 735 + } 736 + 737 + dev_dbg(data->dev, "events: 0x%02x,%02x,%02x,%02x,%02x\n", evt->flag1, evt->flag2, 738 + evt->flag3, evt->flag4, bc12_flag); 739 + 740 + if (evt->flag2 & RT9756_EVT_VAC_INSERT) { 741 + ret = regmap_field_write(data->rm_fields[F_BC12_EN], 1); 742 + if (ret) 743 + return IRQ_NONE; 744 + } 745 + 746 + if (evt->flag3 & RT9756_EVT_VAC_UVLO) 747 + atomic_set(&data->usb_type, POWER_SUPPLY_USB_TYPE_UNKNOWN); 748 + 749 + if (bc12_flag & RT9756_EVT_BC12_DONE) { 750 + ret = rt9756_get_usb_type(data); 751 + if (ret) 752 + return IRQ_NONE; 753 + } 754 + 755 + power_supply_changed(data->psy); 756 + 757 + return IRQ_HANDLED; 758 + } 759 + 760 + static int rt9756_config_batsense_resistor(struct rt9756_data *data) 761 + { 762 + unsigned int shunt_resistor_uohms = 2000, rsense_sel; 763 + 764 + device_property_read_u32(data->dev, "shunt-resistor-micro-ohms", &shunt_resistor_uohms); 765 + 766 + if (!shunt_resistor_uohms || shunt_resistor_uohms > 5000) 767 + return -EINVAL; 768 + 769 + data->real_resistor = shunt_resistor_uohms; 770 + 771 + /* Always choose the larger or equal one to prevent false ocp alarm */ 772 + if (shunt_resistor_uohms <= 1000) { 773 + rsense_sel = 0; 774 + data->rg_resistor = 1000; 775 + } else if (shunt_resistor_uohms <= 2000) { 776 + rsense_sel = 1; 777 + data->rg_resistor = 2000; 778 + } else { 779 + rsense_sel = 2; 780 + data->rg_resistor = 5000; 781 + } 782 + 783 + return regmap_field_write(data->rm_fields[F_IBAT_RSEN], rsense_sel); 784 + } 785 + 786 + static const struct reg_sequence rt9756_init_regs[] = { 787 + REG_SEQ(0x00, 0x80, 1000), /* REG_RESET */ 788 + REG_SEQ0(0x04, 0x13), /* VACOVP/OVPGATE 12V */ 789 + REG_SEQ0(0x00, 0x28), /* WDT_DIS = 1 */ 790 + REG_SEQ0(0x0c, 0x02), /* MASK FLAG1 */ 791 + REG_SEQ0(0x0e, 0x06), /* MASK FLAG2 */ 792 + REG_SEQ0(0x10, 0xca), /* MASK FLAG3 */ 793 + REG_SEQ0(0x44, 0xa0), /* BC12_EN */ 794 + REG_SEQ0(0x47, 0x07), /* MASK BC12FLAG */ 795 + REG_SEQ0(0x4a, 0xfe), /* MASK FLAG4 */ 796 + REG_SEQ0(0x5c, 0x40), /* MASK CON_SWITCHING */ 797 + REG_SEQ0(0x63, 0x01), /* MASK VDDA_UVLO */ 798 + }; 799 + 800 + static const struct reg_sequence rt9770_init_regs[] = { 801 + REG_SEQ(0x00, 0x80, 1000), /* REG_RESET */ 802 + REG_SEQ0(0x04, 0x13), /* VACOVP/OVPGATE 12V */ 803 + REG_SEQ0(0x00, 0x28), /* WDT_DIS = 1 */ 804 + REG_SEQ0(0x0c, 0x02), /* MASK FLAG1 */ 805 + REG_SEQ0(0x0e, 0x06), /* MASK FLAG2 */ 806 + REG_SEQ0(0x10, 0xca), /* MASK FLAG3 */ 807 + REG_SEQ0(0x5c, 0x40), /* MASK CON_SWITCHING */ 808 + REG_SEQ0(0x63, 0x01), /* MASK VDDA_UVLO */ 809 + }; 810 + 811 + static const struct regmap_config rt9756_regmap_config = { 812 + .name = "rt9756", 813 + .reg_bits = 16, 814 + .val_bits = 8, 815 + .max_register = 0x1ff, 816 + }; 817 + 818 + static const struct regmap_config rt9770_regmap_config = { 819 + .name = "rt9770", 820 + .reg_bits = 8, 821 + .val_bits = 8, 822 + .max_register = 0xff, 823 + }; 824 + 825 + static int rt9756_check_device_model(struct rt9756_data *data) 826 + { 827 + struct device *dev = data->dev; 828 + unsigned int revid; 829 + int ret; 830 + 831 + ret = regmap_field_read(data->rm_fields[F_REVISION], &revid); 832 + if (ret) 833 + return dev_err_probe(dev, ret, "Failed to read revid\n"); 834 + 835 + if (revid == RT9757_REVID || revid == RT9757A_REVID) 836 + data->model = MODEL_RT9757; 837 + else if (revid == RT9756_REVID || revid == RT9756A_REVID) 838 + data->model = MODEL_RT9756; 839 + else 840 + return dev_err_probe(dev, -EINVAL, "Unknown revision %d\n", revid); 841 + 842 + return 0; 843 + } 844 + 845 + static int rt9770_check_device_model(struct rt9756_data *data) 846 + { 847 + data->model = MODEL_RT9770; 848 + return 0; 849 + } 850 + 851 + static int rt9756_probe(struct i2c_client *i2c) 852 + { 853 + const struct rt975x_dev_data *dev_data; 854 + struct device *dev = &i2c->dev; 855 + struct rt9756_data *data; 856 + struct regmap *regmap; 857 + unsigned int devid; 858 + int ret; 859 + 860 + dev_data = device_get_match_data(dev); 861 + if (!dev_data) 862 + return dev_err_probe(dev, -EINVAL, "No device data found\n"); 863 + 864 + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 865 + if (!data) 866 + return -ENOMEM; 867 + 868 + data->dev = dev; 869 + mutex_init(&data->adc_lock); 870 + atomic_set(&data->usb_type, POWER_SUPPLY_USB_TYPE_UNKNOWN); 871 + i2c_set_clientdata(i2c, data); 872 + 873 + regmap = devm_regmap_init_i2c(i2c, dev_data->regmap_config); 874 + if (IS_ERR(regmap)) 875 + return dev_err_probe(dev, PTR_ERR(regmap), "Failed to init regmap\n"); 876 + 877 + data->regmap = regmap; 878 + 879 + ret = devm_regmap_field_bulk_alloc(dev, regmap, data->rm_fields, dev_data->reg_fields, 880 + F_MAX_FIELD); 881 + if (ret) 882 + return dev_err_probe(dev, ret, "Failed to alloc regmap fields\n"); 883 + 884 + /* Richtek Device ID check */ 885 + ret = regmap_field_read(data->rm_fields[F_DEV_ID], &devid); 886 + if (ret) 887 + return dev_err_probe(dev, ret, "Failed to read devid\n"); 888 + 889 + if (devid != RICHTEK_DEVID) 890 + return dev_err_probe(dev, -ENODEV, "Incorrect VID 0x%02x\n", devid); 891 + 892 + /* Get specific model */ 893 + ret = dev_data->check_device_model(data); 894 + if (ret) 895 + return ret; 896 + 897 + ret = regmap_register_patch(regmap, dev_data->init_regs, dev_data->num_init_regs); 898 + if (ret) 899 + return dev_err_probe(dev, ret, "Failed to init registers\n"); 900 + 901 + ret = rt9756_config_batsense_resistor(data); 902 + if (ret) 903 + return dev_err_probe(dev, ret, "Failed to config batsense resistor\n"); 904 + 905 + ret = rt9756_register_psy(data); 906 + if (ret) 907 + return dev_err_probe(dev, ret, "Failed to init power supply\n"); 908 + 909 + return devm_request_threaded_irq(dev, i2c->irq, NULL, rt9756_irq_handler, IRQF_ONESHOT, 910 + dev_name(dev), data); 911 + } 912 + 913 + static void rt9756_shutdown(struct i2c_client *i2c) 914 + { 915 + struct rt9756_data *data = i2c_get_clientdata(i2c); 916 + 917 + regmap_field_write(data->rm_fields[F_REG_RST], 1); 918 + } 919 + 920 + static const struct rt975x_dev_data rt9756_dev_data = { 921 + .regmap_config = &rt9756_regmap_config, 922 + .reg_fields = rt9756_chg_fields, 923 + .init_regs = rt9756_init_regs, 924 + .num_init_regs = ARRAY_SIZE(rt9756_init_regs), 925 + .check_device_model = rt9756_check_device_model, 926 + }; 927 + 928 + static const struct rt975x_dev_data rt9770_dev_data = { 929 + .regmap_config = &rt9770_regmap_config, 930 + .reg_fields = rt9770_chg_fields, 931 + .init_regs = rt9770_init_regs, 932 + .num_init_regs = ARRAY_SIZE(rt9770_init_regs), 933 + .check_device_model = rt9770_check_device_model, 934 + }; 935 + 936 + static const struct of_device_id rt9756_device_match_table[] = { 937 + { .compatible = "richtek,rt9756", .data = &rt9756_dev_data }, 938 + { .compatible = "richtek,rt9770", .data = &rt9770_dev_data }, 939 + {} 940 + }; 941 + MODULE_DEVICE_TABLE(of, rt9756_device_match_table); 942 + 943 + static struct i2c_driver rt9756_charger_driver = { 944 + .driver = { 945 + .name = "rt9756", 946 + .of_match_table = rt9756_device_match_table, 947 + }, 948 + .probe = rt9756_probe, 949 + .shutdown = rt9756_shutdown, 950 + }; 951 + module_i2c_driver(rt9756_charger_driver); 952 + 953 + MODULE_DESCRIPTION("Richtek RT9756 charger driver"); 954 + MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>"); 955 + MODULE_LICENSE("GPL");
+8 -2
drivers/power/supply/wm831x_power.c
··· 144 144 struct wm831x_power, 145 145 usb_notify); 146 146 unsigned int i, best; 147 + int ret; 147 148 148 149 /* Find the highest supported limit */ 149 150 best = 0; ··· 157 156 dev_dbg(wm831x_power->wm831x->dev, 158 157 "Limiting USB current to %umA", wm831x_usb_limits[best]); 159 158 160 - wm831x_set_bits(wm831x_power->wm831x, WM831X_POWER_STATE, 161 - WM831X_USB_ILIM_MASK, best); 159 + ret = wm831x_set_bits(wm831x_power->wm831x, WM831X_POWER_STATE, 160 + WM831X_USB_ILIM_MASK, best); 161 + if (ret < 0) { 162 + dev_err(wm831x_power->wm831x->dev, 163 + "Failed to set USB current limit: %d\n", ret); 164 + return ret; 165 + } 162 166 163 167 return 0; 164 168 }
+2
include/linux/power/max77705_charger.h
··· 123 123 #define MAX77705_DISABLE_SKIP 1 124 124 #define MAX77705_AUTO_SKIP 0 125 125 126 + #define AICL_WORK_DELAY_MS 100 127 + 126 128 /* uA */ 127 129 #define MAX77705_CURRENT_CHGIN_STEP 25000 128 130 #define MAX77705_CURRENT_CHG_STEP 50000