* [PATCH 0/4] power: supply: Add support for liquid detection
@ 2026-10-28 21:56 Waqar Hameed
2026-10-28 21:56 ` [PATCH 2/4] power: supply: Add liquid detection to health property enum Waqar Hameed
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Waqar Hameed @ 2026-10-28 21:56 UTC (permalink / raw)
To: Sebastian Reichel; +Cc: kernel, linux-pm, linux-kernel
During discussions of the development of a new driver [1], it was
concluded that a new `sysfs` ABI for reporting and controlling liquid
detection is wanted. This patchset introduces this.
Since there are currently not many devices with support for this. ABI
for setting/getting detection threshold values has been left out (as
discussed in [1]). Hopefully when more devices are supported, a good
common way to specify this will be designed.
[1] https://lore.kernel.org/lkml/cover.1772201049.git.waqar.hameed@axis.com/
Waqar Hameed (4):
power: supply: Add sysfs entry for liquid detection control
power: supply: Add liquid detection to health property enum
power: supply: bq25630: Add macro define for IRQ cycle time
power: supply: bq25630: Add support for liquid detection
Documentation/ABI/testing/sysfs-class-power | 22 ++-
drivers/power/supply/bq25630_charger.c | 163 +++++++++++++++++++-
drivers/power/supply/power_supply_sysfs.c | 9 ++
include/linux/power_supply.h | 9 ++
4 files changed, 199 insertions(+), 4 deletions(-)
base-commit: 151a134a4e6ec66f69db8750c66006f5207f7a9d
--
2.43.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/4] power: supply: Add sysfs entry for liquid detection control
2026-10-28 21:56 [PATCH 0/4] power: supply: Add support for liquid detection Waqar Hameed
2026-10-28 21:56 ` [PATCH 2/4] power: supply: Add liquid detection to health property enum Waqar Hameed
@ 2026-10-28 21:56 ` Waqar Hameed
2026-10-28 21:56 ` [PATCH 3/4] power: supply: bq25630: Add macro define for IRQ cycle time Waqar Hameed
2026-10-28 21:56 ` [PATCH 4/4] power: supply: bq25630: Add support for liquid detection Waqar Hameed
3 siblings, 0 replies; 5+ messages in thread
From: Waqar Hameed @ 2026-10-28 21:56 UTC (permalink / raw)
To: Sebastian Reichel; +Cc: kernel, linux-pm, linux-kernel
There are devices that have built-in liquid detection. For example to
mitigate corrosion caused by moisture in a port. In order to be able to
configure such devices, add sysfs entry for controlling a device's
liquid detection.
Signed-off-by: Waqar Hameed <waqar.hameed@axis.com>
---
Documentation/ABI/testing/sysfs-class-power | 19 +++++++++++++++++++
drivers/power/supply/power_supply_sysfs.c | 8 ++++++++
include/linux/power_supply.h | 8 ++++++++
3 files changed, 35 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-class-power b/Documentation/ABI/testing/sysfs-class-power
index 671786d4600de..a98e6b2a75fbc 100644
--- a/Documentation/ABI/testing/sysfs-class-power
+++ b/Documentation/ABI/testing/sysfs-class-power
@@ -619,6 +619,25 @@ Description:
"Ship" (4) Ship mode.
============= ==================================
+What: /sys/class/power_supply/<supply_name>/liquid_detection_control
+Date: October 2026
+Contact: linux-pm@vger.kernel.org
+Description:
+ Devices can have built-in liquid detection functionality. This
+ can for example be used to mitigate port corrosion caused by
+ moisture. This entry controls a device's liquid detection.
+
+ Access: Read, Write
+
+ Valid values:
+
+ ============= ===============================================
+ "Unknown" (0) Unknown state.
+ "Off" (1) Liquid detection is disabled.
+ "Auto" (2) Liquid detection is checked periodically.
+ "Once" (3) Check for liquid once then transition to "Off".
+ ============= ===============================================
+
**USB Properties**
What: /sys/class/power_supply/<supply_name>/input_current_limit
diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c
index 9704557ffe1dc..661b42adf6efc 100644
--- a/drivers/power/supply/power_supply_sysfs.c
+++ b/drivers/power/supply/power_supply_sysfs.c
@@ -160,6 +160,13 @@ static const char *const POWER_SUPPLY_LOAD_SWITCH_TEXT[] = {
[POWER_SUPPLY_LOAD_SWITCH_SHIP] = "Ship",
};
+static const char *const POWER_SUPPLY_LIQUID_DETECTION_CONTROL_TEXT[] = {
+ [POWER_SUPPLY_LIQUID_DETECTION_CONTROL_UNKNOWN] = "Unknown",
+ [POWER_SUPPLY_LIQUID_DETECTION_CONTROL_OFF] = "Off",
+ [POWER_SUPPLY_LIQUID_DETECTION_CONTROL_AUTO] = "Auto",
+ [POWER_SUPPLY_LIQUID_DETECTION_CONTROL_ONCE] = "Once",
+};
+
static struct power_supply_attr power_supply_attrs[] __ro_after_init = {
/* Properties of type `int' */
POWER_SUPPLY_ENUM_ATTR(STATUS),
@@ -240,6 +247,7 @@ static struct power_supply_attr power_supply_attrs[] __ro_after_init = {
POWER_SUPPLY_ATTR(INTERNAL_RESISTANCE),
POWER_SUPPLY_ATTR(STATE_OF_HEALTH),
POWER_SUPPLY_ENUM_ATTR(LOAD_SWITCH),
+ POWER_SUPPLY_ENUM_ATTR(LIQUID_DETECTION_CONTROL),
/* Properties of type `const char *' */
POWER_SUPPLY_ATTR(MODEL_NAME),
POWER_SUPPLY_ATTR(MANUFACTURER),
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index cce61137aef4d..8e5bbdfebe794 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -112,6 +112,13 @@ enum {
POWER_SUPPLY_LOAD_SWITCH_SHIP,
};
+enum {
+ POWER_SUPPLY_LIQUID_DETECTION_CONTROL_UNKNOWN = 0,
+ POWER_SUPPLY_LIQUID_DETECTION_CONTROL_OFF,
+ POWER_SUPPLY_LIQUID_DETECTION_CONTROL_AUTO,
+ POWER_SUPPLY_LIQUID_DETECTION_CONTROL_ONCE,
+};
+
enum power_supply_property {
/* Properties of type `int' */
POWER_SUPPLY_PROP_STATUS = 0,
@@ -191,6 +198,7 @@ enum power_supply_property {
POWER_SUPPLY_PROP_INTERNAL_RESISTANCE,
POWER_SUPPLY_PROP_STATE_OF_HEALTH,
POWER_SUPPLY_PROP_LOAD_SWITCH,
+ POWER_SUPPLY_PROP_LIQUID_DETECTION_CONTROL,
/* Properties of type `const char *' */
POWER_SUPPLY_PROP_MODEL_NAME,
POWER_SUPPLY_PROP_MANUFACTURER,
--
2.43.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 2/4] power: supply: Add liquid detection to health property enum
2026-10-28 21:56 [PATCH 0/4] power: supply: Add support for liquid detection Waqar Hameed
@ 2026-10-28 21:56 ` Waqar Hameed
2026-10-28 21:56 ` [PATCH 1/4] power: supply: Add sysfs entry for liquid detection control Waqar Hameed
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Waqar Hameed @ 2026-10-28 21:56 UTC (permalink / raw)
To: Sebastian Reichel; +Cc: kernel, linux-pm, linux-kernel
There are devices that can detect liquid. For example, moisture in a
port. To be able to report this state for such devices, add "liquid
detected" to the health property enum.
Signed-off-by: Waqar Hameed <waqar.hameed@axis.com>
---
Documentation/ABI/testing/sysfs-class-power | 3 ++-
drivers/power/supply/power_supply_sysfs.c | 1 +
include/linux/power_supply.h | 1 +
3 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/Documentation/ABI/testing/sysfs-class-power b/Documentation/ABI/testing/sysfs-class-power
index a98e6b2a75fbc..fdc6cd543c229 100644
--- a/Documentation/ABI/testing/sysfs-class-power
+++ b/Documentation/ABI/testing/sysfs-class-power
@@ -460,7 +460,8 @@ Description:
"Over voltage", "Under voltage", "Unspecified failure", "Cold",
"Watchdog timer expire", "Safety timer expire",
"Over current", "Calibration required", "Warm",
- "Cool", "Hot", "No battery", "Blown fuse", "Cell imbalance"
+ "Cool", "Hot", "No battery", "Blown fuse", "Cell imbalance",
+ "Liquid detected"
What: /sys/class/power_supply/<supply_name>/precharge_current
Date: June 2017
diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c
index 661b42adf6efc..d851e655f8414 100644
--- a/drivers/power/supply/power_supply_sysfs.c
+++ b/drivers/power/supply/power_supply_sysfs.c
@@ -114,6 +114,7 @@ static const char * const POWER_SUPPLY_HEALTH_TEXT[] = {
[POWER_SUPPLY_HEALTH_NO_BATTERY] = "No battery",
[POWER_SUPPLY_HEALTH_BLOWN_FUSE] = "Blown fuse",
[POWER_SUPPLY_HEALTH_CELL_IMBALANCE] = "Cell imbalance",
+ [POWER_SUPPLY_HEALTH_LIQUID_DETECTED] = "Liquid detected",
};
static const char * const POWER_SUPPLY_TECHNOLOGY_TEXT[] = {
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 8e5bbdfebe794..7fbc0b80bcbb6 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -73,6 +73,7 @@ enum {
POWER_SUPPLY_HEALTH_NO_BATTERY,
POWER_SUPPLY_HEALTH_BLOWN_FUSE,
POWER_SUPPLY_HEALTH_CELL_IMBALANCE,
+ POWER_SUPPLY_HEALTH_LIQUID_DETECTED,
};
enum {
--
2.43.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 3/4] power: supply: bq25630: Add macro define for IRQ cycle time
2026-10-28 21:56 [PATCH 0/4] power: supply: Add support for liquid detection Waqar Hameed
2026-10-28 21:56 ` [PATCH 2/4] power: supply: Add liquid detection to health property enum Waqar Hameed
2026-10-28 21:56 ` [PATCH 1/4] power: supply: Add sysfs entry for liquid detection control Waqar Hameed
@ 2026-10-28 21:56 ` Waqar Hameed
2026-10-28 21:56 ` [PATCH 4/4] power: supply: bq25630: Add support for liquid detection Waqar Hameed
3 siblings, 0 replies; 5+ messages in thread
From: Waqar Hameed @ 2026-10-28 21:56 UTC (permalink / raw)
To: Sebastian Reichel; +Cc: kernel, linux-pm, linux-kernel
The interrupt pulse time of 256 µs can be seen as an "inherent" property
of the device. It is currently only used for when polling the reset
register, but it could/should be used when polling whatever
register (e.g. liquid check). To facilitate this, add a macro define for
the interrupt pulse time.
Signed-off-by: Waqar Hameed <waqar.hameed@axis.com>
---
drivers/power/supply/bq25630_charger.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/power/supply/bq25630_charger.c b/drivers/power/supply/bq25630_charger.c
index 3106da710d6b6..a934f3deba63b 100644
--- a/drivers/power/supply/bq25630_charger.c
+++ b/drivers/power/supply/bq25630_charger.c
@@ -15,6 +15,7 @@
#include <linux/power_supply.h>
#define BQ25630_DRV_NAME "bq25630-charger"
+#define BQ25630_IRQ_CYCLE 256 /* µs */
/* Registers. */
#define BQ25630_REG_CHARGE_CURRENT_LIMIT 0x02
@@ -726,8 +727,8 @@ static int bq25630_reset(struct bq25630_data *data)
* this register field to 0. Try reading it for some interrupt cycles.
*/
ret = regmap_field_read_poll_timeout(
- data->regfields[BQ25630_REGF_REG_RST], regval, regval == 0, 256,
- 100000);
+ data->regfields[BQ25630_REGF_REG_RST], regval, regval == 0,
+ BQ25630_IRQ_CYCLE, 100000);
if (ret) {
dev_err(data->dev, "Could not read reset register field (%d)\n",
ret);
--
2.43.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 4/4] power: supply: bq25630: Add support for liquid detection
2026-10-28 21:56 [PATCH 0/4] power: supply: Add support for liquid detection Waqar Hameed
` (2 preceding siblings ...)
2026-10-28 21:56 ` [PATCH 3/4] power: supply: bq25630: Add macro define for IRQ cycle time Waqar Hameed
@ 2026-10-28 21:56 ` Waqar Hameed
3 siblings, 0 replies; 5+ messages in thread
From: Waqar Hameed @ 2026-10-28 21:56 UTC (permalink / raw)
To: Sebastian Reichel; +Cc: kernel, linux-pm, linux-kernel
The framework supports reporting and controlling liquid detection. Map
this to the different liquid detection registers available in the
device. Moreover, use the default reset detection threshold values since
the framework currently has no way to specify this.
Signed-off-by: Waqar Hameed <waqar.hameed@axis.com>
---
drivers/power/supply/bq25630_charger.c | 158 ++++++++++++++++++++++++-
1 file changed, 157 insertions(+), 1 deletion(-)
diff --git a/drivers/power/supply/bq25630_charger.c b/drivers/power/supply/bq25630_charger.c
index a934f3deba63b..dac791718bd98 100644
--- a/drivers/power/supply/bq25630_charger.c
+++ b/drivers/power/supply/bq25630_charger.c
@@ -198,6 +198,16 @@ enum bq25630_regfield {
/* VBUS fault. */
BQ25630_REGF_VBUS_FAULT_STAT,
+ /* Force liquid detection. */
+ BQ25630_REGF_FORCE_LQD_DET,
+ /* Automatic liquid detection. */
+ BQ25630_REGF_AUTO_LQD_DET,
+ /* Enable liquid detection. */
+ BQ25630_REGF_EN_LQD_DET,
+
+ /* Liquid detection status. */
+ BQ25630_REGF_LQD_STAT,
+
/* Sentinel value. */
BQ25630_REGF_MAX
};
@@ -250,6 +260,16 @@ static const struct reg_field bq25630_regfields[] = {
REG_FIELD(BQ25630_REG_FAULT_STATUS, 6, 6),
[BQ25630_REGF_VBUS_FAULT_STAT] =
REG_FIELD(BQ25630_REG_FAULT_STATUS, 7, 7),
+
+ [BQ25630_REGF_FORCE_LQD_DET] =
+ REG_FIELD(BQ25630_REG_LIQUID_CONTROL_0, 3, 3),
+ [BQ25630_REGF_AUTO_LQD_DET] =
+ REG_FIELD(BQ25630_REG_LIQUID_CONTROL_0, 6, 6),
+ [BQ25630_REGF_EN_LQD_DET] =
+ REG_FIELD(BQ25630_REG_LIQUID_CONTROL_0, 7, 7),
+
+ [BQ25630_REGF_LQD_STAT] =
+ REG_FIELD(BQ25630_REG_USB_C_INFORMATION_0, 6, 6),
};
/* 8-bit value regmap. */
@@ -451,6 +471,115 @@ static int bq25630_write_limit(struct bq25630_data *data,
return 0;
}
+static int bq25630_read_liquid_detection(struct bq25630_data *data, int *val)
+{
+ unsigned int regval;
+ int ret;
+
+ ret = regmap_field_read(data->regfields[BQ25630_REGF_EN_LQD_DET],
+ ®val);
+ if (ret) {
+ dev_err(data->dev,
+ "Could not read liquid detection setting (%d)\n", ret);
+ return ret;
+ }
+
+ if (!regval) {
+ *val = POWER_SUPPLY_LIQUID_DETECTION_CONTROL_OFF;
+ return 0;
+ }
+
+ ret = regmap_field_read(data->regfields[BQ25630_REGF_AUTO_LQD_DET],
+ ®val);
+ if (ret) {
+ dev_err(data->dev,
+ "Could not read liquid detection type (%d)\n", ret);
+ return ret;
+ }
+
+ if (regval) {
+ *val = POWER_SUPPLY_LIQUID_DETECTION_CONTROL_AUTO;
+ return 0;
+ }
+
+ /* Can only happen after unsuccessful writes... */
+ *val = POWER_SUPPLY_LIQUID_DETECTION_CONTROL_UNKNOWN;
+ return 0;
+}
+
+static int bq25630_write_liquid_detection(struct bq25630_data *data,
+ const int val)
+{
+ unsigned int regval;
+ bool automatic;
+ bool enable;
+ int ret;
+
+ switch (val) {
+ case POWER_SUPPLY_LIQUID_DETECTION_CONTROL_OFF:
+ automatic = false;
+ enable = false;
+ break;
+ case POWER_SUPPLY_LIQUID_DETECTION_CONTROL_AUTO:
+ automatic = true;
+ enable = true;
+ break;
+ case POWER_SUPPLY_LIQUID_DETECTION_CONTROL_ONCE:
+ automatic = false;
+ enable = true;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = regmap_field_write(data->regfields[BQ25630_REGF_AUTO_LQD_DET],
+ automatic);
+ if (ret) {
+ dev_err(data->dev,
+ "Could not write liquid detection type (%d)\n", ret);
+ return ret;
+ }
+
+ ret = regmap_field_write(data->regfields[BQ25630_REGF_EN_LQD_DET],
+ enable);
+ if (ret) {
+ dev_err(data->dev,
+ "Could not write liquid detection setting (%d)\n", ret);
+ return ret;
+ }
+
+ if (val != POWER_SUPPLY_LIQUID_DETECTION_CONTROL_ONCE)
+ return 0;
+
+ ret = regmap_field_write(data->regfields[BQ25630_REGF_FORCE_LQD_DET],
+ 1);
+ if (ret) {
+ dev_err(data->dev,
+ "Could not write liquid detection check (%d)\n", ret);
+ return ret;
+ }
+
+ /*
+ * Datasheet says the register resets when liquid check completes. Poll
+ * it for the default check cycle of 500 ms (field LQD_WAIT in
+ * BQ25630_REG_LIQUID_CONTROL_0).
+ */
+ ret = regmap_field_read_poll_timeout(
+ data->regfields[BQ25630_REGF_FORCE_LQD_DET], regval,
+ regval == 0, BQ25630_IRQ_CYCLE, 500000);
+ if (ret)
+ dev_err(data->dev,
+ "Could not read liquid detection check (%d)\n", ret);
+
+ /* Turn it off after checking once. */
+ ret = regmap_field_write(data->regfields[BQ25630_REGF_EN_LQD_DET], 0);
+ if (ret)
+ dev_err(data->dev,
+ "Could not write liquid detection setting (%d)\n", ret);
+
+ return ret;
+}
+
static int bq25630_read_charge_type(struct bq25630_data *data, int *val)
{
unsigned int regval;
@@ -493,6 +622,19 @@ static int bq25630_read_health(struct bq25630_data *data, int *val)
int ret;
u8 temp;
+ ret = regmap_field_read(data->regfields[BQ25630_REGF_LQD_STAT],
+ ®val);
+ if (ret) {
+ dev_err(data->dev,
+ "Could not read liquid detection status (%d)\n", ret);
+ return ret;
+ }
+
+ if (regval) {
+ *val = POWER_SUPPLY_HEALTH_LIQUID_DETECTED;
+ return 0;
+ }
+
ret = regmap_read(data->regmap8, BQ25630_REG_FAULT_STATUS, ®val);
if (ret) {
dev_err(data->dev, "Could not read fault status (%d)\n", ret);
@@ -921,6 +1063,9 @@ static int bq25630_charger_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_LOAD_SWITCH:
ret = bq25630_read_batfet_ctrl(data, &val->intval);
break;
+ case POWER_SUPPLY_PROP_LIQUID_DETECTION_CONTROL:
+ ret = bq25630_read_liquid_detection(data, &val->intval);
+ break;
case POWER_SUPPLY_PROP_MODEL_NAME:
val->strval = "BQ25630";
break;
@@ -992,6 +1137,9 @@ static int bq25630_charger_set_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_LOAD_SWITCH:
ret = bq25630_write_batfet_ctrl(data, val->intval);
break;
+ case POWER_SUPPLY_PROP_LIQUID_DETECTION_CONTROL:
+ ret = bq25630_write_liquid_detection(data, val->intval);
+ break;
default:
return -EINVAL;
}
@@ -1012,6 +1160,7 @@ static int bq25630_charger_property_is_writeable(struct power_supply *psy,
case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
case POWER_SUPPLY_PROP_LOAD_SWITCH:
+ case POWER_SUPPLY_PROP_LIQUID_DETECTION_CONTROL:
return true;
default:
return false;
@@ -1035,6 +1184,7 @@ static const enum power_supply_property bq25630_charger_properties[] = {
POWER_SUPPLY_PROP_PRECHARGE_CURRENT,
POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT,
POWER_SUPPLY_PROP_LOAD_SWITCH,
+ POWER_SUPPLY_PROP_LIQUID_DETECTION_CONTROL,
POWER_SUPPLY_PROP_MODEL_NAME,
POWER_SUPPLY_PROP_MANUFACTURER,
};
@@ -1084,7 +1234,13 @@ static int bq25630_probe(struct i2c_client *client)
"Could not initialize regmap8\n");
ret = bq25630_alloc_regfield_range(data, BQ25630_REGF_WATCHDOG,
- BQ25630_REGF_TS_STAT,
+ BQ25630_REGF_VBUS_STAT,
+ data->regmap8);
+ if (ret)
+ return ret;
+
+ ret = bq25630_alloc_regfield_range(data, BQ25630_REGF_FORCE_LQD_DET,
+ BQ25630_REGF_LQD_STAT,
data->regmap8);
if (ret)
return ret;
--
2.43.0
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-10-28 21:56 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-28 21:56 [PATCH 0/4] power: supply: Add support for liquid detection Waqar Hameed
2026-10-28 21:56 ` [PATCH 2/4] power: supply: Add liquid detection to health property enum Waqar Hameed
2026-10-28 21:56 ` [PATCH 1/4] power: supply: Add sysfs entry for liquid detection control Waqar Hameed
2026-10-28 21:56 ` [PATCH 3/4] power: supply: bq25630: Add macro define for IRQ cycle time Waqar Hameed
2026-10-28 21:56 ` [PATCH 4/4] power: supply: bq25630: Add support for liquid detection Waqar Hameed
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®