[PATCH] hwmon: Driver for TI TPS2483 hotswap controller

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

 



Adds support for Texas Instruments TPS2483 Series
Hot Swap Voltage Controller. The driver in its current form
supports reading Shunt Voltage, Bus Voltage, Power and Current.

Since TPS2483 can be configured to a particular slave address
based on the state of A0 and A1 pins, instantiation is done
manually. For eg:-
echo tps2483 0x40 > /sys/bus/i2c/devices/i2c-1/new_device

Signed-off-by: Philby John <philby.j@xxxxxxx>
---
 drivers/hwmon/Kconfig   |  11 +++
 drivers/hwmon/Makefile  |   1 +
 drivers/hwmon/tps2483.c | 174 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 186 insertions(+)
 create mode 100644 drivers/hwmon/tps2483.c

diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 8dc28b26916e..9e51c25f695e 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1852,6 +1852,17 @@ config SENSORS_TMP513
 	  This driver can also be built as a module. If so, the module
 	  will be called tmp513.
 
+config SENSORS_TPS2483
+	tristate "Texas Instruments TPS2483"
+	depends on I2C
+	select REGMAP_I2C
+	help
+	  If you say yes here you get support for Texas Instruments TPS2483
+	  Hot Swap Controller I2C interface.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called tps2483.
+
 config SENSORS_VEXPRESS
 	tristate "Versatile Express"
 	depends on VEXPRESS_CONFIG
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index a8f4b35b136b..2f1551c77a4c 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -179,6 +179,7 @@ obj-$(CONFIG_SENSORS_TMP108)	+= tmp108.o
 obj-$(CONFIG_SENSORS_TMP401)	+= tmp401.o
 obj-$(CONFIG_SENSORS_TMP421)	+= tmp421.o
 obj-$(CONFIG_SENSORS_TMP513)	+= tmp513.o
+obj-$(CONFIG_SENSORS_TPS2483)   += tps2483.o
 obj-$(CONFIG_SENSORS_VEXPRESS)	+= vexpress-hwmon.o
 obj-$(CONFIG_SENSORS_VIA_CPUTEMP)+= via-cputemp.o
 obj-$(CONFIG_SENSORS_VIA686A)	+= via686a.o
diff --git a/drivers/hwmon/tps2483.c b/drivers/hwmon/tps2483.c
new file mode 100644
index 000000000000..957b6e3e0cd9
--- /dev/null
+++ b/drivers/hwmon/tps2483.c
@@ -0,0 +1,174 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Driver for Texas Instruments TPS 2483 Hot Swap controller
+ *
+ * Copyright (c) 2020 Philby John
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/bitops.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/jiffies.h>
+#include <linux/regmap.h>
+
+/* chip registers */
+#define TPS2483_CONFIG		0x00
+#define TPS2483_SHUNT_VOLT	0x01
+#define TPS2483_BUS_VOLT	0x02
+#define TPS2483_PWR		0x03
+#define TPS2483_CURRENT		0x04
+#define TPS2483_CALIB		0x05
+#define TPS2483_MASK		0x06
+#define TPS2483_ALERT		0x07
+
+#define MAX_CALIB_FACTOR	32757
+#define MIN_CALIB_FACTOR	0
+
+/* Fault register bits */
+#define SHUNT_OV	BIT(15)
+#define SHUNT_UV	BIT(14)
+#define BUS_OV		BIT(13)
+#define BUS_UV		BIT(12)
+#define POWER_OL	BIT(11)
+#define MATH_OF		BIT(2)
+#define LATCH_EN	BIT(0)
+
+
+static ssize_t tps2483_set_value(struct device *dev,
+					struct device_attribute *da,
+					const char *buf, size_t count)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct regmap *regmap = dev_get_drvdata(dev);
+	u8 reg = attr->index;
+	unsigned long val;
+	int ret;
+
+	ret = kstrtoul(buf, 10, &val);
+	if (ret)
+		return ret;
+
+	val = clamp_val(val, MIN_CALIB_FACTOR, MAX_CALIB_FACTOR);
+	ret = regmap_write(regmap, reg, val);
+	return ret < 0 ? ret : count;
+}
+
+/* Return the voltage from the given register in mV or mA */
+static int tps2483_get_value(struct device *dev, u8 reg)
+{
+	struct regmap *regmap = dev_get_drvdata(dev);
+	unsigned int val;
+	int ret;
+
+	ret = regmap_read(regmap, reg, &val);
+	if (ret < 0)
+		return ret;
+
+	switch (reg) {
+	case TPS2483_SHUNT_VOLT:
+		val = DIV_ROUND_CLOSEST(val * 25, 10000);
+		break;
+	case TPS2483_BUS_VOLT:
+		DIV_ROUND_CLOSEST(val * 125, 100);
+		break;
+	case TPS2483_PWR:
+		val = DIV_ROUND_CLOSEST(val * 125, 100);
+		break;
+	case TPS2483_CURRENT:
+		break;
+	default:
+		return -EINVAL;
+	}
+	return val;
+}
+
+static ssize_t tps2483_show_value(struct device *dev,
+				  struct device_attribute *da, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	int value;
+
+	value = tps2483_get_value(dev, attr->index);
+	if (value < 0)
+		return value;
+	return snprintf(buf, PAGE_SIZE, "%d\n", value);
+}
+
+/* Voltages */
+static SENSOR_DEVICE_ATTR(in0_input, 0444, tps2483_show_value, NULL,
+			  TPS2483_CONFIG);
+static SENSOR_DEVICE_ATTR(in1_input, 0444, tps2483_show_value, NULL,
+			  TPS2483_SHUNT_VOLT);
+static SENSOR_DEVICE_ATTR(in2_input, 0444, tps2483_show_value, NULL,
+			  TPS2483_BUS_VOLT);
+static SENSOR_DEVICE_ATTR(power1_input, 0444, tps2483_show_value, NULL,
+			  TPS2483_PWR);
+static SENSOR_DEVICE_ATTR(curr1_input, 0444, tps2483_show_value, NULL,
+			  TPS2483_CURRENT);
+static SENSOR_DEVICE_ATTR(in3_input, 0644, tps2483_show_value,
+			tps2483_set_value, TPS2483_CALIB);
+
+static struct attribute *tpm2483_attrs[] = {
+	&sensor_dev_attr_in0_input.dev_attr.attr,
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+	&sensor_dev_attr_in3_input.dev_attr.attr,
+	&sensor_dev_attr_power1_input.dev_attr.attr,
+	&sensor_dev_attr_curr1_input.dev_attr.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(tpm2483);
+
+static const struct regmap_config tps2483_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 16,
+	.max_register = TPS2483_ALERT,
+};
+
+static int tps2483_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct device *dev = &client->dev;
+	struct device *hwmon_dev;
+	struct regmap *regmap;
+
+	regmap = devm_regmap_init_i2c(client, &tps2483_regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(dev, "failed to allocate register map\n");
+		return PTR_ERR(regmap);
+	}
+
+	/* Clear faults */
+	regmap_write(regmap, TPS2483_ALERT, 0x00);
+
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+			regmap,
+			tpm2483_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+static const struct i2c_device_id tps2483_id[] = {
+	{"tps2483", 0},
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, tps2483_id);
+
+static struct i2c_driver tps2483_driver = {
+	.driver = {
+		.name = "tps2483",
+	},
+	.probe = tps2483_probe,
+	.id_table = tps2483_id,
+};
+
+module_i2c_driver(tps2483_driver);
+
+MODULE_AUTHOR("Philby John <philby.j@xxxxxxx>");
+MODULE_DESCRIPTION("TPS2483 driver");
+MODULE_LICENSE("GPL");
-- 
2.13.6




[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