diff options
-rw-r--r-- | Documentation/hwmon/ltc2990 | 43 | ||||
-rw-r--r-- | drivers/hwmon/Kconfig | 14 | ||||
-rw-r--r-- | drivers/hwmon/Makefile | 1 | ||||
-rw-r--r-- | drivers/hwmon/ltc2990.c | 161 |
4 files changed, 219 insertions, 0 deletions
diff --git a/Documentation/hwmon/ltc2990 b/Documentation/hwmon/ltc2990 new file mode 100644 index 000000000000..c25211e90bdc --- /dev/null +++ b/Documentation/hwmon/ltc2990 | |||
@@ -0,0 +1,43 @@ | |||
1 | Kernel driver ltc2990 | ||
2 | ===================== | ||
3 | |||
4 | Supported chips: | ||
5 | * Linear Technology LTC2990 | ||
6 | Prefix: 'ltc2990' | ||
7 | Addresses scanned: - | ||
8 | Datasheet: http://www.linear.com/product/ltc2990 | ||
9 | |||
10 | Author: Mike Looijmans <mike.looijmans@topic.nl> | ||
11 | |||
12 | |||
13 | Description | ||
14 | ----------- | ||
15 | |||
16 | LTC2990 is a Quad I2C Voltage, Current and Temperature Monitor. | ||
17 | The chip's inputs can measure 4 voltages, or two inputs together (1+2 and 3+4) | ||
18 | can be combined to measure a differential voltage, which is typically used to | ||
19 | measure current through a series resistor, or a temperature. | ||
20 | |||
21 | This driver currently uses the 2x differential mode only. In order to support | ||
22 | other modes, the driver will need to be expanded. | ||
23 | |||
24 | |||
25 | Usage Notes | ||
26 | ----------- | ||
27 | |||
28 | This driver does not probe for PMBus devices. You will have to instantiate | ||
29 | devices explicitly. | ||
30 | |||
31 | |||
32 | Sysfs attributes | ||
33 | ---------------- | ||
34 | |||
35 | The "curr*_input" measurements actually report the voltage drop across the | ||
36 | input pins in microvolts. This is equivalent to the current through a 1mOhm | ||
37 | sense resistor. Divide the reported value by the actual sense resistor value | ||
38 | in mOhm to get the actual value. | ||
39 | |||
40 | in0_input Voltage at Vcc pin in millivolt (range 2.5V to 5V) | ||
41 | temp1_input Internal chip temperature in millidegrees Celcius | ||
42 | curr1_input Current in mA across v1-v2 assuming a 1mOhm sense resistor. | ||
43 | curr2_input Current in mA across v3-v4 assuming a 1mOhm sense resistor. | ||
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 60fb80bd353d..852c8a85e1e8 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -685,6 +685,20 @@ config SENSORS_LTC2945 | |||
685 | This driver can also be built as a module. If so, the module will | 685 | This driver can also be built as a module. If so, the module will |
686 | be called ltc2945. | 686 | be called ltc2945. |
687 | 687 | ||
688 | config SENSORS_LTC2990 | ||
689 | tristate "Linear Technology LTC2990 (current monitoring mode only)" | ||
690 | depends on I2C | ||
691 | help | ||
692 | If you say yes here you get support for Linear Technology LTC2990 | ||
693 | I2C System Monitor. The LTC2990 supports a combination of voltage, | ||
694 | current and temperature monitoring, but in addition to the Vcc supply | ||
695 | voltage and chip temperature, this driver currently only supports | ||
696 | reading two currents by measuring two differential voltages across | ||
697 | series resistors. | ||
698 | |||
699 | This driver can also be built as a module. If so, the module will | ||
700 | be called ltc2990. | ||
701 | |||
688 | config SENSORS_LTC4151 | 702 | config SENSORS_LTC4151 |
689 | tristate "Linear Technology LTC4151" | 703 | tristate "Linear Technology LTC4151" |
690 | depends on I2C | 704 | depends on I2C |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index cfc09711810c..a7ecaf2f29aa 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
@@ -100,6 +100,7 @@ obj-$(CONFIG_SENSORS_LM95234) += lm95234.o | |||
100 | obj-$(CONFIG_SENSORS_LM95241) += lm95241.o | 100 | obj-$(CONFIG_SENSORS_LM95241) += lm95241.o |
101 | obj-$(CONFIG_SENSORS_LM95245) += lm95245.o | 101 | obj-$(CONFIG_SENSORS_LM95245) += lm95245.o |
102 | obj-$(CONFIG_SENSORS_LTC2945) += ltc2945.o | 102 | obj-$(CONFIG_SENSORS_LTC2945) += ltc2945.o |
103 | obj-$(CONFIG_SENSORS_LTC2990) += ltc2990.o | ||
103 | obj-$(CONFIG_SENSORS_LTC4151) += ltc4151.o | 104 | obj-$(CONFIG_SENSORS_LTC4151) += ltc4151.o |
104 | obj-$(CONFIG_SENSORS_LTC4215) += ltc4215.o | 105 | obj-$(CONFIG_SENSORS_LTC4215) += ltc4215.o |
105 | obj-$(CONFIG_SENSORS_LTC4222) += ltc4222.o | 106 | obj-$(CONFIG_SENSORS_LTC4222) += ltc4222.o |
diff --git a/drivers/hwmon/ltc2990.c b/drivers/hwmon/ltc2990.c new file mode 100644 index 000000000000..8f8fe059ab48 --- /dev/null +++ b/drivers/hwmon/ltc2990.c | |||
@@ -0,0 +1,161 @@ | |||
1 | /* | ||
2 | * Driver for Linear Technology LTC2990 power monitor | ||
3 | * | ||
4 | * Copyright (C) 2014 Topic Embedded Products | ||
5 | * Author: Mike Looijmans <mike.looijmans@topic.nl> | ||
6 | * | ||
7 | * License: GPLv2 | ||
8 | * | ||
9 | * This driver assumes the chip is wired as a dual current monitor, and | ||
10 | * reports the voltage drop across two series resistors. It also reports | ||
11 | * the chip's internal temperature and Vcc power supply voltage. | ||
12 | */ | ||
13 | |||
14 | #include <linux/err.h> | ||
15 | #include <linux/hwmon.h> | ||
16 | #include <linux/hwmon-sysfs.h> | ||
17 | #include <linux/i2c.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/module.h> | ||
20 | |||
21 | #define LTC2990_STATUS 0x00 | ||
22 | #define LTC2990_CONTROL 0x01 | ||
23 | #define LTC2990_TRIGGER 0x02 | ||
24 | #define LTC2990_TINT_MSB 0x04 | ||
25 | #define LTC2990_V1_MSB 0x06 | ||
26 | #define LTC2990_V2_MSB 0x08 | ||
27 | #define LTC2990_V3_MSB 0x0A | ||
28 | #define LTC2990_V4_MSB 0x0C | ||
29 | #define LTC2990_VCC_MSB 0x0E | ||
30 | |||
31 | #define LTC2990_CONTROL_KELVIN BIT(7) | ||
32 | #define LTC2990_CONTROL_SINGLE BIT(6) | ||
33 | #define LTC2990_CONTROL_MEASURE_ALL (0x3 << 3) | ||
34 | #define LTC2990_CONTROL_MODE_CURRENT 0x06 | ||
35 | #define LTC2990_CONTROL_MODE_VOLTAGE 0x07 | ||
36 | |||
37 | /* convert raw register value to sign-extended integer in 16-bit range */ | ||
38 | static int ltc2990_voltage_to_int(int raw) | ||
39 | { | ||
40 | if (raw & BIT(14)) | ||
41 | return -(0x4000 - (raw & 0x3FFF)) << 2; | ||
42 | else | ||
43 | return (raw & 0x3FFF) << 2; | ||
44 | } | ||
45 | |||
46 | /* Return the converted value from the given register in uV or mC */ | ||
47 | static int ltc2990_get_value(struct i2c_client *i2c, u8 reg, int *result) | ||
48 | { | ||
49 | int val; | ||
50 | |||
51 | val = i2c_smbus_read_word_swapped(i2c, reg); | ||
52 | if (unlikely(val < 0)) | ||
53 | return val; | ||
54 | |||
55 | switch (reg) { | ||
56 | case LTC2990_TINT_MSB: | ||
57 | /* internal temp, 0.0625 degrees/LSB, 13-bit */ | ||
58 | val = (val & 0x1FFF) << 3; | ||
59 | *result = (val * 1000) >> 7; | ||
60 | break; | ||
61 | case LTC2990_V1_MSB: | ||
62 | case LTC2990_V3_MSB: | ||
63 | /* Vx-Vy, 19.42uV/LSB. Depends on mode. */ | ||
64 | *result = ltc2990_voltage_to_int(val) * 1942 / (4 * 100); | ||
65 | break; | ||
66 | case LTC2990_VCC_MSB: | ||
67 | /* Vcc, 305.18μV/LSB, 2.5V offset */ | ||
68 | *result = (ltc2990_voltage_to_int(val) * 30518 / | ||
69 | (4 * 100 * 1000)) + 2500; | ||
70 | break; | ||
71 | default: | ||
72 | return -EINVAL; /* won't happen, keep compiler happy */ | ||
73 | } | ||
74 | |||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | static ssize_t ltc2990_show_value(struct device *dev, | ||
79 | struct device_attribute *da, char *buf) | ||
80 | { | ||
81 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
82 | int value; | ||
83 | int ret; | ||
84 | |||
85 | ret = ltc2990_get_value(dev_get_drvdata(dev), attr->index, &value); | ||
86 | if (unlikely(ret < 0)) | ||
87 | return ret; | ||
88 | |||
89 | return snprintf(buf, PAGE_SIZE, "%d\n", value); | ||
90 | } | ||
91 | |||
92 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ltc2990_show_value, NULL, | ||
93 | LTC2990_TINT_MSB); | ||
94 | static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc2990_show_value, NULL, | ||
95 | LTC2990_V1_MSB); | ||
96 | static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, ltc2990_show_value, NULL, | ||
97 | LTC2990_V3_MSB); | ||
98 | static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, ltc2990_show_value, NULL, | ||
99 | LTC2990_VCC_MSB); | ||
100 | |||
101 | static struct attribute *ltc2990_attrs[] = { | ||
102 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
103 | &sensor_dev_attr_curr1_input.dev_attr.attr, | ||
104 | &sensor_dev_attr_curr2_input.dev_attr.attr, | ||
105 | &sensor_dev_attr_in0_input.dev_attr.attr, | ||
106 | NULL, | ||
107 | }; | ||
108 | ATTRIBUTE_GROUPS(ltc2990); | ||
109 | |||
110 | static int ltc2990_i2c_probe(struct i2c_client *i2c, | ||
111 | const struct i2c_device_id *id) | ||
112 | { | ||
113 | int ret; | ||
114 | struct device *hwmon_dev; | ||
115 | |||
116 | if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA | | ||
117 | I2C_FUNC_SMBUS_WORD_DATA)) | ||
118 | return -ENODEV; | ||
119 | |||
120 | /* Setup continuous mode, current monitor */ | ||
121 | ret = i2c_smbus_write_byte_data(i2c, LTC2990_CONTROL, | ||
122 | LTC2990_CONTROL_MEASURE_ALL | | ||
123 | LTC2990_CONTROL_MODE_CURRENT); | ||
124 | if (ret < 0) { | ||
125 | dev_err(&i2c->dev, "Error: Failed to set control mode.\n"); | ||
126 | return ret; | ||
127 | } | ||
128 | /* Trigger once to start continuous conversion */ | ||
129 | ret = i2c_smbus_write_byte_data(i2c, LTC2990_TRIGGER, 1); | ||
130 | if (ret < 0) { | ||
131 | dev_err(&i2c->dev, "Error: Failed to start acquisition.\n"); | ||
132 | return ret; | ||
133 | } | ||
134 | |||
135 | hwmon_dev = devm_hwmon_device_register_with_groups(&i2c->dev, | ||
136 | i2c->name, | ||
137 | i2c, | ||
138 | ltc2990_groups); | ||
139 | |||
140 | return PTR_ERR_OR_ZERO(hwmon_dev); | ||
141 | } | ||
142 | |||
143 | static const struct i2c_device_id ltc2990_i2c_id[] = { | ||
144 | { "ltc2990", 0 }, | ||
145 | {} | ||
146 | }; | ||
147 | MODULE_DEVICE_TABLE(i2c, ltc2990_i2c_id); | ||
148 | |||
149 | static struct i2c_driver ltc2990_i2c_driver = { | ||
150 | .driver = { | ||
151 | .name = "ltc2990", | ||
152 | }, | ||
153 | .probe = ltc2990_i2c_probe, | ||
154 | .id_table = ltc2990_i2c_id, | ||
155 | }; | ||
156 | |||
157 | module_i2c_driver(ltc2990_i2c_driver); | ||
158 | |||
159 | MODULE_DESCRIPTION("LTC2990 Sensor Driver"); | ||
160 | MODULE_AUTHOR("Topic Embedded Products"); | ||
161 | MODULE_LICENSE("GPL v2"); | ||