-----Original Message-----Add a driver to support ltc4286 chip
From: Guenter Roeck <groeck7@xxxxxxxxx> On Behalf Of Guenter Roeck
Sent: Monday, April 24, 2023 10:14 PM
To: Delphine_CC_Chiu/WYHQ/Wiwynn <Delphine_CC_Chiu@xxxxxxxxxx>
Cc: patrick@xxxxxxxxx; Jean Delvare <jdelvare@xxxxxxxx>; Rob Herring
<robh+dt@xxxxxxxxxx>; Krzysztof Kozlowski
<krzysztof.kozlowski+dt@xxxxxxxxxx>; linux-i2c@xxxxxxxxxxxxxxx;
linux-hwmon@xxxxxxxxxxxxxxx; devicetree@xxxxxxxxxxxxxxx;
linux-kernel@xxxxxxxxxxxxxxx
Subject: Re: [PATCH v1 2/2] hwmon: pmbus: Add ltc4286 driver
Security Reminder: Please be aware that this email is sent by an external
sender.
On Mon, Apr 24, 2023 at 06:13:50PM +0800, Delphine CC Chiu wrote:
Add support for ltc4286 driver
The patch does not add support for a driver, it adds support for a chip.
Documentation is in patch one ([PATCH v1 1/2] dt-bindings: hwmon: Add lltc ltc4286 driver bindings)
Signed-off-by: Delphine CC Chiu <Delphine_CC_Chiu@xxxxxxxxxx>
---
drivers/hwmon/pmbus/Kconfig | 9 +++
drivers/hwmon/pmbus/Makefile | 1 +
drivers/hwmon/pmbus/ltc4286.c | 142
++++++++++++++++++++++++++++++++++
Documentation is missing.
We will revise to "Analog Devices LTC4286"
3 files changed, 152 insertions(+)
create mode 100644 drivers/hwmon/pmbus/ltc4286.c
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
index 59d9a7430499..1230d910d681 100644
--- a/drivers/hwmon/pmbus/Kconfig
+++ b/drivers/hwmon/pmbus/Kconfig
@@ -218,6 +218,15 @@ config SENSORS_LTC3815
This driver can also be built as a module. If so, the module will
be called ltc3815.
+config SENSORS_LTC4286
+ bool "Linear Technologies LTC4286"
Analog Devices ?
We will remove the copyright declaration as it was false reference from other drivers
+ help100644
+ If you say yes here you get hardware monitoring support for Linear
+ Technology LTC4286.
+
+ This driver can also be built as a module. If so, the module will
+ be called ltc4286.
+
config SENSORS_MAX15301
tristate "Maxim MAX15301"
help
diff --git a/drivers/hwmon/pmbus/Makefile
b/drivers/hwmon/pmbus/Makefile index 3ae019916267..540265539580
--- a/drivers/hwmon/pmbus/Makefilelm25066.o
+++ b/drivers/hwmon/pmbus/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_SENSORS_LM25066) +=
obj-$(CONFIG_SENSORS_LT7182S) += lt7182s.o
obj-$(CONFIG_SENSORS_LTC2978) += ltc2978.o
obj-$(CONFIG_SENSORS_LTC3815) += ltc3815.o
+obj-$(CONFIG_SENSORS_LTC4286) += ltc4286.o
obj-$(CONFIG_SENSORS_MAX15301) += max15301.o
obj-$(CONFIG_SENSORS_MAX16064) += max16064.o
obj-$(CONFIG_SENSORS_MAX16601) += max16601.o
diff --git a/drivers/hwmon/pmbus/ltc4286.c
b/drivers/hwmon/pmbus/ltc4286.c new file mode 100644 index
000000000000..474f4ec9107c
--- /dev/null
+++ b/drivers/hwmon/pmbus/ltc4286.c
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Hardware monitoring driver for LTC4286 Hot-Swap Controller
+ *
+ * Copyright (c) 2023 Linear Technology
Really ?
Chip vendor doesn't support this driver, so we implement it for our own use and contribute it as Wiwynn is a system manufacturer, our server products use this chip.
We will revise to /* LTC4286 register */
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pmbus.h>
+#include "pmbus.h"
+
+// LTC4286 register
Please no C++ comments in the code.
We will revise to #define LTC4286_MFR_CONFIG1 0xF2
+#define LTC4286_MFR_CONFIG1 (0xF2)
Unnecessary ( )
We will revise to below.
+
+// LTC4286 configuration
+#define VRANGE_SELECT (1 << 1)
#define<space>DEFINE<tab>value, please. Also, please use BIT() macros where
appropriate.
#define VRANGE_SELECT_BIT BIT(1)
It has been announced on Analog Devices website.+
+#define LTC4286_MFR_ID_SIZE 3
+
+enum chips { ltc4286, ltc4287 };
There is no LTC4287 according to information available in public.
It has not even be announced.
Besides, the above enum is not really used anywhere and therefore has zero
value. Maybe the LTC4287 is not yet released. Even then, there is no value
listing it here because its parameters seem to be identical to LTC4286.
Please refer to this link: https://www.analog.com/en/products/ltc2487.html#product-overview
enum chips { ltc4286 = 0, ltc4287 };
Use in v1 line 118 to list chip index instead of hardcoding
We will add comments as below
+
+static struct pmbus_driver_info ltc4286_info = {
+ .pages = 1,
+ .format[PSC_VOLTAGE_IN] = direct,
+ .format[PSC_VOLTAGE_OUT] = direct,
+ .format[PSC_CURRENT_OUT] = direct,
+ .format[PSC_POWER] = direct,
+ .format[PSC_TEMPERATURE] = direct,
+ .m[PSC_VOLTAGE_IN] = 32,
+ .b[PSC_VOLTAGE_IN] = 0,
+ .R[PSC_VOLTAGE_IN] = 1,
+ .m[PSC_VOLTAGE_OUT] = 32,
+ .b[PSC_VOLTAGE_OUT] = 0,
+ .R[PSC_VOLTAGE_OUT] = 1,
+ .m[PSC_CURRENT_OUT] = 1024,
+ .b[PSC_CURRENT_OUT] = 0,
+ .R[PSC_CURRENT_OUT] = 3 - 6,
This needs explanation.
/* Initialize the MBR as default settings which is referred to LTC4286 datasheet(March 22, 2022 version) table 3 page 16 */
We will add comments as below
+ .m[PSC_POWER] = 1,
+ .b[PSC_POWER] = 0,
+ .R[PSC_POWER] = 4 - 6,
This needs explanation.
/* To support small shunt resistor value */
We will revise to .b[PSC_TEMPERATURE] = 273,
+ .m[PSC_TEMPERATURE] = 1,
+ .b[PSC_TEMPERATURE] = 273.15,
Assigning a float to an int doesn't make much sense.
However the value for this MBR is 273.15 in datasheet
We use 273 due to pmbus code limitation
We will add status registers here
+ .R[PSC_TEMPERATURE] = 0,PMBUS_HAVE_IOUT |
+ .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT |
+ PMBUS_HAVE_PIN | PMBUS_HAVE_TEMP,
The chip does have a number of status registers.
We will drop it
+};block_buffer);
+
+static int ltc4286_probe(struct i2c_client *client,
+ const struct i2c_device_id *id) {
+ int ret;
+ u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1];
+ struct device *dev = &client->dev;
+ struct pmbus_driver_info *info;
+ u32 rsense;
+
+ ret = i2c_smbus_read_block_data(client, PMBUS_MFR_ID,
+ if (ret < 0) {
+ dev_err(&client->dev, "failed to read manufacturer
+ id\n");
Kind of pointless to declare a local 'dev' variable and not use it.
We will revise to
+ return ret;
+ }
+
+ /* Refer to ltc4286 datasheet page 20
+ * the default manufacturer id is LTC
Why "default" ?
/*
* Refer to ltc4286 datasheet page 20
* the manufacturer id is LTC
*/
We will revise to
+ */
Please use standard multi-line comments.
/*
* Refer to ltc4286 datasheet page 20
* the manufacturer id is LTC
*/
We will add comaprision here.
+ if (ret != LTC4286_MFR_ID_SIZE ||block_buffer);
+ strncmp(block_buffer, "LTC", LTC4286_MFR_ID_SIZE)) {
+ dev_err(&client->dev, "unsupported manufacturer id\n");
+ return -ENODEV;
+ }
+
+ ret = i2c_smbus_read_block_data(client, PMBUS_MFR_MODEL,
+ if (ret < 0) {model\n");
+ dev_err(&client->dev, "failed to read manufacturer
+ return ret;
+ }
Why read the model if you don't do anything with it ?
for (mid = ltc4286_id; mid->name[0]; mid++) {
if (!strncasecmp(mid->name, block_buffer, strlen(mid->name)))
break;
}
After confirming with vendor, they said there is no default rsesne for this chip
+"rsense-micro-ohms",
+ ret = of_property_read_u32(client->dev.of_node,
+ &rsense);
+ if (ret < 0)
+ return ret;
+
+ if (rsense == 0)
+ return -EINVAL;
+
There should be a default for systems not supporting devicetree.
The value for rsense depends on hardware engineer in each manufacturer
ret = i2c_smbus_write_word_data(client, LTC4286_MFR_CONFIG1, ret);
+ info = <c4286_info;LTC4286_MFR_CONFIG1);
+
+ /* Default of VRANGE_SELECT = 1 */
+ if (device_property_read_bool(dev, "vrange_select_25p6")) {
+ /* Setup MFR1 CONFIG register bit 1 VRANGE_SELECT */
+ ret = i2c_smbus_read_word_data(client,
+ if (ret < 0) {configuration one\n");
+ dev_err(&client->dev,
+ "failed to read manufacturer
+ return ret;LTC4286_MFR_CONFIG1,
+ }
+
+ ret &= ~VRANGE_SELECT; /* VRANGE_SELECT = 0, 25.6V */
+ i2c_smbus_write_word_data(client,
+ ret);
Error check missing.
if (ret < 0) {
dev_err(&client->dev, "failed to set vrange\n");
return ret;
}
The MBR values are based on hardware design, so it must be set in initial stage
+
+ info->m[PSC_VOLTAGE_IN] = 128;
+ info->m[PSC_VOLTAGE_OUT] = 128;
+ info->m[PSC_POWER] = 4 * rsense;
+ } else {
+ info->m[PSC_POWER] = rsense;
This just takes the current configuration, and assumes it is the default.
That may not be correct. The chip may have been configured by the BIOS, or
manually.
If there are more than one LTC4286 or LTC4287 chips, user can add the configuration for different chips in dts file
+ }
+
The code assumes that there is only a single chip in the system, or that the
configuration of all chips is identical. This is not necessarily correct.
So do you recommend us to put this enum (enum chips { ltc4286, ltc4287 };) here?
+ info->m[PSC_CURRENT_OUT] = 1024 * rsense;ltc4287
+
+ return pmbus_do_probe(client, info); }
+
+static const struct i2c_device_id ltc4286_id[] = { { "ltc4286", ltc4286 },
+ { "ltc4287",
+},
Even if LTC4287 existed, assigning the ID here ...
So do you recommend us to not put this enum (enum chips { ltc4286, ltc4287 };) here?
+ {} };
+MODULE_DEVICE_TABLE(i2c, ltc4286_id);
+
+static const struct of_device_id ltc4286_of_match[] = {
+ { .compatible = "lltc,ltc4286" },
+ { .compatible = "lltc,ltc4287" },
... but not here defeats having it in the first place.
In v1 line 120
+ {}
+};
MODULE_DEVOCE_TABLE() missing.
We will drop it.
+
+/* This is the driver that will be inserted */
Useless comment
+static struct i2c_driver ltc4286_driver = {<Delphine_CC_Chiu@xxxxxxxxxx>");
+ .driver = {
+ .name = "ltc4286",
+ .of_match_table = ltc4286_of_match,
+ },
+ .probe = ltc4286_probe,
+ .id_table = ltc4286_id,
+};
+
+module_i2c_driver(ltc4286_driver);
+
+MODULE_AUTHOR("Delphine CC Chiu
+MODULE_DESCRIPTION("PMBUS driver for LTC4286 and compatibles");
+MODULE_LICENSE("GPL");
--
2.17.1