diff mbox series

[2/2] hwmon: Add driver for TI INA233 Current and Power Monitor

Message ID 20250106071337.3017926-3-Leo-Yang@quantatw.com (mailing list archive)
State Changes Requested
Headers show
Series hwmon: Add support for INA233 | expand

Commit Message

Leo Yang Jan. 6, 2025, 7:13 a.m. UTC
Support ina233 driver for Meta Yosemite V4.

Driver for Texas Instruments INA233 Current and Power Monitor
With I2C-, SMBus-, and PMBus-Compatible Interface

According to the mail
https://lore.kernel.org/all/
20230920054739.1561080-1-Delphine_CC_Chiu@wiwynn.com
maintainer's suggested rewrite driver

Signed-off-by: Leo Yang <Leo-Yang@quantatw.com>
---
 Documentation/hwmon/ina233.rst |  77 +++++++++++++
 Documentation/hwmon/index.rst  |   1 +
 MAINTAINERS                    |   9 ++
 drivers/hwmon/pmbus/Kconfig    |   9 ++
 drivers/hwmon/pmbus/Makefile   |   1 +
 drivers/hwmon/pmbus/ina233.c   | 200 +++++++++++++++++++++++++++++++++
 6 files changed, 297 insertions(+)
 create mode 100644 Documentation/hwmon/ina233.rst
 create mode 100644 drivers/hwmon/pmbus/ina233.c

Comments

kernel test robot Jan. 6, 2025, 9:45 a.m. UTC | #1
Hi Leo,

kernel test robot noticed the following build warnings:

[auto build test WARNING on groeck-staging/hwmon-next]
[also build test WARNING on linus/master v6.13-rc6 next-20241220]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Leo-Yang/dt-bindings-Add-INA233-device/20250106-151934
base:   https://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git hwmon-next
patch link:    https://lore.kernel.org/r/20250106071337.3017926-3-Leo-Yang%40quantatw.com
patch subject: [PATCH 2/2] hwmon: Add driver for TI INA233 Current and Power Monitor
reproduce: (https://download.01.org/0day-ci/archive/20250106/202501061734.nPNdRKqO-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202501061734.nPNdRKqO-lkp@intel.com/

All warnings (new ones prefixed by >>):

   Warning: Documentation/devicetree/bindings/regulator/siliconmitus,sm5703-regulator.yaml references a file that doesn't exist: Documentation/devicetree/bindings/mfd/siliconmitus,sm5703.yaml
   Warning: Documentation/hwmon/g762.rst references a file that doesn't exist: Documentation/devicetree/bindings/hwmon/g762.txt
   Warning: Documentation/translations/ja_JP/SubmittingPatches references a file that doesn't exist: linux-2.6.12-vanilla/Documentation/dontdiff
   Warning: Documentation/userspace-api/netlink/index.rst references a file that doesn't exist: Documentation/networking/netlink_spec/index.rst
   Warning: Documentation/userspace-api/netlink/specs.rst references a file that doesn't exist: Documentation/networking/netlink_spec/index.rst
>> Warning: MAINTAINERS references a file that doesn't exist: Documentation/devicetree/bindings/hwmon/ina233.txt
   Warning: MAINTAINERS references a file that doesn't exist: Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt
   Warning: lib/Kconfig.debug references a file that doesn't exist: Documentation/dev-tools/fault-injection/fault-injection.rst
   Using alabaster theme
Krzysztof Kozlowski Jan. 6, 2025, 10:52 a.m. UTC | #2
On 06/01/2025 08:13, Leo Yang wrote:
> Support ina233 driver for Meta Yosemite V4.
> 
> Driver for Texas Instruments INA233 Current and Power Monitor
> With I2C-, SMBus-, and PMBus-Compatible Interface
> 
> According to the mail
> https://lore.kernel.org/all/
> 20230920054739.1561080-1-Delphine_CC_Chiu@wiwynn.com

Don't break the URLs. It makes them difficult to use.


> maintainer's suggested rewrite driver
> 



> +INA233 HARDWARE MONITOR DRIVER
> +M:	Leo Yang <Leo-Yang@quantatw.com>
> +M:	Leo Yang <leo.yang.sy0@gmail.com>
> +L:	linux-hwmon@vger.kernel.org
> +S:	Odd Fixes
> +F:	Documentation/devicetree/bindings/hwmon/ina233.txt

There is no such file.


...

> +
> +struct pmbus_driver_info ina233_info = {

Why this cannot be const and static?

> +	.pages = 1,
> +	.format[PSC_VOLTAGE_IN] = direct,
> +	.format[PSC_VOLTAGE_OUT] = direct,
> +	.format[PSC_CURRENT_OUT] = direct,
> +	.format[PSC_POWER] = direct,
> +	.func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_INPUT
> +		| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
> +		| PMBUS_HAVE_POUT
> +		| PMBUS_HAVE_VMON | PMBUS_HAVE_STATUS_VMON,
> +	.m[PSC_VOLTAGE_IN] = 8,
> +	.R[PSC_VOLTAGE_IN] = 2,
> +	.m[PSC_VOLTAGE_OUT] = 8,
> +	.R[PSC_VOLTAGE_OUT] = 2,
> +	.read_word_data = ina233_read_word_data,
> +};
> +
> +static int ina233_probe(struct i2c_client *client)
> +{
> +	int ret, m, R;
> +	u32 rshunt;
> +	u16 current_lsb;
> +	u16 calibration;
> +
> +	/* If INA233 skips current/power, shunt-resistor and current-lsb aren't needed.	*/
> +
> +	/* read rshunt value (uOhm) */
> +	ret = of_property_read_u32(client->dev.of_node, "shunt-resistor", &rshunt);
> +	if (ret < 0 || !rshunt) {
> +		dev_err(&client->dev, "Unable to read shunt-resistor or value is 0, default value %d uOhm is used.\n",
> +			INA233_RSHUNT_DEFAULT);

Your binding said this is optional, so how this can be an error?

> +		rshunt = INA233_RSHUNT_DEFAULT;
> +	}
> +
> +	/* read current_lsb value (uA/bit) */
> +	ret = of_property_read_u16(client->dev.of_node, "current-lsb", &current_lsb);
> +	if (ret < 0 || !current_lsb) {
> +		dev_err(&client->dev, "Unable to read current_lsb or value is 0, default value %d uA/bit is used.\n",
> +			INA233_CURRENT_LSB_DEFAULT);

Same problem

> +		current_lsb = INA233_CURRENT_LSB_DEFAULT;
> +	}
> +
Best regards,
Krzysztof
Guenter Roeck Jan. 6, 2025, 3:31 p.m. UTC | #3
On 1/5/25 23:13, Leo Yang wrote:
> Support ina233 driver for Meta Yosemite V4.
> 
> Driver for Texas Instruments INA233 Current and Power Monitor
> With I2C-, SMBus-, and PMBus-Compatible Interface
> 
> According to the mail
> https://lore.kernel.org/all/
> 20230920054739.1561080-1-Delphine_CC_Chiu@wiwynn.com
> maintainer's suggested rewrite driver
> 
Drop the last sentence, or move after "---".

Besides, while I did point out a number of problems, but I did not suggest
to "rewrite the driver".

Since this is v2 of this driver, the submission should have been versioned,
and a change log should have been provided.

> Signed-off-by: Leo Yang <Leo-Yang@quantatw.com>
> ---
>   Documentation/hwmon/ina233.rst |  77 +++++++++++++
>   Documentation/hwmon/index.rst  |   1 +
>   MAINTAINERS                    |   9 ++
>   drivers/hwmon/pmbus/Kconfig    |   9 ++
>   drivers/hwmon/pmbus/Makefile   |   1 +
>   drivers/hwmon/pmbus/ina233.c   | 200 +++++++++++++++++++++++++++++++++
>   6 files changed, 297 insertions(+)
>   create mode 100644 Documentation/hwmon/ina233.rst
>   create mode 100644 drivers/hwmon/pmbus/ina233.c
> 
> diff --git a/Documentation/hwmon/ina233.rst b/Documentation/hwmon/ina233.rst
> new file mode 100644
> index 000000000000..5c9e5ed2d6d5
> --- /dev/null
> +++ b/Documentation/hwmon/ina233.rst
> @@ -0,0 +1,77 @@
> +.. SPDX-License-Identifier: GPL-2.0
> +
> +Kernel driver ina233
> +====================
> +
> +Supported chips:
> +
> +  * TI INA233
> +
> +    Prefix: 'ina233'
> +
> +  * Datasheet
> +
> +    Publicly available at the TI website : https://www.ti.com/lit/ds/symlink/ina233.pdf
> +
> +Author:
> +
> +	Leo Yang <Leo-Yang@quantatw.com>
> +
> +Usage Notes
> +-----------
> +
> +The shunt resistor value can be configured by a device tree property;
> +see Documentation/devicetree/bindings/hwmon/pmbus/ti,ina233.yaml for details.
> +
> +
> +Description
> +-----------
> +
> +This driver supports hardware monitoring for TI INA233.
> +
> +The driver is a client driver to the core PMBus driver. Please see
> +Documentation/hwmon/pmbus.rst for details on PMBus client drivers.
> +
> +The driver provides the following attributes for input voltage:
> +
> +**in1_input**
> +
> +**in1_label**
> +
> +**in1_max**
> +
> +**in1_max_alarm**
> +
> +**in1_min**
> +
> +**in1_min_alarm**
> +
> +The driver provides the following attributes for shunt voltage:
> +
> +**in2_input**
> +
> +**in2_label**
> +
> +The driver provides the following attributes for output voltage:
> +
> +**in3_input**
> +
> +**in3_label**
> +
> +**in3_alarm**
> +
> +The driver provides the following attributes for output current:
> +
> +**curr1_input**
> +
> +**curr1_label**
> +
> +**curr1_max**
> +
> +**curr1_max_alarm**
> +
> +The driver provides the following attributes for input power:
> +
> +**power1_input**
> +
> +**power1_label**
> \ No newline at end of file
> diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst
> index 55f1111594b2..f280fa6e7d95 100644
> --- a/Documentation/hwmon/index.rst
> +++ b/Documentation/hwmon/index.rst
> @@ -89,6 +89,7 @@ Hardware Monitoring Kernel Drivers
>      ibmpowernv
>      ina209
>      ina2xx
> +   ina233
>      ina238
>      ina3221
>      inspur-ipsps1
> diff --git a/MAINTAINERS b/MAINTAINERS
> index c575de4903db..061da798536d 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -11226,6 +11226,15 @@ L:	linux-fbdev@vger.kernel.org
>   S:	Orphan
>   F:	drivers/video/fbdev/imsttfb.c
>   
> +INA233 HARDWARE MONITOR DRIVER
> +M:	Leo Yang <Leo-Yang@quantatw.com>
> +M:	Leo Yang <leo.yang.sy0@gmail.com>
> +L:	linux-hwmon@vger.kernel.org
> +S:	Odd Fixes
> +F:	Documentation/devicetree/bindings/hwmon/ina233.txt
> +F:	Documentation/hwmon/ina233.rst
> +F:	drivers/hwmon/pmbus/ina233.c
> +
>   INDEX OF FURTHER KERNEL DOCUMENTATION
>   M:	Carlos Bilbao <carlos.bilbao.osdev@gmail.com>
>   S:	Maintained
> diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
> index f6d352841953..55db0ddc94ed 100644
> --- a/drivers/hwmon/pmbus/Kconfig
> +++ b/drivers/hwmon/pmbus/Kconfig
> @@ -124,6 +124,15 @@ config SENSORS_DPS920AB
>   	  This driver can also be built as a module. If so, the module will
>   	  be called dps920ab.
>   
> +config SENSORS_INA233
> +	tristate "Texas Instruments INA233 and compatibles"
> +	help
> +	  If you say yes here you get hardware monitoring support for Texas
> +	  Instruments INA233.
> +
> +	  This driver can also be built as a module. If so, the module will
> +	  be called ina233.
> +
>   config SENSORS_INSPUR_IPSPS
>   	tristate "INSPUR Power System Power Supply"
>   	help
> diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile
> index d00bcc758b97..3c4b06fb939e 100644
> --- a/drivers/hwmon/pmbus/Makefile
> +++ b/drivers/hwmon/pmbus/Makefile
> @@ -15,6 +15,7 @@ obj-$(CONFIG_SENSORS_DELTA_AHE50DC_FAN) += delta-ahe50dc-fan.o
>   obj-$(CONFIG_SENSORS_FSP_3Y)	+= fsp-3y.o
>   obj-$(CONFIG_SENSORS_IBM_CFFPS)	+= ibm-cffps.o
>   obj-$(CONFIG_SENSORS_DPS920AB)	+= dps920ab.o
> +obj-$(CONFIG_SENSORS_INA233)	+= ina233.o
>   obj-$(CONFIG_SENSORS_INSPUR_IPSPS) += inspur-ipsps.o
>   obj-$(CONFIG_SENSORS_IR35221)	+= ir35221.o
>   obj-$(CONFIG_SENSORS_IR36021)	+= ir36021.o
> diff --git a/drivers/hwmon/pmbus/ina233.c b/drivers/hwmon/pmbus/ina233.c
> new file mode 100644
> index 000000000000..1f7be600dea4
> --- /dev/null
> +++ b/drivers/hwmon/pmbus/ina233.c
> @@ -0,0 +1,200 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Hardware monitoring driver for ina233
> + *
> + * Copyright (c) 2024 Leo Yang
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/err.h>
> +#include <linux/i2c.h>

Alphabetic include file order, please.

> +#include "pmbus.h"
> +
> +#define MFR_READ_VSHUNT 0xd1
> +#define MFR_CALIBRATION 0xd4
> +
> +#define INA233_RSHUNT_DEFAULT		2000 /* uOhm */
> +#define INA233_CURRENT_LSB_DEFAULT	1000 /* uA/bit */

"bit" is implied in "LSB".

> +
> +#define MAX_M_VAL 32767
> +#define MIN_M_VAL -32768
> +
> +static int calculate_coef(int *m, int *R, bool power)
> +{
> +	s64 scaled_m;
> +	int scale_factor = 0;
> +	int scale_coef = 1;
> +	int power_coef = 1;
> +	bool is_integer = false;
> +
> +	if (*m == 0) {
> +		*R = 0;
> +		return -1;
> +	}

*m is never 0.

> +
> +	if (power)
> +		power_coef = 25;
> +

Why not just pass the power coefficient directly as parameter ?

> +	if (1000000 % *m) {

I fail to understand the logic here. Why scale if and only if m is a clean
multiple of 1000000 ? Scale if m == 1000001 but not if m == 1000000 ?
Please explain.

> +		/* Default value, Scaling to keep integer precision,
> +		 * Change it if you need

This comment does not provide any actual information and thus does not
add any value. Change to what ? Why ? And, again, why not scale if
m is a multiple of 1000000, no matter how large or small it is ?

> +		 */
> +		scale_factor = -3;
> +		scale_coef = 1000;
> +	} else {
> +		is_integer = true;
> +	}
> +
> +	/*
> +	 * Unit Conversion (Current_LSB A->uA) and use scaling(scale_factor)
> +	 * to keep integer precision.
> +	 * Formulae referenced from spec.
> +	 */
> +	scaled_m = div_s64(1000000 * scale_coef, *m * power_coef);
> +
> +	/* Maximize while keeping it bounded.*/
> +	while (scaled_m > MAX_M_VAL || scaled_m < MIN_M_VAL) {
> +		scaled_m /= 10;

This looks wrong. If scaled_m < MIN_M_VAL it doesn't make sense
to decrease it even more.

> +		scale_factor++;
> +	}
> +	/* Scale up only if fractional part exists. */
> +	while (scaled_m * 10 < MAX_M_VAL && scaled_m * 10 > MIN_M_VAL && !is_integer) {

This looks just as wrong. If scaled_m > 10 * MIN_M_VAL, why increase it even more ?

> +		scaled_m *= 10;
> +		scale_factor--;
> +	}
> +
> +	*m = scaled_m;
> +	*R = scale_factor;
> +	return 0;
> +}
> +
> +static int ina233_read_word_data(struct i2c_client *client, int page,
> +				 int phase, int reg)
> +{
> +	int ret;
> +
> +	switch (reg) {
> +	case PMBUS_VIRT_READ_VMON:
> +		ret = pmbus_read_word_data(client, 0, 0xff, MFR_READ_VSHUNT);
> +
> +		/* Adjust returned value to match VIN coefficients */
> +		/* VIN: 1.25 mV VSHUNT: 2.5 uV LSB */
> +		ret = DIV_ROUND_CLOSEST(ret * 25, 12500);
> +		break;
> +	default:
> +		ret = -ENODATA;
> +		break;
> +	}
> +	return ret;
> +}
> +
> +struct pmbus_driver_info ina233_info = {
> +	.pages = 1,
> +	.format[PSC_VOLTAGE_IN] = direct,
> +	.format[PSC_VOLTAGE_OUT] = direct,
> +	.format[PSC_CURRENT_OUT] = direct,
> +	.format[PSC_POWER] = direct,
> +	.func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_INPUT
> +		| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
> +		| PMBUS_HAVE_POUT
> +		| PMBUS_HAVE_VMON | PMBUS_HAVE_STATUS_VMON,
> +	.m[PSC_VOLTAGE_IN] = 8,
> +	.R[PSC_VOLTAGE_IN] = 2,
> +	.m[PSC_VOLTAGE_OUT] = 8,
> +	.R[PSC_VOLTAGE_OUT] = 2,
> +	.read_word_data = ina233_read_word_data,
> +};
> +
> +static int ina233_probe(struct i2c_client *client)
> +{
> +	int ret, m, R;
> +	u32 rshunt;
> +	u16 current_lsb;
> +	u16 calibration;
> +
> +	/* If INA233 skips current/power, shunt-resistor and current-lsb aren't needed.	*/
> +
> +	/* read rshunt value (uOhm) */
> +	ret = of_property_read_u32(client->dev.of_node, "shunt-resistor", &rshunt);
> +	if (ret < 0 || !rshunt) {
An rshunt value of 0 would be wrong and must not be accepted.

> +		dev_err(&client->dev, "Unable to read shunt-resistor or value is 0, default value %d uOhm is used.\n",
> +			INA233_RSHUNT_DEFAULT);

This is not an error and thus must not result in an error message.

> +		rshunt = INA233_RSHUNT_DEFAULT;
> +	}
> +
> +	/* read current_lsb value (uA/bit) */
> +	ret = of_property_read_u16(client->dev.of_node, "current-lsb", &current_lsb);
> +	if (ret < 0 || !current_lsb) {
> +		dev_err(&client->dev, "Unable to read current_lsb or value is 0, default value %d uA/bit is used.\n",
> +			INA233_CURRENT_LSB_DEFAULT);

Thjs is not an error and thus must not result in an error message.
Also, a current-lsb value of 0 in devicetree would be wrong and
must not be accepted.

> +		current_lsb = INA233_CURRENT_LSB_DEFAULT;
> +	}
> +
> +	/* calculate current coefficient */
> +	m = current_lsb;
> +	ret = calculate_coef(&m, &R, false);
> +	if (ret < 0) {
> +		dev_err(&client->dev, "Calculate_coef error\n");

And ignore the error ? This is a no-go. Either it is an error, and the driver
should abort, or it isn't, and there should be no error message.

Besides, current_lsb is never 0, and the function will never return an error,
so this "error handling" is not only unnecessary but misleading.

> +	} else {
> +		ina233_info.m[PSC_CURRENT_OUT] = m;
> +		ina233_info.R[PSC_CURRENT_OUT] = R;

This is a no-go. There could be multiple INA233 with different parameters
in the system. The second one would overwrite the first one's parameters.

> +	}
> +
> +	/* calculate power coefficient */
> +	m = current_lsb;
> +	ret = calculate_coef(&m, &R, true);
> +	if (ret < 0) {
> +		dev_err(&client->dev, "Calculate_coef error\n");
> +	} else {
> +		ina233_info.m[PSC_POWER] = m;
> +		ina233_info.R[PSC_POWER] = R;
> +	}

Same comments as above.

> +
> +	/* write MFR_CALIBRATION register, Apply formula from spec with unit scaling. */
> +	calibration = div_u64((u64)5120000000, (u64)rshunt * current_lsb);

5120000000ULL, and drop the type cast. Also, the divisor of div_u64() is u32,
so type casting its parameter to u64 won't help. If rshunt * current_lsb can
be larger than 32 bit, this would have to use div64_u64().

> +	if (calibration <= 0) {

The result of this calculation is never < 0.

> +		dev_err(&client->dev, "Calibration error\n");
> +		return -1;

This is not a valid error code, and the message is useless. It needs to explain why
the calibration failed, and the returned error code should be -EINVAL.

> +	}
> +	ret = i2c_smbus_write_word_data(client, MFR_CALIBRATION, calibration);

This only writes 16 bit. What if the calibration value is larger than 0xffff ?

> +	if (ret < 0) {
> +		dev_err(&client->dev, "Unable to write calibration\n");
> +		return ret;
> +	}
> +
> +	dev_info(&client->dev, "power monitor %s (Rshunt = %u uOhm, Current_LSB = %u uA/bit)\n",
> +		 client->name, rshunt, current_lsb);

Please refrain from logging noise and make this dev_dbg().

> +
> +	return pmbus_do_probe(client, &ina233_info);
> +}
> +
> +static const struct i2c_device_id ina233_id[] = {
> +	{"ina233", 0},
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(i2c, ina233_id);
> +
> +static const struct of_device_id __maybe_unused ina233_of_match[] = {
> +	{ .compatible = "ti,ina233" },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, ina233_of_match);
> +
> +/* This is the driver that will be inserted */

Useless comment. Please drop. Yes, it is kind of common in hwmon drivers,
and its existence is partly my fault, but that doesn't make it better.

Thanks,
Guenter

> +static struct i2c_driver ina233_driver = {
> +	.driver = {
> +		   .name = "ina233",
> +		   .of_match_table = of_match_ptr(ina233_of_match),
> +	},
> +	.probe = ina233_probe,
> +	.id_table = ina233_id,
> +};
> +
> +module_i2c_driver(ina233_driver);
> +
> +MODULE_AUTHOR("Leo Yang <Leo-Yang@quantatw.com>");
> +MODULE_DESCRIPTION("PMBus driver for INA233 and compatible chips");
> +MODULE_LICENSE("GPL");
> +MODULE_IMPORT_NS("PMBUS");
kernel test robot Jan. 7, 2025, 5:08 p.m. UTC | #4
Hi Leo,

kernel test robot noticed the following build warnings:

[auto build test WARNING on groeck-staging/hwmon-next]
[also build test WARNING on linus/master v6.13-rc6 next-20250107]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Leo-Yang/dt-bindings-Add-INA233-device/20250106-151934
base:   https://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git hwmon-next
patch link:    https://lore.kernel.org/r/20250106071337.3017926-3-Leo-Yang%40quantatw.com
patch subject: [PATCH 2/2] hwmon: Add driver for TI INA233 Current and Power Monitor
config: csky-randconfig-r131-20250107 (https://download.01.org/0day-ci/archive/20250108/202501080011.H8YAGThn-lkp@intel.com/config)
compiler: csky-linux-gcc (GCC) 14.2.0
reproduce: (https://download.01.org/0day-ci/archive/20250108/202501080011.H8YAGThn-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202501080011.H8YAGThn-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> drivers/hwmon/pmbus/ina233.c:93:26: sparse: sparse: symbol 'ina233_info' was not declared. Should it be static?

vim +/ina233_info +93 drivers/hwmon/pmbus/ina233.c

    92	
  > 93	struct pmbus_driver_info ina233_info = {
    94		.pages = 1,
    95		.format[PSC_VOLTAGE_IN] = direct,
    96		.format[PSC_VOLTAGE_OUT] = direct,
    97		.format[PSC_CURRENT_OUT] = direct,
    98		.format[PSC_POWER] = direct,
    99		.func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_INPUT
   100			| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
   101			| PMBUS_HAVE_POUT
   102			| PMBUS_HAVE_VMON | PMBUS_HAVE_STATUS_VMON,
   103		.m[PSC_VOLTAGE_IN] = 8,
   104		.R[PSC_VOLTAGE_IN] = 2,
   105		.m[PSC_VOLTAGE_OUT] = 8,
   106		.R[PSC_VOLTAGE_OUT] = 2,
   107		.read_word_data = ina233_read_word_data,
   108	};
   109
Leo Yang Jan. 9, 2025, 12:50 a.m. UTC | #5
Hi Guenter,

On Mon, Jan 6, 2025 at 11:31 PM Guenter Roeck <linux@roeck-us.net> wrote:
>
> Besides, while I did point out a number of problems, but I did not suggest
> to "rewrite the driver".
>
> Since this is v2 of this driver, the submission should have been versioned,
> and a change log should have been provided.
>

Sorry this is my first v2 patch,
I should have been more aware of this problem, thank you.

>
> Why not just pass the power coefficient directly as parameter ?
>
> > +     if (1000000 % *m) {
>
> I fail to understand the logic here. Why scale if and only if m is a clean
> multiple of 1000000 ? Scale if m == 1000001 but not if m == 1000000 ?
> Please explain.
>
> > +             /* Default value, Scaling to keep integer precision,
> > +              * Change it if you need
>
> This comment does not provide any actual information and thus does not
> add any value. Change to what ? Why ? And, again, why not scale if
> m is a multiple of 1000000, no matter how large or small it is ?
>

When we calculate the Telemetry and Warning Conversion Coefficients,
the m-value of the current needs to be calculated via Equation:
1(A)/Current_LSB(A).

The number 1000000 comes from A->uA to match the unit uA of Current_LSB.
Try to prevent the loss of fractional precision in integer.

But this is not enough,
according to spec 7.5.4 Reading Telemetry Data and Warning Thresholds
If there is decimal information in m, we should try to move the decimal point
so that the value of m is between -32768 and 32767 and maximize it as much
as possible to minimize rounding errors.

Therefore, if m does not have decimal information, even if the value of m is
scaled up, it is not possible to minimize rounding errors.

But my comments are not clear enough, I'll fix it.

> > +
> > +     /* Maximize while keeping it bounded.*/
> > +     while (scaled_m > MAX_M_VAL || scaled_m < MIN_M_VAL) {
> > +             scaled_m /= 10;
>
> This looks wrong. If scaled_m < MIN_M_VAL it doesn't make sense
> to decrease it even more.
>

In this part, I try to move the decimal point so that the value of m is between
-32768 and 32767.
Assuming scaled_m = -40001, I can scale it to m = -4000 and adjust it by R++

> > +             scale_factor++;
> > +     }
> > +     /* Scale up only if fractional part exists. */
> > +     while (scaled_m * 10 < MAX_M_VAL && scaled_m * 10 > MIN_M_VAL && !is_integer) {
>
> This looks just as wrong. If scaled_m > 10 * MIN_M_VAL, why increase it even more ?
>

I think the purpose of spec is to keep as many integers as possible in m, and
then save the information in decimals via R to minimize rounding errors.
So here I keep the positive numbers as close to 32767 as possible, and the
negative numbers as close to -32768 as possible.

And thank you for the suggestions, they are very helpful and I will
try to fix them.


Best Regards,

Leo Yang
Guenter Roeck Jan. 9, 2025, 3:04 a.m. UTC | #6
On 1/8/25 16:50, Leo Yang wrote:
> Hi Guenter,
> 
> On Mon, Jan 6, 2025 at 11:31 PM Guenter Roeck <linux@roeck-us.net> wrote:
>>
>> Besides, while I did point out a number of problems, but I did not suggest
>> to "rewrite the driver".
>>
>> Since this is v2 of this driver, the submission should have been versioned,
>> and a change log should have been provided.
>>
> 
> Sorry this is my first v2 patch,
> I should have been more aware of this problem, thank you.
> 
>>
>> Why not just pass the power coefficient directly as parameter ?
>>
>>> +     if (1000000 % *m) {
>>
>> I fail to understand the logic here. Why scale if and only if m is a clean
>> multiple of 1000000 ? Scale if m == 1000001 but not if m == 1000000 ?
>> Please explain.
>>
>>> +             /* Default value, Scaling to keep integer precision,
>>> +              * Change it if you need
>>
>> This comment does not provide any actual information and thus does not
>> add any value. Change to what ? Why ? And, again, why not scale if
>> m is a multiple of 1000000, no matter how large or small it is ?
>>
> 
> When we calculate the Telemetry and Warning Conversion Coefficients,
> the m-value of the current needs to be calculated via Equation:
> 1(A)/Current_LSB(A).
> 
> The number 1000000 comes from A->uA to match the unit uA of Current_LSB.
> Try to prevent the loss of fractional precision in integer.
> 
> But this is not enough,
> according to spec 7.5.4 Reading Telemetry Data and Warning Thresholds
> If there is decimal information in m, we should try to move the decimal point
> so that the value of m is between -32768 and 32767 and maximize it as much
> as possible to minimize rounding errors.
> 
> Therefore, if m does not have decimal information, even if the value of m is
> scaled up, it is not possible to minimize rounding errors.
> 
> But my comments are not clear enough, I'll fix it.
> 
>>> +
>>> +     /* Maximize while keeping it bounded.*/
>>> +     while (scaled_m > MAX_M_VAL || scaled_m < MIN_M_VAL) {
>>> +             scaled_m /= 10;
>>
>> This looks wrong. If scaled_m < MIN_M_VAL it doesn't make sense
>> to decrease it even more.
>>
> 
> In this part, I try to move the decimal point so that the value of m is between
> -32768 and 32767.
> Assuming scaled_m = -40001, I can scale it to m = -4000 and adjust it by R++
> 
Sorry, I missed that MIN_M_VAL is negative.

Guenter

>>> +             scale_factor++;
>>> +     }
>>> +     /* Scale up only if fractional part exists. */
>>> +     while (scaled_m * 10 < MAX_M_VAL && scaled_m * 10 > MIN_M_VAL && !is_integer) {
>>
>> This looks just as wrong. If scaled_m > 10 * MIN_M_VAL, why increase it even more ?
>>
> 
> I think the purpose of spec is to keep as many integers as possible in m, and
> then save the information in decimals via R to minimize rounding errors.
> So here I keep the positive numbers as close to 32767 as possible, and the
> negative numbers as close to -32768 as possible.
> 
> And thank you for the suggestions, they are very helpful and I will
> try to fix them.
> 
> 
> Best Regards,
> 
> Leo Yang
kernel test robot Jan. 9, 2025, 10:15 a.m. UTC | #7
Hi Leo,

kernel test robot noticed the following build errors:

[auto build test ERROR on groeck-staging/hwmon-next]
[also build test ERROR on linus/master v6.13-rc6 next-20250108]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Leo-Yang/dt-bindings-Add-INA233-device/20250106-151934
base:   https://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git hwmon-next
patch link:    https://lore.kernel.org/r/20250106071337.3017926-3-Leo-Yang%40quantatw.com
patch subject: [PATCH 2/2] hwmon: Add driver for TI INA233 Current and Power Monitor
config: i386-randconfig-001-20250108 (https://download.01.org/0day-ci/archive/20250109/202501091702.8ZdJcvFC-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250109/202501091702.8ZdJcvFC-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202501091702.8ZdJcvFC-lkp@intel.com/

All errors (new ones prefixed by >>, old ones prefixed by <<):

>> ERROR: modpost: "__divdi3" [drivers/hwmon/pmbus/ina233.ko] undefined!
kernel test robot Jan. 9, 2025, 2:59 p.m. UTC | #8
Hi Leo,

kernel test robot noticed the following build errors:

[auto build test ERROR on groeck-staging/hwmon-next]
[also build test ERROR on linus/master v6.13-rc6 next-20250109]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Leo-Yang/dt-bindings-Add-INA233-device/20250106-151934
base:   https://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git hwmon-next
patch link:    https://lore.kernel.org/r/20250106071337.3017926-3-Leo-Yang%40quantatw.com
patch subject: [PATCH 2/2] hwmon: Add driver for TI INA233 Current and Power Monitor
config: i386-randconfig-r072-20250109 (https://download.01.org/0day-ci/archive/20250109/202501092213.X9mbPW5Q-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250109/202501092213.X9mbPW5Q-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202501092213.X9mbPW5Q-lkp@intel.com/

All errors (new ones prefixed by >>):

   ld: drivers/hwmon/pmbus/ina233.o: in function `calculate_coef':
>> drivers/hwmon/pmbus/ina233.c:59: undefined reference to `__divdi3'


vim +59 drivers/hwmon/pmbus/ina233.c

    23	
    24	static int calculate_coef(int *m, int *R, bool power)
    25	{
    26		s64 scaled_m;
    27		int scale_factor = 0;
    28		int scale_coef = 1;
    29		int power_coef = 1;
    30		bool is_integer = false;
    31	
    32		if (*m == 0) {
    33			*R = 0;
    34			return -1;
    35		}
    36	
    37		if (power)
    38			power_coef = 25;
    39	
    40		if (1000000 % *m) {
    41			/* Default value, Scaling to keep integer precision,
    42			 * Change it if you need
    43			 */
    44			scale_factor = -3;
    45			scale_coef = 1000;
    46		} else {
    47			is_integer = true;
    48		}
    49	
    50		/*
    51		 * Unit Conversion (Current_LSB A->uA) and use scaling(scale_factor)
    52		 * to keep integer precision.
    53		 * Formulae referenced from spec.
    54		 */
    55		scaled_m = div_s64(1000000 * scale_coef, *m * power_coef);
    56	
    57		/* Maximize while keeping it bounded.*/
    58		while (scaled_m > MAX_M_VAL || scaled_m < MIN_M_VAL) {
  > 59			scaled_m /= 10;
    60			scale_factor++;
    61		}
    62		/* Scale up only if fractional part exists. */
    63		while (scaled_m * 10 < MAX_M_VAL && scaled_m * 10 > MIN_M_VAL && !is_integer) {
    64			scaled_m *= 10;
    65			scale_factor--;
    66		}
    67	
    68		*m = scaled_m;
    69		*R = scale_factor;
    70		return 0;
    71	}
    72
diff mbox series

Patch

diff --git a/Documentation/hwmon/ina233.rst b/Documentation/hwmon/ina233.rst
new file mode 100644
index 000000000000..5c9e5ed2d6d5
--- /dev/null
+++ b/Documentation/hwmon/ina233.rst
@@ -0,0 +1,77 @@ 
+.. SPDX-License-Identifier: GPL-2.0
+
+Kernel driver ina233
+====================
+
+Supported chips:
+
+  * TI INA233
+
+    Prefix: 'ina233'
+
+  * Datasheet
+
+    Publicly available at the TI website : https://www.ti.com/lit/ds/symlink/ina233.pdf
+
+Author:
+
+	Leo Yang <Leo-Yang@quantatw.com>
+
+Usage Notes
+-----------
+
+The shunt resistor value can be configured by a device tree property;
+see Documentation/devicetree/bindings/hwmon/pmbus/ti,ina233.yaml for details.
+
+
+Description
+-----------
+
+This driver supports hardware monitoring for TI INA233.
+
+The driver is a client driver to the core PMBus driver. Please see
+Documentation/hwmon/pmbus.rst for details on PMBus client drivers.
+
+The driver provides the following attributes for input voltage:
+
+**in1_input**
+
+**in1_label**
+
+**in1_max**
+
+**in1_max_alarm**
+
+**in1_min**
+
+**in1_min_alarm**
+
+The driver provides the following attributes for shunt voltage:
+
+**in2_input**
+
+**in2_label**
+
+The driver provides the following attributes for output voltage:
+
+**in3_input**
+
+**in3_label**
+
+**in3_alarm**
+
+The driver provides the following attributes for output current:
+
+**curr1_input**
+
+**curr1_label**
+
+**curr1_max**
+
+**curr1_max_alarm**
+
+The driver provides the following attributes for input power:
+
+**power1_input**
+
+**power1_label**
\ No newline at end of file
diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst
index 55f1111594b2..f280fa6e7d95 100644
--- a/Documentation/hwmon/index.rst
+++ b/Documentation/hwmon/index.rst
@@ -89,6 +89,7 @@  Hardware Monitoring Kernel Drivers
    ibmpowernv
    ina209
    ina2xx
+   ina233
    ina238
    ina3221
    inspur-ipsps1
diff --git a/MAINTAINERS b/MAINTAINERS
index c575de4903db..061da798536d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11226,6 +11226,15 @@  L:	linux-fbdev@vger.kernel.org
 S:	Orphan
 F:	drivers/video/fbdev/imsttfb.c
 
+INA233 HARDWARE MONITOR DRIVER
+M:	Leo Yang <Leo-Yang@quantatw.com>
+M:	Leo Yang <leo.yang.sy0@gmail.com>
+L:	linux-hwmon@vger.kernel.org
+S:	Odd Fixes
+F:	Documentation/devicetree/bindings/hwmon/ina233.txt
+F:	Documentation/hwmon/ina233.rst
+F:	drivers/hwmon/pmbus/ina233.c
+
 INDEX OF FURTHER KERNEL DOCUMENTATION
 M:	Carlos Bilbao <carlos.bilbao.osdev@gmail.com>
 S:	Maintained
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
index f6d352841953..55db0ddc94ed 100644
--- a/drivers/hwmon/pmbus/Kconfig
+++ b/drivers/hwmon/pmbus/Kconfig
@@ -124,6 +124,15 @@  config SENSORS_DPS920AB
 	  This driver can also be built as a module. If so, the module will
 	  be called dps920ab.
 
+config SENSORS_INA233
+	tristate "Texas Instruments INA233 and compatibles"
+	help
+	  If you say yes here you get hardware monitoring support for Texas
+	  Instruments INA233.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called ina233.
+
 config SENSORS_INSPUR_IPSPS
 	tristate "INSPUR Power System Power Supply"
 	help
diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile
index d00bcc758b97..3c4b06fb939e 100644
--- a/drivers/hwmon/pmbus/Makefile
+++ b/drivers/hwmon/pmbus/Makefile
@@ -15,6 +15,7 @@  obj-$(CONFIG_SENSORS_DELTA_AHE50DC_FAN) += delta-ahe50dc-fan.o
 obj-$(CONFIG_SENSORS_FSP_3Y)	+= fsp-3y.o
 obj-$(CONFIG_SENSORS_IBM_CFFPS)	+= ibm-cffps.o
 obj-$(CONFIG_SENSORS_DPS920AB)	+= dps920ab.o
+obj-$(CONFIG_SENSORS_INA233)	+= ina233.o
 obj-$(CONFIG_SENSORS_INSPUR_IPSPS) += inspur-ipsps.o
 obj-$(CONFIG_SENSORS_IR35221)	+= ir35221.o
 obj-$(CONFIG_SENSORS_IR36021)	+= ir36021.o
diff --git a/drivers/hwmon/pmbus/ina233.c b/drivers/hwmon/pmbus/ina233.c
new file mode 100644
index 000000000000..1f7be600dea4
--- /dev/null
+++ b/drivers/hwmon/pmbus/ina233.c
@@ -0,0 +1,200 @@ 
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Hardware monitoring driver for ina233
+ *
+ * Copyright (c) 2024 Leo Yang
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include "pmbus.h"
+
+#define MFR_READ_VSHUNT 0xd1
+#define MFR_CALIBRATION 0xd4
+
+#define INA233_RSHUNT_DEFAULT		2000 /* uOhm */
+#define INA233_CURRENT_LSB_DEFAULT	1000 /* uA/bit */
+
+#define MAX_M_VAL 32767
+#define MIN_M_VAL -32768
+
+static int calculate_coef(int *m, int *R, bool power)
+{
+	s64 scaled_m;
+	int scale_factor = 0;
+	int scale_coef = 1;
+	int power_coef = 1;
+	bool is_integer = false;
+
+	if (*m == 0) {
+		*R = 0;
+		return -1;
+	}
+
+	if (power)
+		power_coef = 25;
+
+	if (1000000 % *m) {
+		/* Default value, Scaling to keep integer precision,
+		 * Change it if you need
+		 */
+		scale_factor = -3;
+		scale_coef = 1000;
+	} else {
+		is_integer = true;
+	}
+
+	/*
+	 * Unit Conversion (Current_LSB A->uA) and use scaling(scale_factor)
+	 * to keep integer precision.
+	 * Formulae referenced from spec.
+	 */
+	scaled_m = div_s64(1000000 * scale_coef, *m * power_coef);
+
+	/* Maximize while keeping it bounded.*/
+	while (scaled_m > MAX_M_VAL || scaled_m < MIN_M_VAL) {
+		scaled_m /= 10;
+		scale_factor++;
+	}
+	/* Scale up only if fractional part exists. */
+	while (scaled_m * 10 < MAX_M_VAL && scaled_m * 10 > MIN_M_VAL && !is_integer) {
+		scaled_m *= 10;
+		scale_factor--;
+	}
+
+	*m = scaled_m;
+	*R = scale_factor;
+	return 0;
+}
+
+static int ina233_read_word_data(struct i2c_client *client, int page,
+				 int phase, int reg)
+{
+	int ret;
+
+	switch (reg) {
+	case PMBUS_VIRT_READ_VMON:
+		ret = pmbus_read_word_data(client, 0, 0xff, MFR_READ_VSHUNT);
+
+		/* Adjust returned value to match VIN coefficients */
+		/* VIN: 1.25 mV VSHUNT: 2.5 uV LSB */
+		ret = DIV_ROUND_CLOSEST(ret * 25, 12500);
+		break;
+	default:
+		ret = -ENODATA;
+		break;
+	}
+	return ret;
+}
+
+struct pmbus_driver_info ina233_info = {
+	.pages = 1,
+	.format[PSC_VOLTAGE_IN] = direct,
+	.format[PSC_VOLTAGE_OUT] = direct,
+	.format[PSC_CURRENT_OUT] = direct,
+	.format[PSC_POWER] = direct,
+	.func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_INPUT
+		| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
+		| PMBUS_HAVE_POUT
+		| PMBUS_HAVE_VMON | PMBUS_HAVE_STATUS_VMON,
+	.m[PSC_VOLTAGE_IN] = 8,
+	.R[PSC_VOLTAGE_IN] = 2,
+	.m[PSC_VOLTAGE_OUT] = 8,
+	.R[PSC_VOLTAGE_OUT] = 2,
+	.read_word_data = ina233_read_word_data,
+};
+
+static int ina233_probe(struct i2c_client *client)
+{
+	int ret, m, R;
+	u32 rshunt;
+	u16 current_lsb;
+	u16 calibration;
+
+	/* If INA233 skips current/power, shunt-resistor and current-lsb aren't needed.	*/
+
+	/* read rshunt value (uOhm) */
+	ret = of_property_read_u32(client->dev.of_node, "shunt-resistor", &rshunt);
+	if (ret < 0 || !rshunt) {
+		dev_err(&client->dev, "Unable to read shunt-resistor or value is 0, default value %d uOhm is used.\n",
+			INA233_RSHUNT_DEFAULT);
+		rshunt = INA233_RSHUNT_DEFAULT;
+	}
+
+	/* read current_lsb value (uA/bit) */
+	ret = of_property_read_u16(client->dev.of_node, "current-lsb", &current_lsb);
+	if (ret < 0 || !current_lsb) {
+		dev_err(&client->dev, "Unable to read current_lsb or value is 0, default value %d uA/bit is used.\n",
+			INA233_CURRENT_LSB_DEFAULT);
+		current_lsb = INA233_CURRENT_LSB_DEFAULT;
+	}
+
+	/* calculate current coefficient */
+	m = current_lsb;
+	ret = calculate_coef(&m, &R, false);
+	if (ret < 0) {
+		dev_err(&client->dev, "Calculate_coef error\n");
+	} else {
+		ina233_info.m[PSC_CURRENT_OUT] = m;
+		ina233_info.R[PSC_CURRENT_OUT] = R;
+	}
+
+	/* calculate power coefficient */
+	m = current_lsb;
+	ret = calculate_coef(&m, &R, true);
+	if (ret < 0) {
+		dev_err(&client->dev, "Calculate_coef error\n");
+	} else {
+		ina233_info.m[PSC_POWER] = m;
+		ina233_info.R[PSC_POWER] = R;
+	}
+
+	/* write MFR_CALIBRATION register, Apply formula from spec with unit scaling. */
+	calibration = div_u64((u64)5120000000, (u64)rshunt * current_lsb);
+	if (calibration <= 0) {
+		dev_err(&client->dev, "Calibration error\n");
+		return -1;
+	}
+	ret = i2c_smbus_write_word_data(client, MFR_CALIBRATION, calibration);
+	if (ret < 0) {
+		dev_err(&client->dev, "Unable to write calibration\n");
+		return ret;
+	}
+
+	dev_info(&client->dev, "power monitor %s (Rshunt = %u uOhm, Current_LSB = %u uA/bit)\n",
+		 client->name, rshunt, current_lsb);
+
+	return pmbus_do_probe(client, &ina233_info);
+}
+
+static const struct i2c_device_id ina233_id[] = {
+	{"ina233", 0},
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ina233_id);
+
+static const struct of_device_id __maybe_unused ina233_of_match[] = {
+	{ .compatible = "ti,ina233" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, ina233_of_match);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver ina233_driver = {
+	.driver = {
+		   .name = "ina233",
+		   .of_match_table = of_match_ptr(ina233_of_match),
+	},
+	.probe = ina233_probe,
+	.id_table = ina233_id,
+};
+
+module_i2c_driver(ina233_driver);
+
+MODULE_AUTHOR("Leo Yang <Leo-Yang@quantatw.com>");
+MODULE_DESCRIPTION("PMBus driver for INA233 and compatible chips");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("PMBUS");