* [PATCH v1 1/4] arm64: dts: imx8mq-librem5: Remove invalid monitored-battery
2026-09-27 14:55 [PATCH v1 0/4] power: supply: bq25890: add input voltage limit Vincent Cloutier
@ 2026-09-27 14:55 ` Vincent Cloutier
2026-09-27 14:55 ` [PATCH v1 2/4] dt-bindings: power: supply: bq25890: Add input voltage limit Vincent Cloutier
` (2 subsequent siblings)
3 siblings, 0 replies; 8+ messages in thread
From: Vincent Cloutier @ 2026-09-27 14:55 UTC (permalink / raw)
To: sre
Cc: linux-pm, devicetree, linux-arm-kernel, imx, linux-kernel, robh,
krzk+dt, conor+dt, Frank.Li, s.hauer, kernel, festevam,
daniel.baluta, shawnguo, agx, angus, Vincent Cloutier
From: "Angus Ainslie (Purism)" <angus@akkea.ca>
The BQ25895 charger node points monitored-battery at the MAX17055 fuel
gauge. The property requires a phandle to a simple-battery node, and the
upstream BQ25890 driver does not consume battery information.
Remove the invalid relationship.
Fixes: 8f0216b006e5 ("arm64: dts: Add a device tree for the Librem 5 phone")
Signed-off-by: Angus Ainslie (Purism) <angus@akkea.ca>
Signed-off-by: Vincent Cloutier <vincent@cloutier.co>
---
arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi | 1 -
1 file changed, 1 deletion(-)
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi b/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi
index f5d529c5baf3..099195279e84 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi
@@ -1201,7 +1201,6 @@ bq25895: charger@6a {
ti,minimum-sys-voltage = <3700000>; /* uV */
ti,boost-voltage = <5000000>; /* uV */
ti,boost-max-current = <1500000>; /* uA */
- monitored-battery = <&bat>;
power-supplies = <&typec_pd>;
};
};
--
2.55.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v1 2/4] dt-bindings: power: supply: bq25890: Add input voltage limit
2026-09-27 14:55 [PATCH v1 0/4] power: supply: bq25890: add input voltage limit Vincent Cloutier
2026-09-27 14:55 ` [PATCH v1 1/4] arm64: dts: imx8mq-librem5: Remove invalid monitored-battery Vincent Cloutier
@ 2026-09-27 14:55 ` Vincent Cloutier
2026-09-28 16:42 ` Conor Dooley
2026-09-27 14:55 ` [PATCH v1 3/4] " Vincent Cloutier
2026-09-27 14:55 ` [PATCH v1 4/4] arm64: dts: imx8mq-librem5: Set BQ25895 " Vincent Cloutier
3 siblings, 1 reply; 8+ messages in thread
From: Vincent Cloutier @ 2026-09-27 14:55 UTC (permalink / raw)
To: sre
Cc: linux-pm, devicetree, linux-arm-kernel, imx, linux-kernel, robh,
krzk+dt, conor+dt, Frank.Li, s.hauer, kernel, festevam,
daniel.baluta, shawnguo, agx, angus, Vincent Cloutier
From: Vincent Cloutier <vincent@cloutier.co>
Document input-voltage-limit-microvolt for configuring the absolute input
voltage dynamic power management threshold. When the property is absent,
the charger retains its relative VINDPM behavior.
Assisted-by: OpenCode:gpt-5.6-sol
Signed-off-by: Vincent Cloutier <vincent@cloutier.co>
---
.../devicetree/bindings/power/supply/bq25890.yaml | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/Documentation/devicetree/bindings/power/supply/bq25890.yaml b/Documentation/devicetree/bindings/power/supply/bq25890.yaml
index 0ad302ab2bcc..8d1f27447cca 100644
--- a/Documentation/devicetree/bindings/power/supply/bq25890.yaml
+++ b/Documentation/devicetree/bindings/power/supply/bq25890.yaml
@@ -31,6 +31,14 @@ properties:
interrupts:
maxItems: 1
+ input-voltage-limit-microvolt:
+ description: |
+ Absolute input voltage limit. When present, the charger uses the
+ absolute VINDPM threshold instead of relative VINDPM.
+ minimum: 3900000
+ maximum: 14000000
+ multipleOf: 100000
+
ti,battery-regulation-voltage:
$ref: /schemas/types.yaml#/definitions/uint32
description: maximum charging voltage (in uV)
@@ -113,6 +121,7 @@ examples:
interrupt-parent = <&gpio1>;
interrupts = <16 IRQ_TYPE_EDGE_FALLING>;
+ input-voltage-limit-microvolt = <3900000>;
ti,battery-regulation-voltage = <4200000>;
ti,charge-current = <1000000>;
ti,termination-current = <50000>;
--
2.55.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v1 3/4] power: supply: bq25890: Add input voltage limit
2026-09-27 14:55 [PATCH v1 0/4] power: supply: bq25890: add input voltage limit Vincent Cloutier
2026-09-27 14:55 ` [PATCH v1 1/4] arm64: dts: imx8mq-librem5: Remove invalid monitored-battery Vincent Cloutier
2026-09-27 14:55 ` [PATCH v1 2/4] dt-bindings: power: supply: bq25890: Add input voltage limit Vincent Cloutier
@ 2026-09-27 14:55 ` Vincent Cloutier
2026-09-27 15:06 ` sashiko-bot
2026-09-27 14:55 ` [PATCH v1 4/4] arm64: dts: imx8mq-librem5: Set BQ25895 " Vincent Cloutier
3 siblings, 1 reply; 8+ messages in thread
From: Vincent Cloutier @ 2026-09-27 14:55 UTC (permalink / raw)
To: sre
Cc: linux-pm, devicetree, linux-arm-kernel, imx, linux-kernel, robh,
krzk+dt, conor+dt, Frank.Li, s.hauer, kernel, festevam,
daniel.baluta, shawnguo, agx, angus, Vincent Cloutier
From: Vincent Cloutier <vincent@cloutier.co>
The BQ25890 family supports an absolute input voltage dynamic power
management threshold. Read input-voltage-limit-microvolt from firmware,
enable absolute VINDPM, and then program the requested threshold. Only
program and restore VINDPM when this property is parsed. Without it,
retain the existing VINDPM behavior.
As with the other initialization properties, linux,read-back-settings
bypasses parsing this property. Do not read back VINDPM into the requested
settings, so a firmware-configured absolute threshold does not implicitly
enable restoration.
The BQ25896 resets FORCE_VINDPM and VINDPM when an input source is
inserted. Source detection and VINDPM threshold selection generate
separate interrupts, so compare the fields with the requested values on
every online state refresh before returning for unchanged charger state.
Restore them only when they differ to avoid an interrupt loop. Report a
successful restoration as a handled interrupt even when the tracked state
is unchanged, without sending a redundant power-supply change notification.
Repeat the comparison during resume because an input insertion while
suspended may not leave a visible offline-to-online transition.
The BQ25896-specific restoration path has not been tested on hardware.
Assisted-by: OpenCode:gpt-5.6-sol
Assisted-by: OpenCode:gpt-6-astra
Signed-off-by: Vincent Cloutier <vincent@cloutier.co>
---
drivers/power/supply/bq25890_charger.c | 74 +++++++++++++++++++++++++-
1 file changed, 73 insertions(+), 1 deletion(-)
diff --git a/drivers/power/supply/bq25890_charger.c b/drivers/power/supply/bq25890_charger.c
index 741a45cc5f35..71d6cf179667 100644
--- a/drivers/power/supply/bq25890_charger.c
+++ b/drivers/power/supply/bq25890_charger.c
@@ -88,6 +88,8 @@ struct bq25890_init_data {
u8 boosti; /* boost current limit */
u8 boostf; /* boost frequency */
u8 ilim_en; /* enable ILIM pin */
+ bool force_vindpm; /* explicit absolute VINDPM request */
+ u8 vindpm; /* absolute VINDPM threshold */
u8 treg; /* thermal regulation threshold */
u8 rbatcomp; /* IBAT sense resistor value */
u8 vclamp; /* IBAT compensation voltage limit */
@@ -284,6 +286,7 @@ enum bq25890_table_ids {
TBL_VBUSV,
TBL_VBATCOMP,
TBL_RBATCOMP,
+ TBL_VINDPM,
/* lookup tables */
TBL_TREG,
@@ -351,6 +354,7 @@ static const union {
[TBL_VBUSV] = { .rt = {2600000, 15300000, 100000} }, /* uV */
[TBL_VBATCOMP] = { .rt = {0, 224000, 32000} }, /* uV */
[TBL_RBATCOMP] = { .rt = {0, 140000, 20000} }, /* uOhm */
+ [TBL_VINDPM] = { .rt = {2600000, 15300000, 100000} }, /* uV */
/* lookup tables */
[TBL_TREG] = { .lt = {bq25890_treg_tbl, BQ25890_TREG_TBL_SIZE} },
@@ -814,18 +818,67 @@ static int bq25890_get_chip_state(struct bq25890_device *bq,
return 0;
}
+static int bq25890_set_vindpm(struct bq25890_device *bq)
+{
+ int ret;
+
+ if (!bq->init_data.force_vindpm)
+ return 0;
+
+ ret = bq25890_field_write(bq, F_FORCE_VINDPM, 1);
+ if (ret < 0)
+ return ret;
+
+ return bq25890_field_write(bq, F_VINDPM, bq->init_data.vindpm);
+}
+
+/* Return 1 if restored, 0 if unchanged, or a negative error. */
+static int bq25890_restore_vindpm(struct bq25890_device *bq)
+{
+ int force, vindpm, ret;
+
+ if (!bq->init_data.force_vindpm || bq->chip_version != BQ25896)
+ return 0;
+
+ force = bq25890_field_read(bq, F_FORCE_VINDPM);
+ if (force < 0)
+ return force;
+
+ vindpm = bq25890_field_read(bq, F_VINDPM);
+ if (vindpm < 0)
+ return vindpm;
+
+ if (force && vindpm == bq->init_data.vindpm)
+ return 0;
+
+ ret = bq25890_set_vindpm(bq);
+ if (ret < 0)
+ return ret;
+
+ return 1;
+}
+
static irqreturn_t __bq25890_handle_irq(struct bq25890_device *bq)
{
bool adc_conv_rate, new_adc_conv_rate;
struct bq25890_state new_state;
+ irqreturn_t irq_ret = IRQ_NONE;
int ret;
ret = bq25890_get_chip_state(bq, &new_state);
if (ret < 0)
return IRQ_NONE;
+ if (new_state.online) {
+ ret = bq25890_restore_vindpm(bq);
+ if (ret < 0)
+ goto error;
+ if (ret > 0)
+ irq_ret = IRQ_HANDLED;
+ }
+
if (!memcmp(&bq->state, &new_state, sizeof(new_state)))
- return IRQ_NONE;
+ return irq_ret;
/*
* Restore HiZ bit in case it was set by user. The chip does not retain
@@ -932,6 +985,9 @@ static int bq25890_rw_init_data(struct bq25890_device *bq)
}
}
+ if (write)
+ return bq25890_set_vindpm(bq);
+
return 0;
}
@@ -1386,6 +1442,18 @@ static int bq25890_fw_read_u32_props(struct bq25890_device *bq)
props[i].tbl_id);
}
+ if (device_property_present(bq->dev,
+ "input-voltage-limit-microvolt")) {
+ ret = device_property_read_u32(bq->dev,
+ "input-voltage-limit-microvolt",
+ &property);
+ if (ret < 0)
+ return ret;
+
+ init->vindpm = bq25890_find_idx(property, TBL_VINDPM);
+ init->force_vindpm = true;
+ }
+
return 0;
}
@@ -1609,6 +1677,10 @@ static int bq25890_resume(struct device *dev)
/* Re-enable ADC only if charger is plugged in. */
if (bq->state.online) {
+ ret = bq25890_restore_vindpm(bq);
+ if (ret < 0)
+ goto unlock;
+
ret = bq25890_field_write(bq, F_CONV_RATE, 1);
if (ret < 0)
goto unlock;
--
2.55.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v1 4/4] arm64: dts: imx8mq-librem5: Set BQ25895 input voltage limit
2026-09-27 14:55 [PATCH v1 0/4] power: supply: bq25890: add input voltage limit Vincent Cloutier
` (2 preceding siblings ...)
2026-09-27 14:55 ` [PATCH v1 3/4] " Vincent Cloutier
@ 2026-09-27 14:55 ` Vincent Cloutier
2026-10-03 1:08 ` Sebastian Krzyszkowiak
3 siblings, 1 reply; 8+ messages in thread
From: Vincent Cloutier @ 2026-09-27 14:55 UTC (permalink / raw)
To: sre
Cc: linux-pm, devicetree, linux-arm-kernel, imx, linux-kernel, robh,
krzk+dt, conor+dt, Frank.Li, s.hauer, kernel, festevam,
daniel.baluta, shawnguo, agx, angus, Vincent Cloutier
From: Vincent Cloutier <vincent@cloutier.co>
Purism's production Librem 5 kernels used a 3.9 V absolute VINDPM
threshold for years, from the 2019 board support through the releases
preceding the March 2026 charging update. Use this established board
setting for the BQ25895 input voltage limit.
Set input-voltage-limit-microvolt to 3900000 to select absolute VINDPM
and program the 3.9 V threshold through the generic binding.
Tested on Librem 5r4: REG0D remained 0x8d across an attached boot, unplug,
and flipped replug.
Assisted-by: OpenCode:gpt-5.6-sol
Assisted-by: OpenCode:gpt-6-astra
Signed-off-by: Vincent Cloutier <vincent@cloutier.co>
---
arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi b/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi
index 099195279e84..8badebfcdbb4 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi
@@ -1195,6 +1195,7 @@ bq25895: charger@6a {
pinctrl-0 = <&pinctrl_charger_in>;
interrupt-parent = <&gpio3>;
interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+ input-voltage-limit-microvolt = <3900000>;
ti,battery-regulation-voltage = <4208000>; /* uV */
ti,termination-current = <128000>; /* uA */
ti,precharge-current = <128000>; /* uA */
--
2.55.0
^ permalink raw reply related [flat|nested] 8+ messages in thread