blob: 50580c883053ea9f6bf2852f3fcd311cb310ee31 [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>
Jean Delvare360782d2008-10-17 17:51:19 +02007 Copyright (c) 2007 - 2008 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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201struct w83781d_data {
202 struct i2c_client client;
Tony Jones1beeffe2007-08-20 13:46:20 -0700203 struct device *hwmon_dev;
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100204 struct mutex lock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205 enum chips type;
206
Jean Delvare360782d2008-10-17 17:51:19 +0200207 /* For ISA device only */
208 const char *name;
209 int isa_addr;
210
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100211 struct mutex update_lock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 char valid; /* !=0 if following fields are valid */
213 unsigned long last_updated; /* In jiffies */
214
215 struct i2c_client *lm75[2]; /* for secondary I2C addresses */
216 /* array of 2 pointers to subclients */
217
218 u8 in[9]; /* Register value - 8 & 9 for 782D only */
219 u8 in_max[9]; /* Register value - 8 & 9 for 782D only */
220 u8 in_min[9]; /* Register value - 8 & 9 for 782D only */
221 u8 fan[3]; /* Register value */
222 u8 fan_min[3]; /* Register value */
Jean Delvare474d00a2007-05-08 17:22:03 +0200223 s8 temp; /* Register value */
224 s8 temp_max; /* Register value */
225 s8 temp_max_hyst; /* Register value */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226 u16 temp_add[2]; /* Register value */
227 u16 temp_max_add[2]; /* Register value */
228 u16 temp_max_hyst_add[2]; /* Register value */
229 u8 fan_div[3]; /* Register encoding, shifted right */
230 u8 vid; /* Register encoding, combined */
231 u32 alarms; /* Register encoding, combined */
232 u32 beep_mask; /* Register encoding, combined */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 u8 pwm[4]; /* Register value */
Jean Delvare34875332007-05-08 17:22:03 +0200234 u8 pwm2_enable; /* Boolean */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 u16 sens[3]; /* 782D/783S only.
236 1 = pentium diode; 2 = 3904 diode;
Jean Delvareb26f9332007-08-16 14:30:01 +0200237 4 = thermistor */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 u8 vrm;
239};
240
Wolfgang Grandegger443850c2008-10-17 17:51:18 +0200241static struct w83781d_data *w83781d_data_if_isa(void);
242static int w83781d_alias_detect(struct i2c_client *client, u8 chipid);
243
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244static int w83781d_attach_adapter(struct i2c_adapter *adapter);
245static int w83781d_detect(struct i2c_adapter *adapter, int address, int kind);
246static int w83781d_detach_client(struct i2c_client *client);
247
Jean Delvare31b8dc42007-05-08 17:22:03 +0200248static int w83781d_read_value(struct w83781d_data *data, u16 reg);
249static int w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250static struct w83781d_data *w83781d_update_device(struct device *dev);
Jean Delvare7666c132007-05-08 17:22:02 +0200251static void w83781d_init_device(struct device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252
253static struct i2c_driver w83781d_driver = {
Laurent Riffardcdaf7932005-11-26 20:37:41 +0100254 .driver = {
Laurent Riffardcdaf7932005-11-26 20:37:41 +0100255 .name = "w83781d",
256 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 .attach_adapter = w83781d_attach_adapter,
258 .detach_client = w83781d_detach_client,
259};
260
261/* following are the sysfs callback functions */
262#define show_in_reg(reg) \
Jean Delvare34875332007-05-08 17:22:03 +0200263static ssize_t show_##reg (struct device *dev, struct device_attribute *da, \
264 char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265{ \
Jean Delvare34875332007-05-08 17:22:03 +0200266 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 struct w83781d_data *data = w83781d_update_device(dev); \
Jean Delvare34875332007-05-08 17:22:03 +0200268 return sprintf(buf, "%ld\n", \
269 (long)IN_FROM_REG(data->reg[attr->index])); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270}
271show_in_reg(in);
272show_in_reg(in_min);
273show_in_reg(in_max);
274
275#define store_in_reg(REG, reg) \
Jean Delvare34875332007-05-08 17:22:03 +0200276static ssize_t store_in_##reg (struct device *dev, struct device_attribute \
277 *da, const char *buf, size_t count) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278{ \
Jean Delvare34875332007-05-08 17:22:03 +0200279 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \
Jean Delvare7666c132007-05-08 17:22:02 +0200280 struct w83781d_data *data = dev_get_drvdata(dev); \
Jean Delvare34875332007-05-08 17:22:03 +0200281 int nr = attr->index; \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 u32 val; \
283 \
Jean Delvare474d00a2007-05-08 17:22:03 +0200284 val = simple_strtoul(buf, NULL, 10); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 \
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100286 mutex_lock(&data->update_lock); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 data->in_##reg[nr] = IN_TO_REG(val); \
Jean Delvare31b8dc42007-05-08 17:22:03 +0200288 w83781d_write_value(data, W83781D_REG_IN_##REG(nr), data->in_##reg[nr]); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289 \
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100290 mutex_unlock(&data->update_lock); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 return count; \
292}
293store_in_reg(MIN, min);
294store_in_reg(MAX, max);
295
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296#define sysfs_in_offsets(offset) \
Jean Delvare34875332007-05-08 17:22:03 +0200297static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \
298 show_in, NULL, offset); \
299static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
300 show_in_min, store_in_min, offset); \
301static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
302 show_in_max, store_in_max, offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303
304sysfs_in_offsets(0);
305sysfs_in_offsets(1);
306sysfs_in_offsets(2);
307sysfs_in_offsets(3);
308sysfs_in_offsets(4);
309sysfs_in_offsets(5);
310sysfs_in_offsets(6);
311sysfs_in_offsets(7);
312sysfs_in_offsets(8);
313
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314#define show_fan_reg(reg) \
Jean Delvare34875332007-05-08 17:22:03 +0200315static ssize_t show_##reg (struct device *dev, struct device_attribute *da, \
316 char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317{ \
Jean Delvare34875332007-05-08 17:22:03 +0200318 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319 struct w83781d_data *data = w83781d_update_device(dev); \
320 return sprintf(buf,"%ld\n", \
Jean Delvare34875332007-05-08 17:22:03 +0200321 FAN_FROM_REG(data->reg[attr->index], \
322 DIV_FROM_REG(data->fan_div[attr->index]))); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323}
324show_fan_reg(fan);
325show_fan_reg(fan_min);
326
327static ssize_t
Jean Delvare34875332007-05-08 17:22:03 +0200328store_fan_min(struct device *dev, struct device_attribute *da,
329 const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330{
Jean Delvare34875332007-05-08 17:22:03 +0200331 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
Jean Delvare7666c132007-05-08 17:22:02 +0200332 struct w83781d_data *data = dev_get_drvdata(dev);
Jean Delvare34875332007-05-08 17:22:03 +0200333 int nr = attr->index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 u32 val;
335
336 val = simple_strtoul(buf, NULL, 10);
337
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100338 mutex_lock(&data->update_lock);
Jean Delvare34875332007-05-08 17:22:03 +0200339 data->fan_min[nr] =
340 FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
Jean Delvare31b8dc42007-05-08 17:22:03 +0200341 w83781d_write_value(data, W83781D_REG_FAN_MIN(nr),
Jean Delvare34875332007-05-08 17:22:03 +0200342 data->fan_min[nr]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100344 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345 return count;
346}
347
Jean Delvare34875332007-05-08 17:22:03 +0200348static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
349static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR,
350 show_fan_min, store_fan_min, 0);
351static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
352static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO | S_IWUSR,
353 show_fan_min, store_fan_min, 1);
354static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2);
355static SENSOR_DEVICE_ATTR(fan3_min, S_IRUGO | S_IWUSR,
356 show_fan_min, store_fan_min, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358#define show_temp_reg(reg) \
Jean Delvare34875332007-05-08 17:22:03 +0200359static ssize_t show_##reg (struct device *dev, struct device_attribute *da, \
360 char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361{ \
Jean Delvare34875332007-05-08 17:22:03 +0200362 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363 struct w83781d_data *data = w83781d_update_device(dev); \
Jean Delvare34875332007-05-08 17:22:03 +0200364 int nr = attr->index; \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 if (nr >= 2) { /* TEMP2 and TEMP3 */ \
366 return sprintf(buf,"%d\n", \
367 LM75_TEMP_FROM_REG(data->reg##_add[nr-2])); \
368 } else { /* TEMP1 */ \
369 return sprintf(buf,"%ld\n", (long)TEMP_FROM_REG(data->reg)); \
370 } \
371}
372show_temp_reg(temp);
373show_temp_reg(temp_max);
374show_temp_reg(temp_max_hyst);
375
376#define store_temp_reg(REG, reg) \
Jean Delvare34875332007-05-08 17:22:03 +0200377static ssize_t store_temp_##reg (struct device *dev, \
378 struct device_attribute *da, const char *buf, size_t count) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379{ \
Jean Delvare34875332007-05-08 17:22:03 +0200380 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \
Jean Delvare7666c132007-05-08 17:22:02 +0200381 struct w83781d_data *data = dev_get_drvdata(dev); \
Jean Delvare34875332007-05-08 17:22:03 +0200382 int nr = attr->index; \
Christian Hohnstaedt5bfedac2007-08-16 11:40:10 +0200383 long val; \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 \
385 val = simple_strtol(buf, NULL, 10); \
386 \
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100387 mutex_lock(&data->update_lock); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 \
389 if (nr >= 2) { /* TEMP2 and TEMP3 */ \
390 data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \
Jean Delvare31b8dc42007-05-08 17:22:03 +0200391 w83781d_write_value(data, W83781D_REG_TEMP_##REG(nr), \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 data->temp_##reg##_add[nr-2]); \
393 } else { /* TEMP1 */ \
394 data->temp_##reg = TEMP_TO_REG(val); \
Jean Delvare31b8dc42007-05-08 17:22:03 +0200395 w83781d_write_value(data, W83781D_REG_TEMP_##REG(nr), \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 data->temp_##reg); \
397 } \
398 \
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100399 mutex_unlock(&data->update_lock); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 return count; \
401}
402store_temp_reg(OVER, max);
403store_temp_reg(HYST, max_hyst);
404
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405#define sysfs_temp_offsets(offset) \
Jean Delvare34875332007-05-08 17:22:03 +0200406static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
407 show_temp, NULL, offset); \
408static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \
409 show_temp_max, store_temp_max, offset); \
410static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \
411 show_temp_max_hyst, store_temp_max_hyst, offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412
413sysfs_temp_offsets(1);
414sysfs_temp_offsets(2);
415sysfs_temp_offsets(3);
416
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417static ssize_t
Yani Ioannoue404e272005-05-17 06:42:58 -0400418show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419{
420 struct w83781d_data *data = w83781d_update_device(dev);
421 return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
422}
423
Jim Cromie311ce2e2006-09-24 21:22:52 +0200424static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
425
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426static ssize_t
Yani Ioannoue404e272005-05-17 06:42:58 -0400427show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428{
Jean Delvare90d66192007-10-08 18:24:35 +0200429 struct w83781d_data *data = dev_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 return sprintf(buf, "%ld\n", (long) data->vrm);
431}
432
433static ssize_t
Yani Ioannoue404e272005-05-17 06:42:58 -0400434store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435{
Jean Delvare7666c132007-05-08 17:22:02 +0200436 struct w83781d_data *data = dev_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 u32 val;
438
439 val = simple_strtoul(buf, NULL, 10);
440 data->vrm = val;
441
442 return count;
443}
444
Jim Cromie311ce2e2006-09-24 21:22:52 +0200445static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
446
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447static ssize_t
Yani Ioannoue404e272005-05-17 06:42:58 -0400448show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449{
450 struct w83781d_data *data = w83781d_update_device(dev);
Jean Delvare68188ba2005-05-16 18:52:38 +0200451 return sprintf(buf, "%u\n", data->alarms);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452}
453
Jim Cromie311ce2e2006-09-24 21:22:52 +0200454static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
455
Jean Delvare7d4a1372007-10-08 18:29:43 +0200456static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
457 char *buf)
458{
459 struct w83781d_data *data = w83781d_update_device(dev);
460 int bitnr = to_sensor_dev_attr(attr)->index;
461 return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
462}
463
464/* The W83781D has a single alarm bit for temp2 and temp3 */
465static ssize_t show_temp3_alarm(struct device *dev,
466 struct device_attribute *attr, char *buf)
467{
468 struct w83781d_data *data = w83781d_update_device(dev);
469 int bitnr = (data->type == w83781d) ? 5 : 13;
470 return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
471}
472
473static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
474static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
475static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
476static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
477static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8);
478static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9);
479static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 10);
480static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 16);
481static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 17);
482static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6);
483static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7);
484static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11);
485static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4);
486static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5);
487static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_temp3_alarm, NULL, 0);
488
Yani Ioannoue404e272005-05-17 06:42:58 -0400489static ssize_t show_beep_mask (struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490{
491 struct w83781d_data *data = w83781d_update_device(dev);
492 return sprintf(buf, "%ld\n",
493 (long)BEEP_MASK_FROM_REG(data->beep_mask, data->type));
494}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496static ssize_t
Jean Delvare34875332007-05-08 17:22:03 +0200497store_beep_mask(struct device *dev, struct device_attribute *attr,
498 const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499{
Jean Delvare7666c132007-05-08 17:22:02 +0200500 struct w83781d_data *data = dev_get_drvdata(dev);
Jean Delvare34875332007-05-08 17:22:03 +0200501 u32 val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502
503 val = simple_strtoul(buf, NULL, 10);
504
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100505 mutex_lock(&data->update_lock);
Jean Delvare2fbbbf12008-10-17 17:51:18 +0200506 data->beep_mask &= 0x8000; /* preserve beep enable */
507 data->beep_mask |= BEEP_MASK_TO_REG(val, data->type);
Jean Delvare34875332007-05-08 17:22:03 +0200508 w83781d_write_value(data, W83781D_REG_BEEP_INTS1,
509 data->beep_mask & 0xff);
Jean Delvare31b8dc42007-05-08 17:22:03 +0200510 w83781d_write_value(data, W83781D_REG_BEEP_INTS2,
Jean Delvare2fbbbf12008-10-17 17:51:18 +0200511 (data->beep_mask >> 8) & 0xff);
Jean Delvare34875332007-05-08 17:22:03 +0200512 if (data->type != w83781d && data->type != as99127f) {
513 w83781d_write_value(data, W83781D_REG_BEEP_INTS3,
514 ((data->beep_mask) >> 16) & 0xff);
515 }
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100516 mutex_unlock(&data->update_lock);
Jean Delvare34875332007-05-08 17:22:03 +0200517
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 return count;
519}
520
Jean Delvare34875332007-05-08 17:22:03 +0200521static DEVICE_ATTR(beep_mask, S_IRUGO | S_IWUSR,
522 show_beep_mask, store_beep_mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523
Jean Delvare7d4a1372007-10-08 18:29:43 +0200524static ssize_t show_beep(struct device *dev, struct device_attribute *attr,
525 char *buf)
526{
527 struct w83781d_data *data = w83781d_update_device(dev);
528 int bitnr = to_sensor_dev_attr(attr)->index;
529 return sprintf(buf, "%u\n", (data->beep_mask >> bitnr) & 1);
530}
531
532static ssize_t
533store_beep(struct device *dev, struct device_attribute *attr,
534 const char *buf, size_t count)
535{
536 struct w83781d_data *data = dev_get_drvdata(dev);
537 int bitnr = to_sensor_dev_attr(attr)->index;
538 unsigned long bit;
539 u8 reg;
540
541 bit = simple_strtoul(buf, NULL, 10);
542 if (bit & ~1)
543 return -EINVAL;
544
545 mutex_lock(&data->update_lock);
546 if (bit)
547 data->beep_mask |= (1 << bitnr);
548 else
549 data->beep_mask &= ~(1 << bitnr);
550
551 if (bitnr < 8) {
552 reg = w83781d_read_value(data, W83781D_REG_BEEP_INTS1);
553 if (bit)
554 reg |= (1 << bitnr);
555 else
556 reg &= ~(1 << bitnr);
557 w83781d_write_value(data, W83781D_REG_BEEP_INTS1, reg);
558 } else if (bitnr < 16) {
559 reg = w83781d_read_value(data, W83781D_REG_BEEP_INTS2);
560 if (bit)
561 reg |= (1 << (bitnr - 8));
562 else
563 reg &= ~(1 << (bitnr - 8));
564 w83781d_write_value(data, W83781D_REG_BEEP_INTS2, reg);
565 } else {
566 reg = w83781d_read_value(data, W83781D_REG_BEEP_INTS3);
567 if (bit)
568 reg |= (1 << (bitnr - 16));
569 else
570 reg &= ~(1 << (bitnr - 16));
571 w83781d_write_value(data, W83781D_REG_BEEP_INTS3, reg);
572 }
573 mutex_unlock(&data->update_lock);
574
575 return count;
576}
577
578/* The W83781D has a single beep bit for temp2 and temp3 */
579static ssize_t show_temp3_beep(struct device *dev,
580 struct device_attribute *attr, char *buf)
581{
582 struct w83781d_data *data = w83781d_update_device(dev);
583 int bitnr = (data->type == w83781d) ? 5 : 13;
584 return sprintf(buf, "%u\n", (data->beep_mask >> bitnr) & 1);
585}
586
587static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR,
588 show_beep, store_beep, 0);
589static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO | S_IWUSR,
590 show_beep, store_beep, 1);
591static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO | S_IWUSR,
592 show_beep, store_beep, 2);
593static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO | S_IWUSR,
594 show_beep, store_beep, 3);
595static SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO | S_IWUSR,
596 show_beep, store_beep, 8);
597static SENSOR_DEVICE_ATTR(in5_beep, S_IRUGO | S_IWUSR,
598 show_beep, store_beep, 9);
599static SENSOR_DEVICE_ATTR(in6_beep, S_IRUGO | S_IWUSR,
600 show_beep, store_beep, 10);
601static SENSOR_DEVICE_ATTR(in7_beep, S_IRUGO | S_IWUSR,
602 show_beep, store_beep, 16);
603static SENSOR_DEVICE_ATTR(in8_beep, S_IRUGO | S_IWUSR,
604 show_beep, store_beep, 17);
605static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO | S_IWUSR,
606 show_beep, store_beep, 6);
607static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO | S_IWUSR,
608 show_beep, store_beep, 7);
609static SENSOR_DEVICE_ATTR(fan3_beep, S_IRUGO | S_IWUSR,
610 show_beep, store_beep, 11);
611static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR,
612 show_beep, store_beep, 4);
613static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO | S_IWUSR,
614 show_beep, store_beep, 5);
615static SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO,
616 show_temp3_beep, store_beep, 13);
Jean Delvare2fbbbf12008-10-17 17:51:18 +0200617static SENSOR_DEVICE_ATTR(beep_enable, S_IRUGO | S_IWUSR,
618 show_beep, store_beep, 15);
Jean Delvare7d4a1372007-10-08 18:29:43 +0200619
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620static ssize_t
Jean Delvare34875332007-05-08 17:22:03 +0200621show_fan_div(struct device *dev, struct device_attribute *da, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622{
Jean Delvare34875332007-05-08 17:22:03 +0200623 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624 struct w83781d_data *data = w83781d_update_device(dev);
625 return sprintf(buf, "%ld\n",
Jean Delvare34875332007-05-08 17:22:03 +0200626 (long) DIV_FROM_REG(data->fan_div[attr->index]));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627}
628
629/* Note: we save and restore the fan minimum here, because its value is
630 determined in part by the fan divisor. This follows the principle of
Andreas Mohrd6e05ed2006-06-26 18:35:02 +0200631 least surprise; the user doesn't expect the fan minimum to change just
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 because the divisor changed. */
633static ssize_t
Jean Delvare34875332007-05-08 17:22:03 +0200634store_fan_div(struct device *dev, struct device_attribute *da,
635 const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636{
Jean Delvare34875332007-05-08 17:22:03 +0200637 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
Jean Delvare7666c132007-05-08 17:22:02 +0200638 struct w83781d_data *data = dev_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 unsigned long min;
Jean Delvare34875332007-05-08 17:22:03 +0200640 int nr = attr->index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 u8 reg;
642 unsigned long val = simple_strtoul(buf, NULL, 10);
643
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100644 mutex_lock(&data->update_lock);
Jean Delvare293c0992007-11-30 23:52:44 +0100645
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 /* Save fan_min */
647 min = FAN_FROM_REG(data->fan_min[nr],
648 DIV_FROM_REG(data->fan_div[nr]));
649
650 data->fan_div[nr] = DIV_TO_REG(val, data->type);
651
Jean Delvare31b8dc42007-05-08 17:22:03 +0200652 reg = (w83781d_read_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 & (nr==0 ? 0xcf : 0x3f))
654 | ((data->fan_div[nr] & 0x03) << (nr==0 ? 4 : 6));
Jean Delvare31b8dc42007-05-08 17:22:03 +0200655 w83781d_write_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656
657 /* w83781d and as99127f don't have extended divisor bits */
658 if (data->type != w83781d && data->type != as99127f) {
Jean Delvare31b8dc42007-05-08 17:22:03 +0200659 reg = (w83781d_read_value(data, W83781D_REG_VBAT)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660 & ~(1 << (5 + nr)))
661 | ((data->fan_div[nr] & 0x04) << (3 + nr));
Jean Delvare31b8dc42007-05-08 17:22:03 +0200662 w83781d_write_value(data, W83781D_REG_VBAT, reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 }
664
665 /* Restore fan_min */
666 data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
Jean Delvare34875332007-05-08 17:22:03 +0200667 w83781d_write_value(data, W83781D_REG_FAN_MIN(nr), data->fan_min[nr]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100669 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 return count;
671}
672
Jean Delvare34875332007-05-08 17:22:03 +0200673static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR,
674 show_fan_div, store_fan_div, 0);
675static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR,
676 show_fan_div, store_fan_div, 1);
677static SENSOR_DEVICE_ATTR(fan3_div, S_IRUGO | S_IWUSR,
678 show_fan_div, store_fan_div, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680static ssize_t
Jean Delvare34875332007-05-08 17:22:03 +0200681show_pwm(struct device *dev, struct device_attribute *da, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682{
Jean Delvare34875332007-05-08 17:22:03 +0200683 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 struct w83781d_data *data = w83781d_update_device(dev);
Jean Delvare34875332007-05-08 17:22:03 +0200685 return sprintf(buf, "%d\n", (int)data->pwm[attr->index]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686}
687
688static ssize_t
Jean Delvare34875332007-05-08 17:22:03 +0200689show_pwm2_enable(struct device *dev, struct device_attribute *da, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690{
691 struct w83781d_data *data = w83781d_update_device(dev);
Jean Delvare34875332007-05-08 17:22:03 +0200692 return sprintf(buf, "%d\n", (int)data->pwm2_enable);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693}
694
695static ssize_t
Jean Delvare34875332007-05-08 17:22:03 +0200696store_pwm(struct device *dev, struct device_attribute *da, const char *buf,
697 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698{
Jean Delvare34875332007-05-08 17:22:03 +0200699 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
Jean Delvare7666c132007-05-08 17:22:02 +0200700 struct w83781d_data *data = dev_get_drvdata(dev);
Jean Delvare34875332007-05-08 17:22:03 +0200701 int nr = attr->index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 u32 val;
703
704 val = simple_strtoul(buf, NULL, 10);
705
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100706 mutex_lock(&data->update_lock);
Jean Delvare34875332007-05-08 17:22:03 +0200707 data->pwm[nr] = SENSORS_LIMIT(val, 0, 255);
708 w83781d_write_value(data, W83781D_REG_PWM[nr], data->pwm[nr]);
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100709 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710 return count;
711}
712
713static ssize_t
Jean Delvare34875332007-05-08 17:22:03 +0200714store_pwm2_enable(struct device *dev, struct device_attribute *da,
715 const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716{
Jean Delvare7666c132007-05-08 17:22:02 +0200717 struct w83781d_data *data = dev_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 u32 val, reg;
719
720 val = simple_strtoul(buf, NULL, 10);
721
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100722 mutex_lock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723
724 switch (val) {
725 case 0:
726 case 1:
Jean Delvare31b8dc42007-05-08 17:22:03 +0200727 reg = w83781d_read_value(data, W83781D_REG_PWMCLK12);
728 w83781d_write_value(data, W83781D_REG_PWMCLK12,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 (reg & 0xf7) | (val << 3));
730
Jean Delvare31b8dc42007-05-08 17:22:03 +0200731 reg = w83781d_read_value(data, W83781D_REG_BEEP_CONFIG);
732 w83781d_write_value(data, W83781D_REG_BEEP_CONFIG,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 (reg & 0xef) | (!val << 4));
734
Jean Delvare34875332007-05-08 17:22:03 +0200735 data->pwm2_enable = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 break;
737
738 default:
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100739 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 return -EINVAL;
741 }
742
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100743 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 return count;
745}
746
Jean Delvare34875332007-05-08 17:22:03 +0200747static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 0);
748static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 1);
749static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 2);
750static SENSOR_DEVICE_ATTR(pwm4, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 3);
751/* only PWM2 can be enabled/disabled */
752static DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR,
753 show_pwm2_enable, store_pwm2_enable);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755static ssize_t
Jean Delvare34875332007-05-08 17:22:03 +0200756show_sensor(struct device *dev, struct device_attribute *da, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757{
Jean Delvare34875332007-05-08 17:22:03 +0200758 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 struct w83781d_data *data = w83781d_update_device(dev);
Jean Delvare34875332007-05-08 17:22:03 +0200760 return sprintf(buf, "%d\n", (int)data->sens[attr->index]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761}
762
763static ssize_t
Jean Delvare34875332007-05-08 17:22:03 +0200764store_sensor(struct device *dev, struct device_attribute *da,
765 const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766{
Jean Delvare34875332007-05-08 17:22:03 +0200767 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
Jean Delvare7666c132007-05-08 17:22:02 +0200768 struct w83781d_data *data = dev_get_drvdata(dev);
Jean Delvare34875332007-05-08 17:22:03 +0200769 int nr = attr->index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 u32 val, tmp;
771
772 val = simple_strtoul(buf, NULL, 10);
773
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100774 mutex_lock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775
776 switch (val) {
777 case 1: /* PII/Celeron diode */
Jean Delvare31b8dc42007-05-08 17:22:03 +0200778 tmp = w83781d_read_value(data, W83781D_REG_SCFG1);
779 w83781d_write_value(data, W83781D_REG_SCFG1,
Jean Delvare34875332007-05-08 17:22:03 +0200780 tmp | BIT_SCFG1[nr]);
Jean Delvare31b8dc42007-05-08 17:22:03 +0200781 tmp = w83781d_read_value(data, W83781D_REG_SCFG2);
782 w83781d_write_value(data, W83781D_REG_SCFG2,
Jean Delvare34875332007-05-08 17:22:03 +0200783 tmp | BIT_SCFG2[nr]);
784 data->sens[nr] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785 break;
786 case 2: /* 3904 */
Jean Delvare31b8dc42007-05-08 17:22:03 +0200787 tmp = w83781d_read_value(data, W83781D_REG_SCFG1);
788 w83781d_write_value(data, W83781D_REG_SCFG1,
Jean Delvare34875332007-05-08 17:22:03 +0200789 tmp | BIT_SCFG1[nr]);
Jean Delvare31b8dc42007-05-08 17:22:03 +0200790 tmp = w83781d_read_value(data, W83781D_REG_SCFG2);
791 w83781d_write_value(data, W83781D_REG_SCFG2,
Jean Delvare34875332007-05-08 17:22:03 +0200792 tmp & ~BIT_SCFG2[nr]);
793 data->sens[nr] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 break;
Jean Delvareb26f9332007-08-16 14:30:01 +0200795 case W83781D_DEFAULT_BETA:
796 dev_warn(dev, "Sensor type %d is deprecated, please use 4 "
797 "instead\n", W83781D_DEFAULT_BETA);
798 /* fall through */
799 case 4: /* thermistor */
Jean Delvare31b8dc42007-05-08 17:22:03 +0200800 tmp = w83781d_read_value(data, W83781D_REG_SCFG1);
801 w83781d_write_value(data, W83781D_REG_SCFG1,
Jean Delvare34875332007-05-08 17:22:03 +0200802 tmp & ~BIT_SCFG1[nr]);
803 data->sens[nr] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 break;
805 default:
Jean Delvareb26f9332007-08-16 14:30:01 +0200806 dev_err(dev, "Invalid sensor type %ld; must be 1, 2, or 4\n",
807 (long) val);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 break;
809 }
810
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100811 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 return count;
813}
814
Jean Delvare34875332007-05-08 17:22:03 +0200815static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO | S_IWUSR,
816 show_sensor, store_sensor, 0);
817static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO | S_IWUSR,
Mark M. Hoffman393cdad2007-08-09 08:12:46 -0400818 show_sensor, store_sensor, 1);
Jean Delvare34875332007-05-08 17:22:03 +0200819static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO | S_IWUSR,
Mark M. Hoffman393cdad2007-08-09 08:12:46 -0400820 show_sensor, store_sensor, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822/* This function is called when:
823 * w83781d_driver is inserted (when this module is loaded), for each
824 available adapter
Jean Delvarec6566202008-10-17 17:51:18 +0200825 * when a new adapter is inserted (and w83781d_driver is still present)
826 We block updates of the ISA device to minimize the risk of concurrent
827 access to the same W83781D chip through different interfaces. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828static int
829w83781d_attach_adapter(struct i2c_adapter *adapter)
830{
Wolfgang Grandegger443850c2008-10-17 17:51:18 +0200831 struct w83781d_data *data = w83781d_data_if_isa();
Jean Delvarec6566202008-10-17 17:51:18 +0200832 int err;
833
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 if (!(adapter->class & I2C_CLASS_HWMON))
835 return 0;
Jean Delvarec6566202008-10-17 17:51:18 +0200836
Jean Delvarec6566202008-10-17 17:51:18 +0200837 if (data)
838 mutex_lock(&data->update_lock);
839 err = i2c_probe(adapter, &addr_data, w83781d_detect);
840 if (data)
841 mutex_unlock(&data->update_lock);
842 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843}
844
845/* Assumes that adapter is of I2C, not ISA variety.
846 * OTHERWISE DON'T CALL THIS
847 */
848static int
849w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
850 struct i2c_client *new_client)
851{
852 int i, val1 = 0, id;
853 int err;
854 const char *client_name = "";
855 struct w83781d_data *data = i2c_get_clientdata(new_client);
856
Deepak Saxenaba9c2e82005-10-17 23:08:32 +0200857 data->lm75[0] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 if (!(data->lm75[0])) {
859 err = -ENOMEM;
860 goto ERROR_SC_0;
861 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862
863 id = i2c_adapter_id(adapter);
864
865 if (force_subclients[0] == id && force_subclients[1] == address) {
866 for (i = 2; i <= 3; i++) {
867 if (force_subclients[i] < 0x48 ||
868 force_subclients[i] > 0x4f) {
869 dev_err(&new_client->dev, "Invalid subclient "
870 "address %d; must be 0x48-0x4f\n",
871 force_subclients[i]);
872 err = -EINVAL;
873 goto ERROR_SC_1;
874 }
875 }
Jean Delvare31b8dc42007-05-08 17:22:03 +0200876 w83781d_write_value(data, W83781D_REG_I2C_SUBADDR,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 (force_subclients[2] & 0x07) |
878 ((force_subclients[3] & 0x07) << 4));
879 data->lm75[0]->addr = force_subclients[2];
880 } else {
Jean Delvare31b8dc42007-05-08 17:22:03 +0200881 val1 = w83781d_read_value(data, W83781D_REG_I2C_SUBADDR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 data->lm75[0]->addr = 0x48 + (val1 & 0x07);
883 }
884
885 if (kind != w83783s) {
Deepak Saxenaba9c2e82005-10-17 23:08:32 +0200886 data->lm75[1] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887 if (!(data->lm75[1])) {
888 err = -ENOMEM;
889 goto ERROR_SC_1;
890 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891
892 if (force_subclients[0] == id &&
893 force_subclients[1] == address) {
894 data->lm75[1]->addr = force_subclients[3];
895 } else {
896 data->lm75[1]->addr = 0x48 + ((val1 >> 4) & 0x07);
897 }
898 if (data->lm75[0]->addr == data->lm75[1]->addr) {
899 dev_err(&new_client->dev,
900 "Duplicate addresses 0x%x for subclients.\n",
901 data->lm75[0]->addr);
902 err = -EBUSY;
903 goto ERROR_SC_2;
904 }
905 }
906
907 if (kind == w83781d)
908 client_name = "w83781d subclient";
909 else if (kind == w83782d)
910 client_name = "w83782d subclient";
911 else if (kind == w83783s)
912 client_name = "w83783s subclient";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 else if (kind == as99127f)
914 client_name = "as99127f subclient";
915
916 for (i = 0; i <= 1; i++) {
917 /* store all data in w83781d */
918 i2c_set_clientdata(data->lm75[i], NULL);
919 data->lm75[i]->adapter = adapter;
920 data->lm75[i]->driver = &w83781d_driver;
921 data->lm75[i]->flags = 0;
922 strlcpy(data->lm75[i]->name, client_name,
923 I2C_NAME_SIZE);
924 if ((err = i2c_attach_client(data->lm75[i]))) {
925 dev_err(&new_client->dev, "Subclient %d "
926 "registration at address 0x%x "
927 "failed.\n", i, data->lm75[i]->addr);
928 if (i == 1)
929 goto ERROR_SC_3;
930 goto ERROR_SC_2;
931 }
932 if (kind == w83783s)
933 break;
934 }
935
936 return 0;
937
938/* Undo inits in case of errors */
939ERROR_SC_3:
940 i2c_detach_client(data->lm75[0]);
941ERROR_SC_2:
Jesper Juhl6044ec82005-11-07 01:01:32 -0800942 kfree(data->lm75[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943ERROR_SC_1:
Jesper Juhl6044ec82005-11-07 01:01:32 -0800944 kfree(data->lm75[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945ERROR_SC_0:
946 return err;
947}
948
Jean Delvare34875332007-05-08 17:22:03 +0200949#define IN_UNIT_ATTRS(X) \
950 &sensor_dev_attr_in##X##_input.dev_attr.attr, \
951 &sensor_dev_attr_in##X##_min.dev_attr.attr, \
Jean Delvare293c0992007-11-30 23:52:44 +0100952 &sensor_dev_attr_in##X##_max.dev_attr.attr, \
Jean Delvare7d4a1372007-10-08 18:29:43 +0200953 &sensor_dev_attr_in##X##_alarm.dev_attr.attr, \
954 &sensor_dev_attr_in##X##_beep.dev_attr.attr
Jim Cromie311ce2e2006-09-24 21:22:52 +0200955
Jean Delvare34875332007-05-08 17:22:03 +0200956#define FAN_UNIT_ATTRS(X) \
957 &sensor_dev_attr_fan##X##_input.dev_attr.attr, \
958 &sensor_dev_attr_fan##X##_min.dev_attr.attr, \
Jean Delvare7d4a1372007-10-08 18:29:43 +0200959 &sensor_dev_attr_fan##X##_div.dev_attr.attr, \
960 &sensor_dev_attr_fan##X##_alarm.dev_attr.attr, \
961 &sensor_dev_attr_fan##X##_beep.dev_attr.attr
Jim Cromie311ce2e2006-09-24 21:22:52 +0200962
Jean Delvare34875332007-05-08 17:22:03 +0200963#define TEMP_UNIT_ATTRS(X) \
964 &sensor_dev_attr_temp##X##_input.dev_attr.attr, \
965 &sensor_dev_attr_temp##X##_max.dev_attr.attr, \
Jean Delvare7d4a1372007-10-08 18:29:43 +0200966 &sensor_dev_attr_temp##X##_max_hyst.dev_attr.attr, \
967 &sensor_dev_attr_temp##X##_alarm.dev_attr.attr, \
968 &sensor_dev_attr_temp##X##_beep.dev_attr.attr
Jim Cromie311ce2e2006-09-24 21:22:52 +0200969
970static struct attribute* w83781d_attributes[] = {
971 IN_UNIT_ATTRS(0),
972 IN_UNIT_ATTRS(2),
973 IN_UNIT_ATTRS(3),
974 IN_UNIT_ATTRS(4),
975 IN_UNIT_ATTRS(5),
976 IN_UNIT_ATTRS(6),
977 FAN_UNIT_ATTRS(1),
978 FAN_UNIT_ATTRS(2),
979 FAN_UNIT_ATTRS(3),
980 TEMP_UNIT_ATTRS(1),
981 TEMP_UNIT_ATTRS(2),
982 &dev_attr_cpu0_vid.attr,
983 &dev_attr_vrm.attr,
984 &dev_attr_alarms.attr,
985 &dev_attr_beep_mask.attr,
Jean Delvare2fbbbf12008-10-17 17:51:18 +0200986 &sensor_dev_attr_beep_enable.dev_attr.attr,
Jim Cromie311ce2e2006-09-24 21:22:52 +0200987 NULL
988};
989static const struct attribute_group w83781d_group = {
990 .attrs = w83781d_attributes,
991};
992
993static struct attribute *w83781d_attributes_opt[] = {
994 IN_UNIT_ATTRS(1),
995 IN_UNIT_ATTRS(7),
996 IN_UNIT_ATTRS(8),
997 TEMP_UNIT_ATTRS(3),
Jean Delvare34875332007-05-08 17:22:03 +0200998 &sensor_dev_attr_pwm1.dev_attr.attr,
999 &sensor_dev_attr_pwm2.dev_attr.attr,
1000 &sensor_dev_attr_pwm3.dev_attr.attr,
1001 &sensor_dev_attr_pwm4.dev_attr.attr,
Jim Cromie311ce2e2006-09-24 21:22:52 +02001002 &dev_attr_pwm2_enable.attr,
Jean Delvare34875332007-05-08 17:22:03 +02001003 &sensor_dev_attr_temp1_type.dev_attr.attr,
1004 &sensor_dev_attr_temp2_type.dev_attr.attr,
1005 &sensor_dev_attr_temp3_type.dev_attr.attr,
Jim Cromie311ce2e2006-09-24 21:22:52 +02001006 NULL
1007};
1008static const struct attribute_group w83781d_group_opt = {
1009 .attrs = w83781d_attributes_opt,
1010};
1011
Jean Delvare7666c132007-05-08 17:22:02 +02001012/* No clean up is done on error, it's up to the caller */
1013static int
1014w83781d_create_files(struct device *dev, int kind, int is_isa)
1015{
1016 int err;
1017
1018 if ((err = sysfs_create_group(&dev->kobj, &w83781d_group)))
1019 return err;
1020
1021 if (kind != w83783s) {
Jean Delvare34875332007-05-08 17:22:03 +02001022 if ((err = device_create_file(dev,
1023 &sensor_dev_attr_in1_input.dev_attr))
1024 || (err = device_create_file(dev,
1025 &sensor_dev_attr_in1_min.dev_attr))
1026 || (err = device_create_file(dev,
Jean Delvare7d4a1372007-10-08 18:29:43 +02001027 &sensor_dev_attr_in1_max.dev_attr))
1028 || (err = device_create_file(dev,
1029 &sensor_dev_attr_in1_alarm.dev_attr))
1030 || (err = device_create_file(dev,
1031 &sensor_dev_attr_in1_beep.dev_attr)))
Jean Delvare7666c132007-05-08 17:22:02 +02001032 return err;
1033 }
1034 if (kind != as99127f && kind != w83781d && kind != w83783s) {
Jean Delvare34875332007-05-08 17:22:03 +02001035 if ((err = device_create_file(dev,
1036 &sensor_dev_attr_in7_input.dev_attr))
1037 || (err = device_create_file(dev,
1038 &sensor_dev_attr_in7_min.dev_attr))
1039 || (err = device_create_file(dev,
1040 &sensor_dev_attr_in7_max.dev_attr))
1041 || (err = device_create_file(dev,
Jean Delvare7d4a1372007-10-08 18:29:43 +02001042 &sensor_dev_attr_in7_alarm.dev_attr))
1043 || (err = device_create_file(dev,
1044 &sensor_dev_attr_in7_beep.dev_attr))
1045 || (err = device_create_file(dev,
Jean Delvare34875332007-05-08 17:22:03 +02001046 &sensor_dev_attr_in8_input.dev_attr))
1047 || (err = device_create_file(dev,
1048 &sensor_dev_attr_in8_min.dev_attr))
1049 || (err = device_create_file(dev,
Jean Delvare7d4a1372007-10-08 18:29:43 +02001050 &sensor_dev_attr_in8_max.dev_attr))
1051 || (err = device_create_file(dev,
1052 &sensor_dev_attr_in8_alarm.dev_attr))
1053 || (err = device_create_file(dev,
1054 &sensor_dev_attr_in8_beep.dev_attr)))
Jean Delvare7666c132007-05-08 17:22:02 +02001055 return err;
1056 }
1057 if (kind != w83783s) {
Jean Delvare34875332007-05-08 17:22:03 +02001058 if ((err = device_create_file(dev,
1059 &sensor_dev_attr_temp3_input.dev_attr))
Jean Delvare7666c132007-05-08 17:22:02 +02001060 || (err = device_create_file(dev,
Jean Delvare34875332007-05-08 17:22:03 +02001061 &sensor_dev_attr_temp3_max.dev_attr))
1062 || (err = device_create_file(dev,
Jean Delvare7d4a1372007-10-08 18:29:43 +02001063 &sensor_dev_attr_temp3_max_hyst.dev_attr))
1064 || (err = device_create_file(dev,
1065 &sensor_dev_attr_temp3_alarm.dev_attr))
1066 || (err = device_create_file(dev,
1067 &sensor_dev_attr_temp3_beep.dev_attr)))
Jean Delvare7666c132007-05-08 17:22:02 +02001068 return err;
Jean Delvare7d4a1372007-10-08 18:29:43 +02001069
Jean Delvare7768aa72007-10-25 13:11:01 +02001070 if (kind != w83781d) {
Jean Delvare7d4a1372007-10-08 18:29:43 +02001071 err = sysfs_chmod_file(&dev->kobj,
1072 &sensor_dev_attr_temp3_alarm.dev_attr.attr,
1073 S_IRUGO | S_IWUSR);
1074 if (err)
1075 return err;
Jean Delvare7768aa72007-10-25 13:11:01 +02001076 }
Jean Delvare7666c132007-05-08 17:22:02 +02001077 }
1078
1079 if (kind != w83781d && kind != as99127f) {
Jean Delvare34875332007-05-08 17:22:03 +02001080 if ((err = device_create_file(dev,
1081 &sensor_dev_attr_pwm1.dev_attr))
1082 || (err = device_create_file(dev,
1083 &sensor_dev_attr_pwm2.dev_attr))
Jean Delvare7666c132007-05-08 17:22:02 +02001084 || (err = device_create_file(dev, &dev_attr_pwm2_enable)))
1085 return err;
1086 }
1087 if (kind == w83782d && !is_isa) {
Jean Delvare34875332007-05-08 17:22:03 +02001088 if ((err = device_create_file(dev,
1089 &sensor_dev_attr_pwm3.dev_attr))
1090 || (err = device_create_file(dev,
1091 &sensor_dev_attr_pwm4.dev_attr)))
Jean Delvare7666c132007-05-08 17:22:02 +02001092 return err;
1093 }
1094
1095 if (kind != as99127f && kind != w83781d) {
Jean Delvare34875332007-05-08 17:22:03 +02001096 if ((err = device_create_file(dev,
1097 &sensor_dev_attr_temp1_type.dev_attr))
Jean Delvare7666c132007-05-08 17:22:02 +02001098 || (err = device_create_file(dev,
Jean Delvare34875332007-05-08 17:22:03 +02001099 &sensor_dev_attr_temp2_type.dev_attr)))
Jean Delvare7666c132007-05-08 17:22:02 +02001100 return err;
1101 if (kind != w83783s) {
1102 if ((err = device_create_file(dev,
Jean Delvare34875332007-05-08 17:22:03 +02001103 &sensor_dev_attr_temp3_type.dev_attr)))
Jean Delvare7666c132007-05-08 17:22:02 +02001104 return err;
1105 }
1106 }
1107
Jean Delvare7666c132007-05-08 17:22:02 +02001108 return 0;
1109}
1110
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111static int
1112w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
1113{
Jean Delvare7666c132007-05-08 17:22:02 +02001114 int val1 = 0, val2;
Jim Cromie311ce2e2006-09-24 21:22:52 +02001115 struct i2c_client *client;
1116 struct device *dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 struct w83781d_data *data;
1118 int err;
1119 const char *client_name = "";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 enum vendor { winbond, asus } vendid;
1121
Jean Delvare7666c132007-05-08 17:22:02 +02001122 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 err = -EINVAL;
Jean Delvare7666c132007-05-08 17:22:02 +02001124 goto ERROR1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 }
1126
1127 /* OK. For now, we presume we have a valid client. We now create the
1128 client structure, even though we cannot fill it completely yet.
1129 But it allows us to access w83781d_{read,write}_value. */
1130
Deepak Saxenaba9c2e82005-10-17 23:08:32 +02001131 if (!(data = kzalloc(sizeof(struct w83781d_data), GFP_KERNEL))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 err = -ENOMEM;
1133 goto ERROR1;
1134 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135
Jim Cromie311ce2e2006-09-24 21:22:52 +02001136 client = &data->client;
1137 i2c_set_clientdata(client, data);
1138 client->addr = address;
Ingo Molnar9a61bf62006-01-18 23:19:26 +01001139 mutex_init(&data->lock);
Jim Cromie311ce2e2006-09-24 21:22:52 +02001140 client->adapter = adapter;
Jean Delvare7666c132007-05-08 17:22:02 +02001141 client->driver = &w83781d_driver;
Jim Cromie311ce2e2006-09-24 21:22:52 +02001142 dev = &client->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143
1144 /* Now, we do the remaining detection. */
1145
1146 /* The w8378?d may be stuck in some other bank than bank 0. This may
1147 make reading other information impossible. Specify a force=... or
1148 force_*=... parameter, and the Winbond will be reset to the right
1149 bank. */
1150 if (kind < 0) {
Jean Delvare31b8dc42007-05-08 17:22:03 +02001151 if (w83781d_read_value(data, W83781D_REG_CONFIG) & 0x80) {
Jean Delvarebd452e62006-10-13 17:03:42 +02001152 dev_dbg(&adapter->dev, "Detection of w83781d chip "
1153 "failed at step 3\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 err = -ENODEV;
1155 goto ERROR2;
1156 }
Jean Delvare31b8dc42007-05-08 17:22:03 +02001157 val1 = w83781d_read_value(data, W83781D_REG_BANK);
1158 val2 = w83781d_read_value(data, W83781D_REG_CHIPMAN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 /* Check for Winbond or Asus ID if in bank 0 */
1160 if ((!(val1 & 0x07)) &&
1161 (((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3))
1162 || ((val1 & 0x80) && (val2 != 0x5c) && (val2 != 0x12)))) {
Jean Delvarebd452e62006-10-13 17:03:42 +02001163 dev_dbg(&adapter->dev, "Detection of w83781d chip "
1164 "failed at step 4\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 err = -ENODEV;
1166 goto ERROR2;
1167 }
1168 /* If Winbond SMBus, check address at 0x48.
1169 Asus doesn't support, except for as99127f rev.2 */
Jean Delvare7666c132007-05-08 17:22:02 +02001170 if ((!(val1 & 0x80) && (val2 == 0xa3)) ||
1171 ((val1 & 0x80) && (val2 == 0x5c))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172 if (w83781d_read_value
Jean Delvare31b8dc42007-05-08 17:22:03 +02001173 (data, W83781D_REG_I2C_ADDR) != address) {
Jean Delvarebd452e62006-10-13 17:03:42 +02001174 dev_dbg(&adapter->dev, "Detection of w83781d "
1175 "chip failed at step 5\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 err = -ENODEV;
1177 goto ERROR2;
1178 }
1179 }
1180 }
1181
1182 /* We have either had a force parameter, or we have already detected the
1183 Winbond. Put it now into bank 0 and Vendor ID High Byte */
Jean Delvare31b8dc42007-05-08 17:22:03 +02001184 w83781d_write_value(data, W83781D_REG_BANK,
1185 (w83781d_read_value(data, W83781D_REG_BANK)
Jim Cromie311ce2e2006-09-24 21:22:52 +02001186 & 0x78) | 0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187
1188 /* Determine the chip type. */
1189 if (kind <= 0) {
1190 /* get vendor ID */
Jean Delvare31b8dc42007-05-08 17:22:03 +02001191 val2 = w83781d_read_value(data, W83781D_REG_CHIPMAN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 if (val2 == 0x5c)
1193 vendid = winbond;
1194 else if (val2 == 0x12)
1195 vendid = asus;
1196 else {
Jean Delvarebd452e62006-10-13 17:03:42 +02001197 dev_dbg(&adapter->dev, "w83781d chip vendor is "
1198 "neither Winbond nor Asus\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199 err = -ENODEV;
1200 goto ERROR2;
1201 }
1202
Jean Delvare31b8dc42007-05-08 17:22:03 +02001203 val1 = w83781d_read_value(data, W83781D_REG_WCHIPID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 if ((val1 == 0x10 || val1 == 0x11) && vendid == winbond)
1205 kind = w83781d;
1206 else if (val1 == 0x30 && vendid == winbond)
1207 kind = w83782d;
Jean Delvare7666c132007-05-08 17:22:02 +02001208 else if (val1 == 0x40 && vendid == winbond && address == 0x2d)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 kind = w83783s;
Jean Delvare6722fea2007-10-07 12:25:46 +02001210 else if (val1 == 0x31)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 kind = as99127f;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 else {
1213 if (kind == 0)
Jean Delvarebd452e62006-10-13 17:03:42 +02001214 dev_warn(&adapter->dev, "Ignoring 'force' "
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 "parameter for unknown chip at "
Jean Delvarebd452e62006-10-13 17:03:42 +02001216 "address 0x%02x\n", address);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 err = -EINVAL;
1218 goto ERROR2;
1219 }
Jean Delvarec6566202008-10-17 17:51:18 +02001220
1221 if ((kind == w83781d || kind == w83782d)
1222 && w83781d_alias_detect(client, val1)) {
1223 dev_dbg(&adapter->dev, "Device at 0x%02x appears to "
1224 "be the same as ISA device\n", address);
1225 err = -ENODEV;
1226 goto ERROR2;
1227 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 }
1229
1230 if (kind == w83781d) {
1231 client_name = "w83781d";
1232 } else if (kind == w83782d) {
1233 client_name = "w83782d";
1234 } else if (kind == w83783s) {
1235 client_name = "w83783s";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236 } else if (kind == as99127f) {
1237 client_name = "as99127f";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 }
1239
1240 /* Fill in the remaining client fields and put into the global list */
Jim Cromie311ce2e2006-09-24 21:22:52 +02001241 strlcpy(client->name, client_name, I2C_NAME_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 data->type = kind;
1243
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 /* Tell the I2C layer a new client has arrived */
Jim Cromie311ce2e2006-09-24 21:22:52 +02001245 if ((err = i2c_attach_client(client)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246 goto ERROR2;
1247
1248 /* attach secondary i2c lm75-like clients */
Jean Delvare7666c132007-05-08 17:22:02 +02001249 if ((err = w83781d_detect_subclients(adapter, address,
1250 kind, client)))
1251 goto ERROR3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252
1253 /* Initialize the chip */
Jean Delvare7666c132007-05-08 17:22:02 +02001254 w83781d_init_device(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255
1256 /* Register sysfs hooks */
Jean Delvare7666c132007-05-08 17:22:02 +02001257 err = w83781d_create_files(dev, kind, 0);
1258 if (err)
Jim Cromie311ce2e2006-09-24 21:22:52 +02001259 goto ERROR4;
1260
Tony Jones1beeffe2007-08-20 13:46:20 -07001261 data->hwmon_dev = hwmon_device_register(dev);
1262 if (IS_ERR(data->hwmon_dev)) {
1263 err = PTR_ERR(data->hwmon_dev);
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001264 goto ERROR4;
1265 }
1266
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267 return 0;
1268
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001269ERROR4:
Jim Cromie311ce2e2006-09-24 21:22:52 +02001270 sysfs_remove_group(&dev->kobj, &w83781d_group);
1271 sysfs_remove_group(&dev->kobj, &w83781d_group_opt);
1272
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001273 if (data->lm75[1]) {
1274 i2c_detach_client(data->lm75[1]);
1275 kfree(data->lm75[1]);
1276 }
1277 if (data->lm75[0]) {
1278 i2c_detach_client(data->lm75[0]);
1279 kfree(data->lm75[0]);
1280 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281ERROR3:
Jim Cromie311ce2e2006-09-24 21:22:52 +02001282 i2c_detach_client(client);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283ERROR2:
1284 kfree(data);
1285ERROR1:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 return err;
1287}
1288
1289static int
1290w83781d_detach_client(struct i2c_client *client)
1291{
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001292 struct w83781d_data *data = i2c_get_clientdata(client);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293 int err;
1294
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001295 /* main client */
Jim Cromie311ce2e2006-09-24 21:22:52 +02001296 if (data) {
Tony Jones1beeffe2007-08-20 13:46:20 -07001297 hwmon_device_unregister(data->hwmon_dev);
Jim Cromie311ce2e2006-09-24 21:22:52 +02001298 sysfs_remove_group(&client->dev.kobj, &w83781d_group);
1299 sysfs_remove_group(&client->dev.kobj, &w83781d_group_opt);
1300 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301
Jean Delvare7bef5592005-07-27 22:14:49 +02001302 if ((err = i2c_detach_client(client)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001305 /* main client */
1306 if (data)
1307 kfree(data);
1308
1309 /* subclient */
1310 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311 kfree(client);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312
1313 return 0;
1314}
1315
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316static int
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001317w83781d_read_value_i2c(struct w83781d_data *data, u16 reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318{
Jean Delvare31b8dc42007-05-08 17:22:03 +02001319 struct i2c_client *client = &data->client;
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001320 int res, bank;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 struct i2c_client *cl;
1322
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001323 bank = (reg >> 8) & 0x0f;
1324 if (bank > 2)
1325 /* switch banks */
1326 i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
1327 bank);
1328 if (bank == 0 || bank > 2) {
1329 res = i2c_smbus_read_byte_data(client, reg & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330 } else {
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001331 /* switch to subclient */
1332 cl = data->lm75[bank - 1];
1333 /* convert from ISA to LM75 I2C addresses */
1334 switch (reg & 0xff) {
1335 case 0x50: /* TEMP */
1336 res = swab16(i2c_smbus_read_word_data(cl, 0));
1337 break;
1338 case 0x52: /* CONFIG */
1339 res = i2c_smbus_read_byte_data(cl, 1);
1340 break;
1341 case 0x53: /* HYST */
1342 res = swab16(i2c_smbus_read_word_data(cl, 2));
1343 break;
1344 case 0x55: /* OVER */
1345 default:
1346 res = swab16(i2c_smbus_read_word_data(cl, 3));
1347 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 }
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001350 if (bank > 2)
1351 i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0);
1352
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 return res;
1354}
1355
1356static int
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001357w83781d_write_value_i2c(struct w83781d_data *data, u16 reg, u16 value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358{
Jean Delvare31b8dc42007-05-08 17:22:03 +02001359 struct i2c_client *client = &data->client;
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001360 int bank;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 struct i2c_client *cl;
1362
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001363 bank = (reg >> 8) & 0x0f;
1364 if (bank > 2)
1365 /* switch banks */
1366 i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
1367 bank);
1368 if (bank == 0 || bank > 2) {
1369 i2c_smbus_write_byte_data(client, reg & 0xff,
1370 value & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 } else {
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001372 /* switch to subclient */
1373 cl = data->lm75[bank - 1];
1374 /* convert from ISA to LM75 I2C addresses */
1375 switch (reg & 0xff) {
1376 case 0x52: /* CONFIG */
1377 i2c_smbus_write_byte_data(cl, 1, value & 0xff);
1378 break;
1379 case 0x53: /* HYST */
1380 i2c_smbus_write_word_data(cl, 2, swab16(value));
1381 break;
1382 case 0x55: /* OVER */
1383 i2c_smbus_write_word_data(cl, 3, swab16(value));
1384 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386 }
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001387 if (bank > 2)
1388 i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0);
1389
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390 return 0;
1391}
1392
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393static void
Jean Delvare7666c132007-05-08 17:22:02 +02001394w83781d_init_device(struct device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395{
Jean Delvare7666c132007-05-08 17:22:02 +02001396 struct w83781d_data *data = dev_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 int i, p;
1398 int type = data->type;
1399 u8 tmp;
1400
Jean Delvarefabddcd2006-02-05 23:26:51 +01001401 if (reset && type != as99127f) { /* this resets registers we don't have
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402 documentation for on the as99127f */
Jean Delvarefabddcd2006-02-05 23:26:51 +01001403 /* Resetting the chip has been the default for a long time,
1404 but it causes the BIOS initializations (fan clock dividers,
1405 thermal sensor types...) to be lost, so it is now optional.
1406 It might even go away if nobody reports it as being useful,
1407 as I see very little reason why this would be needed at
1408 all. */
Jean Delvare7666c132007-05-08 17:22:02 +02001409 dev_info(dev, "If reset=1 solved a problem you were "
Jean Delvarefabddcd2006-02-05 23:26:51 +01001410 "having, please report!\n");
1411
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 /* save these registers */
Jean Delvare31b8dc42007-05-08 17:22:03 +02001413 i = w83781d_read_value(data, W83781D_REG_BEEP_CONFIG);
1414 p = w83781d_read_value(data, W83781D_REG_PWMCLK12);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 /* Reset all except Watchdog values and last conversion values
1416 This sets fan-divs to 2, among others */
Jean Delvare31b8dc42007-05-08 17:22:03 +02001417 w83781d_write_value(data, W83781D_REG_CONFIG, 0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 /* Restore the registers and disable power-on abnormal beep.
1419 This saves FAN 1/2/3 input/output values set by BIOS. */
Jean Delvare31b8dc42007-05-08 17:22:03 +02001420 w83781d_write_value(data, W83781D_REG_BEEP_CONFIG, i | 0x80);
1421 w83781d_write_value(data, W83781D_REG_PWMCLK12, p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422 /* Disable master beep-enable (reset turns it on).
1423 Individual beep_mask should be reset to off but for some reason
1424 disabling this bit helps some people not get beeped */
Jean Delvare31b8dc42007-05-08 17:22:03 +02001425 w83781d_write_value(data, W83781D_REG_BEEP_INTS2, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426 }
1427
Jean Delvarefabddcd2006-02-05 23:26:51 +01001428 /* Disable power-on abnormal beep, as advised by the datasheet.
1429 Already done if reset=1. */
1430 if (init && !reset && type != as99127f) {
Jean Delvare31b8dc42007-05-08 17:22:03 +02001431 i = w83781d_read_value(data, W83781D_REG_BEEP_CONFIG);
1432 w83781d_write_value(data, W83781D_REG_BEEP_CONFIG, i | 0x80);
Jean Delvarefabddcd2006-02-05 23:26:51 +01001433 }
1434
Jean Delvare303760b2005-07-31 21:52:01 +02001435 data->vrm = vid_which_vrm();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436
1437 if ((type != w83781d) && (type != as99127f)) {
Jean Delvare31b8dc42007-05-08 17:22:03 +02001438 tmp = w83781d_read_value(data, W83781D_REG_SCFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439 for (i = 1; i <= 3; i++) {
1440 if (!(tmp & BIT_SCFG1[i - 1])) {
Jean Delvareb26f9332007-08-16 14:30:01 +02001441 data->sens[i - 1] = 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442 } else {
1443 if (w83781d_read_value
Jean Delvare31b8dc42007-05-08 17:22:03 +02001444 (data,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 W83781D_REG_SCFG2) & BIT_SCFG2[i - 1])
1446 data->sens[i - 1] = 1;
1447 else
1448 data->sens[i - 1] = 2;
1449 }
Jean Delvare7c7a5302005-06-16 19:24:14 +02001450 if (type == w83783s && i == 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451 break;
1452 }
1453 }
1454
1455 if (init && type != as99127f) {
1456 /* Enable temp2 */
Jean Delvare31b8dc42007-05-08 17:22:03 +02001457 tmp = w83781d_read_value(data, W83781D_REG_TEMP2_CONFIG);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458 if (tmp & 0x01) {
Jean Delvare7666c132007-05-08 17:22:02 +02001459 dev_warn(dev, "Enabling temp2, readings "
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460 "might not make sense\n");
Jean Delvare31b8dc42007-05-08 17:22:03 +02001461 w83781d_write_value(data, W83781D_REG_TEMP2_CONFIG,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462 tmp & 0xfe);
1463 }
1464
1465 /* Enable temp3 */
Jean Delvare7c7a5302005-06-16 19:24:14 +02001466 if (type != w83783s) {
Jean Delvare31b8dc42007-05-08 17:22:03 +02001467 tmp = w83781d_read_value(data,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 W83781D_REG_TEMP3_CONFIG);
1469 if (tmp & 0x01) {
Jean Delvare7666c132007-05-08 17:22:02 +02001470 dev_warn(dev, "Enabling temp3, "
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 "readings might not make sense\n");
Jean Delvare31b8dc42007-05-08 17:22:03 +02001472 w83781d_write_value(data,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 W83781D_REG_TEMP3_CONFIG, tmp & 0xfe);
1474 }
1475 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476 }
1477
1478 /* Start monitoring */
Jean Delvare31b8dc42007-05-08 17:22:03 +02001479 w83781d_write_value(data, W83781D_REG_CONFIG,
1480 (w83781d_read_value(data,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481 W83781D_REG_CONFIG) & 0xf7)
1482 | 0x01);
Jean Delvare7666c132007-05-08 17:22:02 +02001483
1484 /* A few vars need to be filled upon startup */
Jean Delvare34875332007-05-08 17:22:03 +02001485 for (i = 0; i < 3; i++) {
1486 data->fan_min[i] = w83781d_read_value(data,
Jean Delvare7666c132007-05-08 17:22:02 +02001487 W83781D_REG_FAN_MIN(i));
1488 }
Jean Delvare7666c132007-05-08 17:22:02 +02001489
1490 mutex_init(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491}
1492
1493static struct w83781d_data *w83781d_update_device(struct device *dev)
1494{
Jean Delvare7666c132007-05-08 17:22:02 +02001495 struct w83781d_data *data = dev_get_drvdata(dev);
1496 struct i2c_client *client = &data->client;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 int i;
1498
Ingo Molnar9a61bf62006-01-18 23:19:26 +01001499 mutex_lock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500
1501 if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
1502 || !data->valid) {
1503 dev_dbg(dev, "Starting device update\n");
1504
1505 for (i = 0; i <= 8; i++) {
Jean Delvare7c7a5302005-06-16 19:24:14 +02001506 if (data->type == w83783s && i == 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507 continue; /* 783S has no in1 */
1508 data->in[i] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001509 w83781d_read_value(data, W83781D_REG_IN(i));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510 data->in_min[i] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001511 w83781d_read_value(data, W83781D_REG_IN_MIN(i));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512 data->in_max[i] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001513 w83781d_read_value(data, W83781D_REG_IN_MAX(i));
Jean Delvare05663362007-11-30 23:51:24 +01001514 if ((data->type != w83782d) && (i == 6))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 break;
1516 }
Jean Delvare34875332007-05-08 17:22:03 +02001517 for (i = 0; i < 3; i++) {
1518 data->fan[i] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001519 w83781d_read_value(data, W83781D_REG_FAN(i));
Jean Delvare34875332007-05-08 17:22:03 +02001520 data->fan_min[i] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001521 w83781d_read_value(data, W83781D_REG_FAN_MIN(i));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522 }
1523 if (data->type != w83781d && data->type != as99127f) {
Jean Delvare34875332007-05-08 17:22:03 +02001524 for (i = 0; i < 4; i++) {
1525 data->pwm[i] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001526 w83781d_read_value(data,
Jean Delvare34875332007-05-08 17:22:03 +02001527 W83781D_REG_PWM[i]);
Jean Delvare7666c132007-05-08 17:22:02 +02001528 if ((data->type != w83782d || !client->driver)
Jean Delvare34875332007-05-08 17:22:03 +02001529 && i == 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530 break;
1531 }
1532 /* Only PWM2 can be disabled */
Jean Delvare34875332007-05-08 17:22:03 +02001533 data->pwm2_enable = (w83781d_read_value(data,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534 W83781D_REG_PWMCLK12) & 0x08) >> 3;
1535 }
1536
Jean Delvare31b8dc42007-05-08 17:22:03 +02001537 data->temp = w83781d_read_value(data, W83781D_REG_TEMP(1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538 data->temp_max =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001539 w83781d_read_value(data, W83781D_REG_TEMP_OVER(1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 data->temp_max_hyst =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001541 w83781d_read_value(data, W83781D_REG_TEMP_HYST(1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542 data->temp_add[0] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001543 w83781d_read_value(data, W83781D_REG_TEMP(2));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544 data->temp_max_add[0] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001545 w83781d_read_value(data, W83781D_REG_TEMP_OVER(2));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 data->temp_max_hyst_add[0] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001547 w83781d_read_value(data, W83781D_REG_TEMP_HYST(2));
Jean Delvare7c7a5302005-06-16 19:24:14 +02001548 if (data->type != w83783s) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549 data->temp_add[1] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001550 w83781d_read_value(data, W83781D_REG_TEMP(3));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551 data->temp_max_add[1] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001552 w83781d_read_value(data,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553 W83781D_REG_TEMP_OVER(3));
1554 data->temp_max_hyst_add[1] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001555 w83781d_read_value(data,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556 W83781D_REG_TEMP_HYST(3));
1557 }
Jean Delvare31b8dc42007-05-08 17:22:03 +02001558 i = w83781d_read_value(data, W83781D_REG_VID_FANDIV);
Jean Delvare7c7a5302005-06-16 19:24:14 +02001559 data->vid = i & 0x0f;
Jean Delvare31b8dc42007-05-08 17:22:03 +02001560 data->vid |= (w83781d_read_value(data,
Jean Delvare7c7a5302005-06-16 19:24:14 +02001561 W83781D_REG_CHIPID) & 0x01) << 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562 data->fan_div[0] = (i >> 4) & 0x03;
1563 data->fan_div[1] = (i >> 6) & 0x03;
Jean Delvare31b8dc42007-05-08 17:22:03 +02001564 data->fan_div[2] = (w83781d_read_value(data,
Jean Delvare7c7a5302005-06-16 19:24:14 +02001565 W83781D_REG_PIN) >> 6) & 0x03;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566 if ((data->type != w83781d) && (data->type != as99127f)) {
Jean Delvare31b8dc42007-05-08 17:22:03 +02001567 i = w83781d_read_value(data, W83781D_REG_VBAT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568 data->fan_div[0] |= (i >> 3) & 0x04;
1569 data->fan_div[1] |= (i >> 4) & 0x04;
Jean Delvare7c7a5302005-06-16 19:24:14 +02001570 data->fan_div[2] |= (i >> 5) & 0x04;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571 }
Jean Delvare05663362007-11-30 23:51:24 +01001572 if (data->type == w83782d) {
Jean Delvare31b8dc42007-05-08 17:22:03 +02001573 data->alarms = w83781d_read_value(data,
Jean Delvarec7f5d7e2006-02-05 23:13:48 +01001574 W83782D_REG_ALARM1)
Jean Delvare31b8dc42007-05-08 17:22:03 +02001575 | (w83781d_read_value(data,
Jean Delvarec7f5d7e2006-02-05 23:13:48 +01001576 W83782D_REG_ALARM2) << 8)
Jean Delvare31b8dc42007-05-08 17:22:03 +02001577 | (w83781d_read_value(data,
Jean Delvarec7f5d7e2006-02-05 23:13:48 +01001578 W83782D_REG_ALARM3) << 16);
1579 } else if (data->type == w83783s) {
Jean Delvare31b8dc42007-05-08 17:22:03 +02001580 data->alarms = w83781d_read_value(data,
Jean Delvarec7f5d7e2006-02-05 23:13:48 +01001581 W83782D_REG_ALARM1)
Jean Delvare31b8dc42007-05-08 17:22:03 +02001582 | (w83781d_read_value(data,
Jean Delvarec7f5d7e2006-02-05 23:13:48 +01001583 W83782D_REG_ALARM2) << 8);
1584 } else {
1585 /* No real-time status registers, fall back to
1586 interrupt status registers */
Jean Delvare31b8dc42007-05-08 17:22:03 +02001587 data->alarms = w83781d_read_value(data,
Jean Delvarec7f5d7e2006-02-05 23:13:48 +01001588 W83781D_REG_ALARM1)
Jean Delvare31b8dc42007-05-08 17:22:03 +02001589 | (w83781d_read_value(data,
Jean Delvarec7f5d7e2006-02-05 23:13:48 +01001590 W83781D_REG_ALARM2) << 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591 }
Jean Delvare31b8dc42007-05-08 17:22:03 +02001592 i = w83781d_read_value(data, W83781D_REG_BEEP_INTS2);
Jean Delvare2fbbbf12008-10-17 17:51:18 +02001593 data->beep_mask = (i << 8) +
Jean Delvare31b8dc42007-05-08 17:22:03 +02001594 w83781d_read_value(data, W83781D_REG_BEEP_INTS1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595 if ((data->type != w83781d) && (data->type != as99127f)) {
1596 data->beep_mask |=
Jean Delvare31b8dc42007-05-08 17:22:03 +02001597 w83781d_read_value(data,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598 W83781D_REG_BEEP_INTS3) << 16;
1599 }
1600 data->last_updated = jiffies;
1601 data->valid = 1;
1602 }
1603
Ingo Molnar9a61bf62006-01-18 23:19:26 +01001604 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605
1606 return data;
1607}
1608
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001609#ifdef CONFIG_ISA
1610
1611/* ISA device, if found */
1612static struct platform_device *pdev;
1613
1614static unsigned short isa_address = 0x290;
1615
1616/* I2C devices get this name attribute automatically, but for ISA devices
1617 we must create it by ourselves. */
1618static ssize_t
1619show_name(struct device *dev, struct device_attribute *devattr, char *buf)
1620{
1621 struct w83781d_data *data = dev_get_drvdata(dev);
Jean Delvare360782d2008-10-17 17:51:19 +02001622 return sprintf(buf, "%s\n", data->name);
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001623}
1624static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
1625
1626static struct w83781d_data *w83781d_data_if_isa(void)
1627{
1628 return pdev ? platform_get_drvdata(pdev) : NULL;
1629}
1630
1631/* Returns 1 if the I2C chip appears to be an alias of the ISA chip */
1632static int w83781d_alias_detect(struct i2c_client *client, u8 chipid)
1633{
1634 struct w83781d_data *i2c, *isa;
1635 int i;
1636
1637 if (!pdev) /* No ISA chip */
1638 return 0;
1639
1640 i2c = i2c_get_clientdata(client);
1641 isa = platform_get_drvdata(pdev);
1642
1643 if (w83781d_read_value(isa, W83781D_REG_I2C_ADDR) != client->addr)
1644 return 0; /* Address doesn't match */
1645 if (w83781d_read_value(isa, W83781D_REG_WCHIPID) != chipid)
1646 return 0; /* Chip type doesn't match */
1647
1648 /* We compare all the limit registers, the config register and the
1649 * interrupt mask registers */
1650 for (i = 0x2b; i <= 0x3d; i++) {
1651 if (w83781d_read_value(isa, i) != w83781d_read_value(i2c, i))
1652 return 0;
1653 }
1654 if (w83781d_read_value(isa, W83781D_REG_CONFIG) !=
1655 w83781d_read_value(i2c, W83781D_REG_CONFIG))
1656 return 0;
1657 for (i = 0x43; i <= 0x46; i++) {
1658 if (w83781d_read_value(isa, i) != w83781d_read_value(i2c, i))
1659 return 0;
1660 }
1661
1662 return 1;
1663}
1664
1665static int
1666w83781d_read_value_isa(struct w83781d_data *data, u16 reg)
1667{
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001668 int word_sized, res;
1669
1670 word_sized = (((reg & 0xff00) == 0x100)
1671 || ((reg & 0xff00) == 0x200))
1672 && (((reg & 0x00ff) == 0x50)
1673 || ((reg & 0x00ff) == 0x53)
1674 || ((reg & 0x00ff) == 0x55));
1675 if (reg & 0xff00) {
1676 outb_p(W83781D_REG_BANK,
Jean Delvare360782d2008-10-17 17:51:19 +02001677 data->isa_addr + W83781D_ADDR_REG_OFFSET);
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001678 outb_p(reg >> 8,
Jean Delvare360782d2008-10-17 17:51:19 +02001679 data->isa_addr + W83781D_DATA_REG_OFFSET);
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001680 }
Jean Delvare360782d2008-10-17 17:51:19 +02001681 outb_p(reg & 0xff, data->isa_addr + W83781D_ADDR_REG_OFFSET);
1682 res = inb_p(data->isa_addr + W83781D_DATA_REG_OFFSET);
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001683 if (word_sized) {
1684 outb_p((reg & 0xff) + 1,
Jean Delvare360782d2008-10-17 17:51:19 +02001685 data->isa_addr + W83781D_ADDR_REG_OFFSET);
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001686 res =
Jean Delvare360782d2008-10-17 17:51:19 +02001687 (res << 8) + inb_p(data->isa_addr +
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001688 W83781D_DATA_REG_OFFSET);
1689 }
1690 if (reg & 0xff00) {
1691 outb_p(W83781D_REG_BANK,
Jean Delvare360782d2008-10-17 17:51:19 +02001692 data->isa_addr + W83781D_ADDR_REG_OFFSET);
1693 outb_p(0, data->isa_addr + W83781D_DATA_REG_OFFSET);
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001694 }
1695 return res;
1696}
1697
1698static void
1699w83781d_write_value_isa(struct w83781d_data *data, u16 reg, u16 value)
1700{
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001701 int word_sized;
1702
1703 word_sized = (((reg & 0xff00) == 0x100)
1704 || ((reg & 0xff00) == 0x200))
1705 && (((reg & 0x00ff) == 0x53)
1706 || ((reg & 0x00ff) == 0x55));
1707 if (reg & 0xff00) {
1708 outb_p(W83781D_REG_BANK,
Jean Delvare360782d2008-10-17 17:51:19 +02001709 data->isa_addr + W83781D_ADDR_REG_OFFSET);
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001710 outb_p(reg >> 8,
Jean Delvare360782d2008-10-17 17:51:19 +02001711 data->isa_addr + W83781D_DATA_REG_OFFSET);
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001712 }
Jean Delvare360782d2008-10-17 17:51:19 +02001713 outb_p(reg & 0xff, data->isa_addr + W83781D_ADDR_REG_OFFSET);
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001714 if (word_sized) {
1715 outb_p(value >> 8,
Jean Delvare360782d2008-10-17 17:51:19 +02001716 data->isa_addr + W83781D_DATA_REG_OFFSET);
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001717 outb_p((reg & 0xff) + 1,
Jean Delvare360782d2008-10-17 17:51:19 +02001718 data->isa_addr + W83781D_ADDR_REG_OFFSET);
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001719 }
Jean Delvare360782d2008-10-17 17:51:19 +02001720 outb_p(value & 0xff, data->isa_addr + W83781D_DATA_REG_OFFSET);
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001721 if (reg & 0xff00) {
1722 outb_p(W83781D_REG_BANK,
Jean Delvare360782d2008-10-17 17:51:19 +02001723 data->isa_addr + W83781D_ADDR_REG_OFFSET);
1724 outb_p(0, data->isa_addr + W83781D_DATA_REG_OFFSET);
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001725 }
1726}
1727
1728/* The SMBus locks itself, usually, but nothing may access the Winbond between
1729 bank switches. ISA access must always be locked explicitly!
1730 We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks,
1731 would slow down the W83781D access and should not be necessary.
1732 There are some ugly typecasts here, but the good news is - they should
1733 nowhere else be necessary! */
1734static int
1735w83781d_read_value(struct w83781d_data *data, u16 reg)
1736{
1737 struct i2c_client *client = &data->client;
1738 int res;
1739
1740 mutex_lock(&data->lock);
1741 if (client->driver)
1742 res = w83781d_read_value_i2c(data, reg);
1743 else
1744 res = w83781d_read_value_isa(data, reg);
1745 mutex_unlock(&data->lock);
1746 return res;
1747}
1748
1749static int
1750w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value)
1751{
1752 struct i2c_client *client = &data->client;
1753
1754 mutex_lock(&data->lock);
1755 if (client->driver)
1756 w83781d_write_value_i2c(data, reg, value);
1757 else
1758 w83781d_write_value_isa(data, reg, value);
1759 mutex_unlock(&data->lock);
1760 return 0;
1761}
1762
1763static int __devinit
1764w83781d_isa_probe(struct platform_device *pdev)
1765{
1766 int err, reg;
1767 struct w83781d_data *data;
1768 struct resource *res;
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001769
1770 /* Reserve the ISA region */
1771 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
1772 if (!request_region(res->start + W83781D_ADDR_REG_OFFSET, 2,
1773 "w83781d")) {
1774 err = -EBUSY;
1775 goto exit;
1776 }
1777
1778 data = kzalloc(sizeof(struct w83781d_data), GFP_KERNEL);
1779 if (!data) {
1780 err = -ENOMEM;
1781 goto exit_release_region;
1782 }
1783 mutex_init(&data->lock);
Jean Delvare360782d2008-10-17 17:51:19 +02001784 data->isa_addr = res->start;
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001785 platform_set_drvdata(pdev, data);
1786
1787 reg = w83781d_read_value(data, W83781D_REG_WCHIPID);
1788 switch (reg) {
1789 case 0x30:
1790 data->type = w83782d;
Jean Delvare360782d2008-10-17 17:51:19 +02001791 data->name = "w83782d";
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001792 break;
1793 default:
1794 data->type = w83781d;
Jean Delvare360782d2008-10-17 17:51:19 +02001795 data->name = "w83781d";
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001796 }
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001797
1798 /* Initialize the W83781D chip */
1799 w83781d_init_device(&pdev->dev);
1800
1801 /* Register sysfs hooks */
1802 err = w83781d_create_files(&pdev->dev, data->type, 1);
1803 if (err)
1804 goto exit_remove_files;
1805
1806 err = device_create_file(&pdev->dev, &dev_attr_name);
1807 if (err)
1808 goto exit_remove_files;
1809
1810 data->hwmon_dev = hwmon_device_register(&pdev->dev);
1811 if (IS_ERR(data->hwmon_dev)) {
1812 err = PTR_ERR(data->hwmon_dev);
1813 goto exit_remove_files;
1814 }
1815
1816 return 0;
1817
1818 exit_remove_files:
1819 sysfs_remove_group(&pdev->dev.kobj, &w83781d_group);
1820 sysfs_remove_group(&pdev->dev.kobj, &w83781d_group_opt);
1821 device_remove_file(&pdev->dev, &dev_attr_name);
1822 kfree(data);
1823 exit_release_region:
1824 release_region(res->start + W83781D_ADDR_REG_OFFSET, 2);
1825 exit:
1826 return err;
1827}
1828
1829static int __devexit
1830w83781d_isa_remove(struct platform_device *pdev)
1831{
1832 struct w83781d_data *data = platform_get_drvdata(pdev);
1833
1834 hwmon_device_unregister(data->hwmon_dev);
1835 sysfs_remove_group(&pdev->dev.kobj, &w83781d_group);
1836 sysfs_remove_group(&pdev->dev.kobj, &w83781d_group_opt);
1837 device_remove_file(&pdev->dev, &dev_attr_name);
Jean Delvare360782d2008-10-17 17:51:19 +02001838 release_region(data->isa_addr + W83781D_ADDR_REG_OFFSET, 2);
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001839 kfree(data);
1840
1841 return 0;
1842}
1843
1844static struct platform_driver w83781d_isa_driver = {
1845 .driver = {
1846 .owner = THIS_MODULE,
1847 .name = "w83781d",
1848 },
1849 .probe = w83781d_isa_probe,
1850 .remove = __devexit_p(w83781d_isa_remove),
1851};
1852
Jean Delvare7666c132007-05-08 17:22:02 +02001853/* return 1 if a supported chip is found, 0 otherwise */
1854static int __init
1855w83781d_isa_found(unsigned short address)
1856{
1857 int val, save, found = 0;
1858
Jean Delvare2961cb22008-03-09 13:34:28 +01001859 /* We have to request the region in two parts because some
1860 boards declare base+4 to base+7 as a PNP device */
1861 if (!request_region(address, 4, "w83781d")) {
1862 pr_debug("w83781d: Failed to request low part of region\n");
Jean Delvare7666c132007-05-08 17:22:02 +02001863 return 0;
Jean Delvare2961cb22008-03-09 13:34:28 +01001864 }
1865 if (!request_region(address + 4, 4, "w83781d")) {
1866 pr_debug("w83781d: Failed to request high part of region\n");
1867 release_region(address, 4);
1868 return 0;
1869 }
Jean Delvare7666c132007-05-08 17:22:02 +02001870
1871#define REALLY_SLOW_IO
1872 /* We need the timeouts for at least some W83781D-like
1873 chips. But only if we read 'undefined' registers. */
1874 val = inb_p(address + 1);
1875 if (inb_p(address + 2) != val
1876 || inb_p(address + 3) != val
1877 || inb_p(address + 7) != val) {
1878 pr_debug("w83781d: Detection failed at step 1\n");
1879 goto release;
1880 }
1881#undef REALLY_SLOW_IO
1882
1883 /* We should be able to change the 7 LSB of the address port. The
1884 MSB (busy flag) should be clear initially, set after the write. */
1885 save = inb_p(address + W83781D_ADDR_REG_OFFSET);
1886 if (save & 0x80) {
1887 pr_debug("w83781d: Detection failed at step 2\n");
1888 goto release;
1889 }
1890 val = ~save & 0x7f;
1891 outb_p(val, address + W83781D_ADDR_REG_OFFSET);
1892 if (inb_p(address + W83781D_ADDR_REG_OFFSET) != (val | 0x80)) {
1893 outb_p(save, address + W83781D_ADDR_REG_OFFSET);
1894 pr_debug("w83781d: Detection failed at step 3\n");
1895 goto release;
1896 }
1897
1898 /* We found a device, now see if it could be a W83781D */
1899 outb_p(W83781D_REG_CONFIG, address + W83781D_ADDR_REG_OFFSET);
1900 val = inb_p(address + W83781D_DATA_REG_OFFSET);
1901 if (val & 0x80) {
1902 pr_debug("w83781d: Detection failed at step 4\n");
1903 goto release;
1904 }
1905 outb_p(W83781D_REG_BANK, address + W83781D_ADDR_REG_OFFSET);
1906 save = inb_p(address + W83781D_DATA_REG_OFFSET);
1907 outb_p(W83781D_REG_CHIPMAN, address + W83781D_ADDR_REG_OFFSET);
1908 val = inb_p(address + W83781D_DATA_REG_OFFSET);
1909 if ((!(save & 0x80) && (val != 0xa3))
1910 || ((save & 0x80) && (val != 0x5c))) {
1911 pr_debug("w83781d: Detection failed at step 5\n");
1912 goto release;
1913 }
1914 outb_p(W83781D_REG_I2C_ADDR, address + W83781D_ADDR_REG_OFFSET);
1915 val = inb_p(address + W83781D_DATA_REG_OFFSET);
1916 if (val < 0x03 || val > 0x77) { /* Not a valid I2C address */
1917 pr_debug("w83781d: Detection failed at step 6\n");
1918 goto release;
1919 }
1920
1921 /* The busy flag should be clear again */
1922 if (inb_p(address + W83781D_ADDR_REG_OFFSET) & 0x80) {
1923 pr_debug("w83781d: Detection failed at step 7\n");
1924 goto release;
1925 }
1926
1927 /* Determine the chip type */
1928 outb_p(W83781D_REG_BANK, address + W83781D_ADDR_REG_OFFSET);
1929 save = inb_p(address + W83781D_DATA_REG_OFFSET);
1930 outb_p(save & 0xf8, address + W83781D_DATA_REG_OFFSET);
1931 outb_p(W83781D_REG_WCHIPID, address + W83781D_ADDR_REG_OFFSET);
1932 val = inb_p(address + W83781D_DATA_REG_OFFSET);
1933 if ((val & 0xfe) == 0x10 /* W83781D */
Jean Delvare05663362007-11-30 23:51:24 +01001934 || val == 0x30) /* W83782D */
Jean Delvare7666c132007-05-08 17:22:02 +02001935 found = 1;
1936
1937 if (found)
1938 pr_info("w83781d: Found a %s chip at %#x\n",
Jean Delvare7666c132007-05-08 17:22:02 +02001939 val == 0x30 ? "W83782D" : "W83781D", (int)address);
1940
1941 release:
Jean Delvare2961cb22008-03-09 13:34:28 +01001942 release_region(address + 4, 4);
1943 release_region(address, 4);
Jean Delvare7666c132007-05-08 17:22:02 +02001944 return found;
1945}
1946
1947static int __init
1948w83781d_isa_device_add(unsigned short address)
1949{
1950 struct resource res = {
1951 .start = address,
Jean Delvare15bde2f2007-08-29 10:39:57 +02001952 .end = address + W83781D_EXTENT - 1,
Jean Delvare7666c132007-05-08 17:22:02 +02001953 .name = "w83781d",
1954 .flags = IORESOURCE_IO,
1955 };
1956 int err;
1957
1958 pdev = platform_device_alloc("w83781d", address);
1959 if (!pdev) {
1960 err = -ENOMEM;
1961 printk(KERN_ERR "w83781d: Device allocation failed\n");
1962 goto exit;
1963 }
1964
1965 err = platform_device_add_resources(pdev, &res, 1);
1966 if (err) {
1967 printk(KERN_ERR "w83781d: Device resource addition failed "
1968 "(%d)\n", err);
1969 goto exit_device_put;
1970 }
1971
1972 err = platform_device_add(pdev);
1973 if (err) {
1974 printk(KERN_ERR "w83781d: Device addition failed (%d)\n",
1975 err);
1976 goto exit_device_put;
1977 }
1978
1979 return 0;
1980
1981 exit_device_put:
1982 platform_device_put(pdev);
1983 exit:
1984 pdev = NULL;
1985 return err;
1986}
1987
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988static int __init
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02001989w83781d_isa_register(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990{
Jean Delvarefde09502005-07-19 23:51:07 +02001991 int res;
1992
Jean Delvare7666c132007-05-08 17:22:02 +02001993 if (w83781d_isa_found(isa_address)) {
1994 res = platform_driver_register(&w83781d_isa_driver);
1995 if (res)
Jean Delvarec6566202008-10-17 17:51:18 +02001996 goto exit;
Jean Delvare7666c132007-05-08 17:22:02 +02001997
1998 /* Sets global pdev as a side effect */
1999 res = w83781d_isa_device_add(isa_address);
2000 if (res)
2001 goto exit_unreg_isa_driver;
2002 }
Jean Delvarefde09502005-07-19 23:51:07 +02002003
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02002004 return 0;
2005
2006exit_unreg_isa_driver:
2007 platform_driver_unregister(&w83781d_isa_driver);
2008exit:
2009 return res;
2010}
2011
2012static void __exit
2013w83781d_isa_unregister(void)
2014{
2015 if (pdev) {
2016 platform_device_unregister(pdev);
2017 platform_driver_unregister(&w83781d_isa_driver);
2018 }
2019}
2020#else /* !CONFIG_ISA */
2021
2022static struct w83781d_data *w83781d_data_if_isa(void)
2023{
2024 return NULL;
2025}
2026
2027static int
2028w83781d_alias_detect(struct i2c_client *client, u8 chipid)
2029{
2030 return 0;
2031}
2032
2033static int
2034w83781d_read_value(struct w83781d_data *data, u16 reg)
2035{
2036 int res;
2037
2038 mutex_lock(&data->lock);
2039 res = w83781d_read_value_i2c(data, reg);
2040 mutex_unlock(&data->lock);
2041
2042 return res;
2043}
2044
2045static int
2046w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value)
2047{
2048 mutex_lock(&data->lock);
2049 w83781d_write_value_i2c(data, reg, value);
2050 mutex_unlock(&data->lock);
2051
2052 return 0;
2053}
2054
2055static int __init
2056w83781d_isa_register(void)
2057{
2058 return 0;
2059}
2060
2061static void __exit
2062w83781d_isa_unregister(void)
2063{
2064}
2065#endif /* CONFIG_ISA */
2066
2067static int __init
2068sensors_w83781d_init(void)
2069{
2070 int res;
2071
2072 /* We register the ISA device first, so that we can skip the
2073 * registration of an I2C interface to the same device. */
2074 res = w83781d_isa_register();
2075 if (res)
2076 goto exit;
2077
Jean Delvarec6566202008-10-17 17:51:18 +02002078 res = i2c_add_driver(&w83781d_driver);
2079 if (res)
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02002080 goto exit_unreg_isa;
Jean Delvarec6566202008-10-17 17:51:18 +02002081
Jean Delvarefde09502005-07-19 23:51:07 +02002082 return 0;
Jean Delvare7666c132007-05-08 17:22:02 +02002083
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02002084 exit_unreg_isa:
2085 w83781d_isa_unregister();
Jean Delvare7666c132007-05-08 17:22:02 +02002086 exit:
2087 return res;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088}
2089
2090static void __exit
2091sensors_w83781d_exit(void)
2092{
Wolfgang Grandegger443850c2008-10-17 17:51:18 +02002093 w83781d_isa_unregister();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094 i2c_del_driver(&w83781d_driver);
2095}
2096
2097MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
2098 "Philip Edelbrock <phil@netroedge.com>, "
2099 "and Mark Studebaker <mdsxyz123@yahoo.com>");
2100MODULE_DESCRIPTION("W83781D driver");
2101MODULE_LICENSE("GPL");
2102
2103module_init(sensors_w83781d_init);
2104module_exit(sensors_w83781d_exit);