blob: 21aa9a41f62cbc5e7432a73e93318de9be0cf666 [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>
Mark M. Hoffman943b0832005-07-15 21:39:18 -040059#include <linux/hwmon.h>
60#include <linux/err.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070061#include <linux/init.h>
Dominik Hacklff324092005-05-16 18:12:18 +020062#include <linux/jiffies.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070063#include <asm/io.h>
64
65
66/* If force_addr is set to anything different from 0, we forcibly enable
67 the device at the given address. */
68static u16 force_addr;
69module_param(force_addr, ushort, 0);
70MODULE_PARM_DESC(force_addr,
71 "Initialize the base address of the sensors");
72
Jean Delvare2d8672c2005-07-19 23:56:35 +020073/* Device address
Linus Torvalds1da177e2005-04-16 15:20:36 -070074 Note that we can't determine the ISA address until we have initialized
75 our module */
Jean Delvare2d8672c2005-07-19 23:56:35 +020076static unsigned short address;
Linus Torvalds1da177e2005-04-16 15:20:36 -070077
78/* Many SIS5595 constants specified below */
79
80/* Length of ISA address segment */
81#define SIS5595_EXTENT 8
82/* PCI Config Registers */
83#define SIS5595_REVISION_REG 0x08
84#define SIS5595_BASE_REG 0x68
85#define SIS5595_PIN_REG 0x7A
86#define SIS5595_ENABLE_REG 0x7B
87
88/* Where are the ISA address/data registers relative to the base address */
89#define SIS5595_ADDR_REG_OFFSET 5
90#define SIS5595_DATA_REG_OFFSET 6
91
92/* The SIS5595 registers */
93#define SIS5595_REG_IN_MAX(nr) (0x2b + (nr) * 2)
94#define SIS5595_REG_IN_MIN(nr) (0x2c + (nr) * 2)
95#define SIS5595_REG_IN(nr) (0x20 + (nr))
96
97#define SIS5595_REG_FAN_MIN(nr) (0x3b + (nr))
98#define SIS5595_REG_FAN(nr) (0x28 + (nr))
99
100/* On the first version of the chip, the temp registers are separate.
101 On the second version,
102 TEMP pin is shared with IN4, configured in PCI register 0x7A.
103 The registers are the same as well.
104 OVER and HYST are really MAX and MIN. */
105
106#define REV2MIN 0xb0
107#define SIS5595_REG_TEMP (( data->revision) >= REV2MIN) ? \
108 SIS5595_REG_IN(4) : 0x27
109#define SIS5595_REG_TEMP_OVER (( data->revision) >= REV2MIN) ? \
110 SIS5595_REG_IN_MAX(4) : 0x39
111#define SIS5595_REG_TEMP_HYST (( data->revision) >= REV2MIN) ? \
112 SIS5595_REG_IN_MIN(4) : 0x3a
113
114#define SIS5595_REG_CONFIG 0x40
115#define SIS5595_REG_ALARM1 0x41
116#define SIS5595_REG_ALARM2 0x42
117#define SIS5595_REG_FANDIV 0x47
118
119/* Conversions. Limit checking is only done on the TO_REG
120 variants. */
121
122/* IN: mV, (0V to 4.08V)
123 REG: 16mV/bit */
124static inline u8 IN_TO_REG(unsigned long val)
125{
126 unsigned long nval = SENSORS_LIMIT(val, 0, 4080);
127 return (nval + 8) / 16;
128}
129#define IN_FROM_REG(val) ((val) * 16)
130
131static inline u8 FAN_TO_REG(long rpm, int div)
132{
133 if (rpm <= 0)
134 return 255;
135 return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
136}
137
138static inline int FAN_FROM_REG(u8 val, int div)
139{
140 return val==0 ? -1 : val==255 ? 0 : 1350000/(val*div);
141}
142
143/* TEMP: mC (-54.12C to +157.53C)
144 REG: 0.83C/bit + 52.12, two's complement */
145static inline int TEMP_FROM_REG(s8 val)
146{
147 return val * 830 + 52120;
148}
149static inline s8 TEMP_TO_REG(int val)
150{
151 int nval = SENSORS_LIMIT(val, -54120, 157530) ;
152 return nval<0 ? (nval-5212-415)/830 : (nval-5212+415)/830;
153}
154
155/* FAN DIV: 1, 2, 4, or 8 (defaults to 2)
156 REG: 0, 1, 2, or 3 (respectively) (defaults to 1) */
157static inline u8 DIV_TO_REG(int val)
158{
159 return val==8 ? 3 : val==4 ? 2 : val==1 ? 0 : 1;
160}
161#define DIV_FROM_REG(val) (1 << (val))
162
163/* For the SIS5595, we need to keep some data in memory. That
164 data is pointed to by sis5595_list[NR]->data. The structure itself is
165 dynamically allocated, at the time when the new sis5595 client is
166 allocated. */
167struct sis5595_data {
168 struct i2c_client client;
Mark M. Hoffman943b0832005-07-15 21:39:18 -0400169 struct class_device *class_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170 struct semaphore lock;
171
172 struct semaphore update_lock;
173 char valid; /* !=0 if following fields are valid */
174 unsigned long last_updated; /* In jiffies */
175 char maxins; /* == 3 if temp enabled, otherwise == 4 */
176 u8 revision; /* Reg. value */
177
178 u8 in[5]; /* Register value */
179 u8 in_max[5]; /* Register value */
180 u8 in_min[5]; /* Register value */
181 u8 fan[2]; /* Register value */
182 u8 fan_min[2]; /* Register value */
183 s8 temp; /* Register value */
184 s8 temp_over; /* Register value */
185 s8 temp_hyst; /* Register value */
186 u8 fan_div[2]; /* Register encoding, shifted right */
187 u16 alarms; /* Register encoding, combined */
188};
189
190static struct pci_dev *s_bridge; /* pointer to the (only) sis5595 */
191
Jean Delvare2d8672c2005-07-19 23:56:35 +0200192static int sis5595_detect(struct i2c_adapter *adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193static int sis5595_detach_client(struct i2c_client *client);
194
195static int sis5595_read_value(struct i2c_client *client, u8 register);
196static int sis5595_write_value(struct i2c_client *client, u8 register, u8 value);
197static struct sis5595_data *sis5595_update_device(struct device *dev);
198static void sis5595_init_client(struct i2c_client *client);
199
200static struct i2c_driver sis5595_driver = {
201 .owner = THIS_MODULE,
202 .name = "sis5595",
Jean Delvare2d8672c2005-07-19 23:56:35 +0200203 .attach_adapter = sis5595_detect,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204 .detach_client = sis5595_detach_client,
205};
206
207/* 4 Voltages */
208static ssize_t show_in(struct device *dev, char *buf, int nr)
209{
210 struct sis5595_data *data = sis5595_update_device(dev);
211 return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr]));
212}
213
214static ssize_t show_in_min(struct device *dev, char *buf, int nr)
215{
216 struct sis5595_data *data = sis5595_update_device(dev);
217 return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr]));
218}
219
220static ssize_t show_in_max(struct device *dev, char *buf, int nr)
221{
222 struct sis5595_data *data = sis5595_update_device(dev);
223 return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr]));
224}
225
226static ssize_t set_in_min(struct device *dev, const char *buf,
227 size_t count, int nr)
228{
229 struct i2c_client *client = to_i2c_client(dev);
230 struct sis5595_data *data = i2c_get_clientdata(client);
231 unsigned long val = simple_strtoul(buf, NULL, 10);
232
233 down(&data->update_lock);
234 data->in_min[nr] = IN_TO_REG(val);
235 sis5595_write_value(client, SIS5595_REG_IN_MIN(nr), data->in_min[nr]);
236 up(&data->update_lock);
237 return count;
238}
239
240static ssize_t set_in_max(struct device *dev, const char *buf,
241 size_t count, int nr)
242{
243 struct i2c_client *client = to_i2c_client(dev);
244 struct sis5595_data *data = i2c_get_clientdata(client);
245 unsigned long val = simple_strtoul(buf, NULL, 10);
246
247 down(&data->update_lock);
248 data->in_max[nr] = IN_TO_REG(val);
249 sis5595_write_value(client, SIS5595_REG_IN_MAX(nr), data->in_max[nr]);
250 up(&data->update_lock);
251 return count;
252}
253
254#define show_in_offset(offset) \
255static ssize_t \
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400256 show_in##offset (struct device *dev, struct device_attribute *attr, char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257{ \
258 return show_in(dev, buf, offset); \
259} \
260static DEVICE_ATTR(in##offset##_input, S_IRUGO, \
261 show_in##offset, NULL); \
262static ssize_t \
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400263 show_in##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264{ \
265 return show_in_min(dev, buf, offset); \
266} \
267static ssize_t \
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400268 show_in##offset##_max (struct device *dev, struct device_attribute *attr, char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269{ \
270 return show_in_max(dev, buf, offset); \
271} \
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400272static ssize_t set_in##offset##_min (struct device *dev, struct device_attribute *attr, \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 const char *buf, size_t count) \
274{ \
275 return set_in_min(dev, buf, count, offset); \
276} \
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400277static ssize_t set_in##offset##_max (struct device *dev, struct device_attribute *attr, \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 const char *buf, size_t count) \
279{ \
280 return set_in_max(dev, buf, count, offset); \
281} \
282static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
283 show_in##offset##_min, set_in##offset##_min); \
284static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
285 show_in##offset##_max, set_in##offset##_max);
286
287show_in_offset(0);
288show_in_offset(1);
289show_in_offset(2);
290show_in_offset(3);
291show_in_offset(4);
292
293/* Temperature */
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400294static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295{
296 struct sis5595_data *data = sis5595_update_device(dev);
297 return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp));
298}
299
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400300static ssize_t show_temp_over(struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301{
302 struct sis5595_data *data = sis5595_update_device(dev);
303 return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_over));
304}
305
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400306static 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 -0700307{
308 struct i2c_client *client = to_i2c_client(dev);
309 struct sis5595_data *data = i2c_get_clientdata(client);
310 long val = simple_strtol(buf, NULL, 10);
311
312 down(&data->update_lock);
313 data->temp_over = TEMP_TO_REG(val);
314 sis5595_write_value(client, SIS5595_REG_TEMP_OVER, data->temp_over);
315 up(&data->update_lock);
316 return count;
317}
318
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400319static ssize_t show_temp_hyst(struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320{
321 struct sis5595_data *data = sis5595_update_device(dev);
322 return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_hyst));
323}
324
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400325static 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 -0700326{
327 struct i2c_client *client = to_i2c_client(dev);
328 struct sis5595_data *data = i2c_get_clientdata(client);
329 long val = simple_strtol(buf, NULL, 10);
330
331 down(&data->update_lock);
332 data->temp_hyst = TEMP_TO_REG(val);
333 sis5595_write_value(client, SIS5595_REG_TEMP_HYST, data->temp_hyst);
334 up(&data->update_lock);
335 return count;
336}
337
338static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL);
339static DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR,
340 show_temp_over, set_temp_over);
341static DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR,
342 show_temp_hyst, set_temp_hyst);
343
344/* 2 Fans */
345static ssize_t show_fan(struct device *dev, char *buf, int nr)
346{
347 struct sis5595_data *data = sis5595_update_device(dev);
348 return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
349 DIV_FROM_REG(data->fan_div[nr])) );
350}
351
352static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
353{
354 struct sis5595_data *data = sis5595_update_device(dev);
355 return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan_min[nr],
356 DIV_FROM_REG(data->fan_div[nr])) );
357}
358
359static ssize_t set_fan_min(struct device *dev, const char *buf,
360 size_t count, int nr)
361{
362 struct i2c_client *client = to_i2c_client(dev);
363 struct sis5595_data *data = i2c_get_clientdata(client);
364 unsigned long val = simple_strtoul(buf, NULL, 10);
365
366 down(&data->update_lock);
367 data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
368 sis5595_write_value(client, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]);
369 up(&data->update_lock);
370 return count;
371}
372
373static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
374{
375 struct sis5595_data *data = sis5595_update_device(dev);
376 return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]) );
377}
378
379/* Note: we save and restore the fan minimum here, because its value is
380 determined in part by the fan divisor. This follows the principle of
381 least suprise; the user doesn't expect the fan minimum to change just
382 because the divisor changed. */
383static ssize_t set_fan_div(struct device *dev, const char *buf,
384 size_t count, int nr)
385{
386 struct i2c_client *client = to_i2c_client(dev);
387 struct sis5595_data *data = i2c_get_clientdata(client);
388 unsigned long min;
389 unsigned long val = simple_strtoul(buf, NULL, 10);
390 int reg;
391
392 down(&data->update_lock);
393 min = FAN_FROM_REG(data->fan_min[nr],
394 DIV_FROM_REG(data->fan_div[nr]));
395 reg = sis5595_read_value(client, SIS5595_REG_FANDIV);
396
397 switch (val) {
398 case 1: data->fan_div[nr] = 0; break;
399 case 2: data->fan_div[nr] = 1; break;
400 case 4: data->fan_div[nr] = 2; break;
401 case 8: data->fan_div[nr] = 3; break;
402 default:
403 dev_err(&client->dev, "fan_div value %ld not "
404 "supported. Choose one of 1, 2, 4 or 8!\n", val);
405 up(&data->update_lock);
406 return -EINVAL;
407 }
408
409 switch (nr) {
410 case 0:
411 reg = (reg & 0xcf) | (data->fan_div[nr] << 4);
412 break;
413 case 1:
414 reg = (reg & 0x3f) | (data->fan_div[nr] << 6);
415 break;
416 }
417 sis5595_write_value(client, SIS5595_REG_FANDIV, reg);
418 data->fan_min[nr] =
419 FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
420 sis5595_write_value(client, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]);
421 up(&data->update_lock);
422 return count;
423}
424
425#define show_fan_offset(offset) \
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400426static ssize_t show_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427{ \
428 return show_fan(dev, buf, offset - 1); \
429} \
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400430static ssize_t show_fan_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431{ \
432 return show_fan_min(dev, buf, offset - 1); \
433} \
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400434static ssize_t show_fan_##offset##_div (struct device *dev, struct device_attribute *attr, char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435{ \
436 return show_fan_div(dev, buf, offset - 1); \
437} \
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400438static ssize_t set_fan_##offset##_min (struct device *dev, struct device_attribute *attr, \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 const char *buf, size_t count) \
440{ \
441 return set_fan_min(dev, buf, count, offset - 1); \
442} \
443static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL);\
444static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
445 show_fan_##offset##_min, set_fan_##offset##_min);
446
447show_fan_offset(1);
448show_fan_offset(2);
449
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400450static ssize_t set_fan_1_div(struct device *dev, struct device_attribute *attr, const char *buf,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 size_t count)
452{
453 return set_fan_div(dev, buf, count, 0) ;
454}
455
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400456static ssize_t set_fan_2_div(struct device *dev, struct device_attribute *attr, const char *buf,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 size_t count)
458{
459 return set_fan_div(dev, buf, count, 1) ;
460}
461static DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR,
462 show_fan_1_div, set_fan_1_div);
463static DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR,
464 show_fan_2_div, set_fan_2_div);
465
466/* Alarms */
Yani Ioannoua5099cf2005-05-17 06:42:25 -0400467static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468{
469 struct sis5595_data *data = sis5595_update_device(dev);
470 return sprintf(buf, "%d\n", data->alarms);
471}
472static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
473
474/* This is called when the module is loaded */
Jean Delvare2d8672c2005-07-19 23:56:35 +0200475static int sis5595_detect(struct i2c_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476{
477 int err = 0;
478 int i;
479 struct i2c_client *new_client;
480 struct sis5595_data *data;
481 char val;
482 u16 a;
483
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 if (force_addr)
485 address = force_addr & ~(SIS5595_EXTENT - 1);
486 /* Reserve the ISA region */
487 if (!request_region(address, SIS5595_EXTENT, sis5595_driver.name)) {
488 err = -EBUSY;
489 goto exit;
490 }
491 if (force_addr) {
492 dev_warn(&adapter->dev, "forcing ISA address 0x%04X\n", address);
493 if (PCIBIOS_SUCCESSFUL !=
494 pci_write_config_word(s_bridge, SIS5595_BASE_REG, address))
495 goto exit_release;
496 if (PCIBIOS_SUCCESSFUL !=
497 pci_read_config_word(s_bridge, SIS5595_BASE_REG, &a))
498 goto exit_release;
499 if ((a & ~(SIS5595_EXTENT - 1)) != address)
500 /* doesn't work for some chips? */
501 goto exit_release;
502 }
503
504 if (PCIBIOS_SUCCESSFUL !=
505 pci_read_config_byte(s_bridge, SIS5595_ENABLE_REG, &val)) {
506 goto exit_release;
507 }
508 if ((val & 0x80) == 0) {
509 if (PCIBIOS_SUCCESSFUL !=
510 pci_write_config_byte(s_bridge, SIS5595_ENABLE_REG,
511 val | 0x80))
512 goto exit_release;
513 if (PCIBIOS_SUCCESSFUL !=
514 pci_read_config_byte(s_bridge, SIS5595_ENABLE_REG, &val))
515 goto exit_release;
516 if ((val & 0x80) == 0)
517 /* doesn't work for some chips! */
518 goto exit_release;
519 }
520
521 if (!(data = kmalloc(sizeof(struct sis5595_data), GFP_KERNEL))) {
522 err = -ENOMEM;
523 goto exit_release;
524 }
525 memset(data, 0, sizeof(struct sis5595_data));
526
527 new_client = &data->client;
528 new_client->addr = address;
529 init_MUTEX(&data->lock);
530 i2c_set_clientdata(new_client, data);
531 new_client->adapter = adapter;
532 new_client->driver = &sis5595_driver;
533 new_client->flags = 0;
534
535 /* Check revision and pin registers to determine whether 4 or 5 voltages */
536 pci_read_config_byte(s_bridge, SIS5595_REVISION_REG, &(data->revision));
537 /* 4 voltages, 1 temp */
538 data->maxins = 3;
539 if (data->revision >= REV2MIN) {
540 pci_read_config_byte(s_bridge, SIS5595_PIN_REG, &val);
541 if (!(val & 0x80))
542 /* 5 voltages, no temps */
543 data->maxins = 4;
544 }
545
546 /* Fill in the remaining client fields and put it into the global list */
547 strlcpy(new_client->name, "sis5595", I2C_NAME_SIZE);
548
549 data->valid = 0;
550 init_MUTEX(&data->update_lock);
551
552 /* Tell the I2C layer a new client has arrived */
553 if ((err = i2c_attach_client(new_client)))
554 goto exit_free;
555
556 /* Initialize the SIS5595 chip */
557 sis5595_init_client(new_client);
558
559 /* A few vars need to be filled upon startup */
560 for (i = 0; i < 2; i++) {
561 data->fan_min[i] = sis5595_read_value(new_client,
562 SIS5595_REG_FAN_MIN(i));
563 }
564
565 /* Register sysfs hooks */
Mark M. Hoffman943b0832005-07-15 21:39:18 -0400566 data->class_dev = hwmon_device_register(&new_client->dev);
567 if (IS_ERR(data->class_dev)) {
568 err = PTR_ERR(data->class_dev);
569 goto exit_detach;
570 }
571
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572 device_create_file(&new_client->dev, &dev_attr_in0_input);
573 device_create_file(&new_client->dev, &dev_attr_in0_min);
574 device_create_file(&new_client->dev, &dev_attr_in0_max);
575 device_create_file(&new_client->dev, &dev_attr_in1_input);
576 device_create_file(&new_client->dev, &dev_attr_in1_min);
577 device_create_file(&new_client->dev, &dev_attr_in1_max);
578 device_create_file(&new_client->dev, &dev_attr_in2_input);
579 device_create_file(&new_client->dev, &dev_attr_in2_min);
580 device_create_file(&new_client->dev, &dev_attr_in2_max);
581 device_create_file(&new_client->dev, &dev_attr_in3_input);
582 device_create_file(&new_client->dev, &dev_attr_in3_min);
583 device_create_file(&new_client->dev, &dev_attr_in3_max);
584 if (data->maxins == 4) {
585 device_create_file(&new_client->dev, &dev_attr_in4_input);
586 device_create_file(&new_client->dev, &dev_attr_in4_min);
587 device_create_file(&new_client->dev, &dev_attr_in4_max);
588 }
589 device_create_file(&new_client->dev, &dev_attr_fan1_input);
590 device_create_file(&new_client->dev, &dev_attr_fan1_min);
591 device_create_file(&new_client->dev, &dev_attr_fan1_div);
592 device_create_file(&new_client->dev, &dev_attr_fan2_input);
593 device_create_file(&new_client->dev, &dev_attr_fan2_min);
594 device_create_file(&new_client->dev, &dev_attr_fan2_div);
595 device_create_file(&new_client->dev, &dev_attr_alarms);
596 if (data->maxins == 3) {
597 device_create_file(&new_client->dev, &dev_attr_temp1_input);
598 device_create_file(&new_client->dev, &dev_attr_temp1_max);
599 device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
600 }
601 return 0;
Mark M. Hoffman943b0832005-07-15 21:39:18 -0400602
603exit_detach:
604 i2c_detach_client(new_client);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605exit_free:
606 kfree(data);
607exit_release:
608 release_region(address, SIS5595_EXTENT);
609exit:
610 return err;
611}
612
613static int sis5595_detach_client(struct i2c_client *client)
614{
Mark M. Hoffman943b0832005-07-15 21:39:18 -0400615 struct sis5595_data *data = i2c_get_clientdata(client);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 int err;
617
Mark M. Hoffman943b0832005-07-15 21:39:18 -0400618 hwmon_device_unregister(data->class_dev);
619
Jean Delvare7bef5592005-07-27 22:14:49 +0200620 if ((err = i2c_detach_client(client)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622
Jean Delvare2d8672c2005-07-19 23:56:35 +0200623 release_region(client->addr, SIS5595_EXTENT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624
Mark M. Hoffman943b0832005-07-15 21:39:18 -0400625 kfree(data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626
627 return 0;
628}
629
630
631/* ISA access must be locked explicitly. */
632static int sis5595_read_value(struct i2c_client *client, u8 reg)
633{
634 int res;
635
636 struct sis5595_data *data = i2c_get_clientdata(client);
637 down(&data->lock);
638 outb_p(reg, client->addr + SIS5595_ADDR_REG_OFFSET);
639 res = inb_p(client->addr + SIS5595_DATA_REG_OFFSET);
640 up(&data->lock);
641 return res;
642}
643
644static int sis5595_write_value(struct i2c_client *client, u8 reg, u8 value)
645{
646 struct sis5595_data *data = i2c_get_clientdata(client);
647 down(&data->lock);
648 outb_p(reg, client->addr + SIS5595_ADDR_REG_OFFSET);
649 outb_p(value, client->addr + SIS5595_DATA_REG_OFFSET);
650 up(&data->lock);
651 return 0;
652}
653
654/* Called when we have found a new SIS5595. */
655static void sis5595_init_client(struct i2c_client *client)
656{
657 u8 config = sis5595_read_value(client, SIS5595_REG_CONFIG);
658 if (!(config & 0x01))
659 sis5595_write_value(client, SIS5595_REG_CONFIG,
660 (config & 0xf7) | 0x01);
661}
662
663static struct sis5595_data *sis5595_update_device(struct device *dev)
664{
665 struct i2c_client *client = to_i2c_client(dev);
666 struct sis5595_data *data = i2c_get_clientdata(client);
667 int i;
668
669 down(&data->update_lock);
670
671 if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
672 || !data->valid) {
673
674 for (i = 0; i <= data->maxins; i++) {
675 data->in[i] =
676 sis5595_read_value(client, SIS5595_REG_IN(i));
677 data->in_min[i] =
678 sis5595_read_value(client,
679 SIS5595_REG_IN_MIN(i));
680 data->in_max[i] =
681 sis5595_read_value(client,
682 SIS5595_REG_IN_MAX(i));
683 }
684 for (i = 0; i < 2; i++) {
685 data->fan[i] =
686 sis5595_read_value(client, SIS5595_REG_FAN(i));
687 data->fan_min[i] =
688 sis5595_read_value(client,
689 SIS5595_REG_FAN_MIN(i));
690 }
691 if (data->maxins == 3) {
692 data->temp =
693 sis5595_read_value(client, SIS5595_REG_TEMP);
694 data->temp_over =
695 sis5595_read_value(client, SIS5595_REG_TEMP_OVER);
696 data->temp_hyst =
697 sis5595_read_value(client, SIS5595_REG_TEMP_HYST);
698 }
699 i = sis5595_read_value(client, SIS5595_REG_FANDIV);
700 data->fan_div[0] = (i >> 4) & 0x03;
701 data->fan_div[1] = i >> 6;
702 data->alarms =
703 sis5595_read_value(client, SIS5595_REG_ALARM1) |
704 (sis5595_read_value(client, SIS5595_REG_ALARM2) << 8);
705 data->last_updated = jiffies;
706 data->valid = 1;
707 }
708
709 up(&data->update_lock);
710
711 return data;
712}
713
714static struct pci_device_id sis5595_pci_ids[] = {
715 { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) },
716 { 0, }
717};
718
719MODULE_DEVICE_TABLE(pci, sis5595_pci_ids);
720
721static int blacklist[] __devinitdata = {
722 PCI_DEVICE_ID_SI_540,
723 PCI_DEVICE_ID_SI_550,
724 PCI_DEVICE_ID_SI_630,
725 PCI_DEVICE_ID_SI_645,
726 PCI_DEVICE_ID_SI_730,
727 PCI_DEVICE_ID_SI_735,
728 PCI_DEVICE_ID_SI_5511, /* 5513 chip has the 0008 device but
729 that ID shows up in other chips so we
730 use the 5511 ID for recognition */
731 PCI_DEVICE_ID_SI_5597,
732 PCI_DEVICE_ID_SI_5598,
733 0 };
734
735static int __devinit sis5595_pci_probe(struct pci_dev *dev,
736 const struct pci_device_id *id)
737{
738 u16 val;
739 int *i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740
741 for (i = blacklist; *i != 0; i++) {
742 struct pci_dev *dev;
743 dev = pci_get_device(PCI_VENDOR_ID_SI, *i, NULL);
744 if (dev) {
745 dev_err(&dev->dev, "Looked for SIS5595 but found unsupported device %.4x\n", *i);
746 pci_dev_put(dev);
747 return -ENODEV;
748 }
749 }
750
751 if (PCIBIOS_SUCCESSFUL !=
752 pci_read_config_word(dev, SIS5595_BASE_REG, &val))
753 return -ENODEV;
754
Jean Delvare2d8672c2005-07-19 23:56:35 +0200755 address = val & ~(SIS5595_EXTENT - 1);
756 if (address == 0 && force_addr == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 dev_err(&dev->dev, "Base address not set - upgrade BIOS or use force_addr=0xaddr\n");
758 return -ENODEV;
759 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 s_bridge = pci_dev_get(dev);
Jean Delvarefde09502005-07-19 23:51:07 +0200762 if (i2c_isa_add_driver(&sis5595_driver)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 pci_dev_put(s_bridge);
764 s_bridge = NULL;
765 }
766
767 /* Always return failure here. This is to allow other drivers to bind
768 * to this pci device. We don't really want to have control over the
769 * pci device, we only wanted to read as few register values from it.
770 */
771 return -ENODEV;
772}
773
774static struct pci_driver sis5595_pci_driver = {
775 .name = "sis5595",
776 .id_table = sis5595_pci_ids,
777 .probe = sis5595_pci_probe,
778};
779
780static int __init sm_sis5595_init(void)
781{
782 return pci_register_driver(&sis5595_pci_driver);
783}
784
785static void __exit sm_sis5595_exit(void)
786{
787 pci_unregister_driver(&sis5595_pci_driver);
788 if (s_bridge != NULL) {
Jean Delvarefde09502005-07-19 23:51:07 +0200789 i2c_isa_del_driver(&sis5595_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 pci_dev_put(s_bridge);
791 s_bridge = NULL;
792 }
793}
794
795MODULE_AUTHOR("Aurelien Jarno <aurelien@aurel32.net>");
796MODULE_DESCRIPTION("SiS 5595 Sensor device");
797MODULE_LICENSE("GPL");
798
799module_init(sm_sis5595_init);
800module_exit(sm_sis5595_exit);