blob: 67246299a30814e50ddfbf422046d909036b85ad [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 sis5595.c - Part of lm_sensors, Linux kernel modules
3 for hardware monitoring
4
5 Copyright (C) 1998 - 2001 Frodo Looijaard <frodol@dds.nl>,
6 Kyösti Mälkki <kmalkki@cc.hut.fi>, and
7 Mark D. Studebaker <mdsxyz123@yahoo.com>
8 Ported to Linux 2.6 by Aurelien Jarno <aurelien@aurel32.net> with
9 the help of Jean Delvare <khali@linux-fr.org>
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24*/
25
26/*
27 SiS southbridge has a LM78-like chip integrated on the same IC.
28 This driver is a customized copy of lm78.c
29
30 Supports following revisions:
31 Version PCI ID PCI Revision
32 1 1039/0008 AF or less
33 2 1039/0008 B0 or greater
34
35 Note: these chips contain a 0008 device which is incompatible with the
36 5595. We recognize these by the presence of the listed
37 "blacklist" PCI ID and refuse to load.
38
39 NOT SUPPORTED PCI ID BLACKLIST PCI ID
40 540 0008 0540
41 550 0008 0550
42 5513 0008 5511
43 5581 0008 5597
44 5582 0008 5597
45 5597 0008 5597
46 5598 0008 5597/5598
47 630 0008 0630
48 645 0008 0645
49 730 0008 0730
50 735 0008 0735
51*/
52
53#include <linux/module.h>
54#include <linux/slab.h>
55#include <linux/ioport.h>
56#include <linux/pci.h>
57#include <linux/i2c.h>
Jean Delvarefde09502005-07-19 23:51:07 +020058#include <linux/i2c-isa.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070059#include <linux/i2c-sensor.h>
Mark M. Hoffman943b0832005-07-15 21:39:18 -040060#include <linux/hwmon.h>
61#include <linux/err.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070062#include <linux/init.h>
Dominik Hacklff324092005-05-16 18:12:18 +020063#include <linux/jiffies.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070064#include <asm/io.h>
65
66
67/* If force_addr is set to anything different from 0, we forcibly enable
68 the device at the given address. */
69static u16 force_addr;
70module_param(force_addr, ushort, 0);
71MODULE_PARM_DESC(force_addr,
72 "Initialize the base address of the sensors");
73
Jean Delvare2d8672c2005-07-19 23:56:35 +020074/* Device address
Linus Torvalds1da177e2005-04-16 15:20:36 -070075 Note that we can't determine the ISA address until we have initialized
76 our module */
Jean Delvare2d8672c2005-07-19 23:56:35 +020077static unsigned short address;
Linus Torvalds1da177e2005-04-16 15:20:36 -070078
79/* Many SIS5595 constants specified below */
80
81/* Length of ISA address segment */
82#define SIS5595_EXTENT 8
83/* PCI Config Registers */
84#define SIS5595_REVISION_REG 0x08
85#define SIS5595_BASE_REG 0x68
86#define SIS5595_PIN_REG 0x7A
87#define SIS5595_ENABLE_REG 0x7B
88
89/* Where are the ISA address/data registers relative to the base address */
90#define SIS5595_ADDR_REG_OFFSET 5
91#define SIS5595_DATA_REG_OFFSET 6
92
93/* The SIS5595 registers */
94#define SIS5595_REG_IN_MAX(nr) (0x2b + (nr) * 2)
95#define SIS5595_REG_IN_MIN(nr) (0x2c + (nr) * 2)
96#define SIS5595_REG_IN(nr) (0x20 + (nr))
97
98#define SIS5595_REG_FAN_MIN(nr) (0x3b + (nr))
99#define SIS5595_REG_FAN(nr) (0x28 + (nr))
100
101/* On the first version of the chip, the temp registers are separate.
102 On the second version,
103 TEMP pin is shared with IN4, configured in PCI register 0x7A.
104 The registers are the same as well.
105 OVER and HYST are really MAX and MIN. */
106
107#define REV2MIN 0xb0
108#define SIS5595_REG_TEMP (( data->revision) >= REV2MIN) ? \
109 SIS5595_REG_IN(4) : 0x27
110#define SIS5595_REG_TEMP_OVER (( data->revision) >= REV2MIN) ? \
111 SIS5595_REG_IN_MAX(4) : 0x39
112#define SIS5595_REG_TEMP_HYST (( data->revision) >= REV2MIN) ? \
113 SIS5595_REG_IN_MIN(4) : 0x3a
114
115#define SIS5595_REG_CONFIG 0x40
116#define SIS5595_REG_ALARM1 0x41
117#define SIS5595_REG_ALARM2 0x42
118#define SIS5595_REG_FANDIV 0x47
119
120/* Conversions. Limit checking is only done on the TO_REG
121 variants. */
122
123/* IN: mV, (0V to 4.08V)
124 REG: 16mV/bit */
125static inline u8 IN_TO_REG(unsigned long val)
126{
127 unsigned long nval = SENSORS_LIMIT(val, 0, 4080);
128 return (nval + 8) / 16;
129}
130#define IN_FROM_REG(val) ((val) * 16)
131
132static inline u8 FAN_TO_REG(long rpm, int div)
133{
134 if (rpm <= 0)
135 return 255;
136 return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
137}
138
139static inline int FAN_FROM_REG(u8 val, int div)
140{
141 return val==0 ? -1 : val==255 ? 0 : 1350000/(val*div);
142}
143
144/* TEMP: mC (-54.12C to +157.53C)
145 REG: 0.83C/bit + 52.12, two's complement */
146static inline int TEMP_FROM_REG(s8 val)
147{
148 return val * 830 + 52120;
149}
150static inline s8 TEMP_TO_REG(int val)
151{
152 int nval = SENSORS_LIMIT(val, -54120, 157530) ;
153 return nval<0 ? (nval-5212-415)/830 : (nval-5212+415)/830;
154}
155
156/* FAN DIV: 1, 2, 4, or 8 (defaults to 2)
157 REG: 0, 1, 2, or 3 (respectively) (defaults to 1) */
158static inline u8 DIV_TO_REG(int val)
159{
160 return val==8 ? 3 : val==4 ? 2 : val==1 ? 0 : 1;
161}
162#define DIV_FROM_REG(val) (1 << (val))
163
164/* For the SIS5595, we need to keep some data in memory. That
165 data is pointed to by sis5595_list[NR]->data. The structure itself is
166 dynamically allocated, at the time when the new sis5595 client is
167 allocated. */
168struct sis5595_data {
169 struct i2c_client client;
Mark M. Hoffman943b0832005-07-15 21:39:18 -0400170 struct class_device *class_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171 struct semaphore lock;
172
173 struct semaphore update_lock;
174 char valid; /* !=0 if following fields are valid */
175 unsigned long last_updated; /* In jiffies */
176 char maxins; /* == 3 if temp enabled, otherwise == 4 */
177 u8 revision; /* Reg. value */
178
179 u8 in[5]; /* Register value */
180 u8 in_max[5]; /* Register value */
181 u8 in_min[5]; /* Register value */
182 u8 fan[2]; /* Register value */
183 u8 fan_min[2]; /* Register value */
184 s8 temp; /* Register value */
185 s8 temp_over; /* Register value */
186 s8 temp_hyst; /* Register value */
187 u8 fan_div[2]; /* Register encoding, shifted right */
188 u16 alarms; /* Register encoding, combined */
189};
190
191static struct pci_dev *s_bridge; /* pointer to the (only) sis5595 */
192
Jean Delvare2d8672c2005-07-19 23:56:35 +0200193static int sis5595_detect(struct i2c_adapter *adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194static int sis5595_detach_client(struct i2c_client *client);
195
196static int sis5595_read_value(struct i2c_client *client, u8 register);
197static int sis5595_write_value(struct i2c_client *client, u8 register, u8 value);
198static struct sis5595_data *sis5595_update_device(struct device *dev);
199static void sis5595_init_client(struct i2c_client *client);
200
201static struct i2c_driver sis5595_driver = {
202 .owner = THIS_MODULE,
203 .name = "sis5595",
Jean Delvare2d8672c2005-07-19 23:56:35 +0200204 .attach_adapter = sis5595_detect,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205 .detach_client = sis5595_detach_client,
206};
207
208/* 4 Voltages */
209static ssize_t show_in(struct device *dev, char *buf, int nr)
210{
211 struct sis5595_data *data = sis5595_update_device(dev);
212 return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr]));
213}
214
215static ssize_t show_in_min(struct device *dev, char *buf, int nr)
216{
217 struct sis5595_data *data = sis5595_update_device(dev);
218 return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr]));
219}
220
221static ssize_t show_in_max(struct device *dev, char *buf, int nr)
222{
223 struct sis5595_data *data = sis5595_update_device(dev);
224 return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr]));
225}
226
227static ssize_t set_in_min(struct device *dev, const char *buf,
228 size_t count, int nr)
229{
230 struct i2c_client *client = to_i2c_client(dev);
231 struct sis5595_data *data = i2c_get_clientdata(client);
232 unsigned long val = simple_strtoul(buf, NULL, 10);
233
234 down(&data->update_lock);
235 data->in_min[nr] = IN_TO_REG(val);
236 sis5595_write_value(client, SIS5595_REG_IN_MIN(nr), data->in_min[nr]);
237 up(&data->update_lock);
238 return count;
239}
240
241static ssize_t set_in_max(struct device *dev, const char *buf,
242 size_t count, int nr)
243{
244 struct i2c_client *client = to_i2c_client(dev);
245 struct sis5595_data *data = i2c_get_clientdata(client);
246 unsigned long val = simple_strtoul(buf, NULL, 10);
247
248 down(&data->update_lock);
249 data->in_max[nr] = IN_TO_REG(val);
250 sis5595_write_value(client, SIS5595_REG_IN_MAX(nr), data->in_max[nr]);
251 up(&data->update_lock);
252 return count;
253}
254
255#define show_in_offset(offset) \
256static ssize_t \
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400257 show_in##offset (struct device *dev, struct device_attribute *attr, char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258{ \
259 return show_in(dev, buf, offset); \
260} \
261static DEVICE_ATTR(in##offset##_input, S_IRUGO, \
262 show_in##offset, NULL); \
263static ssize_t \
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400264 show_in##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265{ \
266 return show_in_min(dev, buf, offset); \
267} \
268static ssize_t \
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400269 show_in##offset##_max (struct device *dev, struct device_attribute *attr, char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270{ \
271 return show_in_max(dev, buf, offset); \
272} \
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400273static ssize_t set_in##offset##_min (struct device *dev, struct device_attribute *attr, \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 const char *buf, size_t count) \
275{ \
276 return set_in_min(dev, buf, count, offset); \
277} \
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400278static ssize_t set_in##offset##_max (struct device *dev, struct device_attribute *attr, \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 const char *buf, size_t count) \
280{ \
281 return set_in_max(dev, buf, count, offset); \
282} \
283static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
284 show_in##offset##_min, set_in##offset##_min); \
285static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
286 show_in##offset##_max, set_in##offset##_max);
287
288show_in_offset(0);
289show_in_offset(1);
290show_in_offset(2);
291show_in_offset(3);
292show_in_offset(4);
293
294/* Temperature */
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400295static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296{
297 struct sis5595_data *data = sis5595_update_device(dev);
298 return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp));
299}
300
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400301static ssize_t show_temp_over(struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302{
303 struct sis5595_data *data = sis5595_update_device(dev);
304 return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_over));
305}
306
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400307static ssize_t set_temp_over(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308{
309 struct i2c_client *client = to_i2c_client(dev);
310 struct sis5595_data *data = i2c_get_clientdata(client);
311 long val = simple_strtol(buf, NULL, 10);
312
313 down(&data->update_lock);
314 data->temp_over = TEMP_TO_REG(val);
315 sis5595_write_value(client, SIS5595_REG_TEMP_OVER, data->temp_over);
316 up(&data->update_lock);
317 return count;
318}
319
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400320static ssize_t show_temp_hyst(struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321{
322 struct sis5595_data *data = sis5595_update_device(dev);
323 return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_hyst));
324}
325
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400326static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327{
328 struct i2c_client *client = to_i2c_client(dev);
329 struct sis5595_data *data = i2c_get_clientdata(client);
330 long val = simple_strtol(buf, NULL, 10);
331
332 down(&data->update_lock);
333 data->temp_hyst = TEMP_TO_REG(val);
334 sis5595_write_value(client, SIS5595_REG_TEMP_HYST, data->temp_hyst);
335 up(&data->update_lock);
336 return count;
337}
338
339static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL);
340static DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR,
341 show_temp_over, set_temp_over);
342static DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR,
343 show_temp_hyst, set_temp_hyst);
344
345/* 2 Fans */
346static ssize_t show_fan(struct device *dev, char *buf, int nr)
347{
348 struct sis5595_data *data = sis5595_update_device(dev);
349 return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
350 DIV_FROM_REG(data->fan_div[nr])) );
351}
352
353static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
354{
355 struct sis5595_data *data = sis5595_update_device(dev);
356 return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan_min[nr],
357 DIV_FROM_REG(data->fan_div[nr])) );
358}
359
360static ssize_t set_fan_min(struct device *dev, const char *buf,
361 size_t count, int nr)
362{
363 struct i2c_client *client = to_i2c_client(dev);
364 struct sis5595_data *data = i2c_get_clientdata(client);
365 unsigned long val = simple_strtoul(buf, NULL, 10);
366
367 down(&data->update_lock);
368 data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
369 sis5595_write_value(client, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]);
370 up(&data->update_lock);
371 return count;
372}
373
374static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
375{
376 struct sis5595_data *data = sis5595_update_device(dev);
377 return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]) );
378}
379
380/* Note: we save and restore the fan minimum here, because its value is
381 determined in part by the fan divisor. This follows the principle of
382 least suprise; the user doesn't expect the fan minimum to change just
383 because the divisor changed. */
384static ssize_t set_fan_div(struct device *dev, const char *buf,
385 size_t count, int nr)
386{
387 struct i2c_client *client = to_i2c_client(dev);
388 struct sis5595_data *data = i2c_get_clientdata(client);
389 unsigned long min;
390 unsigned long val = simple_strtoul(buf, NULL, 10);
391 int reg;
392
393 down(&data->update_lock);
394 min = FAN_FROM_REG(data->fan_min[nr],
395 DIV_FROM_REG(data->fan_div[nr]));
396 reg = sis5595_read_value(client, SIS5595_REG_FANDIV);
397
398 switch (val) {
399 case 1: data->fan_div[nr] = 0; break;
400 case 2: data->fan_div[nr] = 1; break;
401 case 4: data->fan_div[nr] = 2; break;
402 case 8: data->fan_div[nr] = 3; break;
403 default:
404 dev_err(&client->dev, "fan_div value %ld not "
405 "supported. Choose one of 1, 2, 4 or 8!\n", val);
406 up(&data->update_lock);
407 return -EINVAL;
408 }
409
410 switch (nr) {
411 case 0:
412 reg = (reg & 0xcf) | (data->fan_div[nr] << 4);
413 break;
414 case 1:
415 reg = (reg & 0x3f) | (data->fan_div[nr] << 6);
416 break;
417 }
418 sis5595_write_value(client, SIS5595_REG_FANDIV, reg);
419 data->fan_min[nr] =
420 FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
421 sis5595_write_value(client, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]);
422 up(&data->update_lock);
423 return count;
424}
425
426#define show_fan_offset(offset) \
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400427static ssize_t show_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428{ \
429 return show_fan(dev, buf, offset - 1); \
430} \
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400431static ssize_t show_fan_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432{ \
433 return show_fan_min(dev, buf, offset - 1); \
434} \
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400435static ssize_t show_fan_##offset##_div (struct device *dev, struct device_attribute *attr, char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436{ \
437 return show_fan_div(dev, buf, offset - 1); \
438} \
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400439static ssize_t set_fan_##offset##_min (struct device *dev, struct device_attribute *attr, \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 const char *buf, size_t count) \
441{ \
442 return set_fan_min(dev, buf, count, offset - 1); \
443} \
444static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL);\
445static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
446 show_fan_##offset##_min, set_fan_##offset##_min);
447
448show_fan_offset(1);
449show_fan_offset(2);
450
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400451static ssize_t set_fan_1_div(struct device *dev, struct device_attribute *attr, const char *buf,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 size_t count)
453{
454 return set_fan_div(dev, buf, count, 0) ;
455}
456
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400457static ssize_t set_fan_2_div(struct device *dev, struct device_attribute *attr, const char *buf,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 size_t count)
459{
460 return set_fan_div(dev, buf, count, 1) ;
461}
462static DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR,
463 show_fan_1_div, set_fan_1_div);
464static DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR,
465 show_fan_2_div, set_fan_2_div);
466
467/* Alarms */
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400468static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469{
470 struct sis5595_data *data = sis5595_update_device(dev);
471 return sprintf(buf, "%d\n", data->alarms);
472}
473static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
474
475/* This is called when the module is loaded */
Jean Delvare2d8672c2005-07-19 23:56:35 +0200476static int sis5595_detect(struct i2c_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477{
478 int err = 0;
479 int i;
480 struct i2c_client *new_client;
481 struct sis5595_data *data;
482 char val;
483 u16 a;
484
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 if (force_addr)
486 address = force_addr & ~(SIS5595_EXTENT - 1);
487 /* Reserve the ISA region */
488 if (!request_region(address, SIS5595_EXTENT, sis5595_driver.name)) {
489 err = -EBUSY;
490 goto exit;
491 }
492 if (force_addr) {
493 dev_warn(&adapter->dev, "forcing ISA address 0x%04X\n", address);
494 if (PCIBIOS_SUCCESSFUL !=
495 pci_write_config_word(s_bridge, SIS5595_BASE_REG, address))
496 goto exit_release;
497 if (PCIBIOS_SUCCESSFUL !=
498 pci_read_config_word(s_bridge, SIS5595_BASE_REG, &a))
499 goto exit_release;
500 if ((a & ~(SIS5595_EXTENT - 1)) != address)
501 /* doesn't work for some chips? */
502 goto exit_release;
503 }
504
505 if (PCIBIOS_SUCCESSFUL !=
506 pci_read_config_byte(s_bridge, SIS5595_ENABLE_REG, &val)) {
507 goto exit_release;
508 }
509 if ((val & 0x80) == 0) {
510 if (PCIBIOS_SUCCESSFUL !=
511 pci_write_config_byte(s_bridge, SIS5595_ENABLE_REG,
512 val | 0x80))
513 goto exit_release;
514 if (PCIBIOS_SUCCESSFUL !=
515 pci_read_config_byte(s_bridge, SIS5595_ENABLE_REG, &val))
516 goto exit_release;
517 if ((val & 0x80) == 0)
518 /* doesn't work for some chips! */
519 goto exit_release;
520 }
521
522 if (!(data = kmalloc(sizeof(struct sis5595_data), GFP_KERNEL))) {
523 err = -ENOMEM;
524 goto exit_release;
525 }
526 memset(data, 0, sizeof(struct sis5595_data));
527
528 new_client = &data->client;
529 new_client->addr = address;
530 init_MUTEX(&data->lock);
531 i2c_set_clientdata(new_client, data);
532 new_client->adapter = adapter;
533 new_client->driver = &sis5595_driver;
534 new_client->flags = 0;
535
536 /* Check revision and pin registers to determine whether 4 or 5 voltages */
537 pci_read_config_byte(s_bridge, SIS5595_REVISION_REG, &(data->revision));
538 /* 4 voltages, 1 temp */
539 data->maxins = 3;
540 if (data->revision >= REV2MIN) {
541 pci_read_config_byte(s_bridge, SIS5595_PIN_REG, &val);
542 if (!(val & 0x80))
543 /* 5 voltages, no temps */
544 data->maxins = 4;
545 }
546
547 /* Fill in the remaining client fields and put it into the global list */
548 strlcpy(new_client->name, "sis5595", I2C_NAME_SIZE);
549
550 data->valid = 0;
551 init_MUTEX(&data->update_lock);
552
553 /* Tell the I2C layer a new client has arrived */
554 if ((err = i2c_attach_client(new_client)))
555 goto exit_free;
556
557 /* Initialize the SIS5595 chip */
558 sis5595_init_client(new_client);
559
560 /* A few vars need to be filled upon startup */
561 for (i = 0; i < 2; i++) {
562 data->fan_min[i] = sis5595_read_value(new_client,
563 SIS5595_REG_FAN_MIN(i));
564 }
565
566 /* Register sysfs hooks */
Mark M. Hoffman943b0832005-07-15 21:39:18 -0400567 data->class_dev = hwmon_device_register(&new_client->dev);
568 if (IS_ERR(data->class_dev)) {
569 err = PTR_ERR(data->class_dev);
570 goto exit_detach;
571 }
572
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 device_create_file(&new_client->dev, &dev_attr_in0_input);
574 device_create_file(&new_client->dev, &dev_attr_in0_min);
575 device_create_file(&new_client->dev, &dev_attr_in0_max);
576 device_create_file(&new_client->dev, &dev_attr_in1_input);
577 device_create_file(&new_client->dev, &dev_attr_in1_min);
578 device_create_file(&new_client->dev, &dev_attr_in1_max);
579 device_create_file(&new_client->dev, &dev_attr_in2_input);
580 device_create_file(&new_client->dev, &dev_attr_in2_min);
581 device_create_file(&new_client->dev, &dev_attr_in2_max);
582 device_create_file(&new_client->dev, &dev_attr_in3_input);
583 device_create_file(&new_client->dev, &dev_attr_in3_min);
584 device_create_file(&new_client->dev, &dev_attr_in3_max);
585 if (data->maxins == 4) {
586 device_create_file(&new_client->dev, &dev_attr_in4_input);
587 device_create_file(&new_client->dev, &dev_attr_in4_min);
588 device_create_file(&new_client->dev, &dev_attr_in4_max);
589 }
590 device_create_file(&new_client->dev, &dev_attr_fan1_input);
591 device_create_file(&new_client->dev, &dev_attr_fan1_min);
592 device_create_file(&new_client->dev, &dev_attr_fan1_div);
593 device_create_file(&new_client->dev, &dev_attr_fan2_input);
594 device_create_file(&new_client->dev, &dev_attr_fan2_min);
595 device_create_file(&new_client->dev, &dev_attr_fan2_div);
596 device_create_file(&new_client->dev, &dev_attr_alarms);
597 if (data->maxins == 3) {
598 device_create_file(&new_client->dev, &dev_attr_temp1_input);
599 device_create_file(&new_client->dev, &dev_attr_temp1_max);
600 device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
601 }
602 return 0;
Mark M. Hoffman943b0832005-07-15 21:39:18 -0400603
604exit_detach:
605 i2c_detach_client(new_client);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606exit_free:
607 kfree(data);
608exit_release:
609 release_region(address, SIS5595_EXTENT);
610exit:
611 return err;
612}
613
614static int sis5595_detach_client(struct i2c_client *client)
615{
Mark M. Hoffman943b0832005-07-15 21:39:18 -0400616 struct sis5595_data *data = i2c_get_clientdata(client);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 int err;
618
Mark M. Hoffman943b0832005-07-15 21:39:18 -0400619 hwmon_device_unregister(data->class_dev);
620
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 if ((err = i2c_detach_client(client))) {
622 dev_err(&client->dev,
623 "Client deregistration failed, client not detached.\n");
624 return err;
625 }
626
Jean Delvare2d8672c2005-07-19 23:56:35 +0200627 release_region(client->addr, SIS5595_EXTENT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628
Mark M. Hoffman943b0832005-07-15 21:39:18 -0400629 kfree(data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630
631 return 0;
632}
633
634
635/* ISA access must be locked explicitly. */
636static int sis5595_read_value(struct i2c_client *client, u8 reg)
637{
638 int res;
639
640 struct sis5595_data *data = i2c_get_clientdata(client);
641 down(&data->lock);
642 outb_p(reg, client->addr + SIS5595_ADDR_REG_OFFSET);
643 res = inb_p(client->addr + SIS5595_DATA_REG_OFFSET);
644 up(&data->lock);
645 return res;
646}
647
648static int sis5595_write_value(struct i2c_client *client, u8 reg, u8 value)
649{
650 struct sis5595_data *data = i2c_get_clientdata(client);
651 down(&data->lock);
652 outb_p(reg, client->addr + SIS5595_ADDR_REG_OFFSET);
653 outb_p(value, client->addr + SIS5595_DATA_REG_OFFSET);
654 up(&data->lock);
655 return 0;
656}
657
658/* Called when we have found a new SIS5595. */
659static void sis5595_init_client(struct i2c_client *client)
660{
661 u8 config = sis5595_read_value(client, SIS5595_REG_CONFIG);
662 if (!(config & 0x01))
663 sis5595_write_value(client, SIS5595_REG_CONFIG,
664 (config & 0xf7) | 0x01);
665}
666
667static struct sis5595_data *sis5595_update_device(struct device *dev)
668{
669 struct i2c_client *client = to_i2c_client(dev);
670 struct sis5595_data *data = i2c_get_clientdata(client);
671 int i;
672
673 down(&data->update_lock);
674
675 if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
676 || !data->valid) {
677
678 for (i = 0; i <= data->maxins; i++) {
679 data->in[i] =
680 sis5595_read_value(client, SIS5595_REG_IN(i));
681 data->in_min[i] =
682 sis5595_read_value(client,
683 SIS5595_REG_IN_MIN(i));
684 data->in_max[i] =
685 sis5595_read_value(client,
686 SIS5595_REG_IN_MAX(i));
687 }
688 for (i = 0; i < 2; i++) {
689 data->fan[i] =
690 sis5595_read_value(client, SIS5595_REG_FAN(i));
691 data->fan_min[i] =
692 sis5595_read_value(client,
693 SIS5595_REG_FAN_MIN(i));
694 }
695 if (data->maxins == 3) {
696 data->temp =
697 sis5595_read_value(client, SIS5595_REG_TEMP);
698 data->temp_over =
699 sis5595_read_value(client, SIS5595_REG_TEMP_OVER);
700 data->temp_hyst =
701 sis5595_read_value(client, SIS5595_REG_TEMP_HYST);
702 }
703 i = sis5595_read_value(client, SIS5595_REG_FANDIV);
704 data->fan_div[0] = (i >> 4) & 0x03;
705 data->fan_div[1] = i >> 6;
706 data->alarms =
707 sis5595_read_value(client, SIS5595_REG_ALARM1) |
708 (sis5595_read_value(client, SIS5595_REG_ALARM2) << 8);
709 data->last_updated = jiffies;
710 data->valid = 1;
711 }
712
713 up(&data->update_lock);
714
715 return data;
716}
717
718static struct pci_device_id sis5595_pci_ids[] = {
719 { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) },
720 { 0, }
721};
722
723MODULE_DEVICE_TABLE(pci, sis5595_pci_ids);
724
725static int blacklist[] __devinitdata = {
726 PCI_DEVICE_ID_SI_540,
727 PCI_DEVICE_ID_SI_550,
728 PCI_DEVICE_ID_SI_630,
729 PCI_DEVICE_ID_SI_645,
730 PCI_DEVICE_ID_SI_730,
731 PCI_DEVICE_ID_SI_735,
732 PCI_DEVICE_ID_SI_5511, /* 5513 chip has the 0008 device but
733 that ID shows up in other chips so we
734 use the 5511 ID for recognition */
735 PCI_DEVICE_ID_SI_5597,
736 PCI_DEVICE_ID_SI_5598,
737 0 };
738
739static int __devinit sis5595_pci_probe(struct pci_dev *dev,
740 const struct pci_device_id *id)
741{
742 u16 val;
743 int *i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744
745 for (i = blacklist; *i != 0; i++) {
746 struct pci_dev *dev;
747 dev = pci_get_device(PCI_VENDOR_ID_SI, *i, NULL);
748 if (dev) {
749 dev_err(&dev->dev, "Looked for SIS5595 but found unsupported device %.4x\n", *i);
750 pci_dev_put(dev);
751 return -ENODEV;
752 }
753 }
754
755 if (PCIBIOS_SUCCESSFUL !=
756 pci_read_config_word(dev, SIS5595_BASE_REG, &val))
757 return -ENODEV;
758
Jean Delvare2d8672c2005-07-19 23:56:35 +0200759 address = val & ~(SIS5595_EXTENT - 1);
760 if (address == 0 && force_addr == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 dev_err(&dev->dev, "Base address not set - upgrade BIOS or use force_addr=0xaddr\n");
762 return -ENODEV;
763 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764
Jean Delvare2d8672c2005-07-19 23:56:35 +0200765 if (!address) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 dev_err(&dev->dev,"No SiS 5595 sensors found.\n");
767 return -ENODEV;
768 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769
770 s_bridge = pci_dev_get(dev);
Jean Delvarefde09502005-07-19 23:51:07 +0200771 if (i2c_isa_add_driver(&sis5595_driver)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 pci_dev_put(s_bridge);
773 s_bridge = NULL;
774 }
775
776 /* Always return failure here. This is to allow other drivers to bind
777 * to this pci device. We don't really want to have control over the
778 * pci device, we only wanted to read as few register values from it.
779 */
780 return -ENODEV;
781}
782
783static struct pci_driver sis5595_pci_driver = {
784 .name = "sis5595",
785 .id_table = sis5595_pci_ids,
786 .probe = sis5595_pci_probe,
787};
788
789static int __init sm_sis5595_init(void)
790{
791 return pci_register_driver(&sis5595_pci_driver);
792}
793
794static void __exit sm_sis5595_exit(void)
795{
796 pci_unregister_driver(&sis5595_pci_driver);
797 if (s_bridge != NULL) {
Jean Delvarefde09502005-07-19 23:51:07 +0200798 i2c_isa_del_driver(&sis5595_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 pci_dev_put(s_bridge);
800 s_bridge = NULL;
801 }
802}
803
804MODULE_AUTHOR("Aurelien Jarno <aurelien@aurel32.net>");
805MODULE_DESCRIPTION("SiS 5595 Sensor device");
806MODULE_LICENSE("GPL");
807
808module_init(sm_sis5595_init);
809module_exit(sm_sis5595_exit);