aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuenter Roeck <guenter.roeck@ericsson.com>2011-03-09 01:01:39 -0500
committerGuenter Roeck <guenter.roeck@ericsson.com>2011-05-19 11:19:40 -0400
commit0c0a0615163e025eb978547969467012529e01d5 (patch)
tree5a30c5a7ba79426be50c8bb573fe3784badc1aa4
parent84fc4585c152f34a1a90a03b7abb88a2e1218a42 (diff)
hwmon: (pmbus) Support for TI UCD90xxx series Sequencer and System Health Controllers
Hardware monitoring support for TI UCD90120, UCD90124, UCD9090, and UCD90910 Sequencer and System Health Controllers. Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com> Reviewed-by: Tom Grennan <tom.grennan@ericsson.com>
-rw-r--r--Documentation/hwmon/ucd9000110
-rw-r--r--drivers/hwmon/Kconfig14
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/ucd9000.c278
4 files changed, 402 insertions, 1 deletions
diff --git a/Documentation/hwmon/ucd9000 b/Documentation/hwmon/ucd9000
new file mode 100644
index 000000000000..40ca6db50c48
--- /dev/null
+++ b/Documentation/hwmon/ucd9000
@@ -0,0 +1,110 @@
1Kernel driver ucd9000
2=====================
3
4Supported chips:
5 * TI UCD90120, UCD90124, UCD9090, and UCD90910
6 Prefixes: 'ucd90120', 'ucd90124', 'ucd9090', 'ucd90910'
7 Addresses scanned: -
8 Datasheets:
9 http://focus.ti.com/lit/ds/symlink/ucd90120.pdf
10 http://focus.ti.com/lit/ds/symlink/ucd90124.pdf
11 http://focus.ti.com/lit/ds/symlink/ucd9090.pdf
12 http://focus.ti.com/lit/ds/symlink/ucd90910.pdf
13
14Author: Guenter Roeck <guenter.roeck@ericsson.com>
15
16
17Description
18-----------
19
20From datasheets:
21
22The UCD90120 Power Supply Sequencer and System Health Monitor monitors and
23sequences up to 12 independent voltage rails. The device integrates a 12-bit
24ADC with a 2.5V internal reference for monitoring up to 13 power supply voltage,
25current, or temperature inputs.
26
27The UCD90124 is a 12-rail PMBus/I2C addressable power-supply sequencer and
28system-health monitor. The device integrates a 12-bit ADC for monitoring up to
2913 power-supply voltage, current, or temperature inputs. Twenty-six GPIO pins
30can be used for power supply enables, power-on reset signals, external
31interrupts, cascading, or other system functions. Twelve of these pins offer PWM
32functionality. Using these pins, the UCD90124 offers support for fan control,
33margining, and general-purpose PWM functions.
34
35The UCD9090 is a 10-rail PMBus/I2C addressable power-supply sequencer and
36monitor. The device integrates a 12-bit ADC for monitoring up to 10 power-supply
37voltage inputs. Twenty-three GPIO pins can be used for power supply enables,
38power-on reset signals, external interrupts, cascading, or other system
39functions. Ten of these pins offer PWM functionality. Using these pins, the
40UCD9090 offers support for margining, and general-purpose PWM functions.
41
42The UCD90910 is a ten-rail I2C / PMBus addressable power-supply sequencer and
43system-health monitor. The device integrates a 12-bit ADC for monitoring up to
4413 power-supply voltage, current, or temperature inputs.
45
46This driver is a client driver to the core PMBus driver. Please see
47Documentation/hwmon/pmbus for details on PMBus client drivers.
48
49
50Usage Notes
51-----------
52
53This driver does not auto-detect devices. You will have to instantiate the
54devices explicitly. Please see Documentation/i2c/instantiating-devices for
55details.
56
57
58Platform data support
59---------------------
60
61The driver supports standard PMBus driver platform data. Please see
62Documentation/hwmon/pmbus for details.
63
64
65Sysfs entries
66-------------
67
68The following attributes are supported. Limits are read-write; all other
69attributes are read-only.
70
71in[1-12]_label "vout[1-12]".
72in[1-12]_input Measured voltage. From READ_VOUT register.
73in[1-12]_min Minumum Voltage. From VOUT_UV_WARN_LIMIT register.
74in[1-12]_max Maximum voltage. From VOUT_OV_WARN_LIMIT register.
75in[1-12]_lcrit Critical minumum Voltage. VOUT_UV_FAULT_LIMIT register.
76in[1-12]_crit Critical maximum voltage. From VOUT_OV_FAULT_LIMIT register.
77in[1-12]_min_alarm Voltage low alarm. From VOLTAGE_UV_WARNING status.
78in[1-12]_max_alarm Voltage high alarm. From VOLTAGE_OV_WARNING status.
79in[1-12]_lcrit_alarm Voltage critical low alarm. From VOLTAGE_UV_FAULT status.
80in[1-12]_crit_alarm Voltage critical high alarm. From VOLTAGE_OV_FAULT status.
81
82curr[1-12]_label "iout[1-12]".
83curr[1-12]_input Measured current. From READ_IOUT register.
84curr[1-12]_max Maximum current. From IOUT_OC_WARN_LIMIT register.
85curr[1-12]_lcrit Critical minumum output current. From IOUT_UC_FAULT_LIMIT
86 register.
87curr[1-12]_crit Critical maximum current. From IOUT_OC_FAULT_LIMIT register.
88curr[1-12]_max_alarm Current high alarm. From IOUT_OC_WARNING status.
89curr[1-12]_crit_alarm Current critical high alarm. From IOUT_OC_FAULT status.
90
91 For each attribute index, either voltage or current is
92 reported, but not both. If voltage or current is
93 reported depends on the chip configuration.
94
95temp[1-2]_input Measured temperatures. From READ_TEMPERATURE_1 and
96 READ_TEMPERATURE_2 registers.
97temp[1-2]_max Maximum temperature. From OT_WARN_LIMIT register.
98temp[1-2]_crit Critical high temperature. From OT_FAULT_LIMIT register.
99temp[1-2]_max_alarm Temperature high alarm.
100temp[1-2]_crit_alarm Temperature critical high alarm.
101
102fan[1-4]_input Fan RPM.
103fan[1-4]_alarm Fan alarm.
104fan[1-4]_fault Fan fault.
105
106 Fan attributes are only available on chips supporting
107 fan control (UCD90124, UCD90910). Attribute files are
108 created only for enabled fans.
109 Note that even though UCD90910 supports up to 10 fans,
110 only up to four fans are currently supported.
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 07c4a860dffe..d00fd39f6ee3 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -857,12 +857,24 @@ config SENSORS_MAX8688
857 This driver can also be built as a module. If so, the module will 857 This driver can also be built as a module. If so, the module will
858 be called max8688. 858 be called max8688.
859 859
860config SENSORS_UCD9000
861 tristate "TI UCD90120, UCD90124, UCD9090, UCD90910"
862 default n
863 help
864 If you say yes here you get hardware monitoring support for TI
865 UCD90120, UCD90124, UCD9090, UCD90910 Sequencer and System Health
866 Controllers.
867
868 This driver can also be built as a module. If so, the module will
869 be called ucd9000.
870
860config SENSORS_UCD9200 871config SENSORS_UCD9200
861 tristate "TI UCD9220, UCD9222, UCD9224, UCD9240, UCD9244, UCD9246, UCD9248" 872 tristate "TI UCD9220, UCD9222, UCD9224, UCD9240, UCD9244, UCD9246, UCD9248"
862 default n 873 default n
863 help 874 help
864 If you say yes here you get hardware monitoring support for TI 875 If you say yes here you get hardware monitoring support for TI
865 UCD9220, UCD9222, UCD9224, UCD9240, UCD9244, UCD9246, and UCD9248. 876 UCD9220, UCD9222, UCD9224, UCD9240, UCD9244, UCD9246, and UCD9248
877 Digital PWM System Controllers.
866 878
867 This driver can also be built as a module. If so, the module will 879 This driver can also be built as a module. If so, the module will
868 be called ucd9200. 880 be called ucd9200.
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 1afe02961dec..c4a269b06925 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -123,6 +123,7 @@ obj-$(CONFIG_SENSORS_PMBUS) += pmbus.o
123obj-$(CONFIG_SENSORS_MAX16064) += max16064.o 123obj-$(CONFIG_SENSORS_MAX16064) += max16064.o
124obj-$(CONFIG_SENSORS_MAX34440) += max34440.o 124obj-$(CONFIG_SENSORS_MAX34440) += max34440.o
125obj-$(CONFIG_SENSORS_MAX8688) += max8688.o 125obj-$(CONFIG_SENSORS_MAX8688) += max8688.o
126obj-$(CONFIG_SENSORS_UCD9000) += ucd9000.o
126obj-$(CONFIG_SENSORS_UCD9200) += ucd9200.o 127obj-$(CONFIG_SENSORS_UCD9200) += ucd9200.o
127 128
128ccflags-$(CONFIG_HWMON_DEBUG_CHIP) := -DDEBUG 129ccflags-$(CONFIG_HWMON_DEBUG_CHIP) := -DDEBUG
diff --git a/drivers/hwmon/ucd9000.c b/drivers/hwmon/ucd9000.c
new file mode 100644
index 000000000000..ace1c7319734
--- /dev/null
+++ b/drivers/hwmon/ucd9000.c
@@ -0,0 +1,278 @@
1/*
2 * Hardware monitoring driver for UCD90xxx Sequencer and System Health
3 * Controller series
4 *
5 * Copyright (C) 2011 Ericsson AB.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/init.h>
25#include <linux/err.h>
26#include <linux/slab.h>
27#include <linux/i2c.h>
28#include <linux/i2c/pmbus.h>
29#include "pmbus.h"
30
31enum chips { ucd9000, ucd90120, ucd90124, ucd9090, ucd90910 };
32
33#define UCD9000_MONITOR_CONFIG 0xd5
34#define UCD9000_NUM_PAGES 0xd6
35#define UCD9000_FAN_CONFIG_INDEX 0xe7
36#define UCD9000_FAN_CONFIG 0xe8
37#define UCD9000_DEVICE_ID 0xfd
38
39#define UCD9000_MON_TYPE(x) (((x) >> 5) & 0x07)
40#define UCD9000_MON_PAGE(x) ((x) & 0x0f)
41
42#define UCD9000_MON_VOLTAGE 1
43#define UCD9000_MON_TEMPERATURE 2
44#define UCD9000_MON_CURRENT 3
45#define UCD9000_MON_VOLTAGE_HW 4
46
47#define UCD9000_NUM_FAN 4
48
49struct ucd9000_data {
50 u8 fan_data[UCD9000_NUM_FAN][I2C_SMBUS_BLOCK_MAX];
51 struct pmbus_driver_info info;
52};
53#define to_ucd9000_data(_info) container_of(_info, struct ucd9000_data, info)
54
55static int ucd9000_get_fan_config(struct i2c_client *client, int fan)
56{
57 int fan_config = 0;
58 struct ucd9000_data *data
59 = to_ucd9000_data(pmbus_get_driver_info(client));
60
61 if (data->fan_data[fan][3] & 1)
62 fan_config |= PB_FAN_2_INSTALLED; /* Use lower bit position */
63
64 /* Pulses/revolution */
65 fan_config |= (data->fan_data[fan][3] & 0x06) >> 1;
66
67 return fan_config;
68}
69
70static int ucd9000_read_byte_data(struct i2c_client *client, int page, int reg)
71{
72 int ret = 0;
73 int fan_config;
74
75 switch (reg) {
76 case PMBUS_FAN_CONFIG_12:
77 if (page)
78 return -EINVAL;
79
80 ret = ucd9000_get_fan_config(client, 0);
81 if (ret < 0)
82 return ret;
83 fan_config = ret << 4;
84 ret = ucd9000_get_fan_config(client, 1);
85 if (ret < 0)
86 return ret;
87 fan_config |= ret;
88 ret = fan_config;
89 break;
90 case PMBUS_FAN_CONFIG_34:
91 if (page)
92 return -EINVAL;
93
94 ret = ucd9000_get_fan_config(client, 2);
95 if (ret < 0)
96 return ret;
97 fan_config = ret << 4;
98 ret = ucd9000_get_fan_config(client, 3);
99 if (ret < 0)
100 return ret;
101 fan_config |= ret;
102 ret = fan_config;
103 break;
104 default:
105 ret = -ENODATA;
106 break;
107 }
108 return ret;
109}
110
111static const struct i2c_device_id ucd9000_id[] = {
112 {"ucd9000", ucd9000},
113 {"ucd90120", ucd90120},
114 {"ucd90124", ucd90124},
115 {"ucd9090", ucd9090},
116 {"ucd90910", ucd90910},
117 {}
118};
119MODULE_DEVICE_TABLE(i2c, ucd9000_id);
120
121static int ucd9000_probe(struct i2c_client *client,
122 const struct i2c_device_id *id)
123{
124 u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1];
125 struct ucd9000_data *data;
126 struct pmbus_driver_info *info;
127 const struct i2c_device_id *mid;
128 int i, ret;
129
130 if (!i2c_check_functionality(client->adapter,
131 I2C_FUNC_SMBUS_BYTE_DATA |
132 I2C_FUNC_SMBUS_BLOCK_DATA))
133 return -ENODEV;
134
135 ret = i2c_smbus_read_block_data(client, UCD9000_DEVICE_ID,
136 block_buffer);
137 if (ret < 0) {
138 dev_err(&client->dev, "Failed to read device ID\n");
139 return ret;
140 }
141 block_buffer[ret] = '\0';
142 dev_info(&client->dev, "Device ID %s\n", block_buffer);
143
144 mid = NULL;
145 for (i = 0; i < ARRAY_SIZE(ucd9000_id); i++) {
146 mid = &ucd9000_id[i];
147 if (!strncasecmp(mid->name, block_buffer, strlen(mid->name)))
148 break;
149 }
150 if (!mid || !strlen(mid->name)) {
151 dev_err(&client->dev, "Unsupported device\n");
152 return -ENODEV;
153 }
154
155 if (id->driver_data != ucd9000 && id->driver_data != mid->driver_data)
156 dev_notice(&client->dev,
157 "Device mismatch: Configured %s, detected %s\n",
158 id->name, mid->name);
159
160 data = kzalloc(sizeof(struct ucd9000_data), GFP_KERNEL);
161 if (!data)
162 return -ENOMEM;
163 info = &data->info;
164
165 ret = i2c_smbus_read_byte_data(client, UCD9000_NUM_PAGES);
166 if (ret < 0) {
167 dev_err(&client->dev,
168 "Failed to read number of active pages\n");
169 goto out;
170 }
171 info->pages = ret;
172 if (!info->pages) {
173 dev_err(&client->dev, "No pages configured\n");
174 ret = -ENODEV;
175 goto out;
176 }
177
178 /* The internal temperature sensor is always active */
179 info->func[0] = PMBUS_HAVE_TEMP;
180
181 /* Everything else is configurable */
182 ret = i2c_smbus_read_block_data(client, UCD9000_MONITOR_CONFIG,
183 block_buffer);
184 if (ret <= 0) {
185 dev_err(&client->dev, "Failed to read configuration data\n");
186 ret = -ENODEV;
187 goto out;
188 }
189 for (i = 0; i < ret; i++) {
190 int page = UCD9000_MON_PAGE(block_buffer[i]);
191
192 if (page >= info->pages)
193 continue;
194
195 switch (UCD9000_MON_TYPE(block_buffer[i])) {
196 case UCD9000_MON_VOLTAGE:
197 case UCD9000_MON_VOLTAGE_HW:
198 info->func[page] |= PMBUS_HAVE_VOUT
199 | PMBUS_HAVE_STATUS_VOUT;
200 break;
201 case UCD9000_MON_TEMPERATURE:
202 info->func[page] |= PMBUS_HAVE_TEMP2
203 | PMBUS_HAVE_STATUS_TEMP;
204 break;
205 case UCD9000_MON_CURRENT:
206 info->func[page] |= PMBUS_HAVE_IOUT
207 | PMBUS_HAVE_STATUS_IOUT;
208 break;
209 default:
210 break;
211 }
212 }
213
214 /* Fan configuration */
215 if (mid->driver_data == ucd90124) {
216 for (i = 0; i < UCD9000_NUM_FAN; i++) {
217 i2c_smbus_write_byte_data(client,
218 UCD9000_FAN_CONFIG_INDEX, i);
219 ret = i2c_smbus_read_block_data(client,
220 UCD9000_FAN_CONFIG,
221 data->fan_data[i]);
222 if (ret < 0)
223 goto out;
224 }
225 i2c_smbus_write_byte_data(client, UCD9000_FAN_CONFIG_INDEX, 0);
226
227 info->read_byte_data = ucd9000_read_byte_data;
228 info->func[0] |= PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12
229 | PMBUS_HAVE_FAN34 | PMBUS_HAVE_STATUS_FAN34;
230 }
231
232 ret = pmbus_do_probe(client, mid, info);
233 if (ret < 0)
234 goto out;
235 return 0;
236
237out:
238 kfree(data);
239 return ret;
240}
241
242static int ucd9000_remove(struct i2c_client *client)
243{
244 int ret;
245 struct ucd9000_data *data;
246
247 data = to_ucd9000_data(pmbus_get_driver_info(client));
248 ret = pmbus_do_remove(client);
249 kfree(data);
250 return ret;
251}
252
253
254/* This is the driver that will be inserted */
255static struct i2c_driver ucd9000_driver = {
256 .driver = {
257 .name = "ucd9000",
258 },
259 .probe = ucd9000_probe,
260 .remove = ucd9000_remove,
261 .id_table = ucd9000_id,
262};
263
264static int __init ucd9000_init(void)
265{
266 return i2c_add_driver(&ucd9000_driver);
267}
268
269static void __exit ucd9000_exit(void)
270{
271 i2c_del_driver(&ucd9000_driver);
272}
273
274MODULE_AUTHOR("Guenter Roeck");
275MODULE_DESCRIPTION("PMBus driver for TI UCD90xxx");
276MODULE_LICENSE("GPL");
277module_init(ucd9000_init);
278module_exit(ucd9000_exit);