mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v3 0/2] Add LT8491 driver
@ 2026-10-29  7:30 John Erasmus Mari Geronimo
  2026-10-29  7:30 ` [PATCH v3 1/2] dt-bindings: power: supply: add adi,lt8491.yaml John Erasmus Mari Geronimo
  2026-10-29  7:30 ` [PATCH v3 2/2] power: supply: add LT8491 battery charger driver John Erasmus Mari Geronimo
  0 siblings, 2 replies; 3+ messages in thread
From: John Erasmus Mari Geronimo @ 2026-10-29  7:30 UTC (permalink / raw)
  To: sre; +Cc: robh, krzk+dt, conor+dt, linux-pm, devicetree, linux-kernel

The LT8491 is a buck-boost switching regulator battery charger that
implements a constant-current constant-voltage (CCCV) charging profile.

Changes since v2:
https://lore.kernel.org/all/cover.1788432152.git.johnerasmusmari.geronimo@analog.com/
 - dt-bindings: use unevaluatedProperties: false instead of
   additionalProperties: false (Conor Dooley, sashiko-bot).
 - driver: drop the <linux/mod_devicetable.h> include and use a named
   initializer for the i2c_device_id table (Uwe Kleine-König).
 - driver: use an int for ret in lt8491_get_property() so readings
   >= 0x8000 are not treated as errors (sashiko-bot).
 - driver: register the power supply with
   devm_power_supply_register() (sashiko-bot).
 - driver: poll the telemetry-active bit after triggering a telemetry
   update (sashiko-bot).
 - driver: bounds-check the temperature limits and the resistor
   configuration values before truncating them into registers
   (sashiko-bot).
 - driver: write the 16-bit resistor configuration registers as two
   byte writes, as the device has no word-write transaction.
 - driver: report current_now in microamps.
 - driver: return -ENODATA for the temperature when the chip reports
   the not-measured-yet (0x7FFF) or thermistor-disconnected (0x7777)
   values.
 - driver: minor cleanups.

Tested on a DC2703A-A-KIT evaluation board with a Raspberry Pi 4B
(6.12-based vendor kernel) with no battery connected; charging was not
tested, nor were the two special temperature values above. Build-tested
against the power-supply for-next tree.

John Erasmus Mari Geronimo (2):
  dt-bindings: power: supply: add adi,lt8491.yaml
  power: supply: add LT8491 battery charger driver

 .../bindings/power/supply/adi,lt8491.yaml     |  92 ++++
 MAINTAINERS                                   |   7 +
 drivers/power/supply/Kconfig                  |   9 +
 drivers/power/supply/Makefile                 |   1 +
 drivers/power/supply/lt8491_charger.c         | 428 ++++++++++++++++++
 5 files changed, 537 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/power/supply/adi,lt8491.yaml
 create mode 100644 drivers/power/supply/lt8491_charger.c


base-commit: f0f400459bf6a037e70768de623fff3f8920b8bb
-- 
2.34.1


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH v3 1/2] dt-bindings: power: supply: add adi,lt8491.yaml
  2026-10-29  7:30 [PATCH v3 0/2] Add LT8491 driver John Erasmus Mari Geronimo
@ 2026-10-29  7:30 ` John Erasmus Mari Geronimo
  2026-10-29  7:30 ` [PATCH v3 2/2] power: supply: add LT8491 battery charger driver John Erasmus Mari Geronimo
  1 sibling, 0 replies; 3+ messages in thread
From: John Erasmus Mari Geronimo @ 2026-10-29  7:30 UTC (permalink / raw)
  To: sre; +Cc: robh, krzk+dt, conor+dt, linux-pm, devicetree, linux-kernel

Add the devicetree binding for the Analog Devices LT8491, a high
voltage buck-boost battery charge controller with an I2C interface.
The values of the PCB resistors used by the chip's telemetry are
described as properties.

Signed-off-by: John Erasmus Mari Geronimo <johnerasmusmari.geronimo@analog.com>
---
 .../bindings/power/supply/adi,lt8491.yaml     | 92 +++++++++++++++++++
 MAINTAINERS                                   |  6 ++
 2 files changed, 98 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/power/supply/adi,lt8491.yaml

diff --git a/Documentation/devicetree/bindings/power/supply/adi,lt8491.yaml b/Documentation/devicetree/bindings/power/supply/adi,lt8491.yaml
new file mode 100644
index 000000000..268289841
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/supply/adi,lt8491.yaml
@@ -0,0 +1,92 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/power/supply/adi,lt8491.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Linear Technology (Analog Devices) LT8491 Battery Charger
+
+maintainers:
+  - John Erasmus Mari Geronimo <johnerasmusmari.geronimo@analog.com>
+
+description: |
+  The LT8491 is a buck-boost switching regulator battery charger that implements
+  a constant-current constant-voltage (CCCV) charging profile used for most
+  battery types, including sealed lead-acid (SLA), flooded, gel and lithium-ion.
+
+  Specifications about the charger can be found at:
+    https://www.analog.com/en/products/lt8491.html
+
+allOf:
+  - $ref: power-supply.yaml#
+
+properties:
+  compatible:
+    enum:
+      - adi,lt8491
+
+  reg:
+    maxItems: 1
+
+  adi,rsense1-micro-ohms:
+    description: Resistance value of RSENSE1 in micro ohms.
+
+  adi,rimon-out-ohms:
+    description: Resistance value of RIMON_OUT in ohms.
+
+  adi,rsense2-micro-ohms:
+    description: Resistance value of RSENSE2 in micro ohms.
+
+  adi,rdaco-ohms:
+    description: Resistance value of RDACO1 + RDACO2 in ohms.
+
+  adi,rfbout1-ohms:
+    description: Resistance value of RFBOUT1 in ohms.
+
+  adi,rfbout2-ohms:
+    description: Resistance value of RFBOUT2 in ohms.
+
+  adi,rdaci-ohms:
+    description: Resistance value of RDACI1 + RDACI2 in ohms.
+
+  adi,rfbin2-ohms:
+    description: Resistance value of RFBIN2 in ohms.
+
+  adi,rfbin1-ohms:
+    description: Resistance value of RFBIN1 in ohms.
+
+required:
+  - compatible
+  - reg
+  - adi,rsense1-micro-ohms
+  - adi,rimon-out-ohms
+  - adi,rsense2-micro-ohms
+  - adi,rdaco-ohms
+  - adi,rfbout1-ohms
+  - adi,rfbout2-ohms
+  - adi,rdaci-ohms
+  - adi,rfbin2-ohms
+  - adi,rfbin1-ohms
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        battery-charger@10 {
+            compatible = "adi,lt8491";
+            reg = <0x10>;
+            adi,rsense1-micro-ohms = <5000>;
+            adi,rimon-out-ohms = <124000>;
+            adi,rsense2-micro-ohms = <3000>;
+            adi,rdaco-ohms = <64900>;
+            adi,rfbout1-ohms = <113000>;
+            adi,rfbout2-ohms = <10000>;
+            adi,rdaci-ohms = <7000>;
+            adi,rfbin2-ohms = <3480>;
+            adi,rfbin1-ohms = <102000>;
+        };
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index 3a19da74d..2b3cc7649 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15466,6 +15466,12 @@ F:	Documentation/devicetree/bindings/hwmon/pmbus/adi,lt3074.yaml
 F:	Documentation/hwmon/lt3074.rst
 F:	drivers/hwmon/pmbus/lt3074.c
 
+LT8491 BATTERY CHARGER DRIVER
+M:	John Erasmus Mari Geronimo <johnerasmusmari.geronimo@analog.com>
+L:	linux-pm@vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/power/supply/adi,lt8491.yaml
+
 LTC1660 DAC DRIVER
 M:	Marcus Folkesson <marcus.folkesson@gmail.com>
 L:	linux-iio@vger.kernel.org
-- 
2.34.1


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH v3 2/2] power: supply: add LT8491 battery charger driver
  2026-10-29  7:30 [PATCH v3 0/2] Add LT8491 driver John Erasmus Mari Geronimo
  2026-10-29  7:30 ` [PATCH v3 1/2] dt-bindings: power: supply: add adi,lt8491.yaml John Erasmus Mari Geronimo
@ 2026-10-29  7:30 ` John Erasmus Mari Geronimo
  1 sibling, 0 replies; 3+ messages in thread
From: John Erasmus Mari Geronimo @ 2026-10-29  7:30 UTC (permalink / raw)
  To: sre; +Cc: robh, krzk+dt, conor+dt, linux-pm, devicetree, linux-kernel

Add support for the Analog Devices LT8491 buck-boost battery charge
controller connected over I2C. The driver registers a power supply
exposing the charging status, battery voltage, current, power and
temperature, and the battery temperature limits. The PCB resistor
values needed by the chip's telemetry are read from the devicetree and
written to the chip at probe.

Signed-off-by: John Erasmus Mari Geronimo <johnerasmusmari.geronimo@analog.com>
---
 MAINTAINERS                           |   1 +
 drivers/power/supply/Kconfig          |   9 +
 drivers/power/supply/Makefile         |   1 +
 drivers/power/supply/lt8491_charger.c | 428 ++++++++++++++++++++++++++
 4 files changed, 439 insertions(+)
 create mode 100644 drivers/power/supply/lt8491_charger.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 2b3cc7649..badfce0b8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15471,6 +15471,7 @@ M:	John Erasmus Mari Geronimo <johnerasmusmari.geronimo@analog.com>
 L:	linux-pm@vger.kernel.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/power/supply/adi,lt8491.yaml
+F:	drivers/power/supply/lt8491_charger.c
 
 LTC1660 DAC DRIVER
 M:	Marcus Folkesson <marcus.folkesson@gmail.com>
diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index ee7dc5f26..2a5a0c823 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -598,6 +598,15 @@ config CHARGER_LT3651
 	  Say Y to include support for the Analog Devices (Linear Technology)
 	  LT3651 battery charger which reports its status via GPIO lines.
 
+config CHARGER_LT8491
+	tristate "Analog Devices LT8491 charger"
+	depends on I2C
+	help
+	  Say Y to include support for the Analog Devices (Linear Technology)
+	  LT8491 battery charge controller connected to I2C. The LT8491 is a
+	  high voltage buck-boost switching regulator battery charger
+	  controller.
+
 config CHARGER_LTC4162L
 	tristate "LTC4162-L charger"
 	depends on I2C
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index f3c0d1006..7b85b35b5 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -81,6 +81,7 @@ obj-$(CONFIG_CHARGER_LP8788)	+= lp8788-charger.o
 obj-$(CONFIG_CHARGER_GPIO)	+= gpio-charger.o
 obj-$(CONFIG_CHARGER_MANAGER)	+= charger-manager.o
 obj-$(CONFIG_CHARGER_LT3651)	+= lt3651-charger.o
+obj-$(CONFIG_CHARGER_LT8491)	+= lt8491_charger.o
 obj-$(CONFIG_CHARGER_LTC4162L)	+= ltc4162-l-charger.o
 obj-$(CONFIG_CHARGER_MAX14577)	+= max14577_charger.o
 obj-$(CONFIG_CHARGER_DETECTOR_MAX14656)	+= max14656_charger_detector.o
diff --git a/drivers/power/supply/lt8491_charger.c b/drivers/power/supply/lt8491_charger.c
new file mode 100644
index 000000000..eab5ea720
--- /dev/null
+++ b/drivers/power/supply/lt8491_charger.c
@@ -0,0 +1,428 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Analog Devices LT8491 Battery Charger
+ *
+ * Copyright 2024 Analog Devices Inc.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/power_supply.h>
+
+#define LT8491_TELE_TBAT_REG 0x0
+#define LT8491_TELE_POUT_REG 0x2
+#define LT8491_TELE_PIN_REG  0x4
+#define LT8491_TELE_EFF_REG  0x6
+#define LT8491_TELE_IOUT_REG 0x8
+#define LT8491_TELE_IIN_REG  0xA
+#define LT8491_TELE_VBAT_REG 0xC
+#define LT8491_TELE_VIN_REG  0xE
+#define LT8491_TELE_VINR_REG 0x10
+#define LT8491_STAT_CHARGER_REG 0x12
+#define LT8491_CTRL_UPDATE_TELEM_REG 0x26
+
+#define LT8491_CFG_RSENSE1_REG 0x28
+#define LT8491_CFG_RIMON_OUT_REG 0x2A
+#define LT8491_CFG_RSENSE2_REG 0x2C
+#define LT8491_CFG_RDACO_REG 0x2E
+#define LT8491_CFG_RFBOUT1_REG 0x30
+#define LT8491_CFG_RFBOUT2_REG 0x32
+#define LT8491_CFG_RDACI_REG 0x34
+#define LT8491_CFG_RFBIN2_REG 0x36
+#define LT8491_CFG_RFBIN1_REG 0x38
+#define LT8491_CFG_TBAT_MIN_REG 0x40
+#define LT8491_CFG_TBAT_MAX_REG 0x41
+#define LT8491_MFR_DATA1_LSB_REG 0x5C
+
+#define LT8491_TELEM_ACTIVE_MASK BIT(6)
+#define LT8491_CHARGING_MASK BIT(2)
+
+#define LT8491_UPDATE_TELEM_CMD 0xAA
+
+/* A telemetry update typically takes 20ms to complete, per the datasheet. */
+#define LT8491_TELEM_POLL_PERIOD_US 2000
+#define LT8491_TELEM_UPDATE_TIMEOUT_US 50000
+
+/* LT8491_CFG_TBAT_{MIN,MAX}_REG hold a signed whole-degree-Celsius value. */
+#define LT8491_TBAT_MIN_C -128
+#define LT8491_TBAT_MAX_C 127
+
+/* LT8491_TELE_TBAT_REG: reset value, and thermistor-disconnected indication. */
+#define LT8491_TBAT_NOT_MEASURED 0x7FFF
+#define LT8491_TBAT_DISCONNECTED 0x7777
+
+#define LT8491_MFR_DATA_LEN 0x3
+
+struct lt8491_info {
+	struct i2c_client *client;
+	struct power_supply *psp;
+	char serial_number[16];
+	/* protect against device accesses */
+	struct mutex lock;
+};
+
+static int lt8491_read_serial_number(struct lt8491_info *info)
+{
+	int i;
+	int serial_number[LT8491_MFR_DATA_LEN];
+
+	for (i = 0; i < LT8491_MFR_DATA_LEN; i++) {
+		serial_number[i] = i2c_smbus_read_word_data(info->client,
+							    LT8491_MFR_DATA1_LSB_REG + i * 2);
+		if (serial_number[i] < 0)
+			return serial_number[i];
+	}
+
+	scnprintf(info->serial_number, sizeof(info->serial_number), "%04x%04x%04x",
+		  serial_number[0], serial_number[1], serial_number[2]);
+
+	return 0;
+}
+
+static int lt8491_update_telemetry(struct lt8491_info *info)
+{
+	int ret, val;
+
+	ret = i2c_smbus_read_byte_data(info->client, LT8491_STAT_CHARGER_REG);
+	if (ret < 0)
+		return ret;
+
+	/* Telemetry acquisition is already running; nothing to trigger. */
+	if (FIELD_GET(LT8491_TELEM_ACTIVE_MASK, ret))
+		return 0;
+
+	ret = i2c_smbus_write_byte_data(info->client, LT8491_CTRL_UPDATE_TELEM_REG,
+					LT8491_UPDATE_TELEM_CMD);
+	if (ret)
+		return ret;
+
+	ret = read_poll_timeout(i2c_smbus_read_byte_data, val,
+				val < 0 || !FIELD_GET(LT8491_TELEM_ACTIVE_MASK, val),
+				LT8491_TELEM_POLL_PERIOD_US,
+				LT8491_TELEM_UPDATE_TIMEOUT_US, false,
+				info->client, LT8491_STAT_CHARGER_REG);
+	if (ret)
+		return ret;
+
+	return val < 0 ? val : 0;
+}
+
+static int lt8491_get_property(struct power_supply *psy,
+			       enum power_supply_property psp,
+			       union power_supply_propval *val)
+{
+	struct lt8491_info *info = power_supply_get_drvdata(psy);
+	int ret;
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_STATUS:
+		ret = i2c_smbus_read_byte_data(info->client,
+					       LT8491_STAT_CHARGER_REG);
+		if (ret < 0)
+			return ret;
+
+		val->intval = FIELD_GET(LT8491_CHARGING_MASK, ret) ?
+					POWER_SUPPLY_STATUS_CHARGING :
+					POWER_SUPPLY_STATUS_NOT_CHARGING;
+
+		return 0;
+	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+		scoped_guard(mutex, &info->lock) {
+			ret = lt8491_update_telemetry(info);
+			if (ret)
+				return ret;
+
+			ret = i2c_smbus_read_word_data(info->client,
+						       LT8491_TELE_VBAT_REG);
+			if (ret < 0)
+				return ret;
+		}
+
+		val->intval = ret * 10000;
+
+		return 0;
+	case POWER_SUPPLY_PROP_CURRENT_NOW:
+		scoped_guard(mutex, &info->lock) {
+			ret = lt8491_update_telemetry(info);
+			if (ret)
+				return ret;
+
+			ret = i2c_smbus_read_word_data(info->client,
+						       LT8491_TELE_IOUT_REG);
+			if (ret < 0)
+				return ret;
+		}
+
+		val->intval = ret * 1000;
+
+		return 0;
+	case POWER_SUPPLY_PROP_POWER_NOW:
+		scoped_guard(mutex, &info->lock) {
+			ret = lt8491_update_telemetry(info);
+			if (ret)
+				return ret;
+
+			ret = i2c_smbus_read_word_data(info->client,
+						       LT8491_TELE_POUT_REG);
+			if (ret < 0)
+				return ret;
+		}
+
+		val->intval = ret * 10000;
+
+		return 0;
+	case POWER_SUPPLY_PROP_TEMP:
+		scoped_guard(mutex, &info->lock) {
+			ret = lt8491_update_telemetry(info);
+			if (ret)
+				return ret;
+
+			ret = i2c_smbus_read_word_data(info->client,
+						       LT8491_TELE_TBAT_REG);
+			if (ret < 0)
+				return ret;
+		}
+
+		if (ret == LT8491_TBAT_NOT_MEASURED ||
+		    ret == LT8491_TBAT_DISCONNECTED)
+			return -ENODATA;
+
+		val->intval = sign_extend32(ret, 15);
+
+		return 0;
+	case POWER_SUPPLY_PROP_TEMP_ALERT_MIN:
+		ret = i2c_smbus_read_byte_data(info->client,
+					       LT8491_CFG_TBAT_MIN_REG);
+		if (ret < 0)
+			return ret;
+
+		val->intval = sign_extend32(ret, 7) * 10;
+
+		return 0;
+	case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
+		ret = i2c_smbus_read_byte_data(info->client,
+					       LT8491_CFG_TBAT_MAX_REG);
+		if (ret < 0)
+			return ret;
+
+		val->intval = sign_extend32(ret, 7) * 10;
+
+		return 0;
+	case POWER_SUPPLY_PROP_MODEL_NAME:
+		val->strval = "lt8491";
+
+		return 0;
+	case POWER_SUPPLY_PROP_MANUFACTURER:
+		val->strval = "Analog Devices";
+
+		return 0;
+	case POWER_SUPPLY_PROP_SERIAL_NUMBER:
+		val->strval = info->serial_number;
+
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int lt8491_set_property(struct power_supply *psy,
+			       enum power_supply_property psp,
+			       const union power_supply_propval *val)
+{
+	struct lt8491_info *info = power_supply_get_drvdata(psy);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_TEMP_ALERT_MIN:
+	case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
+		if (val->intval < LT8491_TBAT_MIN_C * 10 ||
+		    val->intval > LT8491_TBAT_MAX_C * 10)
+			return -EINVAL;
+
+		return i2c_smbus_write_byte_data(info->client,
+						 psp == POWER_SUPPLY_PROP_TEMP_ALERT_MIN ?
+						 LT8491_CFG_TBAT_MIN_REG :
+						 LT8491_CFG_TBAT_MAX_REG,
+						 val->intval / 10);
+	default:
+		return -EINVAL;
+	}
+}
+
+static int lt8491_property_is_writeable(struct power_supply *psy,
+					enum power_supply_property psp)
+{
+	switch (psp) {
+	case POWER_SUPPLY_PROP_TEMP_ALERT_MIN:
+	case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+static const enum power_supply_property lt8491_properties[] = {
+	POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_CURRENT_NOW,
+	POWER_SUPPLY_PROP_POWER_NOW,
+	POWER_SUPPLY_PROP_TEMP,
+	POWER_SUPPLY_PROP_TEMP_ALERT_MIN,
+	POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
+	POWER_SUPPLY_PROP_MODEL_NAME,
+	POWER_SUPPLY_PROP_MANUFACTURER,
+	POWER_SUPPLY_PROP_SERIAL_NUMBER,
+};
+
+static const struct power_supply_desc lt8491_desc = {
+	.name		= "lt8491",
+	.type		= POWER_SUPPLY_TYPE_BATTERY,
+	.properties	= lt8491_properties,
+	.num_properties	= ARRAY_SIZE(lt8491_properties),
+	.get_property	= lt8491_get_property,
+	.set_property	= lt8491_set_property,
+	.property_is_writeable = lt8491_property_is_writeable,
+};
+
+static int lt8491_configure_resistor(struct lt8491_info *info,
+				     const char *propname, int divider,
+				     unsigned int reg)
+{
+	struct device *dev = &info->client->dev;
+	int ret;
+	u32 val;
+
+	ret = device_property_read_u32(dev, propname, &val);
+	if (ret < 0)
+		return dev_err_probe(dev, ret, "Missing %s property.\n",
+				     propname);
+
+	val /= divider;
+	if (val > U16_MAX)
+		return dev_err_probe(dev, -EINVAL,
+				     "Value for %s is out of range.\n",
+				     propname);
+
+	/* The device has no word-write transaction; write low then high byte. */
+	ret = i2c_smbus_write_byte_data(info->client, reg, val & 0xff);
+	if (ret)
+		return ret;
+
+	return i2c_smbus_write_byte_data(info->client, reg + 1, val >> 8);
+}
+
+static int lt8491_configure_telemetry(struct lt8491_info *info)
+{
+	int ret;
+
+	ret = lt8491_configure_resistor(info, "adi,rsense1-micro-ohms", 10,
+					LT8491_CFG_RSENSE1_REG);
+	if (ret)
+		return ret;
+
+	ret = lt8491_configure_resistor(info, "adi,rimon-out-ohms", 10,
+					LT8491_CFG_RIMON_OUT_REG);
+	if (ret)
+		return ret;
+
+	ret = lt8491_configure_resistor(info, "adi,rsense2-micro-ohms", 10,
+					LT8491_CFG_RSENSE2_REG);
+	if (ret)
+		return ret;
+
+	ret = lt8491_configure_resistor(info, "adi,rdaco-ohms", 10,
+					LT8491_CFG_RDACO_REG);
+	if (ret)
+		return ret;
+
+	ret = lt8491_configure_resistor(info, "adi,rfbout1-ohms", 100,
+					LT8491_CFG_RFBOUT1_REG);
+	if (ret)
+		return ret;
+
+	ret = lt8491_configure_resistor(info, "adi,rfbout2-ohms", 10,
+					LT8491_CFG_RFBOUT2_REG);
+	if (ret)
+		return ret;
+
+	ret = lt8491_configure_resistor(info, "adi,rdaci-ohms", 10,
+					LT8491_CFG_RDACI_REG);
+	if (ret)
+		return ret;
+
+	ret = lt8491_configure_resistor(info, "adi,rfbin2-ohms", 10,
+					LT8491_CFG_RFBIN2_REG);
+	if (ret)
+		return ret;
+
+	return lt8491_configure_resistor(info, "adi,rfbin1-ohms", 100,
+					 LT8491_CFG_RFBIN1_REG);
+}
+
+static int lt8491_probe(struct i2c_client *client)
+{
+	struct device *dev = &client->dev;
+	struct lt8491_info *info;
+	struct power_supply_config psy_cfg = {};
+	int ret;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA |
+				     I2C_FUNC_SMBUS_READ_WORD_DATA))
+		return -EOPNOTSUPP;
+
+	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->client = client;
+	psy_cfg.drv_data = info;
+
+	ret = devm_mutex_init(dev, &info->lock);
+	if (ret)
+		return ret;
+
+	ret = lt8491_read_serial_number(info);
+	if (ret)
+		return dev_err_probe(dev, ret,
+				     "Can't read serial. Hardware error.\n");
+
+	ret = lt8491_configure_telemetry(info);
+	if (ret)
+		return ret;
+
+	info->psp = devm_power_supply_register(dev, &lt8491_desc, &psy_cfg);
+	if (IS_ERR(info->psp))
+		return dev_err_probe(dev, PTR_ERR(info->psp),
+				     "Failed to register power supply.\n");
+
+	return 0;
+}
+
+static const struct i2c_device_id lt8491_id[] = {
+	{ .name = "lt8491" },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, lt8491_id);
+
+static const struct of_device_id lt8491_of_match[] = {
+	{ .compatible = "adi,lt8491" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, lt8491_of_match);
+
+static struct i2c_driver lt8491_driver = {
+	.driver = {
+		.name = "lt8491",
+		.of_match_table = lt8491_of_match,
+	},
+	.probe = lt8491_probe,
+	.id_table = lt8491_id,
+};
+module_i2c_driver(lt8491_driver);
+
+MODULE_AUTHOR("John Erasmus Mari Geronimo <johnerasmusmari.geronimo@analog.com>");
+MODULE_DESCRIPTION("LT8491 battery charger");
+MODULE_LICENSE("GPL");
-- 
2.34.1


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-10-29  7:30 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-29  7:30 [PATCH v3 0/2] Add LT8491 driver John Erasmus Mari Geronimo
2026-10-29  7:30 ` [PATCH v3 1/2] dt-bindings: power: supply: add adi,lt8491.yaml John Erasmus Mari Geronimo
2026-10-29  7:30 ` [PATCH v3 2/2] power: supply: add LT8491 battery charger driver John Erasmus Mari Geronimo

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®