blob: a47da3ec5472e61eaab91f5c837df97f708502e0 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 w83781d.c - Part of lm_sensors, Linux kernel modules for hardware
3 monitoring
4 Copyright (c) 1998 - 2001 Frodo Looijaard <frodol@dds.nl>,
5 Philip Edelbrock <phil@netroedge.com>,
6 and Mark Studebaker <mdsxyz123@yahoo.com>
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21*/
22
23/*
24 Supports following chips:
25
26 Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
27 as99127f 7 3 0 3 0x31 0x12c3 yes no
28 as99127f rev.2 (type_name = as99127f) 0x31 0x5ca3 yes no
29 w83781d 7 3 0 3 0x10-1 0x5ca3 yes yes
30 w83627hf 9 3 2 3 0x21 0x5ca3 yes yes(LPC)
Linus Torvalds1da177e2005-04-16 15:20:36 -070031 w83782d 9 3 2-4 3 0x30 0x5ca3 yes yes
32 w83783s 5-6 3 2 1-2 0x40 0x5ca3 yes no
Linus Torvalds1da177e2005-04-16 15:20:36 -070033
34*/
35
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include <linux/module.h>
37#include <linux/init.h>
38#include <linux/slab.h>
39#include <linux/jiffies.h>
40#include <linux/i2c.h>
Jean Delvarefde09502005-07-19 23:51:07 +020041#include <linux/i2c-isa.h>
Mark M. Hoffman943b0832005-07-15 21:39:18 -040042#include <linux/hwmon.h>
Jean Delvare303760b2005-07-31 21:52:01 +020043#include <linux/hwmon-vid.h>
Jim Cromie311ce2e2006-09-24 21:22:52 +020044#include <linux/sysfs.h>
Mark M. Hoffman943b0832005-07-15 21:39:18 -040045#include <linux/err.h>
Ingo Molnar9a61bf62006-01-18 23:19:26 +010046#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include <asm/io.h>
48#include "lm75.h"
49
50/* Addresses to scan */
51static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
52 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
53 0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END };
Jean Delvare2d8672c2005-07-19 23:56:35 +020054static unsigned short isa_address = 0x290;
Linus Torvalds1da177e2005-04-16 15:20:36 -070055
56/* Insmod parameters */
Jean Delvaref4b50262005-07-31 21:49:03 +020057I2C_CLIENT_INSMOD_5(w83781d, w83782d, w83783s, w83627hf, as99127f);
Linus Torvalds1da177e2005-04-16 15:20:36 -070058I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
59 "{bus, clientaddr, subclientaddr1, subclientaddr2}");
60
Jean Delvarefabddcd2006-02-05 23:26:51 +010061static int reset;
62module_param(reset, bool, 0);
63MODULE_PARM_DESC(reset, "Set to one to reset chip on load");
64
Linus Torvalds1da177e2005-04-16 15:20:36 -070065static int init = 1;
66module_param(init, bool, 0);
67MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
68
69/* Constants specified below */
70
71/* Length of ISA address segment */
72#define W83781D_EXTENT 8
73
74/* Where are the ISA address/data registers relative to the base address */
75#define W83781D_ADDR_REG_OFFSET 5
76#define W83781D_DATA_REG_OFFSET 6
77
78/* The W83781D registers */
79/* The W83782D registers for nr=7,8 are in bank 5 */
80#define W83781D_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \
81 (0x554 + (((nr) - 7) * 2)))
82#define W83781D_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \
83 (0x555 + (((nr) - 7) * 2)))
84#define W83781D_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \
85 (0x550 + (nr) - 7))
86
87#define W83781D_REG_FAN_MIN(nr) (0x3a + (nr))
88#define W83781D_REG_FAN(nr) (0x27 + (nr))
89
90#define W83781D_REG_BANK 0x4E
91#define W83781D_REG_TEMP2_CONFIG 0x152
92#define W83781D_REG_TEMP3_CONFIG 0x252
93#define W83781D_REG_TEMP(nr) ((nr == 3) ? (0x0250) : \
94 ((nr == 2) ? (0x0150) : \
95 (0x27)))
96#define W83781D_REG_TEMP_HYST(nr) ((nr == 3) ? (0x253) : \
97 ((nr == 2) ? (0x153) : \
98 (0x3A)))
99#define W83781D_REG_TEMP_OVER(nr) ((nr == 3) ? (0x255) : \
100 ((nr == 2) ? (0x155) : \
101 (0x39)))
102
103#define W83781D_REG_CONFIG 0x40
Jean Delvarec7f5d7e2006-02-05 23:13:48 +0100104
105/* Interrupt status (W83781D, AS99127F) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106#define W83781D_REG_ALARM1 0x41
107#define W83781D_REG_ALARM2 0x42
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108
Jean Delvarec7f5d7e2006-02-05 23:13:48 +0100109/* Real-time status (W83782D, W83783S, W83627HF) */
110#define W83782D_REG_ALARM1 0x459
111#define W83782D_REG_ALARM2 0x45A
112#define W83782D_REG_ALARM3 0x45B
113
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114#define W83781D_REG_BEEP_CONFIG 0x4D
115#define W83781D_REG_BEEP_INTS1 0x56
116#define W83781D_REG_BEEP_INTS2 0x57
117#define W83781D_REG_BEEP_INTS3 0x453 /* not on W83781D */
118
119#define W83781D_REG_VID_FANDIV 0x47
120
121#define W83781D_REG_CHIPID 0x49
122#define W83781D_REG_WCHIPID 0x58
123#define W83781D_REG_CHIPMAN 0x4F
124#define W83781D_REG_PIN 0x4B
125
126/* 782D/783S only */
127#define W83781D_REG_VBAT 0x5D
128
129/* PWM 782D (1-4) and 783S (1-2) only */
130#define W83781D_REG_PWM1 0x5B /* 782d and 783s/627hf datasheets disagree */
131 /* on which is which; */
132#define W83781D_REG_PWM2 0x5A /* We follow the 782d convention here, */
133 /* However 782d is probably wrong. */
134#define W83781D_REG_PWM3 0x5E
135#define W83781D_REG_PWM4 0x5F
136#define W83781D_REG_PWMCLK12 0x5C
137#define W83781D_REG_PWMCLK34 0x45C
138static const u8 regpwm[] = { W83781D_REG_PWM1, W83781D_REG_PWM2,
139 W83781D_REG_PWM3, W83781D_REG_PWM4
140};
141
142#define W83781D_REG_PWM(nr) (regpwm[(nr) - 1])
143
144#define W83781D_REG_I2C_ADDR 0x48
145#define W83781D_REG_I2C_SUBADDR 0x4A
146
147/* The following are undocumented in the data sheets however we
148 received the information in an email from Winbond tech support */
149/* Sensor selection - not on 781d */
150#define W83781D_REG_SCFG1 0x5D
151static const u8 BIT_SCFG1[] = { 0x02, 0x04, 0x08 };
152
153#define W83781D_REG_SCFG2 0x59
154static const u8 BIT_SCFG2[] = { 0x10, 0x20, 0x40 };
155
156#define W83781D_DEFAULT_BETA 3435
157
158/* RT Table registers */
159#define W83781D_REG_RT_IDX 0x50
160#define W83781D_REG_RT_VAL 0x51
161
162/* Conversions. Rounding and limit checking is only done on the TO_REG
163 variants. Note that you should be a bit careful with which arguments
164 these macros are called: arguments may be evaluated more than once.
165 Fixing this is just not worth it. */
166#define IN_TO_REG(val) (SENSORS_LIMIT((((val) * 10 + 8)/16),0,255))
167#define IN_FROM_REG(val) (((val) * 16) / 10)
168
169static inline u8
170FAN_TO_REG(long rpm, int div)
171{
172 if (rpm == 0)
173 return 255;
174 rpm = SENSORS_LIMIT(rpm, 1, 1000000);
175 return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
176}
177
178#define FAN_FROM_REG(val,div) ((val) == 0 ? -1 : \
179 ((val) == 255 ? 0 : \
180 1350000 / ((val) * (div))))
181
182#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val) < 0 ? (val)+0x100*1000 \
183 : (val)) / 1000, 0, 0xff))
184#define TEMP_FROM_REG(val) (((val) & 0x80 ? (val)-0x100 : (val)) * 1000)
185
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186#define PWM_FROM_REG(val) (val)
187#define PWM_TO_REG(val) (SENSORS_LIMIT((val),0,255))
188#define BEEP_MASK_FROM_REG(val,type) ((type) == as99127f ? \
189 (val) ^ 0x7fff : (val))
190#define BEEP_MASK_TO_REG(val,type) ((type) == as99127f ? \
191 (~(val)) & 0x7fff : (val) & 0xffffff)
192
193#define BEEP_ENABLE_TO_REG(val) ((val) ? 1 : 0)
194#define BEEP_ENABLE_FROM_REG(val) ((val) ? 1 : 0)
195
196#define DIV_FROM_REG(val) (1 << (val))
197
198static inline u8
199DIV_TO_REG(long val, enum chips type)
200{
201 int i;
202 val = SENSORS_LIMIT(val, 1,
203 ((type == w83781d
204 || type == as99127f) ? 8 : 128)) >> 1;
Grant Coadyabc01922005-05-12 13:41:51 +1000205 for (i = 0; i < 7; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206 if (val == 0)
207 break;
208 val >>= 1;
209 }
210 return ((u8) i);
211}
212
213/* There are some complications in a module like this. First off, W83781D chips
214 may be both present on the SMBus and the ISA bus, and we have to handle
215 those cases separately at some places. Second, there might be several
216 W83781D chips available (well, actually, that is probably never done; but
217 it is a clean illustration of how to handle a case like that). Finally,
218 a specific chip may be attached to *both* ISA and SMBus, and we would
219 not like to detect it double. Fortunately, in the case of the W83781D at
220 least, a register tells us what SMBus address we are on, so that helps
221 a bit - except if there could be more than one SMBus. Groan. No solution
222 for this yet. */
223
Jean Delvareed6bafb2007-02-14 21:15:03 +0100224/* For each registered chip, we need to keep some data in memory.
225 The structure is dynamically allocated. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226struct w83781d_data {
227 struct i2c_client client;
Mark M. Hoffman943b0832005-07-15 21:39:18 -0400228 struct class_device *class_dev;
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100229 struct mutex lock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230 enum chips type;
231
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100232 struct mutex update_lock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 char valid; /* !=0 if following fields are valid */
234 unsigned long last_updated; /* In jiffies */
235
236 struct i2c_client *lm75[2]; /* for secondary I2C addresses */
237 /* array of 2 pointers to subclients */
238
239 u8 in[9]; /* Register value - 8 & 9 for 782D only */
240 u8 in_max[9]; /* Register value - 8 & 9 for 782D only */
241 u8 in_min[9]; /* Register value - 8 & 9 for 782D only */
242 u8 fan[3]; /* Register value */
243 u8 fan_min[3]; /* Register value */
244 u8 temp;
245 u8 temp_max; /* Register value */
246 u8 temp_max_hyst; /* Register value */
247 u16 temp_add[2]; /* Register value */
248 u16 temp_max_add[2]; /* Register value */
249 u16 temp_max_hyst_add[2]; /* Register value */
250 u8 fan_div[3]; /* Register encoding, shifted right */
251 u8 vid; /* Register encoding, combined */
252 u32 alarms; /* Register encoding, combined */
253 u32 beep_mask; /* Register encoding, combined */
254 u8 beep_enable; /* Boolean */
255 u8 pwm[4]; /* Register value */
256 u8 pwmenable[4]; /* Boolean */
257 u16 sens[3]; /* 782D/783S only.
258 1 = pentium diode; 2 = 3904 diode;
259 3000-5000 = thermistor beta.
260 Default = 3435.
261 Other Betas unimplemented */
262 u8 vrm;
263};
264
265static int w83781d_attach_adapter(struct i2c_adapter *adapter);
Jean Delvare2d8672c2005-07-19 23:56:35 +0200266static int w83781d_isa_attach_adapter(struct i2c_adapter *adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267static int w83781d_detect(struct i2c_adapter *adapter, int address, int kind);
268static int w83781d_detach_client(struct i2c_client *client);
269
Darren Jenkinsf6c27fc2006-02-27 23:14:58 +0100270static int w83781d_read_value(struct i2c_client *client, u16 reg);
271static int w83781d_write_value(struct i2c_client *client, u16 reg, u16 value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272static struct w83781d_data *w83781d_update_device(struct device *dev);
273static void w83781d_init_client(struct i2c_client *client);
274
275static struct i2c_driver w83781d_driver = {
Laurent Riffardcdaf7932005-11-26 20:37:41 +0100276 .driver = {
Laurent Riffardcdaf7932005-11-26 20:37:41 +0100277 .name = "w83781d",
278 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 .id = I2C_DRIVERID_W83781D,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 .attach_adapter = w83781d_attach_adapter,
281 .detach_client = w83781d_detach_client,
282};
283
Jean Delvarefde09502005-07-19 23:51:07 +0200284static struct i2c_driver w83781d_isa_driver = {
Laurent Riffardcdaf7932005-11-26 20:37:41 +0100285 .driver = {
Jean Delvare87218842006-09-03 22:36:14 +0200286 .owner = THIS_MODULE,
Laurent Riffardcdaf7932005-11-26 20:37:41 +0100287 .name = "w83781d-isa",
288 },
Jean Delvare2d8672c2005-07-19 23:56:35 +0200289 .attach_adapter = w83781d_isa_attach_adapter,
Jean Delvarefde09502005-07-19 23:51:07 +0200290 .detach_client = w83781d_detach_client,
291};
292
293
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294/* following are the sysfs callback functions */
295#define show_in_reg(reg) \
296static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
297{ \
298 struct w83781d_data *data = w83781d_update_device(dev); \
299 return sprintf(buf,"%ld\n", (long)IN_FROM_REG(data->reg[nr] * 10)); \
300}
301show_in_reg(in);
302show_in_reg(in_min);
303show_in_reg(in_max);
304
305#define store_in_reg(REG, reg) \
306static ssize_t store_in_##reg (struct device *dev, const char *buf, size_t count, int nr) \
307{ \
308 struct i2c_client *client = to_i2c_client(dev); \
309 struct w83781d_data *data = i2c_get_clientdata(client); \
310 u32 val; \
311 \
312 val = simple_strtoul(buf, NULL, 10) / 10; \
313 \
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100314 mutex_lock(&data->update_lock); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315 data->in_##reg[nr] = IN_TO_REG(val); \
316 w83781d_write_value(client, W83781D_REG_IN_##REG(nr), data->in_##reg[nr]); \
317 \
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100318 mutex_unlock(&data->update_lock); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319 return count; \
320}
321store_in_reg(MIN, min);
322store_in_reg(MAX, max);
323
324#define sysfs_in_offset(offset) \
325static ssize_t \
Yani Ioannoue404e272005-05-17 06:42:58 -0400326show_regs_in_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327{ \
328 return show_in(dev, buf, offset); \
329} \
330static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_regs_in_##offset, NULL);
331
332#define sysfs_in_reg_offset(reg, offset) \
Yani Ioannoue404e272005-05-17 06:42:58 -0400333static ssize_t show_regs_in_##reg##offset (struct device *dev, struct device_attribute *attr, char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334{ \
335 return show_in_##reg (dev, buf, offset); \
336} \
Yani Ioannoue404e272005-05-17 06:42:58 -0400337static ssize_t store_regs_in_##reg##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338{ \
339 return store_in_##reg (dev, buf, count, offset); \
340} \
341static DEVICE_ATTR(in##offset##_##reg, S_IRUGO| S_IWUSR, show_regs_in_##reg##offset, store_regs_in_##reg##offset);
342
343#define sysfs_in_offsets(offset) \
344sysfs_in_offset(offset); \
345sysfs_in_reg_offset(min, offset); \
346sysfs_in_reg_offset(max, offset);
347
348sysfs_in_offsets(0);
349sysfs_in_offsets(1);
350sysfs_in_offsets(2);
351sysfs_in_offsets(3);
352sysfs_in_offsets(4);
353sysfs_in_offsets(5);
354sysfs_in_offsets(6);
355sysfs_in_offsets(7);
356sysfs_in_offsets(8);
357
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358#define show_fan_reg(reg) \
359static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
360{ \
361 struct w83781d_data *data = w83781d_update_device(dev); \
362 return sprintf(buf,"%ld\n", \
363 FAN_FROM_REG(data->reg[nr-1], (long)DIV_FROM_REG(data->fan_div[nr-1]))); \
364}
365show_fan_reg(fan);
366show_fan_reg(fan_min);
367
368static ssize_t
369store_fan_min(struct device *dev, const char *buf, size_t count, int nr)
370{
371 struct i2c_client *client = to_i2c_client(dev);
372 struct w83781d_data *data = i2c_get_clientdata(client);
373 u32 val;
374
375 val = simple_strtoul(buf, NULL, 10);
376
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100377 mutex_lock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 data->fan_min[nr - 1] =
379 FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr - 1]));
380 w83781d_write_value(client, W83781D_REG_FAN_MIN(nr),
381 data->fan_min[nr - 1]);
382
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100383 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 return count;
385}
386
387#define sysfs_fan_offset(offset) \
Yani Ioannoue404e272005-05-17 06:42:58 -0400388static ssize_t show_regs_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389{ \
390 return show_fan(dev, buf, offset); \
391} \
392static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_regs_fan_##offset, NULL);
393
394#define sysfs_fan_min_offset(offset) \
Yani Ioannoue404e272005-05-17 06:42:58 -0400395static ssize_t show_regs_fan_min##offset (struct device *dev, struct device_attribute *attr, char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396{ \
397 return show_fan_min(dev, buf, offset); \
398} \
Yani Ioannoue404e272005-05-17 06:42:58 -0400399static ssize_t store_regs_fan_min##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400{ \
401 return store_fan_min(dev, buf, count, offset); \
402} \
403static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, show_regs_fan_min##offset, store_regs_fan_min##offset);
404
405sysfs_fan_offset(1);
406sysfs_fan_min_offset(1);
407sysfs_fan_offset(2);
408sysfs_fan_min_offset(2);
409sysfs_fan_offset(3);
410sysfs_fan_min_offset(3);
411
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412#define show_temp_reg(reg) \
413static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
414{ \
415 struct w83781d_data *data = w83781d_update_device(dev); \
416 if (nr >= 2) { /* TEMP2 and TEMP3 */ \
417 return sprintf(buf,"%d\n", \
418 LM75_TEMP_FROM_REG(data->reg##_add[nr-2])); \
419 } else { /* TEMP1 */ \
420 return sprintf(buf,"%ld\n", (long)TEMP_FROM_REG(data->reg)); \
421 } \
422}
423show_temp_reg(temp);
424show_temp_reg(temp_max);
425show_temp_reg(temp_max_hyst);
426
427#define store_temp_reg(REG, reg) \
428static ssize_t store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \
429{ \
430 struct i2c_client *client = to_i2c_client(dev); \
431 struct w83781d_data *data = i2c_get_clientdata(client); \
432 s32 val; \
433 \
434 val = simple_strtol(buf, NULL, 10); \
435 \
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100436 mutex_lock(&data->update_lock); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 \
438 if (nr >= 2) { /* TEMP2 and TEMP3 */ \
439 data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \
440 w83781d_write_value(client, W83781D_REG_TEMP_##REG(nr), \
441 data->temp_##reg##_add[nr-2]); \
442 } else { /* TEMP1 */ \
443 data->temp_##reg = TEMP_TO_REG(val); \
444 w83781d_write_value(client, W83781D_REG_TEMP_##REG(nr), \
445 data->temp_##reg); \
446 } \
447 \
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100448 mutex_unlock(&data->update_lock); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 return count; \
450}
451store_temp_reg(OVER, max);
452store_temp_reg(HYST, max_hyst);
453
454#define sysfs_temp_offset(offset) \
455static ssize_t \
Yani Ioannoue404e272005-05-17 06:42:58 -0400456show_regs_temp_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457{ \
458 return show_temp(dev, buf, offset); \
459} \
460static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_regs_temp_##offset, NULL);
461
462#define sysfs_temp_reg_offset(reg, offset) \
Yani Ioannoue404e272005-05-17 06:42:58 -0400463static ssize_t show_regs_temp_##reg##offset (struct device *dev, struct device_attribute *attr, char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464{ \
465 return show_temp_##reg (dev, buf, offset); \
466} \
Yani Ioannoue404e272005-05-17 06:42:58 -0400467static ssize_t store_regs_temp_##reg##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468{ \
469 return store_temp_##reg (dev, buf, count, offset); \
470} \
471static DEVICE_ATTR(temp##offset##_##reg, S_IRUGO| S_IWUSR, show_regs_temp_##reg##offset, store_regs_temp_##reg##offset);
472
473#define sysfs_temp_offsets(offset) \
474sysfs_temp_offset(offset); \
475sysfs_temp_reg_offset(max, offset); \
476sysfs_temp_reg_offset(max_hyst, offset);
477
478sysfs_temp_offsets(1);
479sysfs_temp_offsets(2);
480sysfs_temp_offsets(3);
481
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482static ssize_t
Yani Ioannoue404e272005-05-17 06:42:58 -0400483show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484{
485 struct w83781d_data *data = w83781d_update_device(dev);
486 return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
487}
488
Jim Cromie311ce2e2006-09-24 21:22:52 +0200489static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
490
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491static ssize_t
Yani Ioannoue404e272005-05-17 06:42:58 -0400492show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493{
494 struct w83781d_data *data = w83781d_update_device(dev);
495 return sprintf(buf, "%ld\n", (long) data->vrm);
496}
497
498static ssize_t
Yani Ioannoue404e272005-05-17 06:42:58 -0400499store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500{
501 struct i2c_client *client = to_i2c_client(dev);
502 struct w83781d_data *data = i2c_get_clientdata(client);
503 u32 val;
504
505 val = simple_strtoul(buf, NULL, 10);
506 data->vrm = val;
507
508 return count;
509}
510
Jim Cromie311ce2e2006-09-24 21:22:52 +0200511static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
512
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513static ssize_t
Yani Ioannoue404e272005-05-17 06:42:58 -0400514show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515{
516 struct w83781d_data *data = w83781d_update_device(dev);
Jean Delvare68188ba2005-05-16 18:52:38 +0200517 return sprintf(buf, "%u\n", data->alarms);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518}
519
Jim Cromie311ce2e2006-09-24 21:22:52 +0200520static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
521
Yani Ioannoue404e272005-05-17 06:42:58 -0400522static ssize_t show_beep_mask (struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523{
524 struct w83781d_data *data = w83781d_update_device(dev);
525 return sprintf(buf, "%ld\n",
526 (long)BEEP_MASK_FROM_REG(data->beep_mask, data->type));
527}
Yani Ioannoue404e272005-05-17 06:42:58 -0400528static ssize_t show_beep_enable (struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529{
530 struct w83781d_data *data = w83781d_update_device(dev);
531 return sprintf(buf, "%ld\n",
532 (long)BEEP_ENABLE_FROM_REG(data->beep_enable));
533}
534
535#define BEEP_ENABLE 0 /* Store beep_enable */
536#define BEEP_MASK 1 /* Store beep_mask */
537
538static ssize_t
539store_beep_reg(struct device *dev, const char *buf, size_t count,
540 int update_mask)
541{
542 struct i2c_client *client = to_i2c_client(dev);
543 struct w83781d_data *data = i2c_get_clientdata(client);
544 u32 val, val2;
545
546 val = simple_strtoul(buf, NULL, 10);
547
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100548 mutex_lock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549
550 if (update_mask == BEEP_MASK) { /* We are storing beep_mask */
551 data->beep_mask = BEEP_MASK_TO_REG(val, data->type);
552 w83781d_write_value(client, W83781D_REG_BEEP_INTS1,
553 data->beep_mask & 0xff);
554
555 if ((data->type != w83781d) && (data->type != as99127f)) {
556 w83781d_write_value(client, W83781D_REG_BEEP_INTS3,
557 ((data->beep_mask) >> 16) & 0xff);
558 }
559
560 val2 = (data->beep_mask >> 8) & 0x7f;
561 } else { /* We are storing beep_enable */
562 val2 = w83781d_read_value(client, W83781D_REG_BEEP_INTS2) & 0x7f;
563 data->beep_enable = BEEP_ENABLE_TO_REG(val);
564 }
565
566 w83781d_write_value(client, W83781D_REG_BEEP_INTS2,
567 val2 | data->beep_enable << 7);
568
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100569 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 return count;
571}
572
573#define sysfs_beep(REG, reg) \
Yani Ioannoue404e272005-05-17 06:42:58 -0400574static ssize_t show_regs_beep_##reg (struct device *dev, struct device_attribute *attr, char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575{ \
Yani Ioannoue404e272005-05-17 06:42:58 -0400576 return show_beep_##reg(dev, attr, buf); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577} \
Yani Ioannoue404e272005-05-17 06:42:58 -0400578static ssize_t store_regs_beep_##reg (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579{ \
580 return store_beep_reg(dev, buf, count, BEEP_##REG); \
581} \
582static DEVICE_ATTR(beep_##reg, S_IRUGO | S_IWUSR, show_regs_beep_##reg, store_regs_beep_##reg);
583
584sysfs_beep(ENABLE, enable);
585sysfs_beep(MASK, mask);
586
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587static ssize_t
588show_fan_div_reg(struct device *dev, char *buf, int nr)
589{
590 struct w83781d_data *data = w83781d_update_device(dev);
591 return sprintf(buf, "%ld\n",
592 (long) DIV_FROM_REG(data->fan_div[nr - 1]));
593}
594
595/* Note: we save and restore the fan minimum here, because its value is
596 determined in part by the fan divisor. This follows the principle of
Andreas Mohrd6e05ed2006-06-26 18:35:02 +0200597 least surprise; the user doesn't expect the fan minimum to change just
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598 because the divisor changed. */
599static ssize_t
600store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr)
601{
602 struct i2c_client *client = to_i2c_client(dev);
603 struct w83781d_data *data = i2c_get_clientdata(client);
604 unsigned long min;
605 u8 reg;
606 unsigned long val = simple_strtoul(buf, NULL, 10);
607
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100608 mutex_lock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609
610 /* Save fan_min */
611 min = FAN_FROM_REG(data->fan_min[nr],
612 DIV_FROM_REG(data->fan_div[nr]));
613
614 data->fan_div[nr] = DIV_TO_REG(val, data->type);
615
616 reg = (w83781d_read_value(client, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV)
617 & (nr==0 ? 0xcf : 0x3f))
618 | ((data->fan_div[nr] & 0x03) << (nr==0 ? 4 : 6));
619 w83781d_write_value(client, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg);
620
621 /* w83781d and as99127f don't have extended divisor bits */
622 if (data->type != w83781d && data->type != as99127f) {
623 reg = (w83781d_read_value(client, W83781D_REG_VBAT)
624 & ~(1 << (5 + nr)))
625 | ((data->fan_div[nr] & 0x04) << (3 + nr));
626 w83781d_write_value(client, W83781D_REG_VBAT, reg);
627 }
628
629 /* Restore fan_min */
630 data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
631 w83781d_write_value(client, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]);
632
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100633 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 return count;
635}
636
637#define sysfs_fan_div(offset) \
Yani Ioannoue404e272005-05-17 06:42:58 -0400638static ssize_t show_regs_fan_div_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639{ \
640 return show_fan_div_reg(dev, buf, offset); \
641} \
Yani Ioannoue404e272005-05-17 06:42:58 -0400642static ssize_t store_regs_fan_div_##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643{ \
644 return store_fan_div_reg(dev, buf, count, offset - 1); \
645} \
646static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, show_regs_fan_div_##offset, store_regs_fan_div_##offset);
647
648sysfs_fan_div(1);
649sysfs_fan_div(2);
650sysfs_fan_div(3);
651
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652static ssize_t
653show_pwm_reg(struct device *dev, char *buf, int nr)
654{
655 struct w83781d_data *data = w83781d_update_device(dev);
656 return sprintf(buf, "%ld\n", (long) PWM_FROM_REG(data->pwm[nr - 1]));
657}
658
659static ssize_t
660show_pwmenable_reg(struct device *dev, char *buf, int nr)
661{
662 struct w83781d_data *data = w83781d_update_device(dev);
663 return sprintf(buf, "%ld\n", (long) data->pwmenable[nr - 1]);
664}
665
666static ssize_t
667store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr)
668{
669 struct i2c_client *client = to_i2c_client(dev);
670 struct w83781d_data *data = i2c_get_clientdata(client);
671 u32 val;
672
673 val = simple_strtoul(buf, NULL, 10);
674
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100675 mutex_lock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 data->pwm[nr - 1] = PWM_TO_REG(val);
677 w83781d_write_value(client, W83781D_REG_PWM(nr), data->pwm[nr - 1]);
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100678 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679 return count;
680}
681
682static ssize_t
683store_pwmenable_reg(struct device *dev, const char *buf, size_t count, int nr)
684{
685 struct i2c_client *client = to_i2c_client(dev);
686 struct w83781d_data *data = i2c_get_clientdata(client);
687 u32 val, reg;
688
689 val = simple_strtoul(buf, NULL, 10);
690
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100691 mutex_lock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692
693 switch (val) {
694 case 0:
695 case 1:
696 reg = w83781d_read_value(client, W83781D_REG_PWMCLK12);
697 w83781d_write_value(client, W83781D_REG_PWMCLK12,
698 (reg & 0xf7) | (val << 3));
699
700 reg = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG);
701 w83781d_write_value(client, W83781D_REG_BEEP_CONFIG,
702 (reg & 0xef) | (!val << 4));
703
704 data->pwmenable[nr - 1] = val;
705 break;
706
707 default:
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100708 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709 return -EINVAL;
710 }
711
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100712 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713 return count;
714}
715
716#define sysfs_pwm(offset) \
Yani Ioannoue404e272005-05-17 06:42:58 -0400717static ssize_t show_regs_pwm_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718{ \
719 return show_pwm_reg(dev, buf, offset); \
720} \
Yani Ioannoue404e272005-05-17 06:42:58 -0400721static ssize_t store_regs_pwm_##offset (struct device *dev, struct device_attribute *attr, \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 const char *buf, size_t count) \
723{ \
724 return store_pwm_reg(dev, buf, count, offset); \
725} \
726static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \
727 show_regs_pwm_##offset, store_regs_pwm_##offset);
728
729#define sysfs_pwmenable(offset) \
Yani Ioannoue404e272005-05-17 06:42:58 -0400730static ssize_t show_regs_pwmenable_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731{ \
732 return show_pwmenable_reg(dev, buf, offset); \
733} \
Yani Ioannoue404e272005-05-17 06:42:58 -0400734static ssize_t store_regs_pwmenable_##offset (struct device *dev, struct device_attribute *attr, \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 const char *buf, size_t count) \
736{ \
737 return store_pwmenable_reg(dev, buf, count, offset); \
738} \
739static DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \
740 show_regs_pwmenable_##offset, store_regs_pwmenable_##offset);
741
742sysfs_pwm(1);
743sysfs_pwm(2);
744sysfs_pwmenable(2); /* only PWM2 can be enabled/disabled */
745sysfs_pwm(3);
746sysfs_pwm(4);
747
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748static ssize_t
749show_sensor_reg(struct device *dev, char *buf, int nr)
750{
751 struct w83781d_data *data = w83781d_update_device(dev);
752 return sprintf(buf, "%ld\n", (long) data->sens[nr - 1]);
753}
754
755static ssize_t
756store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr)
757{
758 struct i2c_client *client = to_i2c_client(dev);
759 struct w83781d_data *data = i2c_get_clientdata(client);
760 u32 val, tmp;
761
762 val = simple_strtoul(buf, NULL, 10);
763
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100764 mutex_lock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765
766 switch (val) {
767 case 1: /* PII/Celeron diode */
768 tmp = w83781d_read_value(client, W83781D_REG_SCFG1);
769 w83781d_write_value(client, W83781D_REG_SCFG1,
770 tmp | BIT_SCFG1[nr - 1]);
771 tmp = w83781d_read_value(client, W83781D_REG_SCFG2);
772 w83781d_write_value(client, W83781D_REG_SCFG2,
773 tmp | BIT_SCFG2[nr - 1]);
774 data->sens[nr - 1] = val;
775 break;
776 case 2: /* 3904 */
777 tmp = w83781d_read_value(client, W83781D_REG_SCFG1);
778 w83781d_write_value(client, W83781D_REG_SCFG1,
779 tmp | BIT_SCFG1[nr - 1]);
780 tmp = w83781d_read_value(client, W83781D_REG_SCFG2);
781 w83781d_write_value(client, W83781D_REG_SCFG2,
782 tmp & ~BIT_SCFG2[nr - 1]);
783 data->sens[nr - 1] = val;
784 break;
785 case W83781D_DEFAULT_BETA: /* thermistor */
786 tmp = w83781d_read_value(client, W83781D_REG_SCFG1);
787 w83781d_write_value(client, W83781D_REG_SCFG1,
788 tmp & ~BIT_SCFG1[nr - 1]);
789 data->sens[nr - 1] = val;
790 break;
791 default:
792 dev_err(dev, "Invalid sensor type %ld; must be 1, 2, or %d\n",
793 (long) val, W83781D_DEFAULT_BETA);
794 break;
795 }
796
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100797 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 return count;
799}
800
801#define sysfs_sensor(offset) \
Yani Ioannoue404e272005-05-17 06:42:58 -0400802static ssize_t show_regs_sensor_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803{ \
804 return show_sensor_reg(dev, buf, offset); \
805} \
Yani Ioannoue404e272005-05-17 06:42:58 -0400806static ssize_t store_regs_sensor_##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807{ \
808 return store_sensor_reg(dev, buf, count, offset); \
809} \
810static DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, show_regs_sensor_##offset, store_regs_sensor_##offset);
811
812sysfs_sensor(1);
813sysfs_sensor(2);
814sysfs_sensor(3);
815
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816/* This function is called when:
817 * w83781d_driver is inserted (when this module is loaded), for each
818 available adapter
819 * when a new adapter is inserted (and w83781d_driver is still present) */
820static int
821w83781d_attach_adapter(struct i2c_adapter *adapter)
822{
823 if (!(adapter->class & I2C_CLASS_HWMON))
824 return 0;
Jean Delvare2ed2dc32005-07-31 21:42:02 +0200825 return i2c_probe(adapter, &addr_data, w83781d_detect);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826}
827
Jean Delvare2d8672c2005-07-19 23:56:35 +0200828static int
829w83781d_isa_attach_adapter(struct i2c_adapter *adapter)
830{
831 return w83781d_detect(adapter, isa_address, -1);
832}
833
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834/* Assumes that adapter is of I2C, not ISA variety.
835 * OTHERWISE DON'T CALL THIS
836 */
837static int
838w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
839 struct i2c_client *new_client)
840{
841 int i, val1 = 0, id;
842 int err;
843 const char *client_name = "";
844 struct w83781d_data *data = i2c_get_clientdata(new_client);
845
Deepak Saxenaba9c2e82005-10-17 23:08:32 +0200846 data->lm75[0] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 if (!(data->lm75[0])) {
848 err = -ENOMEM;
849 goto ERROR_SC_0;
850 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851
852 id = i2c_adapter_id(adapter);
853
854 if (force_subclients[0] == id && force_subclients[1] == address) {
855 for (i = 2; i <= 3; i++) {
856 if (force_subclients[i] < 0x48 ||
857 force_subclients[i] > 0x4f) {
858 dev_err(&new_client->dev, "Invalid subclient "
859 "address %d; must be 0x48-0x4f\n",
860 force_subclients[i]);
861 err = -EINVAL;
862 goto ERROR_SC_1;
863 }
864 }
865 w83781d_write_value(new_client, W83781D_REG_I2C_SUBADDR,
866 (force_subclients[2] & 0x07) |
867 ((force_subclients[3] & 0x07) << 4));
868 data->lm75[0]->addr = force_subclients[2];
869 } else {
870 val1 = w83781d_read_value(new_client, W83781D_REG_I2C_SUBADDR);
871 data->lm75[0]->addr = 0x48 + (val1 & 0x07);
872 }
873
874 if (kind != w83783s) {
Deepak Saxenaba9c2e82005-10-17 23:08:32 +0200875 data->lm75[1] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 if (!(data->lm75[1])) {
877 err = -ENOMEM;
878 goto ERROR_SC_1;
879 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880
881 if (force_subclients[0] == id &&
882 force_subclients[1] == address) {
883 data->lm75[1]->addr = force_subclients[3];
884 } else {
885 data->lm75[1]->addr = 0x48 + ((val1 >> 4) & 0x07);
886 }
887 if (data->lm75[0]->addr == data->lm75[1]->addr) {
888 dev_err(&new_client->dev,
889 "Duplicate addresses 0x%x for subclients.\n",
890 data->lm75[0]->addr);
891 err = -EBUSY;
892 goto ERROR_SC_2;
893 }
894 }
895
896 if (kind == w83781d)
897 client_name = "w83781d subclient";
898 else if (kind == w83782d)
899 client_name = "w83782d subclient";
900 else if (kind == w83783s)
901 client_name = "w83783s subclient";
902 else if (kind == w83627hf)
903 client_name = "w83627hf subclient";
904 else if (kind == as99127f)
905 client_name = "as99127f subclient";
906
907 for (i = 0; i <= 1; i++) {
908 /* store all data in w83781d */
909 i2c_set_clientdata(data->lm75[i], NULL);
910 data->lm75[i]->adapter = adapter;
911 data->lm75[i]->driver = &w83781d_driver;
912 data->lm75[i]->flags = 0;
913 strlcpy(data->lm75[i]->name, client_name,
914 I2C_NAME_SIZE);
915 if ((err = i2c_attach_client(data->lm75[i]))) {
916 dev_err(&new_client->dev, "Subclient %d "
917 "registration at address 0x%x "
918 "failed.\n", i, data->lm75[i]->addr);
919 if (i == 1)
920 goto ERROR_SC_3;
921 goto ERROR_SC_2;
922 }
923 if (kind == w83783s)
924 break;
925 }
926
927 return 0;
928
929/* Undo inits in case of errors */
930ERROR_SC_3:
931 i2c_detach_client(data->lm75[0]);
932ERROR_SC_2:
Jesper Juhl6044ec82005-11-07 01:01:32 -0800933 kfree(data->lm75[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934ERROR_SC_1:
Jesper Juhl6044ec82005-11-07 01:01:32 -0800935 kfree(data->lm75[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936ERROR_SC_0:
937 return err;
938}
939
Jim Cromie311ce2e2006-09-24 21:22:52 +0200940#define IN_UNIT_ATTRS(X) \
941 &dev_attr_in##X##_input.attr, \
942 &dev_attr_in##X##_min.attr, \
943 &dev_attr_in##X##_max.attr
944
945#define FAN_UNIT_ATTRS(X) \
946 &dev_attr_fan##X##_input.attr, \
947 &dev_attr_fan##X##_min.attr, \
948 &dev_attr_fan##X##_div.attr
949
950#define TEMP_UNIT_ATTRS(X) \
951 &dev_attr_temp##X##_input.attr, \
952 &dev_attr_temp##X##_max.attr, \
953 &dev_attr_temp##X##_max_hyst.attr
954
955static struct attribute* w83781d_attributes[] = {
956 IN_UNIT_ATTRS(0),
957 IN_UNIT_ATTRS(2),
958 IN_UNIT_ATTRS(3),
959 IN_UNIT_ATTRS(4),
960 IN_UNIT_ATTRS(5),
961 IN_UNIT_ATTRS(6),
962 FAN_UNIT_ATTRS(1),
963 FAN_UNIT_ATTRS(2),
964 FAN_UNIT_ATTRS(3),
965 TEMP_UNIT_ATTRS(1),
966 TEMP_UNIT_ATTRS(2),
967 &dev_attr_cpu0_vid.attr,
968 &dev_attr_vrm.attr,
969 &dev_attr_alarms.attr,
970 &dev_attr_beep_mask.attr,
971 &dev_attr_beep_enable.attr,
972 NULL
973};
974static const struct attribute_group w83781d_group = {
975 .attrs = w83781d_attributes,
976};
977
978static struct attribute *w83781d_attributes_opt[] = {
979 IN_UNIT_ATTRS(1),
980 IN_UNIT_ATTRS(7),
981 IN_UNIT_ATTRS(8),
982 TEMP_UNIT_ATTRS(3),
983 &dev_attr_pwm1.attr,
984 &dev_attr_pwm2.attr,
985 &dev_attr_pwm2_enable.attr,
986 &dev_attr_pwm3.attr,
987 &dev_attr_pwm4.attr,
988 &dev_attr_temp1_type.attr,
989 &dev_attr_temp2_type.attr,
990 &dev_attr_temp3_type.attr,
991 NULL
992};
993static const struct attribute_group w83781d_group_opt = {
994 .attrs = w83781d_attributes_opt,
995};
996
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997static int
998w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
999{
1000 int i = 0, val1 = 0, val2;
Jim Cromie311ce2e2006-09-24 21:22:52 +02001001 struct i2c_client *client;
1002 struct device *dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 struct w83781d_data *data;
1004 int err;
1005 const char *client_name = "";
1006 int is_isa = i2c_is_isa_adapter(adapter);
1007 enum vendor { winbond, asus } vendid;
1008
1009 if (!is_isa
1010 && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
1011 err = -EINVAL;
1012 goto ERROR0;
1013 }
1014
1015 /* Prevent users from forcing a kind for a bus it isn't supposed
1016 to possibly be on */
1017 if (is_isa && (kind == as99127f || kind == w83783s)) {
1018 dev_err(&adapter->dev,
1019 "Cannot force I2C-only chip for ISA address 0x%02x.\n",
1020 address);
1021 err = -EINVAL;
1022 goto ERROR0;
1023 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024
1025 if (is_isa)
1026 if (!request_region(address, W83781D_EXTENT,
Laurent Riffardcdaf7932005-11-26 20:37:41 +01001027 w83781d_isa_driver.driver.name)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 dev_dbg(&adapter->dev, "Request of region "
1029 "0x%x-0x%x for w83781d failed\n", address,
1030 address + W83781D_EXTENT - 1);
1031 err = -EBUSY;
1032 goto ERROR0;
1033 }
1034
1035 /* Probe whether there is anything available on this address. Already
1036 done for SMBus clients */
1037 if (kind < 0) {
1038 if (is_isa) {
1039
1040#define REALLY_SLOW_IO
1041 /* We need the timeouts for at least some LM78-like
1042 chips. But only if we read 'undefined' registers. */
1043 i = inb_p(address + 1);
1044 if (inb_p(address + 2) != i
1045 || inb_p(address + 3) != i
1046 || inb_p(address + 7) != i) {
1047 dev_dbg(&adapter->dev, "Detection of w83781d "
1048 "chip failed at step 1\n");
1049 err = -ENODEV;
1050 goto ERROR1;
1051 }
1052#undef REALLY_SLOW_IO
1053
1054 /* Let's just hope nothing breaks here */
1055 i = inb_p(address + 5) & 0x7f;
1056 outb_p(~i & 0x7f, address + 5);
1057 val2 = inb_p(address + 5) & 0x7f;
1058 if (val2 != (~i & 0x7f)) {
1059 outb_p(i, address + 5);
1060 dev_dbg(&adapter->dev, "Detection of w83781d "
1061 "chip failed at step 2 (0x%x != "
1062 "0x%x at 0x%x)\n", val2, ~i & 0x7f,
1063 address + 5);
1064 err = -ENODEV;
1065 goto ERROR1;
1066 }
1067 }
1068 }
1069
1070 /* OK. For now, we presume we have a valid client. We now create the
1071 client structure, even though we cannot fill it completely yet.
1072 But it allows us to access w83781d_{read,write}_value. */
1073
Deepak Saxenaba9c2e82005-10-17 23:08:32 +02001074 if (!(data = kzalloc(sizeof(struct w83781d_data), GFP_KERNEL))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075 err = -ENOMEM;
1076 goto ERROR1;
1077 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078
Jim Cromie311ce2e2006-09-24 21:22:52 +02001079 client = &data->client;
1080 i2c_set_clientdata(client, data);
1081 client->addr = address;
Ingo Molnar9a61bf62006-01-18 23:19:26 +01001082 mutex_init(&data->lock);
Jim Cromie311ce2e2006-09-24 21:22:52 +02001083 client->adapter = adapter;
1084 client->driver = is_isa ? &w83781d_isa_driver : &w83781d_driver;
1085 client->flags = 0;
1086 dev = &client->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087
1088 /* Now, we do the remaining detection. */
1089
1090 /* The w8378?d may be stuck in some other bank than bank 0. This may
1091 make reading other information impossible. Specify a force=... or
1092 force_*=... parameter, and the Winbond will be reset to the right
1093 bank. */
1094 if (kind < 0) {
Jim Cromie311ce2e2006-09-24 21:22:52 +02001095 if (w83781d_read_value(client, W83781D_REG_CONFIG) & 0x80) {
Jean Delvarebd452e62006-10-13 17:03:42 +02001096 dev_dbg(&adapter->dev, "Detection of w83781d chip "
1097 "failed at step 3\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 err = -ENODEV;
1099 goto ERROR2;
1100 }
Jim Cromie311ce2e2006-09-24 21:22:52 +02001101 val1 = w83781d_read_value(client, W83781D_REG_BANK);
1102 val2 = w83781d_read_value(client, W83781D_REG_CHIPMAN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 /* Check for Winbond or Asus ID if in bank 0 */
1104 if ((!(val1 & 0x07)) &&
1105 (((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3))
1106 || ((val1 & 0x80) && (val2 != 0x5c) && (val2 != 0x12)))) {
Jean Delvarebd452e62006-10-13 17:03:42 +02001107 dev_dbg(&adapter->dev, "Detection of w83781d chip "
1108 "failed at step 4\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 err = -ENODEV;
1110 goto ERROR2;
1111 }
1112 /* If Winbond SMBus, check address at 0x48.
1113 Asus doesn't support, except for as99127f rev.2 */
1114 if ((!is_isa) && (((!(val1 & 0x80)) && (val2 == 0xa3)) ||
1115 ((val1 & 0x80) && (val2 == 0x5c)))) {
1116 if (w83781d_read_value
Jim Cromie311ce2e2006-09-24 21:22:52 +02001117 (client, W83781D_REG_I2C_ADDR) != address) {
Jean Delvarebd452e62006-10-13 17:03:42 +02001118 dev_dbg(&adapter->dev, "Detection of w83781d "
1119 "chip failed at step 5\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 err = -ENODEV;
1121 goto ERROR2;
1122 }
1123 }
1124 }
1125
1126 /* We have either had a force parameter, or we have already detected the
1127 Winbond. Put it now into bank 0 and Vendor ID High Byte */
Jim Cromie311ce2e2006-09-24 21:22:52 +02001128 w83781d_write_value(client, W83781D_REG_BANK,
1129 (w83781d_read_value(client, W83781D_REG_BANK)
1130 & 0x78) | 0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131
1132 /* Determine the chip type. */
1133 if (kind <= 0) {
1134 /* get vendor ID */
Jim Cromie311ce2e2006-09-24 21:22:52 +02001135 val2 = w83781d_read_value(client, W83781D_REG_CHIPMAN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136 if (val2 == 0x5c)
1137 vendid = winbond;
1138 else if (val2 == 0x12)
1139 vendid = asus;
1140 else {
Jean Delvarebd452e62006-10-13 17:03:42 +02001141 dev_dbg(&adapter->dev, "w83781d chip vendor is "
1142 "neither Winbond nor Asus\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143 err = -ENODEV;
1144 goto ERROR2;
1145 }
1146
Jim Cromie311ce2e2006-09-24 21:22:52 +02001147 val1 = w83781d_read_value(client, W83781D_REG_WCHIPID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 if ((val1 == 0x10 || val1 == 0x11) && vendid == winbond)
1149 kind = w83781d;
1150 else if (val1 == 0x30 && vendid == winbond)
1151 kind = w83782d;
1152 else if (val1 == 0x40 && vendid == winbond && !is_isa
1153 && address == 0x2d)
1154 kind = w83783s;
Jean Delvare7c7a5302005-06-16 19:24:14 +02001155 else if (val1 == 0x21 && vendid == winbond)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 kind = w83627hf;
1157 else if (val1 == 0x31 && !is_isa && address >= 0x28)
1158 kind = as99127f;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 else {
1160 if (kind == 0)
Jean Delvarebd452e62006-10-13 17:03:42 +02001161 dev_warn(&adapter->dev, "Ignoring 'force' "
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 "parameter for unknown chip at "
Jean Delvarebd452e62006-10-13 17:03:42 +02001163 "address 0x%02x\n", address);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 err = -EINVAL;
1165 goto ERROR2;
1166 }
1167 }
1168
1169 if (kind == w83781d) {
1170 client_name = "w83781d";
1171 } else if (kind == w83782d) {
1172 client_name = "w83782d";
1173 } else if (kind == w83783s) {
1174 client_name = "w83783s";
1175 } else if (kind == w83627hf) {
Jean Delvare7c7a5302005-06-16 19:24:14 +02001176 client_name = "w83627hf";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 } else if (kind == as99127f) {
1178 client_name = "as99127f";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 }
1180
1181 /* Fill in the remaining client fields and put into the global list */
Jim Cromie311ce2e2006-09-24 21:22:52 +02001182 strlcpy(client->name, client_name, I2C_NAME_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 data->type = kind;
1184
1185 data->valid = 0;
Ingo Molnar9a61bf62006-01-18 23:19:26 +01001186 mutex_init(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187
1188 /* Tell the I2C layer a new client has arrived */
Jim Cromie311ce2e2006-09-24 21:22:52 +02001189 if ((err = i2c_attach_client(client)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190 goto ERROR2;
1191
1192 /* attach secondary i2c lm75-like clients */
1193 if (!is_isa) {
1194 if ((err = w83781d_detect_subclients(adapter, address,
Jim Cromie311ce2e2006-09-24 21:22:52 +02001195 kind, client)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196 goto ERROR3;
1197 } else {
1198 data->lm75[0] = NULL;
1199 data->lm75[1] = NULL;
1200 }
1201
1202 /* Initialize the chip */
Jim Cromie311ce2e2006-09-24 21:22:52 +02001203 w83781d_init_client(client);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204
1205 /* A few vars need to be filled upon startup */
1206 for (i = 1; i <= 3; i++) {
Jim Cromie311ce2e2006-09-24 21:22:52 +02001207 data->fan_min[i - 1] = w83781d_read_value(client,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 W83781D_REG_FAN_MIN(i));
1209 }
1210 if (kind != w83781d && kind != as99127f)
1211 for (i = 0; i < 4; i++)
1212 data->pwmenable[i] = 1;
1213
1214 /* Register sysfs hooks */
Jim Cromie311ce2e2006-09-24 21:22:52 +02001215 if ((err = sysfs_create_group(&dev->kobj, &w83781d_group)))
1216 goto ERROR4;
1217
1218 if (kind != w83783s) {
1219 if ((err = device_create_file(dev, &dev_attr_in1_input))
1220 || (err = device_create_file(dev, &dev_attr_in1_min))
1221 || (err = device_create_file(dev, &dev_attr_in1_max)))
1222 goto ERROR4;
1223 }
1224 if (kind != as99127f && kind != w83781d && kind != w83783s) {
1225 if ((err = device_create_file(dev, &dev_attr_in7_input))
1226 || (err = device_create_file(dev, &dev_attr_in7_min))
1227 || (err = device_create_file(dev, &dev_attr_in7_max))
1228 || (err = device_create_file(dev, &dev_attr_in8_input))
1229 || (err = device_create_file(dev, &dev_attr_in8_min))
1230 || (err = device_create_file(dev, &dev_attr_in8_max)))
1231 goto ERROR4;
1232 }
1233 if (kind != w83783s) {
1234 if ((err = device_create_file(dev, &dev_attr_temp3_input))
1235 || (err = device_create_file(dev, &dev_attr_temp3_max))
1236 || (err = device_create_file(dev,
1237 &dev_attr_temp3_max_hyst)))
1238 goto ERROR4;
1239 }
1240
1241 if (kind != w83781d && kind != as99127f) {
1242 if ((err = device_create_file(dev, &dev_attr_pwm1))
1243 || (err = device_create_file(dev, &dev_attr_pwm2))
1244 || (err = device_create_file(dev, &dev_attr_pwm2_enable)))
1245 goto ERROR4;
1246 }
1247 if (kind == w83782d && !is_isa) {
1248 if ((err = device_create_file(dev, &dev_attr_pwm3))
1249 || (err = device_create_file(dev, &dev_attr_pwm4)))
1250 goto ERROR4;
1251 }
1252
1253 if (kind != as99127f && kind != w83781d) {
1254 if ((err = device_create_file(dev, &dev_attr_temp1_type))
1255 || (err = device_create_file(dev,
1256 &dev_attr_temp2_type)))
1257 goto ERROR4;
1258 if (kind != w83783s) {
1259 if ((err = device_create_file(dev,
1260 &dev_attr_temp3_type)))
1261 goto ERROR4;
1262 }
1263 }
1264
1265 data->class_dev = hwmon_device_register(dev);
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001266 if (IS_ERR(data->class_dev)) {
1267 err = PTR_ERR(data->class_dev);
1268 goto ERROR4;
1269 }
1270
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 return 0;
1272
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001273ERROR4:
Jim Cromie311ce2e2006-09-24 21:22:52 +02001274 sysfs_remove_group(&dev->kobj, &w83781d_group);
1275 sysfs_remove_group(&dev->kobj, &w83781d_group_opt);
1276
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001277 if (data->lm75[1]) {
1278 i2c_detach_client(data->lm75[1]);
1279 kfree(data->lm75[1]);
1280 }
1281 if (data->lm75[0]) {
1282 i2c_detach_client(data->lm75[0]);
1283 kfree(data->lm75[0]);
1284 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285ERROR3:
Jim Cromie311ce2e2006-09-24 21:22:52 +02001286 i2c_detach_client(client);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287ERROR2:
1288 kfree(data);
1289ERROR1:
1290 if (is_isa)
1291 release_region(address, W83781D_EXTENT);
1292ERROR0:
1293 return err;
1294}
1295
1296static int
1297w83781d_detach_client(struct i2c_client *client)
1298{
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001299 struct w83781d_data *data = i2c_get_clientdata(client);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 int err;
1301
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001302 /* main client */
Jim Cromie311ce2e2006-09-24 21:22:52 +02001303 if (data) {
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001304 hwmon_device_unregister(data->class_dev);
Jim Cromie311ce2e2006-09-24 21:22:52 +02001305 sysfs_remove_group(&client->dev.kobj, &w83781d_group);
1306 sysfs_remove_group(&client->dev.kobj, &w83781d_group_opt);
1307 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308 if (i2c_is_isa_client(client))
1309 release_region(client->addr, W83781D_EXTENT);
1310
Jean Delvare7bef5592005-07-27 22:14:49 +02001311 if ((err = i2c_detach_client(client)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001314 /* main client */
1315 if (data)
1316 kfree(data);
1317
1318 /* subclient */
1319 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 kfree(client);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321
1322 return 0;
1323}
1324
1325/* The SMBus locks itself, usually, but nothing may access the Winbond between
1326 bank switches. ISA access must always be locked explicitly!
1327 We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks,
1328 would slow down the W83781D access and should not be necessary.
1329 There are some ugly typecasts here, but the good news is - they should
1330 nowhere else be necessary! */
1331static int
1332w83781d_read_value(struct i2c_client *client, u16 reg)
1333{
1334 struct w83781d_data *data = i2c_get_clientdata(client);
1335 int res, word_sized, bank;
1336 struct i2c_client *cl;
1337
Ingo Molnar9a61bf62006-01-18 23:19:26 +01001338 mutex_lock(&data->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339 if (i2c_is_isa_client(client)) {
1340 word_sized = (((reg & 0xff00) == 0x100)
1341 || ((reg & 0xff00) == 0x200))
1342 && (((reg & 0x00ff) == 0x50)
1343 || ((reg & 0x00ff) == 0x53)
1344 || ((reg & 0x00ff) == 0x55));
1345 if (reg & 0xff00) {
1346 outb_p(W83781D_REG_BANK,
1347 client->addr + W83781D_ADDR_REG_OFFSET);
1348 outb_p(reg >> 8,
1349 client->addr + W83781D_DATA_REG_OFFSET);
1350 }
1351 outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET);
1352 res = inb_p(client->addr + W83781D_DATA_REG_OFFSET);
1353 if (word_sized) {
1354 outb_p((reg & 0xff) + 1,
1355 client->addr + W83781D_ADDR_REG_OFFSET);
1356 res =
1357 (res << 8) + inb_p(client->addr +
1358 W83781D_DATA_REG_OFFSET);
1359 }
1360 if (reg & 0xff00) {
1361 outb_p(W83781D_REG_BANK,
1362 client->addr + W83781D_ADDR_REG_OFFSET);
1363 outb_p(0, client->addr + W83781D_DATA_REG_OFFSET);
1364 }
1365 } else {
1366 bank = (reg >> 8) & 0x0f;
1367 if (bank > 2)
1368 /* switch banks */
1369 i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
1370 bank);
1371 if (bank == 0 || bank > 2) {
1372 res = i2c_smbus_read_byte_data(client, reg & 0xff);
1373 } else {
1374 /* switch to subclient */
1375 cl = data->lm75[bank - 1];
1376 /* convert from ISA to LM75 I2C addresses */
1377 switch (reg & 0xff) {
1378 case 0x50: /* TEMP */
1379 res = swab16(i2c_smbus_read_word_data(cl, 0));
1380 break;
1381 case 0x52: /* CONFIG */
1382 res = i2c_smbus_read_byte_data(cl, 1);
1383 break;
1384 case 0x53: /* HYST */
1385 res = swab16(i2c_smbus_read_word_data(cl, 2));
1386 break;
1387 case 0x55: /* OVER */
1388 default:
1389 res = swab16(i2c_smbus_read_word_data(cl, 3));
1390 break;
1391 }
1392 }
1393 if (bank > 2)
1394 i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0);
1395 }
Ingo Molnar9a61bf62006-01-18 23:19:26 +01001396 mutex_unlock(&data->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 return res;
1398}
1399
1400static int
1401w83781d_write_value(struct i2c_client *client, u16 reg, u16 value)
1402{
1403 struct w83781d_data *data = i2c_get_clientdata(client);
1404 int word_sized, bank;
1405 struct i2c_client *cl;
1406
Ingo Molnar9a61bf62006-01-18 23:19:26 +01001407 mutex_lock(&data->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 if (i2c_is_isa_client(client)) {
1409 word_sized = (((reg & 0xff00) == 0x100)
1410 || ((reg & 0xff00) == 0x200))
1411 && (((reg & 0x00ff) == 0x53)
1412 || ((reg & 0x00ff) == 0x55));
1413 if (reg & 0xff00) {
1414 outb_p(W83781D_REG_BANK,
1415 client->addr + W83781D_ADDR_REG_OFFSET);
1416 outb_p(reg >> 8,
1417 client->addr + W83781D_DATA_REG_OFFSET);
1418 }
1419 outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET);
1420 if (word_sized) {
1421 outb_p(value >> 8,
1422 client->addr + W83781D_DATA_REG_OFFSET);
1423 outb_p((reg & 0xff) + 1,
1424 client->addr + W83781D_ADDR_REG_OFFSET);
1425 }
1426 outb_p(value & 0xff, client->addr + W83781D_DATA_REG_OFFSET);
1427 if (reg & 0xff00) {
1428 outb_p(W83781D_REG_BANK,
1429 client->addr + W83781D_ADDR_REG_OFFSET);
1430 outb_p(0, client->addr + W83781D_DATA_REG_OFFSET);
1431 }
1432 } else {
1433 bank = (reg >> 8) & 0x0f;
1434 if (bank > 2)
1435 /* switch banks */
1436 i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
1437 bank);
1438 if (bank == 0 || bank > 2) {
1439 i2c_smbus_write_byte_data(client, reg & 0xff,
1440 value & 0xff);
1441 } else {
1442 /* switch to subclient */
1443 cl = data->lm75[bank - 1];
1444 /* convert from ISA to LM75 I2C addresses */
1445 switch (reg & 0xff) {
1446 case 0x52: /* CONFIG */
1447 i2c_smbus_write_byte_data(cl, 1, value & 0xff);
1448 break;
1449 case 0x53: /* HYST */
1450 i2c_smbus_write_word_data(cl, 2, swab16(value));
1451 break;
1452 case 0x55: /* OVER */
1453 i2c_smbus_write_word_data(cl, 3, swab16(value));
1454 break;
1455 }
1456 }
1457 if (bank > 2)
1458 i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0);
1459 }
Ingo Molnar9a61bf62006-01-18 23:19:26 +01001460 mutex_unlock(&data->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461 return 0;
1462}
1463
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464static void
1465w83781d_init_client(struct i2c_client *client)
1466{
1467 struct w83781d_data *data = i2c_get_clientdata(client);
1468 int i, p;
1469 int type = data->type;
1470 u8 tmp;
1471
Jean Delvarefabddcd2006-02-05 23:26:51 +01001472 if (reset && type != as99127f) { /* this resets registers we don't have
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 documentation for on the as99127f */
Jean Delvarefabddcd2006-02-05 23:26:51 +01001474 /* Resetting the chip has been the default for a long time,
1475 but it causes the BIOS initializations (fan clock dividers,
1476 thermal sensor types...) to be lost, so it is now optional.
1477 It might even go away if nobody reports it as being useful,
1478 as I see very little reason why this would be needed at
1479 all. */
1480 dev_info(&client->dev, "If reset=1 solved a problem you were "
1481 "having, please report!\n");
1482
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483 /* save these registers */
1484 i = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG);
1485 p = w83781d_read_value(client, W83781D_REG_PWMCLK12);
1486 /* Reset all except Watchdog values and last conversion values
1487 This sets fan-divs to 2, among others */
1488 w83781d_write_value(client, W83781D_REG_CONFIG, 0x80);
1489 /* Restore the registers and disable power-on abnormal beep.
1490 This saves FAN 1/2/3 input/output values set by BIOS. */
1491 w83781d_write_value(client, W83781D_REG_BEEP_CONFIG, i | 0x80);
1492 w83781d_write_value(client, W83781D_REG_PWMCLK12, p);
1493 /* Disable master beep-enable (reset turns it on).
1494 Individual beep_mask should be reset to off but for some reason
1495 disabling this bit helps some people not get beeped */
1496 w83781d_write_value(client, W83781D_REG_BEEP_INTS2, 0);
1497 }
1498
Jean Delvarefabddcd2006-02-05 23:26:51 +01001499 /* Disable power-on abnormal beep, as advised by the datasheet.
1500 Already done if reset=1. */
1501 if (init && !reset && type != as99127f) {
1502 i = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG);
1503 w83781d_write_value(client, W83781D_REG_BEEP_CONFIG, i | 0x80);
1504 }
1505
Jean Delvare303760b2005-07-31 21:52:01 +02001506 data->vrm = vid_which_vrm();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507
1508 if ((type != w83781d) && (type != as99127f)) {
1509 tmp = w83781d_read_value(client, W83781D_REG_SCFG1);
1510 for (i = 1; i <= 3; i++) {
1511 if (!(tmp & BIT_SCFG1[i - 1])) {
1512 data->sens[i - 1] = W83781D_DEFAULT_BETA;
1513 } else {
1514 if (w83781d_read_value
1515 (client,
1516 W83781D_REG_SCFG2) & BIT_SCFG2[i - 1])
1517 data->sens[i - 1] = 1;
1518 else
1519 data->sens[i - 1] = 2;
1520 }
Jean Delvare7c7a5302005-06-16 19:24:14 +02001521 if (type == w83783s && i == 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522 break;
1523 }
1524 }
1525
1526 if (init && type != as99127f) {
1527 /* Enable temp2 */
1528 tmp = w83781d_read_value(client, W83781D_REG_TEMP2_CONFIG);
1529 if (tmp & 0x01) {
1530 dev_warn(&client->dev, "Enabling temp2, readings "
1531 "might not make sense\n");
1532 w83781d_write_value(client, W83781D_REG_TEMP2_CONFIG,
1533 tmp & 0xfe);
1534 }
1535
1536 /* Enable temp3 */
Jean Delvare7c7a5302005-06-16 19:24:14 +02001537 if (type != w83783s) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538 tmp = w83781d_read_value(client,
1539 W83781D_REG_TEMP3_CONFIG);
1540 if (tmp & 0x01) {
1541 dev_warn(&client->dev, "Enabling temp3, "
1542 "readings might not make sense\n");
1543 w83781d_write_value(client,
1544 W83781D_REG_TEMP3_CONFIG, tmp & 0xfe);
1545 }
1546 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547 }
1548
1549 /* Start monitoring */
1550 w83781d_write_value(client, W83781D_REG_CONFIG,
1551 (w83781d_read_value(client,
1552 W83781D_REG_CONFIG) & 0xf7)
1553 | 0x01);
1554}
1555
1556static struct w83781d_data *w83781d_update_device(struct device *dev)
1557{
1558 struct i2c_client *client = to_i2c_client(dev);
1559 struct w83781d_data *data = i2c_get_clientdata(client);
1560 int i;
1561
Ingo Molnar9a61bf62006-01-18 23:19:26 +01001562 mutex_lock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563
1564 if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
1565 || !data->valid) {
1566 dev_dbg(dev, "Starting device update\n");
1567
1568 for (i = 0; i <= 8; i++) {
Jean Delvare7c7a5302005-06-16 19:24:14 +02001569 if (data->type == w83783s && i == 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570 continue; /* 783S has no in1 */
1571 data->in[i] =
1572 w83781d_read_value(client, W83781D_REG_IN(i));
1573 data->in_min[i] =
1574 w83781d_read_value(client, W83781D_REG_IN_MIN(i));
1575 data->in_max[i] =
1576 w83781d_read_value(client, W83781D_REG_IN_MAX(i));
Jean Delvare7c7a5302005-06-16 19:24:14 +02001577 if ((data->type != w83782d)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578 && (data->type != w83627hf) && (i == 6))
1579 break;
1580 }
1581 for (i = 1; i <= 3; i++) {
1582 data->fan[i - 1] =
1583 w83781d_read_value(client, W83781D_REG_FAN(i));
1584 data->fan_min[i - 1] =
1585 w83781d_read_value(client, W83781D_REG_FAN_MIN(i));
1586 }
1587 if (data->type != w83781d && data->type != as99127f) {
1588 for (i = 1; i <= 4; i++) {
1589 data->pwm[i - 1] =
1590 w83781d_read_value(client,
1591 W83781D_REG_PWM(i));
1592 if ((data->type != w83782d
1593 || i2c_is_isa_client(client))
1594 && i == 2)
1595 break;
1596 }
1597 /* Only PWM2 can be disabled */
1598 data->pwmenable[1] = (w83781d_read_value(client,
1599 W83781D_REG_PWMCLK12) & 0x08) >> 3;
1600 }
1601
1602 data->temp = w83781d_read_value(client, W83781D_REG_TEMP(1));
1603 data->temp_max =
1604 w83781d_read_value(client, W83781D_REG_TEMP_OVER(1));
1605 data->temp_max_hyst =
1606 w83781d_read_value(client, W83781D_REG_TEMP_HYST(1));
1607 data->temp_add[0] =
1608 w83781d_read_value(client, W83781D_REG_TEMP(2));
1609 data->temp_max_add[0] =
1610 w83781d_read_value(client, W83781D_REG_TEMP_OVER(2));
1611 data->temp_max_hyst_add[0] =
1612 w83781d_read_value(client, W83781D_REG_TEMP_HYST(2));
Jean Delvare7c7a5302005-06-16 19:24:14 +02001613 if (data->type != w83783s) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614 data->temp_add[1] =
1615 w83781d_read_value(client, W83781D_REG_TEMP(3));
1616 data->temp_max_add[1] =
1617 w83781d_read_value(client,
1618 W83781D_REG_TEMP_OVER(3));
1619 data->temp_max_hyst_add[1] =
1620 w83781d_read_value(client,
1621 W83781D_REG_TEMP_HYST(3));
1622 }
1623 i = w83781d_read_value(client, W83781D_REG_VID_FANDIV);
Jean Delvare7c7a5302005-06-16 19:24:14 +02001624 data->vid = i & 0x0f;
1625 data->vid |= (w83781d_read_value(client,
1626 W83781D_REG_CHIPID) & 0x01) << 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627 data->fan_div[0] = (i >> 4) & 0x03;
1628 data->fan_div[1] = (i >> 6) & 0x03;
Jean Delvare7c7a5302005-06-16 19:24:14 +02001629 data->fan_div[2] = (w83781d_read_value(client,
1630 W83781D_REG_PIN) >> 6) & 0x03;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 if ((data->type != w83781d) && (data->type != as99127f)) {
1632 i = w83781d_read_value(client, W83781D_REG_VBAT);
1633 data->fan_div[0] |= (i >> 3) & 0x04;
1634 data->fan_div[1] |= (i >> 4) & 0x04;
Jean Delvare7c7a5302005-06-16 19:24:14 +02001635 data->fan_div[2] |= (i >> 5) & 0x04;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637 if ((data->type == w83782d) || (data->type == w83627hf)) {
Jean Delvarec7f5d7e2006-02-05 23:13:48 +01001638 data->alarms = w83781d_read_value(client,
1639 W83782D_REG_ALARM1)
1640 | (w83781d_read_value(client,
1641 W83782D_REG_ALARM2) << 8)
1642 | (w83781d_read_value(client,
1643 W83782D_REG_ALARM3) << 16);
1644 } else if (data->type == w83783s) {
1645 data->alarms = w83781d_read_value(client,
1646 W83782D_REG_ALARM1)
1647 | (w83781d_read_value(client,
1648 W83782D_REG_ALARM2) << 8);
1649 } else {
1650 /* No real-time status registers, fall back to
1651 interrupt status registers */
1652 data->alarms = w83781d_read_value(client,
1653 W83781D_REG_ALARM1)
1654 | (w83781d_read_value(client,
1655 W83781D_REG_ALARM2) << 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656 }
1657 i = w83781d_read_value(client, W83781D_REG_BEEP_INTS2);
1658 data->beep_enable = i >> 7;
1659 data->beep_mask = ((i & 0x7f) << 8) +
1660 w83781d_read_value(client, W83781D_REG_BEEP_INTS1);
1661 if ((data->type != w83781d) && (data->type != as99127f)) {
1662 data->beep_mask |=
1663 w83781d_read_value(client,
1664 W83781D_REG_BEEP_INTS3) << 16;
1665 }
1666 data->last_updated = jiffies;
1667 data->valid = 1;
1668 }
1669
Ingo Molnar9a61bf62006-01-18 23:19:26 +01001670 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671
1672 return data;
1673}
1674
1675static int __init
1676sensors_w83781d_init(void)
1677{
Jean Delvarefde09502005-07-19 23:51:07 +02001678 int res;
1679
1680 res = i2c_add_driver(&w83781d_driver);
1681 if (res)
1682 return res;
1683
Jean Delvaree6938102006-10-13 16:56:28 +02001684 /* Don't exit if this one fails, we still want the I2C variants
1685 to work! */
1686 if (i2c_isa_add_driver(&w83781d_isa_driver))
1687 isa_address = 0;
Jean Delvarefde09502005-07-19 23:51:07 +02001688
1689 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690}
1691
1692static void __exit
1693sensors_w83781d_exit(void)
1694{
Jean Delvaree6938102006-10-13 16:56:28 +02001695 if (isa_address)
1696 i2c_isa_del_driver(&w83781d_isa_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697 i2c_del_driver(&w83781d_driver);
1698}
1699
1700MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
1701 "Philip Edelbrock <phil@netroedge.com>, "
1702 "and Mark Studebaker <mdsxyz123@yahoo.com>");
1703MODULE_DESCRIPTION("W83781D driver");
1704MODULE_LICENSE("GPL");
1705
1706module_init(sensors_w83781d_init);
1707module_exit(sensors_w83781d_exit);