]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
hwmon: (pmbus/xdp720) Add support for efuse xdp730
authorAshish Yadav <ashish.yadav@infineon.com>
Tue, 9 Jun 2026 07:22:30 +0000 (12:52 +0530)
committerGuenter Roeck <linux@roeck-us.net>
Tue, 9 Jun 2026 15:23:18 +0000 (08:23 -0700)
Adds support for the Infineon XDP730 Digital eFuse Controller by
updating the existing XDP720 driver.

Signed-off-by: Ashish Yadav <ashish.yadav@infineon.com>
Link: https://lore.kernel.org/r/20260609072231.15486-3-Ashish.Yadav@infineon.com
[groeck: Fixed conflicts in xdp720_id declaration]
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
drivers/hwmon/pmbus/Kconfig
drivers/hwmon/pmbus/xdp720.c

index f330dc3f21fe5f309554f3fbf6dae95c7c78f730..c8cda160b5f8e15718fb0e9161e61a3d633de364 100644 (file)
@@ -780,7 +780,7 @@ config SENSORS_XDP720
        tristate "Infineon XDP720 family"
        help
          If you say yes here you get hardware monitoring support for Infineon
-         XDP720.
+         XDP720 and XDP730 Digital eFuse Controllers.
 
          This driver can also be built as a module. If so, the module will
          be called xdp720.
index 60491e9217bfb9c1490db945385d85d2f75f646b..88f076e3d15bc4d20768ef5dfce59df7522d07b5 100644 (file)
@@ -1,6 +1,11 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * Hardware monitoring driver for Infineon XDP720 Digital eFuse Controller
+ * Hardware monitoring driver for Infineon XDP720 / XDP730 Digital
+ * eFuse Controllers.
+ *
+ * Both parts share the same PMBus register map and direct-format
+ * coefficients; they differ in the GIMON gain step exposed via
+ * the TELEMETRY_AVG register and in the VDD_VIN pin number.
  *
  * Copyright (c) 2026 Infineon Technologies. All rights reserved.
  */
  */
 #define XDP720_DEFAULT_RIMON 2000000000 /* 2k ohm */
 #define XDP720_TELEMETRY_AVG 0xE9
+#define XDP720_TELEMETRY_AVG_GIMON BIT(10) /* high/low GIMON select */
+
+/* Chip identifiers carried in OF match-data and i2c_device_id->driver_data. */
+enum xdp720_chip_id {
+       CHIP_XDP720 = 0,
+       CHIP_XDP730,
+};
+
+struct xdp720_data {
+       enum xdp720_chip_id      id;
+       struct pmbus_driver_info info;
+};
 
 static struct pmbus_driver_info xdp720_info = {
        .pages = 1,
@@ -56,16 +73,18 @@ static struct pmbus_driver_info xdp720_info = {
 
 static int xdp720_probe(struct i2c_client *client)
 {
-       struct pmbus_driver_info *info;
+       struct xdp720_data *data;
        int ret;
        u32 rimon;
        int gimon;
 
-       info = devm_kmemdup(&client->dev, &xdp720_info, sizeof(*info),
-                           GFP_KERNEL);
-       if (!info)
+       data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+       if (!data)
                return -ENOMEM;
 
+       data->id = (enum xdp720_chip_id)(uintptr_t)i2c_get_match_data(client);
+       data->info = xdp720_info;
+
        ret = devm_regulator_get_enable(&client->dev, "vdd-vin");
        if (ret)
                return dev_err_probe(&client->dev, ret,
@@ -77,36 +96,47 @@ static int xdp720_probe(struct i2c_client *client)
                return ret;
        }
 
-       ret >>= 10; /* 10th bit of TELEMETRY_AVG REG for GIMON Value */
-       ret &= GENMASK(0, 0);
-       if (ret == 1)
-               gimon = 18200; /* output gain 18.2 microA/A */
-       else
-               gimon = 9100; /* output gain 9.1 microA/A */
+       /* Bit 10 of TELEMETRY_AVG selects the GIMON gain step in microA/A */
+       switch (data->id) {
+       case CHIP_XDP720:
+               gimon = (ret & XDP720_TELEMETRY_AVG_GIMON) ? 18200 : 9100;
+               dev_info(&client->dev, "Initialised XDP720 instance\n");
+               break;
+       case CHIP_XDP730:
+               gimon = (ret & XDP720_TELEMETRY_AVG_GIMON) ? 20000 : 10000;
+               dev_info(&client->dev, "Initialised XDP730 instance\n");
+               break;
+       default:
+               return -EINVAL;
+       }
 
-       if (of_property_read_u32(client->dev.of_node,
-                                "infineon,rimon-micro-ohms", &rimon))
-               rimon = XDP720_DEFAULT_RIMON; /* Default if not set via DT */
+       if (device_property_read_u32(&client->dev,
+                                    "infineon,rimon-micro-ohms", &rimon))
+               rimon = XDP720_DEFAULT_RIMON;   /* Default if not in FW */
        if (rimon == 0)
                return -EINVAL;
 
        /* Adapt the current and power scale for each instance */
-       info->m[PSC_CURRENT_OUT] = DIV64_U64_ROUND_CLOSEST((u64)
-               info->m[PSC_CURRENT_OUT] * rimon * gimon, 1000000000000ULL);
-       info->m[PSC_POWER] = DIV64_U64_ROUND_CLOSEST((u64)
-               info->m[PSC_POWER] * rimon * gimon, 1000000000000000ULL);
-
-       return pmbus_do_probe(client, info);
+       data->info.m[PSC_CURRENT_OUT] = DIV64_U64_ROUND_CLOSEST((u64)
+               data->info.m[PSC_CURRENT_OUT] * rimon * gimon,
+               1000000000000ULL);
+       data->info.m[PSC_POWER] = DIV64_U64_ROUND_CLOSEST((u64)
+               data->info.m[PSC_POWER] * rimon * gimon,
+               1000000000000000ULL);
+
+       return pmbus_do_probe(client, &data->info);
 }
 
 static const struct of_device_id xdp720_of_match[] = {
-       { .compatible = "infineon,xdp720" },
+       { .compatible = "infineon,xdp720", .data = (void *)CHIP_XDP720 },
+       { .compatible = "infineon,xdp730", .data = (void *)CHIP_XDP730 },
        {}
 };
 MODULE_DEVICE_TABLE(of, xdp720_of_match);
 
 static const struct i2c_device_id xdp720_id[] = {
-       { .name = "xdp720" },
+       { .name = "xdp720", .driver_data = CHIP_XDP720 },
+       { .name = "xdp730", .driver_data = CHIP_XDP730 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, xdp720_id);
@@ -123,6 +153,6 @@ static struct i2c_driver xdp720_driver = {
 module_i2c_driver(xdp720_driver);
 
 MODULE_AUTHOR("Ashish Yadav <ashish.yadav@infineon.com>");
-MODULE_DESCRIPTION("PMBus driver for Infineon XDP720 Digital eFuse Controller");
+MODULE_DESCRIPTION("PMBus driver for Infineon XDP720/XDP730 Digital eFuse Controllers");
 MODULE_LICENSE("GPL");
 MODULE_IMPORT_NS("PMBUS");