blob: 29a95ea08564b1ffba3b361ef14eb9743a457fe1 [file]
From e15ed815cd09fbef8dfa34ec3349d64d1132219c Mon Sep 17 00:00:00 2001
From: Changming Liu <cmliu@google.com>
Date: Tue, 2 Dec 2025 03:31:32 +0000
Subject: [PATCH] add tda38740 driver
this driver essentially is copied from cl/742742120
Signed-off-by: Changming Liu <cmliu@google.com>
---
drivers/hwmon/pmbus/Kconfig | 16 ++
drivers/hwmon/pmbus/Makefile | 1 +
drivers/hwmon/pmbus/tda38740.c | 439 +++++++++++++++++++++++++++++++++
3 files changed, 456 insertions(+)
create mode 100644 drivers/hwmon/pmbus/tda38740.c
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
index 632ac3cbeb05..e6a7daf761e3 100644
--- a/drivers/hwmon/pmbus/Kconfig
+++ b/drivers/hwmon/pmbus/Kconfig
@@ -350,6 +350,22 @@ config SENSORS_STPDDC60
This driver can also be built as a module. If so, the module will
be called stpddc60.
+config SENSORS_TDA38740
+ tristate "Infineon TDA38740"
+ help
+ If you say yes here you get hardware monitoring support for Infineon
+ TDA38740/25 and XDPE1A2G5B/19284C/192C4B.
+
+ This driver can also be built as a module. If so, the module will
+ be called tda38740.
+
+config SENSORS_TDA38740_REGULATOR
+ bool "Regulator support for TDA38740 and compatibles"
+ depends on SENSORS_TDA38740 && REGULATOR
+ help
+ If you say yes here you get regulator support for Infineon
+ TDA38740/25 as regulator.
+
config SENSORS_TPS40422
tristate "TI TPS40422"
help
diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile
index e0026afd59d1..9029ff89daf6 100644
--- a/drivers/hwmon/pmbus/Makefile
+++ b/drivers/hwmon/pmbus/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_SENSORS_PM6764TR) += pm6764tr.o
obj-$(CONFIG_SENSORS_PXE1610) += pxe1610.o
obj-$(CONFIG_SENSORS_Q54SJ108A2) += q54sj108a2.o
obj-$(CONFIG_SENSORS_STPDDC60) += stpddc60.o
+obj-$(CONFIG_SENSORS_TDA38740) += tda38740.o
obj-$(CONFIG_SENSORS_TPS40422) += tps40422.o
obj-$(CONFIG_SENSORS_TPS53679) += tps53679.o
obj-$(CONFIG_SENSORS_TPS546D24) += tps546d24.o
diff --git a/drivers/hwmon/pmbus/tda38740.c b/drivers/hwmon/pmbus/tda38740.c
new file mode 100644
index 000000000000..b5e5ef7339e9
--- /dev/null
+++ b/drivers/hwmon/pmbus/tda38740.c
@@ -0,0 +1,439 @@
+// SPDX-License-Identifier: GPL-2.0+
+/**
+ * Hardware monitoring driver for Infineon Integrated-pol-voltage-regulators or
+ * Digital-Multiphase-Controllers
+ * Driver for TDA38725,TDA38725A,TDA38740,TDA38740A,XDPE1A2G5B,XDPE19284C,XDPE192C4B,XDPE19283B
+ *
+ * Copyright (c) 2024 Infineon Technologies
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of_device.h>
+#include <linux/regulator/driver.h>
+#include "pmbus.h"
+
+#define TDA38725_IC_DEVICE_ID "\x92"
+#define TDA38725A_IC_DEVICE_ID "\xA9"
+#define TDA38740_IC_DEVICE_ID "\x84"
+#define TDA38740A_IC_DEVICE_ID "\xA8"
+#define XDPE1A2G5B_IC_DEVICE_ID "\x01\x9E"
+#define XDPE19284C_IC_DEVICE_ID "\x02\x98"
+#define XDPE192C4B_IC_DEVICE_ID "\x01\x99"
+#define XDPE19283B_IC_DEVICE_ID "\x01\x00"
+
+#define IC_DEV_ID_READ_BLOCK_SIZE 2
+
+static const struct i2c_device_id tda38740_id[];
+
+enum chips {
+ tda38725,
+ tda38725a,
+ tda38740,
+ tda38740a,
+ xdpe1a2g5b,
+ xdpe19284c,
+ xdpe192c4b,
+ xdpe19283b
+};
+
+struct tda38740_data {
+ enum chips id;
+ struct pmbus_driver_info info;
+ u32 vout_multiplier[2];
+};
+
+#define to_tda38740_data(x) container_of(x, struct tda38740_data, info)
+
+static int tda38740_read_word_data(struct i2c_client *client, int page,
+ int phase, int reg)
+{
+ struct device *dev = &client->dev;
+ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+ const struct tda38740_data *data = to_tda38740_data(info);
+ int ret = 0;
+
+ /* Virtual PMBUS Command not supported */
+ if (reg >= PMBUS_VIRT_BASE) {
+ ret = -ENXIO;
+ return ret;
+ }
+
+ dev_dbg(dev, "Read word: page[%d] phase[%d] reg[%d]", page, phase, reg);
+
+ switch (reg) {
+ case PMBUS_READ_VOUT:
+ ret = pmbus_read_word_data(client, page, phase, reg);
+ ret = ((ret * data->vout_multiplier[0])/data->vout_multiplier[1]);
+ break;
+ default:
+ ret = pmbus_read_word_data(client, page, phase, reg);
+ break;
+ }
+
+ dev_dbg(dev, "Word data: [0x%x]", ret);
+
+ return ret;
+}
+
+static const struct regulator_desc __maybe_unused tda38740_reg_desc[] = {
+ PMBUS_REGULATOR("vout", 0),
+};
+
+static struct pmbus_driver_info tda38740_info[] = {
+ [tda38725] = {
+ .pages = 1,
+ .read_word_data = tda38740_read_word_data,
+ .format[PSC_VOLTAGE_IN] = linear,
+ .format[PSC_VOLTAGE_OUT] = 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,
+#if IS_ENABLED(CONFIG_SENSORS_TDA38740_REGULATOR)
+ .num_regulators = 1,
+ .reg_desc = tda38740_reg_desc,
+#endif
+ },
+ [tda38725a] = {
+ .pages = 1,
+ .read_word_data = tda38740_read_word_data,
+ .format[PSC_VOLTAGE_IN] = linear,
+ .format[PSC_VOLTAGE_OUT] = 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,
+#if IS_ENABLED(CONFIG_SENSORS_TDA38740_REGULATOR)
+ .num_regulators = 1,
+ .reg_desc = tda38740_reg_desc,
+#endif
+ },
+ [tda38740] = {
+ .pages = 1,
+ .read_word_data = tda38740_read_word_data,
+ .format[PSC_VOLTAGE_IN] = linear,
+ .format[PSC_VOLTAGE_OUT] = 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,
+#if IS_ENABLED(CONFIG_SENSORS_TDA38740_REGULATOR)
+ .num_regulators = 1,
+ .reg_desc = tda38740_reg_desc,
+#endif
+ },
+ [tda38740a] = {
+ .pages = 1,
+ .read_word_data = tda38740_read_word_data,
+ .format[PSC_VOLTAGE_IN] = linear,
+ .format[PSC_VOLTAGE_OUT] = 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,
+#if IS_ENABLED(CONFIG_SENSORS_TDA38740_REGULATOR)
+ .num_regulators = 1,
+ .reg_desc = tda38740_reg_desc,
+#endif
+ },
+ [xdpe1a2g5b] = {
+ .pages = 2,
+ .read_word_data = tda38740_read_word_data,
+ .format[PSC_VOLTAGE_IN] = linear,
+ .format[PSC_VOLTAGE_OUT] = linear,
+ .format[PSC_TEMPERATURE] = linear,
+ .format[PSC_CURRENT_IN] = linear,
+ .format[PSC_CURRENT_OUT] = linear,
+ .format[PSC_POWER] = linear,
+ .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
+ PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP |
+ PMBUS_HAVE_POUT | PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT,
+ .func[1] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
+ PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP |
+ PMBUS_HAVE_POUT | PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT,
+ },
+ [xdpe19284c] = {
+ .pages = 2,
+ .read_word_data = tda38740_read_word_data,
+ .format[PSC_VOLTAGE_IN] = linear,
+ .format[PSC_VOLTAGE_OUT] = linear,
+ .format[PSC_TEMPERATURE] = linear,
+ .format[PSC_CURRENT_IN] = linear,
+ .format[PSC_CURRENT_OUT] = linear,
+ .format[PSC_POWER] = linear,
+ .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
+ PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP |
+ PMBUS_HAVE_POUT | PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT,
+ .func[1] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
+ PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP |
+ PMBUS_HAVE_POUT | PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT,
+ },
+ [xdpe192c4b] = {
+ .pages = 2,
+ .read_word_data = tda38740_read_word_data,
+ .format[PSC_VOLTAGE_IN] = linear,
+ .format[PSC_VOLTAGE_OUT] = linear,
+ .format[PSC_TEMPERATURE] = linear,
+ .format[PSC_CURRENT_IN] = linear,
+ .format[PSC_CURRENT_OUT] = linear,
+ .format[PSC_POWER] = linear,
+ .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
+ PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP |
+ PMBUS_HAVE_POUT | PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT,
+ .func[1] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
+ PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP |
+ PMBUS_HAVE_POUT | PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT,
+ },
+ [xdpe19283b] = {
+ .pages = 2,
+ .read_word_data = tda38740_read_word_data,
+ .format[PSC_VOLTAGE_IN] = linear,
+ .format[PSC_VOLTAGE_OUT] = linear,
+ .format[PSC_TEMPERATURE] = linear,
+ .format[PSC_CURRENT_IN] = linear,
+ .format[PSC_CURRENT_OUT] = linear,
+ .format[PSC_POWER] = linear,
+ .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
+ PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP |
+ PMBUS_HAVE_POUT | PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT,
+ .func[1] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
+ PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP |
+ PMBUS_HAVE_POUT | PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT,
+ },
+};
+
+/*
+ * Description: Pmbus block read data.
+ * client: i2c_client struct pointer
+ * cmd: pmbus command
+ * r_len: read data length
+ * data_r: pointer to return data buffer
+ */
+static int tda38740_pmbus_read_block_data(struct i2c_client *client, u8 cmd, u8 r_len, u8 *data_r)
+{
+ struct device *dev = &client->dev;
+ u8 write_buf[I2C_SMBUS_BLOCK_MAX + 1] = {0};
+ u8 read_buf[I2C_SMBUS_BLOCK_MAX + 1] = {0};
+ int ret = 0;
+ int len = 0;
+ struct i2c_msg msgs[2] = {
+ {
+ .addr = client->addr,
+ .flags = I2C_M_DMA_SAFE,
+ .buf = write_buf,
+ .len = 1,
+ },
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD | I2C_M_DMA_SAFE,
+ .buf = read_buf,
+ // +1 for the initial length byte
+ .len = r_len + 1,
+ }
+ };
+
+ if (r_len > I2C_SMBUS_BLOCK_MAX) {
+ dev_err(dev, "Error: Invalid data length[%d] to read.", r_len);
+ return -EPROTO;
+ }
+
+ /* fill in command byte */
+ msgs[0].buf[0] = cmd;
+
+ dev_dbg(dev, "Performing pmbus block read %d bytes data.", r_len);
+
+ /* perform i2c transfer to read block data */
+ ret = i2c_transfer(client->adapter, msgs, 2);
+
+ /* return data: first byte is the data count byte, second byte onwards are the data content bytes */
+ if (ret != r_len) {
+ dev_err(dev, "i2c block read error.");
+ return -EPROTO;
+ }
+
+ len = msgs[1].buf[0];
+
+ /* copy the read data into return buffer */
+ memcpy(data_r, &msgs[1].buf[1], len);
+ *(data_r + len) = '\0';
+
+ return ret;
+}
+
+static int tda38740_get_device_id(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ u8 device_id[I2C_SMBUS_BLOCK_MAX + 1] = {0};
+ enum chips id;
+ int status;
+
+ status = tda38740_pmbus_read_block_data(client, PMBUS_IC_DEVICE_ID, IC_DEV_ID_READ_BLOCK_SIZE, device_id);
+ if (status < 0) {
+ dev_err(dev, "Failed to read Device Id.\n");
+ return status;
+ }
+
+ dev_info(dev, "PMBUS IC DEVICE_ID: %02X %02X %02X\n", device_id[0], device_id[1], device_id[2]);
+
+ if (!strncasecmp(TDA38725_IC_DEVICE_ID, device_id, strlen(TDA38725_IC_DEVICE_ID))) {
+ id = tda38725;
+ } else if (!strncasecmp(TDA38725A_IC_DEVICE_ID, device_id, strlen(TDA38725A_IC_DEVICE_ID))) {
+ id = tda38725a;
+ } else if (!strncasecmp(TDA38740_IC_DEVICE_ID, device_id, strlen(TDA38740_IC_DEVICE_ID))) {
+ id = tda38740;
+ } else if (!strncasecmp(TDA38740A_IC_DEVICE_ID, device_id, strlen(TDA38740A_IC_DEVICE_ID))) {
+ id = tda38740a;
+ } else if (!strncasecmp(XDPE1A2G5B_IC_DEVICE_ID, device_id, strlen(XDPE1A2G5B_IC_DEVICE_ID))) {
+ id = xdpe1a2g5b;
+ } else if (!strncasecmp(XDPE19284C_IC_DEVICE_ID, device_id, strlen(XDPE19284C_IC_DEVICE_ID))) {
+ id = xdpe19284c;
+ } else if (!strncasecmp(XDPE192C4B_IC_DEVICE_ID, device_id, strlen(XDPE192C4B_IC_DEVICE_ID))) {
+ id = xdpe192c4b;
+ } else if (!strncasecmp(XDPE19283B_IC_DEVICE_ID, device_id, strlen(XDPE19283B_IC_DEVICE_ID))) {
+ id = xdpe19283b;
+ } else {
+ dev_err(dev, "Unsupported device\n");
+ return -ENODEV;
+ }
+
+ return id;
+}
+
+static int tda38740_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct tda38740_data *data;
+ enum chips id;
+ int chip_id;
+
+ /* FUNC for I2C SMBUS */
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_READ_BYTE_DATA |
+ I2C_FUNC_SMBUS_READ_WORD_DATA |
+ I2C_FUNC_SMBUS_BLOCK_DATA))
+ return -ENODEV;
+
+ chip_id = tda38740_get_device_id(client);
+ if (chip_id < 0)
+ return chip_id;
+
+ if (dev->of_node)
+ id = (uintptr_t)of_device_get_match_data(dev);
+ else
+ id = i2c_match_id(tda38740_id, client)->driver_data;
+
+ if (chip_id != id) {
+ dev_err(&client->dev, "Device mismatch: %d %d\n", id, chip_id);
+ return -ENODEV;
+ }
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data) {
+ dev_dbg(dev, "Kernal memory allocation failed.");
+ return -ENOMEM;
+ }
+
+ data->id = chip_id;
+ memcpy(&data->info, &tda38740_info[chip_id], sizeof(data->info));
+
+ if (!of_property_read_u32_array(client->dev.of_node, "vout_multiplier",
+ data->vout_multiplier, ARRAY_SIZE(data->vout_multiplier))) {
+ dev_dbg(dev, "vout_multipplier from Device Tree:%d %d\n",
+ data->vout_multiplier[0], data->vout_multiplier[1]);
+ } else {
+ data->vout_multiplier[0] = 0x01;
+ data->vout_multiplier[1] = 0x01;
+ dev_dbg(dev, "vout_multipplier default value:%d %d\n",
+ data->vout_multiplier[0], data->vout_multiplier[1]);
+ }
+
+ return pmbus_do_probe(client, &data->info);
+}
+
+static const struct i2c_device_id tda38740_id[] = {
+ {"tda38725", tda38725},
+ {"tda38725a", tda38725a},
+ {"tda38740", tda38740},
+ {"tda38740a", tda38740a},
+ {"xdpe1a2g5b", xdpe1a2g5b},
+ {"xdpe19284c", xdpe19284c},
+ {"xdpe192c4b", xdpe192c4b},
+ {"xdpe19283b", xdpe19283b},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, tda38740_id);
+
+static const struct of_device_id __maybe_unused tda38740_of_match[] = {
+ {.compatible = "infineon,tda38725", .data = (void *)tda38725 },
+ {.compatible = "infineon,tda38725a", .data = (void *)tda38725a },
+ {.compatible = "infineon,tda38740", .data = (void *)tda38740 },
+ {.compatible = "infineon,tda38740a", .data = (void *)tda38740a },
+ {.compatible = "infineon,xdpe1a2g5b", .data = (void *)xdpe1a2g5b},
+ {.compatible = "infineon,xdpe19284c", .data = (void *)xdpe19284c},
+ {.compatible = "infineon,xdpe192c4b", .data = (void *)xdpe192c4b},
+ {.compatible = "infineon,xdpe19283b", .data = (void *)xdpe19283b},
+ { }
+};
+
+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_new = tda38740_probe,
+ .id_table = tda38740_id,
+};
+
+module_i2c_driver(tda38740_driver);
+
+MODULE_AUTHOR("Ashish Yadav <Ashish.Yadav@infineon.com>");
+MODULE_DESCRIPTION("PMBus driver for Infineon IPOL/DMC");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(PMBUS);
--
2.52.0.177.g9f829587af-goog