mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/3] hwmon: (pmbus/fs1412) Add TDK FS1412 support
@ 2026-10-09  0:56 Abdurrahman Hussain
  2026-10-09  0:56 ` [PATCH 1/3] dt-bindings: vendor-prefixes: Add TDK Corporation Abdurrahman Hussain
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Abdurrahman Hussain @ 2026-10-09  0:56 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Abdurrahman Hussain, Guenter Roeck, Jonathan Corbet, Shuah Khan,
	Randy Dunlap
  Cc: devicetree, linux-kernel, linux-hwmon, linux-doc

The TDK FS1412 is a 12A uPOL regulator with PMBus telemetry. Its
VOUT_MODE has bit 7 set, which makes the VOUT limits relative to
VOUT_COMMAND, and the PMBus core rejects that mode, so the generic pmbus
driver cannot bind it. This series adds a small client driver that
clears the bit and converts the limits to absolute voltages.

Patch 1 adds the TDK vendor prefix, patch 2 documents the FS1412 as a
trivial device, and patch 3 adds the driver.

The driver only advertises what the datasheet's command table lists.
READ_IOUT and OT_WARN_LIMIT answer on the bus but are not in the table,
and the part reports OT_WARNING at room temperature, so the driver leaves
both alone.

Tested on a 6.12 kernel with an FS1412 behind an AXI IIC controller: the
driver binds, input voltage, output voltage and temperature match the raw
registers, the VOUT limits convert both ways, and a written limit reads
back as described.

---
Abdurrahman Hussain (3):
      dt-bindings: vendor-prefixes: Add TDK Corporation
      dt-bindings: trivial-devices: Add TDK FS1412
      hwmon: (pmbus/fs1412) Add TDK FS1412 driver

 .../devicetree/bindings/trivial-devices.yaml       |   2 +
 .../devicetree/bindings/vendor-prefixes.yaml       |   2 +
 Documentation/hwmon/fs1412.rst                     |  87 ++++++++++
 Documentation/hwmon/index.rst                      |   1 +
 MAINTAINERS                                        |   7 +
 drivers/hwmon/pmbus/Kconfig                        |   9 ++
 drivers/hwmon/pmbus/Makefile                       |   1 +
 drivers/hwmon/pmbus/fs1412.c                       | 179 +++++++++++++++++++++
 8 files changed, 288 insertions(+)
---
base-commit: a90ee4305c4a5df72c11b31dacfdc76e00fcf78a
change-id: 20261008-hwmon-pmbus-fs1412-fd4434717c19

Best regards,
--  
Abdurrahman Hussain <abdurrahman@nexthop.ai>


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

* [PATCH 1/3] dt-bindings: vendor-prefixes: Add TDK Corporation
  2026-10-09  0:56 [PATCH 0/3] hwmon: (pmbus/fs1412) Add TDK FS1412 support Abdurrahman Hussain
@ 2026-10-09  0:56 ` Abdurrahman Hussain
  2026-10-09 10:47   ` Krzysztof Kozlowski
  2026-10-09  0:56 ` [PATCH 2/3] dt-bindings: trivial-devices: Add TDK FS1412 Abdurrahman Hussain
  2026-10-09  0:56 ` [PATCH 3/3] hwmon: (pmbus/fs1412) Add TDK FS1412 driver Abdurrahman Hussain
  2 siblings, 1 reply; 9+ messages in thread
From: Abdurrahman Hussain @ 2026-10-09  0:56 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Abdurrahman Hussain, Guenter Roeck, Jonathan Corbet, Shuah Khan,
	Randy Dunlap
  Cc: devicetree, linux-kernel, linux-hwmon, linux-doc

Add the vendor prefix for TDK Corporation, the maker of the FS1412
point-of-load regulator.

Signed-off-by: Abdurrahman Hussain <abdurrahman@nexthop.ai>
---
 Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index ba2002969373..a7c484d1113b 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -1680,6 +1680,8 @@ patternProperties:
     description: Shenzhen City Tang Cheng Technology Co., Ltd.
   "^tcu,.*":
     description: TC Unterhaltungselektronik AG
+  "^tdk,.*":
+    description: TDK Corporation
   "^tdo,.*":
     description: Shangai Top Display Optoelectronics Co., Ltd
   "^team-source-display,.*":

-- 
2.54.0


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

* [PATCH 2/3] dt-bindings: trivial-devices: Add TDK FS1412
  2026-10-09  0:56 [PATCH 0/3] hwmon: (pmbus/fs1412) Add TDK FS1412 support Abdurrahman Hussain
  2026-10-09  0:56 ` [PATCH 1/3] dt-bindings: vendor-prefixes: Add TDK Corporation Abdurrahman Hussain
@ 2026-10-09  0:56 ` Abdurrahman Hussain
  2026-10-09 10:47   ` Krzysztof Kozlowski
  2026-10-09  0:56 ` [PATCH 3/3] hwmon: (pmbus/fs1412) Add TDK FS1412 driver Abdurrahman Hussain
  2 siblings, 1 reply; 9+ messages in thread
From: Abdurrahman Hussain @ 2026-10-09  0:56 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Abdurrahman Hussain, Guenter Roeck, Jonathan Corbet, Shuah Khan,
	Randy Dunlap
  Cc: devicetree, linux-kernel, linux-hwmon, linux-doc

The TDK FS1412 is a 12A uPOL regulator with a PMBus interface. It needs
only a reg property, so document it as a trivial device.

Signed-off-by: Abdurrahman Hussain <abdurrahman@nexthop.ai>
---
 Documentation/devicetree/bindings/trivial-devices.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/trivial-devices.yaml b/Documentation/devicetree/bindings/trivial-devices.yaml
index 2de8eb09cb7d..d2dfde1344e5 100644
--- a/Documentation/devicetree/bindings/trivial-devices.yaml
+++ b/Documentation/devicetree/bindings/trivial-devices.yaml
@@ -469,6 +469,8 @@ properties:
           - synaptics,synaptics_i2c
             # Ambient Light Sensor with SMBUS/Two Wire Serial Interface
           - taos,tsl2550
+            # TDK FS1412 12A uPOL regulator with PMBus
+          - tdk,fs1412
             # Digital PWM System Controller PMBus
           - ti,cd9200
             # Digital PWM System Controller PMBus

-- 
2.54.0


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

* [PATCH 3/3] hwmon: (pmbus/fs1412) Add TDK FS1412 driver
  2026-10-09  0:56 [PATCH 0/3] hwmon: (pmbus/fs1412) Add TDK FS1412 support Abdurrahman Hussain
  2026-10-09  0:56 ` [PATCH 1/3] dt-bindings: vendor-prefixes: Add TDK Corporation Abdurrahman Hussain
  2026-10-09  0:56 ` [PATCH 2/3] dt-bindings: trivial-devices: Add TDK FS1412 Abdurrahman Hussain
@ 2026-10-09  0:56 ` Abdurrahman Hussain
  2026-10-19 20:25   ` Guenter Roeck
  2 siblings, 1 reply; 9+ messages in thread
From: Abdurrahman Hussain @ 2026-10-09  0:56 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Abdurrahman Hussain, Guenter Roeck, Jonathan Corbet, Shuah Khan,
	Randy Dunlap
  Cc: devicetree, linux-kernel, linux-hwmon, linux-doc

The TDK FS1412 is a 12A uPOL regulator with PMBus telemetry for input
voltage, output voltage and temperature, plus the matching status
registers. It has over-current and over-temperature protection with
programmable fault limits but no current telemetry: READ_IOUT is not in
its command table. Its MFR_ID reads "KDT", which the driver checks
before binding.

VOUT_MODE reads 0x98: LINEAR mode with exponent -8 and bit 7 set. The
datasheet defines the output voltage limits relative to the output
voltage with a resolution of 1/256, so 0x0133 against a 0.6V command is
a 120% over-voltage limit. The PMBus core takes bits [7:5] as the mode
and rejects the device, so the driver reports VOUT_MODE with bit 7
cleared and converts the four VOUT limits to and from absolute voltages
against VOUT_COMMAND.

OT_WARN_LIMIT is not in the command table either. The register answers,
but the part has no warning threshold and reports OT_WARNING at room
temperature, so the driver hides the register from the core and only
the OT_FAULT_LIMIT based attributes are provided.

READ_VOUT reports the voltage at the feedback pin, so boards that set
the output with a resistor divider scale in2_input in user space.

Signed-off-by: Abdurrahman Hussain <abdurrahman@nexthop.ai>
---
 Documentation/hwmon/fs1412.rst |  87 ++++++++++++++++++++
 Documentation/hwmon/index.rst  |   1 +
 MAINTAINERS                    |   7 ++
 drivers/hwmon/pmbus/Kconfig    |   9 +++
 drivers/hwmon/pmbus/Makefile   |   1 +
 drivers/hwmon/pmbus/fs1412.c   | 179 +++++++++++++++++++++++++++++++++++++++++
 6 files changed, 284 insertions(+)

diff --git a/Documentation/hwmon/fs1412.rst b/Documentation/hwmon/fs1412.rst
new file mode 100644
index 000000000000..b9b12fcbc5d9
--- /dev/null
+++ b/Documentation/hwmon/fs1412.rst
@@ -0,0 +1,87 @@
+.. SPDX-License-Identifier: GPL-2.0-or-later
+
+Kernel driver fs1412
+====================
+
+Supported chips:
+
+  * TDK FS1412
+
+    Prefix: 'fs1412'
+
+    Addresses scanned: -
+
+    Datasheet: https://product.tdk.com/system/files/dam/doc/product/power/switching-power/micro-pol/data_sheet/fs1412_datasheet.pdf
+
+Authors:
+    Abdurrahman Hussain <abdurrahman@nexthop.ai>
+
+
+Description
+-----------
+
+This driver implements support for the TDK FS1412, a 12A uPOL DC/DC
+regulator with PMBus monitoring of its input voltage, output voltage and
+temperature. The part has over-current and over-temperature protection with
+programmable fault limits but no current telemetry, so no current attributes
+are provided.
+
+The device answers on two I2C addresses: a register interface at the I2C
+base address (0x08 by default) and the PMBus interface at the PMBus base
+address (0x70 by default), each plus the offset strapped on the ADDR pin.
+This driver binds to the PMBus address.
+
+The driver is a client driver to the core PMBus driver.
+Please see Documentation/hwmon/pmbus.rst for details on PMBus client drivers.
+
+
+Usage Notes
+-----------
+
+This driver does not auto-detect devices. You will have to instantiate the
+devices explicitly. Please see Documentation/i2c/instantiating-devices.rst for
+details.
+
+READ_VOUT reports the voltage at the feedback (VFB) pin, not the regulated
+output. When the output is set with an external resistor divider, scale
+in2_input and the in2 limits by the divider ratio in user space.
+
+The device stores its output voltage limits relative to VOUT_COMMAND
+(VOUT_MODE bit 7 set). The driver converts them to and from absolute
+voltages, so the in2 limits read and write in the same units as in2_input.
+A written limit is stored as a 1/256 fraction of VOUT_COMMAND, so it may
+read back rounded to that resolution. The over-voltage protection itself
+engages at one of four thresholds the device rounds the fault limit to; see
+the datasheet.
+
+The part reports an over-temperature warning at room temperature and has no
+OT_WARN_LIMIT in its command table, so temp1_max and its alarm are not
+provided; temp1_crit comes from OT_FAULT_LIMIT.
+
+
+Sysfs entries
+-------------
+
+======================= ======================================================
+in1_label		"vin"
+in1_input		Measured input voltage
+in1_min			Minimum input voltage
+in1_min_alarm		Input voltage low alarm
+in1_crit		Critical high input voltage
+in1_crit_alarm		Input voltage critical high alarm
+
+in2_label		"vout1"
+in2_input		Measured voltage at the feedback pin
+in2_min			Minimum output voltage
+in2_min_alarm		Output voltage low alarm
+in2_max			Maximum output voltage
+in2_max_alarm		Output voltage high alarm
+in2_lcrit		Critical low output voltage
+in2_lcrit_alarm		Output voltage critical low alarm
+in2_crit		Critical high output voltage
+in2_crit_alarm		Output voltage critical high alarm
+
+temp1_input		Measured temperature
+temp1_crit		Critical high temperature
+temp1_crit_alarm	Temperature critical high alarm
+======================= ======================================================
diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst
index 9955a525436a..625833374c94 100644
--- a/Documentation/hwmon/index.rst
+++ b/Documentation/hwmon/index.rst
@@ -79,6 +79,7 @@ Hardware Monitoring Kernel Drivers
    f71805f
    f71882fg
    fam15h_power
+   fs1412
    fsp-3y
    ftsteutates
    g760a
diff --git a/MAINTAINERS b/MAINTAINERS
index 65e8a4b5c90b..05461a380bf7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -26778,6 +26778,13 @@ W:	https://linuxtv.org
 T:	git git://linuxtv.org/media.git
 F:	drivers/media/i2c/tda9840*
 
+TDK FS1412 MICRO POL DRIVER
+M:	Abdurrahman Hussain <abdurrahman@nexthop.ai>
+L:	linux-hwmon@vger.kernel.org
+S:	Maintained
+F:	Documentation/hwmon/fs1412.rst
+F:	drivers/hwmon/pmbus/fs1412.c
+
 TEA5761 TUNER DRIVER
 M:	Mauro Carvalho Chehab <mchehab@kernel.org>
 L:	linux-media@vger.kernel.org
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
index eb71a0ac044b..030ef72415fe 100644
--- a/drivers/hwmon/pmbus/Kconfig
+++ b/drivers/hwmon/pmbus/Kconfig
@@ -132,6 +132,15 @@ config SENSORS_DELTA_AHE50DC_FAN
 	  This driver can also be built as a module. If so, the module
 	  will be called delta-ahe50dc-fan.
 
+config SENSORS_FS1412
+	tristate "TDK FS1412"
+	help
+	  If you say yes here you get hardware monitoring support for the TDK
+	  FS1412 uPOL regulator.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called fs1412.
+
 config SENSORS_FSP_3Y
 	tristate "FSP/3Y-Power power supplies"
 	help
diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile
index e288fe72a437..7bbc0d02bfad 100644
--- a/drivers/hwmon/pmbus/Makefile
+++ b/drivers/hwmon/pmbus/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_SENSORS_APS_379)	+= aps-379.o
 obj-$(CONFIG_SENSORS_BEL_PFE)	+= bel-pfe.o
 obj-$(CONFIG_SENSORS_BPA_RS600)	+= bpa-rs600.o
 obj-$(CONFIG_SENSORS_DELTA_AHE50DC_FAN) += delta-ahe50dc-fan.o
+obj-$(CONFIG_SENSORS_FS1412)	+= fs1412.o
 obj-$(CONFIG_SENSORS_FSP_3Y)	+= fsp-3y.o
 obj-$(CONFIG_SENSORS_HAC300S)	+= hac300s.o
 obj-$(CONFIG_SENSORS_IBM_CFFPS)	+= ibm-cffps.o
diff --git a/drivers/hwmon/pmbus/fs1412.c b/drivers/hwmon/pmbus/fs1412.c
new file mode 100644
index 000000000000..90a72b23967e
--- /dev/null
+++ b/drivers/hwmon/pmbus/fs1412.c
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Hardware monitoring driver for the TDK FS1412 uPOL regulator
+ *
+ * Copyright 2026 Nexthop Systems.
+ */
+
+#include <linux/bits.h>
+#include <linux/i2c.h>
+#include <linux/math.h>
+#include <linux/minmax.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/pmbus.h>
+#include <linux/string.h>
+
+#include "pmbus.h"
+
+#define FS1412_MFR_ID		"KDT"
+#define FS1412_MFR_ID_LEN	(sizeof(FS1412_MFR_ID) - 1)
+
+/* VOUT_MODE: bit 7 selects relative VOUT limits, bits [4:0] the exponent. */
+#define FS1412_VOUT_MODE_RELATIVE	BIT(7)
+#define FS1412_VOUT_MODE_EXP_MASK	0x1f
+#define FS1412_VOUT_EXP_SHIFT		8	/* exponent -8: 1/256 V per LSB */
+
+/*
+ * VOUT_MODE reads 0x98: LINEAR mode with exponent -8 and bit 7 set, which
+ * makes the VOUT limit commands relative to VOUT_COMMAND. The PMBus core
+ * treats bits [7:5] as the mode, so report the mode and exponent with bit
+ * 7 cleared and convert the relative limits in the word accessors below.
+ */
+static int fs1412_read_byte_data(struct i2c_client *client, int page, int reg)
+{
+	int ret;
+
+	if (reg != PMBUS_VOUT_MODE)
+		return -ENODATA;
+
+	ret = pmbus_read_byte_data(client, page, reg);
+	if (ret < 0 || ret == 0xff)
+		return ret;
+
+	return ret & ~FS1412_VOUT_MODE_RELATIVE;
+}
+
+static bool fs1412_vout_limit(int reg)
+{
+	switch (reg) {
+	case PMBUS_VOUT_OV_FAULT_LIMIT:
+	case PMBUS_VOUT_OV_WARN_LIMIT:
+	case PMBUS_VOUT_UV_WARN_LIMIT:
+	case PMBUS_VOUT_UV_FAULT_LIMIT:
+		return true;
+	default:
+		return false;
+	}
+}
+
+/*
+ * The VOUT limits hold the limit as a fraction of VOUT_COMMAND in the same
+ * 1/256 units, so 0x0133 on a 0.6 V command is a 120% limit. Report them
+ * as absolute voltages: limit = fraction * VOUT_COMMAND.
+ */
+static int fs1412_read_word_data(struct i2c_client *client, int page,
+				 int phase, int reg)
+{
+	int rel, cmd;
+
+	/*
+	 * OT_WARN_LIMIT is not in the command table. The register answers,
+	 * but the part has no warning threshold and reports OT_WARNING at
+	 * room temperature, so keep the core from exposing either.
+	 */
+	if (reg == PMBUS_OT_WARN_LIMIT)
+		return -ENXIO;
+	if (!fs1412_vout_limit(reg))
+		return -ENODATA;
+
+	rel = pmbus_read_word_data(client, page, phase, reg);
+	if (rel < 0)
+		return rel;
+
+	cmd = pmbus_read_word_data(client, page, 0xff, PMBUS_VOUT_COMMAND);
+	if (cmd < 0)
+		return cmd;
+
+	return min_t(u32, DIV_ROUND_CLOSEST((u32)rel * cmd,
+					     1 << FS1412_VOUT_EXP_SHIFT), 0xffff);
+}
+
+static int fs1412_write_word_data(struct i2c_client *client, int page,
+				  int reg, u16 word)
+{
+	int cmd;
+
+	if (reg == PMBUS_OT_WARN_LIMIT)
+		return -ENXIO;
+	if (!fs1412_vout_limit(reg))
+		return -ENODATA;
+
+	cmd = pmbus_read_word_data(client, page, 0xff, PMBUS_VOUT_COMMAND);
+	if (cmd < 0)
+		return cmd;
+	if (!cmd)
+		return -EINVAL;
+
+	word = clamp_val(DIV_ROUND_CLOSEST(word << FS1412_VOUT_EXP_SHIFT, cmd),
+			 0, 0xffff);
+
+	return pmbus_write_word_data(client, page, reg, word);
+}
+
+static struct pmbus_driver_info fs1412_info = {
+	.pages = 1,
+	.format[PSC_VOLTAGE_IN] = linear,
+	.format[PSC_VOLTAGE_OUT] = linear,
+	.format[PSC_TEMPERATURE] = linear,
+	.func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT |
+		   PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
+		   PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+	.read_byte_data = fs1412_read_byte_data,
+	.read_word_data = fs1412_read_word_data,
+	.write_word_data = fs1412_write_word_data,
+};
+
+static int fs1412_probe(struct i2c_client *client)
+{
+	char buf[I2C_SMBUS_BLOCK_MAX + 1] = { 0 };
+	struct device *dev = &client->dev;
+	int ret;
+
+	ret = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, buf);
+	if (ret < 0)
+		return dev_err_probe(dev, ret, "Failed to read PMBUS_MFR_ID\n");
+
+	if (ret != FS1412_MFR_ID_LEN ||
+	    strncmp(buf, FS1412_MFR_ID, FS1412_MFR_ID_LEN))
+		return dev_err_probe(dev, -ENODEV,
+				     "Unsupported Manufacturer ID '%s'\n", buf);
+
+	/* The relative limit conversion assumes the 1/256 V exponent. */
+	ret = i2c_smbus_read_byte_data(client, PMBUS_VOUT_MODE);
+	if (ret < 0)
+		return dev_err_probe(dev, ret, "Failed to read VOUT_MODE\n");
+	if ((ret & FS1412_VOUT_MODE_EXP_MASK) != 0x18)
+		return dev_err_probe(dev, -ENODEV,
+				     "Unsupported VOUT_MODE 0x%02x\n", ret);
+
+	return pmbus_do_probe(client, &fs1412_info);
+}
+
+static const struct i2c_device_id fs1412_id[] = {
+	{ .name = "fs1412" },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, fs1412_id);
+
+static const struct of_device_id fs1412_of_match[] = {
+	{ .compatible = "tdk,fs1412" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, fs1412_of_match);
+
+static struct i2c_driver fs1412_driver = {
+	.driver = {
+		.name = "fs1412",
+		.of_match_table = fs1412_of_match,
+	},
+	.probe = fs1412_probe,
+	.id_table = fs1412_id,
+};
+
+module_i2c_driver(fs1412_driver);
+
+MODULE_AUTHOR("Abdurrahman Hussain <abdurrahman@nexthop.ai>");
+MODULE_DESCRIPTION("PMBus driver for the TDK FS1412 uPOL regulator");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("PMBUS");

-- 
2.54.0


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

* Re: [PATCH 1/3] dt-bindings: vendor-prefixes: Add TDK Corporation
  2026-10-09  0:56 ` [PATCH 1/3] dt-bindings: vendor-prefixes: Add TDK Corporation Abdurrahman Hussain
@ 2026-10-09 10:47   ` Krzysztof Kozlowski
  0 siblings, 0 replies; 9+ messages in thread
From: Krzysztof Kozlowski @ 2026-10-09 10:47 UTC (permalink / raw)
  To: Abdurrahman Hussain
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Guenter Roeck,
	Jonathan Corbet, Shuah Khan, Randy Dunlap, devicetree,
	linux-kernel, linux-hwmon, linux-doc

On Thu, Oct 08, 2026 at 05:56:02PM -0700, Abdurrahman Hussain wrote:
> Add the vendor prefix for TDK Corporation, the maker of the FS1412
> point-of-load regulator.
> 
> Signed-off-by: Abdurrahman Hussain <abdurrahman@nexthop.ai>
> ---
>  Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++
>  1 file changed, 2 insertions(+)

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>

Best regards,
Krzysztof


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

* Re: [PATCH 2/3] dt-bindings: trivial-devices: Add TDK FS1412
  2026-10-09  0:56 ` [PATCH 2/3] dt-bindings: trivial-devices: Add TDK FS1412 Abdurrahman Hussain
@ 2026-10-09 10:47   ` Krzysztof Kozlowski
  0 siblings, 0 replies; 9+ messages in thread
From: Krzysztof Kozlowski @ 2026-10-09 10:47 UTC (permalink / raw)
  To: Abdurrahman Hussain
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Guenter Roeck,
	Jonathan Corbet, Shuah Khan, Randy Dunlap, devicetree,
	linux-kernel, linux-hwmon, linux-doc

On Thu, Oct 08, 2026 at 05:56:03PM -0700, Abdurrahman Hussain wrote:
> The TDK FS1412 is a 12A uPOL regulator with a PMBus interface. It needs
> only a reg property, so document it as a trivial device.
> 
> Signed-off-by: Abdurrahman Hussain <abdurrahman@nexthop.ai>
> ---
>  Documentation/devicetree/bindings/trivial-devices.yaml | 2 ++
>  1 file changed, 2 insertions(+)

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>

Best regards,
Krzysztof


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

* Re: [PATCH 3/3] hwmon: (pmbus/fs1412) Add TDK FS1412 driver
  2026-10-09  0:56 ` [PATCH 3/3] hwmon: (pmbus/fs1412) Add TDK FS1412 driver Abdurrahman Hussain
@ 2026-10-19 20:25   ` Guenter Roeck
  2026-10-20  7:31     ` Abdurrahman Hussain
  0 siblings, 1 reply; 9+ messages in thread
From: Guenter Roeck @ 2026-10-19 20:25 UTC (permalink / raw)
  To: Abdurrahman Hussain
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jonathan Corbet,
	Shuah Khan, Randy Dunlap, devicetree, linux-kernel, linux-hwmon,
	linux-doc

On Thu, Oct 08, 2026 at 05:56:04PM -0700, Abdurrahman Hussain wrote:
> The TDK FS1412 is a 12A uPOL regulator with PMBus telemetry for input
> voltage, output voltage and temperature, plus the matching status
> registers. It has over-current and over-temperature protection with
> programmable fault limits but no current telemetry: READ_IOUT is not in
> its command table. Its MFR_ID reads "KDT", which the driver checks
> before binding.
> 
> VOUT_MODE reads 0x98: LINEAR mode with exponent -8 and bit 7 set. The
> datasheet defines the output voltage limits relative to the output
> voltage with a resolution of 1/256, so 0x0133 against a 0.6V command is
> a 120% over-voltage limit. The PMBus core takes bits [7:5] as the mode
> and rejects the device, so the driver reports VOUT_MODE with bit 7
> cleared and converts the four VOUT limits to and from absolute voltages
> against VOUT_COMMAND.
> 
> OT_WARN_LIMIT is not in the command table either. The register answers,
> but the part has no warning threshold and reports OT_WARNING at room
> temperature, so the driver hides the register from the core and only
> the OT_FAULT_LIMIT based attributes are provided.
> 
> READ_VOUT reports the voltage at the feedback pin, so boards that set
> the output with a resistor divider scale in2_input in user space.
> 
> Signed-off-by: Abdurrahman Hussain <abdurrahman@nexthop.ai>
> ---
>  Documentation/hwmon/fs1412.rst |  87 ++++++++++++++++++++
>  Documentation/hwmon/index.rst  |   1 +
>  MAINTAINERS                    |   7 ++
>  drivers/hwmon/pmbus/Kconfig    |   9 +++
>  drivers/hwmon/pmbus/Makefile   |   1 +
>  drivers/hwmon/pmbus/fs1412.c   | 179 +++++++++++++++++++++++++++++++++++++++++
>  6 files changed, 284 insertions(+)
> 
> diff --git a/Documentation/hwmon/fs1412.rst b/Documentation/hwmon/fs1412.rst
> new file mode 100644
> index 000000000000..b9b12fcbc5d9
> --- /dev/null
> +++ b/Documentation/hwmon/fs1412.rst
> @@ -0,0 +1,87 @@
> +.. SPDX-License-Identifier: GPL-2.0-or-later
> +
> +Kernel driver fs1412
> +====================
> +
> +Supported chips:
> +
> +  * TDK FS1412
> +
> +    Prefix: 'fs1412'
> +
> +    Addresses scanned: -
> +
> +    Datasheet: https://product.tdk.com/system/files/dam/doc/product/power/switching-power/micro-pol/data_sheet/fs1412_datasheet.pdf
> +
> +Authors:
> +    Abdurrahman Hussain <abdurrahman@nexthop.ai>
> +
> +
> +Description
> +-----------
> +
> +This driver implements support for the TDK FS1412, a 12A uPOL DC/DC
> +regulator with PMBus monitoring of its input voltage, output voltage and
> +temperature. The part has over-current and over-temperature protection with
> +programmable fault limits but no current telemetry, so no current attributes
> +are provided.
> +
> +The device answers on two I2C addresses: a register interface at the I2C
> +base address (0x08 by default) and the PMBus interface at the PMBus base
> +address (0x70 by default), each plus the offset strapped on the ADDR pin.
> +This driver binds to the PMBus address.
> +
> +The driver is a client driver to the core PMBus driver.
> +Please see Documentation/hwmon/pmbus.rst for details on PMBus client drivers.
> +
> +
> +Usage Notes
> +-----------
> +
> +This driver does not auto-detect devices. You will have to instantiate the
> +devices explicitly. Please see Documentation/i2c/instantiating-devices.rst for
> +details.
> +
> +READ_VOUT reports the voltage at the feedback (VFB) pin, not the regulated
> +output. When the output is set with an external resistor divider, scale
> +in2_input and the in2 limits by the divider ratio in user space.
> +
> +The device stores its output voltage limits relative to VOUT_COMMAND
> +(VOUT_MODE bit 7 set). The driver converts them to and from absolute
> +voltages, so the in2 limits read and write in the same units as in2_input.
> +A written limit is stored as a 1/256 fraction of VOUT_COMMAND, so it may
> +read back rounded to that resolution. The over-voltage protection itself
> +engages at one of four thresholds the device rounds the fault limit to; see
> +the datasheet.
> +
> +The part reports an over-temperature warning at room temperature and has no
> +OT_WARN_LIMIT in its command table, so temp1_max and its alarm are not
> +provided; temp1_crit comes from OT_FAULT_LIMIT.
> +
> +
> +Sysfs entries
> +-------------
> +
> +======================= ======================================================
> +in1_label		"vin"
> +in1_input		Measured input voltage
> +in1_min			Minimum input voltage
> +in1_min_alarm		Input voltage low alarm
> +in1_crit		Critical high input voltage
> +in1_crit_alarm		Input voltage critical high alarm
> +
> +in2_label		"vout1"
> +in2_input		Measured voltage at the feedback pin
> +in2_min			Minimum output voltage
> +in2_min_alarm		Output voltage low alarm
> +in2_max			Maximum output voltage
> +in2_max_alarm		Output voltage high alarm
> +in2_lcrit		Critical low output voltage
> +in2_lcrit_alarm		Output voltage critical low alarm
> +in2_crit		Critical high output voltage
> +in2_crit_alarm		Output voltage critical high alarm
> +
> +temp1_input		Measured temperature
> +temp1_crit		Critical high temperature
> +temp1_crit_alarm	Temperature critical high alarm
> +======================= ======================================================
> diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst
> index 9955a525436a..625833374c94 100644
> --- a/Documentation/hwmon/index.rst
> +++ b/Documentation/hwmon/index.rst
> @@ -79,6 +79,7 @@ Hardware Monitoring Kernel Drivers
>     f71805f
>     f71882fg
>     fam15h_power
> +   fs1412
>     fsp-3y
>     ftsteutates
>     g760a
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 65e8a4b5c90b..05461a380bf7 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -26778,6 +26778,13 @@ W:	https://linuxtv.org
>  T:	git git://linuxtv.org/media.git
>  F:	drivers/media/i2c/tda9840*
>  
> +TDK FS1412 MICRO POL DRIVER
> +M:	Abdurrahman Hussain <abdurrahman@nexthop.ai>
> +L:	linux-hwmon@vger.kernel.org
> +S:	Maintained
> +F:	Documentation/hwmon/fs1412.rst
> +F:	drivers/hwmon/pmbus/fs1412.c
> +
>  TEA5761 TUNER DRIVER
>  M:	Mauro Carvalho Chehab <mchehab@kernel.org>
>  L:	linux-media@vger.kernel.org
> diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
> index eb71a0ac044b..030ef72415fe 100644
> --- a/drivers/hwmon/pmbus/Kconfig
> +++ b/drivers/hwmon/pmbus/Kconfig
> @@ -132,6 +132,15 @@ config SENSORS_DELTA_AHE50DC_FAN
>  	  This driver can also be built as a module. If so, the module
>  	  will be called delta-ahe50dc-fan.
>  
> +config SENSORS_FS1412
> +	tristate "TDK FS1412"
> +	help
> +	  If you say yes here you get hardware monitoring support for the TDK
> +	  FS1412 uPOL regulator.
> +
> +	  This driver can also be built as a module. If so, the module will
> +	  be called fs1412.
> +
>  config SENSORS_FSP_3Y
>  	tristate "FSP/3Y-Power power supplies"
>  	help
> diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile
> index e288fe72a437..7bbc0d02bfad 100644
> --- a/drivers/hwmon/pmbus/Makefile
> +++ b/drivers/hwmon/pmbus/Makefile
> @@ -13,6 +13,7 @@ obj-$(CONFIG_SENSORS_APS_379)	+= aps-379.o
>  obj-$(CONFIG_SENSORS_BEL_PFE)	+= bel-pfe.o
>  obj-$(CONFIG_SENSORS_BPA_RS600)	+= bpa-rs600.o
>  obj-$(CONFIG_SENSORS_DELTA_AHE50DC_FAN) += delta-ahe50dc-fan.o
> +obj-$(CONFIG_SENSORS_FS1412)	+= fs1412.o
>  obj-$(CONFIG_SENSORS_FSP_3Y)	+= fsp-3y.o
>  obj-$(CONFIG_SENSORS_HAC300S)	+= hac300s.o
>  obj-$(CONFIG_SENSORS_IBM_CFFPS)	+= ibm-cffps.o
> diff --git a/drivers/hwmon/pmbus/fs1412.c b/drivers/hwmon/pmbus/fs1412.c
> new file mode 100644
> index 000000000000..90a72b23967e
> --- /dev/null
> +++ b/drivers/hwmon/pmbus/fs1412.c
> @@ -0,0 +1,179 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Hardware monitoring driver for the TDK FS1412 uPOL regulator
> + *
> + * Copyright 2026 Nexthop Systems.
> + */
> +
> +#include <linux/bits.h>
> +#include <linux/i2c.h>
> +#include <linux/math.h>
> +#include <linux/minmax.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/pmbus.h>
> +#include <linux/string.h>
> +
> +#include "pmbus.h"
> +
> +#define FS1412_MFR_ID		"KDT"
> +#define FS1412_MFR_ID_LEN	(sizeof(FS1412_MFR_ID) - 1)
> +
> +/* VOUT_MODE: bit 7 selects relative VOUT limits, bits [4:0] the exponent. */
> +#define FS1412_VOUT_MODE_RELATIVE	BIT(7)
> +#define FS1412_VOUT_MODE_EXP_MASK	0x1f
> +#define FS1412_VOUT_EXP_SHIFT		8	/* exponent -8: 1/256 V per LSB */
> +
> +/*
> + * VOUT_MODE reads 0x98: LINEAR mode with exponent -8 and bit 7 set, which
> + * makes the VOUT limit commands relative to VOUT_COMMAND. The PMBus core
> + * treats bits [7:5] as the mode, so report the mode and exponent with bit
> + * 7 cleared and convert the relative limits in the word accessors below.
> + */
> +static int fs1412_read_byte_data(struct i2c_client *client, int page, int reg)
> +{
> +	int ret;
> +
> +	if (reg != PMBUS_VOUT_MODE)
> +		return -ENODATA;
> +
> +	ret = pmbus_read_byte_data(client, page, reg);
> +	if (ret < 0 || ret == 0xff)
> +		return ret;
> +
> +	return ret & ~FS1412_VOUT_MODE_RELATIVE;

This implementation is wrong. Support for relative mode should instead
be added to the PMBus core. Or, rather, this driver should be tested with
https://patchwork.kernel.org/project/linux-hwmon/patch/20240315151855.377627-2-lars.petter.mostad@appear.net/
in place (with appropriate fixes for that patch if necessary), and the
patches should be applied together.

Thanks,
Guenter

> +}
> +
> +static bool fs1412_vout_limit(int reg)
> +{
> +	switch (reg) {
> +	case PMBUS_VOUT_OV_FAULT_LIMIT:
> +	case PMBUS_VOUT_OV_WARN_LIMIT:
> +	case PMBUS_VOUT_UV_WARN_LIMIT:
> +	case PMBUS_VOUT_UV_FAULT_LIMIT:
> +		return true;
> +	default:
> +		return false;
> +	}
> +}
> +
> +/*
> + * The VOUT limits hold the limit as a fraction of VOUT_COMMAND in the same
> + * 1/256 units, so 0x0133 on a 0.6 V command is a 120% limit. Report them
> + * as absolute voltages: limit = fraction * VOUT_COMMAND.
> + */
> +static int fs1412_read_word_data(struct i2c_client *client, int page,
> +				 int phase, int reg)
> +{
> +	int rel, cmd;
> +
> +	/*
> +	 * OT_WARN_LIMIT is not in the command table. The register answers,
> +	 * but the part has no warning threshold and reports OT_WARNING at
> +	 * room temperature, so keep the core from exposing either.
> +	 */
> +	if (reg == PMBUS_OT_WARN_LIMIT)
> +		return -ENXIO;
> +	if (!fs1412_vout_limit(reg))
> +		return -ENODATA;
> +
> +	rel = pmbus_read_word_data(client, page, phase, reg);
> +	if (rel < 0)
> +		return rel;
> +
> +	cmd = pmbus_read_word_data(client, page, 0xff, PMBUS_VOUT_COMMAND);
> +	if (cmd < 0)
> +		return cmd;
> +
> +	return min_t(u32, DIV_ROUND_CLOSEST((u32)rel * cmd,
> +					     1 << FS1412_VOUT_EXP_SHIFT), 0xffff);
> +}
> +
> +static int fs1412_write_word_data(struct i2c_client *client, int page,
> +				  int reg, u16 word)
> +{
> +	int cmd;
> +
> +	if (reg == PMBUS_OT_WARN_LIMIT)
> +		return -ENXIO;
> +	if (!fs1412_vout_limit(reg))
> +		return -ENODATA;
> +
> +	cmd = pmbus_read_word_data(client, page, 0xff, PMBUS_VOUT_COMMAND);
> +	if (cmd < 0)
> +		return cmd;
> +	if (!cmd)
> +		return -EINVAL;
> +
> +	word = clamp_val(DIV_ROUND_CLOSEST(word << FS1412_VOUT_EXP_SHIFT, cmd),
> +			 0, 0xffff);
> +
> +	return pmbus_write_word_data(client, page, reg, word);
> +}
> +
> +static struct pmbus_driver_info fs1412_info = {
> +	.pages = 1,
> +	.format[PSC_VOLTAGE_IN] = linear,
> +	.format[PSC_VOLTAGE_OUT] = linear,
> +	.format[PSC_TEMPERATURE] = linear,
> +	.func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT |
> +		   PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
> +		   PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
> +	.read_byte_data = fs1412_read_byte_data,
> +	.read_word_data = fs1412_read_word_data,
> +	.write_word_data = fs1412_write_word_data,
> +};
> +
> +static int fs1412_probe(struct i2c_client *client)
> +{
> +	char buf[I2C_SMBUS_BLOCK_MAX + 1] = { 0 };
> +	struct device *dev = &client->dev;
> +	int ret;
> +
> +	ret = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, buf);
> +	if (ret < 0)
> +		return dev_err_probe(dev, ret, "Failed to read PMBUS_MFR_ID\n");
> +
> +	if (ret != FS1412_MFR_ID_LEN ||
> +	    strncmp(buf, FS1412_MFR_ID, FS1412_MFR_ID_LEN))
> +		return dev_err_probe(dev, -ENODEV,
> +				     "Unsupported Manufacturer ID '%s'\n", buf);
> +
> +	/* The relative limit conversion assumes the 1/256 V exponent. */
> +	ret = i2c_smbus_read_byte_data(client, PMBUS_VOUT_MODE);
> +	if (ret < 0)
> +		return dev_err_probe(dev, ret, "Failed to read VOUT_MODE\n");
> +	if ((ret & FS1412_VOUT_MODE_EXP_MASK) != 0x18)
> +		return dev_err_probe(dev, -ENODEV,
> +				     "Unsupported VOUT_MODE 0x%02x\n", ret);
> +
> +	return pmbus_do_probe(client, &fs1412_info);
> +}
> +
> +static const struct i2c_device_id fs1412_id[] = {
> +	{ .name = "fs1412" },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(i2c, fs1412_id);
> +
> +static const struct of_device_id fs1412_of_match[] = {
> +	{ .compatible = "tdk,fs1412" },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, fs1412_of_match);
> +
> +static struct i2c_driver fs1412_driver = {
> +	.driver = {
> +		.name = "fs1412",
> +		.of_match_table = fs1412_of_match,
> +	},
> +	.probe = fs1412_probe,
> +	.id_table = fs1412_id,
> +};
> +
> +module_i2c_driver(fs1412_driver);
> +
> +MODULE_AUTHOR("Abdurrahman Hussain <abdurrahman@nexthop.ai>");
> +MODULE_DESCRIPTION("PMBus driver for the TDK FS1412 uPOL regulator");
> +MODULE_LICENSE("GPL");
> +MODULE_IMPORT_NS("PMBUS");

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

* Re: [PATCH 3/3] hwmon: (pmbus/fs1412) Add TDK FS1412 driver
  2026-10-19 20:25   ` Guenter Roeck
@ 2026-10-20  7:31     ` Abdurrahman Hussain
  2026-10-20 15:27       ` Guenter Roeck
  0 siblings, 1 reply; 9+ messages in thread
From: Abdurrahman Hussain @ 2026-10-20  7:31 UTC (permalink / raw)
  To: Guenter Roeck, Abdurrahman Hussain
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jonathan Corbet,
	Shuah Khan, Randy Dunlap, devicetree, linux-kernel, linux-hwmon,
	linux-doc, Guenter Roeck

On Mon Oct 19, 2026 at 1:25 PM PDT, Guenter Roeck wrote:
> This implementation is wrong. Support for relative mode should instead
> be added to the PMBus core. Or, rather, this driver should be tested with
> https://patchwork.kernel.org/project/linux-hwmon/patch/20240315151855.377627-2-lars.petter.mostad@appear.net/
> in place (with appropriate fixes for that patch if necessary), and the
> patches should be applied together.

Thanks! That is exactly what I was looking for, but my search for
fs1412 on lore didn't turn it up anything.

v2 will carry Lars' patch (Cc'd), rebased, with the driver reduced to
the MFR_ID check and hiding OT_WARN_LIMIT. v2 also adds the FS1525, a
25A part from the same family that is relative-only as well, so the
core change has two users. Fixes on top of Lars' version:

 - check VOUT_MODE for 0xff before testing the relative bit; as posted,
   a chip that does not support VOUT_MODE (reads 0xff) is marked
   relative and gets a bogus exponent
 - signed division, and clamp the user value before scaling it
 - fail probe if VOUT_COMMAND reads 0 rather than divide by it later
 - only update the cached VOUT_COMMAND after the write succeeded

We have a board with four FS1412 and one FS1525, so I could test both
parts with these patches on 7.2.10. Since your concerns in the 2024
thread were about how these parts actually behave, here is what they
do:

VOUT_MODE is read-only and relative-only. Both datasheets mark it
read-only. FS1412 returns 0x98 (exponent -8), FS1525 returns 0x96
(exponent -10). Writing 0x18 to VOUT_MODE on all four FS1412 is NACKed,
STATUS_CML reports invalid data (0x40), and VOUT_MODE stays 0x98.

Which commands are relative. The FS1525 command table marks
VOUT_MARGIN_HIGH/LOW, VOUT_OV_FAULT_LIMIT, VOUT_OV_WARN_LIMIT,
VOUT_UV_WARN_LIMIT, VOUT_UV_FAULT_LIMIT and POWER_GOOD_ON as "L16, 1.3
relative format". VOUT_COMMAND, VOUT_MAX and READ_VOUT are absolute.
That matches the list in Lars' patch; POWER_GOOD_ON is relative too,
but the core does not use it. The FS1412 datasheet says the same for
the limits it describes. Raw defaults, as a fraction of VOUT_COMMAND:

                     FS1412 (0x98)   FS1525 (0x96)
  VOUT_COMMAND       0x009a  0.602V  0x0266  0.600V
  VOUT_OV_FAULT      0x0133  1.199   0x04cc  1.199
  VOUT_OV_WARN       0x0126  1.148   0x1000  4.000
  VOUT_UV_WARN       0x00d9  0.848   0x0366  0.850
  VOUT_UV_FAULT      0x00cc  0.797   0x0333  0.800
  POWER_GOOD_ON      0x00e6  0.898   0x0365  0.849
  VOUT_MARGIN_HIGH   0x0119  1.098   0x0466  1.100
  VOUT_MARGIN_LOW    0x00e6  0.898   0x0399  0.899

With the patches the FS1412 reports in2_crit/max/min/lcrit as
721/690/509/478 mV against an in2_input of ~560-580 mV. Writing
in2_max and in2_min stores 0x012e / 0x00d0 and reads back within one
1/256 step. On the FS1525, writing 600 to in2_min stores 0x0402 and
writing 509 restores the original 0x0366. I did not exercise the
regulator path; the driver does not register a regulator.

Paging. Neither part implements PAGE. A PAGE read is NACKed and sets
STATUS_CML INVALID_CMD (0x80), so on these parts relative mode can only
be per chip. The patch tracks it per page, which also covers a
multi-page chip that sets the bit on every page.

Vendors getting it wrong. You were right to worry. Some things I ran
into:

 - The OV fault limit is rounded internally to one of four settings
   (105-120% in 5% steps on the FS1525), so only some values written
   to it take effect.
 - The parts are only partly consistent with their own command tables:
   OT_WARN_LIMIT and READ_IOUT are not listed for the FS1412, but both
   answer without a CML error, and OT_WARNING sets at room temperature.
 - The factory programming varies between parts on the same board: one
   FS1412 has VOUT_MAX 0xa500 and VOUT_MARGIN_HIGH 0xa400, the others
   0x0300 and 0x0119; another has VOUT_MARGIN_LOW 0x0000. The core does
   not touch these for hwmon.
 - The VOUT domain differs between the two parts. FS1412 reports
   READ_VOUT at the feedback pin, so it is in the same domain as
   VOUT_COMMAND and the converted limits. TDK told us that the FS1525
   reports READ_VOUT as the actual output regardless of an external
   divider. On our board that is 1.094V against a VOUT_COMMAND of 0.600V
   (a divider for a 1.1V rail).

   I checked what the FS1525 compares READ_VOUT against. Setting
   VOUT_OV_WARN_LIMIT to 1.5 sets VOUT_OV_WARNING; setting
   VOUT_UV_WARN_LIMIT to 1.5 does not. So the part compares the
   output-domain READ_VOUT against limit * VOUT_COMMAND (0.9V), which
   is exactly the value the core reports. That is presumably why this
   board's OV warn limit defaults to 400%.

One question before v2. The FS1525 over-voltage fault is the exception:
the datasheet says it is an analog comparison at the FB pin, at the
VOUT_OV_FAULT_LIMIT fraction of VOUT_COMMAND. So on a board with an
external divider in2_crit is in feedback-pin volts while in2_input is
the rail. On our board's FS1525 that is in2_crit 718 mV against
in2_input 1093 mV, with no alarm, and the actual trip point is about
1.31V on the rail. The chip has no way to report the divider. Which
would you prefer?

 a) Hide VOUT_OV_FAULT_LIMIT on the FS1525, so there is no in2_crit.
    Nothing misleading, but boards without a divider lose a correct
    in2_crit too.
 b) Scale in2_crit by READ_VOUT / VOUT_COMMAND measured at probe.
    Right while the rail regulates, wrong if it is off, ramping or
    margined at probe time.
 c) Describe the divider in DT and scale in2_crit by it. The FS1525
    would then need its own binding instead of a trivial-devices entry.

I lean towards a).

For other parts with relative mode I only know of the NCP3286 you
mentioned.

Thanks,
Abdurrahman


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

* Re: [PATCH 3/3] hwmon: (pmbus/fs1412) Add TDK FS1412 driver
  2026-10-20  7:31     ` Abdurrahman Hussain
@ 2026-10-20 15:27       ` Guenter Roeck
  0 siblings, 0 replies; 9+ messages in thread
From: Guenter Roeck @ 2026-10-20 15:27 UTC (permalink / raw)
  To: Abdurrahman Hussain
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jonathan Corbet,
	Shuah Khan, Randy Dunlap, devicetree, linux-kernel, linux-hwmon,
	linux-doc, Guenter Roeck

On Tue, Oct 20, 2026 at 12:31:11AM -0700, Abdurrahman Hussain wrote:
> On Mon Oct 19, 2026 at 1:25 PM PDT, Guenter Roeck wrote:
> > This implementation is wrong. Support for relative mode should instead
> > be added to the PMBus core. Or, rather, this driver should be tested with
> > https://patchwork.kernel.org/project/linux-hwmon/patch/20240315151855.377627-2-lars.petter.mostad@appear.net/
> > in place (with appropriate fixes for that patch if necessary), and the
> > patches should be applied together.
> 
> Thanks! That is exactly what I was looking for, but my search for
> fs1412 on lore didn't turn it up anything.
> 
> v2 will carry Lars' patch (Cc'd), rebased, with the driver reduced to
> the MFR_ID check and hiding OT_WARN_LIMIT. v2 also adds the FS1525, a
> 25A part from the same family that is relative-only as well, so the
> core change has two users. Fixes on top of Lars' version:
> 
>  - check VOUT_MODE for 0xff before testing the relative bit; as posted,
>    a chip that does not support VOUT_MODE (reads 0xff) is marked
>    relative and gets a bogus exponent
>  - signed division, and clamp the user value before scaling it
>  - fail probe if VOUT_COMMAND reads 0 rather than divide by it later
>  - only update the cached VOUT_COMMAND after the write succeeded
> 
> We have a board with four FS1412 and one FS1525, so I could test both
> parts with these patches on 7.2.10. Since your concerns in the 2024
> thread were about how these parts actually behave, here is what they

Not that I recall that ;-)

> do:
> 
> VOUT_MODE is read-only and relative-only. Both datasheets mark it
> read-only. FS1412 returns 0x98 (exponent -8), FS1525 returns 0x96
> (exponent -10). Writing 0x18 to VOUT_MODE on all four FS1412 is NACKed,
> STATUS_CML reports invalid data (0x40), and VOUT_MODE stays 0x98.
> 
> Which commands are relative. The FS1525 command table marks
> VOUT_MARGIN_HIGH/LOW, VOUT_OV_FAULT_LIMIT, VOUT_OV_WARN_LIMIT,
> VOUT_UV_WARN_LIMIT, VOUT_UV_FAULT_LIMIT and POWER_GOOD_ON as "L16, 1.3
> relative format". VOUT_COMMAND, VOUT_MAX and READ_VOUT are absolute.
> That matches the list in Lars' patch; POWER_GOOD_ON is relative too,
> but the core does not use it. The FS1412 datasheet says the same for
> the limits it describes. Raw defaults, as a fraction of VOUT_COMMAND:
> 
>                      FS1412 (0x98)   FS1525 (0x96)
>   VOUT_COMMAND       0x009a  0.602V  0x0266  0.600V
>   VOUT_OV_FAULT      0x0133  1.199   0x04cc  1.199
>   VOUT_OV_WARN       0x0126  1.148   0x1000  4.000
>   VOUT_UV_WARN       0x00d9  0.848   0x0366  0.850
>   VOUT_UV_FAULT      0x00cc  0.797   0x0333  0.800
>   POWER_GOOD_ON      0x00e6  0.898   0x0365  0.849
>   VOUT_MARGIN_HIGH   0x0119  1.098   0x0466  1.100
>   VOUT_MARGIN_LOW    0x00e6  0.898   0x0399  0.899
> 
> With the patches the FS1412 reports in2_crit/max/min/lcrit as
> 721/690/509/478 mV against an in2_input of ~560-580 mV. Writing
> in2_max and in2_min stores 0x012e / 0x00d0 and reads back within one
> 1/256 step. On the FS1525, writing 600 to in2_min stores 0x0402 and
> writing 509 restores the original 0x0366. I did not exercise the
> regulator path; the driver does not register a regulator.
> 
> Paging. Neither part implements PAGE. A PAGE read is NACKed and sets
> STATUS_CML INVALID_CMD (0x80), so on these parts relative mode can only
> be per chip. The patch tracks it per page, which also covers a
> multi-page chip that sets the bit on every page.
> 
> Vendors getting it wrong. You were right to worry. Some things I ran
> into:
> 
>  - The OV fault limit is rounded internally to one of four settings
>    (105-120% in 5% steps on the FS1525), so only some values written
>    to it take effect.
>  - The parts are only partly consistent with their own command tables:
>    OT_WARN_LIMIT and READ_IOUT are not listed for the FS1412, but both
>    answer without a CML error, and OT_WARNING sets at room temperature.
>  - The factory programming varies between parts on the same board: one
>    FS1412 has VOUT_MAX 0xa500 and VOUT_MARGIN_HIGH 0xa400, the others
>    0x0300 and 0x0119; another has VOUT_MARGIN_LOW 0x0000. The core does
>    not touch these for hwmon.
>  - The VOUT domain differs between the two parts. FS1412 reports
>    READ_VOUT at the feedback pin, so it is in the same domain as
>    VOUT_COMMAND and the converted limits. TDK told us that the FS1525
>    reports READ_VOUT as the actual output regardless of an external
>    divider. On our board that is 1.094V against a VOUT_COMMAND of 0.600V
>    (a divider for a 1.1V rail).
> 
>    I checked what the FS1525 compares READ_VOUT against. Setting
>    VOUT_OV_WARN_LIMIT to 1.5 sets VOUT_OV_WARNING; setting
>    VOUT_UV_WARN_LIMIT to 1.5 does not. So the part compares the
>    output-domain READ_VOUT against limit * VOUT_COMMAND (0.9V), which
>    is exactly the value the core reports. That is presumably why this
>    board's OV warn limit defaults to 400%.
> 
> One question before v2. The FS1525 over-voltage fault is the exception:
> the datasheet says it is an analog comparison at the FB pin, at the
> VOUT_OV_FAULT_LIMIT fraction of VOUT_COMMAND. So on a board with an
> external divider in2_crit is in feedback-pin volts while in2_input is
> the rail. On our board's FS1525 that is in2_crit 718 mV against
> in2_input 1093 mV, with no alarm, and the actual trip point is about
> 1.31V on the rail. The chip has no way to report the divider. Which
> would you prefer?
> 
>  a) Hide VOUT_OV_FAULT_LIMIT on the FS1525, so there is no in2_crit.
>     Nothing misleading, but boards without a divider lose a correct
>     in2_crit too.
>  b) Scale in2_crit by READ_VOUT / VOUT_COMMAND measured at probe.
>     Right while the rail regulates, wrong if it is off, ramping or
>     margined at probe time.
>  c) Describe the divider in DT and scale in2_crit by it. The FS1525
>     would then need its own binding instead of a trivial-devices entry.
> 
> I lean towards a).
> 
Either a) or c), your call. We already have a vout-voltage-divider
property, but it looks like that won't work here (it sounds like only
the limit is affected ?), so something new/similar would be required.

Thanks,
Guenter

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

end of thread, other threads:[~2026-10-20 15:27 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-09  0:56 [PATCH 0/3] hwmon: (pmbus/fs1412) Add TDK FS1412 support Abdurrahman Hussain
2026-10-09  0:56 ` [PATCH 1/3] dt-bindings: vendor-prefixes: Add TDK Corporation Abdurrahman Hussain
2026-10-09 10:47   ` Krzysztof Kozlowski
2026-10-09  0:56 ` [PATCH 2/3] dt-bindings: trivial-devices: Add TDK FS1412 Abdurrahman Hussain
2026-10-09 10:47   ` Krzysztof Kozlowski
2026-10-09  0:56 ` [PATCH 3/3] hwmon: (pmbus/fs1412) Add TDK FS1412 driver Abdurrahman Hussain
2026-10-19 20:25   ` Guenter Roeck
2026-10-20  7:31     ` Abdurrahman Hussain
2026-10-20 15:27       ` Guenter Roeck

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®