aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThilo Cestonaro <thilo@cestona.ro>2016-07-18 07:51:29 -0400
committerGuenter Roeck <linux@roeck-us.net>2016-07-20 09:29:54 -0400
commit08426eda58e07af44aac7c9900ec8a6a62e16b2f (patch)
tree415c0eb9d0d43f85e0a5224ce6b6879be0437bce
parent50c22cd154e5f7d13072d98ef3e2baba3c074734 (diff)
hwmon: Add driver for FTS BMC chip "Teutates"
This driver implements hardware monitoring and watchdog support for the FTS BMC Chip "Teutates". Signed-off-by: Thilo Cestonaro <thilo@cestona.ro> [groeck: Updated subject and description; fixed dependencies] Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r--Documentation/hwmon/ftsteutates23
-rw-r--r--drivers/hwmon/Kconfig12
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/ftsteutates.c820
4 files changed, 856 insertions, 0 deletions
diff --git a/Documentation/hwmon/ftsteutates b/Documentation/hwmon/ftsteutates
new file mode 100644
index 000000000000..2a1bf69c6a26
--- /dev/null
+++ b/Documentation/hwmon/ftsteutates
@@ -0,0 +1,23 @@
1Kernel driver ftsteutates
2=====================
3
4Supported chips:
5 * FTS Teutates
6 Prefix: 'ftsteutates'
7 Addresses scanned: I2C 0x73 (7-Bit)
8
9Author: Thilo Cestonaro <thilo.cestonaro@ts.fujitsu.com>
10
11
12Description
13-----------
14The BMC Teutates is the Eleventh generation of Superior System
15monitoring and thermal management solution. It is builds on the basic
16functionality of the BMC Theseus and contains several new features and
17enhancements. It can monitor up to 4 voltages, 16 temperatures and
188 fans. It also contains an integrated watchdog which is currently
19implemented in this driver.
20
21Specification of the chip can be found here:
22ftp:///pub/Mainboard-OEM-Sales/Services/Software&Tools/Linux_SystemMonitoring&Watchdog&GPIO/BMC-Teutates_Specification_V1.21.pdf
23ftp:///pub/Mainboard-OEM-Sales/Services/Software&Tools/Linux_SystemMonitoring&Watchdog&GPIO/Fujitsu_mainboards-1-Sensors_HowTo-en-US.pdf
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index e72cd3d33d4e..eaf2f916d48c 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -486,6 +486,18 @@ config SENSORS_FSCHMD
486 This driver can also be built as a module. If so, the module 486 This driver can also be built as a module. If so, the module
487 will be called fschmd. 487 will be called fschmd.
488 488
489config SENSORS_FTSTEUTATES
490 tristate "Fujitsu Technology Solutions sensor chip Teutates"
491 depends on I2C && WATCHDOG
492 select WATCHDOG_CORE
493 help
494 If you say yes here you get support for the Fujitsu Technology
495 Solutions (FTS) sensor chip "Teutates" including support for
496 the integrated watchdog.
497
498 This driver can also be built as a module. If so, the module
499 will be called ftsteutates.
500
489config SENSORS_GL518SM 501config SENSORS_GL518SM
490 tristate "Genesys Logic GL518SM" 502 tristate "Genesys Logic GL518SM"
491 depends on I2C 503 depends on I2C
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 446a4e74c7cf..fe87d2895a97 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -62,6 +62,7 @@ obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o
62obj-$(CONFIG_SENSORS_F75375S) += f75375s.o 62obj-$(CONFIG_SENSORS_F75375S) += f75375s.o
63obj-$(CONFIG_SENSORS_FAM15H_POWER) += fam15h_power.o 63obj-$(CONFIG_SENSORS_FAM15H_POWER) += fam15h_power.o
64obj-$(CONFIG_SENSORS_FSCHMD) += fschmd.o 64obj-$(CONFIG_SENSORS_FSCHMD) += fschmd.o
65obj-$(CONFIG_SENSORS_FTSTEUTATES) += ftsteutates.o
65obj-$(CONFIG_SENSORS_G760A) += g760a.o 66obj-$(CONFIG_SENSORS_G760A) += g760a.o
66obj-$(CONFIG_SENSORS_G762) += g762.o 67obj-$(CONFIG_SENSORS_G762) += g762.o
67obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o 68obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o
diff --git a/drivers/hwmon/ftsteutates.c b/drivers/hwmon/ftsteutates.c
new file mode 100644
index 000000000000..aaef5b570da7
--- /dev/null
+++ b/drivers/hwmon/ftsteutates.c
@@ -0,0 +1,820 @@
1/*
2 * Support for the FTS Systemmonitoring Chip "Teutates"
3 *
4 * Copyright (C) 2016 Fujitsu Technology Solutions GmbH,
5 * Thilo Cestonaro <thilo.cestonaro@ts.fujitsu.com>
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 */
18#include <linux/err.h>
19#include <linux/fs.h>
20#include <linux/hwmon.h>
21#include <linux/hwmon-sysfs.h>
22#include <linux/i2c.h>
23#include <linux/init.h>
24#include <linux/jiffies.h>
25#include <linux/module.h>
26#include <linux/mutex.h>
27#include <linux/slab.h>
28#include <linux/sysfs.h>
29#include <linux/uaccess.h>
30#include <linux/version.h>
31#include <linux/watchdog.h>
32
33#define FTS_DEVICE_ID_REG 0x0000
34#define FTS_DEVICE_REVISION_REG 0x0001
35#define FTS_DEVICE_STATUS_REG 0x0004
36#define FTS_SATELLITE_STATUS_REG 0x0005
37#define FTS_EVENT_STATUS_REG 0x0006
38#define FTS_GLOBAL_CONTROL_REG 0x0007
39
40#define FTS_SENSOR_EVENT_REG 0x0010
41
42#define FTS_FAN_EVENT_REG 0x0014
43#define FTS_FAN_PRESENT_REG 0x0015
44
45#define FTS_POWER_ON_TIME_COUNTER_A 0x007A
46#define FTS_POWER_ON_TIME_COUNTER_B 0x007B
47#define FTS_POWER_ON_TIME_COUNTER_C 0x007C
48
49#define FTS_PAGE_SELECT_REG 0x007F
50
51#define FTS_WATCHDOG_TIME_PRESET 0x000B
52#define FTS_WATCHDOG_CONTROL 0x5081
53
54#define FTS_NO_FAN_SENSORS 0x08
55#define FTS_NO_TEMP_SENSORS 0x10
56#define FTS_NO_VOLT_SENSORS 0x04
57
58static struct i2c_device_id fts_id[] = {
59 { "ftsteutates", 0 },
60 { }
61};
62MODULE_DEVICE_TABLE(i2c, fts_id);
63
64enum WATCHDOG_RESOLUTION {
65 seconds = 1,
66 minutes = 60
67};
68
69struct fts_data {
70 struct i2c_client *client;
71 /* update sensor data lock */
72 struct mutex update_lock;
73 /* read/write register lock */
74 struct mutex access_lock;
75 unsigned long last_updated; /* in jiffies */
76 struct watchdog_device wdd;
77 enum WATCHDOG_RESOLUTION resolution;
78 bool valid; /* false until following fields are valid */
79
80 u8 volt[FTS_NO_VOLT_SENSORS];
81
82 u8 temp_input[FTS_NO_TEMP_SENSORS];
83 u8 temp_alarm;
84
85 u8 fan_present;
86 u8 fan_input[FTS_NO_FAN_SENSORS]; /* in rps */
87 u8 fan_source[FTS_NO_FAN_SENSORS];
88 u8 fan_alarm;
89};
90
91#define FTS_REG_FAN_INPUT(idx) ((idx) + 0x20)
92#define FTS_REG_FAN_SOURCE(idx) ((idx) + 0x30)
93#define FTS_REG_FAN_CONTROL(idx) (((idx) << 16) + 0x4881)
94
95#define FTS_REG_TEMP_INPUT(idx) ((idx) + 0x40)
96#define FTS_REG_TEMP_CONTROL(idx) (((idx) << 16) + 0x0681)
97
98#define FTS_REG_VOLT(idx) ((idx) + 0x18)
99
100/*****************************************************************************/
101/* I2C Helper functions */
102/*****************************************************************************/
103static int fts_read_byte(struct i2c_client *client, unsigned short reg)
104{
105 int ret;
106 unsigned char page = reg >> 8;
107 struct fts_data *data = dev_get_drvdata(&client->dev);
108
109 mutex_lock(&data->access_lock);
110
111 dev_dbg(&client->dev, "page select - page: 0x%.02x\n", page);
112 ret = i2c_smbus_write_byte_data(client, FTS_PAGE_SELECT_REG, page);
113 if (ret < 0)
114 goto error;
115
116 reg &= 0xFF;
117 ret = i2c_smbus_read_byte_data(client, reg);
118 dev_dbg(&client->dev, "read - reg: 0x%.02x: val: 0x%.02x\n", reg, ret);
119
120error:
121 mutex_unlock(&data->access_lock);
122 return ret;
123}
124
125static int fts_write_byte(struct i2c_client *client, unsigned short reg,
126 unsigned char value)
127{
128 int ret;
129 unsigned char page = reg >> 8;
130 struct fts_data *data = dev_get_drvdata(&client->dev);
131
132 mutex_lock(&data->access_lock);
133
134 dev_dbg(&client->dev, "page select - page: 0x%.02x\n", page);
135 ret = i2c_smbus_write_byte_data(client, FTS_PAGE_SELECT_REG, page);
136 if (ret < 0)
137 goto error;
138
139 reg &= 0xFF;
140 dev_dbg(&client->dev,
141 "write - reg: 0x%.02x: val: 0x%.02x\n", reg, value);
142 ret = i2c_smbus_write_byte_data(client, reg, value);
143
144error:
145 mutex_unlock(&data->access_lock);
146 return ret;
147}
148
149/*****************************************************************************/
150/* Data Updater Helper function */
151/*****************************************************************************/
152static int fts_update_device(struct fts_data *data)
153{
154 int i;
155 int err = 0;
156
157 mutex_lock(&data->update_lock);
158 if (!time_after(jiffies, data->last_updated + 2 * HZ) && data->valid)
159 goto exit;
160
161 err = fts_read_byte(data->client, FTS_DEVICE_STATUS_REG);
162 if (err < 0)
163 goto exit;
164
165 data->valid = !!(err & 0x02); /* Data not ready yet */
166 if (unlikely(!data->valid)) {
167 err = -EAGAIN;
168 goto exit;
169 }
170
171 err = fts_read_byte(data->client, FTS_FAN_PRESENT_REG);
172 if (err < 0)
173 goto exit;
174 data->fan_present = err;
175
176 err = fts_read_byte(data->client, FTS_FAN_EVENT_REG);
177 if (err < 0)
178 goto exit;
179 data->fan_alarm = err;
180
181 for (i = 0; i < FTS_NO_FAN_SENSORS; i++) {
182 if (data->fan_present & BIT(i)) {
183 err = fts_read_byte(data->client, FTS_REG_FAN_INPUT(i));
184 if (err < 0)
185 goto exit;
186 data->fan_input[i] = err;
187
188 err = fts_read_byte(data->client,
189 FTS_REG_FAN_SOURCE(i));
190 if (err < 0)
191 goto exit;
192 data->fan_source[i] = err;
193 } else {
194 data->fan_input[i] = 0;
195 data->fan_source[i] = 0;
196 }
197 }
198
199 err = fts_read_byte(data->client, FTS_SENSOR_EVENT_REG);
200 if (err < 0)
201 goto exit;
202 data->temp_alarm = err;
203
204 for (i = 0; i < FTS_NO_TEMP_SENSORS; i++) {
205 err = fts_read_byte(data->client, FTS_REG_TEMP_INPUT(i));
206 if (err < 0)
207 goto exit;
208 data->temp_input[i] = err;
209 }
210
211 for (i = 0; i < FTS_NO_VOLT_SENSORS; i++) {
212 err = fts_read_byte(data->client, FTS_REG_VOLT(i));
213 if (err < 0)
214 goto exit;
215 data->volt[i] = err;
216 }
217 data->last_updated = jiffies;
218 err = 0;
219exit:
220 mutex_unlock(&data->update_lock);
221 return err;
222}
223
224/*****************************************************************************/
225/* Watchdog functions */
226/*****************************************************************************/
227static int fts_wd_set_resolution(struct fts_data *data,
228 enum WATCHDOG_RESOLUTION resolution)
229{
230 int ret;
231
232 if (data->resolution == resolution)
233 return 0;
234
235 ret = fts_read_byte(data->client, FTS_WATCHDOG_CONTROL);
236 if (ret < 0)
237 return ret;
238
239 if ((resolution == seconds && ret & BIT(1)) ||
240 (resolution == minutes && (ret & BIT(1)) == 0)) {
241 data->resolution = resolution;
242 return 0;
243 }
244
245 if (resolution == seconds)
246 set_bit(1, (unsigned long *)&ret);
247 else
248 ret &= ~BIT(1);
249
250 ret = fts_write_byte(data->client, FTS_WATCHDOG_CONTROL, ret);
251 if (ret < 0)
252 return ret;
253
254 data->resolution = resolution;
255 return ret;
256}
257
258static int fts_wd_set_timeout(struct watchdog_device *wdd, unsigned int timeout)
259{
260 struct fts_data *data;
261 enum WATCHDOG_RESOLUTION resolution = seconds;
262 int ret;
263
264 data = watchdog_get_drvdata(wdd);
265 /* switch watchdog resolution to minutes if timeout does not fit
266 * into a byte
267 */
268 if (timeout > 0xFF) {
269 timeout = DIV_ROUND_UP(timeout, 60) * 60;
270 resolution = minutes;
271 }
272
273 ret = fts_wd_set_resolution(data, resolution);
274 if (ret < 0)
275 return ret;
276
277 wdd->timeout = timeout;
278 return 0;
279}
280
281static int fts_wd_start(struct watchdog_device *wdd)
282{
283 struct fts_data *data = watchdog_get_drvdata(wdd);
284
285 return fts_write_byte(data->client, FTS_WATCHDOG_TIME_PRESET,
286 wdd->timeout / (u8)data->resolution);
287}
288
289static int fts_wd_stop(struct watchdog_device *wdd)
290{
291 struct fts_data *data;
292
293 data = watchdog_get_drvdata(wdd);
294 return fts_write_byte(data->client, FTS_WATCHDOG_TIME_PRESET, 0);
295}
296
297static const struct watchdog_info fts_wd_info = {
298 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
299 .identity = "FTS Teutates Hardware Watchdog",
300};
301
302static const struct watchdog_ops fts_wd_ops = {
303 .owner = THIS_MODULE,
304 .start = fts_wd_start,
305 .stop = fts_wd_stop,
306 .set_timeout = fts_wd_set_timeout,
307};
308
309static int fts_watchdog_init(struct fts_data *data)
310{
311 int timeout, ret;
312
313 watchdog_set_drvdata(&data->wdd, data);
314
315 timeout = fts_read_byte(data->client, FTS_WATCHDOG_TIME_PRESET);
316 if (timeout < 0)
317 return timeout;
318
319 /* watchdog not running, set timeout to a default of 60 sec. */
320 if (timeout == 0) {
321 ret = fts_wd_set_resolution(data, seconds);
322 if (ret < 0)
323 return ret;
324 data->wdd.timeout = 60;
325 } else {
326 ret = fts_read_byte(data->client, FTS_WATCHDOG_CONTROL);
327 if (ret < 0)
328 return ret;
329
330 data->resolution = ret & BIT(1) ? seconds : minutes;
331 data->wdd.timeout = timeout * (u8)data->resolution;
332 set_bit(WDOG_HW_RUNNING, &data->wdd.status);
333 }
334
335 /* Register our watchdog part */
336 data->wdd.info = &fts_wd_info;
337 data->wdd.ops = &fts_wd_ops;
338 data->wdd.parent = &data->client->dev;
339 data->wdd.min_timeout = 1;
340
341 /* max timeout 255 minutes. */
342 data->wdd.max_hw_heartbeat_ms = 0xFF * 60 * MSEC_PER_SEC;
343
344 return watchdog_register_device(&data->wdd);
345}
346
347/*****************************************************************************/
348/* SysFS handler functions */
349/*****************************************************************************/
350static ssize_t show_in_value(struct device *dev,
351 struct device_attribute *devattr, char *buf)
352{
353 struct fts_data *data = dev_get_drvdata(dev);
354 int index = to_sensor_dev_attr(devattr)->index;
355 int err;
356
357 err = fts_update_device(data);
358 if (err < 0)
359 return err;
360
361 return sprintf(buf, "%u\n", data->volt[index]);
362}
363
364static ssize_t show_temp_value(struct device *dev,
365 struct device_attribute *devattr, char *buf)
366{
367 struct fts_data *data = dev_get_drvdata(dev);
368 int index = to_sensor_dev_attr(devattr)->index;
369 int err;
370
371 err = fts_update_device(data);
372 if (err < 0)
373 return err;
374
375 return sprintf(buf, "%u\n", data->temp_input[index]);
376}
377
378static ssize_t show_temp_fault(struct device *dev,
379 struct device_attribute *devattr, char *buf)
380{
381 struct fts_data *data = dev_get_drvdata(dev);
382 int index = to_sensor_dev_attr(devattr)->index;
383 int err;
384
385 err = fts_update_device(data);
386 if (err < 0)
387 return err;
388
389 /* 00h Temperature = Sensor Error */
390 return sprintf(buf, "%d\n", data->temp_input[index] == 0);
391}
392
393static ssize_t show_temp_alarm(struct device *dev,
394 struct device_attribute *devattr, char *buf)
395{
396 struct fts_data *data = dev_get_drvdata(dev);
397 int index = to_sensor_dev_attr(devattr)->index;
398 int err;
399
400 err = fts_update_device(data);
401 if (err < 0)
402 return err;
403
404 return sprintf(buf, "%u\n", !!(data->temp_alarm & BIT(index)));
405}
406
407static ssize_t
408clear_temp_alarm(struct device *dev, struct device_attribute *devattr,
409 const char *buf, size_t count)
410{
411 struct fts_data *data = dev_get_drvdata(dev);
412 int index = to_sensor_dev_attr(devattr)->index;
413 long ret;
414
415 ret = fts_update_device(data);
416 if (ret < 0)
417 return ret;
418
419 if (kstrtoul(buf, 10, &ret) || ret != 0)
420 return -EINVAL;
421
422 mutex_lock(&data->update_lock);
423 ret = fts_read_byte(data->client, FTS_REG_TEMP_CONTROL(index));
424 if (ret < 0)
425 goto error;
426
427 ret = fts_write_byte(data->client, FTS_REG_TEMP_CONTROL(index),
428 ret | 0x1);
429 if (ret < 0)
430 goto error;
431
432 data->valid = false;
433error:
434 mutex_unlock(&data->update_lock);
435 return ret;
436}
437
438static ssize_t show_fan_value(struct device *dev,
439 struct device_attribute *devattr, char *buf)
440{
441 struct fts_data *data = dev_get_drvdata(dev);
442 int index = to_sensor_dev_attr(devattr)->index;
443 int err;
444
445 err = fts_update_device(data);
446 if (err < 0)
447 return err;
448
449 return sprintf(buf, "%u\n", data->fan_input[index]);
450}
451
452static ssize_t show_fan_source(struct device *dev,
453 struct device_attribute *devattr, char *buf)
454{
455 struct fts_data *data = dev_get_drvdata(dev);
456 int index = to_sensor_dev_attr(devattr)->index;
457 int err;
458
459 err = fts_update_device(data);
460 if (err < 0)
461 return err;
462
463 return sprintf(buf, "%u\n", data->fan_source[index]);
464}
465
466static ssize_t show_fan_alarm(struct device *dev,
467 struct device_attribute *devattr, char *buf)
468{
469 struct fts_data *data = dev_get_drvdata(dev);
470 int index = to_sensor_dev_attr(devattr)->index;
471 int err;
472
473 err = fts_update_device(data);
474 if (err < 0)
475 return err;
476
477 return sprintf(buf, "%d\n", !!(data->fan_alarm & BIT(index)));
478}
479
480static ssize_t
481clear_fan_alarm(struct device *dev, struct device_attribute *devattr,
482 const char *buf, size_t count)
483{
484 struct fts_data *data = dev_get_drvdata(dev);
485 int index = to_sensor_dev_attr(devattr)->index;
486 long ret;
487
488 ret = fts_update_device(data);
489 if (ret < 0)
490 return ret;
491
492 if (kstrtoul(buf, 10, &ret) || ret != 0)
493 return -EINVAL;
494
495 mutex_lock(&data->update_lock);
496 ret = fts_read_byte(data->client, FTS_REG_FAN_CONTROL(index));
497 if (ret < 0)
498 goto error;
499
500 ret = fts_write_byte(data->client, FTS_REG_FAN_CONTROL(index),
501 ret | 0x1);
502 if (ret < 0)
503 goto error;
504
505 data->valid = false;
506error:
507 mutex_unlock(&data->update_lock);
508 return ret;
509}
510
511/*****************************************************************************/
512/* SysFS structs */
513/*****************************************************************************/
514
515/* Temprature sensors */
516static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_value, NULL, 0);
517static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_value, NULL, 1);
518static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_value, NULL, 2);
519static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_value, NULL, 3);
520static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp_value, NULL, 4);
521static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_temp_value, NULL, 5);
522static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, show_temp_value, NULL, 6);
523static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_temp_value, NULL, 7);
524static SENSOR_DEVICE_ATTR(temp9_input, S_IRUGO, show_temp_value, NULL, 8);
525static SENSOR_DEVICE_ATTR(temp10_input, S_IRUGO, show_temp_value, NULL, 9);
526static SENSOR_DEVICE_ATTR(temp11_input, S_IRUGO, show_temp_value, NULL, 10);
527static SENSOR_DEVICE_ATTR(temp12_input, S_IRUGO, show_temp_value, NULL, 11);
528static SENSOR_DEVICE_ATTR(temp13_input, S_IRUGO, show_temp_value, NULL, 12);
529static SENSOR_DEVICE_ATTR(temp14_input, S_IRUGO, show_temp_value, NULL, 13);
530static SENSOR_DEVICE_ATTR(temp15_input, S_IRUGO, show_temp_value, NULL, 14);
531static SENSOR_DEVICE_ATTR(temp16_input, S_IRUGO, show_temp_value, NULL, 15);
532
533static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0);
534static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1);
535static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2);
536static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_temp_fault, NULL, 3);
537static SENSOR_DEVICE_ATTR(temp5_fault, S_IRUGO, show_temp_fault, NULL, 4);
538static SENSOR_DEVICE_ATTR(temp6_fault, S_IRUGO, show_temp_fault, NULL, 5);
539static SENSOR_DEVICE_ATTR(temp7_fault, S_IRUGO, show_temp_fault, NULL, 6);
540static SENSOR_DEVICE_ATTR(temp8_fault, S_IRUGO, show_temp_fault, NULL, 7);
541static SENSOR_DEVICE_ATTR(temp9_fault, S_IRUGO, show_temp_fault, NULL, 8);
542static SENSOR_DEVICE_ATTR(temp10_fault, S_IRUGO, show_temp_fault, NULL, 9);
543static SENSOR_DEVICE_ATTR(temp11_fault, S_IRUGO, show_temp_fault, NULL, 10);
544static SENSOR_DEVICE_ATTR(temp12_fault, S_IRUGO, show_temp_fault, NULL, 11);
545static SENSOR_DEVICE_ATTR(temp13_fault, S_IRUGO, show_temp_fault, NULL, 12);
546static SENSOR_DEVICE_ATTR(temp14_fault, S_IRUGO, show_temp_fault, NULL, 13);
547static SENSOR_DEVICE_ATTR(temp15_fault, S_IRUGO, show_temp_fault, NULL, 14);
548static SENSOR_DEVICE_ATTR(temp16_fault, S_IRUGO, show_temp_fault, NULL, 15);
549
550static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO | S_IWUSR, show_temp_alarm,
551 clear_temp_alarm, 0);
552static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO | S_IWUSR, show_temp_alarm,
553 clear_temp_alarm, 1);
554static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO | S_IWUSR, show_temp_alarm,
555 clear_temp_alarm, 2);
556static SENSOR_DEVICE_ATTR(temp4_alarm, S_IRUGO | S_IWUSR, show_temp_alarm,
557 clear_temp_alarm, 3);
558static SENSOR_DEVICE_ATTR(temp5_alarm, S_IRUGO | S_IWUSR, show_temp_alarm,
559 clear_temp_alarm, 4);
560static SENSOR_DEVICE_ATTR(temp6_alarm, S_IRUGO | S_IWUSR, show_temp_alarm,
561 clear_temp_alarm, 5);
562static SENSOR_DEVICE_ATTR(temp7_alarm, S_IRUGO | S_IWUSR, show_temp_alarm,
563 clear_temp_alarm, 6);
564static SENSOR_DEVICE_ATTR(temp8_alarm, S_IRUGO | S_IWUSR, show_temp_alarm,
565 clear_temp_alarm, 7);
566static SENSOR_DEVICE_ATTR(temp9_alarm, S_IRUGO | S_IWUSR, show_temp_alarm,
567 clear_temp_alarm, 8);
568static SENSOR_DEVICE_ATTR(temp10_alarm, S_IRUGO | S_IWUSR, show_temp_alarm,
569 clear_temp_alarm, 9);
570static SENSOR_DEVICE_ATTR(temp11_alarm, S_IRUGO | S_IWUSR, show_temp_alarm,
571 clear_temp_alarm, 10);
572static SENSOR_DEVICE_ATTR(temp12_alarm, S_IRUGO | S_IWUSR, show_temp_alarm,
573 clear_temp_alarm, 11);
574static SENSOR_DEVICE_ATTR(temp13_alarm, S_IRUGO | S_IWUSR, show_temp_alarm,
575 clear_temp_alarm, 12);
576static SENSOR_DEVICE_ATTR(temp14_alarm, S_IRUGO | S_IWUSR, show_temp_alarm,
577 clear_temp_alarm, 13);
578static SENSOR_DEVICE_ATTR(temp15_alarm, S_IRUGO | S_IWUSR, show_temp_alarm,
579 clear_temp_alarm, 14);
580static SENSOR_DEVICE_ATTR(temp16_alarm, S_IRUGO | S_IWUSR, show_temp_alarm,
581 clear_temp_alarm, 15);
582
583static struct attribute *fts_temp_attrs[] = {
584 &sensor_dev_attr_temp1_input.dev_attr.attr,
585 &sensor_dev_attr_temp2_input.dev_attr.attr,
586 &sensor_dev_attr_temp3_input.dev_attr.attr,
587 &sensor_dev_attr_temp4_input.dev_attr.attr,
588 &sensor_dev_attr_temp5_input.dev_attr.attr,
589 &sensor_dev_attr_temp6_input.dev_attr.attr,
590 &sensor_dev_attr_temp7_input.dev_attr.attr,
591 &sensor_dev_attr_temp8_input.dev_attr.attr,
592 &sensor_dev_attr_temp9_input.dev_attr.attr,
593 &sensor_dev_attr_temp10_input.dev_attr.attr,
594 &sensor_dev_attr_temp11_input.dev_attr.attr,
595 &sensor_dev_attr_temp12_input.dev_attr.attr,
596 &sensor_dev_attr_temp13_input.dev_attr.attr,
597 &sensor_dev_attr_temp14_input.dev_attr.attr,
598 &sensor_dev_attr_temp15_input.dev_attr.attr,
599 &sensor_dev_attr_temp16_input.dev_attr.attr,
600
601 &sensor_dev_attr_temp1_fault.dev_attr.attr,
602 &sensor_dev_attr_temp2_fault.dev_attr.attr,
603 &sensor_dev_attr_temp3_fault.dev_attr.attr,
604 &sensor_dev_attr_temp4_fault.dev_attr.attr,
605 &sensor_dev_attr_temp5_fault.dev_attr.attr,
606 &sensor_dev_attr_temp6_fault.dev_attr.attr,
607 &sensor_dev_attr_temp7_fault.dev_attr.attr,
608 &sensor_dev_attr_temp8_fault.dev_attr.attr,
609 &sensor_dev_attr_temp9_fault.dev_attr.attr,
610 &sensor_dev_attr_temp10_fault.dev_attr.attr,
611 &sensor_dev_attr_temp11_fault.dev_attr.attr,
612 &sensor_dev_attr_temp12_fault.dev_attr.attr,
613 &sensor_dev_attr_temp13_fault.dev_attr.attr,
614 &sensor_dev_attr_temp14_fault.dev_attr.attr,
615 &sensor_dev_attr_temp15_fault.dev_attr.attr,
616 &sensor_dev_attr_temp16_fault.dev_attr.attr,
617
618 &sensor_dev_attr_temp1_alarm.dev_attr.attr,
619 &sensor_dev_attr_temp2_alarm.dev_attr.attr,
620 &sensor_dev_attr_temp3_alarm.dev_attr.attr,
621 &sensor_dev_attr_temp4_alarm.dev_attr.attr,
622 &sensor_dev_attr_temp5_alarm.dev_attr.attr,
623 &sensor_dev_attr_temp6_alarm.dev_attr.attr,
624 &sensor_dev_attr_temp7_alarm.dev_attr.attr,
625 &sensor_dev_attr_temp8_alarm.dev_attr.attr,
626 &sensor_dev_attr_temp9_alarm.dev_attr.attr,
627 &sensor_dev_attr_temp10_alarm.dev_attr.attr,
628 &sensor_dev_attr_temp11_alarm.dev_attr.attr,
629 &sensor_dev_attr_temp12_alarm.dev_attr.attr,
630 &sensor_dev_attr_temp13_alarm.dev_attr.attr,
631 &sensor_dev_attr_temp14_alarm.dev_attr.attr,
632 &sensor_dev_attr_temp15_alarm.dev_attr.attr,
633 &sensor_dev_attr_temp16_alarm.dev_attr.attr,
634 NULL
635};
636
637/* Fans */
638static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_value, NULL, 0);
639static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_value, NULL, 1);
640static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan_value, NULL, 2);
641static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan_value, NULL, 3);
642static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan_value, NULL, 4);
643static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan_value, NULL, 5);
644static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan_value, NULL, 6);
645static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan_value, NULL, 7);
646
647static SENSOR_DEVICE_ATTR(fan1_source, S_IRUGO, show_fan_source, NULL, 0);
648static SENSOR_DEVICE_ATTR(fan2_source, S_IRUGO, show_fan_source, NULL, 1);
649static SENSOR_DEVICE_ATTR(fan3_source, S_IRUGO, show_fan_source, NULL, 2);
650static SENSOR_DEVICE_ATTR(fan4_source, S_IRUGO, show_fan_source, NULL, 3);
651static SENSOR_DEVICE_ATTR(fan5_source, S_IRUGO, show_fan_source, NULL, 4);
652static SENSOR_DEVICE_ATTR(fan6_source, S_IRUGO, show_fan_source, NULL, 5);
653static SENSOR_DEVICE_ATTR(fan7_source, S_IRUGO, show_fan_source, NULL, 6);
654static SENSOR_DEVICE_ATTR(fan8_source, S_IRUGO, show_fan_source, NULL, 7);
655
656static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO | S_IWUSR,
657 show_fan_alarm, clear_fan_alarm, 0);
658static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO | S_IWUSR,
659 show_fan_alarm, clear_fan_alarm, 1);
660static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO | S_IWUSR,
661 show_fan_alarm, clear_fan_alarm, 2);
662static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO | S_IWUSR,
663 show_fan_alarm, clear_fan_alarm, 3);
664static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO | S_IWUSR,
665 show_fan_alarm, clear_fan_alarm, 4);
666static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO | S_IWUSR,
667 show_fan_alarm, clear_fan_alarm, 5);
668static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO | S_IWUSR,
669 show_fan_alarm, clear_fan_alarm, 6);
670static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO | S_IWUSR,
671 show_fan_alarm, clear_fan_alarm, 7);
672
673static struct attribute *fts_fan_attrs[] = {
674 &sensor_dev_attr_fan1_input.dev_attr.attr,
675 &sensor_dev_attr_fan2_input.dev_attr.attr,
676 &sensor_dev_attr_fan3_input.dev_attr.attr,
677 &sensor_dev_attr_fan4_input.dev_attr.attr,
678 &sensor_dev_attr_fan5_input.dev_attr.attr,
679 &sensor_dev_attr_fan6_input.dev_attr.attr,
680 &sensor_dev_attr_fan7_input.dev_attr.attr,
681 &sensor_dev_attr_fan8_input.dev_attr.attr,
682
683 &sensor_dev_attr_fan1_source.dev_attr.attr,
684 &sensor_dev_attr_fan2_source.dev_attr.attr,
685 &sensor_dev_attr_fan3_source.dev_attr.attr,
686 &sensor_dev_attr_fan4_source.dev_attr.attr,
687 &sensor_dev_attr_fan5_source.dev_attr.attr,
688 &sensor_dev_attr_fan6_source.dev_attr.attr,
689 &sensor_dev_attr_fan7_source.dev_attr.attr,
690 &sensor_dev_attr_fan8_source.dev_attr.attr,
691
692 &sensor_dev_attr_fan1_alarm.dev_attr.attr,
693 &sensor_dev_attr_fan2_alarm.dev_attr.attr,
694 &sensor_dev_attr_fan3_alarm.dev_attr.attr,
695 &sensor_dev_attr_fan4_alarm.dev_attr.attr,
696 &sensor_dev_attr_fan5_alarm.dev_attr.attr,
697 &sensor_dev_attr_fan6_alarm.dev_attr.attr,
698 &sensor_dev_attr_fan7_alarm.dev_attr.attr,
699 &sensor_dev_attr_fan8_alarm.dev_attr.attr,
700 NULL
701};
702
703/* Voltages */
704static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in_value, NULL, 0);
705static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in_value, NULL, 1);
706static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in_value, NULL, 2);
707static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in_value, NULL, 3);
708static struct attribute *fts_voltage_attrs[] = {
709 &sensor_dev_attr_in1_input.dev_attr.attr,
710 &sensor_dev_attr_in2_input.dev_attr.attr,
711 &sensor_dev_attr_in3_input.dev_attr.attr,
712 &sensor_dev_attr_in4_input.dev_attr.attr,
713 NULL
714};
715
716static const struct attribute_group fts_voltage_attr_group = {
717 .attrs = fts_voltage_attrs
718};
719
720static const struct attribute_group fts_temp_attr_group = {
721 .attrs = fts_temp_attrs
722};
723
724static const struct attribute_group fts_fan_attr_group = {
725 .attrs = fts_fan_attrs
726};
727
728static const struct attribute_group *fts_attr_groups[] = {
729 &fts_voltage_attr_group,
730 &fts_temp_attr_group,
731 &fts_fan_attr_group,
732 NULL
733};
734
735/*****************************************************************************/
736/* Module initialization / remove functions */
737/*****************************************************************************/
738static int fts_remove(struct i2c_client *client)
739{
740 struct fts_data *data = dev_get_drvdata(&client->dev);
741
742 watchdog_unregister_device(&data->wdd);
743 return 0;
744}
745
746static int fts_probe(struct i2c_client *client, const struct i2c_device_id *id)
747{
748 u8 revision;
749 struct fts_data *data;
750 int err;
751 s8 deviceid;
752 struct device *hwmon_dev;
753
754 if (client->addr != 0x73)
755 return -ENODEV;
756
757 /* Baseboard Management Controller check */
758 deviceid = i2c_smbus_read_byte_data(client, FTS_DEVICE_ID_REG);
759 if (deviceid > 0 && (deviceid & 0xF0) == 0x10) {
760 switch (deviceid & 0x0F) {
761 case 0x01:
762 break;
763 default:
764 dev_dbg(&client->dev,
765 "No Baseboard Management Controller\n");
766 return -ENODEV;
767 }
768 } else {
769 dev_dbg(&client->dev, "No fujitsu board\n");
770 return -ENODEV;
771 }
772
773 data = devm_kzalloc(&client->dev, sizeof(struct fts_data),
774 GFP_KERNEL);
775 if (!data)
776 return -ENOMEM;
777
778 mutex_init(&data->update_lock);
779 mutex_init(&data->access_lock);
780 data->client = client;
781 dev_set_drvdata(&client->dev, data);
782
783 err = i2c_smbus_read_byte_data(client, FTS_DEVICE_REVISION_REG);
784 if (err < 0)
785 return err;
786 revision = err;
787
788 hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev,
789 "ftsteutates",
790 data,
791 fts_attr_groups);
792 if (IS_ERR(hwmon_dev))
793 return PTR_ERR(hwmon_dev);
794
795 err = fts_watchdog_init(data);
796 if (err)
797 return err;
798
799 dev_info(&client->dev, "Detected FTS Teutates chip, revision: %d.%d\n",
800 (revision & 0xF0) >> 4, revision & 0x0F);
801 return 0;
802}
803
804/*****************************************************************************/
805/* Module Details */
806/*****************************************************************************/
807static struct i2c_driver fts_driver = {
808 .driver = {
809 .name = "ftsteutates",
810 },
811 .id_table = fts_id,
812 .probe = fts_probe,
813 .remove = fts_remove,
814};
815
816module_i2c_driver(fts_driver);
817
818MODULE_AUTHOR("Thilo Cestonaro <thilo.cestonaro@ts.fujitsu.com>");
819MODULE_DESCRIPTION("FTS Teutates driver");
820MODULE_LICENSE("GPL");