[PATCH] hwmon: (pmbus) Add support for 2nd Gen Renesas digital multiphase

From: Grant Peltier
Date: Fri Feb 28 2020 - 16:24:28 EST


Add a driver to support 2nd generation Renesas digital multiphase power
regulators. The driver is meant to support a large family of part
numbers spanning isl682xx, isl692xx, and some raa228/9 part designations.

Signed-off-by: Grant Peltier <grantpeltier93@xxxxxxxxx>
---
drivers/hwmon/pmbus/Kconfig | 9 +
drivers/hwmon/pmbus/Makefile | 1 +
drivers/hwmon/pmbus/isl692xx.c | 352 +++++++++++++++++++++++++++++++++
3 files changed, 362 insertions(+)
create mode 100644 drivers/hwmon/pmbus/isl692xx.c

diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
index a9ea06204767..fbe7bbc8b37c 100644
--- a/drivers/hwmon/pmbus/Kconfig
+++ b/drivers/hwmon/pmbus/Kconfig
@@ -100,6 +100,15 @@ config SENSORS_ISL68137
This driver can also be built as a module. If so, the module will
be called isl68137.

+config SENSORS_ISL692XX
+ tristate "Renesas 2nd Gen Digital Multiphase"
+ help
+ If you say yes here you get hardware monitoring support for Renesas
+ 2nd Generation Digital Multiphase power regulators.
+
+ This driver can also be built as a module. If so, the module will
+ be called isl692xx.
+
config SENSORS_LM25066
tristate "National Semiconductor LM25066 and compatibles"
help
diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile
index 5feb45806123..bf1ea99a6120 100644
--- a/drivers/hwmon/pmbus/Makefile
+++ b/drivers/hwmon/pmbus/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_SENSORS_IR35221) += ir35221.o
obj-$(CONFIG_SENSORS_IR38064) += ir38064.o
obj-$(CONFIG_SENSORS_IRPS5401) += irps5401.o
obj-$(CONFIG_SENSORS_ISL68137) += isl68137.o
+obj-$(CONFIG_SENSORS_ISL692XX) += isl692xx.o
obj-$(CONFIG_SENSORS_LM25066) += lm25066.o
obj-$(CONFIG_SENSORS_LTC2978) += ltc2978.o
obj-$(CONFIG_SENSORS_LTC3815) += ltc3815.o
diff --git a/drivers/hwmon/pmbus/isl692xx.c b/drivers/hwmon/pmbus/isl692xx.c
new file mode 100644
index 000000000000..26f3d90a7ddc
--- /dev/null
+++ b/drivers/hwmon/pmbus/isl692xx.c
@@ -0,0 +1,352 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Hardware monitoring driver for Renesas Gen 2 Digital Multiphase Devices
+ *
+ * Copyright (c) 2020 Renesas Electronics America
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+
+#include "pmbus.h"
+
+#define ISL692XX_READ_VMON 0xc8
+
+enum parts {
+ isl68220,
+ isl68221,
+ isl68222,
+ isl68223,
+ isl68224,
+ isl68225,
+ isl68226,
+ isl68227,
+ isl68229,
+ isl68233,
+ isl68239,
+ isl69222,
+ isl69223,
+ isl69224,
+ isl69225,
+ isl69227,
+ isl69228,
+ isl69234,
+ isl69236,
+ isl69239,
+ isl69242,
+ isl69243,
+ isl69247,
+ isl69248,
+ isl69254,
+ isl69255,
+ isl69256,
+ isl69259,
+ isl69260,
+ isl69268,
+ isl69269,
+ isl69298,
+ raa228000,
+ raa228004,
+ raa228006,
+ raa228228,
+ raa229001,
+ raa229004,
+};
+
+enum rail_configs { high_voltage, one_rail, two_rail, three_rail };
+
+static const struct i2c_device_id isl692xx_id[] = {
+ { "isl68220", isl68220 },
+ { "isl68221", isl68221 },
+ { "isl68222", isl68222 },
+ { "isl68223", isl68223 },
+ { "isl68224", isl68224 },
+ { "isl68225", isl68225 },
+ { "isl68226", isl68226 },
+ { "isl68227", isl68227 },
+ { "isl68229", isl68229 },
+ { "isl68233", isl68233 },
+ { "isl68239", isl68239 },
+ { "isl69222", isl69222 },
+ { "isl69223", isl69223 },
+ { "isl69224", isl69224 },
+ { "isl69225", isl69225 },
+ { "isl69227", isl69227 },
+ { "isl69228", isl69228 },
+ { "isl69234", isl69234 },
+ { "isl69236", isl69236 },
+ { "isl69239", isl69239 },
+ { "isl69242", isl69242 },
+ { "isl69243", isl69243 },
+ { "isl69247", isl69247 },
+ { "isl69248", isl69248 },
+ { "isl69254", isl69254 },
+ { "isl69255", isl69255 },
+ { "isl69256", isl69256 },
+ { "isl69259", isl69259 },
+ { "isl69260", isl69260 },
+ { "isl69268", isl69268 },
+ { "isl69269", isl69269 },
+ { "isl69298", isl69298 },
+ { "raa228000", raa228000 },
+ { "raa228004", raa228004 },
+ { "raa228006", raa228006 },
+ { "raa228228", raa228228 },
+ { "raa229001", raa229001 },
+ { "raa229004", raa229004 },
+ { },
+};
+
+MODULE_DEVICE_TABLE(i2c, isl692xx_id);
+
+static int isl692xx_read_word_data(struct i2c_client *client, int page, int reg)
+{
+ int ret;
+
+ switch (reg) {
+ case PMBUS_VIRT_READ_VMON:
+ ret = pmbus_read_word_data(client, page, ISL692XX_READ_VMON);
+ break;
+ default:
+ ret = -ENODATA;
+ break;
+ }
+
+ return ret;
+}
+
+static struct pmbus_driver_info isl692xx_info[] = {
+ [high_voltage] = {
+ .pages = 1,
+ .format[PSC_VOLTAGE_IN] = direct,
+ .format[PSC_VOLTAGE_OUT] = direct,
+ .format[PSC_CURRENT_IN] = direct,
+ .format[PSC_CURRENT_OUT] = direct,
+ .format[PSC_POWER] = direct,
+ .format[PSC_TEMPERATURE] = direct,
+ .m[PSC_VOLTAGE_IN] = 1,
+ .b[PSC_VOLTAGE_IN] = 0,
+ .R[PSC_VOLTAGE_IN] = 1,
+ .m[PSC_VOLTAGE_OUT] = 2,
+ .b[PSC_VOLTAGE_OUT] = 0,
+ .R[PSC_VOLTAGE_OUT] = 2,
+ .m[PSC_CURRENT_IN] = 2,
+ .b[PSC_CURRENT_IN] = 0,
+ .R[PSC_CURRENT_IN] = 2,
+ .m[PSC_CURRENT_OUT] = 1,
+ .b[PSC_CURRENT_OUT] = 0,
+ .R[PSC_CURRENT_OUT] = 1,
+ .m[PSC_POWER] = 2,
+ .b[PSC_POWER] = 0,
+ .R[PSC_POWER] = -1,
+ .m[PSC_TEMPERATURE] = 1,
+ .b[PSC_TEMPERATURE] = 0,
+ .R[PSC_TEMPERATURE] = 0,
+ .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_IIN |
+ PMBUS_HAVE_IOUT | PMBUS_HAVE_PIN | PMBUS_HAVE_POUT |
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_TEMP3 |
+ PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT |
+ PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP |
+ PMBUS_HAVE_VMON,
+ .read_word_data = isl692xx_read_word_data,
+ },
+ [one_rail] = {
+ .pages = 1,
+ .format[PSC_VOLTAGE_IN] = direct,
+ .format[PSC_VOLTAGE_OUT] = direct,
+ .format[PSC_CURRENT_IN] = direct,
+ .format[PSC_CURRENT_OUT] = direct,
+ .format[PSC_POWER] = direct,
+ .format[PSC_TEMPERATURE] = direct,
+ .m[PSC_VOLTAGE_IN] = 1,
+ .b[PSC_VOLTAGE_IN] = 0,
+ .R[PSC_VOLTAGE_IN] = 2,
+ .m[PSC_VOLTAGE_OUT] = 1,
+ .b[PSC_VOLTAGE_OUT] = 0,
+ .R[PSC_VOLTAGE_OUT] = 3,
+ .m[PSC_CURRENT_IN] = 1,
+ .b[PSC_CURRENT_IN] = 0,
+ .R[PSC_CURRENT_IN] = 2,
+ .m[PSC_CURRENT_OUT] = 1,
+ .b[PSC_CURRENT_OUT] = 0,
+ .R[PSC_CURRENT_OUT] = 1,
+ .m[PSC_POWER] = 1,
+ .b[PSC_POWER] = 0,
+ .R[PSC_POWER] = 0,
+ .m[PSC_TEMPERATURE] = 1,
+ .b[PSC_TEMPERATURE] = 0,
+ .R[PSC_TEMPERATURE] = 0,
+ .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_IIN |
+ PMBUS_HAVE_IOUT | PMBUS_HAVE_PIN | PMBUS_HAVE_POUT |
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_TEMP3 |
+ PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT |
+ PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP |
+ PMBUS_HAVE_VMON,
+ .read_word_data = isl692xx_read_word_data,
+ },
+ [two_rail] = {
+ .pages = 2,
+ .format[PSC_VOLTAGE_IN] = direct,
+ .format[PSC_VOLTAGE_OUT] = direct,
+ .format[PSC_CURRENT_IN] = direct,
+ .format[PSC_CURRENT_OUT] = direct,
+ .format[PSC_POWER] = direct,
+ .format[PSC_TEMPERATURE] = direct,
+ .m[PSC_VOLTAGE_IN] = 1,
+ .b[PSC_VOLTAGE_IN] = 0,
+ .R[PSC_VOLTAGE_IN] = 2,
+ .m[PSC_VOLTAGE_OUT] = 1,
+ .b[PSC_VOLTAGE_OUT] = 0,
+ .R[PSC_VOLTAGE_OUT] = 3,
+ .m[PSC_CURRENT_IN] = 1,
+ .b[PSC_CURRENT_IN] = 0,
+ .R[PSC_CURRENT_IN] = 2,
+ .m[PSC_CURRENT_OUT] = 1,
+ .b[PSC_CURRENT_OUT] = 0,
+ .R[PSC_CURRENT_OUT] = 1,
+ .m[PSC_POWER] = 1,
+ .b[PSC_POWER] = 0,
+ .R[PSC_POWER] = 0,
+ .m[PSC_TEMPERATURE] = 1,
+ .b[PSC_TEMPERATURE] = 0,
+ .R[PSC_TEMPERATURE] = 0,
+ .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_IIN |
+ PMBUS_HAVE_IOUT | PMBUS_HAVE_PIN | PMBUS_HAVE_POUT |
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_TEMP3 |
+ PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT |
+ PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP |
+ PMBUS_HAVE_VMON,
+ .func[1] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_IIN |
+ PMBUS_HAVE_IOUT | PMBUS_HAVE_PIN | PMBUS_HAVE_POUT |
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_TEMP3 |
+ PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT |
+ PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP |
+ PMBUS_HAVE_VMON,
+ .read_word_data = isl692xx_read_word_data,
+ },
+ [three_rail] = {
+ .pages = 3,
+ .format[PSC_VOLTAGE_IN] = direct,
+ .format[PSC_VOLTAGE_OUT] = direct,
+ .format[PSC_CURRENT_IN] = direct,
+ .format[PSC_CURRENT_OUT] = direct,
+ .format[PSC_POWER] = direct,
+ .format[PSC_TEMPERATURE] = direct,
+ .m[PSC_VOLTAGE_IN] = 1,
+ .b[PSC_VOLTAGE_IN] = 0,
+ .R[PSC_VOLTAGE_IN] = 2,
+ .m[PSC_VOLTAGE_OUT] = 1,
+ .b[PSC_VOLTAGE_OUT] = 0,
+ .R[PSC_VOLTAGE_OUT] = 3,
+ .m[PSC_CURRENT_IN] = 1,
+ .b[PSC_CURRENT_IN] = 0,
+ .R[PSC_CURRENT_IN] = 2,
+ .m[PSC_CURRENT_OUT] = 1,
+ .b[PSC_CURRENT_OUT] = 0,
+ .R[PSC_CURRENT_OUT] = 1,
+ .m[PSC_POWER] = 1,
+ .b[PSC_POWER] = 0,
+ .R[PSC_POWER] = 0,
+ .m[PSC_TEMPERATURE] = 1,
+ .b[PSC_TEMPERATURE] = 0,
+ .R[PSC_TEMPERATURE] = 0,
+ .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_IIN |
+ PMBUS_HAVE_IOUT | PMBUS_HAVE_PIN | PMBUS_HAVE_POUT |
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_TEMP3 |
+ PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT |
+ PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP |
+ PMBUS_HAVE_VMON,
+ .func[1] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_IIN |
+ PMBUS_HAVE_IOUT | PMBUS_HAVE_PIN | PMBUS_HAVE_POUT |
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_TEMP3 |
+ PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT |
+ PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP |
+ PMBUS_HAVE_VMON,
+ .func[2] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_IIN |
+ PMBUS_HAVE_IOUT | PMBUS_HAVE_PIN | PMBUS_HAVE_POUT |
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_TEMP3 |
+ PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT |
+ PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP |
+ PMBUS_HAVE_VMON,
+ .read_word_data = isl692xx_read_word_data,
+ },
+};
+
+static int isl692xx_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int ret;
+
+ switch (id->driver_data) {
+ case raa228000:
+ case raa228004:
+ case raa228006:
+ ret = pmbus_do_probe(client, id, &isl692xx_info[high_voltage]);
+ break;
+ case isl68227:
+ case isl69243:
+ ret = pmbus_do_probe(client, id, &isl692xx_info[one_rail]);
+ break;
+ case isl68220:
+ case isl68222:
+ case isl68223:
+ case isl68225:
+ case isl68233:
+ case isl69222:
+ case isl69224:
+ case isl69225:
+ case isl69234:
+ case isl69236:
+ case isl69242:
+ case isl69247:
+ case isl69248:
+ case isl69254:
+ case isl69255:
+ case isl69256:
+ case isl69259:
+ case isl69260:
+ case isl69268:
+ case isl69298:
+ case raa228228:
+ case raa229001:
+ case raa229004:
+ ret = pmbus_do_probe(client, id, &isl692xx_info[two_rail]);
+ break;
+ case isl68221:
+ case isl68224:
+ case isl68226:
+ case isl68229:
+ case isl68239:
+ case isl69223:
+ case isl69227:
+ case isl69228:
+ case isl69239:
+ case isl69269:
+ ret = pmbus_do_probe(client, id, &isl692xx_info[three_rail]);
+ break;
+ default:
+ ret = -ENODEV;
+ }
+
+ return ret;
+}
+
+static struct i2c_driver isl692xx_driver = {
+ .driver = {
+ .name = "isl692xx",
+ },
+ .probe = isl692xx_probe,
+ .remove = pmbus_do_remove,
+ .id_table = isl692xx_id,
+};
+
+module_i2c_driver(isl692xx_driver);
+
+MODULE_AUTHOR("Grant Peltier");
+MODULE_DESCRIPTION("PMBus driver for 2nd Gen Renesas digital multiphase "
+ "devices");
+MODULE_LICENSE("GPL");
+
--
2.20.1