| 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 |
| |