From: Delphine CC Chiu <Delphine_CC_Chiu@Wiwynn.com>
To: patrick@stwcx.xyz, Jean Delvare <jdelvare@suse.com>,
Guenter Roeck <linux@roeck-us.net>,
Jonathan Corbet <corbet@lwn.net>,
Delphine CC Chiu <Delphine_CC_Chiu@Wiwynn.com>
Cc: Rob Herring <robh+dt@kernel.org>,
Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
Conor Dooley <conor+dt@kernel.org>,
linux-i2c@vger.kernel.org, linux-hwmon@vger.kernel.org,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-doc@vger.kernel.org
Subject: [PATCH v3 2/2] hwmon: pmbus: Add ltc4286 driver
Date: Tue, 31 Oct 2023 15:21:22 +0800 [thread overview]
Message-ID: <20231031072124.201181-3-Delphine_CC_Chiu@Wiwynn.com> (raw)
In-Reply-To: <20231031072124.201181-1-Delphine_CC_Chiu@Wiwynn.com>
Add a driver to support ltc4286 chip
Signed-off-by: Delphine CC Chiu <Delphine_CC_Chiu@Wiwynn.com>
Changelog:
v3 - Use dev_err_probe() instead of dev_err()
- The VRANGE_SELECT bit only be written if it actually changed
- Avoid the info pointer being overwritten
- Check the MBR value range to avoid overflow
- Revise ltc4286.rst to corrcet description
v2 - Revise Linear Technologies LTC4286 to
Analog Devices LTC4286 in Kconfig
- Add more description for this driver in Kconfig
- Add some comments for MBR setting in ltc4286.c
- Add ltc4286.rst
---
Documentation/hwmon/ltc4286.rst | 95 +++++++++++++++++
drivers/hwmon/pmbus/Kconfig | 9 ++
drivers/hwmon/pmbus/Makefile | 1 +
drivers/hwmon/pmbus/ltc4286.c | 178 ++++++++++++++++++++++++++++++++
4 files changed, 283 insertions(+)
create mode 100644 Documentation/hwmon/ltc4286.rst
create mode 100644 drivers/hwmon/pmbus/ltc4286.c
diff --git a/Documentation/hwmon/ltc4286.rst b/Documentation/hwmon/ltc4286.rst
new file mode 100644
index 000000000000..2cd149676d86
--- /dev/null
+++ b/Documentation/hwmon/ltc4286.rst
@@ -0,0 +1,95 @@
+.. SPDX-License-Identifier: GPL-2.0-or-later
+
+Kernel driver ltc4286
+=====================
+
+Supported chips:
+
+ * Analog Devices LTC4286
+
+ Prefix: 'ltc4286'
+
+ Addresses scanned: -
+
+ Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ltc4286.pdf
+
+ * Analog Devices LTC4287
+
+ Prefix: 'ltc4287'
+
+ Addresses scanned: -
+
+ Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ltc4287.pdf
+
+Author: Delphine CC Chiu <Delphine_CC_Chiu@Wiwynn.com>
+
+
+Description
+-----------
+
+This driver supports hardware monitoring for Analog Devices LTC4286
+and LTC4287 Hot-Swap Controller and Digital Power Monitors.
+
+LTC4286 and LTC4287 are hot-swap controllers that allow a circuit board
+to be removed from or inserted into a live backplane. They also feature
+current and voltage readback via an integrated 12 bit analog-to-digital
+converter (ADC), accessed using a PMBus interface.
+
+The driver is a client driver to the core PMBus driver. Please see
+Documentation/hwmon/pmbus.rst for details on PMBus client drivers.
+
+
+Usage Notes
+-----------
+
+This driver does not auto-detect devices. You will have to instantiate the
+devices explicitly. Please see Documentation/i2c/instantiating-devices.rst for
+details.
+
+The shunt value in micro-ohms can be set via device tree at compile-time. Please
+refer to the Documentation/devicetree/bindings/hwmon/lltc,ltc4286.yaml for bindings
+if the device tree is used.
+
+
+Platform data support
+---------------------
+
+The driver supports standard PMBus driver platform data. Please see
+Documentation/hwmon/pmbus.rst for details.
+
+
+Sysfs entries
+-------------
+
+The following attributes are supported. Limits are read-write, history reset
+attributes are write-only, all other attributes are read-only.
+
+======================= =======================================================
+in1_label "vin"
+in1_input Measured voltage.
+in1_alarm Input voltage alarm.
+in1_min Minimum input voltage.
+in1_max Maximum input voltage.
+
+in2_label "vout1"
+in2_input Measured voltage.
+in2_alarm Output voltage alarm.
+in2_min Minimum output voltage.
+in2_max Maximum output voltage.
+
+curr1_label "iout1"
+curr1_input Measured current.
+curr1_alarm Output current alarm.
+curr1_max Maximum current.
+
+power1_label "pin"
+power1_input Input power.
+power1_alarm Input power alarm.
+power1_max Maximum poewr.
+
+temp1_input Chip temperature.
+temp1_min Minimum chip temperature.
+temp1_max Maximum chip temperature.
+temp1_crit Critical chip temperature.
+temp1_alarm Chip temperature alarm.
+======================= =======================================================
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
index b4e93bd5835e..f2b53e8abc3c 100644
--- a/drivers/hwmon/pmbus/Kconfig
+++ b/drivers/hwmon/pmbus/Kconfig
@@ -226,6 +226,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 "Analog Devices LTC4286"
+ help
+ LTC4286 is an integrated solution for hot swap applications that
+ allows a board to be safely inserted and removed from a live
+ backplane.
+ This chip could be used to monitor voltage, current, ...etc.
+ If you say yes here you get hardware monitoring support for Analog
+ Devices LTC4286.
config SENSORS_MAX15301
tristate "Maxim MAX15301"
diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile
index 84ee960a6c2d..94e28f6d6a61 100644
--- a/drivers/hwmon/pmbus/Makefile
+++ b/drivers/hwmon/pmbus/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_SENSORS_LM25066) += lm25066.o
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..042d3af99489
--- /dev/null
+++ b/drivers/hwmon/pmbus/ltc4286.c
@@ -0,0 +1,178 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#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 */
+#define LTC4286_MFR_CONFIG1 0xF2
+
+/* LTC4286 configuration */
+#define VRANGE_SELECT_BIT BIT(1)
+
+#define LTC4286_MFR_ID_SIZE 3
+#define VRANGE_25P6 0
+
+enum chips { ltc4286, ltc4287 };
+
+/*
+ * Initialize the MBR as default settings which is referred to LTC4286 datasheet
+ * (March 22, 2022 version) table 3 page 16
+ */
+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,
+ /*
+ * The rsense value used in MBR formula in LTC4286 datasheet should be ohm unit.
+ * However, the rsense value that user input is mirco ohm.
+ * Thus, the MBR setting which involves rsense should be shifted by 6 digits.
+ */
+ .R[PSC_CURRENT_OUT] = 3 - 6,
+ .m[PSC_POWER] = 1,
+ .b[PSC_POWER] = 0,
+ /*
+ * The rsense value used in MBR formula in LTC4286 datasheet should be ohm unit.
+ * However, the rsense value that user input is mirco ohm.
+ * Thus, the MBR setting which involves rsense should be shifted by 6 digits.
+ */
+ .R[PSC_POWER] = 4 - 6,
+ .m[PSC_TEMPERATURE] = 1,
+ .b[PSC_TEMPERATURE] = 273,
+ .R[PSC_TEMPERATURE] = 0,
+ .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT |
+ PMBUS_HAVE_PIN | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_VOUT |
+ PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_STATUS_TEMP,
+};
+
+static const struct i2c_device_id ltc4286_id[] = { { "ltc4286", ltc4286 },
+ { "ltc4287", ltc4287 },
+ {} };
+MODULE_DEVICE_TABLE(i2c, ltc4286_id);
+
+static int ltc4286_probe(struct i2c_client *client)
+{
+ int ret;
+ const struct i2c_device_id *mid;
+ u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1];
+ struct pmbus_driver_info *info;
+ u32 rsense;
+
+ ret = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, block_buffer);
+ if (ret < 0) {
+ return dev_err_probe(&client->dev, ret,
+ "Failed to read manufacturer id\n");
+ }
+
+ /*
+ * Refer to ltc4286 datasheet page 20
+ * the manufacturer id is LTC
+ */
+ if (ret != LTC4286_MFR_ID_SIZE ||
+ strncmp(block_buffer, "LTC", LTC4286_MFR_ID_SIZE)) {
+ return dev_err_probe(&client->dev, ret,
+ "Manufacturer id mismatch\n");
+ }
+
+ ret = i2c_smbus_read_block_data(client, PMBUS_MFR_MODEL, block_buffer);
+ if (ret < 0) {
+ return dev_err_probe(&client->dev, ret,
+ "Failed to read manufacturer model\n");
+ }
+
+ for (mid = ltc4286_id; mid->name[0]; mid++) {
+ if (!strncasecmp(mid->name, block_buffer, strlen(mid->name)))
+ break;
+ }
+ if (!mid->name[0])
+ return dev_err_probe(&client->dev, -ENODEV,
+ "Unsupported device\n");
+
+ ret = of_property_read_u32(client->dev.of_node,
+ "shunt-resistor-micro-ohms", &rsense);
+ if (ret < 0)
+ return ret;
+
+ if (rsense == 0)
+ return -EINVAL;
+
+ info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+ memcpy(info, <c4286_info, sizeof(*info));
+
+ /* Default of VRANGE_SELECT = 1, 102.4V */
+ if (device_property_read_bool(&client->dev, "adi,vrange-low-enable")) {
+ /* Setup MFR1 CONFIG register bit 1 VRANGE_SELECT */
+ ret = i2c_smbus_read_word_data(client, LTC4286_MFR_CONFIG1);
+ if (ret < 0) {
+ return dev_err_probe(
+ &client->dev, ret,
+ "Failed to read manufacturer configuration one\n");
+ }
+
+ if ((ret & VRANGE_SELECT_BIT) != VRANGE_25P6) {
+ ret &= ~VRANGE_SELECT_BIT; /* VRANGE_SELECT = 0, 25.6V */
+ ret = i2c_smbus_write_word_data(
+ client, LTC4286_MFR_CONFIG1, ret);
+ if (ret < 0)
+ return dev_err_probe(&client->dev, ret,
+ "Failed to set vrange\n");
+ }
+
+ info->m[PSC_VOLTAGE_IN] = 128;
+ info->m[PSC_VOLTAGE_OUT] = 128;
+ info->m[PSC_POWER] = 4 * rsense;
+ if (info->m[PSC_POWER] > INT_MAX)
+ return dev_err_probe(&client->dev, -ERANGE,
+ "Power coefficient overflow\n");
+ } else {
+ info->m[PSC_POWER] = rsense;
+ if (info->m[PSC_POWER] > INT_MAX)
+ return dev_err_probe(&client->dev, -ERANGE,
+ "Power coefficient overflow\n");
+ }
+
+ info->m[PSC_CURRENT_OUT] = 1024 * rsense;
+ if (info->m[PSC_CURRENT_OUT] > INT_MAX)
+ return dev_err_probe(&client->dev, -ERANGE,
+ "Current coefficient overflow\n");
+
+ return pmbus_do_probe(client, info);
+}
+
+static const struct of_device_id ltc4286_of_match[] = {
+ { .compatible = "lltc,ltc4286" },
+ { .compatible = "lltc,ltc4287" },
+ {}
+};
+
+static struct i2c_driver ltc4286_driver = {
+ .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 <Delphine_CC_Chiu@wiwynn.com>");
+MODULE_DESCRIPTION("PMBUS driver for LTC4286 and compatibles");
+MODULE_LICENSE("GPL");
--
2.25.1
next prev parent reply other threads:[~2023-10-31 7:21 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-10-31 7:21 [PATCH v3 0/2] LTC4286 and LTC4287 driver support Delphine CC Chiu
2023-10-31 7:21 ` [PATCH v3 1/2] dt-bindings: hwmon: Add lltc ltc4286 driver bindings Delphine CC Chiu
2023-10-31 17:06 ` Conor Dooley
2023-10-31 17:11 ` Guenter Roeck
2023-11-07 3:12 ` Delphine_CC_Chiu/WYHQ/Wiwynn
2023-10-31 7:21 ` Delphine CC Chiu [this message]
2023-10-31 18:09 ` [PATCH v3 2/2] hwmon: pmbus: Add ltc4286 driver Guenter Roeck
2023-11-07 3:21 ` Delphine_CC_Chiu/WYHQ/Wiwynn
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20231031072124.201181-3-Delphine_CC_Chiu@Wiwynn.com \
--to=delphine_cc_chiu@wiwynn.com \
--cc=conor+dt@kernel.org \
--cc=corbet@lwn.net \
--cc=devicetree@vger.kernel.org \
--cc=jdelvare@suse.com \
--cc=krzysztof.kozlowski+dt@linaro.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-hwmon@vger.kernel.org \
--cc=linux-i2c@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@roeck-us.net \
--cc=patrick@stwcx.xyz \
--cc=robh+dt@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.