[PATCH 1/2] hwmon: pmbus: adm1266: add initial support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add initial pmbus probing driver for the adm1266 Cascadable
Super Sequencer with Margin Control and Fault Recording.
Driver is currently using the pmbus_core, creating sysfs
files under hwmon for inputs: vh1->vh4 and vp1->vp13.

Signed-off-by: Alexandru Tachici <alexandru.tachici@xxxxxxxxxx>
---
 Documentation/hwmon/adm1266   |  34 ++++++++
 drivers/hwmon/pmbus/Kconfig   |  10 +++
 drivers/hwmon/pmbus/Makefile  |   1 +
 drivers/hwmon/pmbus/adm1266.c | 146 ++++++++++++++++++++++++++++++++++
 4 files changed, 191 insertions(+)
 create mode 100644 Documentation/hwmon/adm1266
 create mode 100644 drivers/hwmon/pmbus/adm1266.c

diff --git a/Documentation/hwmon/adm1266 b/Documentation/hwmon/adm1266
new file mode 100644
index 000000000000..64651b5086a7
--- /dev/null
+++ b/Documentation/hwmon/adm1266
@@ -0,0 +1,34 @@
+Kernel driver adm1266
+=====================
+
+Supported chips:
+  * Analog Devices ADM1266
+    Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ADM1266.pdf
+
+Author: Alexandru Tachici <alexandru.tachici@xxxxxxxxxx>
+
+
+Description
+-----------
+
+This driver supports hardware monitoring for Analog Devices ADM1266 sequencer.
+
+ADM1266 is a sequencer that feature voltage readback from 17 channels via an
+integrated 12 bit SAR ADC, accessed using a PMBus interface.
+
+The driver is a client driver to the core PMBus driver. Please see
+Documentation/hwmon/pmbus for details on PMBus client drivers.
+
+
+Sysfs entries
+-------------
+
+The following attributes are supported. Limits are read-write, history reset
+attributes are write-only, all other attributes are read-only.
+
+inX_label		"voutx"
+inX_input		Measured voltage.
+inX_min			Minimum Voltage.
+inX_max			Maximum voltage.
+inX_min_alarm		Voltage low alarm.
+inX_max_alarm		Voltage high alarm.
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
index a9ea06204767..153e64febe98 100644
--- a/drivers/hwmon/pmbus/Kconfig
+++ b/drivers/hwmon/pmbus/Kconfig
@@ -26,6 +26,16 @@ config SENSORS_PMBUS
 	  This driver can also be built as a module. If so, the module will
 	  be called pmbus.
 
+config SENSORS_ADM1266
+	tristate "Analog Devices ADM1266"
+	default n
+	help
+	  If you say yes here you get hardware monitoring support for Analog
+	  Devices ADM1266.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called adm1266.
+
 config SENSORS_ADM1275
 	tristate "Analog Devices ADM1275 and compatibles"
 	help
diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile
index 5feb45806123..ed38f6d6f845 100644
--- a/drivers/hwmon/pmbus/Makefile
+++ b/drivers/hwmon/pmbus/Makefile
@@ -5,6 +5,7 @@
 
 obj-$(CONFIG_PMBUS)		+= pmbus_core.o
 obj-$(CONFIG_SENSORS_PMBUS)	+= pmbus.o
+obj-$(CONFIG_SENSORS_ADM1266)	+= adm1266.o
 obj-$(CONFIG_SENSORS_ADM1275)	+= adm1275.o
 obj-$(CONFIG_SENSORS_BEL_PFE)	+= bel-pfe.o
 obj-$(CONFIG_SENSORS_IBM_CFFPS)	+= ibm-cffps.o
diff --git a/drivers/hwmon/pmbus/adm1266.c b/drivers/hwmon/pmbus/adm1266.c
new file mode 100644
index 000000000000..3aa8262f9bd6
--- /dev/null
+++ b/drivers/hwmon/pmbus/adm1266.c
@@ -0,0 +1,146 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ADM1266 - Cascadable Super Sequencer with Margin
+ * Control and Fault Recording
+ *
+ * Copyright 2020 Analog Devices Inc.
+ */
+
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/fwnode.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "pmbus.h"
+
+enum chips { adm1266 };
+
+struct adm1266_data {
+	enum chips id;
+	struct pmbus_driver_info info;
+};
+
+static int adm1266_block_wr(struct i2c_client *client, u8 cmd, u8 wr_len,
+			    u8 *data_w, u8 *data_r)
+{
+	union i2c_smbus_data smbus_data;
+	int ret;
+
+	smbus_data.block[0] = wr_len;
+	memcpy(smbus_data.block + 1, data_w, wr_len);
+	ret = i2c_smbus_xfer(client->adapter, client->addr,
+			     client->flags, I2C_SMBUS_READ, cmd,
+			     I2C_SMBUS_BLOCK_PROC_CALL, &smbus_data);
+	if (ret < 0)
+		return ret;
+
+	memcpy(data_r, &smbus_data.block[1], smbus_data.block[0]);
+
+	return 0;
+}
+
+static int adm1266_config(struct pmbus_driver_info *info)
+{
+	u32 funcs;
+	int i;
+
+	info->pages = 17;
+	info->format[PSC_VOLTAGE_OUT] = linear;
+
+	funcs = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
+	for (i = 0; i < info->pages; i++)
+		info->func[i] = funcs;
+
+	return 0;
+}
+
+static const struct i2c_device_id adm1266_id[] = {
+	{ "adm1266", adm1266 },
+	{ },
+};
+MODULE_DEVICE_TABLE(i2c, adm1266_id);
+
+static int adm1266_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1];
+	u8 wr_buffer[I2C_SMBUS_BLOCK_MAX + 1];
+	const struct i2c_device_id *mid;
+	struct adm1266_data *data;
+	int ret;
+
+	if (!i2c_check_functionality(client->adapter,
+				     I2C_FUNC_SMBUS_READ_BYTE_DATA
+				     | I2C_FUNC_SMBUS_BLOCK_DATA))
+		return -ENODEV;
+
+	wr_buffer[0] = 32;
+	ret = adm1266_block_wr(client, PMBUS_MFR_ID, 1, wr_buffer,
+			       block_buffer);
+	if (ret < 0) {
+		dev_err(&client->dev, "Failed to read Manufacturer ID\n");
+		return ret;
+	}
+
+	if (strncmp(block_buffer, "Analog Devices, Inc", 19)) {
+		dev_err(&client->dev, "Unsupported Manufacturer ID\n");
+		return -ENODEV;
+	}
+
+	wr_buffer[0] = 32;
+	ret = adm1266_block_wr(client, PMBUS_MFR_MODEL, 1, wr_buffer,
+			       block_buffer);
+	if (ret < 0) {
+		dev_err(&client->dev, "Failed to read Manufacturer Model\n");
+		return ret;
+	}
+
+	for (mid = adm1266_id; mid->name[0]; mid++) {
+		if (!strncasecmp(mid->name, block_buffer, strlen(mid->name)))
+			break;
+	}
+	if (!mid->name[0]) {
+		dev_err(&client->dev, "Unsupported device\n");
+		return -ENODEV;
+	}
+
+	data = devm_kzalloc(&client->dev, sizeof(struct adm1266_data),
+			    GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+	data->id = mid->driver_data;
+
+	ret = adm1266_config(&data->info);
+	if (ret < 0) {
+		dev_err(&client->dev, "Could not configure device.");
+		return ret;
+	}
+
+	return pmbus_do_probe(client, id, &data->info);
+}
+
+static const struct of_device_id adm1266_of_match[] = {
+	{ .compatible = "adi,adm1266" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, adm1266_of_match);
+
+static struct i2c_driver adm1266_driver = {
+	.driver = {
+		   .name = "adm1266",
+		   .of_match_table = adm1266_of_match,
+		  },
+	.probe = adm1266_probe,
+	.remove = pmbus_do_remove,
+	.id_table = adm1266_id,
+};
+
+module_i2c_driver(adm1266_driver);
+
+MODULE_AUTHOR("Alexandru Tachici <alexandru.tachici@xxxxxxxxxx>");
+MODULE_DESCRIPTION("PMBus driver for Analog Devices ADM1266");
+MODULE_LICENSE("GPL v2");
-- 
2.20.1




[Index of Archives]     [LM Sensors]     [Linux Sound]     [ALSA Users]     [ALSA Devel]     [Linux Audio Users]     [Linux Media]     [Kernel]     [Gimp]     [Yosemite News]     [Linux Media]

  Powered by Linux