* [PATCH 0/3] power: supply: battery: Allow separate charging limits vs. discharging
@ 2026-11-09 9:41 Alexey Charkov
2026-11-09 9:41 ` [PATCH 1/3] dt-bindings: power: supply: battery: Add a charging temperature range Alexey Charkov
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Alexey Charkov @ 2026-11-09 9:41 UTC (permalink / raw)
To: Sebastian Reichel, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-pm, devicetree, linux-kernel, Alexey Charkov
Some batteries specify different operating temperature ranges when
charging vs. when discharging, e.g. charge at 0C to 45C, but discharge
at up to -20C to 60C. Current DT bindings and power supply core don't
allow that, so extend them with additional properties so that a separate
limit could be programmed for when a charger should cut voltage going into
the battery vs. when the system itself should shut down.
Additionally, allow the DT to specify voltage/current limits to be applied
when the battery is being charged in the "alert" band (either high or low
temperature, which often requires derating especially at the low end).
Signed-off-by: Alexey Charkov <alchark@flipper.net>
---
Alexey Charkov (3):
dt-bindings: power: supply: battery: Add a charging temperature range
power: supply: core: Read the charging temperature range and alert settings
power: supply: samsung-sdi-battery: Set the charging temperature range
.../devicetree/bindings/power/supply/battery.yaml | 45 +++++++++++++++++++++-
drivers/power/supply/power_supply_core.c | 16 ++++++++
drivers/power/supply/samsung-sdi-battery.c | 12 ++++++
include/linux/power_supply.h | 16 ++++++--
4 files changed, 83 insertions(+), 6 deletions(-)
---
base-commit: ddfe51b0a0f5dc9e415cc2c8ad8db17532dd426b
change-id: 20261109-battery-charge-temp-range-37fc54d4e3a3
Best regards,
--
Alexey Charkov <alchark@flipper.net>
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/3] dt-bindings: power: supply: battery: Add a charging temperature range
2026-11-09 9:41 [PATCH 0/3] power: supply: battery: Allow separate charging limits vs. discharging Alexey Charkov
@ 2026-11-09 9:41 ` Alexey Charkov
2026-11-09 9:41 ` [PATCH 2/3] power: supply: core: Read the charging temperature range and alert settings Alexey Charkov
2026-11-09 9:41 ` [PATCH 3/3] power: supply: samsung-sdi-battery: Set the charging temperature range Alexey Charkov
2 siblings, 0 replies; 5+ messages in thread
From: Alexey Charkov @ 2026-11-09 9:41 UTC (permalink / raw)
To: Sebastian Reichel, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-pm, devicetree, linux-kernel, Alexey Charkov
Describe batteries rated for separate charging and discharging
temperature ranges, such as 0-45C for charging and -20-60C for
discharging, often with a reduced charge current near the ends of the
charging range: operating-range-celsius holds a single range, and
existing users read it both as the limit for any use of the battery and
as the limit for charging.
Add charge-temp-range-celsius for the charging range, falling back to
operating-range-celsius when absent, and state that
operating-range-celsius covers discharging. Add the charge current and
voltage to use between alert-celsius and the charging range limits, to
describe a reduced charge rate near those limits and none beyond them.
A missing half of an alert charge current and voltage pair falls back to
the matching constant-charge-* setting. alert-celsius is expected to fully
fall inside charge-temp-range-celsius, but when it does not,
charge-temp-range-celsius takes precedence to ensure no charge occurs
outside the allowed range.
Signed-off-by: Alexey Charkov <alchark@flipper.net>
---
.../devicetree/bindings/power/supply/battery.yaml | 45 +++++++++++++++++++++-
1 file changed, 43 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/power/supply/battery.yaml b/Documentation/devicetree/bindings/power/supply/battery.yaml
index 9575ee1491bb..d2f2ed9a01fe 100644
--- a/Documentation/devicetree/bindings/power/supply/battery.yaml
+++ b/Documentation/devicetree/bindings/power/supply/battery.yaml
@@ -111,11 +111,21 @@ properties:
for each of the battery capacity lookup table.
operating-range-celsius:
- description: operating temperature range of a battery
+ description: operating temperature range of a battery, in which it can be
+ discharged. Charging may be further restricted by
+ charge-temp-range-celsius.
items:
- description: minimum temperature at which battery can operate
- description: maximum temperature at which battery can operate
+ charge-temp-range-celsius:
+ description: temperature range in which the battery can be charged, within
+ operating-range-celsius. If absent, the battery can be charged in all of
+ operating-range-celsius. Outside this range the battery is not charged.
+ items:
+ - description: minimum temperature at which battery can be charged
+ - description: maximum temperature at which battery can be charged
+
ambient-celsius:
description: safe range of ambient temperature
items:
@@ -123,11 +133,39 @@ properties:
- description: alert when ambient temperature is higher than this value
alert-celsius:
- description: safe range of battery temperature
+ description: safe range of battery temperature. Where a limit of this
+ range lies within charge-temp-range-celsius, the battery is charged
+ between the two limits with the alert-low-temp-charge-* or
+ alert-high-temp-charge-* settings. Each of those that is absent falls
+ back to the corresponding constant-charge-* setting.
items:
- description: alert when battery temperature is lower than this value
- description: alert when battery temperature is higher than this value
+ alert-low-temp-charge-current-microamp:
+ description: charge current in place of
+ constant-charge-current-max-microamp, while the battery temperature is
+ between the lower limits of charge-temp-range-celsius and alert-celsius
+ minimum: 1
+
+ alert-low-temp-charge-voltage-microvolt:
+ description: charge voltage in place of
+ constant-charge-voltage-max-microvolt, while the battery temperature is
+ between the lower limits of charge-temp-range-celsius and alert-celsius
+ minimum: 1
+
+ alert-high-temp-charge-current-microamp:
+ description: charge current in place of
+ constant-charge-current-max-microamp, while the battery temperature is
+ between the upper limits of alert-celsius and charge-temp-range-celsius
+ minimum: 1
+
+ alert-high-temp-charge-voltage-microvolt:
+ description: charge voltage in place of
+ constant-charge-voltage-max-microvolt, while the battery temperature is
+ between the upper limits of alert-celsius and charge-temp-range-celsius
+ minimum: 1
+
# The volt-drop* -properties describe voltage-drop for a battery, described
# as VDROP in:
# https://patentimages.storage.googleapis.com/6c/f5/17/c1d901c220f6a9/US20150032394A1.pdf
@@ -200,8 +238,11 @@ examples:
ocv-capacity-table-2 = <4250000 100>, <4200000 95>, <4185000 90>;
resistance-temp-table = <20 100>, <10 90>, <0 80>, <(-10) 60>;
operating-range-celsius = <(-30) 50>;
+ charge-temp-range-celsius = <0 45>;
ambient-celsius = <(-5) 50>;
alert-celsius = <0 40>;
+ alert-high-temp-charge-current-microamp = <450000>;
+ alert-high-temp-charge-voltage-microvolt = <4100000>;
};
charger@11 {
--
2.56.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/3] power: supply: core: Read the charging temperature range and alert settings
2026-11-09 9:41 [PATCH 0/3] power: supply: battery: Allow separate charging limits vs. discharging Alexey Charkov
2026-11-09 9:41 ` [PATCH 1/3] dt-bindings: power: supply: battery: Add a charging temperature range Alexey Charkov
@ 2026-11-09 9:41 ` Alexey Charkov
2026-11-10 23:24 ` sashiko-bot
2026-11-09 9:41 ` [PATCH 3/3] power: supply: samsung-sdi-battery: Set the charging temperature range Alexey Charkov
2 siblings, 1 reply; 5+ messages in thread
From: Alexey Charkov @ 2026-11-09 9:41 UTC (permalink / raw)
To: Sebastian Reichel, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-pm, devicetree, linux-kernel, Alexey Charkov
Read charge-temp-range-celsius into new temp_charge_min and
temp_charge_max fields, falling back to the operating range when it is
absent, so that a charger can stop charging outside a narrower range
while the battery stays in use. Read the alert-*-temp-charge-*
properties into the existing alert_*_temp_charge_* fields, which no
firmware description could set before, and document them as applying
between the alert and charging limits.
Signed-off-by: Alexey Charkov <alchark@flipper.net>
---
drivers/power/supply/power_supply_core.c | 16 ++++++++++++++++
include/linux/power_supply.h | 16 ++++++++++++----
2 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c
index de15314ef954..3bfc4fb8687e 100644
--- a/drivers/power/supply/power_supply_core.c
+++ b/drivers/power/supply/power_supply_core.c
@@ -855,6 +855,14 @@ int power_supply_get_battery_info(struct power_supply *psy,
&info->constant_charge_voltage_max_uv);
fwnode_property_read_u32(fwnode, "factory-internal-resistance-micro-ohms",
&info->factory_internal_resistance_uohm);
+ fwnode_property_read_u32(fwnode, "alert-low-temp-charge-current-microamp",
+ &info->alert_low_temp_charge_current_ua);
+ fwnode_property_read_u32(fwnode, "alert-low-temp-charge-voltage-microvolt",
+ &info->alert_low_temp_charge_voltage_uv);
+ fwnode_property_read_u32(fwnode, "alert-high-temp-charge-current-microamp",
+ &info->alert_high_temp_charge_current_ua);
+ fwnode_property_read_u32(fwnode, "alert-high-temp-charge-voltage-microvolt",
+ &info->alert_high_temp_charge_voltage_uv);
if (!fwnode_property_read_u32_array(fwnode, "ambient-celsius",
min_max, ARRAY_SIZE(min_max))) {
@@ -871,6 +879,14 @@ int power_supply_get_battery_info(struct power_supply *psy,
info->temp_min = min_max[0];
info->temp_max = min_max[1];
}
+ if (!fwnode_property_read_u32_array(fwnode, "charge-temp-range-celsius",
+ min_max, ARRAY_SIZE(min_max))) {
+ info->temp_charge_min = min_max[0];
+ info->temp_charge_max = min_max[1];
+ } else {
+ info->temp_charge_min = info->temp_min;
+ info->temp_charge_max = info->temp_max;
+ }
len = fwnode_property_count_u32(fwnode, "ocv-capacity-celsius");
if (len < 0 && len != -EINVAL) {
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index cce61137aef4..246fba40ea78 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -559,15 +559,15 @@ struct power_supply_maintenance_charge_table {
* maintenance_charge.
* @alert_low_temp_charge_current_ua: The charging current to use if the battery
* enters low alert temperature, i.e. if the internal temperature is between
- * temp_alert_min and temp_min. No matter the charging phase, this
+ * temp_charge_min and temp_alert_min. No matter the charging phase, this
* and alert_high_temp_charge_voltage_uv will be applied.
* @alert_low_temp_charge_voltage_uv: Same as alert_low_temp_charge_current_ua,
* but for the charging voltage.
* @alert_high_temp_charge_current_ua: The charging current to use if the
* battery enters high alert temperature, i.e. if the internal temperature is
- * between temp_alert_max and temp_max. No matter the charging phase, this
- * and alert_high_temp_charge_voltage_uv will be applied, usually lowering
- * the charging current as an evasive manouver.
+ * between temp_alert_max and temp_charge_max. No matter the charging phase,
+ * this and alert_high_temp_charge_voltage_uv will be applied, usually
+ * lowering the charging current as an evasive manouver.
* @alert_high_temp_charge_voltage_uv: Same as
* alert_high_temp_charge_current_ua, but for the charging voltage.
* @factory_internal_resistance_uohm: the internal resistance of the battery
@@ -603,6 +603,12 @@ struct power_supply_maintenance_charge_table {
* @temp_max: the battery will go outside of operating conditions when
* the internal temperature goes above this temperature in degrees Celsius.
* Normally this means the system should shut down.
+ * @temp_charge_min: the battery must not be charged when the internal
+ * temperature is below this temperature in degrees Celsius. Defaults to
+ * temp_min.
+ * @temp_charge_max: the battery must not be charged when the internal
+ * temperature is above this temperature in degrees Celsius. Defaults to
+ * temp_max.
* @ocv_table: for each entry in ocv_temp there is a corresponding entry in
* ocv_table and a size for each entry in ocv_table_size. These arrays
* determine the capacity in percent in relation to the voltage in microvolts
@@ -826,6 +832,8 @@ struct power_supply_battery_info {
int temp_alert_max;
int temp_min;
int temp_max;
+ int temp_charge_min;
+ int temp_charge_max;
const struct power_supply_battery_ocv_table *ocv_table[POWER_SUPPLY_OCV_TEMP_MAX];
int ocv_table_size[POWER_SUPPLY_OCV_TEMP_MAX];
const struct power_supply_resistance_temp_table *resist_table;
--
2.56.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 3/3] power: supply: samsung-sdi-battery: Set the charging temperature range
2026-11-09 9:41 [PATCH 0/3] power: supply: battery: Allow separate charging limits vs. discharging Alexey Charkov
2026-11-09 9:41 ` [PATCH 1/3] dt-bindings: power: supply: battery: Add a charging temperature range Alexey Charkov
2026-11-09 9:41 ` [PATCH 2/3] power: supply: core: Read the charging temperature range and alert settings Alexey Charkov
@ 2026-11-09 9:41 ` Alexey Charkov
2 siblings, 0 replies; 5+ messages in thread
From: Alexey Charkov @ 2026-11-09 9:41 UTC (permalink / raw)
To: Sebastian Reichel, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-pm, devicetree, linux-kernel, Alexey Charkov
Give each battery a charging range equal to its operating range, as the
firmware parsing does when charge-temp-range-celsius is absent, since
these static descriptions skip that parsing: keep their behaviour
unchanged.
Leave any correction of these limits to a separate change, but note
that they follow the charge-block thresholds of the matching vendor
kernels, which count in tenths of a degree: the -50C and -30C lower
limits look like a unit slip in the original import, as -50 there
means -5C.
Signed-off-by: Alexey Charkov <alchark@flipper.net>
---
drivers/power/supply/samsung-sdi-battery.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/power/supply/samsung-sdi-battery.c b/drivers/power/supply/samsung-sdi-battery.c
index 33565002ee27..da283735df3b 100644
--- a/drivers/power/supply/samsung-sdi-battery.c
+++ b/drivers/power/supply/samsung-sdi-battery.c
@@ -659,6 +659,8 @@ static struct samsung_sdi_battery samsung_sdi_batteries[] = {
.temp_alert_min = 0,
.temp_alert_max = 40,
.temp_max = 60,
+ .temp_charge_min = -50,
+ .temp_charge_max = 60,
.resist_table = samsung_temp2res,
.resist_table_size = ARRAY_SIZE(samsung_temp2res),
/* If you have tables for more temperatures, add them */
@@ -703,6 +705,8 @@ static struct samsung_sdi_battery samsung_sdi_batteries[] = {
.temp_alert_min = 0,
.temp_alert_max = 40,
.temp_max = 47,
+ .temp_charge_min = -30,
+ .temp_charge_max = 47,
.resist_table = samsung_temp2res,
.resist_table_size = ARRAY_SIZE(samsung_temp2res),
/* If you have tables for more temperatures, add them */
@@ -747,6 +751,8 @@ static struct samsung_sdi_battery samsung_sdi_batteries[] = {
.temp_alert_min = 0,
.temp_alert_max = 43,
.temp_max = 49,
+ .temp_charge_min = -50,
+ .temp_charge_max = 49,
.resist_table = samsung_temp2res,
.resist_table_size = ARRAY_SIZE(samsung_temp2res),
/* If you have tables for more temperatures, add them */
@@ -790,6 +796,8 @@ static struct samsung_sdi_battery samsung_sdi_batteries[] = {
.temp_alert_min = 0,
.temp_alert_max = 40,
.temp_max = 60,
+ .temp_charge_min = -50,
+ .temp_charge_max = 60,
.resist_table = samsung_temp2res,
.resist_table_size = ARRAY_SIZE(samsung_temp2res),
/* If you have tables for more temperatures, add them */
@@ -835,6 +843,8 @@ static struct samsung_sdi_battery samsung_sdi_batteries[] = {
.temp_alert_min = 0,
.temp_alert_max = 40,
.temp_max = 60,
+ .temp_charge_min = -5,
+ .temp_charge_max = 60,
.resist_table = samsung_temp2res,
.resist_table_size = ARRAY_SIZE(samsung_temp2res),
/* If you have tables for more temperatures, add them */
@@ -879,6 +889,8 @@ static struct samsung_sdi_battery samsung_sdi_batteries[] = {
.temp_alert_min = 0,
.temp_alert_max = 40,
.temp_max = 60,
+ .temp_charge_min = -5,
+ .temp_charge_max = 60,
.resist_table = samsung_temp2res,
.resist_table_size = ARRAY_SIZE(samsung_temp2res),
/* If you have tables for more temperatures, add them */
--
2.56.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 2/3] power: supply: core: Read the charging temperature range and alert settings
2026-11-09 9:41 ` [PATCH 2/3] power: supply: core: Read the charging temperature range and alert settings Alexey Charkov
@ 2026-11-10 23:24 ` sashiko-bot
0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-11-10 23:24 UTC (permalink / raw)
To: Alexey Charkov; +Cc: devicetree, robh, conor+dt
Thank you for your contribution! Sashiko AI review found no new issues
in this patch, but noticed 1 related pre-existing issue it does not
introduce:
- [High] power: supply: core: out-of-bounds read in
power_supply_ocv2cap_simple() [1]
--
commit adb164988f0d04b6bb830ddbcbc6a92311698583
Author: Alexey Charkov <alchark@flipper.net>
power: supply: core: Read the charging temperature range and alert settings
This commit reads the charge-temp-range-celsius and alert-*-temp-charge-*
firmware properties into struct power_supply_battery_info, falling back to
the operating temperature range when charge-temp-range-celsius is absent.
> diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c
> index de15314ef9549..3bfc4fb8687ef 100644
> --- a/drivers/power/supply/power_supply_core.c
> +++ b/drivers/power/supply/power_supply_core.c
> @@ -855,6 +855,14 @@ int power_supply_get_battery_info(struct power_supply *psy,
> &info->constant_charge_voltage_max_uv);
> fwnode_property_read_u32(fwnode, "factory-internal-resistance-micro-ohms",
> &info->factory_internal_resistance_uohm);
> + fwnode_property_read_u32(fwnode, "alert-low-temp-charge-current-microamp",
> + &info->alert_low_temp_charge_current_ua);
> + fwnode_property_read_u32(fwnode, "alert-low-temp-charge-voltage-microvolt",
> + &info->alert_low_temp_charge_voltage_uv);
> + fwnode_property_read_u32(fwnode, "alert-high-temp-charge-current-microamp",
> + &info->alert_high_temp_charge_current_ua);
> + fwnode_property_read_u32(fwnode, "alert-high-temp-charge-voltage-microvolt",
> + &info->alert_high_temp_charge_voltage_uv);
>
> if (!fwnode_property_read_u32_array(fwnode, "ambient-celsius",
> min_max, ARRAY_SIZE(min_max))) {
> @@ -871,6 +879,14 @@ int power_supply_get_battery_info(struct power_supply *psy,
> info->temp_min = min_max[0];
> info->temp_max = min_max[1];
> }
> + if (!fwnode_property_read_u32_array(fwnode, "charge-temp-range-celsius",
> + min_max, ARRAY_SIZE(min_max))) {
> + info->temp_charge_min = min_max[0];
> + info->temp_charge_max = min_max[1];
> + } else {
> + info->temp_charge_min = info->temp_min;
> + info->temp_charge_max = info->temp_max;
> + }
>
> len = fwnode_property_count_u32(fwnode, "ocv-capacity-celsius");
> if (len < 0 && len != -EINVAL) {
[Severity: High]
This problem wasn't introduced by this patch, but can an empty
ocv-capacity-table-N property in power_supply_get_battery_info() [1]
cause an out-of-bounds read in power_supply_ocv2cap_simple()?
drivers/power/supply/power_supply_core.c:power_supply_get_battery_info() {
...
proplen = fwnode_property_count_u32(fwnode, propname);
if (proplen < 0 || proplen % 2 != 0) {
dev_err(&psy->dev, "failed to get %s\n", propname);
power_supply_put_battery_info(psy, info);
err = -EINVAL;
goto out_put_node;
}
...
tab_len = proplen / 2;
info->ocv_table_size[index] = tab_len;
info->ocv_table[index] = table =
devm_kcalloc(&psy->dev, tab_len, sizeof(*table), GFP_KERNEL);
...
}
When ocv-capacity-table-N is present but empty,
fwnode_property_count_u32() returns 0, which passes the proplen < 0 ||
proplen % 2 != 0 check. devm_kcalloc() then returns ZERO_SIZE_PTR with
ocv_table_size[index] set to 0, and power_supply_ocv2cap_simple() later
dereferences table[0], crashing the kernel. Rejecting proplen <= 0 (similar
to resistance-temp-table below) would avoid this.
[1] https://sashiko.dev/#/bug/linux-4a0a5d5f-629d-4b0d-b4be-07415bcb018e
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261109-battery-charge-temp-range-v1-0-a967abd8b80c@flipper.net?part=2
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-11-10 23:24 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-09 9:41 [PATCH 0/3] power: supply: battery: Allow separate charging limits vs. discharging Alexey Charkov
2026-11-09 9:41 ` [PATCH 1/3] dt-bindings: power: supply: battery: Add a charging temperature range Alexey Charkov
2026-11-09 9:41 ` [PATCH 2/3] power: supply: core: Read the charging temperature range and alert settings Alexey Charkov
2026-11-10 23:24 ` sashiko-bot
2026-11-09 9:41 ` [PATCH 3/3] power: supply: samsung-sdi-battery: Set the charging temperature range Alexey Charkov
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.