blob: 1a729a7492770d9d0e1979513b9e9daffc265fa3 [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>,
Jean Delvare7666c132007-05-08 17:22:02 +02005 Philip Edelbrock <phil@netroedge.com>,
6 and Mark Studebaker <mdsxyz123@yahoo.com>
7 Copyright (c) 2007 Jean Delvare <khali@linux-fr.org>
Linus Torvalds1da177e2005-04-16 15:20:36 -07008
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22*/
23
24/*
25 Supports following chips:
26
27 Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
28 as99127f 7 3 0 3 0x31 0x12c3 yes no
29 as99127f rev.2 (type_name = as99127f) 0x31 0x5ca3 yes no
30 w83781d 7 3 0 3 0x10-1 0x5ca3 yes yes
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>
Mark M. Hoffman943b0832005-07-15 21:39:18 -040041#include <linux/hwmon.h>
Jean Delvare303760b2005-07-31 21:52:01 +020042#include <linux/hwmon-vid.h>
Jean Delvare34875332007-05-08 17:22:03 +020043#include <linux/hwmon-sysfs.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
Wolfgang Grandegger443850c2008-10-17 17:51:18 +020048#ifdef CONFIG_ISA
49#include <linux/platform_device.h>
50#include <linux/ioport.h>
51#include <asm/io.h>
52#endif
53
54#include "lm75.h"
Jean Delvare7666c132007-05-08 17:22:02 +020055
Linus Torvalds1da177e2005-04-16 15:20:36 -070056/* Addresses to scan */
Mark M. Hoffman25e9c862008-02-17 22:28:03 -050057static const unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
58 0x2e, 0x2f, I2C_CLIENT_END };
Linus Torvalds1da177e2005-04-16 15:20:36 -070059/* Insmod parameters */
Jean Delvare05663362007-11-30 23:51:24 +010060I2C_CLIENT_INSMOD_4(w83781d, w83782d, w83783s, as99127f);
Linus Torvalds1da177e2005-04-16 15:20:36 -070061I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
62 "{bus, clientaddr, subclientaddr1, subclientaddr2}");
63
Jean Delvarefabddcd2006-02-05 23:26:51 +010064static int reset;
65module_param(reset, bool, 0);
66MODULE_PARM_DESC(reset, "Set to one to reset chip on load");
67
Linus Torvalds1da177e2005-04-16 15:20:36 -070068static int init = 1;
69module_param(init, bool, 0);
70MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
71
72/* Constants specified below */
73
74/* Length of ISA address segment */
75#define W83781D_EXTENT 8
76
77/* Where are the ISA address/data registers relative to the base address */
78#define W83781D_ADDR_REG_OFFSET 5
79#define W83781D_DATA_REG_OFFSET 6
80
Jean Delvare34875332007-05-08 17:22:03 +020081/* The device registers */
82/* in nr from 0 to 8 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070083#define W83781D_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \
84 (0x554 + (((nr) - 7) * 2)))
85#define W83781D_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \
86 (0x555 + (((nr) - 7) * 2)))
87#define W83781D_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \
88 (0x550 + (nr) - 7))
89
Jean Delvare34875332007-05-08 17:22:03 +020090/* fan nr from 0 to 2 */
91#define W83781D_REG_FAN_MIN(nr) (0x3b + (nr))
92#define W83781D_REG_FAN(nr) (0x28 + (nr))
Linus Torvalds1da177e2005-04-16 15:20:36 -070093
94#define W83781D_REG_BANK 0x4E
95#define W83781D_REG_TEMP2_CONFIG 0x152
96#define W83781D_REG_TEMP3_CONFIG 0x252
Jean Delvare34875332007-05-08 17:22:03 +020097/* temp nr from 1 to 3 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070098#define W83781D_REG_TEMP(nr) ((nr == 3) ? (0x0250) : \
99 ((nr == 2) ? (0x0150) : \
100 (0x27)))
101#define W83781D_REG_TEMP_HYST(nr) ((nr == 3) ? (0x253) : \
102 ((nr == 2) ? (0x153) : \
103 (0x3A)))
104#define W83781D_REG_TEMP_OVER(nr) ((nr == 3) ? (0x255) : \
105 ((nr == 2) ? (0x155) : \
106 (0x39)))
107
108#define W83781D_REG_CONFIG 0x40
Jean Delvarec7f5d7e2006-02-05 23:13:48 +0100109
110/* Interrupt status (W83781D, AS99127F) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111#define W83781D_REG_ALARM1 0x41
112#define W83781D_REG_ALARM2 0x42
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113
Jean Delvare05663362007-11-30 23:51:24 +0100114/* Real-time status (W83782D, W83783S) */
Jean Delvarec7f5d7e2006-02-05 23:13:48 +0100115#define W83782D_REG_ALARM1 0x459
116#define W83782D_REG_ALARM2 0x45A
117#define W83782D_REG_ALARM3 0x45B
118
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119#define W83781D_REG_BEEP_CONFIG 0x4D
120#define W83781D_REG_BEEP_INTS1 0x56
121#define W83781D_REG_BEEP_INTS2 0x57
122#define W83781D_REG_BEEP_INTS3 0x453 /* not on W83781D */
123
124#define W83781D_REG_VID_FANDIV 0x47
125
126#define W83781D_REG_CHIPID 0x49
127#define W83781D_REG_WCHIPID 0x58
128#define W83781D_REG_CHIPMAN 0x4F
129#define W83781D_REG_PIN 0x4B
130
131/* 782D/783S only */
132#define W83781D_REG_VBAT 0x5D
133
134/* PWM 782D (1-4) and 783S (1-2) only */
Jean Delvare34875332007-05-08 17:22:03 +0200135static const u8 W83781D_REG_PWM[] = { 0x5B, 0x5A, 0x5E, 0x5F };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136#define W83781D_REG_PWMCLK12 0x5C
137#define W83781D_REG_PWMCLK34 0x45C
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138
139#define W83781D_REG_I2C_ADDR 0x48
140#define W83781D_REG_I2C_SUBADDR 0x4A
141
142/* The following are undocumented in the data sheets however we
143 received the information in an email from Winbond tech support */
144/* Sensor selection - not on 781d */
145#define W83781D_REG_SCFG1 0x5D
146static const u8 BIT_SCFG1[] = { 0x02, 0x04, 0x08 };
147
148#define W83781D_REG_SCFG2 0x59
149static const u8 BIT_SCFG2[] = { 0x10, 0x20, 0x40 };
150
151#define W83781D_DEFAULT_BETA 3435
152
Jean Delvare474d00a2007-05-08 17:22:03 +0200153/* Conversions */
154#define IN_TO_REG(val) SENSORS_LIMIT(((val) + 8) / 16, 0, 255)
155#define IN_FROM_REG(val) ((val) * 16)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156
157static inline u8
158FAN_TO_REG(long rpm, int div)
159{
160 if (rpm == 0)
161 return 255;
162 rpm = SENSORS_LIMIT(rpm, 1, 1000000);
163 return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
164}
165
Jean Delvare474d00a2007-05-08 17:22:03 +0200166static inline long
167FAN_FROM_REG(u8 val, int div)
168{
169 if (val == 0)
170 return -1;
171 if (val == 255)
172 return 0;
173 return 1350000 / (val * div);
174}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175
Jean Delvare474d00a2007-05-08 17:22:03 +0200176#define TEMP_TO_REG(val) SENSORS_LIMIT((val) / 1000, -127, 128)
177#define TEMP_FROM_REG(val) ((val) * 1000)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179#define BEEP_MASK_FROM_REG(val,type) ((type) == as99127f ? \
Jean Delvare2fbbbf12008-10-17 17:51:18 +0200180 (~(val)) & 0x7fff : (val) & 0xff7fff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181#define BEEP_MASK_TO_REG(val,type) ((type) == as99127f ? \
Jean Delvare2fbbbf12008-10-17 17:51:18 +0200182 (~(val)) & 0x7fff : (val) & 0xff7fff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184#define DIV_FROM_REG(val) (1 << (val))
185
186static inline u8
187DIV_TO_REG(long val, enum chips type)
188{
189 int i;
190 val = SENSORS_LIMIT(val, 1,
191 ((type == w83781d
192 || type == as99127f) ? 8 : 128)) >> 1;
Grant Coadyabc01922005-05-12 13:41:51 +1000193 for (i = 0; i < 7; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194 if (val == 0)
195 break;
196 val >>= 1;
197 }
Jean Delvare474d00a2007-05-08 17:22:03 +0200198 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199}
200
201/* There are some complications in a module like this. First off, W83781D chips
202 may be both present on the SMBus and the ISA bus, and we have to handle
203 those cases separately at some places. Second, there might be several
204 W83781D chips available (well, actually, that is probably never done; but
205 it is a clean illustration of how to handle a case like that). Finally,
206 a specific chip may be attached to *both* ISA and SMBus, and we would
Jean Delvarec6566202008-10-17 17:51:18 +0200207 not like to detect it double. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208
Jean Delvare7666c132007-05-08 17:22:02 +0200209/* For ISA chips, we abuse the i2c_client addr and name fields. We also use
210 the driver field to differentiate between I2C and ISA chips. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211struct w83781d_data {
212 struct i2c_client client;
Tony Jones1beeffe2007-08-20 13:46:20 -0700213 struct device *hwmon_dev;
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100214 struct mutex lock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 enum chips type;
216
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100217 struct mutex update_lock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 char valid; /* !=0 if following fields are valid */
219 unsigned long last_updated; /* In jiffies */
220
221 struct i2c_client *lm75[2]; /* for secondary I2C addresses */
222 /* array of 2 pointers to subclients */
223
224 u8 in[9]; /* Register value - 8 & 9 for 782D only */
225 u8 in_max[9]; /* Register value - 8 & 9 for 782D only */
226 u8 in_min[9]; /* Register value - 8 & 9 for 782D only */
227 u8 fan[3]; /* Register value */
228 u8 fan_min[3]; /* Register value */
Jean Delvare474d00a2007-05-08 17:22:03 +0200229 s8 temp; /* Register value */
230 s8 temp_max; /* Register value */
231 s8 temp_max_hyst; /* Register value */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232 u16 temp_add[2]; /* Register value */
233 u16 temp_max_add[2]; /* Register value */
234 u16 temp_max_hyst_add[2]; /* Register value */
235 u8 fan_div[3]; /* Register encoding, shifted right */
236 u8 vid; /* Register encoding, combined */
237 u32 alarms; /* Register encoding, combined */
238 u32 beep_mask; /* Register encoding, combined */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 u8 pwm[4]; /* Register value */
Jean Delvare34875332007-05-08 17:22:03 +0200240 u8 pwm2_enable; /* Boolean */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 u16 sens[3]; /* 782D/783S only.
242 1 = pentium diode; 2 = 3904 diode;
Jean Delvareb26f9332007-08-16 14:30:01 +0200243 4 = thermistor */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 u8 vrm;
245};
246
Wolfgang Grandegger443850c2008-10-17 17:51:18 +0200247static struct w83781d_data *w83781d_data_if_isa(void);
248static int w83781d_alias_detect(struct i2c_client *client, u8 chipid);
249
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250static int w83781d_attach_adapter(struct i2c_adapter *adapter);
251static int w83781d_detect(struct i2c_adapter *adapter, int address, int kind);
252static int w83781d_detach_client(struct i2c_client *client);
253
Jean Delvare31b8dc42007-05-08 17:22:03 +0200254static int w83781d_read_value(struct w83781d_data *data, u16 reg);
255static int w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256static struct w83781d_data *w83781d_update_device(struct device *dev);
Jean Delvare7666c132007-05-08 17:22:02 +0200257static void w83781d_init_device(struct device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258
259static struct i2c_driver w83781d_driver = {
Laurent Riffardcdaf7932005-11-26 20:37:41 +0100260 .driver = {
Laurent Riffardcdaf7932005-11-26 20:37:41 +0100261 .name = "w83781d",
262 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 .attach_adapter = w83781d_attach_adapter,
264 .detach_client = w83781d_detach_client,
265};
266
267/* following are the sysfs callback functions */
268#define show_in_reg(reg) \
Jean Delvare34875332007-05-08 17:22:03 +0200269static ssize_t show_##reg (struct device *dev, struct device_attribute *da, \
270 char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271{ \
Jean Delvare34875332007-05-08 17:22:03 +0200272 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 struct w83781d_data *data = w83781d_update_device(dev); \
Jean Delvare34875332007-05-08 17:22:03 +0200274 return sprintf(buf, "%ld\n", \
275 (long)IN_FROM_REG(data->reg[attr->index])); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276}
277show_in_reg(in);
278show_in_reg(in_min);
279show_in_reg(in_max);
280
281#define store_in_reg(REG, reg) \
Jean Delvare34875332007-05-08 17:22:03 +0200282static ssize_t store_in_##reg (struct device *dev, struct device_attribute \
283 *da, const char *buf, size_t count) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284{ \
Jean Delvare34875332007-05-08 17:22:03 +0200285 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \
Jean Delvare7666c132007-05-08 17:22:02 +0200286 struct w83781d_data *data = dev_get_drvdata(dev); \
Jean Delvare34875332007-05-08 17:22:03 +0200287 int nr = attr->index; \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 u32 val; \
289 \
Jean Delvare474d00a2007-05-08 17:22:03 +0200290 val = simple_strtoul(buf, NULL, 10); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 \
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100292 mutex_lock(&data->update_lock); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 data->in_##reg[nr] = IN_TO_REG(val); \
Jean Delvare31b8dc42007-05-08 17:22:03 +0200294 w83781d_write_value(data, W83781D_REG_IN_##REG(nr), data->in_##reg[nr]); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 \
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100296 mutex_unlock(&data->update_lock); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 return count; \
298}
299store_in_reg(MIN, min);
300store_in_reg(MAX, max);
301
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302#define sysfs_in_offsets(offset) \
Jean Delvare34875332007-05-08 17:22:03 +0200303static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \
304 show_in, NULL, offset); \
305static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
306 show_in_min, store_in_min, offset); \
307static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
308 show_in_max, store_in_max, offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309
310sysfs_in_offsets(0);
311sysfs_in_offsets(1);
312sysfs_in_offsets(2);
313sysfs_in_offsets(3);
314sysfs_in_offsets(4);
315sysfs_in_offsets(5);
316sysfs_in_offsets(6);
317sysfs_in_offsets(7);
318sysfs_in_offsets(8);
319
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320#define show_fan_reg(reg) \
Jean Delvare34875332007-05-08 17:22:03 +0200321static ssize_t show_##reg (struct device *dev, struct device_attribute *da, \
322 char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323{ \
Jean Delvare34875332007-05-08 17:22:03 +0200324 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 struct w83781d_data *data = w83781d_update_device(dev); \
326 return sprintf(buf,"%ld\n", \
Jean Delvare34875332007-05-08 17:22:03 +0200327 FAN_FROM_REG(data->reg[attr->index], \
328 DIV_FROM_REG(data->fan_div[attr->index]))); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329}
330show_fan_reg(fan);
331show_fan_reg(fan_min);
332
333static ssize_t
Jean Delvare34875332007-05-08 17:22:03 +0200334store_fan_min(struct device *dev, struct device_attribute *da,
335 const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336{
Jean Delvare34875332007-05-08 17:22:03 +0200337 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
Jean Delvare7666c132007-05-08 17:22:02 +0200338 struct w83781d_data *data = dev_get_drvdata(dev);
Jean Delvare34875332007-05-08 17:22:03 +0200339 int nr = attr->index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340 u32 val;
341
342 val = simple_strtoul(buf, NULL, 10);
343
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100344 mutex_lock(&data->update_lock);
Jean Delvare34875332007-05-08 17:22:03 +0200345 data->fan_min[nr] =
346 FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
Jean Delvare31b8dc42007-05-08 17:22:03 +0200347 w83781d_write_value(data, W83781D_REG_FAN_MIN(nr),
Jean Delvare34875332007-05-08 17:22:03 +0200348 data->fan_min[nr]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100350 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 return count;
352}
353
Jean Delvare34875332007-05-08 17:22:03 +0200354static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
355static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR,
356 show_fan_min, store_fan_min, 0);
357static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
358static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO | S_IWUSR,
359 show_fan_min, store_fan_min, 1);
360static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2);
361static SENSOR_DEVICE_ATTR(fan3_min, S_IRUGO | S_IWUSR,
362 show_fan_min, store_fan_min, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364#define show_temp_reg(reg) \
Jean Delvare34875332007-05-08 17:22:03 +0200365static ssize_t show_##reg (struct device *dev, struct device_attribute *da, \
366 char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367{ \
Jean Delvare34875332007-05-08 17:22:03 +0200368 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369 struct w83781d_data *data = w83781d_update_device(dev); \
Jean Delvare34875332007-05-08 17:22:03 +0200370 int nr = attr->index; \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 if (nr >= 2) { /* TEMP2 and TEMP3 */ \
372 return sprintf(buf,"%d\n", \
373 LM75_TEMP_FROM_REG(data->reg##_add[nr-2])); \
374 } else { /* TEMP1 */ \
375 return sprintf(buf,"%ld\n", (long)TEMP_FROM_REG(data->reg)); \
376 } \
377}
378show_temp_reg(temp);
379show_temp_reg(temp_max);
380show_temp_reg(temp_max_hyst);
381
382#define store_temp_reg(REG, reg) \
Jean Delvare34875332007-05-08 17:22:03 +0200383static ssize_t store_temp_##reg (struct device *dev, \
384 struct device_attribute *da, const char *buf, size_t count) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385{ \
Jean Delvare34875332007-05-08 17:22:03 +0200386 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \
Jean Delvare7666c132007-05-08 17:22:02 +0200387 struct w83781d_data *data = dev_get_drvdata(dev); \
Jean Delvare34875332007-05-08 17:22:03 +0200388 int nr = attr->index; \
Christian Hohnstaedt5bfedac2007-08-16 11:40:10 +0200389 long val; \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 \
391 val = simple_strtol(buf, NULL, 10); \
392 \
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100393 mutex_lock(&data->update_lock); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 \
395 if (nr >= 2) { /* TEMP2 and TEMP3 */ \
396 data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \
Jean Delvare31b8dc42007-05-08 17:22:03 +0200397 w83781d_write_value(data, W83781D_REG_TEMP_##REG(nr), \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 data->temp_##reg##_add[nr-2]); \
399 } else { /* TEMP1 */ \
400 data->temp_##reg = TEMP_TO_REG(val); \
Jean Delvare31b8dc42007-05-08 17:22:03 +0200401 w83781d_write_value(data, W83781D_REG_TEMP_##REG(nr), \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 data->temp_##reg); \
403 } \
404 \
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100405 mutex_unlock(&data->update_lock); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 return count; \
407}
408store_temp_reg(OVER, max);
409store_temp_reg(HYST, max_hyst);
410
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411#define sysfs_temp_offsets(offset) \
Jean Delvare34875332007-05-08 17:22:03 +0200412static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
413 show_temp, NULL, offset); \
414static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \
415 show_temp_max, store_temp_max, offset); \
416static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \
417 show_temp_max_hyst, store_temp_max_hyst, offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418
419sysfs_temp_offsets(1);
420sysfs_temp_offsets(2);
421sysfs_temp_offsets(3);
422
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423static ssize_t
Yani Ioannoue404e272005-05-17 06:42:58 -0400424show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425{
426 struct w83781d_data *data = w83781d_update_device(dev);
427 return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
428}
429
Jim Cromie311ce2e2006-09-24 21:22:52 +0200430static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
431
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432static ssize_t
Yani Ioannoue404e272005-05-17 06:42:58 -0400433show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434{
Jean Delvare90d66192007-10-08 18:24:35 +0200435 struct w83781d_data *data = dev_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 return sprintf(buf, "%ld\n", (long) data->vrm);
437}
438
439static ssize_t
Yani Ioannoue404e272005-05-17 06:42:58 -0400440store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441{
Jean Delvare7666c132007-05-08 17:22:02 +0200442 struct w83781d_data *data = dev_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 u32 val;
444
445 val = simple_strtoul(buf, NULL, 10);
446 data->vrm = val;
447
448 return count;
449}
450
Jim Cromie311ce2e2006-09-24 21:22:52 +0200451static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
452
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453static ssize_t
Yani Ioannoue404e272005-05-17 06:42:58 -0400454show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455{
456 struct w83781d_data *data = w83781d_update_device(dev);
Jean Delvare68188ba2005-05-16 18:52:38 +0200457 return sprintf(buf, "%u\n", data->alarms);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458}
459
Jim Cromie311ce2e2006-09-24 21:22:52 +0200460static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
461
Jean Delvare7d4a1372007-10-08 18:29:43 +0200462static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
463 char *buf)
464{
465 struct w83781d_data *data = w83781d_update_device(dev);
466 int bitnr = to_sensor_dev_attr(attr)->index;
467 return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
468}
469
470/* The W83781D has a single alarm bit for temp2 and temp3 */
471static ssize_t show_temp3_alarm(struct device *dev,
472 struct device_attribute *attr, char *buf)
473{
474 struct w83781d_data *data = w83781d_update_device(dev);
475 int bitnr = (data->type == w83781d) ? 5 : 13;
476 return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
477}
478
479static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
480static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
481static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
482static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
483static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8);
484static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9);
485static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 10);
486static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 16);
487static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 17);
488static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6);
489static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7);
490static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11);
491static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4);
492static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5);
493static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_temp3_alarm, NULL, 0);
494
Yani Ioannoue404e272005-05-17 06:42:58 -0400495static ssize_t show_beep_mask (struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496{
497 struct w83781d_data *data = w83781d_update_device(dev);
498 return sprintf(buf, "%ld\n",
499 (long)BEEP_MASK_FROM_REG(data->beep_mask, data->type));
500}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502static ssize_t
Jean Delvare34875332007-05-08 17:22:03 +0200503store_beep_mask(struct device *dev, struct device_attribute *attr,
504 const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505{
Jean Delvare7666c132007-05-08 17:22:02 +0200506 struct w83781d_data *data = dev_get_drvdata(dev);
Jean Delvare34875332007-05-08 17:22:03 +0200507 u32 val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508
509 val = simple_strtoul(buf, NULL, 10);
510
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100511 mutex_lock(&data->update_lock);
Jean Delvare2fbbbf12008-10-17 17:51:18 +0200512 data->beep_mask &= 0x8000; /* preserve beep enable */
513 data->beep_mask |= BEEP_MASK_TO_REG(val, data->type);
Jean Delvare34875332007-05-08 17:22:03 +0200514 w83781d_write_value(data, W83781D_REG_BEEP_INTS1,
515 data->beep_mask & 0xff);
Jean Delvare31b8dc42007-05-08 17:22:03 +0200516 w83781d_write_value(data, W83781D_REG_BEEP_INTS2,
Jean Delvare2fbbbf12008-10-17 17:51:18 +0200517 (data->beep_mask >> 8) & 0xff);
Jean Delvare34875332007-05-08 17:22:03 +0200518 if (data->type != w83781d && data->type != as99127f) {
519 w83781d_write_value(data, W83781D_REG_BEEP_INTS3,
520 ((data->beep_mask) >> 16) & 0xff);
521 }
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100522 mutex_unlock(&data->update_lock);
Jean Delvare34875332007-05-08 17:22:03 +0200523
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 return count;
525}
526
Jean Delvare34875332007-05-08 17:22:03 +0200527static DEVICE_ATTR(beep_mask, S_IRUGO | S_IWUSR,
528 show_beep_mask, store_beep_mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529
Jean Delvare7d4a1372007-10-08 18:29:43 +0200530static ssize_t show_beep(struct device *dev, struct device_attribute *attr,
531 char *buf)
532{
533 struct w83781d_data *data = w83781d_update_device(dev);
534 int bitnr = to_sensor_dev_attr(attr)->index;
535 return sprintf(buf, "%u\n", (data->beep_mask >> bitnr) & 1);
536}
537
538static ssize_t
539store_beep(struct device *dev, struct device_attribute *attr,
540 const char *buf, size_t count)
541{
542 struct w83781d_data *data = dev_get_drvdata(dev);
543 int bitnr = to_sensor_dev_attr(attr)->index;
544 unsigned long bit;
545 u8 reg;
546
547 bit = simple_strtoul(buf, NULL, 10);
548 if (bit & ~1)
549 return -EINVAL;
550
551 mutex_lock(&data->update_lock);
552 if (bit)
553 data->beep_mask |= (1 << bitnr);
554 else
555 data->beep_mask &= ~(1 << bitnr);
556
557 if (bitnr < 8) {
558 reg = w83781d_read_value(data, W83781D_REG_BEEP_INTS1);
559 if (bit)
560 reg |= (1 << bitnr);
561 else
562 reg &= ~(1 << bitnr);
563 w83781d_write_value(data, W83781D_REG_BEEP_INTS1, reg);
564 } else if (bitnr < 16) {
565 reg = w83781d_read_value(data, W83781D_REG_BEEP_INTS2);
566 if (bit)
567 reg |= (1 << (bitnr - 8));
568 else
569 reg &= ~(1 << (bitnr - 8));
570 w83781d_write_value(data, W83781D_REG_BEEP_INTS2, reg);
571 } else {
572 reg = w83781d_read_value(data, W83781D_REG_BEEP_INTS3);
573 if (bit)
574 reg |= (1 << (bitnr - 16));
575 else
576 reg &= ~(1 << (bitnr - 16));
577 w83781d_write_value(data, W83781D_REG_BEEP_INTS3, reg);
578 }
579 mutex_unlock(&data->update_lock);
580
581 return count;
582}
583
584/* The W83781D has a single beep bit for temp2 and temp3 */
585static ssize_t show_temp3_beep(struct device *dev,
586 struct device_attribute *attr, char *buf)
587{
588 struct w83781d_data *data = w83781d_update_device(dev);
589 int bitnr = (data->type == w83781d) ? 5 : 13;
590 return sprintf(buf, "%u\n", (data->beep_mask >> bitnr) & 1);
591}
592
593static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR,
594 show_beep, store_beep, 0);
595static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO | S_IWUSR,
596 show_beep, store_beep, 1);
597static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO | S_IWUSR,
598 show_beep, store_beep, 2);
599static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO | S_IWUSR,
600 show_beep, store_beep, 3);
601static SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO | S_IWUSR,
602 show_beep, store_beep, 8);
603static SENSOR_DEVICE_ATTR(in5_beep, S_IRUGO | S_IWUSR,
604 show_beep, store_beep, 9);
605static SENSOR_DEVICE_ATTR(in6_beep, S_IRUGO | S_IWUSR,
606 show_beep, store_beep, 10);
607static SENSOR_DEVICE_ATTR(in7_beep, S_IRUGO | S_IWUSR,
608 show_beep, store_beep, 16);
609static SENSOR_DEVICE_ATTR(in8_beep, S_IRUGO | S_IWUSR,
610 show_beep, store_beep, 17);
611static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO | S_IWUSR,
612 show_beep, store_beep, 6);
613static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO | S_IWUSR,
614 show_beep, store_beep, 7);
615static SENSOR_DEVICE_ATTR(fan3_beep, S_IRUGO | S_IWUSR,
616 show_beep, store_beep, 11);
617static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR,
618 show_beep, store_beep, 4);
619static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO | S_IWUSR,
620 show_beep, store_beep, 5);
621static SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO,
622 show_temp3_beep, store_beep, 13);
Jean Delvare2fbbbf12008-10-17 17:51:18 +0200623static SENSOR_DEVICE_ATTR(beep_enable, S_IRUGO | S_IWUSR,
624 show_beep, store_beep, 15);
Jean Delvare7d4a1372007-10-08 18:29:43 +0200625
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626static ssize_t
Jean Delvare34875332007-05-08 17:22:03 +0200627show_fan_div(struct device *dev, struct device_attribute *da, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628{
Jean Delvare34875332007-05-08 17:22:03 +0200629 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 struct w83781d_data *data = w83781d_update_device(dev);
631 return sprintf(buf, "%ld\n",
Jean Delvare34875332007-05-08 17:22:03 +0200632 (long) DIV_FROM_REG(data->fan_div[attr->index]));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633}
634
635/* Note: we save and restore the fan minimum here, because its value is
636 determined in part by the fan divisor. This follows the principle of
Andreas Mohrd6e05ed2006-06-26 18:35:02 +0200637 least surprise; the user doesn't expect the fan minimum to change just
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 because the divisor changed. */
639static ssize_t
Jean Delvare34875332007-05-08 17:22:03 +0200640store_fan_div(struct device *dev, struct device_attribute *da,
641 const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642{
Jean Delvare34875332007-05-08 17:22:03 +0200643 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
Jean Delvare7666c132007-05-08 17:22:02 +0200644 struct w83781d_data *data = dev_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645 unsigned long min;
Jean Delvare34875332007-05-08 17:22:03 +0200646 int nr = attr->index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 u8 reg;
648 unsigned long val = simple_strtoul(buf, NULL, 10);
649
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100650 mutex_lock(&data->update_lock);
Jean Delvare293c0992007-11-30 23:52:44 +0100651
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 /* Save fan_min */
653 min = FAN_FROM_REG(data->fan_min[nr],
654 DIV_FROM_REG(data->fan_div[nr]));
655
656 data->fan_div[nr] = DIV_TO_REG(val, data->type);
657
Jean Delvare31b8dc42007-05-08 17:22:03 +0200658 reg = (w83781d_read_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 & (nr==0 ? 0xcf : 0x3f))
660 | ((data->fan_div[nr] & 0x03) << (nr==0 ? 4 : 6));
Jean Delvare31b8dc42007-05-08 17:22:03 +0200661 w83781d_write_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662
663 /* w83781d and as99127f don't have extended divisor bits */
664 if (data->type != w83781d && data->type != as99127f) {
Jean Delvare31b8dc42007-05-08 17:22:03 +0200665 reg = (w83781d_read_value(data, W83781D_REG_VBAT)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 & ~(1 << (5 + nr)))
667 | ((data->fan_div[nr] & 0x04) << (3 + nr));
Jean Delvare31b8dc42007-05-08 17:22:03 +0200668 w83781d_write_value(data, W83781D_REG_VBAT, reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669 }
670
671 /* Restore fan_min */
672 data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
Jean Delvare34875332007-05-08 17:22:03 +0200673 w83781d_write_value(data, W83781D_REG_FAN_MIN(nr), data->fan_min[nr]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100675 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 return count;
677}
678
Jean Delvare34875332007-05-08 17:22:03 +0200679static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR,
680 show_fan_div, store_fan_div, 0);
681static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR,
682 show_fan_div, store_fan_div, 1);
683static SENSOR_DEVICE_ATTR(fan3_div, S_IRUGO | S_IWUSR,
684 show_fan_div, store_fan_div, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686static ssize_t
Jean Delvare34875332007-05-08 17:22:03 +0200687show_pwm(struct device *dev, struct device_attribute *da, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688{
Jean Delvare34875332007-05-08 17:22:03 +0200689 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 struct w83781d_data *data = w83781d_update_device(dev);
Jean Delvare34875332007-05-08 17:22:03 +0200691 return sprintf(buf, "%d\n", (int)data->pwm[attr->index]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692}
693
694static ssize_t
Jean Delvare34875332007-05-08 17:22:03 +0200695show_pwm2_enable(struct device *dev, struct device_attribute *da, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696{
697 struct w83781d_data *data = w83781d_update_device(dev);
Jean Delvare34875332007-05-08 17:22:03 +0200698 return sprintf(buf, "%d\n", (int)data->pwm2_enable);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699}
700
701static ssize_t
Jean Delvare34875332007-05-08 17:22:03 +0200702store_pwm(struct device *dev, struct device_attribute *da, const char *buf,
703 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704{
Jean Delvare34875332007-05-08 17:22:03 +0200705 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
Jean Delvare7666c132007-05-08 17:22:02 +0200706 struct w83781d_data *data = dev_get_drvdata(dev);
Jean Delvare34875332007-05-08 17:22:03 +0200707 int nr = attr->index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 u32 val;
709
710 val = simple_strtoul(buf, NULL, 10);
711
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100712 mutex_lock(&data->update_lock);
Jean Delvare34875332007-05-08 17:22:03 +0200713 data->pwm[nr] = SENSORS_LIMIT(val, 0, 255);
714 w83781d_write_value(data, W83781D_REG_PWM[nr], data->pwm[nr]);
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100715 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716 return count;
717}
718
719static ssize_t
Jean Delvare34875332007-05-08 17:22:03 +0200720store_pwm2_enable(struct device *dev, struct device_attribute *da,
721 const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722{
Jean Delvare7666c132007-05-08 17:22:02 +0200723 struct w83781d_data *data = dev_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 u32 val, reg;
725
726 val = simple_strtoul(buf, NULL, 10);
727
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100728 mutex_lock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729
730 switch (val) {
731 case 0:
732 case 1:
Jean Delvare31b8dc42007-05-08 17:22:03 +0200733 reg = w83781d_read_value(data, W83781D_REG_PWMCLK12);
734 w83781d_write_value(data, W83781D_REG_PWMCLK12,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 (reg & 0xf7) | (val << 3));
736
Jean Delvare31b8dc42007-05-08 17:22:03 +0200737 reg = w83781d_read_value(data, W83781D_REG_BEEP_CONFIG);
738 w83781d_write_value(data, W83781D_REG_BEEP_CONFIG,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 (reg & 0xef) | (!val << 4));
740
Jean Delvare34875332007-05-08 17:22:03 +0200741 data->pwm2_enable = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 break;
743
744 default:
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100745 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 return -EINVAL;
747 }
748
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100749 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 return count;
751}
752
Jean Delvare34875332007-05-08 17:22:03 +0200753static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 0);
754static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 1);
755static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 2);
756static SENSOR_DEVICE_ATTR(pwm4, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 3);
757/* only PWM2 can be enabled/disabled */
758static DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR,
759 show_pwm2_enable, store_pwm2_enable);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761static ssize_t
Jean Delvare34875332007-05-08 17:22:03 +0200762show_sensor(struct device *dev, struct device_attribute *da, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763{
Jean Delvare34875332007-05-08 17:22:03 +0200764 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 struct w83781d_data *data = w83781d_update_device(dev);
Jean Delvare34875332007-05-08 17:22:03 +0200766 return sprintf(buf, "%d\n", (int)data->sens[attr->index]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767}
768
769static ssize_t
Jean Delvare34875332007-05-08 17:22:03 +0200770store_sensor(struct device *dev, struct device_attribute *da,
771 const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772{
Jean Delvare34875332007-05-08 17:22:03 +0200773 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
Jean Delvare7666c132007-05-08 17:22:02 +0200774 struct w83781d_data *data = dev_get_drvdata(dev);
Jean Delvare34875332007-05-08 17:22:03 +0200775 int nr = attr->index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 u32 val, tmp;
777
778 val = simple_strtoul(buf, NULL, 10);
779
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100780 mutex_lock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781
782 switch (val) {
783 case 1: /* PII/Celeron diode */
Jean Delvare31b8dc42007-05-08 17:22:03 +0200784 tmp = w83781d_read_value(data, W83781D_REG_SCFG1);
785 w83781d_write_value(data, W83781D_REG_SCFG1,
Jean Delvare34875332007-05-08 17:22:03 +0200786 tmp | BIT_SCFG1[nr]);
Jean Delvare31b8dc42007-05-08 17:22:03 +0200787 tmp = w83781d_read_value(data, W83781D_REG_SCFG2);
788 w83781d_write_value(data, W83781D_REG_SCFG2,
Jean Delvare34875332007-05-08 17:22:03 +0200789 tmp | BIT_SCFG2[nr]);
790 data->sens[nr] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791 break;
792 case 2: /* 3904 */
Jean Delvare31b8dc42007-05-08 17:22:03 +0200793 tmp = w83781d_read_value(data, W83781D_REG_SCFG1);
794 w83781d_write_value(data, W83781D_REG_SCFG1,
Jean Delvare34875332007-05-08 17:22:03 +0200795 tmp | BIT_SCFG1[nr]);
Jean Delvare31b8dc42007-05-08 17:22:03 +0200796 tmp = w83781d_read_value(data, W83781D_REG_SCFG2);
797 w83781d_write_value(data, W83781D_REG_SCFG2,
Jean Delvare34875332007-05-08 17:22:03 +0200798 tmp & ~BIT_SCFG2[nr]);
799 data->sens[nr] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 break;
Jean Delvareb26f9332007-08-16 14:30:01 +0200801 case W83781D_DEFAULT_BETA:
802 dev_warn(dev, "Sensor type %d is deprecated, please use 4 "
803 "instead\n", W83781D_DEFAULT_BETA);
804 /* fall through */
805 case 4: /* thermistor */
Jean Delvare31b8dc42007-05-08 17:22:03 +0200806 tmp = w83781d_read_value(data, W83781D_REG_SCFG1);
807 w83781d_write_value(data, W83781D_REG_SCFG1,
Jean Delvare34875332007-05-08 17:22:03 +0200808 tmp & ~BIT_SCFG1[nr]);
809 data->sens[nr] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 break;
811 default:
Jean Delvareb26f9332007-08-16 14:30:01 +0200812 dev_err(dev, "Invalid sensor type %ld; must be 1, 2, or 4\n",
813 (long) val);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 break;
815 }
816
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100817 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818 return count;
819}
820
Jean Delvare34875332007-05-08 17:22:03 +0200821static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO | S_IWUSR,
822 show_sensor, store_sensor, 0);
823static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO | S_IWUSR,
Mark M. Hoffman393cdad2007-08-09 08:12:46 -0400824 show_sensor, store_sensor, 1);
Jean Delvare34875332007-05-08 17:22:03 +0200825static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO | S_IWUSR,
Mark M. Hoffman393cdad2007-08-09 08:12:46 -0400826 show_sensor, store_sensor, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828/* This function is called when:
829 * w83781d_driver is inserted (when this module is loaded), for each
830 available adapter
Jean Delvarec6566202008-10-17 17:51:18 +0200831 * when a new adapter is inserted (and w83781d_driver is still present)
832 We block updates of the ISA device to minimize the risk of concurrent
833 access to the same W83781D chip through different interfaces. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834static int
835w83781d_attach_adapter(struct i2c_adapter *adapter)
836{
Wolfgang Grandegger443850c2008-10-17 17:51:18 +0200837 struct w83781d_data *data = w83781d_data_if_isa();
Jean Delvarec6566202008-10-17 17:51:18 +0200838 int err;
839
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 if (!(adapter->class & I2C_CLASS_HWMON))
841 return 0;
Jean Delvarec6566202008-10-17 17:51:18 +0200842
Jean Delvarec6566202008-10-17 17:51:18 +0200843 if (data)
844 mutex_lock(&data->update_lock);
845 err = i2c_probe(adapter, &addr_data, w83781d_detect);
846 if (data)
847 mutex_unlock(&data->update_lock);
848 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849}
850
851/* Assumes that adapter is of I2C, not ISA variety.
852 * OTHERWISE DON'T CALL THIS
853 */
854static int
855w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
856 struct i2c_client *new_client)
857{
858 int i, val1 = 0, id;
859 int err;
860 const char *client_name = "";
861 struct w83781d_data *data = i2c_get_clientdata(new_client);
862
Deepak Saxenaba9c2e82005-10-17 23:08:32 +0200863 data->lm75[0] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 if (!(data->lm75[0])) {
865 err = -ENOMEM;
866 goto ERROR_SC_0;
867 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868
869 id = i2c_adapter_id(adapter);
870
871 if (force_subclients[0] == id && force_subclients[1] == address) {
872 for (i = 2; i <= 3; i++) {
873 if (force_subclients[i] < 0x48 ||
874 force_subclients[i] > 0x4f) {
875 dev_err(&new_client->dev, "Invalid subclient "
876 "address %d; must be 0x48-0x4f\n",
877 force_subclients[i]);
878 err = -EINVAL;
879 goto ERROR_SC_1;
880 }
881 }
Jean Delvare31b8dc42007-05-08 17:22:03 +0200882 w83781d_write_value(data, W83781D_REG_I2C_SUBADDR,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 (force_subclients[2] & 0x07) |
884 ((force_subclients[3] & 0x07) << 4));
885 data->lm75[0]->addr = force_subclients[2];
886 } else {
Jean Delvare31b8dc42007-05-08 17:22:03 +0200887 val1 = w83781d_read_value(data, W83781D_REG_I2C_SUBADDR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 data->lm75[0]->addr = 0x48 + (val1 & 0x07);
889 }
890
891 if (kind != w83783s) {
Deepak Saxenaba9c2e82005-10-17 23:08:32 +0200892 data->lm75[1] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 if (!(data->lm75[1])) {
894 err = -ENOMEM;
895 goto ERROR_SC_1;
896 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897
898 if (force_subclients[0] == id &&
899 force_subclients[1] == address) {
900 data->lm75[1]->addr = force_subclients[3];
901 } else {
902 data->lm75[1]->addr = 0x48 + ((val1 >> 4) & 0x07);
903 }
904 if (data->lm75[0]->addr == data->lm75[1]->addr) {
905 dev_err(&new_client->dev,
906 "Duplicate addresses 0x%x for subclients.\n",
907 data->lm75[0]->addr);
908 err = -EBUSY;
909 goto ERROR_SC_2;
910 }
911 }
912
913 if (kind == w83781d)
914 client_name = "w83781d subclient";
915 else if (kind == w83782d)
916 client_name = "w83782d subclient";
917 else if (kind == w83783s)
918 client_name = "w83783s subclient";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 else if (kind == as99127f)
920 client_name = "as99127f subclient";
921
922 for (i = 0; i <= 1; i++) {
923 /* store all data in w83781d */
924 i2c_set_clientdata(data->lm75[i], NULL);
925 data->lm75[i]->adapter = adapter;
926 data->lm75[i]->driver = &w83781d_driver;
927 data->lm75[i]->flags = 0;
928 strlcpy(data->lm75[i]->name, client_name,
929 I2C_NAME_SIZE);
930 if ((err = i2c_attach_client(data->lm75[i]))) {
931 dev_err(&new_client->dev, "Subclient %d "
932 "registration at address 0x%x "
933 "failed.\n", i, data->lm75[i]->addr);
934 if (i == 1)
935 goto ERROR_SC_3;
936 goto ERROR_SC_2;
937 }
938 if (kind == w83783s)
939 break;
940 }
941
942 return 0;
943
944/* Undo inits in case of errors */
945ERROR_SC_3:
946 i2c_detach_client(data->lm75[0]);
947ERROR_SC_2:
Jesper Juhl6044ec82005-11-07 01:01:32 -0800948 kfree(data->lm75[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949ERROR_SC_1:
Jesper Juhl6044ec82005-11-07 01:01:32 -0800950 kfree(data->lm75[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951ERROR_SC_0:
952 return err;
953}
954
Jean Delvare34875332007-05-08 17:22:03 +0200955#define IN_UNIT_ATTRS(X) \
956 &sensor_dev_attr_in##X##_input.dev_attr.attr, \
957 &sensor_dev_attr_in##X##_min.dev_attr.attr, \
Jean Delvare293c0992007-11-30 23:52:44 +0100958 &sensor_dev_attr_in##X##_max.dev_attr.attr, \
Jean Delvare7d4a1372007-10-08 18:29:43 +0200959 &sensor_dev_attr_in##X##_alarm.dev_attr.attr, \
960 &sensor_dev_attr_in##X##_beep.dev_attr.attr
Jim Cromie311ce2e2006-09-24 21:22:52 +0200961
Jean Delvare34875332007-05-08 17:22:03 +0200962#define FAN_UNIT_ATTRS(X) \
963 &sensor_dev_attr_fan##X##_input.dev_attr.attr, \
964 &sensor_dev_attr_fan##X##_min.dev_attr.attr, \
Jean Delvare7d4a1372007-10-08 18:29:43 +0200965 &sensor_dev_attr_fan##X##_div.dev_attr.attr, \
966 &sensor_dev_attr_fan##X##_alarm.dev_attr.attr, \
967 &sensor_dev_attr_fan##X##_beep.dev_attr.attr
Jim Cromie311ce2e2006-09-24 21:22:52 +0200968
Jean Delvare34875332007-05-08 17:22:03 +0200969#define TEMP_UNIT_ATTRS(X) \
970 &sensor_dev_attr_temp##X##_input.dev_attr.attr, \
971 &sensor_dev_attr_temp##X##_max.dev_attr.attr, \
Jean Delvare7d4a1372007-10-08 18:29:43 +0200972 &sensor_dev_attr_temp##X##_max_hyst.dev_attr.attr, \
973 &sensor_dev_attr_temp##X##_alarm.dev_attr.attr, \
974 &sensor_dev_attr_temp##X##_beep.dev_attr.attr
Jim Cromie311ce2e2006-09-24 21:22:52 +0200975
976static struct attribute* w83781d_attributes[] = {
977 IN_UNIT_ATTRS(0),
978 IN_UNIT_ATTRS(2),
979 IN_UNIT_ATTRS(3),
980 IN_UNIT_ATTRS(4),
981 IN_UNIT_ATTRS(5),
982 IN_UNIT_ATTRS(6),
983 FAN_UNIT_ATTRS(1),
984 FAN_UNIT_ATTRS(2),
985 FAN_UNIT_ATTRS(3),
986 TEMP_UNIT_ATTRS(1),
987 TEMP_UNIT_ATTRS(2),
988 &dev_attr_cpu0_vid.attr,
989 &dev_attr_vrm.attr,
990 &dev_attr_alarms.attr,
991 &dev_attr_beep_mask.attr,
Jean Delvare2fbbbf12008-10-17 17:51:18 +0200992 &sensor_dev_attr_beep_enable.dev_attr.attr,
Jim Cromie311ce2e2006-09-24 21:22:52 +0200993 NULL
994};
995static const struct attribute_group w83781d_group = {
996 .attrs = w83781d_attributes,
997};
998
999static struct attribute *w83781d_attributes_opt[] = {
1000 IN_UNIT_ATTRS(1),
1001 IN_UNIT_ATTRS(7),
1002 IN_UNIT_ATTRS(8),
1003 TEMP_UNIT_ATTRS(3),
Jean Delvare34875332007-05-08 17:22:03 +02001004 &sensor_dev_attr_pwm1.dev_attr.attr,
1005 &sensor_dev_attr_pwm2.dev_attr.attr,
1006 &sensor_dev_attr_pwm3.dev_attr.attr,
1007 &sensor_dev_attr_pwm4.dev_attr.attr,
Jim Cromie311ce2e2006-09-24 21:22:52 +02001008 &dev_attr_pwm2_enable.attr,
Jean Delvare34875332007-05-08 17:22:03 +02001009 &sensor_dev_attr_temp1_type.dev_attr.attr,
1010 &sensor_dev_attr_temp2_type.dev_attr.attr,
1011 &sensor_dev_attr_temp3_type.dev_attr.attr,
Jim Cromie311ce2e2006-09-24 21:22:52 +02001012 NULL
1013};
1014static const struct attribute_group w83781d_group_opt = {
1015 .attrs = w83781d_attributes_opt,
1016};
1017
Jean Delvare7666c132007-05-08 17:22:02 +02001018/* No clean up is done on error, it's up to the caller */
1019static int
1020w83781d_create_files(struct device *dev, int kind, int is_isa)
1021{
1022 int err;
1023
1024 if ((err = sysfs_create_group(&dev->kobj, &w83781d_group)))
1025 return err;
1026
1027 if (kind != w83783s) {
Jean Delvare34875332007-05-08 17:22:03 +02001028 if ((err = device_create_file(dev,
1029 &sensor_dev_attr_in1_input.dev_attr))
1030 || (err = device_create_file(dev,
1031 &sensor_dev_attr_in1_min.dev_attr))
1032 || (err = device_create_file(dev,
Jean Delvare7d4a1372007-10-08 18:29:43 +02001033 &sensor_dev_attr_in1_max.dev_attr))
1034 || (err = device_create_file(dev,
1035 &sensor_dev_attr_in1_alarm.dev_attr))
1036 || (err = device_create_file(dev,
1037 &sensor_dev_attr_in1_beep.dev_attr)))
Jean Delvare7666c132007-05-08 17:22:02 +02001038 return err;
1039 }
1040 if (kind != as99127f && kind != w83781d && kind != w83783s) {
Jean Delvare34875332007-05-08 17:22:03 +02001041 if ((err = device_create_file(dev,
1042 &sensor_dev_attr_in7_input.dev_attr))
1043 || (err = device_create_file(dev,
1044 &sensor_dev_attr_in7_min.dev_attr))
1045 || (err = device_create_file(dev,
1046 &sensor_dev_attr_in7_max.dev_attr))
1047 || (err = device_create_file(dev,
Jean Delvare7d4a1372007-10-08 18:29:43 +02001048 &sensor_dev_attr_in7_alarm.dev_attr))
1049 || (err = device_create_file(dev,
1050 &sensor_dev_attr_in7_beep.dev_attr))
1051 || (err = device_create_file(dev,
Jean Delvare34875332007-05-08 17:22:03 +02001052 &sensor_dev_attr_in8_input.dev_attr))
1053 || (err = device_create_file(dev,
1054 &sensor_dev_attr_in8_min.dev_attr))
1055 || (err = device_create_file(dev,
Jean Delvare7d4a1372007-10-08 18:29:43 +02001056 &sensor_dev_attr_in8_max.dev_attr))
1057 || (err = device_create_file(dev,
1058 &sensor_dev_attr_in8_alarm.dev_attr))
1059 || (err = device_create_file(dev,
1060 &sensor_dev_attr_in8_beep.dev_attr)))
Jean Delvare7666c132007-05-08 17:22:02 +02001061 return err;
1062 }
1063 if (kind != w83783s) {
Jean Delvare34875332007-05-08 17:22:03 +02001064 if ((err = device_create_file(dev,
1065 &sensor_dev_attr_temp3_input.dev_attr))
Jean Delvare7666c132007-05-08 17:22:02 +02001066 || (err = device_create_file(dev,
Jean Delvare34875332007-05-08 17:22:03 +02001067 &sensor_dev_attr_temp3_max.dev_attr))
1068 || (err = device_create_file(dev,
Jean Delvare7d4a1372007-10-08 18:29:43 +02001069 &sensor_dev_attr_temp3_max_hyst.dev_attr))
1070 || (err = device_create_file(dev,
1071 &sensor_dev_attr_temp3_alarm.dev_attr))
1072 || (err = device_create_file(dev,
1073 &sensor_dev_attr_temp3_beep.dev_attr)))
Jean Delvare7666c132007-05-08 17:22:02 +02001074 return err;
Jean Delvare7d4a1372007-10-08 18:29:43 +02001075
Jean Delvare7768aa72007-10-25 13:11:01 +02001076 if (kind != w83781d) {
Jean Delvare7d4a1372007-10-08 18:29:43 +02001077 err = sysfs_chmod_file(&dev->kobj,
1078 &sensor_dev_attr_temp3_alarm.dev_attr.attr,
1079 S_IRUGO | S_IWUSR);
1080 if (err)
1081 return err;
Jean Delvare7768aa72007-10-25 13:11:01 +02001082 }
Jean Delvare7666c132007-05-08 17:22:02 +02001083 }
1084
1085 if (kind != w83781d && kind != as99127f) {
Jean Delvare34875332007-05-08 17:22:03 +02001086 if ((err = device_create_file(dev,
1087 &sensor_dev_attr_pwm1.dev_attr))
1088 || (err = device_create_file(dev,
1089 &sensor_dev_attr_pwm2.dev_attr))
Jean Delvare7666c132007-05-08 17:22:02 +02001090 || (err = device_create_file(dev, &dev_attr_pwm2_enable)))
1091 return err;
1092 }
1093 if (kind == w83782d && !is_isa) {
Jean Delvare34875332007-05-08 17:22:03 +02001094 if ((err = device_create_file(dev,
1095 &sensor_dev_attr_pwm3.dev_attr))
1096 || (err = device_create_file(dev,
1097 &sensor_dev_attr_pwm4.dev_attr)))
Jean Delvare7666c132007-05-08 17:22:02 +02001098 return err;
1099 }
1100
1101 if (kind != as99127f && kind != w83781d) {
Jean Delvare34875332007-05-08 17:22:03 +02001102 if ((err = device_create_file(dev,
1103 &sensor_dev_attr_temp1_type.dev_attr))
Jean Delvare7666c132007-05-08 17:22:02 +02001104 || (err = device_create_file(dev,
Jean Delvare34875332007-05-08 17:22:03 +02001105 &sensor_dev_attr_temp2_type.dev_attr)))
Jean Delvare7666c132007-05-08 17:22:02 +02001106 return err;
1107 if (kind != w83783s) {
1108 if ((err = device_create_file(dev,
Jean Delvare34875332007-05-08 17:22:03 +02001109 &sensor_dev_attr_temp3_type.dev_attr)))
Jean Delvare7666c132007-05-08 17:22:02 +02001110 return err;
1111 }
1112 }
1113
Jean Delvare7666c132007-05-08 17:22:02 +02001114 return 0;
1115}
1116
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117static int
1118w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
1119{
Jean Delvare7666c132007-05-08 17:22:02 +02001120 int val1 = 0, val2;
Jim Cromie311ce2e2006-09-24 21:22:52 +02001121 struct i2c_client *client;
1122 struct device *dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 struct w83781d_data *data;
1124 int err;
1125 const char *client_name = "";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 enum vendor { winbond, asus } vendid;
1127
Jean Delvare7666c132007-05-08 17:22:02 +02001128 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129 err = -EINVAL;
Jean Delvare7666c132007-05-08 17:22:02 +02001130 goto ERROR1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 }
1132
1133 /* OK. For now, we presume we have a valid client. We now create the
1134 client structure, even though we cannot fill it completely yet.
1135 But it allows us to access w83781d_{read,write}_value. */
1136
Deepak Saxenaba9c2e82005-10-17 23:08:32 +02001137 if (!(data = kzalloc(sizeof(struct w83781d_data), GFP_KERNEL))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 err = -ENOMEM;
1139 goto ERROR1;
1140 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141
Jim Cromie311ce2e2006-09-24 21:22:52 +02001142 client = &data->client;
1143 i2c_set_clientdata(client, data);
1144 client->addr = address;
Ingo Molnar9a61bf62006-01-18 23:19:26 +01001145 mutex_init(&data->lock);
Jim Cromie311ce2e2006-09-24 21:22:52 +02001146 client->adapter = adapter;
Jean Delvare7666c132007-05-08 17:22:02 +02001147 client->driver = &w83781d_driver;
Jim Cromie311ce2e2006-09-24 21:22:52 +02001148 dev = &client->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149
1150 /* Now, we do the remaining detection. */
1151
1152 /* The w8378?d may be stuck in some other bank than bank 0. This may
1153 make reading other information impossible. Specify a force=... or
1154 force_*=... parameter, and the Winbond will be reset to the right
1155 bank. */
1156 if (kind < 0) {
Jean Delvare31b8dc42007-05-08 17:22:03 +02001157 if (w83781d_read_value(data, W83781D_REG_CONFIG) & 0x80) {
Jean Delvarebd452e62006-10-13 17:03:42 +02001158 dev_dbg(&adapter->dev, "Detection of w83781d chip "
1159 "failed at step 3\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 err = -ENODEV;
1161 goto ERROR2;
1162 }
Jean Delvare31b8dc42007-05-08 17:22:03 +02001163 val1 = w83781d_read_value(data, W83781D_REG_BANK);
1164 val2 = w83781d_read_value(data, W83781D_REG_CHIPMAN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 /* Check for Winbond or Asus ID if in bank 0 */
1166 if ((!(val1 & 0x07)) &&
1167 (((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3))
1168 || ((val1 & 0x80) && (val2 != 0x5c) && (val2 != 0x12)))) {
Jean Delvarebd452e62006-10-13 17:03:42 +02001169 dev_dbg(&adapter->dev, "Detection of w83781d chip "
1170 "failed at step 4\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 err = -ENODEV;
1172 goto ERROR2;
1173 }
1174 /* If Winbond SMBus, check address at 0x48.
1175 Asus doesn't support, except for as99127f rev.2 */
Jean Delvare7666c132007-05-08 17:22:02 +02001176 if ((!(val1 & 0x80) && (val2 == 0xa3)) ||
1177 ((val1 & 0x80) && (val2 == 0x5c))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 if (w83781d_read_value
Jean Delvare31b8dc42007-05-08 17:22:03 +02001179 (data, W83781D_REG_I2C_ADDR) != address) {
Jean Delvarebd452e62006-10-13 17:03:42 +02001180 dev_dbg(&adapter->dev, "Detection of w83781d "
1181 "chip failed at step 5\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 err = -ENODEV;
1183 goto ERROR2;
1184 }
1185 }
1186 }
1187
1188 /* We have either had a force parameter, or we have already detected the
1189 Winbond. Put it now into bank 0 and Vendor ID High Byte */
Jean Delvare31b8dc42007-05-08 17:22:03 +02001190 w83781d_write_value(data, W83781D_REG_BANK,
1191 (w83781d_read_value(data, W83781D_REG_BANK)
Jim Cromie311ce2e2006-09-24 21:22:52 +02001192 & 0x78) | 0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193
1194 /* Determine the chip type. */
1195 if (kind <= 0) {
1196 /* get vendor ID */
Jean Delvare31b8dc42007-05-08 17:22:03 +02001197 val2 = w83781d_read_value(data, W83781D_REG_CHIPMAN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 if (val2 == 0x5c)
1199 vendid = winbond;
1200 else if (val2 == 0x12)
1201 vendid = asus;
1202 else {
Jean Delvarebd452e62006-10-13 17:03:42 +02001203 dev_dbg(&adapter->dev, "w83781d chip vendor is "
1204 "neither Winbond nor Asus\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 err = -ENODEV;
1206 goto ERROR2;
1207 }
1208
Jean Delvare31b8dc42007-05-08 17:22:03 +02001209 val1 = w83781d_read_value(data, W83781D_REG_WCHIPID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210 if ((val1 == 0x10 || val1 == 0x11) && vendid == winbond)
1211 kind = w83781d;
1212 else if (val1 == 0x30 && vendid == winbond)
1213 kind = w83782d;
Jean Delvare7666c132007-05-08 17:22:02 +02001214 else if (val1 == 0x40 && vendid == winbond && address == 0x2d)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 kind = w83783s;
Jean Delvare6722fea2007-10-07 12:25:46 +02001216 else if (val1 == 0x31)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 kind = as99127f;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 else {
1219 if (kind == 0)
Jean Delvarebd452e62006-10-13 17:03:42 +02001220 dev_warn(&adapter->dev, "Ignoring 'force' "
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 "parameter for unknown chip at "
Jean Delvarebd452e62006-10-13 17:03:42 +02001222 "address 0x%02x\n", address);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 err = -EINVAL;
1224 goto ERROR2;
1225 }
Jean Delvarec6566202008-10-17 17:51:18 +02001226
1227 if ((kind == w83781d || kind == w83782d)
1228 && w83781d_alias_detect(client, val1)) {
1229 dev_dbg(&adapter->dev, "Device at 0x%02x appears to "
1230 "be the same as ISA device\n", address);
1231 err = -ENODEV;
1232 goto ERROR2;
1233 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 }
1235
1236 if (kind == w83781d) {
1237 client_name = "w83781d";
1238 } else if (kind == w83782d) {
1239 client_name = "w83782d";
1240 } else if (kind == w83783s) {
1241 client_name = "w83783s";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 } else if (kind == as99127f) {
1243 client_name = "as99127f";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 }
1245
1246 /* Fill in the remaining client fields and put into the global list */
Jim Cromie311ce2e2006-09-24 21:22:52 +02001247 strlcpy(client->name, client_name, I2C_NAME_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248 data->type = kind;
1249
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 /* Tell the I2C layer a new client has arrived */
Jim Cromie311ce2e2006-09-24 21:22:52 +02001251 if ((err = i2c_attach_client(client)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 goto ERROR2;
1253
1254 /* attach secondary i2c lm75-like clients */
Jean Delvare7666c132007-05-08 17:22:02 +02001255 if ((err = w83781d_detect_subclients(adapter, address,
1256 kind, client)))
1257 goto ERROR3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258
1259 /* Initialize the chip */
Jean Delvare7666c132007-05-08 17:22:02 +02001260 w83781d_init_device(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261
1262 /* Register sysfs hooks */
Jean Delvare7666c132007-05-08 17:22:02 +02001263 err = w83781d_create_files(dev, kind, 0);
1264 if (err)
Jim Cromie311ce2e2006-09-24 21:22:52 +02001265 goto ERROR4;
1266
Tony Jones1beeffe2007-08-20 13:46:20 -07001267 data->hwmon_dev = hwmon_device_register(dev);
1268 if (IS_ERR(data->hwmon_dev)) {
1269 err = PTR_ERR(data->hwmon_dev);
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001270 goto ERROR4;
1271 }
1272
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 return 0;
1274
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001275ERROR4:
Jim Cromie311ce2e2006-09-24 21:22:52 +02001276 sysfs_remove_group(&dev->kobj, &w83781d_group);
1277 sysfs_remove_group(&dev->kobj, &w83781d_group_opt);
1278
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001279 if (data->lm75[1]) {
1280 i2c_detach_client(data->lm75[1]);
1281 kfree(data->lm75[1]);
1282 }
1283 if (data->lm75[0]) {
1284 i2c_detach_client(data->lm75[0]);
1285 kfree(data->lm75[0]);
1286 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287ERROR3:
Jim Cromie311ce2e2006-09-24 21:22:52 +02001288 i2c_detach_client(client);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289ERROR2:
1290 kfree(data);
1291ERROR1:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 return err;
1293}
1294
1295static int
1296w83781d_detach_client(struct i2c_client *client)
1297{
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001298 struct w83781d_data *data = i2c_get_clientdata(client);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 int err;
1300
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001301 /* main client */
Jim Cromie311ce2e2006-09-24 21:22:52 +02001302 if (data) {
Tony Jones1beeffe2007-08-20 13:46:20 -07001303 hwmon_device_unregister(data->hwmon_dev);
Jim Cromie311ce2e2006-09-24 21:22:52 +02001304 sysfs_remove_group(&client->dev.kobj, &w83781d_group);
1305 sysfs_remove_group(&client->dev.kobj, &w83781d_group_opt);
1306 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307
Jean Delvare7bef5592005-07-27 22:14:49 +02001308 if ((err = i2c_detach_client(client)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001311 /* main client */
1312 if (data)
1313 kfree(data);
1314
1315 /* subclient */
1316 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 kfree(client);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318
1319 return 0;
1320}
1321
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322static int
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001323w83781d_read_value_i2c(struct w83781d_data *data, u16 reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324{
Jean Delvare31b8dc42007-05-08 17:22:03 +02001325 struct i2c_client *client = &data->client;
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001326 int res, bank;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 struct i2c_client *cl;
1328
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001329 bank = (reg >> 8) & 0x0f;
1330 if (bank > 2)
1331 /* switch banks */
1332 i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
1333 bank);
1334 if (bank == 0 || bank > 2) {
1335 res = i2c_smbus_read_byte_data(client, reg & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 } else {
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001337 /* switch to subclient */
1338 cl = data->lm75[bank - 1];
1339 /* convert from ISA to LM75 I2C addresses */
1340 switch (reg & 0xff) {
1341 case 0x50: /* TEMP */
1342 res = swab16(i2c_smbus_read_word_data(cl, 0));
1343 break;
1344 case 0x52: /* CONFIG */
1345 res = i2c_smbus_read_byte_data(cl, 1);
1346 break;
1347 case 0x53: /* HYST */
1348 res = swab16(i2c_smbus_read_word_data(cl, 2));
1349 break;
1350 case 0x55: /* OVER */
1351 default:
1352 res = swab16(i2c_smbus_read_word_data(cl, 3));
1353 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355 }
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001356 if (bank > 2)
1357 i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0);
1358
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 return res;
1360}
1361
1362static int
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001363w83781d_write_value_i2c(struct w83781d_data *data, u16 reg, u16 value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364{
Jean Delvare31b8dc42007-05-08 17:22:03 +02001365 struct i2c_client *client = &data->client;
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001366 int bank;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 struct i2c_client *cl;
1368
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001369 bank = (reg >> 8) & 0x0f;
1370 if (bank > 2)
1371 /* switch banks */
1372 i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
1373 bank);
1374 if (bank == 0 || bank > 2) {
1375 i2c_smbus_write_byte_data(client, reg & 0xff,
1376 value & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 } else {
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001378 /* switch to subclient */
1379 cl = data->lm75[bank - 1];
1380 /* convert from ISA to LM75 I2C addresses */
1381 switch (reg & 0xff) {
1382 case 0x52: /* CONFIG */
1383 i2c_smbus_write_byte_data(cl, 1, value & 0xff);
1384 break;
1385 case 0x53: /* HYST */
1386 i2c_smbus_write_word_data(cl, 2, swab16(value));
1387 break;
1388 case 0x55: /* OVER */
1389 i2c_smbus_write_word_data(cl, 3, swab16(value));
1390 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392 }
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001393 if (bank > 2)
1394 i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0);
1395
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396 return 0;
1397}
1398
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399static void
Jean Delvare7666c132007-05-08 17:22:02 +02001400w83781d_init_device(struct device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401{
Jean Delvare7666c132007-05-08 17:22:02 +02001402 struct w83781d_data *data = dev_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403 int i, p;
1404 int type = data->type;
1405 u8 tmp;
1406
Jean Delvarefabddcd2006-02-05 23:26:51 +01001407 if (reset && type != as99127f) { /* this resets registers we don't have
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 documentation for on the as99127f */
Jean Delvarefabddcd2006-02-05 23:26:51 +01001409 /* Resetting the chip has been the default for a long time,
1410 but it causes the BIOS initializations (fan clock dividers,
1411 thermal sensor types...) to be lost, so it is now optional.
1412 It might even go away if nobody reports it as being useful,
1413 as I see very little reason why this would be needed at
1414 all. */
Jean Delvare7666c132007-05-08 17:22:02 +02001415 dev_info(dev, "If reset=1 solved a problem you were "
Jean Delvarefabddcd2006-02-05 23:26:51 +01001416 "having, please report!\n");
1417
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 /* save these registers */
Jean Delvare31b8dc42007-05-08 17:22:03 +02001419 i = w83781d_read_value(data, W83781D_REG_BEEP_CONFIG);
1420 p = w83781d_read_value(data, W83781D_REG_PWMCLK12);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 /* Reset all except Watchdog values and last conversion values
1422 This sets fan-divs to 2, among others */
Jean Delvare31b8dc42007-05-08 17:22:03 +02001423 w83781d_write_value(data, W83781D_REG_CONFIG, 0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 /* Restore the registers and disable power-on abnormal beep.
1425 This saves FAN 1/2/3 input/output values set by BIOS. */
Jean Delvare31b8dc42007-05-08 17:22:03 +02001426 w83781d_write_value(data, W83781D_REG_BEEP_CONFIG, i | 0x80);
1427 w83781d_write_value(data, W83781D_REG_PWMCLK12, p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 /* Disable master beep-enable (reset turns it on).
1429 Individual beep_mask should be reset to off but for some reason
1430 disabling this bit helps some people not get beeped */
Jean Delvare31b8dc42007-05-08 17:22:03 +02001431 w83781d_write_value(data, W83781D_REG_BEEP_INTS2, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432 }
1433
Jean Delvarefabddcd2006-02-05 23:26:51 +01001434 /* Disable power-on abnormal beep, as advised by the datasheet.
1435 Already done if reset=1. */
1436 if (init && !reset && type != as99127f) {
Jean Delvare31b8dc42007-05-08 17:22:03 +02001437 i = w83781d_read_value(data, W83781D_REG_BEEP_CONFIG);
1438 w83781d_write_value(data, W83781D_REG_BEEP_CONFIG, i | 0x80);
Jean Delvarefabddcd2006-02-05 23:26:51 +01001439 }
1440
Jean Delvare303760b2005-07-31 21:52:01 +02001441 data->vrm = vid_which_vrm();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442
1443 if ((type != w83781d) && (type != as99127f)) {
Jean Delvare31b8dc42007-05-08 17:22:03 +02001444 tmp = w83781d_read_value(data, W83781D_REG_SCFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 for (i = 1; i <= 3; i++) {
1446 if (!(tmp & BIT_SCFG1[i - 1])) {
Jean Delvareb26f9332007-08-16 14:30:01 +02001447 data->sens[i - 1] = 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448 } else {
1449 if (w83781d_read_value
Jean Delvare31b8dc42007-05-08 17:22:03 +02001450 (data,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451 W83781D_REG_SCFG2) & BIT_SCFG2[i - 1])
1452 data->sens[i - 1] = 1;
1453 else
1454 data->sens[i - 1] = 2;
1455 }
Jean Delvare7c7a5302005-06-16 19:24:14 +02001456 if (type == w83783s && i == 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457 break;
1458 }
1459 }
1460
1461 if (init && type != as99127f) {
1462 /* Enable temp2 */
Jean Delvare31b8dc42007-05-08 17:22:03 +02001463 tmp = w83781d_read_value(data, W83781D_REG_TEMP2_CONFIG);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464 if (tmp & 0x01) {
Jean Delvare7666c132007-05-08 17:22:02 +02001465 dev_warn(dev, "Enabling temp2, readings "
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 "might not make sense\n");
Jean Delvare31b8dc42007-05-08 17:22:03 +02001467 w83781d_write_value(data, W83781D_REG_TEMP2_CONFIG,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 tmp & 0xfe);
1469 }
1470
1471 /* Enable temp3 */
Jean Delvare7c7a5302005-06-16 19:24:14 +02001472 if (type != w83783s) {
Jean Delvare31b8dc42007-05-08 17:22:03 +02001473 tmp = w83781d_read_value(data,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 W83781D_REG_TEMP3_CONFIG);
1475 if (tmp & 0x01) {
Jean Delvare7666c132007-05-08 17:22:02 +02001476 dev_warn(dev, "Enabling temp3, "
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477 "readings might not make sense\n");
Jean Delvare31b8dc42007-05-08 17:22:03 +02001478 w83781d_write_value(data,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 W83781D_REG_TEMP3_CONFIG, tmp & 0xfe);
1480 }
1481 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482 }
1483
1484 /* Start monitoring */
Jean Delvare31b8dc42007-05-08 17:22:03 +02001485 w83781d_write_value(data, W83781D_REG_CONFIG,
1486 (w83781d_read_value(data,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 W83781D_REG_CONFIG) & 0xf7)
1488 | 0x01);
Jean Delvare7666c132007-05-08 17:22:02 +02001489
1490 /* A few vars need to be filled upon startup */
Jean Delvare34875332007-05-08 17:22:03 +02001491 for (i = 0; i < 3; i++) {
1492 data->fan_min[i] = w83781d_read_value(data,
Jean Delvare7666c132007-05-08 17:22:02 +02001493 W83781D_REG_FAN_MIN(i));
1494 }
Jean Delvare7666c132007-05-08 17:22:02 +02001495
1496 mutex_init(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497}
1498
1499static struct w83781d_data *w83781d_update_device(struct device *dev)
1500{
Jean Delvare7666c132007-05-08 17:22:02 +02001501 struct w83781d_data *data = dev_get_drvdata(dev);
1502 struct i2c_client *client = &data->client;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503 int i;
1504
Ingo Molnar9a61bf62006-01-18 23:19:26 +01001505 mutex_lock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506
1507 if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
1508 || !data->valid) {
1509 dev_dbg(dev, "Starting device update\n");
1510
1511 for (i = 0; i <= 8; i++) {
Jean Delvare7c7a5302005-06-16 19:24:14 +02001512 if (data->type == w83783s && i == 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513 continue; /* 783S has no in1 */
1514 data->in[i] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001515 w83781d_read_value(data, W83781D_REG_IN(i));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516 data->in_min[i] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001517 w83781d_read_value(data, W83781D_REG_IN_MIN(i));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518 data->in_max[i] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001519 w83781d_read_value(data, W83781D_REG_IN_MAX(i));
Jean Delvare05663362007-11-30 23:51:24 +01001520 if ((data->type != w83782d) && (i == 6))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 break;
1522 }
Jean Delvare34875332007-05-08 17:22:03 +02001523 for (i = 0; i < 3; i++) {
1524 data->fan[i] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001525 w83781d_read_value(data, W83781D_REG_FAN(i));
Jean Delvare34875332007-05-08 17:22:03 +02001526 data->fan_min[i] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001527 w83781d_read_value(data, W83781D_REG_FAN_MIN(i));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 }
1529 if (data->type != w83781d && data->type != as99127f) {
Jean Delvare34875332007-05-08 17:22:03 +02001530 for (i = 0; i < 4; i++) {
1531 data->pwm[i] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001532 w83781d_read_value(data,
Jean Delvare34875332007-05-08 17:22:03 +02001533 W83781D_REG_PWM[i]);
Jean Delvare7666c132007-05-08 17:22:02 +02001534 if ((data->type != w83782d || !client->driver)
Jean Delvare34875332007-05-08 17:22:03 +02001535 && i == 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536 break;
1537 }
1538 /* Only PWM2 can be disabled */
Jean Delvare34875332007-05-08 17:22:03 +02001539 data->pwm2_enable = (w83781d_read_value(data,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 W83781D_REG_PWMCLK12) & 0x08) >> 3;
1541 }
1542
Jean Delvare31b8dc42007-05-08 17:22:03 +02001543 data->temp = w83781d_read_value(data, W83781D_REG_TEMP(1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544 data->temp_max =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001545 w83781d_read_value(data, W83781D_REG_TEMP_OVER(1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 data->temp_max_hyst =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001547 w83781d_read_value(data, W83781D_REG_TEMP_HYST(1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 data->temp_add[0] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001549 w83781d_read_value(data, W83781D_REG_TEMP(2));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550 data->temp_max_add[0] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001551 w83781d_read_value(data, W83781D_REG_TEMP_OVER(2));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 data->temp_max_hyst_add[0] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001553 w83781d_read_value(data, W83781D_REG_TEMP_HYST(2));
Jean Delvare7c7a5302005-06-16 19:24:14 +02001554 if (data->type != w83783s) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555 data->temp_add[1] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001556 w83781d_read_value(data, W83781D_REG_TEMP(3));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557 data->temp_max_add[1] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001558 w83781d_read_value(data,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559 W83781D_REG_TEMP_OVER(3));
1560 data->temp_max_hyst_add[1] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001561 w83781d_read_value(data,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562 W83781D_REG_TEMP_HYST(3));
1563 }
Jean Delvare31b8dc42007-05-08 17:22:03 +02001564 i = w83781d_read_value(data, W83781D_REG_VID_FANDIV);
Jean Delvare7c7a5302005-06-16 19:24:14 +02001565 data->vid = i & 0x0f;
Jean Delvare31b8dc42007-05-08 17:22:03 +02001566 data->vid |= (w83781d_read_value(data,
Jean Delvare7c7a5302005-06-16 19:24:14 +02001567 W83781D_REG_CHIPID) & 0x01) << 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568 data->fan_div[0] = (i >> 4) & 0x03;
1569 data->fan_div[1] = (i >> 6) & 0x03;
Jean Delvare31b8dc42007-05-08 17:22:03 +02001570 data->fan_div[2] = (w83781d_read_value(data,
Jean Delvare7c7a5302005-06-16 19:24:14 +02001571 W83781D_REG_PIN) >> 6) & 0x03;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572 if ((data->type != w83781d) && (data->type != as99127f)) {
Jean Delvare31b8dc42007-05-08 17:22:03 +02001573 i = w83781d_read_value(data, W83781D_REG_VBAT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574 data->fan_div[0] |= (i >> 3) & 0x04;
1575 data->fan_div[1] |= (i >> 4) & 0x04;
Jean Delvare7c7a5302005-06-16 19:24:14 +02001576 data->fan_div[2] |= (i >> 5) & 0x04;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577 }
Jean Delvare05663362007-11-30 23:51:24 +01001578 if (data->type == w83782d) {
Jean Delvare31b8dc42007-05-08 17:22:03 +02001579 data->alarms = w83781d_read_value(data,
Jean Delvarec7f5d7e2006-02-05 23:13:48 +01001580 W83782D_REG_ALARM1)
Jean Delvare31b8dc42007-05-08 17:22:03 +02001581 | (w83781d_read_value(data,
Jean Delvarec7f5d7e2006-02-05 23:13:48 +01001582 W83782D_REG_ALARM2) << 8)
Jean Delvare31b8dc42007-05-08 17:22:03 +02001583 | (w83781d_read_value(data,
Jean Delvarec7f5d7e2006-02-05 23:13:48 +01001584 W83782D_REG_ALARM3) << 16);
1585 } else if (data->type == w83783s) {
Jean Delvare31b8dc42007-05-08 17:22:03 +02001586 data->alarms = w83781d_read_value(data,
Jean Delvarec7f5d7e2006-02-05 23:13:48 +01001587 W83782D_REG_ALARM1)
Jean Delvare31b8dc42007-05-08 17:22:03 +02001588 | (w83781d_read_value(data,
Jean Delvarec7f5d7e2006-02-05 23:13:48 +01001589 W83782D_REG_ALARM2) << 8);
1590 } else {
1591 /* No real-time status registers, fall back to
1592 interrupt status registers */
Jean Delvare31b8dc42007-05-08 17:22:03 +02001593 data->alarms = w83781d_read_value(data,
Jean Delvarec7f5d7e2006-02-05 23:13:48 +01001594 W83781D_REG_ALARM1)
Jean Delvare31b8dc42007-05-08 17:22:03 +02001595 | (w83781d_read_value(data,
Jean Delvarec7f5d7e2006-02-05 23:13:48 +01001596 W83781D_REG_ALARM2) << 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597 }
Jean Delvare31b8dc42007-05-08 17:22:03 +02001598 i = w83781d_read_value(data, W83781D_REG_BEEP_INTS2);
Jean Delvare2fbbbf12008-10-17 17:51:18 +02001599 data->beep_mask = (i << 8) +
Jean Delvare31b8dc42007-05-08 17:22:03 +02001600 w83781d_read_value(data, W83781D_REG_BEEP_INTS1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601 if ((data->type != w83781d) && (data->type != as99127f)) {
1602 data->beep_mask |=
Jean Delvare31b8dc42007-05-08 17:22:03 +02001603 w83781d_read_value(data,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604 W83781D_REG_BEEP_INTS3) << 16;
1605 }
1606 data->last_updated = jiffies;
1607 data->valid = 1;
1608 }
1609
Ingo Molnar9a61bf62006-01-18 23:19:26 +01001610 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611
1612 return data;
1613}
1614
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001615#ifdef CONFIG_ISA
1616
1617/* ISA device, if found */
1618static struct platform_device *pdev;
1619
1620static unsigned short isa_address = 0x290;
1621
1622/* I2C devices get this name attribute automatically, but for ISA devices
1623 we must create it by ourselves. */
1624static ssize_t
1625show_name(struct device *dev, struct device_attribute *devattr, char *buf)
1626{
1627 struct w83781d_data *data = dev_get_drvdata(dev);
1628 return sprintf(buf, "%s\n", data->client.name);
1629}
1630static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
1631
1632static struct w83781d_data *w83781d_data_if_isa(void)
1633{
1634 return pdev ? platform_get_drvdata(pdev) : NULL;
1635}
1636
1637/* Returns 1 if the I2C chip appears to be an alias of the ISA chip */
1638static int w83781d_alias_detect(struct i2c_client *client, u8 chipid)
1639{
1640 struct w83781d_data *i2c, *isa;
1641 int i;
1642
1643 if (!pdev) /* No ISA chip */
1644 return 0;
1645
1646 i2c = i2c_get_clientdata(client);
1647 isa = platform_get_drvdata(pdev);
1648
1649 if (w83781d_read_value(isa, W83781D_REG_I2C_ADDR) != client->addr)
1650 return 0; /* Address doesn't match */
1651 if (w83781d_read_value(isa, W83781D_REG_WCHIPID) != chipid)
1652 return 0; /* Chip type doesn't match */
1653
1654 /* We compare all the limit registers, the config register and the
1655 * interrupt mask registers */
1656 for (i = 0x2b; i <= 0x3d; i++) {
1657 if (w83781d_read_value(isa, i) != w83781d_read_value(i2c, i))
1658 return 0;
1659 }
1660 if (w83781d_read_value(isa, W83781D_REG_CONFIG) !=
1661 w83781d_read_value(i2c, W83781D_REG_CONFIG))
1662 return 0;
1663 for (i = 0x43; i <= 0x46; i++) {
1664 if (w83781d_read_value(isa, i) != w83781d_read_value(i2c, i))
1665 return 0;
1666 }
1667
1668 return 1;
1669}
1670
1671static int
1672w83781d_read_value_isa(struct w83781d_data *data, u16 reg)
1673{
1674 struct i2c_client *client = &data->client;
1675 int word_sized, res;
1676
1677 word_sized = (((reg & 0xff00) == 0x100)
1678 || ((reg & 0xff00) == 0x200))
1679 && (((reg & 0x00ff) == 0x50)
1680 || ((reg & 0x00ff) == 0x53)
1681 || ((reg & 0x00ff) == 0x55));
1682 if (reg & 0xff00) {
1683 outb_p(W83781D_REG_BANK,
1684 client->addr + W83781D_ADDR_REG_OFFSET);
1685 outb_p(reg >> 8,
1686 client->addr + W83781D_DATA_REG_OFFSET);
1687 }
1688 outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET);
1689 res = inb_p(client->addr + W83781D_DATA_REG_OFFSET);
1690 if (word_sized) {
1691 outb_p((reg & 0xff) + 1,
1692 client->addr + W83781D_ADDR_REG_OFFSET);
1693 res =
1694 (res << 8) + inb_p(client->addr +
1695 W83781D_DATA_REG_OFFSET);
1696 }
1697 if (reg & 0xff00) {
1698 outb_p(W83781D_REG_BANK,
1699 client->addr + W83781D_ADDR_REG_OFFSET);
1700 outb_p(0, client->addr + W83781D_DATA_REG_OFFSET);
1701 }
1702 return res;
1703}
1704
1705static void
1706w83781d_write_value_isa(struct w83781d_data *data, u16 reg, u16 value)
1707{
1708 struct i2c_client *client = &data->client;
1709 int word_sized;
1710
1711 word_sized = (((reg & 0xff00) == 0x100)
1712 || ((reg & 0xff00) == 0x200))
1713 && (((reg & 0x00ff) == 0x53)
1714 || ((reg & 0x00ff) == 0x55));
1715 if (reg & 0xff00) {
1716 outb_p(W83781D_REG_BANK,
1717 client->addr + W83781D_ADDR_REG_OFFSET);
1718 outb_p(reg >> 8,
1719 client->addr + W83781D_DATA_REG_OFFSET);
1720 }
1721 outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET);
1722 if (word_sized) {
1723 outb_p(value >> 8,
1724 client->addr + W83781D_DATA_REG_OFFSET);
1725 outb_p((reg & 0xff) + 1,
1726 client->addr + W83781D_ADDR_REG_OFFSET);
1727 }
1728 outb_p(value & 0xff, client->addr + W83781D_DATA_REG_OFFSET);
1729 if (reg & 0xff00) {
1730 outb_p(W83781D_REG_BANK,
1731 client->addr + W83781D_ADDR_REG_OFFSET);
1732 outb_p(0, client->addr + W83781D_DATA_REG_OFFSET);
1733 }
1734}
1735
1736/* The SMBus locks itself, usually, but nothing may access the Winbond between
1737 bank switches. ISA access must always be locked explicitly!
1738 We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks,
1739 would slow down the W83781D access and should not be necessary.
1740 There are some ugly typecasts here, but the good news is - they should
1741 nowhere else be necessary! */
1742static int
1743w83781d_read_value(struct w83781d_data *data, u16 reg)
1744{
1745 struct i2c_client *client = &data->client;
1746 int res;
1747
1748 mutex_lock(&data->lock);
1749 if (client->driver)
1750 res = w83781d_read_value_i2c(data, reg);
1751 else
1752 res = w83781d_read_value_isa(data, reg);
1753 mutex_unlock(&data->lock);
1754 return res;
1755}
1756
1757static int
1758w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value)
1759{
1760 struct i2c_client *client = &data->client;
1761
1762 mutex_lock(&data->lock);
1763 if (client->driver)
1764 w83781d_write_value_i2c(data, reg, value);
1765 else
1766 w83781d_write_value_isa(data, reg, value);
1767 mutex_unlock(&data->lock);
1768 return 0;
1769}
1770
1771static int __devinit
1772w83781d_isa_probe(struct platform_device *pdev)
1773{
1774 int err, reg;
1775 struct w83781d_data *data;
1776 struct resource *res;
1777 const char *name;
1778
1779 /* Reserve the ISA region */
1780 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
1781 if (!request_region(res->start + W83781D_ADDR_REG_OFFSET, 2,
1782 "w83781d")) {
1783 err = -EBUSY;
1784 goto exit;
1785 }
1786
1787 data = kzalloc(sizeof(struct w83781d_data), GFP_KERNEL);
1788 if (!data) {
1789 err = -ENOMEM;
1790 goto exit_release_region;
1791 }
1792 mutex_init(&data->lock);
1793 data->client.addr = res->start;
1794 i2c_set_clientdata(&data->client, data);
1795 platform_set_drvdata(pdev, data);
1796
1797 reg = w83781d_read_value(data, W83781D_REG_WCHIPID);
1798 switch (reg) {
1799 case 0x30:
1800 data->type = w83782d;
1801 name = "w83782d";
1802 break;
1803 default:
1804 data->type = w83781d;
1805 name = "w83781d";
1806 }
1807 strlcpy(data->client.name, name, I2C_NAME_SIZE);
1808
1809 /* Initialize the W83781D chip */
1810 w83781d_init_device(&pdev->dev);
1811
1812 /* Register sysfs hooks */
1813 err = w83781d_create_files(&pdev->dev, data->type, 1);
1814 if (err)
1815 goto exit_remove_files;
1816
1817 err = device_create_file(&pdev->dev, &dev_attr_name);
1818 if (err)
1819 goto exit_remove_files;
1820
1821 data->hwmon_dev = hwmon_device_register(&pdev->dev);
1822 if (IS_ERR(data->hwmon_dev)) {
1823 err = PTR_ERR(data->hwmon_dev);
1824 goto exit_remove_files;
1825 }
1826
1827 return 0;
1828
1829 exit_remove_files:
1830 sysfs_remove_group(&pdev->dev.kobj, &w83781d_group);
1831 sysfs_remove_group(&pdev->dev.kobj, &w83781d_group_opt);
1832 device_remove_file(&pdev->dev, &dev_attr_name);
1833 kfree(data);
1834 exit_release_region:
1835 release_region(res->start + W83781D_ADDR_REG_OFFSET, 2);
1836 exit:
1837 return err;
1838}
1839
1840static int __devexit
1841w83781d_isa_remove(struct platform_device *pdev)
1842{
1843 struct w83781d_data *data = platform_get_drvdata(pdev);
1844
1845 hwmon_device_unregister(data->hwmon_dev);
1846 sysfs_remove_group(&pdev->dev.kobj, &w83781d_group);
1847 sysfs_remove_group(&pdev->dev.kobj, &w83781d_group_opt);
1848 device_remove_file(&pdev->dev, &dev_attr_name);
1849 release_region(data->client.addr + W83781D_ADDR_REG_OFFSET, 2);
1850 kfree(data);
1851
1852 return 0;
1853}
1854
1855static struct platform_driver w83781d_isa_driver = {
1856 .driver = {
1857 .owner = THIS_MODULE,
1858 .name = "w83781d",
1859 },
1860 .probe = w83781d_isa_probe,
1861 .remove = __devexit_p(w83781d_isa_remove),
1862};
1863
Jean Delvare7666c132007-05-08 17:22:02 +02001864/* return 1 if a supported chip is found, 0 otherwise */
1865static int __init
1866w83781d_isa_found(unsigned short address)
1867{
1868 int val, save, found = 0;
1869
Jean Delvare2961cb22008-03-09 13:34:28 +01001870 /* We have to request the region in two parts because some
1871 boards declare base+4 to base+7 as a PNP device */
1872 if (!request_region(address, 4, "w83781d")) {
1873 pr_debug("w83781d: Failed to request low part of region\n");
Jean Delvare7666c132007-05-08 17:22:02 +02001874 return 0;
Jean Delvare2961cb22008-03-09 13:34:28 +01001875 }
1876 if (!request_region(address + 4, 4, "w83781d")) {
1877 pr_debug("w83781d: Failed to request high part of region\n");
1878 release_region(address, 4);
1879 return 0;
1880 }
Jean Delvare7666c132007-05-08 17:22:02 +02001881
1882#define REALLY_SLOW_IO
1883 /* We need the timeouts for at least some W83781D-like
1884 chips. But only if we read 'undefined' registers. */
1885 val = inb_p(address + 1);
1886 if (inb_p(address + 2) != val
1887 || inb_p(address + 3) != val
1888 || inb_p(address + 7) != val) {
1889 pr_debug("w83781d: Detection failed at step 1\n");
1890 goto release;
1891 }
1892#undef REALLY_SLOW_IO
1893
1894 /* We should be able to change the 7 LSB of the address port. The
1895 MSB (busy flag) should be clear initially, set after the write. */
1896 save = inb_p(address + W83781D_ADDR_REG_OFFSET);
1897 if (save & 0x80) {
1898 pr_debug("w83781d: Detection failed at step 2\n");
1899 goto release;
1900 }
1901 val = ~save & 0x7f;
1902 outb_p(val, address + W83781D_ADDR_REG_OFFSET);
1903 if (inb_p(address + W83781D_ADDR_REG_OFFSET) != (val | 0x80)) {
1904 outb_p(save, address + W83781D_ADDR_REG_OFFSET);
1905 pr_debug("w83781d: Detection failed at step 3\n");
1906 goto release;
1907 }
1908
1909 /* We found a device, now see if it could be a W83781D */
1910 outb_p(W83781D_REG_CONFIG, address + W83781D_ADDR_REG_OFFSET);
1911 val = inb_p(address + W83781D_DATA_REG_OFFSET);
1912 if (val & 0x80) {
1913 pr_debug("w83781d: Detection failed at step 4\n");
1914 goto release;
1915 }
1916 outb_p(W83781D_REG_BANK, address + W83781D_ADDR_REG_OFFSET);
1917 save = inb_p(address + W83781D_DATA_REG_OFFSET);
1918 outb_p(W83781D_REG_CHIPMAN, address + W83781D_ADDR_REG_OFFSET);
1919 val = inb_p(address + W83781D_DATA_REG_OFFSET);
1920 if ((!(save & 0x80) && (val != 0xa3))
1921 || ((save & 0x80) && (val != 0x5c))) {
1922 pr_debug("w83781d: Detection failed at step 5\n");
1923 goto release;
1924 }
1925 outb_p(W83781D_REG_I2C_ADDR, address + W83781D_ADDR_REG_OFFSET);
1926 val = inb_p(address + W83781D_DATA_REG_OFFSET);
1927 if (val < 0x03 || val > 0x77) { /* Not a valid I2C address */
1928 pr_debug("w83781d: Detection failed at step 6\n");
1929 goto release;
1930 }
1931
1932 /* The busy flag should be clear again */
1933 if (inb_p(address + W83781D_ADDR_REG_OFFSET) & 0x80) {
1934 pr_debug("w83781d: Detection failed at step 7\n");
1935 goto release;
1936 }
1937
1938 /* Determine the chip type */
1939 outb_p(W83781D_REG_BANK, address + W83781D_ADDR_REG_OFFSET);
1940 save = inb_p(address + W83781D_DATA_REG_OFFSET);
1941 outb_p(save & 0xf8, address + W83781D_DATA_REG_OFFSET);
1942 outb_p(W83781D_REG_WCHIPID, address + W83781D_ADDR_REG_OFFSET);
1943 val = inb_p(address + W83781D_DATA_REG_OFFSET);
1944 if ((val & 0xfe) == 0x10 /* W83781D */
Jean Delvare05663362007-11-30 23:51:24 +01001945 || val == 0x30) /* W83782D */
Jean Delvare7666c132007-05-08 17:22:02 +02001946 found = 1;
1947
1948 if (found)
1949 pr_info("w83781d: Found a %s chip at %#x\n",
Jean Delvare7666c132007-05-08 17:22:02 +02001950 val == 0x30 ? "W83782D" : "W83781D", (int)address);
1951
1952 release:
Jean Delvare2961cb22008-03-09 13:34:28 +01001953 release_region(address + 4, 4);
1954 release_region(address, 4);
Jean Delvare7666c132007-05-08 17:22:02 +02001955 return found;
1956}
1957
1958static int __init
1959w83781d_isa_device_add(unsigned short address)
1960{
1961 struct resource res = {
1962 .start = address,
Jean Delvare15bde2f2007-08-29 10:39:57 +02001963 .end = address + W83781D_EXTENT - 1,
Jean Delvare7666c132007-05-08 17:22:02 +02001964 .name = "w83781d",
1965 .flags = IORESOURCE_IO,
1966 };
1967 int err;
1968
1969 pdev = platform_device_alloc("w83781d", address);
1970 if (!pdev) {
1971 err = -ENOMEM;
1972 printk(KERN_ERR "w83781d: Device allocation failed\n");
1973 goto exit;
1974 }
1975
1976 err = platform_device_add_resources(pdev, &res, 1);
1977 if (err) {
1978 printk(KERN_ERR "w83781d: Device resource addition failed "
1979 "(%d)\n", err);
1980 goto exit_device_put;
1981 }
1982
1983 err = platform_device_add(pdev);
1984 if (err) {
1985 printk(KERN_ERR "w83781d: Device addition failed (%d)\n",
1986 err);
1987 goto exit_device_put;
1988 }
1989
1990 return 0;
1991
1992 exit_device_put:
1993 platform_device_put(pdev);
1994 exit:
1995 pdev = NULL;
1996 return err;
1997}
1998
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999static int __init
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02002000w83781d_isa_register(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001{
Jean Delvarefde09502005-07-19 23:51:07 +02002002 int res;
2003
Jean Delvare7666c132007-05-08 17:22:02 +02002004 if (w83781d_isa_found(isa_address)) {
2005 res = platform_driver_register(&w83781d_isa_driver);
2006 if (res)
Jean Delvarec6566202008-10-17 17:51:18 +02002007 goto exit;
Jean Delvare7666c132007-05-08 17:22:02 +02002008
2009 /* Sets global pdev as a side effect */
2010 res = w83781d_isa_device_add(isa_address);
2011 if (res)
2012 goto exit_unreg_isa_driver;
2013 }
Jean Delvarefde09502005-07-19 23:51:07 +02002014
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02002015 return 0;
2016
2017exit_unreg_isa_driver:
2018 platform_driver_unregister(&w83781d_isa_driver);
2019exit:
2020 return res;
2021}
2022
2023static void __exit
2024w83781d_isa_unregister(void)
2025{
2026 if (pdev) {
2027 platform_device_unregister(pdev);
2028 platform_driver_unregister(&w83781d_isa_driver);
2029 }
2030}
2031#else /* !CONFIG_ISA */
2032
2033static struct w83781d_data *w83781d_data_if_isa(void)
2034{
2035 return NULL;
2036}
2037
2038static int
2039w83781d_alias_detect(struct i2c_client *client, u8 chipid)
2040{
2041 return 0;
2042}
2043
2044static int
2045w83781d_read_value(struct w83781d_data *data, u16 reg)
2046{
2047 int res;
2048
2049 mutex_lock(&data->lock);
2050 res = w83781d_read_value_i2c(data, reg);
2051 mutex_unlock(&data->lock);
2052
2053 return res;
2054}
2055
2056static int
2057w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value)
2058{
2059 mutex_lock(&data->lock);
2060 w83781d_write_value_i2c(data, reg, value);
2061 mutex_unlock(&data->lock);
2062
2063 return 0;
2064}
2065
2066static int __init
2067w83781d_isa_register(void)
2068{
2069 return 0;
2070}
2071
2072static void __exit
2073w83781d_isa_unregister(void)
2074{
2075}
2076#endif /* CONFIG_ISA */
2077
2078static int __init
2079sensors_w83781d_init(void)
2080{
2081 int res;
2082
2083 /* We register the ISA device first, so that we can skip the
2084 * registration of an I2C interface to the same device. */
2085 res = w83781d_isa_register();
2086 if (res)
2087 goto exit;
2088
Jean Delvarec6566202008-10-17 17:51:18 +02002089 res = i2c_add_driver(&w83781d_driver);
2090 if (res)
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02002091 goto exit_unreg_isa;
Jean Delvarec6566202008-10-17 17:51:18 +02002092
Jean Delvarefde09502005-07-19 23:51:07 +02002093 return 0;
Jean Delvare7666c132007-05-08 17:22:02 +02002094
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02002095 exit_unreg_isa:
2096 w83781d_isa_unregister();
Jean Delvare7666c132007-05-08 17:22:02 +02002097 exit:
2098 return res;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002099}
2100
2101static void __exit
2102sensors_w83781d_exit(void)
2103{
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02002104 w83781d_isa_unregister();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 i2c_del_driver(&w83781d_driver);
2106}
2107
2108MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
2109 "Philip Edelbrock <phil@netroedge.com>, "
2110 "and Mark Studebaker <mdsxyz123@yahoo.com>");
2111MODULE_DESCRIPTION("W83781D driver");
2112MODULE_LICENSE("GPL");
2113
2114module_init(sensors_w83781d_init);
2115module_exit(sensors_w83781d_exit);