aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2009-09-23 16:59:42 -0400
committerJean Delvare <khali@linux-fr.org>2009-09-23 16:59:42 -0400
commit91f17e02a224dc649eaffc8e0bca6db85efb9cd7 (patch)
tree5f538b6afab29f1e63cabdfa42a93d9a14e9d4d8
parent49dc9efed05ad3e49000097ce1ec31cd3bbc909b (diff)
hwmon: Delete deprecated FSC drivers
The legacy fscpos and fscher drivers have been replaced by the unified fschmd driver. The transition period is over now, we can delete them. Signed-off-by: Jean Delvare <khali@linux-fr.org> Acked-by: Hans de Goede <hdegoede@redhat.com>
-rw-r--r--Documentation/feature-removal-schedule.txt8
-rw-r--r--Documentation/hwmon/fscher169
-rw-r--r--drivers/hwmon/Kconfig28
-rw-r--r--drivers/hwmon/Makefile2
-rw-r--r--drivers/hwmon/fscher.c680
-rw-r--r--drivers/hwmon/fscpos.c654
6 files changed, 0 insertions, 1541 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index fa75220f8d34..89a47b5aff07 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -354,14 +354,6 @@ Who: Krzysztof Piotr Oledzki <ole@ans.pl>
354 354
355--------------------------- 355---------------------------
356 356
357What: fscher and fscpos drivers
358When: June 2009
359Why: Deprecated by the new fschmd driver.
360Who: Hans de Goede <hdegoede@redhat.com>
361 Jean Delvare <khali@linux-fr.org>
362
363---------------------------
364
365What: sysfs ui for changing p4-clockmod parameters 357What: sysfs ui for changing p4-clockmod parameters
366When: September 2009 358When: September 2009
367Why: See commits 129f8ae9b1b5be94517da76009ea956e89104ce8 and 359Why: See commits 129f8ae9b1b5be94517da76009ea956e89104ce8 and
diff --git a/Documentation/hwmon/fscher b/Documentation/hwmon/fscher
deleted file mode 100644
index 64031659aff3..000000000000
--- a/Documentation/hwmon/fscher
+++ /dev/null
@@ -1,169 +0,0 @@
1Kernel driver fscher
2====================
3
4Supported chips:
5 * Fujitsu-Siemens Hermes chip
6 Prefix: 'fscher'
7 Addresses scanned: I2C 0x73
8
9Authors:
10 Reinhard Nissl <rnissl@gmx.de> based on work
11 from Hermann Jung <hej@odn.de>,
12 Frodo Looijaard <frodol@dds.nl>,
13 Philip Edelbrock <phil@netroedge.com>
14
15Description
16-----------
17
18This driver implements support for the Fujitsu-Siemens Hermes chip. It is
19described in the 'Register Set Specification BMC Hermes based Systemboard'
20from Fujitsu-Siemens.
21
22The Hermes chip implements a hardware-based system management, e.g. for
23controlling fan speed and core voltage. There is also a watchdog counter on
24the chip which can trigger an alarm and even shut the system down.
25
26The chip provides three temperature values (CPU, motherboard and
27auxiliary), three voltage values (+12V, +5V and battery) and three fans
28(power supply, CPU and auxiliary).
29
30Temperatures are measured in degrees Celsius. The resolution is 1 degree.
31
32Fan rotation speeds are reported in RPM (rotations per minute). The value
33can be divided by a programmable divider (1, 2 or 4) which is stored on
34the chip.
35
36Voltage sensors (also known as "in" sensors) report their values in volts.
37
38All values are reported as final values from the driver. There is no need
39for further calculations.
40
41
42Detailed description
43--------------------
44
45Below you'll find a single line description of all the bit values. With
46this information, you're able to decode e. g. alarms, wdog, etc. To make
47use of the watchdog, you'll need to set the watchdog time and enable the
48watchdog. After that it is necessary to restart the watchdog time within
49the specified period of time, or a system reset will occur.
50
51* revision
52 READING & 0xff = 0x??: HERMES revision identification
53
54* alarms
55 READING & 0x80 = 0x80: CPU throttling active
56 READING & 0x80 = 0x00: CPU running at full speed
57
58 READING & 0x10 = 0x10: software event (see control:1)
59 READING & 0x10 = 0x00: no software event
60
61 READING & 0x08 = 0x08: watchdog event (see wdog:2)
62 READING & 0x08 = 0x00: no watchdog event
63
64 READING & 0x02 = 0x02: thermal event (see temp*:1)
65 READING & 0x02 = 0x00: no thermal event
66
67 READING & 0x01 = 0x01: fan event (see fan*:1)
68 READING & 0x01 = 0x00: no fan event
69
70 READING & 0x13 ! 0x00: ALERT LED is flashing
71
72* control
73 READING & 0x01 = 0x01: software event
74 READING & 0x01 = 0x00: no software event
75
76 WRITING & 0x01 = 0x01: set software event
77 WRITING & 0x01 = 0x00: clear software event
78
79* watchdog_control
80 READING & 0x80 = 0x80: power off on watchdog event while thermal event
81 READING & 0x80 = 0x00: watchdog power off disabled (just system reset enabled)
82
83 READING & 0x40 = 0x40: watchdog timebase 60 seconds (see also wdog:1)
84 READING & 0x40 = 0x00: watchdog timebase 2 seconds
85
86 READING & 0x10 = 0x10: watchdog enabled
87 READING & 0x10 = 0x00: watchdog disabled
88
89 WRITING & 0x80 = 0x80: enable "power off on watchdog event while thermal event"
90 WRITING & 0x80 = 0x00: disable "power off on watchdog event while thermal event"
91
92 WRITING & 0x40 = 0x40: set watchdog timebase to 60 seconds
93 WRITING & 0x40 = 0x00: set watchdog timebase to 2 seconds
94
95 WRITING & 0x20 = 0x20: disable watchdog
96
97 WRITING & 0x10 = 0x10: enable watchdog / restart watchdog time
98
99* watchdog_state
100 READING & 0x02 = 0x02: watchdog system reset occurred
101 READING & 0x02 = 0x00: no watchdog system reset occurred
102
103 WRITING & 0x02 = 0x02: clear watchdog event
104
105* watchdog_preset
106 READING & 0xff = 0x??: configured watch dog time in units (see wdog:3 0x40)
107
108 WRITING & 0xff = 0x??: configure watch dog time in units
109
110* in* (0: +5V, 1: +12V, 2: onboard 3V battery)
111 READING: actual voltage value
112
113* temp*_status (1: CPU sensor, 2: onboard sensor, 3: auxiliary sensor)
114 READING & 0x02 = 0x02: thermal event (overtemperature)
115 READING & 0x02 = 0x00: no thermal event
116
117 READING & 0x01 = 0x01: sensor is working
118 READING & 0x01 = 0x00: sensor is faulty
119
120 WRITING & 0x02 = 0x02: clear thermal event
121
122* temp*_input (1: CPU sensor, 2: onboard sensor, 3: auxiliary sensor)
123 READING: actual temperature value
124
125* fan*_status (1: power supply fan, 2: CPU fan, 3: auxiliary fan)
126 READING & 0x04 = 0x04: fan event (fan fault)
127 READING & 0x04 = 0x00: no fan event
128
129 WRITING & 0x04 = 0x04: clear fan event
130
131* fan*_div (1: power supply fan, 2: CPU fan, 3: auxiliary fan)
132 Divisors 2,4 and 8 are supported, both for reading and writing
133
134* fan*_pwm (1: power supply fan, 2: CPU fan, 3: auxiliary fan)
135 READING & 0xff = 0x00: fan may be switched off
136 READING & 0xff = 0x01: fan must run at least at minimum speed (supply: 6V)
137 READING & 0xff = 0xff: fan must run at maximum speed (supply: 12V)
138 READING & 0xff = 0x??: fan must run at least at given speed (supply: 6V..12V)
139
140 WRITING & 0xff = 0x00: fan may be switched off
141 WRITING & 0xff = 0x01: fan must run at least at minimum speed (supply: 6V)
142 WRITING & 0xff = 0xff: fan must run at maximum speed (supply: 12V)
143 WRITING & 0xff = 0x??: fan must run at least at given speed (supply: 6V..12V)
144
145* fan*_input (1: power supply fan, 2: CPU fan, 3: auxiliary fan)
146 READING: actual RPM value
147
148
149Limitations
150-----------
151
152* Measuring fan speed
153It seems that the chip counts "ripples" (typical fans produce 2 ripples per
154rotation while VERAX fans produce 18) in a 9-bit register. This register is
155read out every second, then the ripple prescaler (2, 4 or 8) is applied and
156the result is stored in the 8 bit output register. Due to the limitation of
157the counting register to 9 bits, it is impossible to measure a VERAX fan
158properly (even with a prescaler of 8). At its maximum speed of 3500 RPM the
159fan produces 1080 ripples per second which causes the counting register to
160overflow twice, leading to only 186 RPM.
161
162* Measuring input voltages
163in2 ("battery") reports the voltage of the onboard lithium battery and not
164+3.3V from the power supply.
165
166* Undocumented features
167Fujitsu-Siemens Computers has not documented all features of the chip so
168far. Their software, System Guard, shows that there are a still some
169features which cannot be controlled by this implementation.
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index ed7711d11ae8..9d881f708912 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -325,34 +325,6 @@ config SENSORS_F75375S
325 This driver can also be built as a module. If so, the module 325 This driver can also be built as a module. If so, the module
326 will be called f75375s. 326 will be called f75375s.
327 327
328config SENSORS_FSCHER
329 tristate "FSC Hermes (DEPRECATED)"
330 depends on X86 && I2C
331 help
332 This driver is DEPRECATED please use the new merged fschmd
333 ("FSC Poseidon, Scylla, Hermes, Heimdall and Heracles") driver
334 instead.
335
336 If you say yes here you get support for Fujitsu Siemens
337 Computers Hermes sensor chips.
338
339 This driver can also be built as a module. If so, the module
340 will be called fscher.
341
342config SENSORS_FSCPOS
343 tristate "FSC Poseidon (DEPRECATED)"
344 depends on X86 && I2C
345 help
346 This driver is DEPRECATED please use the new merged fschmd
347 ("FSC Poseidon, Scylla, Hermes, Heimdall and Heracles") driver
348 instead.
349
350 If you say yes here you get support for Fujitsu Siemens
351 Computers Poseidon sensor chips.
352
353 This driver can also be built as a module. If so, the module
354 will be called fscpos.
355
356config SENSORS_FSCHMD 328config SENSORS_FSCHMD
357 tristate "Fujitsu Siemens Computers sensor chips" 329 tristate "Fujitsu Siemens Computers sensor chips"
358 depends on X86 && I2C 330 depends on X86 && I2C
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index bcf73a9bb619..9f46cb019cc6 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -42,9 +42,7 @@ obj-$(CONFIG_SENSORS_DS1621) += ds1621.o
42obj-$(CONFIG_SENSORS_F71805F) += f71805f.o 42obj-$(CONFIG_SENSORS_F71805F) += f71805f.o
43obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o 43obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o
44obj-$(CONFIG_SENSORS_F75375S) += f75375s.o 44obj-$(CONFIG_SENSORS_F75375S) += f75375s.o
45obj-$(CONFIG_SENSORS_FSCHER) += fscher.o
46obj-$(CONFIG_SENSORS_FSCHMD) += fschmd.o 45obj-$(CONFIG_SENSORS_FSCHMD) += fschmd.o
47obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o
48obj-$(CONFIG_SENSORS_G760A) += g760a.o 46obj-$(CONFIG_SENSORS_G760A) += g760a.o
49obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o 47obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o
50obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o 48obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o
diff --git a/drivers/hwmon/fscher.c b/drivers/hwmon/fscher.c
deleted file mode 100644
index 12c70e402cb2..000000000000
--- a/drivers/hwmon/fscher.c
+++ /dev/null
@@ -1,680 +0,0 @@
1/*
2 * fscher.c - Part of lm_sensors, Linux kernel modules for hardware
3 * monitoring
4 * Copyright (C) 2003, 2004 Reinhard Nissl <rnissl@gmx.de>
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 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21/*
22 * fujitsu siemens hermes chip,
23 * module based on fscpos.c
24 * Copyright (C) 2000 Hermann Jung <hej@odn.de>
25 * Copyright (C) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
26 * and Philip Edelbrock <phil@netroedge.com>
27 */
28
29#include <linux/module.h>
30#include <linux/init.h>
31#include <linux/slab.h>
32#include <linux/jiffies.h>
33#include <linux/i2c.h>
34#include <linux/hwmon.h>
35#include <linux/err.h>
36#include <linux/mutex.h>
37#include <linux/sysfs.h>
38
39/*
40 * Addresses to scan
41 */
42
43static const unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
44
45/*
46 * Insmod parameters
47 */
48
49I2C_CLIENT_INSMOD_1(fscher);
50
51/*
52 * The FSCHER registers
53 */
54
55/* chip identification */
56#define FSCHER_REG_IDENT_0 0x00
57#define FSCHER_REG_IDENT_1 0x01
58#define FSCHER_REG_IDENT_2 0x02
59#define FSCHER_REG_REVISION 0x03
60
61/* global control and status */
62#define FSCHER_REG_EVENT_STATE 0x04
63#define FSCHER_REG_CONTROL 0x05
64
65/* watchdog */
66#define FSCHER_REG_WDOG_PRESET 0x28
67#define FSCHER_REG_WDOG_STATE 0x23
68#define FSCHER_REG_WDOG_CONTROL 0x21
69
70/* fan 0 */
71#define FSCHER_REG_FAN0_MIN 0x55
72#define FSCHER_REG_FAN0_ACT 0x0e
73#define FSCHER_REG_FAN0_STATE 0x0d
74#define FSCHER_REG_FAN0_RIPPLE 0x0f
75
76/* fan 1 */
77#define FSCHER_REG_FAN1_MIN 0x65
78#define FSCHER_REG_FAN1_ACT 0x6b
79#define FSCHER_REG_FAN1_STATE 0x62
80#define FSCHER_REG_FAN1_RIPPLE 0x6f
81
82/* fan 2 */
83#define FSCHER_REG_FAN2_MIN 0xb5
84#define FSCHER_REG_FAN2_ACT 0xbb
85#define FSCHER_REG_FAN2_STATE 0xb2
86#define FSCHER_REG_FAN2_RIPPLE 0xbf
87
88/* voltage supervision */
89#define FSCHER_REG_VOLT_12 0x45
90#define FSCHER_REG_VOLT_5 0x42
91#define FSCHER_REG_VOLT_BATT 0x48
92
93/* temperature 0 */
94#define FSCHER_REG_TEMP0_ACT 0x64
95#define FSCHER_REG_TEMP0_STATE 0x71
96
97/* temperature 1 */
98#define FSCHER_REG_TEMP1_ACT 0x32
99#define FSCHER_REG_TEMP1_STATE 0x81
100
101/* temperature 2 */
102#define FSCHER_REG_TEMP2_ACT 0x35
103#define FSCHER_REG_TEMP2_STATE 0x91
104
105/*
106 * Functions declaration
107 */
108
109static int fscher_probe(struct i2c_client *client,
110 const struct i2c_device_id *id);
111static int fscher_detect(struct i2c_client *client, int kind,
112 struct i2c_board_info *info);
113static int fscher_remove(struct i2c_client *client);
114static struct fscher_data *fscher_update_device(struct device *dev);
115static void fscher_init_client(struct i2c_client *client);
116
117static int fscher_read_value(struct i2c_client *client, u8 reg);
118static int fscher_write_value(struct i2c_client *client, u8 reg, u8 value);
119
120/*
121 * Driver data (common to all clients)
122 */
123
124static const struct i2c_device_id fscher_id[] = {
125 { "fscher", fscher },
126 { }
127};
128
129static struct i2c_driver fscher_driver = {
130 .class = I2C_CLASS_HWMON,
131 .driver = {
132 .name = "fscher",
133 },
134 .probe = fscher_probe,
135 .remove = fscher_remove,
136 .id_table = fscher_id,
137 .detect = fscher_detect,
138 .address_data = &addr_data,
139};
140
141/*
142 * Client data (each client gets its own)
143 */
144
145struct fscher_data {
146 struct device *hwmon_dev;
147 struct mutex update_lock;
148 char valid; /* zero until following fields are valid */
149 unsigned long last_updated; /* in jiffies */
150
151 /* register values */
152 u8 revision; /* revision of chip */
153 u8 global_event; /* global event status */
154 u8 global_control; /* global control register */
155 u8 watchdog[3]; /* watchdog */
156 u8 volt[3]; /* 12, 5, battery voltage */
157 u8 temp_act[3]; /* temperature */
158 u8 temp_status[3]; /* status of sensor */
159 u8 fan_act[3]; /* fans revolutions per second */
160 u8 fan_status[3]; /* fan status */
161 u8 fan_min[3]; /* fan min value for rps */
162 u8 fan_ripple[3]; /* divider for rps */
163};
164
165/*
166 * Sysfs stuff
167 */
168
169#define sysfs_r(kind, sub, offset, reg) \
170static ssize_t show_##kind##sub (struct fscher_data *, char *, int); \
171static ssize_t show_##kind##offset##sub (struct device *, struct device_attribute *attr, char *); \
172static ssize_t show_##kind##offset##sub (struct device *dev, struct device_attribute *attr, char *buf) \
173{ \
174 struct fscher_data *data = fscher_update_device(dev); \
175 return show_##kind##sub(data, buf, (offset)); \
176}
177
178#define sysfs_w(kind, sub, offset, reg) \
179static ssize_t set_##kind##sub (struct i2c_client *, struct fscher_data *, const char *, size_t, int, int); \
180static ssize_t set_##kind##offset##sub (struct device *, struct device_attribute *attr, const char *, size_t); \
181static ssize_t set_##kind##offset##sub (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
182{ \
183 struct i2c_client *client = to_i2c_client(dev); \
184 struct fscher_data *data = i2c_get_clientdata(client); \
185 return set_##kind##sub(client, data, buf, count, (offset), reg); \
186}
187
188#define sysfs_rw_n(kind, sub, offset, reg) \
189sysfs_r(kind, sub, offset, reg) \
190sysfs_w(kind, sub, offset, reg) \
191static DEVICE_ATTR(kind##offset##sub, S_IRUGO | S_IWUSR, show_##kind##offset##sub, set_##kind##offset##sub);
192
193#define sysfs_rw(kind, sub, reg) \
194sysfs_r(kind, sub, 0, reg) \
195sysfs_w(kind, sub, 0, reg) \
196static DEVICE_ATTR(kind##sub, S_IRUGO | S_IWUSR, show_##kind##0##sub, set_##kind##0##sub);
197
198#define sysfs_ro_n(kind, sub, offset, reg) \
199sysfs_r(kind, sub, offset, reg) \
200static DEVICE_ATTR(kind##offset##sub, S_IRUGO, show_##kind##offset##sub, NULL);
201
202#define sysfs_ro(kind, sub, reg) \
203sysfs_r(kind, sub, 0, reg) \
204static DEVICE_ATTR(kind, S_IRUGO, show_##kind##0##sub, NULL);
205
206#define sysfs_fan(offset, reg_status, reg_min, reg_ripple, reg_act) \
207sysfs_rw_n(pwm, , offset, reg_min) \
208sysfs_rw_n(fan, _status, offset, reg_status) \
209sysfs_rw_n(fan, _div , offset, reg_ripple) \
210sysfs_ro_n(fan, _input , offset, reg_act)
211
212#define sysfs_temp(offset, reg_status, reg_act) \
213sysfs_rw_n(temp, _status, offset, reg_status) \
214sysfs_ro_n(temp, _input , offset, reg_act)
215
216#define sysfs_in(offset, reg_act) \
217sysfs_ro_n(in, _input, offset, reg_act)
218
219#define sysfs_revision(reg_revision) \
220sysfs_ro(revision, , reg_revision)
221
222#define sysfs_alarms(reg_events) \
223sysfs_ro(alarms, , reg_events)
224
225#define sysfs_control(reg_control) \
226sysfs_rw(control, , reg_control)
227
228#define sysfs_watchdog(reg_control, reg_status, reg_preset) \
229sysfs_rw(watchdog, _control, reg_control) \
230sysfs_rw(watchdog, _status , reg_status) \
231sysfs_rw(watchdog, _preset , reg_preset)
232
233sysfs_fan(1, FSCHER_REG_FAN0_STATE, FSCHER_REG_FAN0_MIN,
234 FSCHER_REG_FAN0_RIPPLE, FSCHER_REG_FAN0_ACT)
235sysfs_fan(2, FSCHER_REG_FAN1_STATE, FSCHER_REG_FAN1_MIN,
236 FSCHER_REG_FAN1_RIPPLE, FSCHER_REG_FAN1_ACT)
237sysfs_fan(3, FSCHER_REG_FAN2_STATE, FSCHER_REG_FAN2_MIN,
238 FSCHER_REG_FAN2_RIPPLE, FSCHER_REG_FAN2_ACT)
239
240sysfs_temp(1, FSCHER_REG_TEMP0_STATE, FSCHER_REG_TEMP0_ACT)
241sysfs_temp(2, FSCHER_REG_TEMP1_STATE, FSCHER_REG_TEMP1_ACT)
242sysfs_temp(3, FSCHER_REG_TEMP2_STATE, FSCHER_REG_TEMP2_ACT)
243
244sysfs_in(0, FSCHER_REG_VOLT_12)
245sysfs_in(1, FSCHER_REG_VOLT_5)
246sysfs_in(2, FSCHER_REG_VOLT_BATT)
247
248sysfs_revision(FSCHER_REG_REVISION)
249sysfs_alarms(FSCHER_REG_EVENTS)
250sysfs_control(FSCHER_REG_CONTROL)
251sysfs_watchdog(FSCHER_REG_WDOG_CONTROL, FSCHER_REG_WDOG_STATE, FSCHER_REG_WDOG_PRESET)
252
253static struct attribute *fscher_attributes[] = {
254 &dev_attr_revision.attr,
255 &dev_attr_alarms.attr,
256 &dev_attr_control.attr,
257
258 &dev_attr_watchdog_status.attr,
259 &dev_attr_watchdog_control.attr,
260 &dev_attr_watchdog_preset.attr,
261
262 &dev_attr_in0_input.attr,
263 &dev_attr_in1_input.attr,
264 &dev_attr_in2_input.attr,
265
266 &dev_attr_fan1_status.attr,
267 &dev_attr_fan1_div.attr,
268 &dev_attr_fan1_input.attr,
269 &dev_attr_pwm1.attr,
270 &dev_attr_fan2_status.attr,
271 &dev_attr_fan2_div.attr,
272 &dev_attr_fan2_input.attr,
273 &dev_attr_pwm2.attr,
274 &dev_attr_fan3_status.attr,
275 &dev_attr_fan3_div.attr,
276 &dev_attr_fan3_input.attr,
277 &dev_attr_pwm3.attr,
278
279 &dev_attr_temp1_status.attr,
280 &dev_attr_temp1_input.attr,
281 &dev_attr_temp2_status.attr,
282 &dev_attr_temp2_input.attr,
283 &dev_attr_temp3_status.attr,
284 &dev_attr_temp3_input.attr,
285 NULL
286};
287
288static const struct attribute_group fscher_group = {
289 .attrs = fscher_attributes,
290};
291
292/*
293 * Real code
294 */
295
296/* Return 0 if detection is successful, -ENODEV otherwise */
297static int fscher_detect(struct i2c_client *new_client, int kind,
298 struct i2c_board_info *info)
299{
300 struct i2c_adapter *adapter = new_client->adapter;
301
302 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
303 return -ENODEV;
304
305 /* Do the remaining detection unless force or force_fscher parameter */
306 if (kind < 0) {
307 if ((i2c_smbus_read_byte_data(new_client,
308 FSCHER_REG_IDENT_0) != 0x48) /* 'H' */
309 || (i2c_smbus_read_byte_data(new_client,
310 FSCHER_REG_IDENT_1) != 0x45) /* 'E' */
311 || (i2c_smbus_read_byte_data(new_client,
312 FSCHER_REG_IDENT_2) != 0x52)) /* 'R' */
313 return -ENODEV;
314 }
315
316 strlcpy(info->type, "fscher", I2C_NAME_SIZE);
317
318 return 0;
319}
320
321static int fscher_probe(struct i2c_client *new_client,
322 const struct i2c_device_id *id)
323{
324 struct fscher_data *data;
325 int err;
326
327 data = kzalloc(sizeof(struct fscher_data), GFP_KERNEL);
328 if (!data) {
329 err = -ENOMEM;
330 goto exit;
331 }
332
333 i2c_set_clientdata(new_client, data);
334 data->valid = 0;
335 mutex_init(&data->update_lock);
336
337 fscher_init_client(new_client);
338
339 /* Register sysfs hooks */
340 if ((err = sysfs_create_group(&new_client->dev.kobj, &fscher_group)))
341 goto exit_free;
342
343 data->hwmon_dev = hwmon_device_register(&new_client->dev);
344 if (IS_ERR(data->hwmon_dev)) {
345 err = PTR_ERR(data->hwmon_dev);
346 goto exit_remove_files;
347 }
348
349 return 0;
350
351exit_remove_files:
352 sysfs_remove_group(&new_client->dev.kobj, &fscher_group);
353exit_free:
354 kfree(data);
355exit:
356 return err;
357}
358
359static int fscher_remove(struct i2c_client *client)
360{
361 struct fscher_data *data = i2c_get_clientdata(client);
362
363 hwmon_device_unregister(data->hwmon_dev);
364 sysfs_remove_group(&client->dev.kobj, &fscher_group);
365
366 kfree(data);
367 return 0;
368}
369
370static int fscher_read_value(struct i2c_client *client, u8 reg)
371{
372 dev_dbg(&client->dev, "read reg 0x%02x\n", reg);
373
374 return i2c_smbus_read_byte_data(client, reg);
375}
376
377static int fscher_write_value(struct i2c_client *client, u8 reg, u8 value)
378{
379 dev_dbg(&client->dev, "write reg 0x%02x, val 0x%02x\n",
380 reg, value);
381
382 return i2c_smbus_write_byte_data(client, reg, value);
383}
384
385/* Called when we have found a new FSC Hermes. */
386static void fscher_init_client(struct i2c_client *client)
387{
388 struct fscher_data *data = i2c_get_clientdata(client);
389
390 /* Read revision from chip */
391 data->revision = fscher_read_value(client, FSCHER_REG_REVISION);
392}
393
394static struct fscher_data *fscher_update_device(struct device *dev)
395{
396 struct i2c_client *client = to_i2c_client(dev);
397 struct fscher_data *data = i2c_get_clientdata(client);
398
399 mutex_lock(&data->update_lock);
400
401 if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) {
402
403 dev_dbg(&client->dev, "Starting fscher update\n");
404
405 data->temp_act[0] = fscher_read_value(client, FSCHER_REG_TEMP0_ACT);
406 data->temp_act[1] = fscher_read_value(client, FSCHER_REG_TEMP1_ACT);
407 data->temp_act[2] = fscher_read_value(client, FSCHER_REG_TEMP2_ACT);
408 data->temp_status[0] = fscher_read_value(client, FSCHER_REG_TEMP0_STATE);
409 data->temp_status[1] = fscher_read_value(client, FSCHER_REG_TEMP1_STATE);
410 data->temp_status[2] = fscher_read_value(client, FSCHER_REG_TEMP2_STATE);
411
412 data->volt[0] = fscher_read_value(client, FSCHER_REG_VOLT_12);
413 data->volt[1] = fscher_read_value(client, FSCHER_REG_VOLT_5);
414 data->volt[2] = fscher_read_value(client, FSCHER_REG_VOLT_BATT);
415
416 data->fan_act[0] = fscher_read_value(client, FSCHER_REG_FAN0_ACT);
417 data->fan_act[1] = fscher_read_value(client, FSCHER_REG_FAN1_ACT);
418 data->fan_act[2] = fscher_read_value(client, FSCHER_REG_FAN2_ACT);
419 data->fan_status[0] = fscher_read_value(client, FSCHER_REG_FAN0_STATE);
420 data->fan_status[1] = fscher_read_value(client, FSCHER_REG_FAN1_STATE);
421 data->fan_status[2] = fscher_read_value(client, FSCHER_REG_FAN2_STATE);
422 data->fan_min[0] = fscher_read_value(client, FSCHER_REG_FAN0_MIN);
423 data->fan_min[1] = fscher_read_value(client, FSCHER_REG_FAN1_MIN);
424 data->fan_min[2] = fscher_read_value(client, FSCHER_REG_FAN2_MIN);
425 data->fan_ripple[0] = fscher_read_value(client, FSCHER_REG_FAN0_RIPPLE);
426 data->fan_ripple[1] = fscher_read_value(client, FSCHER_REG_FAN1_RIPPLE);
427 data->fan_ripple[2] = fscher_read_value(client, FSCHER_REG_FAN2_RIPPLE);
428
429 data->watchdog[0] = fscher_read_value(client, FSCHER_REG_WDOG_PRESET);
430 data->watchdog[1] = fscher_read_value(client, FSCHER_REG_WDOG_STATE);
431 data->watchdog[2] = fscher_read_value(client, FSCHER_REG_WDOG_CONTROL);
432
433 data->global_event = fscher_read_value(client, FSCHER_REG_EVENT_STATE);
434 data->global_control = fscher_read_value(client,
435 FSCHER_REG_CONTROL);
436
437 data->last_updated = jiffies;
438 data->valid = 1;
439 }
440
441 mutex_unlock(&data->update_lock);
442
443 return data;
444}
445
446
447
448#define FAN_INDEX_FROM_NUM(nr) ((nr) - 1)
449
450static ssize_t set_fan_status(struct i2c_client *client, struct fscher_data *data,
451 const char *buf, size_t count, int nr, int reg)
452{
453 /* bits 0..1, 3..7 reserved => mask with 0x04 */
454 unsigned long v = simple_strtoul(buf, NULL, 10) & 0x04;
455
456 mutex_lock(&data->update_lock);
457 data->fan_status[FAN_INDEX_FROM_NUM(nr)] &= ~v;
458 fscher_write_value(client, reg, v);
459 mutex_unlock(&data->update_lock);
460 return count;
461}
462
463static ssize_t show_fan_status(struct fscher_data *data, char *buf, int nr)
464{
465 /* bits 0..1, 3..7 reserved => mask with 0x04 */
466 return sprintf(buf, "%u\n", data->fan_status[FAN_INDEX_FROM_NUM(nr)] & 0x04);
467}
468
469static ssize_t set_pwm(struct i2c_client *client, struct fscher_data *data,
470 const char *buf, size_t count, int nr, int reg)
471{
472 unsigned long v = simple_strtoul(buf, NULL, 10);
473
474 mutex_lock(&data->update_lock);
475 data->fan_min[FAN_INDEX_FROM_NUM(nr)] = v > 0xff ? 0xff : v;
476 fscher_write_value(client, reg, data->fan_min[FAN_INDEX_FROM_NUM(nr)]);
477 mutex_unlock(&data->update_lock);
478 return count;
479}
480
481static ssize_t show_pwm(struct fscher_data *data, char *buf, int nr)
482{
483 return sprintf(buf, "%u\n", data->fan_min[FAN_INDEX_FROM_NUM(nr)]);
484}
485
486static ssize_t set_fan_div(struct i2c_client *client, struct fscher_data *data,
487 const char *buf, size_t count, int nr, int reg)
488{
489 /* supported values: 2, 4, 8 */
490 unsigned long v = simple_strtoul(buf, NULL, 10);
491
492 switch (v) {
493 case 2: v = 1; break;
494 case 4: v = 2; break;
495 case 8: v = 3; break;
496 default:
497 dev_err(&client->dev, "fan_div value %ld not "
498 "supported. Choose one of 2, 4 or 8!\n", v);
499 return -EINVAL;
500 }
501
502 mutex_lock(&data->update_lock);
503
504 /* bits 2..7 reserved => mask with 0x03 */
505 data->fan_ripple[FAN_INDEX_FROM_NUM(nr)] &= ~0x03;
506 data->fan_ripple[FAN_INDEX_FROM_NUM(nr)] |= v;
507
508 fscher_write_value(client, reg, data->fan_ripple[FAN_INDEX_FROM_NUM(nr)]);
509 mutex_unlock(&data->update_lock);
510 return count;
511}
512
513static ssize_t show_fan_div(struct fscher_data *data, char *buf, int nr)
514{
515 /* bits 2..7 reserved => mask with 0x03 */
516 return sprintf(buf, "%u\n", 1 << (data->fan_ripple[FAN_INDEX_FROM_NUM(nr)] & 0x03));
517}
518
519#define RPM_FROM_REG(val) (val*60)
520
521static ssize_t show_fan_input (struct fscher_data *data, char *buf, int nr)
522{
523 return sprintf(buf, "%u\n", RPM_FROM_REG(data->fan_act[FAN_INDEX_FROM_NUM(nr)]));
524}
525
526
527
528#define TEMP_INDEX_FROM_NUM(nr) ((nr) - 1)
529
530static ssize_t set_temp_status(struct i2c_client *client, struct fscher_data *data,
531 const char *buf, size_t count, int nr, int reg)
532{
533 /* bits 2..7 reserved, 0 read only => mask with 0x02 */
534 unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02;
535
536 mutex_lock(&data->update_lock);
537 data->temp_status[TEMP_INDEX_FROM_NUM(nr)] &= ~v;
538 fscher_write_value(client, reg, v);
539 mutex_unlock(&data->update_lock);
540 return count;
541}
542
543static ssize_t show_temp_status(struct fscher_data *data, char *buf, int nr)
544{
545 /* bits 2..7 reserved => mask with 0x03 */
546 return sprintf(buf, "%u\n", data->temp_status[TEMP_INDEX_FROM_NUM(nr)] & 0x03);
547}
548
549#define TEMP_FROM_REG(val) (((val) - 128) * 1000)
550
551static ssize_t show_temp_input(struct fscher_data *data, char *buf, int nr)
552{
553 return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_act[TEMP_INDEX_FROM_NUM(nr)]));
554}
555
556/*
557 * The final conversion is specified in sensors.conf, as it depends on
558 * mainboard specific values. We export the registers contents as
559 * pseudo-hundredths-of-Volts (range 0V - 2.55V). Not that it makes much
560 * sense per se, but it minimizes the conversions count and keeps the
561 * values within a usual range.
562 */
563#define VOLT_FROM_REG(val) ((val) * 10)
564
565static ssize_t show_in_input(struct fscher_data *data, char *buf, int nr)
566{
567 return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[nr]));
568}
569
570
571
572static ssize_t show_revision(struct fscher_data *data, char *buf, int nr)
573{
574 return sprintf(buf, "%u\n", data->revision);
575}
576
577
578
579static ssize_t show_alarms(struct fscher_data *data, char *buf, int nr)
580{
581 /* bits 2, 5..6 reserved => mask with 0x9b */
582 return sprintf(buf, "%u\n", data->global_event & 0x9b);
583}
584
585
586
587static ssize_t set_control(struct i2c_client *client, struct fscher_data *data,
588 const char *buf, size_t count, int nr, int reg)
589{
590 /* bits 1..7 reserved => mask with 0x01 */
591 unsigned long v = simple_strtoul(buf, NULL, 10) & 0x01;
592
593 mutex_lock(&data->update_lock);
594 data->global_control = v;
595 fscher_write_value(client, reg, v);
596 mutex_unlock(&data->update_lock);
597 return count;
598}
599
600static ssize_t show_control(struct fscher_data *data, char *buf, int nr)
601{
602 /* bits 1..7 reserved => mask with 0x01 */
603 return sprintf(buf, "%u\n", data->global_control & 0x01);
604}
605
606
607
608static ssize_t set_watchdog_control(struct i2c_client *client, struct
609 fscher_data *data, const char *buf, size_t count,
610 int nr, int reg)
611{
612 /* bits 0..3 reserved => mask with 0xf0 */
613 unsigned long v = simple_strtoul(buf, NULL, 10) & 0xf0;
614
615 mutex_lock(&data->update_lock);
616 data->watchdog[2] &= ~0xf0;
617 data->watchdog[2] |= v;
618 fscher_write_value(client, reg, data->watchdog[2]);
619 mutex_unlock(&data->update_lock);
620 return count;
621}
622
623static ssize_t show_watchdog_control(struct fscher_data *data, char *buf, int nr)
624{
625 /* bits 0..3 reserved, bit 5 write only => mask with 0xd0 */
626 return sprintf(buf, "%u\n", data->watchdog[2] & 0xd0);
627}
628
629static ssize_t set_watchdog_status(struct i2c_client *client, struct fscher_data *data,
630 const char *buf, size_t count, int nr, int reg)
631{
632 /* bits 0, 2..7 reserved => mask with 0x02 */
633 unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02;
634
635 mutex_lock(&data->update_lock);
636 data->watchdog[1] &= ~v;
637 fscher_write_value(client, reg, v);
638 mutex_unlock(&data->update_lock);
639 return count;
640}
641
642static ssize_t show_watchdog_status(struct fscher_data *data, char *buf, int nr)
643{
644 /* bits 0, 2..7 reserved => mask with 0x02 */
645 return sprintf(buf, "%u\n", data->watchdog[1] & 0x02);
646}
647
648static ssize_t set_watchdog_preset(struct i2c_client *client, struct fscher_data *data,
649 const char *buf, size_t count, int nr, int reg)
650{
651 unsigned long v = simple_strtoul(buf, NULL, 10) & 0xff;
652
653 mutex_lock(&data->update_lock);
654 data->watchdog[0] = v;
655 fscher_write_value(client, reg, data->watchdog[0]);
656 mutex_unlock(&data->update_lock);
657 return count;
658}
659
660static ssize_t show_watchdog_preset(struct fscher_data *data, char *buf, int nr)
661{
662 return sprintf(buf, "%u\n", data->watchdog[0]);
663}
664
665static int __init sensors_fscher_init(void)
666{
667 return i2c_add_driver(&fscher_driver);
668}
669
670static void __exit sensors_fscher_exit(void)
671{
672 i2c_del_driver(&fscher_driver);
673}
674
675MODULE_AUTHOR("Reinhard Nissl <rnissl@gmx.de>");
676MODULE_DESCRIPTION("FSC Hermes driver");
677MODULE_LICENSE("GPL");
678
679module_init(sensors_fscher_init);
680module_exit(sensors_fscher_exit);
diff --git a/drivers/hwmon/fscpos.c b/drivers/hwmon/fscpos.c
deleted file mode 100644
index 8a7bcf500b4e..000000000000
--- a/drivers/hwmon/fscpos.c
+++ /dev/null
@@ -1,654 +0,0 @@
1/*
2 fscpos.c - Kernel module for hardware monitoring with FSC Poseidon chips
3 Copyright (C) 2004, 2005 Stefan Ott <stefan@desire.ch>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18*/
19
20/*
21 fujitsu siemens poseidon chip,
22 module based on the old fscpos module by Hermann Jung <hej@odn.de> and
23 the fscher module by Reinhard Nissl <rnissl@gmx.de>
24
25 original module based on lm80.c
26 Copyright (C) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
27 and Philip Edelbrock <phil@netroedge.com>
28
29 Thanks to Jean Delvare for reviewing my code and suggesting a lot of
30 improvements.
31*/
32
33#include <linux/module.h>
34#include <linux/slab.h>
35#include <linux/jiffies.h>
36#include <linux/i2c.h>
37#include <linux/init.h>
38#include <linux/hwmon.h>
39#include <linux/err.h>
40#include <linux/mutex.h>
41#include <linux/sysfs.h>
42
43/*
44 * Addresses to scan
45 */
46static const unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
47
48/*
49 * Insmod parameters
50 */
51I2C_CLIENT_INSMOD_1(fscpos);
52
53/*
54 * The FSCPOS registers
55 */
56
57/* chip identification */
58#define FSCPOS_REG_IDENT_0 0x00
59#define FSCPOS_REG_IDENT_1 0x01
60#define FSCPOS_REG_IDENT_2 0x02
61#define FSCPOS_REG_REVISION 0x03
62
63/* global control and status */
64#define FSCPOS_REG_EVENT_STATE 0x04
65#define FSCPOS_REG_CONTROL 0x05
66
67/* watchdog */
68#define FSCPOS_REG_WDOG_PRESET 0x28
69#define FSCPOS_REG_WDOG_STATE 0x23
70#define FSCPOS_REG_WDOG_CONTROL 0x21
71
72/* voltages */
73#define FSCPOS_REG_VOLT_12 0x45
74#define FSCPOS_REG_VOLT_5 0x42
75#define FSCPOS_REG_VOLT_BATT 0x48
76
77/* fans - the chip does not support minimum speed for fan2 */
78static u8 FSCPOS_REG_PWM[] = { 0x55, 0x65 };
79static u8 FSCPOS_REG_FAN_ACT[] = { 0x0e, 0x6b, 0xab };
80static u8 FSCPOS_REG_FAN_STATE[] = { 0x0d, 0x62, 0xa2 };
81static u8 FSCPOS_REG_FAN_RIPPLE[] = { 0x0f, 0x6f, 0xaf };
82
83/* temperatures */
84static u8 FSCPOS_REG_TEMP_ACT[] = { 0x64, 0x32, 0x35 };
85static u8 FSCPOS_REG_TEMP_STATE[] = { 0x71, 0x81, 0x91 };
86
87/*
88 * Functions declaration
89 */
90static int fscpos_probe(struct i2c_client *client,
91 const struct i2c_device_id *id);
92static int fscpos_detect(struct i2c_client *client, int kind,
93 struct i2c_board_info *info);
94static int fscpos_remove(struct i2c_client *client);
95
96static int fscpos_read_value(struct i2c_client *client, u8 reg);
97static int fscpos_write_value(struct i2c_client *client, u8 reg, u8 value);
98static struct fscpos_data *fscpos_update_device(struct device *dev);
99static void fscpos_init_client(struct i2c_client *client);
100
101static void reset_fan_alarm(struct i2c_client *client, int nr);
102
103/*
104 * Driver data (common to all clients)
105 */
106static const struct i2c_device_id fscpos_id[] = {
107 { "fscpos", fscpos },
108 { }
109};
110
111static struct i2c_driver fscpos_driver = {
112 .class = I2C_CLASS_HWMON,
113 .driver = {
114 .name = "fscpos",
115 },
116 .probe = fscpos_probe,
117 .remove = fscpos_remove,
118 .id_table = fscpos_id,
119 .detect = fscpos_detect,
120 .address_data = &addr_data,
121};
122
123/*
124 * Client data (each client gets its own)
125 */
126struct fscpos_data {
127 struct device *hwmon_dev;
128 struct mutex update_lock;
129 char valid; /* 0 until following fields are valid */
130 unsigned long last_updated; /* In jiffies */
131
132 /* register values */
133 u8 revision; /* revision of chip */
134 u8 global_event; /* global event status */
135 u8 global_control; /* global control register */
136 u8 wdog_control; /* watchdog control */
137 u8 wdog_state; /* watchdog status */
138 u8 wdog_preset; /* watchdog preset */
139 u8 volt[3]; /* 12, 5, battery current */
140 u8 temp_act[3]; /* temperature */
141 u8 temp_status[3]; /* status of sensor */
142 u8 fan_act[3]; /* fans revolutions per second */
143 u8 fan_status[3]; /* fan status */
144 u8 pwm[2]; /* fan min value for rps */
145 u8 fan_ripple[3]; /* divider for rps */
146};
147
148/* Temperature */
149#define TEMP_FROM_REG(val) (((val) - 128) * 1000)
150
151static ssize_t show_temp_input(struct fscpos_data *data, char *buf, int nr)
152{
153 return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_act[nr - 1]));
154}
155
156static ssize_t show_temp_status(struct fscpos_data *data, char *buf, int nr)
157{
158 /* bits 2..7 reserved => mask with 0x03 */
159 return sprintf(buf, "%u\n", data->temp_status[nr - 1] & 0x03);
160}
161
162static ssize_t show_temp_reset(struct fscpos_data *data, char *buf, int nr)
163{
164 return sprintf(buf, "1\n");
165}
166
167static ssize_t set_temp_reset(struct i2c_client *client, struct fscpos_data
168 *data, const char *buf, size_t count, int nr, int reg)
169{
170 unsigned long v = simple_strtoul(buf, NULL, 10);
171 if (v != 1) {
172 dev_err(&client->dev, "temp_reset value %ld not supported. "
173 "Use 1 to reset the alarm!\n", v);
174 return -EINVAL;
175 }
176
177 dev_info(&client->dev, "You used the temp_reset feature which has not "
178 "been proplerly tested. Please report your "
179 "experience to the module author.\n");
180
181 /* Supported value: 2 (clears the status) */
182 fscpos_write_value(client, FSCPOS_REG_TEMP_STATE[nr - 1], 2);
183 return count;
184}
185
186/* Fans */
187#define RPM_FROM_REG(val) ((val) * 60)
188
189static ssize_t show_fan_status(struct fscpos_data *data, char *buf, int nr)
190{
191 /* bits 0..1, 3..7 reserved => mask with 0x04 */
192 return sprintf(buf, "%u\n", data->fan_status[nr - 1] & 0x04);
193}
194
195static ssize_t show_fan_input(struct fscpos_data *data, char *buf, int nr)
196{
197 return sprintf(buf, "%u\n", RPM_FROM_REG(data->fan_act[nr - 1]));
198}
199
200static ssize_t show_fan_ripple(struct fscpos_data *data, char *buf, int nr)
201{
202 /* bits 2..7 reserved => mask with 0x03 */
203 return sprintf(buf, "%u\n", data->fan_ripple[nr - 1] & 0x03);
204}
205
206static ssize_t set_fan_ripple(struct i2c_client *client, struct fscpos_data
207 *data, const char *buf, size_t count, int nr, int reg)
208{
209 /* supported values: 2, 4, 8 */
210 unsigned long v = simple_strtoul(buf, NULL, 10);
211
212 switch (v) {
213 case 2: v = 1; break;
214 case 4: v = 2; break;
215 case 8: v = 3; break;
216 default:
217 dev_err(&client->dev, "fan_ripple value %ld not supported. "
218 "Must be one of 2, 4 or 8!\n", v);
219 return -EINVAL;
220 }
221
222 mutex_lock(&data->update_lock);
223 /* bits 2..7 reserved => mask with 0x03 */
224 data->fan_ripple[nr - 1] &= ~0x03;
225 data->fan_ripple[nr - 1] |= v;
226
227 fscpos_write_value(client, reg, data->fan_ripple[nr - 1]);
228 mutex_unlock(&data->update_lock);
229 return count;
230}
231
232static ssize_t show_pwm(struct fscpos_data *data, char *buf, int nr)
233{
234 return sprintf(buf, "%u\n", data->pwm[nr - 1]);
235}
236
237static ssize_t set_pwm(struct i2c_client *client, struct fscpos_data *data,
238 const char *buf, size_t count, int nr, int reg)
239{
240 unsigned long v = simple_strtoul(buf, NULL, 10);
241
242 /* Range: 0..255 */
243 if (v < 0) v = 0;
244 if (v > 255) v = 255;
245
246 mutex_lock(&data->update_lock);
247 data->pwm[nr - 1] = v;
248 fscpos_write_value(client, reg, data->pwm[nr - 1]);
249 mutex_unlock(&data->update_lock);
250 return count;
251}
252
253static void reset_fan_alarm(struct i2c_client *client, int nr)
254{
255 fscpos_write_value(client, FSCPOS_REG_FAN_STATE[nr], 4);
256}
257
258/* Volts */
259#define VOLT_FROM_REG(val, mult) ((val) * (mult) / 255)
260
261static ssize_t show_volt_12(struct device *dev, struct device_attribute *attr, char *buf)
262{
263 struct fscpos_data *data = fscpos_update_device(dev);
264 return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[0], 14200));
265}
266
267static ssize_t show_volt_5(struct device *dev, struct device_attribute *attr, char *buf)
268{
269 struct fscpos_data *data = fscpos_update_device(dev);
270 return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[1], 6600));
271}
272
273static ssize_t show_volt_batt(struct device *dev, struct device_attribute *attr, char *buf)
274{
275 struct fscpos_data *data = fscpos_update_device(dev);
276 return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[2], 3300));
277}
278
279/* Watchdog */
280static ssize_t show_wdog_control(struct fscpos_data *data, char *buf)
281{
282 /* bits 0..3 reserved, bit 6 write only => mask with 0xb0 */
283 return sprintf(buf, "%u\n", data->wdog_control & 0xb0);
284}
285
286static ssize_t set_wdog_control(struct i2c_client *client, struct fscpos_data
287 *data, const char *buf, size_t count, int reg)
288{
289 /* bits 0..3 reserved => mask with 0xf0 */
290 unsigned long v = simple_strtoul(buf, NULL, 10) & 0xf0;
291
292 mutex_lock(&data->update_lock);
293 data->wdog_control &= ~0xf0;
294 data->wdog_control |= v;
295 fscpos_write_value(client, reg, data->wdog_control);
296 mutex_unlock(&data->update_lock);
297 return count;
298}
299
300static ssize_t show_wdog_state(struct fscpos_data *data, char *buf)
301{
302 /* bits 0, 2..7 reserved => mask with 0x02 */
303 return sprintf(buf, "%u\n", data->wdog_state & 0x02);
304}
305
306static ssize_t set_wdog_state(struct i2c_client *client, struct fscpos_data
307 *data, const char *buf, size_t count, int reg)
308{
309 unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02;
310
311 /* Valid values: 2 (clear) */
312 if (v != 2) {
313 dev_err(&client->dev, "wdog_state value %ld not supported. "
314 "Must be 2 to clear the state!\n", v);
315 return -EINVAL;
316 }
317
318 mutex_lock(&data->update_lock);
319 data->wdog_state &= ~v;
320 fscpos_write_value(client, reg, v);
321 mutex_unlock(&data->update_lock);
322 return count;
323}
324
325static ssize_t show_wdog_preset(struct fscpos_data *data, char *buf)
326{
327 return sprintf(buf, "%u\n", data->wdog_preset);
328}
329
330static ssize_t set_wdog_preset(struct i2c_client *client, struct fscpos_data
331 *data, const char *buf, size_t count, int reg)
332{
333 unsigned long v = simple_strtoul(buf, NULL, 10) & 0xff;
334
335 mutex_lock(&data->update_lock);
336 data->wdog_preset = v;
337 fscpos_write_value(client, reg, data->wdog_preset);
338 mutex_unlock(&data->update_lock);
339 return count;
340}
341
342/* Event */
343static ssize_t show_event(struct device *dev, struct device_attribute *attr, char *buf)
344{
345 /* bits 5..7 reserved => mask with 0x1f */
346 struct fscpos_data *data = fscpos_update_device(dev);
347 return sprintf(buf, "%u\n", data->global_event & 0x9b);
348}
349
350/*
351 * Sysfs stuff
352 */
353#define create_getter(kind, sub) \
354 static ssize_t sysfs_show_##kind##sub(struct device *dev, struct device_attribute *attr, char *buf) \
355 { \
356 struct fscpos_data *data = fscpos_update_device(dev); \
357 return show_##kind##sub(data, buf); \
358 }
359
360#define create_getter_n(kind, offset, sub) \
361 static ssize_t sysfs_show_##kind##offset##sub(struct device *dev, struct device_attribute *attr, char\
362 *buf) \
363 { \
364 struct fscpos_data *data = fscpos_update_device(dev); \
365 return show_##kind##sub(data, buf, offset); \
366 }
367
368#define create_setter(kind, sub, reg) \
369 static ssize_t sysfs_set_##kind##sub (struct device *dev, struct device_attribute *attr, const char \
370 *buf, size_t count) \
371 { \
372 struct i2c_client *client = to_i2c_client(dev); \
373 struct fscpos_data *data = i2c_get_clientdata(client); \
374 return set_##kind##sub(client, data, buf, count, reg); \
375 }
376
377#define create_setter_n(kind, offset, sub, reg) \
378 static ssize_t sysfs_set_##kind##offset##sub (struct device *dev, struct device_attribute *attr, \
379 const char *buf, size_t count) \
380 { \
381 struct i2c_client *client = to_i2c_client(dev); \
382 struct fscpos_data *data = i2c_get_clientdata(client); \
383 return set_##kind##sub(client, data, buf, count, offset, reg);\
384 }
385
386#define create_sysfs_device_ro(kind, sub, offset) \
387 static DEVICE_ATTR(kind##offset##sub, S_IRUGO, \
388 sysfs_show_##kind##offset##sub, NULL);
389
390#define create_sysfs_device_rw(kind, sub, offset) \
391 static DEVICE_ATTR(kind##offset##sub, S_IRUGO | S_IWUSR, \
392 sysfs_show_##kind##offset##sub, sysfs_set_##kind##offset##sub);
393
394#define sysfs_ro_n(kind, sub, offset) \
395 create_getter_n(kind, offset, sub); \
396 create_sysfs_device_ro(kind, sub, offset);
397
398#define sysfs_rw_n(kind, sub, offset, reg) \
399 create_getter_n(kind, offset, sub); \
400 create_setter_n(kind, offset, sub, reg); \
401 create_sysfs_device_rw(kind, sub, offset);
402
403#define sysfs_rw(kind, sub, reg) \
404 create_getter(kind, sub); \
405 create_setter(kind, sub, reg); \
406 create_sysfs_device_rw(kind, sub,);
407
408#define sysfs_fan_with_min(offset, reg_status, reg_ripple, reg_min) \
409 sysfs_fan(offset, reg_status, reg_ripple); \
410 sysfs_rw_n(pwm,, offset, reg_min);
411
412#define sysfs_fan(offset, reg_status, reg_ripple) \
413 sysfs_ro_n(fan, _input, offset); \
414 sysfs_ro_n(fan, _status, offset); \
415 sysfs_rw_n(fan, _ripple, offset, reg_ripple);
416
417#define sysfs_temp(offset, reg_status) \
418 sysfs_ro_n(temp, _input, offset); \
419 sysfs_ro_n(temp, _status, offset); \
420 sysfs_rw_n(temp, _reset, offset, reg_status);
421
422#define sysfs_watchdog(reg_wdog_preset, reg_wdog_state, reg_wdog_control) \
423 sysfs_rw(wdog, _control, reg_wdog_control); \
424 sysfs_rw(wdog, _preset, reg_wdog_preset); \
425 sysfs_rw(wdog, _state, reg_wdog_state);
426
427sysfs_fan_with_min(1, FSCPOS_REG_FAN_STATE[0], FSCPOS_REG_FAN_RIPPLE[0],
428 FSCPOS_REG_PWM[0]);
429sysfs_fan_with_min(2, FSCPOS_REG_FAN_STATE[1], FSCPOS_REG_FAN_RIPPLE[1],
430 FSCPOS_REG_PWM[1]);
431sysfs_fan(3, FSCPOS_REG_FAN_STATE[2], FSCPOS_REG_FAN_RIPPLE[2]);
432
433sysfs_temp(1, FSCPOS_REG_TEMP_STATE[0]);
434sysfs_temp(2, FSCPOS_REG_TEMP_STATE[1]);
435sysfs_temp(3, FSCPOS_REG_TEMP_STATE[2]);
436
437sysfs_watchdog(FSCPOS_REG_WDOG_PRESET, FSCPOS_REG_WDOG_STATE,
438 FSCPOS_REG_WDOG_CONTROL);
439
440static DEVICE_ATTR(event, S_IRUGO, show_event, NULL);
441static DEVICE_ATTR(in0_input, S_IRUGO, show_volt_12, NULL);
442static DEVICE_ATTR(in1_input, S_IRUGO, show_volt_5, NULL);
443static DEVICE_ATTR(in2_input, S_IRUGO, show_volt_batt, NULL);
444
445static struct attribute *fscpos_attributes[] = {
446 &dev_attr_event.attr,
447 &dev_attr_in0_input.attr,
448 &dev_attr_in1_input.attr,
449 &dev_attr_in2_input.attr,
450
451 &dev_attr_wdog_control.attr,
452 &dev_attr_wdog_preset.attr,
453 &dev_attr_wdog_state.attr,
454
455 &dev_attr_temp1_input.attr,
456 &dev_attr_temp1_status.attr,
457 &dev_attr_temp1_reset.attr,
458 &dev_attr_temp2_input.attr,
459 &dev_attr_temp2_status.attr,
460 &dev_attr_temp2_reset.attr,
461 &dev_attr_temp3_input.attr,
462 &dev_attr_temp3_status.attr,
463 &dev_attr_temp3_reset.attr,
464
465 &dev_attr_fan1_input.attr,
466 &dev_attr_fan1_status.attr,
467 &dev_attr_fan1_ripple.attr,
468 &dev_attr_pwm1.attr,
469 &dev_attr_fan2_input.attr,
470 &dev_attr_fan2_status.attr,
471 &dev_attr_fan2_ripple.attr,
472 &dev_attr_pwm2.attr,
473 &dev_attr_fan3_input.attr,
474 &dev_attr_fan3_status.attr,
475 &dev_attr_fan3_ripple.attr,
476 NULL
477};
478
479static const struct attribute_group fscpos_group = {
480 .attrs = fscpos_attributes,
481};
482
483/* Return 0 if detection is successful, -ENODEV otherwise */
484static int fscpos_detect(struct i2c_client *new_client, int kind,
485 struct i2c_board_info *info)
486{
487 struct i2c_adapter *adapter = new_client->adapter;
488
489 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
490 return -ENODEV;
491
492 /* Do the remaining detection unless force or force_fscpos parameter */
493 if (kind < 0) {
494 if ((fscpos_read_value(new_client, FSCPOS_REG_IDENT_0)
495 != 0x50) /* 'P' */
496 || (fscpos_read_value(new_client, FSCPOS_REG_IDENT_1)
497 != 0x45) /* 'E' */
498 || (fscpos_read_value(new_client, FSCPOS_REG_IDENT_2)
499 != 0x47))/* 'G' */
500 return -ENODEV;
501 }
502
503 strlcpy(info->type, "fscpos", I2C_NAME_SIZE);
504
505 return 0;
506}
507
508static int fscpos_probe(struct i2c_client *new_client,
509 const struct i2c_device_id *id)
510{
511 struct fscpos_data *data;
512 int err;
513
514 data = kzalloc(sizeof(struct fscpos_data), GFP_KERNEL);
515 if (!data) {
516 err = -ENOMEM;
517 goto exit;
518 }
519
520 i2c_set_clientdata(new_client, data);
521 data->valid = 0;
522 mutex_init(&data->update_lock);
523
524 /* Inizialize the fscpos chip */
525 fscpos_init_client(new_client);
526
527 /* Announce that the chip was found */
528 dev_info(&new_client->dev, "Found fscpos chip, rev %u\n", data->revision);
529
530 /* Register sysfs hooks */
531 if ((err = sysfs_create_group(&new_client->dev.kobj, &fscpos_group)))
532 goto exit_free;
533
534 data->hwmon_dev = hwmon_device_register(&new_client->dev);
535 if (IS_ERR(data->hwmon_dev)) {
536 err = PTR_ERR(data->hwmon_dev);
537 goto exit_remove_files;
538 }
539
540 return 0;
541
542exit_remove_files:
543 sysfs_remove_group(&new_client->dev.kobj, &fscpos_group);
544exit_free:
545 kfree(data);
546exit:
547 return err;
548}
549
550static int fscpos_remove(struct i2c_client *client)
551{
552 struct fscpos_data *data = i2c_get_clientdata(client);
553
554 hwmon_device_unregister(data->hwmon_dev);
555 sysfs_remove_group(&client->dev.kobj, &fscpos_group);
556
557 kfree(data);
558 return 0;
559}
560
561static int fscpos_read_value(struct i2c_client *client, u8 reg)
562{
563 dev_dbg(&client->dev, "Read reg 0x%02x\n", reg);
564 return i2c_smbus_read_byte_data(client, reg);
565}
566
567static int fscpos_write_value(struct i2c_client *client, u8 reg, u8 value)
568{
569 dev_dbg(&client->dev, "Write reg 0x%02x, val 0x%02x\n", reg, value);
570 return i2c_smbus_write_byte_data(client, reg, value);
571}
572
573/* Called when we have found a new FSCPOS chip */
574static void fscpos_init_client(struct i2c_client *client)
575{
576 struct fscpos_data *data = i2c_get_clientdata(client);
577
578 /* read revision from chip */
579 data->revision = fscpos_read_value(client, FSCPOS_REG_REVISION);
580}
581
582static struct fscpos_data *fscpos_update_device(struct device *dev)
583{
584 struct i2c_client *client = to_i2c_client(dev);
585 struct fscpos_data *data = i2c_get_clientdata(client);
586
587 mutex_lock(&data->update_lock);
588
589 if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) {
590 int i;
591
592 dev_dbg(&client->dev, "Starting fscpos update\n");
593
594 for (i = 0; i < 3; i++) {
595 data->temp_act[i] = fscpos_read_value(client,
596 FSCPOS_REG_TEMP_ACT[i]);
597 data->temp_status[i] = fscpos_read_value(client,
598 FSCPOS_REG_TEMP_STATE[i]);
599 data->fan_act[i] = fscpos_read_value(client,
600 FSCPOS_REG_FAN_ACT[i]);
601 data->fan_status[i] = fscpos_read_value(client,
602 FSCPOS_REG_FAN_STATE[i]);
603 data->fan_ripple[i] = fscpos_read_value(client,
604 FSCPOS_REG_FAN_RIPPLE[i]);
605 if (i < 2) {
606 /* fan2_min is not supported by the chip */
607 data->pwm[i] = fscpos_read_value(client,
608 FSCPOS_REG_PWM[i]);
609 }
610 /* reset fan status if speed is back to > 0 */
611 if (data->fan_status[i] != 0 && data->fan_act[i] > 0) {
612 reset_fan_alarm(client, i);
613 }
614 }
615
616 data->volt[0] = fscpos_read_value(client, FSCPOS_REG_VOLT_12);
617 data->volt[1] = fscpos_read_value(client, FSCPOS_REG_VOLT_5);
618 data->volt[2] = fscpos_read_value(client, FSCPOS_REG_VOLT_BATT);
619
620 data->wdog_preset = fscpos_read_value(client,
621 FSCPOS_REG_WDOG_PRESET);
622 data->wdog_state = fscpos_read_value(client,
623 FSCPOS_REG_WDOG_STATE);
624 data->wdog_control = fscpos_read_value(client,
625 FSCPOS_REG_WDOG_CONTROL);
626
627 data->global_event = fscpos_read_value(client,
628 FSCPOS_REG_EVENT_STATE);
629
630 data->last_updated = jiffies;
631 data->valid = 1;
632 }
633 mutex_unlock(&data->update_lock);
634 return data;
635}
636
637static int __init sm_fscpos_init(void)
638{
639 return i2c_add_driver(&fscpos_driver);
640}
641
642static void __exit sm_fscpos_exit(void)
643{
644 i2c_del_driver(&fscpos_driver);
645}
646
647MODULE_AUTHOR("Stefan Ott <stefan@desire.ch> based on work from Hermann Jung "
648 "<hej@odn.de>, Frodo Looijaard <frodol@dds.nl>"
649 " and Philip Edelbrock <phil@netroedge.com>");
650MODULE_DESCRIPTION("fujitsu siemens poseidon chip driver");
651MODULE_LICENSE("GPL");
652
653module_init(sm_fscpos_init);
654module_exit(sm_fscpos_exit);