mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v3 0/2] Add driver for Infineon TDA38740/TDA38725
@ 2026-09-10  6:18 Colin Huang
  2026-09-10  6:18 ` [PATCH v3 1/2] dt-bindings: hwmon: pmbus: Add Infineon tda38740 and tda38725 Colin Huang
  2026-09-10  6:18 ` [PATCH v3 2/2] hwmon: (pmbus/tda38740) Add driver for Infineon TDA38740/TDA38725 Colin Huang
  0 siblings, 2 replies; 6+ messages in thread
From: Colin Huang @ 2026-09-10  6:18 UTC (permalink / raw)
  To: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: linux-hwmon, devicetree, linux-kernel, colin.huang2, Colin Huang

Signed-off-by: Colin Huang <u8813345@gmail.com>
---
Changes in v3:
- Clarify that TDA38725 and TDA38740 share the same PMBus programming
  model, with infineon,tda38740 as the preferred compatible string and
  infineon,tda38725 as a compatibility alias.
- The optional VOUT scaling property with a documented default
  value of 1.0 to support devices that require output-voltage scaling.
- Update the driver to apply the scaling for READ_VOUT.
- Link to v2: https://lore.kernel.org/r/20260907-add-tda38740-and-tda38725-v2-0-1d051d63aa01@gmail.com

Changes in v2:
- Use standard http:// URIs for $id and $schema
- Add maintainers section.
- Use C99 named initializers.
- Link to v1: https://lore.kernel.org/r/20260907-add-tda38740-and-tda38725-v1-0-e2db1b2566b1@gmail.com

---
Colin Huang (2):
      dt-bindings: hwmon: pmbus: Add Infineon tda38740 and tda38725
      hwmon: (pmbus/tda38740) Add driver for Infineon TDA38740/TDA38725

 .../bindings/hwmon/pmbus/infineon,tda38740.yaml    |  87 ++++++++++++
 drivers/hwmon/pmbus/Kconfig                        |   9 ++
 drivers/hwmon/pmbus/Makefile                       |   1 +
 drivers/hwmon/pmbus/tda38740.c                     | 150 +++++++++++++++++++++
 4 files changed, 247 insertions(+)
---
base-commit: ba08432bda66a7889d8f3d1581dabf10f59b25eb
change-id: 20260903-add-tda38740-and-tda38725-32bbb097d41e

Best regards,
-- 
Colin Huang <u8813345@gmail.com>


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

* [PATCH v3 1/2] dt-bindings: hwmon: pmbus: Add Infineon tda38740 and tda38725
  2026-09-10  6:18 [PATCH v3 0/2] Add driver for Infineon TDA38740/TDA38725 Colin Huang
@ 2026-09-10  6:18 ` Colin Huang
  2026-09-10 11:24   ` Conor Dooley
  2026-09-10  6:18 ` [PATCH v3 2/2] hwmon: (pmbus/tda38740) Add driver for Infineon TDA38740/TDA38725 Colin Huang
  1 sibling, 1 reply; 6+ messages in thread
From: Colin Huang @ 2026-09-10  6:18 UTC (permalink / raw)
  To: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: linux-hwmon, devicetree, linux-kernel, colin.huang2, Colin Huang

From: Colin Huang <u8813345@gmail.com>

Add devicetree bindings for the Infineon TDA38740 and TDA38725
single-voltage synchronous buck regulators with PMBus interface.

Signed-off-by: Colin Huang <u8813345@gmail.com>
---
 .../bindings/hwmon/pmbus/infineon,tda38740.yaml    | 87 ++++++++++++++++++++++
 1 file changed, 87 insertions(+)

diff --git a/Documentation/devicetree/bindings/hwmon/pmbus/infineon,tda38740.yaml b/Documentation/devicetree/bindings/hwmon/pmbus/infineon,tda38740.yaml
new file mode 100644
index 000000000000..28e6ff9d9d9c
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/pmbus/infineon,tda38740.yaml
@@ -0,0 +1,87 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+
+$id: http://devicetree.org/schemas/hwmon/pmbus/infineon,tda38740.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Infineon TDA38740 and TDA38725 PMBus Synchronous Buck Regulator
+
+maintainers:
+  - Colin Huang <u8813345@gmail.com>
+
+description: |
+  The Infineon TDA38740/TDA38725 is a 40A/25A single-voltage synchronous
+  buck regulator with a PMBus interface designed for industrial use.
+
+  Datasheet:
+  https://www.infineon.com/row/public/documents/24/49/infineon-tda38740-tda38725-datasheet-en.pdf
+
+properties:
+  compatible:
+    oneOf:
+      - const: infineon,tda38740
+      - const: infineon,tda38725
+    description: |
+      The Infineon TDA38740 and TDA38725 share the same PMBus programming
+      model. Use infineon,tda38740 as the preferred compatible string;
+      infineon,tda38725 is kept as a compatibility alias.
+
+  reg:
+    maxItems: 1
+
+  infineon,vout-scale-micro:
+    description: |
+      Scaling factor applied to READ_VOUT telemetry.
+
+      TDA38740/25 pin strap parts are available in two flavors of
+      VOUT_SCALE_LOOP: 1:1 and 1:2.
+
+      For the 1:1 VOUT_SCALE_LOOP version, output voltage sense pins are
+      directly connected to the output, and no resistor divider is used.
+
+      For the 1:2 version, a resistor divider is typically used (for example,
+      499 ohms for both top and bottom resistors).
+
+      In some designs, users intentionally modify the feedback divider ratio
+      to obtain an output voltage different from the internally configured
+      VBOOT or VOUT value.
+
+      In such cases, the device telemetry (READ_VOUT) continues to report
+      the internally programmed voltage and does not reflect the actual
+      externally adjusted output voltage.
+
+      This property provides a multiplier to scale the reported telemetry
+      value so that the monitoring system reflects the actual output voltage.
+
+      The value shall be expressed in micro units where 1,000,000 represents
+      a scaling factor of 1.0.
+
+      Example:
+        If actual Vout = 0.75V and READ_VOUT reports 0.7V:
+        scaling factor = 0.75 / 0.7 = 1.071
+        value = 1071000
+    $ref: /schemas/types.yaml#/definitions/uint32
+    default: 1000000
+    minimum: 100000
+    maximum: 2000000
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        sensor@40 {
+            compatible = "infineon,tda38740";
+            reg = <0x40>;
+            infineon,vout-scale-micro = <1071000>;
+        };
+    };
+

-- 
2.34.1


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

* [PATCH v3 2/2] hwmon: (pmbus/tda38740) Add driver for Infineon TDA38740/TDA38725
  2026-09-10  6:18 [PATCH v3 0/2] Add driver for Infineon TDA38740/TDA38725 Colin Huang
  2026-09-10  6:18 ` [PATCH v3 1/2] dt-bindings: hwmon: pmbus: Add Infineon tda38740 and tda38725 Colin Huang
@ 2026-09-10  6:18 ` Colin Huang
  2026-09-10  8:55   ` Guenter Roeck
  1 sibling, 1 reply; 6+ messages in thread
From: Colin Huang @ 2026-09-10  6:18 UTC (permalink / raw)
  To: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: linux-hwmon, devicetree, linux-kernel, colin.huang2, Colin Huang

From: Colin Huang <u8813345@gmail.com>

Add a PMBus driver for Infineon TDA38740 and TDA38725
single-voltage synchronous buck regulators.

Signed-off-by: Colin Huang <u8813345@gmail.com>
---
 drivers/hwmon/pmbus/Kconfig    |   9 +++
 drivers/hwmon/pmbus/Makefile   |   1 +
 drivers/hwmon/pmbus/tda38740.c | 150 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 160 insertions(+)

diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
index bcfdc4ce4c10..e4ca80dd0574 100644
--- a/drivers/hwmon/pmbus/Kconfig
+++ b/drivers/hwmon/pmbus/Kconfig
@@ -763,6 +763,15 @@ config SENSORS_TDA38640_REGULATOR
 	  If you say yes here you get regulator support for Infineon
 	  TDA38640 as regulator.
 
+config SENSORS_TDA38740
+	tristate "Infineon TDA38725/TDA38740"
+	help
+	  If you say yes here you get hardware monitoring support for Infineon
+	  TDA38725 and TDA38740.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called tda38740.
+
 config SENSORS_TPS25990
 	tristate "TI TPS25990"
 	help
diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile
index e288fe72a437..eb06d47816fd 100644
--- a/drivers/hwmon/pmbus/Makefile
+++ b/drivers/hwmon/pmbus/Makefile
@@ -70,6 +70,7 @@ obj-$(CONFIG_SENSORS_STEF48H28)	+= stef48h28.o
 obj-$(CONFIG_SENSORS_SQ24860)	+= sq24860.o
 obj-$(CONFIG_SENSORS_STPDDC60)	+= stpddc60.o
 obj-$(CONFIG_SENSORS_TDA38640)	+= tda38640.o
+obj-$(CONFIG_SENSORS_TDA38740)	+= tda38740.o
 obj-$(CONFIG_SENSORS_TPS25990)	+= tps25990.o
 obj-$(CONFIG_SENSORS_TPS40422)	+= tps40422.o
 obj-$(CONFIG_SENSORS_TPS53679)	+= tps53679.o
diff --git a/drivers/hwmon/pmbus/tda38740.c b/drivers/hwmon/pmbus/tda38740.c
new file mode 100644
index 000000000000..df5173d8da0c
--- /dev/null
+++ b/drivers/hwmon/pmbus/tda38740.c
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Hardware monitoring driver for Infineon TDA38725/TDA38740
+ *
+ * Copyright (c) 2023 9elements GmbH
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include "pmbus.h"
+
+#define TDA38740_VOUT_SCALE_DEFAULT_MICRO	1000000
+#define TDA38740_VOUT_SCALE_MIN_MICRO		100000
+#define TDA38740_VOUT_SCALE_MAX_MICRO		2000000
+
+struct tda38740_data {
+	struct pmbus_driver_info info;
+	u32 vout_scale_micro;
+};
+
+static int tda38740_read_word_data(struct i2c_client *client, int page,
+				   int phase, int reg)
+{
+	const struct tda38740_data *data;
+	int ret;
+	u64 scaled;
+
+	if (reg != PMBUS_READ_VOUT)
+		return -ENODATA;
+
+	ret = pmbus_read_word_data(client, page, phase, reg);
+	if (ret < 0)
+		return ret;
+
+	data = container_of(pmbus_get_driver_info(client), struct tda38740_data,
+			    info);
+
+	scaled = (u64)ret * data->vout_scale_micro;
+	scaled = DIV_ROUND_CLOSEST_ULL(scaled,
+				       TDA38740_VOUT_SCALE_DEFAULT_MICRO);
+
+	return clamp_val(scaled, 0, U16_MAX);
+}
+
+/*
+ * TDA38725/TDA38740 only support Linear format for VOUT related commands,
+ * with exponents in the range of -8 to -12 (see datasheet VOUT_MODE
+ * description). Direct format is not supported by this device.
+ */
+static int tda38740_identify(struct i2c_client *client,
+			     struct pmbus_driver_info *info)
+{
+	int vout_mode;
+
+	vout_mode = pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE);
+	if (vout_mode < 0 || vout_mode == 0xff)
+		return vout_mode < 0 ? vout_mode : -ENODEV;
+
+	if ((vout_mode >> 5) != 0)
+		return -ENODEV;
+
+	info->format[PSC_VOLTAGE_OUT] = linear;
+
+	return 0;
+}
+
+static struct pmbus_driver_info tda38740_info = {
+	.pages = 1,
+	.format[PSC_VOLTAGE_IN] = linear,
+	.format[PSC_CURRENT_OUT] = linear,
+	.format[PSC_CURRENT_IN] = linear,
+	.format[PSC_POWER] = linear,
+	.format[PSC_TEMPERATURE] = linear,
+	.func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
+	    | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP
+	    | PMBUS_HAVE_IIN
+	    | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+	    | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
+	    | PMBUS_HAVE_POUT | PMBUS_HAVE_PIN,
+	.identify = tda38740_identify,
+};
+
+static int tda38740_probe(struct i2c_client *client)
+{
+	struct device *dev = &client->dev;
+	struct tda38740_data *data;
+	const char *propname;
+	u32 vout_scale_micro;
+	int ret;
+
+	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	propname = "infineon,vout-scale-micro";
+	if (device_property_present(dev, propname)) {
+		ret = device_property_read_u32(dev, propname, &vout_scale_micro);
+		if (ret)
+			return dev_err_probe(dev, ret,
+					     "%s property read fail.\n",
+					     propname);
+	} else {
+		vout_scale_micro = TDA38740_VOUT_SCALE_DEFAULT_MICRO;
+	}
+
+	if (vout_scale_micro < TDA38740_VOUT_SCALE_MIN_MICRO ||
+	    vout_scale_micro > TDA38740_VOUT_SCALE_MAX_MICRO)
+		return -EINVAL;
+
+	memcpy(&data->info, &tda38740_info, sizeof(tda38740_info));
+	data->vout_scale_micro = vout_scale_micro;
+	data->info.read_word_data = tda38740_read_word_data;
+
+	return pmbus_do_probe(client, &data->info);
+}
+
+static const struct i2c_device_id tda38740_id[] = {
+	{ .name = "tda38725"},
+	{ .name = "tda38740"},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, tda38740_id);
+
+static const struct of_device_id __maybe_unused tda38740_of_match[] = {
+	{ .compatible = "infineon,tda38725"},
+	{ .compatible = "infineon,tda38740"},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, tda38740_of_match);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver tda38740_driver = {
+	.driver = {
+		.name = "tda38740",
+		.of_match_table = of_match_ptr(tda38740_of_match),
+	},
+	.probe = tda38740_probe,
+	.id_table = tda38740_id,
+};
+
+module_i2c_driver(tda38740_driver);
+
+MODULE_DESCRIPTION("PMBus driver for Infineon TDA38725/TDA38740");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("PMBUS");

-- 
2.34.1


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

* Re: [PATCH v3 2/2] hwmon: (pmbus/tda38740) Add driver for Infineon TDA38740/TDA38725
  2026-09-10  6:18 ` [PATCH v3 2/2] hwmon: (pmbus/tda38740) Add driver for Infineon TDA38740/TDA38725 Colin Huang
@ 2026-09-10  8:55   ` Guenter Roeck
  2026-09-10 12:35     ` Colin Huang
  0 siblings, 1 reply; 6+ messages in thread
From: Guenter Roeck @ 2026-09-10  8:55 UTC (permalink / raw)
  To: Colin Huang, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: linux-hwmon, devicetree, linux-kernel, Colin Huang

On 9/9/26 23:18, Colin Huang wrote:
> From: Colin Huang <u8813345@gmail.com>
> 
> Add a PMBus driver for Infineon TDA38740 and TDA38725
> single-voltage synchronous buck regulators.
> 
> Signed-off-by: Colin Huang <u8813345@gmail.com>
> ---
>   drivers/hwmon/pmbus/Kconfig    |   9 +++
>   drivers/hwmon/pmbus/Makefile   |   1 +
>   drivers/hwmon/pmbus/tda38740.c | 150 +++++++++++++++++++++++++++++++++++++++++

Documentation is missing.

>   3 files changed, 160 insertions(+)
> 
> diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
> index bcfdc4ce4c10..e4ca80dd0574 100644
> --- a/drivers/hwmon/pmbus/Kconfig
> +++ b/drivers/hwmon/pmbus/Kconfig
> @@ -763,6 +763,15 @@ config SENSORS_TDA38640_REGULATOR
>   	  If you say yes here you get regulator support for Infineon
>   	  TDA38640 as regulator.
>   
> +config SENSORS_TDA38740
> +	tristate "Infineon TDA38725/TDA38740"
> +	help
> +	  If you say yes here you get hardware monitoring support for Infineon
> +	  TDA38725 and TDA38740.
> +
> +	  This driver can also be built as a module. If so, the module will
> +	  be called tda38740.
> +
>   config SENSORS_TPS25990
>   	tristate "TI TPS25990"
>   	help
> diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile
> index e288fe72a437..eb06d47816fd 100644
> --- a/drivers/hwmon/pmbus/Makefile
> +++ b/drivers/hwmon/pmbus/Makefile
> @@ -70,6 +70,7 @@ obj-$(CONFIG_SENSORS_STEF48H28)	+= stef48h28.o
>   obj-$(CONFIG_SENSORS_SQ24860)	+= sq24860.o
>   obj-$(CONFIG_SENSORS_STPDDC60)	+= stpddc60.o
>   obj-$(CONFIG_SENSORS_TDA38640)	+= tda38640.o
> +obj-$(CONFIG_SENSORS_TDA38740)	+= tda38740.o
>   obj-$(CONFIG_SENSORS_TPS25990)	+= tps25990.o
>   obj-$(CONFIG_SENSORS_TPS40422)	+= tps40422.o
>   obj-$(CONFIG_SENSORS_TPS53679)	+= tps53679.o
> diff --git a/drivers/hwmon/pmbus/tda38740.c b/drivers/hwmon/pmbus/tda38740.c
> new file mode 100644
> index 000000000000..df5173d8da0c
> --- /dev/null
> +++ b/drivers/hwmon/pmbus/tda38740.c
> @@ -0,0 +1,150 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Hardware monitoring driver for Infineon TDA38725/TDA38740
> + *
> + * Copyright (c) 2023 9elements GmbH
> + *
> + */
> +
> +#include <linux/err.h>
> +#include <linux/i2c.h>
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/property.h>
> +#include "pmbus.h"
> +
> +#define TDA38740_VOUT_SCALE_DEFAULT_MICRO	1000000
> +#define TDA38740_VOUT_SCALE_MIN_MICRO		100000
> +#define TDA38740_VOUT_SCALE_MAX_MICRO		2000000
> +
> +struct tda38740_data {
> +	struct pmbus_driver_info info;
> +	u32 vout_scale_micro;
> +};
> +
> +static int tda38740_read_word_data(struct i2c_client *client, int page,
> +				   int phase, int reg)
> +{
> +	const struct tda38740_data *data;
> +	int ret;
> +	u64 scaled;
> +
> +	if (reg != PMBUS_READ_VOUT)
> +		return -ENODATA;
> +
> +	ret = pmbus_read_word_data(client, page, phase, reg);
> +	if (ret < 0)
> +		return ret;
> +
> +	data = container_of(pmbus_get_driver_info(client), struct tda38740_data,
> +			    info);
> +
> +	scaled = (u64)ret * data->vout_scale_micro;
> +	scaled = DIV_ROUND_CLOSEST_ULL(scaled,
> +				       TDA38740_VOUT_SCALE_DEFAULT_MICRO);
> +

The chip supports VOUT_SCALE_LOOP, which should be used for any VOUT scaling.
VOUT values should not be manipulated manually.

Also, Sashiko is correct in complaining about not scaling other VOUT
related commands, both on the read and write side. The chip _does_ support
limit commands.

> +	return clamp_val(scaled, 0, U16_MAX);
> +}
> +
> +/*
> + * TDA38725/TDA38740 only support Linear format for VOUT related commands,
> + * with exponents in the range of -8 to -12 (see datasheet VOUT_MODE
> + * description). Direct format is not supported by this device.
> + */
> +static int tda38740_identify(struct i2c_client *client,
> +			     struct pmbus_driver_info *info)
> +{
> +	int vout_mode;
> +
> +	vout_mode = pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE);
> +	if (vout_mode < 0 || vout_mode == 0xff)
> +		return vout_mode < 0 ? vout_mode : -ENODEV;
> +
> +	if ((vout_mode >> 5) != 0)
> +		return -ENODEV;
> +
> +	info->format[PSC_VOLTAGE_OUT] = linear;
> +
> +	return 0;
> +}
> +
> +static struct pmbus_driver_info tda38740_info = {
> +	.pages = 1,

The chips support the PAGE command, described as "Allows access
of each loop via paging". I don't know what exactly that refers to,
but it does look like it supports multiple pages.
> +	.format[PSC_VOLTAGE_IN] = linear,
> +	.format[PSC_CURRENT_OUT] = linear,
> +	.format[PSC_CURRENT_IN] = linear,
> +	.format[PSC_POWER] = linear,
> +	.format[PSC_TEMPERATURE] = linear,
> +	.func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
> +	    | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP
> +	    | PMBUS_HAVE_IIN
> +	    | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
> +	    | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
> +	    | PMBUS_HAVE_POUT | PMBUS_HAVE_PIN,
> +	.identify = tda38740_identify,
> +};
> +
> +static int tda38740_probe(struct i2c_client *client)
> +{
> +	struct device *dev = &client->dev;
> +	struct tda38740_data *data;
> +	const char *propname;
> +	u32 vout_scale_micro;
> +	int ret;
> +
> +	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +
> +	propname = "infineon,vout-scale-micro";
> +	if (device_property_present(dev, propname)) {
> +		ret = device_property_read_u32(dev, propname, &vout_scale_micro);
> +		if (ret)
> +			return dev_err_probe(dev, ret,
> +					     "%s property read fail.\n",
> +					     propname);
> +	} else {
> +		vout_scale_micro = TDA38740_VOUT_SCALE_DEFAULT_MICRO;
> +	}
> +
> +	if (vout_scale_micro < TDA38740_VOUT_SCALE_MIN_MICRO ||
> +	    vout_scale_micro > TDA38740_VOUT_SCALE_MAX_MICRO)
> +		return -EINVAL;
> +
> +	memcpy(&data->info, &tda38740_info, sizeof(tda38740_info));
> +	data->vout_scale_micro = vout_scale_micro;
> +	data->info.read_word_data = tda38740_read_word_data;
> +
> +	return pmbus_do_probe(client, &data->info);
> +}
> +
> +static const struct i2c_device_id tda38740_id[] = {
> +	{ .name = "tda38725"},
> +	{ .name = "tda38740"},
> +	{}
> +};
> +MODULE_DEVICE_TABLE(i2c, tda38740_id);
> +
> +static const struct of_device_id __maybe_unused tda38740_of_match[] = {
> +	{ .compatible = "infineon,tda38725"},
> +	{ .compatible = "infineon,tda38740"},
> +	{ },

No "," here.

> +};
> +MODULE_DEVICE_TABLE(of, tda38740_of_match);
> +
> +/* This is the driver that will be inserted */

Pointless comment.

> +static struct i2c_driver tda38740_driver = {
> +	.driver = {
> +		.name = "tda38740",
> +		.of_match_table = of_match_ptr(tda38740_of_match),
> +	},
> +	.probe = tda38740_probe,
> +	.id_table = tda38740_id,
> +};
> +
> +module_i2c_driver(tda38740_driver);
> +
> +MODULE_DESCRIPTION("PMBus driver for Infineon TDA38725/TDA38740");
> +MODULE_LICENSE("GPL");
> +MODULE_IMPORT_NS("PMBUS");
> 


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

* Re: [PATCH v3 1/2] dt-bindings: hwmon: pmbus: Add Infineon tda38740 and tda38725
  2026-09-10  6:18 ` [PATCH v3 1/2] dt-bindings: hwmon: pmbus: Add Infineon tda38740 and tda38725 Colin Huang
@ 2026-09-10 11:24   ` Conor Dooley
  0 siblings, 0 replies; 6+ messages in thread
From: Conor Dooley @ 2026-09-10 11:24 UTC (permalink / raw)
  To: Colin Huang
  Cc: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	linux-hwmon, devicetree, linux-kernel, Colin Huang

[-- Attachment #1: Type: text/plain, Size: 3999 bytes --]

On Thu, Sep 10, 2026 at 02:18:55PM +0800, Colin Huang wrote:
> From: Colin Huang <u8813345@gmail.com>
> 
> Add devicetree bindings for the Infineon TDA38740 and TDA38725
> single-voltage synchronous buck regulators with PMBus interface.
> 
> Signed-off-by: Colin Huang <u8813345@gmail.com>
> ---
>  .../bindings/hwmon/pmbus/infineon,tda38740.yaml    | 87 ++++++++++++++++++++++
>  1 file changed, 87 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/hwmon/pmbus/infineon,tda38740.yaml b/Documentation/devicetree/bindings/hwmon/pmbus/infineon,tda38740.yaml
> new file mode 100644
> index 000000000000..28e6ff9d9d9c
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/hwmon/pmbus/infineon,tda38740.yaml
> @@ -0,0 +1,87 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +
> +$id: http://devicetree.org/schemas/hwmon/pmbus/infineon,tda38740.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Infineon TDA38740 and TDA38725 PMBus Synchronous Buck Regulator
> +
> +maintainers:
> +  - Colin Huang <u8813345@gmail.com>
> +
> +description: |
> +  The Infineon TDA38740/TDA38725 is a 40A/25A single-voltage synchronous
> +  buck regulator with a PMBus interface designed for industrial use.
> +
> +  Datasheet:
> +  https://www.infineon.com/row/public/documents/24/49/infineon-tda38740-tda38725-datasheet-en.pdf
> +
> +properties:
> +  compatible:
> +    oneOf:
> +      - const: infineon,tda38740
> +      - const: infineon,tda38725
> +    description: |
> +      The Infineon TDA38740 and TDA38725 share the same PMBus programming
> +      model. Use infineon,tda38740 as the preferred compatible string;
> +      infineon,tda38725 is kept as a compatibility alias.

This is not how this should be done. Instead, tda38725 should list
tda38740 as a fallback compatible. Take a look at the example schema for
how this can be done.
Otherwise, this looks okay to me.

pw-bot: changes-requested

Thanks,
Conor.

> +
> +  reg:
> +    maxItems: 1
> +
> +  infineon,vout-scale-micro:
> +    description: |
> +      Scaling factor applied to READ_VOUT telemetry.
> +
> +      TDA38740/25 pin strap parts are available in two flavors of
> +      VOUT_SCALE_LOOP: 1:1 and 1:2.
> +
> +      For the 1:1 VOUT_SCALE_LOOP version, output voltage sense pins are
> +      directly connected to the output, and no resistor divider is used.
> +
> +      For the 1:2 version, a resistor divider is typically used (for example,
> +      499 ohms for both top and bottom resistors).
> +
> +      In some designs, users intentionally modify the feedback divider ratio
> +      to obtain an output voltage different from the internally configured
> +      VBOOT or VOUT value.
> +
> +      In such cases, the device telemetry (READ_VOUT) continues to report
> +      the internally programmed voltage and does not reflect the actual
> +      externally adjusted output voltage.
> +
> +      This property provides a multiplier to scale the reported telemetry
> +      value so that the monitoring system reflects the actual output voltage.
> +
> +      The value shall be expressed in micro units where 1,000,000 represents
> +      a scaling factor of 1.0.
> +
> +      Example:
> +        If actual Vout = 0.75V and READ_VOUT reports 0.7V:
> +        scaling factor = 0.75 / 0.7 = 1.071
> +        value = 1071000
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    default: 1000000
> +    minimum: 100000
> +    maximum: 2000000
> +
> +required:
> +  - compatible
> +  - reg
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    i2c {
> +        #address-cells = <1>;
> +        #size-cells = <0>;
> +
> +        sensor@40 {
> +            compatible = "infineon,tda38740";
> +            reg = <0x40>;
> +            infineon,vout-scale-micro = <1071000>;
> +        };
> +    };
> +
> 
> -- 
> 2.34.1
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

* Re: [PATCH v3 2/2] hwmon: (pmbus/tda38740) Add driver for Infineon TDA38740/TDA38725
  2026-09-10  8:55   ` Guenter Roeck
@ 2026-09-10 12:35     ` Colin Huang
  0 siblings, 0 replies; 6+ messages in thread
From: Colin Huang @ 2026-09-10 12:35 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Colin Huang, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	linux-hwmon, devicetree, linux-kernel

Guenter Roeck <linux@roeck-us.net> 於 2026年9月10日週四 下午4:55寫道:
>
> On 9/9/26 23:18, Colin Huang wrote:
> > From: Colin Huang <u8813345@gmail.com>
> >
> > Add a PMBus driver for Infineon TDA38740 and TDA38725
> > single-voltage synchronous buck regulators.
> >
> > Signed-off-by: Colin Huang <u8813345@gmail.com>
> > ---
> >   drivers/hwmon/pmbus/Kconfig    |   9 +++
> >   drivers/hwmon/pmbus/Makefile   |   1 +
> >   drivers/hwmon/pmbus/tda38740.c | 150 +++++++++++++++++++++++++++++++++++++++++
>
> Documentation is missing.
>
Hi Guenter,

Thanks for review.

I will prepare Documentation/hwmon/tda38740.rst file for this driver.

> >   3 files changed, 160 insertions(+)
> >
> > diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
> > index bcfdc4ce4c10..e4ca80dd0574 100644
> > --- a/drivers/hwmon/pmbus/Kconfig
> > +++ b/drivers/hwmon/pmbus/Kconfig
> > @@ -763,6 +763,15 @@ config SENSORS_TDA38640_REGULATOR
> >         If you say yes here you get regulator support for Infineon
> >         TDA38640 as regulator.
> >
> > +config SENSORS_TDA38740
> > +     tristate "Infineon TDA38725/TDA38740"
> > +     help
> > +       If you say yes here you get hardware monitoring support for Infineon
> > +       TDA38725 and TDA38740.
> > +
> > +       This driver can also be built as a module. If so, the module will
> > +       be called tda38740.
> > +
> >   config SENSORS_TPS25990
> >       tristate "TI TPS25990"
> >       help
> > diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile
> > index e288fe72a437..eb06d47816fd 100644
> > --- a/drivers/hwmon/pmbus/Makefile
> > +++ b/drivers/hwmon/pmbus/Makefile
> > @@ -70,6 +70,7 @@ obj-$(CONFIG_SENSORS_STEF48H28)     += stef48h28.o
> >   obj-$(CONFIG_SENSORS_SQ24860)       += sq24860.o
> >   obj-$(CONFIG_SENSORS_STPDDC60)      += stpddc60.o
> >   obj-$(CONFIG_SENSORS_TDA38640)      += tda38640.o
> > +obj-$(CONFIG_SENSORS_TDA38740)       += tda38740.o
> >   obj-$(CONFIG_SENSORS_TPS25990)      += tps25990.o
> >   obj-$(CONFIG_SENSORS_TPS40422)      += tps40422.o
> >   obj-$(CONFIG_SENSORS_TPS53679)      += tps53679.o
> > diff --git a/drivers/hwmon/pmbus/tda38740.c b/drivers/hwmon/pmbus/tda38740.c
> > new file mode 100644
> > index 000000000000..df5173d8da0c
> > --- /dev/null
> > +++ b/drivers/hwmon/pmbus/tda38740.c
> > @@ -0,0 +1,150 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Hardware monitoring driver for Infineon TDA38725/TDA38740
> > + *
> > + * Copyright (c) 2023 9elements GmbH
> > + *
> > + */
> > +
> > +#include <linux/err.h>
> > +#include <linux/i2c.h>
> > +#include <linux/init.h>
> > +#include <linux/kernel.h>
> > +#include <linux/module.h>
> > +#include <linux/property.h>
> > +#include "pmbus.h"
> > +
> > +#define TDA38740_VOUT_SCALE_DEFAULT_MICRO    1000000
> > +#define TDA38740_VOUT_SCALE_MIN_MICRO                100000
> > +#define TDA38740_VOUT_SCALE_MAX_MICRO                2000000
> > +
> > +struct tda38740_data {
> > +     struct pmbus_driver_info info;
> > +     u32 vout_scale_micro;
> > +};
> > +
> > +static int tda38740_read_word_data(struct i2c_client *client, int page,
> > +                                int phase, int reg)
> > +{
> > +     const struct tda38740_data *data;
> > +     int ret;
> > +     u64 scaled;
> > +
> > +     if (reg != PMBUS_READ_VOUT)
> > +             return -ENODATA;
> > +
> > +     ret = pmbus_read_word_data(client, page, phase, reg);
> > +     if (ret < 0)
> > +             return ret;
> > +
> > +     data = container_of(pmbus_get_driver_info(client), struct tda38740_data,
> > +                         info);
> > +
> > +     scaled = (u64)ret * data->vout_scale_micro;
> > +     scaled = DIV_ROUND_CLOSEST_ULL(scaled,
> > +                                    TDA38740_VOUT_SCALE_DEFAULT_MICRO);
> > +
>
> The chip supports VOUT_SCALE_LOOP, which should be used for any VOUT scaling.
> VOUT values should not be manipulated manually.
>
> Also, Sashiko is correct in complaining about not scaling other VOUT
> related commands, both on the read and write side. The chip _does_ support
> limit commands.

I will remove the code related vout_scale_micro  support.

>
> > +     return clamp_val(scaled, 0, U16_MAX);
> > +}
> > +
> > +/*
> > + * TDA38725/TDA38740 only support Linear format for VOUT related commands,
> > + * with exponents in the range of -8 to -12 (see datasheet VOUT_MODE
> > + * description). Direct format is not supported by this device.
> > + */
> > +static int tda38740_identify(struct i2c_client *client,
> > +                          struct pmbus_driver_info *info)
> > +{
> > +     int vout_mode;
> > +
> > +     vout_mode = pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE);
> > +     if (vout_mode < 0 || vout_mode == 0xff)
> > +             return vout_mode < 0 ? vout_mode : -ENODEV;
> > +
> > +     if ((vout_mode >> 5) != 0)
> > +             return -ENODEV;
> > +
> > +     info->format[PSC_VOLTAGE_OUT] = linear;
> > +
> > +     return 0;
> > +}
> > +
> > +static struct pmbus_driver_info tda38740_info = {
> > +     .pages = 1,
>
> The chips support the PAGE command, described as "Allows access
> of each loop via paging". I don't know what exactly that refers to,
> but it does look like it supports multiple pages.


TDA38725/TDA38740 are 40A/25A "Single-voltage" Synchronous Buck Regulator
It's one page.

> > +     .format[PSC_VOLTAGE_IN] = linear,
> > +     .format[PSC_CURRENT_OUT] = linear,
> > +     .format[PSC_CURRENT_IN] = linear,
> > +     .format[PSC_POWER] = linear,
> > +     .format[PSC_TEMPERATURE] = linear,
> > +     .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
> > +         | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP
> > +         | PMBUS_HAVE_IIN
> > +         | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
> > +         | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
> > +         | PMBUS_HAVE_POUT | PMBUS_HAVE_PIN,
> > +     .identify = tda38740_identify,
> > +};
> > +
> > +static int tda38740_probe(struct i2c_client *client)
> > +{
> > +     struct device *dev = &client->dev;
> > +     struct tda38740_data *data;
> > +     const char *propname;
> > +     u32 vout_scale_micro;
> > +     int ret;
> > +
> > +     data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
> > +     if (!data)
> > +             return -ENOMEM;
> > +
> > +     propname = "infineon,vout-scale-micro";
> > +     if (device_property_present(dev, propname)) {
> > +             ret = device_property_read_u32(dev, propname, &vout_scale_micro);
> > +             if (ret)
> > +                     return dev_err_probe(dev, ret,
> > +                                          "%s property read fail.\n",
> > +                                          propname);
> > +     } else {
> > +             vout_scale_micro = TDA38740_VOUT_SCALE_DEFAULT_MICRO;
> > +     }
> > +
> > +     if (vout_scale_micro < TDA38740_VOUT_SCALE_MIN_MICRO ||
> > +         vout_scale_micro > TDA38740_VOUT_SCALE_MAX_MICRO)
> > +             return -EINVAL;
> > +
> > +     memcpy(&data->info, &tda38740_info, sizeof(tda38740_info));
> > +     data->vout_scale_micro = vout_scale_micro;
> > +     data->info.read_word_data = tda38740_read_word_data;
> > +
> > +     return pmbus_do_probe(client, &data->info);
> > +}
> > +
> > +static const struct i2c_device_id tda38740_id[] = {
> > +     { .name = "tda38725"},
> > +     { .name = "tda38740"},
> > +     {}
> > +};
> > +MODULE_DEVICE_TABLE(i2c, tda38740_id);
> > +
> > +static const struct of_device_id __maybe_unused tda38740_of_match[] = {
> > +     { .compatible = "infineon,tda38725"},
> > +     { .compatible = "infineon,tda38740"},
> > +     { },
>
> No "," here.
I will remove it.

>
> > +};
> > +MODULE_DEVICE_TABLE(of, tda38740_of_match);
> > +
> > +/* This is the driver that will be inserted */
>
> Pointless comment.
>
I will remove it.

> > +static struct i2c_driver tda38740_driver = {
> > +     .driver = {
> > +             .name = "tda38740",
> > +             .of_match_table = of_match_ptr(tda38740_of_match),
> > +     },
> > +     .probe = tda38740_probe,
> > +     .id_table = tda38740_id,
> > +};
> > +
> > +module_i2c_driver(tda38740_driver);
> > +
> > +MODULE_DESCRIPTION("PMBus driver for Infineon TDA38725/TDA38740");
> > +MODULE_LICENSE("GPL");
> > +MODULE_IMPORT_NS("PMBUS");
> >
>

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

end of thread, other threads:[~2026-09-10 12:35 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-10  6:18 [PATCH v3 0/2] Add driver for Infineon TDA38740/TDA38725 Colin Huang
2026-09-10  6:18 ` [PATCH v3 1/2] dt-bindings: hwmon: pmbus: Add Infineon tda38740 and tda38725 Colin Huang
2026-09-10 11:24   ` Conor Dooley
2026-09-10  6:18 ` [PATCH v3 2/2] hwmon: (pmbus/tda38740) Add driver for Infineon TDA38740/TDA38725 Colin Huang
2026-09-10  8:55   ` Guenter Roeck
2026-09-10 12:35     ` Colin Huang

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®