aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2014-01-11 03:17:05 -0500
committerGuenter Roeck <linux@roeck-us.net>2014-03-03 11:01:03 -0500
commit69e1ded651ee31c8a570d58647902a55806d0db8 (patch)
tree26afb63215698900a51901807b66de66028e08f4
parent79ffe8594f23475d83112cd5bd68805f91e49170 (diff)
hwmon: Driver for Linear Technologies LTC4260
LTC4260 is a Positive Voltage Hot Swap Controller. The driver currently only supports voltage monitoring, not voltage control. Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r--Documentation/hwmon/ltc426056
-rw-r--r--drivers/hwmon/Kconfig12
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/ltc4260.c200
4 files changed, 269 insertions, 0 deletions
diff --git a/Documentation/hwmon/ltc4260 b/Documentation/hwmon/ltc4260
new file mode 100644
index 000000000000..c4ff4ad998b2
--- /dev/null
+++ b/Documentation/hwmon/ltc4260
@@ -0,0 +1,56 @@
1Kernel driver ltc4260
2=====================
3
4Supported chips:
5 * Linear Technology LTC4260
6 Prefix: 'ltc4260'
7 Addresses scanned: -
8 Datasheet:
9 http://cds.linear.com/docs/en/datasheet/4260fc.pdf
10
11Author: Guenter Roeck <linux@roeck-us.net>
12
13
14Description
15-----------
16
17The LTC4260 Hot Swap controller allows a board to be safely inserted
18and removed from a live backplane.
19
20
21Usage Notes
22-----------
23
24This driver does not probe for LTC4260 devices, since there is no register
25which can be safely used to identify the chip. You will have to instantiate
26the devices explicitly.
27
28Example: the following will load the driver for an LTC4260 at address 0x10
29on I2C bus #1:
30$ modprobe ltc4260
31$ echo ltc4260 0x10 > /sys/bus/i2c/devices/i2c-1/new_device
32
33
34Sysfs entries
35-------------
36
37Voltage readings provided by this driver are reported as obtained from the ADC
38registers. If a set of voltage divider resistors is installed, calculate the
39real voltage by multiplying the reported value with (R1+R2)/R2, where R1 is the
40value of the divider resistor against the measured voltage and R2 is the value
41of the divider resistor against Ground.
42
43Current reading provided by this driver is reported as obtained from the ADC
44Current Sense register. The reported value assumes that a 1 mOhm sense resistor
45is installed. If a different sense resistor is installed, calculate the real
46current by dividing the reported value by the sense resistor value in mOhm.
47
48in1_input SOURCE voltage (mV)
49in1_min_alarm Undervoltage alarm
50in1_max_alarm Overvoltage alarm
51
52in2_input ADIN voltage (mV)
53in2_alarm Power bad alarm
54
55curr1_input SENSE current (mA)
56curr1_alarm SENSE overcurrent alarm
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index ebf1131d05ea..436c611a40ca 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -821,6 +821,18 @@ config SENSORS_LTC4245
821 This driver can also be built as a module. If so, the module will 821 This driver can also be built as a module. If so, the module will
822 be called ltc4245. 822 be called ltc4245.
823 823
824config SENSORS_LTC4260
825 tristate "Linear Technology LTC4260"
826 depends on I2C
827 select REGMAP_I2C
828 default n
829 help
830 If you say yes here you get support for Linear Technology LTC4261
831 Positive Voltage Hot Swap Controller I2C interface.
832
833 This driver can also be built as a module. If so, the module will
834 be called ltc4260.
835
824config SENSORS_LTC4261 836config SENSORS_LTC4261
825 tristate "Linear Technology LTC4261" 837 tristate "Linear Technology LTC4261"
826 depends on I2C 838 depends on I2C
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index f2a4048fe6ca..cdf325818af7 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -99,6 +99,7 @@ obj-$(CONFIG_SENSORS_LTC4151) += ltc4151.o
99obj-$(CONFIG_SENSORS_LTC4215) += ltc4215.o 99obj-$(CONFIG_SENSORS_LTC4215) += ltc4215.o
100obj-$(CONFIG_SENSORS_LTC4222) += ltc4222.o 100obj-$(CONFIG_SENSORS_LTC4222) += ltc4222.o
101obj-$(CONFIG_SENSORS_LTC4245) += ltc4245.o 101obj-$(CONFIG_SENSORS_LTC4245) += ltc4245.o
102obj-$(CONFIG_SENSORS_LTC4260) += ltc4260.o
102obj-$(CONFIG_SENSORS_LTC4261) += ltc4261.o 103obj-$(CONFIG_SENSORS_LTC4261) += ltc4261.o
103obj-$(CONFIG_SENSORS_MAX1111) += max1111.o 104obj-$(CONFIG_SENSORS_MAX1111) += max1111.o
104obj-$(CONFIG_SENSORS_MAX16065) += max16065.o 105obj-$(CONFIG_SENSORS_MAX16065) += max16065.o
diff --git a/drivers/hwmon/ltc4260.c b/drivers/hwmon/ltc4260.c
new file mode 100644
index 000000000000..453a250d9df5
--- /dev/null
+++ b/drivers/hwmon/ltc4260.c
@@ -0,0 +1,200 @@
1/*
2 * Driver for Linear Technology LTC4260 I2C Positive Voltage Hot Swap Controller
3 *
4 * Copyright (c) 2014 Guenter Roeck
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/kernel.h>
18#include <linux/module.h>
19#include <linux/err.h>
20#include <linux/slab.h>
21#include <linux/i2c.h>
22#include <linux/hwmon.h>
23#include <linux/hwmon-sysfs.h>
24#include <linux/jiffies.h>
25#include <linux/regmap.h>
26
27/* chip registers */
28#define LTC4260_CONTROL 0x00
29#define LTC4260_ALERT 0x01
30#define LTC4260_STATUS 0x02
31#define LTC4260_FAULT 0x03
32#define LTC4260_SENSE 0x04
33#define LTC4260_SOURCE 0x05
34#define LTC4260_ADIN 0x06
35
36/*
37 * Fault register bits
38 */
39#define FAULT_OV (1 << 0)
40#define FAULT_UV (1 << 1)
41#define FAULT_OC (1 << 2)
42#define FAULT_POWER_BAD (1 << 3)
43#define FAULT_FET_SHORT (1 << 5)
44
45/* Return the voltage from the given register in mV or mA */
46static int ltc4260_get_value(struct device *dev, u8 reg)
47{
48 struct regmap *regmap = dev_get_drvdata(dev);
49 unsigned int val;
50 int ret;
51
52 ret = regmap_read(regmap, reg, &val);
53 if (ret < 0)
54 return ret;
55
56 switch (reg) {
57 case LTC4260_ADIN:
58 /* 10 mV resolution. Convert to mV. */
59 val = val * 10;
60 break;
61 case LTC4260_SOURCE:
62 /* 400 mV resolution. Convert to mV. */
63 val = val * 400;
64 break;
65 case LTC4260_SENSE:
66 /*
67 * 300 uV resolution. Convert to current as measured with
68 * an 1 mOhm sense resistor, in mA. If a different sense
69 * resistor is installed, calculate the actual current by
70 * dividing the reported current by the sense resistor value
71 * in mOhm.
72 */
73 val = val * 300;
74 break;
75 default:
76 return -EINVAL;
77 }
78
79 return val;
80}
81
82static ssize_t ltc4260_show_value(struct device *dev,
83 struct device_attribute *da, char *buf)
84{
85 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
86 int value;
87
88 value = ltc4260_get_value(dev, attr->index);
89 if (value < 0)
90 return value;
91 return snprintf(buf, PAGE_SIZE, "%d\n", value);
92}
93
94static ssize_t ltc4260_show_bool(struct device *dev,
95 struct device_attribute *da, char *buf)
96{
97 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
98 struct regmap *regmap = dev_get_drvdata(dev);
99 unsigned int fault;
100 int ret;
101
102 ret = regmap_read(regmap, LTC4260_FAULT, &fault);
103 if (ret < 0)
104 return ret;
105
106 fault &= attr->index;
107 if (fault) /* Clear reported faults in chip register */
108 regmap_update_bits(regmap, LTC4260_FAULT, attr->index, 0);
109
110 return snprintf(buf, PAGE_SIZE, "%d\n", !!fault);
111}
112
113/* Voltages */
114static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ltc4260_show_value, NULL,
115 LTC4260_SOURCE);
116static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, ltc4260_show_value, NULL,
117 LTC4260_ADIN);
118
119/*
120 * Voltage alarms
121 * UV/OV faults are associated with the input voltage, and the POWER BAD and
122 * FET SHORT faults are associated with the output voltage.
123 */
124static SENSOR_DEVICE_ATTR(in1_min_alarm, S_IRUGO, ltc4260_show_bool, NULL,
125 FAULT_UV);
126static SENSOR_DEVICE_ATTR(in1_max_alarm, S_IRUGO, ltc4260_show_bool, NULL,
127 FAULT_OV);
128static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, ltc4260_show_bool, NULL,
129 FAULT_POWER_BAD | FAULT_FET_SHORT);
130
131/* Current (via sense resistor) */
132static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc4260_show_value, NULL,
133 LTC4260_SENSE);
134
135/* Overcurrent alarm */
136static SENSOR_DEVICE_ATTR(curr1_max_alarm, S_IRUGO, ltc4260_show_bool, NULL,
137 FAULT_OC);
138
139static struct attribute *ltc4260_attrs[] = {
140 &sensor_dev_attr_in1_input.dev_attr.attr,
141 &sensor_dev_attr_in1_min_alarm.dev_attr.attr,
142 &sensor_dev_attr_in1_max_alarm.dev_attr.attr,
143 &sensor_dev_attr_in2_input.dev_attr.attr,
144 &sensor_dev_attr_in2_alarm.dev_attr.attr,
145
146 &sensor_dev_attr_curr1_input.dev_attr.attr,
147 &sensor_dev_attr_curr1_max_alarm.dev_attr.attr,
148
149 NULL,
150};
151ATTRIBUTE_GROUPS(ltc4260);
152
153static struct regmap_config ltc4260_regmap_config = {
154 .reg_bits = 8,
155 .val_bits = 8,
156 .max_register = LTC4260_ADIN,
157};
158
159static int ltc4260_probe(struct i2c_client *client,
160 const struct i2c_device_id *id)
161{
162 struct device *dev = &client->dev;
163 struct device *hwmon_dev;
164 struct regmap *regmap;
165
166 regmap = devm_regmap_init_i2c(client, &ltc4260_regmap_config);
167 if (IS_ERR(regmap)) {
168 dev_err(dev, "failed to allocate register map\n");
169 return PTR_ERR(regmap);
170 }
171
172 /* Clear faults */
173 regmap_write(regmap, LTC4260_FAULT, 0x00);
174
175 hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
176 regmap,
177 ltc4260_groups);
178 return PTR_ERR_OR_ZERO(hwmon_dev);
179}
180
181static const struct i2c_device_id ltc4260_id[] = {
182 {"ltc4260", 0},
183 { }
184};
185
186MODULE_DEVICE_TABLE(i2c, ltc4260_id);
187
188static struct i2c_driver ltc4260_driver = {
189 .driver = {
190 .name = "ltc4260",
191 },
192 .probe = ltc4260_probe,
193 .id_table = ltc4260_id,
194};
195
196module_i2c_driver(ltc4260_driver);
197
198MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
199MODULE_DESCRIPTION("LTC4260 driver");
200MODULE_LICENSE("GPL");