blob: 1c00d9f7c14df620ff1c5e94b2fa907bcd42f502 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 w83781d.c - Part of lm_sensors, Linux kernel modules for hardware
3 monitoring
4 Copyright (c) 1998 - 2001 Frodo Looijaard <frodol@dds.nl>,
Jean Delvare7666c132007-05-08 17:22:02 +02005 Philip Edelbrock <phil@netroedge.com>,
6 and Mark Studebaker <mdsxyz123@yahoo.com>
7 Copyright (c) 2007 Jean Delvare <khali@linux-fr.org>
Linus Torvalds1da177e2005-04-16 15:20:36 -07008
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22*/
23
24/*
25 Supports following chips:
26
27 Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
28 as99127f 7 3 0 3 0x31 0x12c3 yes no
29 as99127f rev.2 (type_name = as99127f) 0x31 0x5ca3 yes no
30 w83781d 7 3 0 3 0x10-1 0x5ca3 yes yes
Linus Torvalds1da177e2005-04-16 15:20:36 -070031 w83782d 9 3 2-4 3 0x30 0x5ca3 yes yes
32 w83783s 5-6 3 2 1-2 0x40 0x5ca3 yes no
Linus Torvalds1da177e2005-04-16 15:20:36 -070033
34*/
35
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include <linux/module.h>
37#include <linux/init.h>
38#include <linux/slab.h>
39#include <linux/jiffies.h>
40#include <linux/i2c.h>
Jean Delvare7666c132007-05-08 17:22:02 +020041#include <linux/platform_device.h>
42#include <linux/ioport.h>
Mark M. Hoffman943b0832005-07-15 21:39:18 -040043#include <linux/hwmon.h>
Jean Delvare303760b2005-07-31 21:52:01 +020044#include <linux/hwmon-vid.h>
Jean Delvare34875332007-05-08 17:22:03 +020045#include <linux/hwmon-sysfs.h>
Jim Cromie311ce2e2006-09-24 21:22:52 +020046#include <linux/sysfs.h>
Mark M. Hoffman943b0832005-07-15 21:39:18 -040047#include <linux/err.h>
Ingo Molnar9a61bf62006-01-18 23:19:26 +010048#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <asm/io.h>
50#include "lm75.h"
51
Jean Delvare7666c132007-05-08 17:22:02 +020052/* ISA device, if found */
53static struct platform_device *pdev;
54
Linus Torvalds1da177e2005-04-16 15:20:36 -070055/* Addresses to scan */
Mark M. Hoffman25e9c862008-02-17 22:28:03 -050056static const unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
57 0x2e, 0x2f, I2C_CLIENT_END };
Jean Delvare2d8672c2005-07-19 23:56:35 +020058static unsigned short isa_address = 0x290;
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
60/* Insmod parameters */
Jean Delvare05663362007-11-30 23:51:24 +010061I2C_CLIENT_INSMOD_4(w83781d, w83782d, w83783s, as99127f);
Linus Torvalds1da177e2005-04-16 15:20:36 -070062I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
63 "{bus, clientaddr, subclientaddr1, subclientaddr2}");
64
Jean Delvarefabddcd2006-02-05 23:26:51 +010065static int reset;
66module_param(reset, bool, 0);
67MODULE_PARM_DESC(reset, "Set to one to reset chip on load");
68
Linus Torvalds1da177e2005-04-16 15:20:36 -070069static int init = 1;
70module_param(init, bool, 0);
71MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
72
73/* Constants specified below */
74
75/* Length of ISA address segment */
76#define W83781D_EXTENT 8
77
78/* Where are the ISA address/data registers relative to the base address */
79#define W83781D_ADDR_REG_OFFSET 5
80#define W83781D_DATA_REG_OFFSET 6
81
Jean Delvare34875332007-05-08 17:22:03 +020082/* The device registers */
83/* in nr from 0 to 8 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070084#define W83781D_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \
85 (0x554 + (((nr) - 7) * 2)))
86#define W83781D_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \
87 (0x555 + (((nr) - 7) * 2)))
88#define W83781D_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \
89 (0x550 + (nr) - 7))
90
Jean Delvare34875332007-05-08 17:22:03 +020091/* fan nr from 0 to 2 */
92#define W83781D_REG_FAN_MIN(nr) (0x3b + (nr))
93#define W83781D_REG_FAN(nr) (0x28 + (nr))
Linus Torvalds1da177e2005-04-16 15:20:36 -070094
95#define W83781D_REG_BANK 0x4E
96#define W83781D_REG_TEMP2_CONFIG 0x152
97#define W83781D_REG_TEMP3_CONFIG 0x252
Jean Delvare34875332007-05-08 17:22:03 +020098/* temp nr from 1 to 3 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070099#define W83781D_REG_TEMP(nr) ((nr == 3) ? (0x0250) : \
100 ((nr == 2) ? (0x0150) : \
101 (0x27)))
102#define W83781D_REG_TEMP_HYST(nr) ((nr == 3) ? (0x253) : \
103 ((nr == 2) ? (0x153) : \
104 (0x3A)))
105#define W83781D_REG_TEMP_OVER(nr) ((nr == 3) ? (0x255) : \
106 ((nr == 2) ? (0x155) : \
107 (0x39)))
108
109#define W83781D_REG_CONFIG 0x40
Jean Delvarec7f5d7e2006-02-05 23:13:48 +0100110
111/* Interrupt status (W83781D, AS99127F) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112#define W83781D_REG_ALARM1 0x41
113#define W83781D_REG_ALARM2 0x42
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114
Jean Delvare05663362007-11-30 23:51:24 +0100115/* Real-time status (W83782D, W83783S) */
Jean Delvarec7f5d7e2006-02-05 23:13:48 +0100116#define W83782D_REG_ALARM1 0x459
117#define W83782D_REG_ALARM2 0x45A
118#define W83782D_REG_ALARM3 0x45B
119
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120#define W83781D_REG_BEEP_CONFIG 0x4D
121#define W83781D_REG_BEEP_INTS1 0x56
122#define W83781D_REG_BEEP_INTS2 0x57
123#define W83781D_REG_BEEP_INTS3 0x453 /* not on W83781D */
124
125#define W83781D_REG_VID_FANDIV 0x47
126
127#define W83781D_REG_CHIPID 0x49
128#define W83781D_REG_WCHIPID 0x58
129#define W83781D_REG_CHIPMAN 0x4F
130#define W83781D_REG_PIN 0x4B
131
132/* 782D/783S only */
133#define W83781D_REG_VBAT 0x5D
134
135/* PWM 782D (1-4) and 783S (1-2) only */
Jean Delvare34875332007-05-08 17:22:03 +0200136static const u8 W83781D_REG_PWM[] = { 0x5B, 0x5A, 0x5E, 0x5F };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137#define W83781D_REG_PWMCLK12 0x5C
138#define W83781D_REG_PWMCLK34 0x45C
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139
140#define W83781D_REG_I2C_ADDR 0x48
141#define W83781D_REG_I2C_SUBADDR 0x4A
142
143/* The following are undocumented in the data sheets however we
144 received the information in an email from Winbond tech support */
145/* Sensor selection - not on 781d */
146#define W83781D_REG_SCFG1 0x5D
147static const u8 BIT_SCFG1[] = { 0x02, 0x04, 0x08 };
148
149#define W83781D_REG_SCFG2 0x59
150static const u8 BIT_SCFG2[] = { 0x10, 0x20, 0x40 };
151
152#define W83781D_DEFAULT_BETA 3435
153
Jean Delvare474d00a2007-05-08 17:22:03 +0200154/* Conversions */
155#define IN_TO_REG(val) SENSORS_LIMIT(((val) + 8) / 16, 0, 255)
156#define IN_FROM_REG(val) ((val) * 16)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157
158static inline u8
159FAN_TO_REG(long rpm, int div)
160{
161 if (rpm == 0)
162 return 255;
163 rpm = SENSORS_LIMIT(rpm, 1, 1000000);
164 return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
165}
166
Jean Delvare474d00a2007-05-08 17:22:03 +0200167static inline long
168FAN_FROM_REG(u8 val, int div)
169{
170 if (val == 0)
171 return -1;
172 if (val == 255)
173 return 0;
174 return 1350000 / (val * div);
175}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176
Jean Delvare474d00a2007-05-08 17:22:03 +0200177#define TEMP_TO_REG(val) SENSORS_LIMIT((val) / 1000, -127, 128)
178#define TEMP_FROM_REG(val) ((val) * 1000)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180#define BEEP_MASK_FROM_REG(val,type) ((type) == as99127f ? \
Jean Delvare2fbbbf12008-10-17 17:51:18 +0200181 (~(val)) & 0x7fff : (val) & 0xff7fff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182#define BEEP_MASK_TO_REG(val,type) ((type) == as99127f ? \
Jean Delvare2fbbbf12008-10-17 17:51:18 +0200183 (~(val)) & 0x7fff : (val) & 0xff7fff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185#define DIV_FROM_REG(val) (1 << (val))
186
187static inline u8
188DIV_TO_REG(long val, enum chips type)
189{
190 int i;
191 val = SENSORS_LIMIT(val, 1,
192 ((type == w83781d
193 || type == as99127f) ? 8 : 128)) >> 1;
Grant Coadyabc01922005-05-12 13:41:51 +1000194 for (i = 0; i < 7; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 if (val == 0)
196 break;
197 val >>= 1;
198 }
Jean Delvare474d00a2007-05-08 17:22:03 +0200199 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200}
201
202/* There are some complications in a module like this. First off, W83781D chips
203 may be both present on the SMBus and the ISA bus, and we have to handle
204 those cases separately at some places. Second, there might be several
205 W83781D chips available (well, actually, that is probably never done; but
206 it is a clean illustration of how to handle a case like that). Finally,
207 a specific chip may be attached to *both* ISA and SMBus, and we would
Jean Delvarec6566202008-10-17 17:51:18 +0200208 not like to detect it double. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209
Jean Delvare7666c132007-05-08 17:22:02 +0200210/* For ISA chips, we abuse the i2c_client addr and name fields. We also use
211 the driver field to differentiate between I2C and ISA chips. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212struct w83781d_data {
213 struct i2c_client client;
Tony Jones1beeffe2007-08-20 13:46:20 -0700214 struct device *hwmon_dev;
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100215 struct mutex lock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216 enum chips type;
217
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100218 struct mutex update_lock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219 char valid; /* !=0 if following fields are valid */
220 unsigned long last_updated; /* In jiffies */
221
222 struct i2c_client *lm75[2]; /* for secondary I2C addresses */
223 /* array of 2 pointers to subclients */
224
225 u8 in[9]; /* Register value - 8 & 9 for 782D only */
226 u8 in_max[9]; /* Register value - 8 & 9 for 782D only */
227 u8 in_min[9]; /* Register value - 8 & 9 for 782D only */
228 u8 fan[3]; /* Register value */
229 u8 fan_min[3]; /* Register value */
Jean Delvare474d00a2007-05-08 17:22:03 +0200230 s8 temp; /* Register value */
231 s8 temp_max; /* Register value */
232 s8 temp_max_hyst; /* Register value */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 u16 temp_add[2]; /* Register value */
234 u16 temp_max_add[2]; /* Register value */
235 u16 temp_max_hyst_add[2]; /* Register value */
236 u8 fan_div[3]; /* Register encoding, shifted right */
237 u8 vid; /* Register encoding, combined */
238 u32 alarms; /* Register encoding, combined */
239 u32 beep_mask; /* Register encoding, combined */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 u8 pwm[4]; /* Register value */
Jean Delvare34875332007-05-08 17:22:03 +0200241 u8 pwm2_enable; /* Boolean */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 u16 sens[3]; /* 782D/783S only.
243 1 = pentium diode; 2 = 3904 diode;
Jean Delvareb26f9332007-08-16 14:30:01 +0200244 4 = thermistor */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245 u8 vrm;
246};
247
248static int w83781d_attach_adapter(struct i2c_adapter *adapter);
249static int w83781d_detect(struct i2c_adapter *adapter, int address, int kind);
250static int w83781d_detach_client(struct i2c_client *client);
251
Jean Delvare7666c132007-05-08 17:22:02 +0200252static int __devinit w83781d_isa_probe(struct platform_device *pdev);
253static int __devexit w83781d_isa_remove(struct platform_device *pdev);
254
Jean Delvare31b8dc42007-05-08 17:22:03 +0200255static int w83781d_read_value(struct w83781d_data *data, u16 reg);
256static int w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257static struct w83781d_data *w83781d_update_device(struct device *dev);
Jean Delvare7666c132007-05-08 17:22:02 +0200258static void w83781d_init_device(struct device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259
260static struct i2c_driver w83781d_driver = {
Laurent Riffardcdaf7932005-11-26 20:37:41 +0100261 .driver = {
Laurent Riffardcdaf7932005-11-26 20:37:41 +0100262 .name = "w83781d",
263 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264 .attach_adapter = w83781d_attach_adapter,
265 .detach_client = w83781d_detach_client,
266};
267
Jean Delvare7666c132007-05-08 17:22:02 +0200268static struct platform_driver w83781d_isa_driver = {
Laurent Riffardcdaf7932005-11-26 20:37:41 +0100269 .driver = {
Jean Delvare87218842006-09-03 22:36:14 +0200270 .owner = THIS_MODULE,
Jean Delvare7666c132007-05-08 17:22:02 +0200271 .name = "w83781d",
Laurent Riffardcdaf7932005-11-26 20:37:41 +0100272 },
Jean Delvare7666c132007-05-08 17:22:02 +0200273 .probe = w83781d_isa_probe,
274 .remove = w83781d_isa_remove,
Jean Delvarefde09502005-07-19 23:51:07 +0200275};
276
277
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278/* following are the sysfs callback functions */
279#define show_in_reg(reg) \
Jean Delvare34875332007-05-08 17:22:03 +0200280static ssize_t show_##reg (struct device *dev, struct device_attribute *da, \
281 char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282{ \
Jean Delvare34875332007-05-08 17:22:03 +0200283 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 struct w83781d_data *data = w83781d_update_device(dev); \
Jean Delvare34875332007-05-08 17:22:03 +0200285 return sprintf(buf, "%ld\n", \
286 (long)IN_FROM_REG(data->reg[attr->index])); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287}
288show_in_reg(in);
289show_in_reg(in_min);
290show_in_reg(in_max);
291
292#define store_in_reg(REG, reg) \
Jean Delvare34875332007-05-08 17:22:03 +0200293static ssize_t store_in_##reg (struct device *dev, struct device_attribute \
294 *da, const char *buf, size_t count) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295{ \
Jean Delvare34875332007-05-08 17:22:03 +0200296 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \
Jean Delvare7666c132007-05-08 17:22:02 +0200297 struct w83781d_data *data = dev_get_drvdata(dev); \
Jean Delvare34875332007-05-08 17:22:03 +0200298 int nr = attr->index; \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 u32 val; \
300 \
Jean Delvare474d00a2007-05-08 17:22:03 +0200301 val = simple_strtoul(buf, NULL, 10); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302 \
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100303 mutex_lock(&data->update_lock); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 data->in_##reg[nr] = IN_TO_REG(val); \
Jean Delvare31b8dc42007-05-08 17:22:03 +0200305 w83781d_write_value(data, W83781D_REG_IN_##REG(nr), data->in_##reg[nr]); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306 \
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100307 mutex_unlock(&data->update_lock); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 return count; \
309}
310store_in_reg(MIN, min);
311store_in_reg(MAX, max);
312
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313#define sysfs_in_offsets(offset) \
Jean Delvare34875332007-05-08 17:22:03 +0200314static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \
315 show_in, NULL, offset); \
316static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
317 show_in_min, store_in_min, offset); \
318static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
319 show_in_max, store_in_max, offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320
321sysfs_in_offsets(0);
322sysfs_in_offsets(1);
323sysfs_in_offsets(2);
324sysfs_in_offsets(3);
325sysfs_in_offsets(4);
326sysfs_in_offsets(5);
327sysfs_in_offsets(6);
328sysfs_in_offsets(7);
329sysfs_in_offsets(8);
330
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331#define show_fan_reg(reg) \
Jean Delvare34875332007-05-08 17:22:03 +0200332static ssize_t show_##reg (struct device *dev, struct device_attribute *da, \
333 char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334{ \
Jean Delvare34875332007-05-08 17:22:03 +0200335 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336 struct w83781d_data *data = w83781d_update_device(dev); \
337 return sprintf(buf,"%ld\n", \
Jean Delvare34875332007-05-08 17:22:03 +0200338 FAN_FROM_REG(data->reg[attr->index], \
339 DIV_FROM_REG(data->fan_div[attr->index]))); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340}
341show_fan_reg(fan);
342show_fan_reg(fan_min);
343
344static ssize_t
Jean Delvare34875332007-05-08 17:22:03 +0200345store_fan_min(struct device *dev, struct device_attribute *da,
346 const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347{
Jean Delvare34875332007-05-08 17:22:03 +0200348 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
Jean Delvare7666c132007-05-08 17:22:02 +0200349 struct w83781d_data *data = dev_get_drvdata(dev);
Jean Delvare34875332007-05-08 17:22:03 +0200350 int nr = attr->index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 u32 val;
352
353 val = simple_strtoul(buf, NULL, 10);
354
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100355 mutex_lock(&data->update_lock);
Jean Delvare34875332007-05-08 17:22:03 +0200356 data->fan_min[nr] =
357 FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
Jean Delvare31b8dc42007-05-08 17:22:03 +0200358 w83781d_write_value(data, W83781D_REG_FAN_MIN(nr),
Jean Delvare34875332007-05-08 17:22:03 +0200359 data->fan_min[nr]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100361 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 return count;
363}
364
Jean Delvare34875332007-05-08 17:22:03 +0200365static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
366static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR,
367 show_fan_min, store_fan_min, 0);
368static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
369static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO | S_IWUSR,
370 show_fan_min, store_fan_min, 1);
371static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2);
372static SENSOR_DEVICE_ATTR(fan3_min, S_IRUGO | S_IWUSR,
373 show_fan_min, store_fan_min, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375#define show_temp_reg(reg) \
Jean Delvare34875332007-05-08 17:22:03 +0200376static ssize_t show_##reg (struct device *dev, struct device_attribute *da, \
377 char *buf) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378{ \
Jean Delvare34875332007-05-08 17:22:03 +0200379 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 struct w83781d_data *data = w83781d_update_device(dev); \
Jean Delvare34875332007-05-08 17:22:03 +0200381 int nr = attr->index; \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 if (nr >= 2) { /* TEMP2 and TEMP3 */ \
383 return sprintf(buf,"%d\n", \
384 LM75_TEMP_FROM_REG(data->reg##_add[nr-2])); \
385 } else { /* TEMP1 */ \
386 return sprintf(buf,"%ld\n", (long)TEMP_FROM_REG(data->reg)); \
387 } \
388}
389show_temp_reg(temp);
390show_temp_reg(temp_max);
391show_temp_reg(temp_max_hyst);
392
393#define store_temp_reg(REG, reg) \
Jean Delvare34875332007-05-08 17:22:03 +0200394static ssize_t store_temp_##reg (struct device *dev, \
395 struct device_attribute *da, const char *buf, size_t count) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396{ \
Jean Delvare34875332007-05-08 17:22:03 +0200397 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \
Jean Delvare7666c132007-05-08 17:22:02 +0200398 struct w83781d_data *data = dev_get_drvdata(dev); \
Jean Delvare34875332007-05-08 17:22:03 +0200399 int nr = attr->index; \
Christian Hohnstaedt5bfedac2007-08-16 11:40:10 +0200400 long val; \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 \
402 val = simple_strtol(buf, NULL, 10); \
403 \
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100404 mutex_lock(&data->update_lock); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 \
406 if (nr >= 2) { /* TEMP2 and TEMP3 */ \
407 data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \
Jean Delvare31b8dc42007-05-08 17:22:03 +0200408 w83781d_write_value(data, W83781D_REG_TEMP_##REG(nr), \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 data->temp_##reg##_add[nr-2]); \
410 } else { /* TEMP1 */ \
411 data->temp_##reg = TEMP_TO_REG(val); \
Jean Delvare31b8dc42007-05-08 17:22:03 +0200412 w83781d_write_value(data, W83781D_REG_TEMP_##REG(nr), \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 data->temp_##reg); \
414 } \
415 \
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100416 mutex_unlock(&data->update_lock); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 return count; \
418}
419store_temp_reg(OVER, max);
420store_temp_reg(HYST, max_hyst);
421
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422#define sysfs_temp_offsets(offset) \
Jean Delvare34875332007-05-08 17:22:03 +0200423static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
424 show_temp, NULL, offset); \
425static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \
426 show_temp_max, store_temp_max, offset); \
427static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \
428 show_temp_max_hyst, store_temp_max_hyst, offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429
430sysfs_temp_offsets(1);
431sysfs_temp_offsets(2);
432sysfs_temp_offsets(3);
433
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434static ssize_t
Yani Ioannoue404e272005-05-17 06:42:58 -0400435show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436{
437 struct w83781d_data *data = w83781d_update_device(dev);
438 return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
439}
440
Jim Cromie311ce2e2006-09-24 21:22:52 +0200441static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
442
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443static ssize_t
Yani Ioannoue404e272005-05-17 06:42:58 -0400444show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445{
Jean Delvare90d66192007-10-08 18:24:35 +0200446 struct w83781d_data *data = dev_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 return sprintf(buf, "%ld\n", (long) data->vrm);
448}
449
450static ssize_t
Yani Ioannoue404e272005-05-17 06:42:58 -0400451store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452{
Jean Delvare7666c132007-05-08 17:22:02 +0200453 struct w83781d_data *data = dev_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 u32 val;
455
456 val = simple_strtoul(buf, NULL, 10);
457 data->vrm = val;
458
459 return count;
460}
461
Jim Cromie311ce2e2006-09-24 21:22:52 +0200462static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
463
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464static ssize_t
Yani Ioannoue404e272005-05-17 06:42:58 -0400465show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466{
467 struct w83781d_data *data = w83781d_update_device(dev);
Jean Delvare68188ba2005-05-16 18:52:38 +0200468 return sprintf(buf, "%u\n", data->alarms);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469}
470
Jim Cromie311ce2e2006-09-24 21:22:52 +0200471static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
472
Jean Delvare7d4a1372007-10-08 18:29:43 +0200473static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
474 char *buf)
475{
476 struct w83781d_data *data = w83781d_update_device(dev);
477 int bitnr = to_sensor_dev_attr(attr)->index;
478 return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
479}
480
481/* The W83781D has a single alarm bit for temp2 and temp3 */
482static ssize_t show_temp3_alarm(struct device *dev,
483 struct device_attribute *attr, char *buf)
484{
485 struct w83781d_data *data = w83781d_update_device(dev);
486 int bitnr = (data->type == w83781d) ? 5 : 13;
487 return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
488}
489
490static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
491static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
492static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
493static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
494static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8);
495static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9);
496static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 10);
497static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 16);
498static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 17);
499static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6);
500static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7);
501static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11);
502static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4);
503static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5);
504static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_temp3_alarm, NULL, 0);
505
Yani Ioannoue404e272005-05-17 06:42:58 -0400506static ssize_t show_beep_mask (struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507{
508 struct w83781d_data *data = w83781d_update_device(dev);
509 return sprintf(buf, "%ld\n",
510 (long)BEEP_MASK_FROM_REG(data->beep_mask, data->type));
511}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513static ssize_t
Jean Delvare34875332007-05-08 17:22:03 +0200514store_beep_mask(struct device *dev, struct device_attribute *attr,
515 const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516{
Jean Delvare7666c132007-05-08 17:22:02 +0200517 struct w83781d_data *data = dev_get_drvdata(dev);
Jean Delvare34875332007-05-08 17:22:03 +0200518 u32 val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519
520 val = simple_strtoul(buf, NULL, 10);
521
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100522 mutex_lock(&data->update_lock);
Jean Delvare2fbbbf12008-10-17 17:51:18 +0200523 data->beep_mask &= 0x8000; /* preserve beep enable */
524 data->beep_mask |= BEEP_MASK_TO_REG(val, data->type);
Jean Delvare34875332007-05-08 17:22:03 +0200525 w83781d_write_value(data, W83781D_REG_BEEP_INTS1,
526 data->beep_mask & 0xff);
Jean Delvare31b8dc42007-05-08 17:22:03 +0200527 w83781d_write_value(data, W83781D_REG_BEEP_INTS2,
Jean Delvare2fbbbf12008-10-17 17:51:18 +0200528 (data->beep_mask >> 8) & 0xff);
Jean Delvare34875332007-05-08 17:22:03 +0200529 if (data->type != w83781d && data->type != as99127f) {
530 w83781d_write_value(data, W83781D_REG_BEEP_INTS3,
531 ((data->beep_mask) >> 16) & 0xff);
532 }
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100533 mutex_unlock(&data->update_lock);
Jean Delvare34875332007-05-08 17:22:03 +0200534
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 return count;
536}
537
Jean Delvare34875332007-05-08 17:22:03 +0200538static DEVICE_ATTR(beep_mask, S_IRUGO | S_IWUSR,
539 show_beep_mask, store_beep_mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540
Jean Delvare7d4a1372007-10-08 18:29:43 +0200541static ssize_t show_beep(struct device *dev, struct device_attribute *attr,
542 char *buf)
543{
544 struct w83781d_data *data = w83781d_update_device(dev);
545 int bitnr = to_sensor_dev_attr(attr)->index;
546 return sprintf(buf, "%u\n", (data->beep_mask >> bitnr) & 1);
547}
548
549static ssize_t
550store_beep(struct device *dev, struct device_attribute *attr,
551 const char *buf, size_t count)
552{
553 struct w83781d_data *data = dev_get_drvdata(dev);
554 int bitnr = to_sensor_dev_attr(attr)->index;
555 unsigned long bit;
556 u8 reg;
557
558 bit = simple_strtoul(buf, NULL, 10);
559 if (bit & ~1)
560 return -EINVAL;
561
562 mutex_lock(&data->update_lock);
563 if (bit)
564 data->beep_mask |= (1 << bitnr);
565 else
566 data->beep_mask &= ~(1 << bitnr);
567
568 if (bitnr < 8) {
569 reg = w83781d_read_value(data, W83781D_REG_BEEP_INTS1);
570 if (bit)
571 reg |= (1 << bitnr);
572 else
573 reg &= ~(1 << bitnr);
574 w83781d_write_value(data, W83781D_REG_BEEP_INTS1, reg);
575 } else if (bitnr < 16) {
576 reg = w83781d_read_value(data, W83781D_REG_BEEP_INTS2);
577 if (bit)
578 reg |= (1 << (bitnr - 8));
579 else
580 reg &= ~(1 << (bitnr - 8));
581 w83781d_write_value(data, W83781D_REG_BEEP_INTS2, reg);
582 } else {
583 reg = w83781d_read_value(data, W83781D_REG_BEEP_INTS3);
584 if (bit)
585 reg |= (1 << (bitnr - 16));
586 else
587 reg &= ~(1 << (bitnr - 16));
588 w83781d_write_value(data, W83781D_REG_BEEP_INTS3, reg);
589 }
590 mutex_unlock(&data->update_lock);
591
592 return count;
593}
594
595/* The W83781D has a single beep bit for temp2 and temp3 */
596static ssize_t show_temp3_beep(struct device *dev,
597 struct device_attribute *attr, char *buf)
598{
599 struct w83781d_data *data = w83781d_update_device(dev);
600 int bitnr = (data->type == w83781d) ? 5 : 13;
601 return sprintf(buf, "%u\n", (data->beep_mask >> bitnr) & 1);
602}
603
604static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR,
605 show_beep, store_beep, 0);
606static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO | S_IWUSR,
607 show_beep, store_beep, 1);
608static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO | S_IWUSR,
609 show_beep, store_beep, 2);
610static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO | S_IWUSR,
611 show_beep, store_beep, 3);
612static SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO | S_IWUSR,
613 show_beep, store_beep, 8);
614static SENSOR_DEVICE_ATTR(in5_beep, S_IRUGO | S_IWUSR,
615 show_beep, store_beep, 9);
616static SENSOR_DEVICE_ATTR(in6_beep, S_IRUGO | S_IWUSR,
617 show_beep, store_beep, 10);
618static SENSOR_DEVICE_ATTR(in7_beep, S_IRUGO | S_IWUSR,
619 show_beep, store_beep, 16);
620static SENSOR_DEVICE_ATTR(in8_beep, S_IRUGO | S_IWUSR,
621 show_beep, store_beep, 17);
622static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO | S_IWUSR,
623 show_beep, store_beep, 6);
624static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO | S_IWUSR,
625 show_beep, store_beep, 7);
626static SENSOR_DEVICE_ATTR(fan3_beep, S_IRUGO | S_IWUSR,
627 show_beep, store_beep, 11);
628static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR,
629 show_beep, store_beep, 4);
630static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO | S_IWUSR,
631 show_beep, store_beep, 5);
632static SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO,
633 show_temp3_beep, store_beep, 13);
Jean Delvare2fbbbf12008-10-17 17:51:18 +0200634static SENSOR_DEVICE_ATTR(beep_enable, S_IRUGO | S_IWUSR,
635 show_beep, store_beep, 15);
Jean Delvare7d4a1372007-10-08 18:29:43 +0200636
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637static ssize_t
Jean Delvare34875332007-05-08 17:22:03 +0200638show_fan_div(struct device *dev, struct device_attribute *da, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639{
Jean Delvare34875332007-05-08 17:22:03 +0200640 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 struct w83781d_data *data = w83781d_update_device(dev);
642 return sprintf(buf, "%ld\n",
Jean Delvare34875332007-05-08 17:22:03 +0200643 (long) DIV_FROM_REG(data->fan_div[attr->index]));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644}
645
646/* Note: we save and restore the fan minimum here, because its value is
647 determined in part by the fan divisor. This follows the principle of
Andreas Mohrd6e05ed2006-06-26 18:35:02 +0200648 least surprise; the user doesn't expect the fan minimum to change just
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649 because the divisor changed. */
650static ssize_t
Jean Delvare34875332007-05-08 17:22:03 +0200651store_fan_div(struct device *dev, struct device_attribute *da,
652 const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653{
Jean Delvare34875332007-05-08 17:22:03 +0200654 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
Jean Delvare7666c132007-05-08 17:22:02 +0200655 struct w83781d_data *data = dev_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 unsigned long min;
Jean Delvare34875332007-05-08 17:22:03 +0200657 int nr = attr->index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 u8 reg;
659 unsigned long val = simple_strtoul(buf, NULL, 10);
660
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100661 mutex_lock(&data->update_lock);
Jean Delvare293c0992007-11-30 23:52:44 +0100662
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 /* Save fan_min */
664 min = FAN_FROM_REG(data->fan_min[nr],
665 DIV_FROM_REG(data->fan_div[nr]));
666
667 data->fan_div[nr] = DIV_TO_REG(val, data->type);
668
Jean Delvare31b8dc42007-05-08 17:22:03 +0200669 reg = (w83781d_read_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 & (nr==0 ? 0xcf : 0x3f))
671 | ((data->fan_div[nr] & 0x03) << (nr==0 ? 4 : 6));
Jean Delvare31b8dc42007-05-08 17:22:03 +0200672 w83781d_write_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673
674 /* w83781d and as99127f don't have extended divisor bits */
675 if (data->type != w83781d && data->type != as99127f) {
Jean Delvare31b8dc42007-05-08 17:22:03 +0200676 reg = (w83781d_read_value(data, W83781D_REG_VBAT)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 & ~(1 << (5 + nr)))
678 | ((data->fan_div[nr] & 0x04) << (3 + nr));
Jean Delvare31b8dc42007-05-08 17:22:03 +0200679 w83781d_write_value(data, W83781D_REG_VBAT, reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680 }
681
682 /* Restore fan_min */
683 data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
Jean Delvare34875332007-05-08 17:22:03 +0200684 w83781d_write_value(data, W83781D_REG_FAN_MIN(nr), data->fan_min[nr]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100686 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 return count;
688}
689
Jean Delvare34875332007-05-08 17:22:03 +0200690static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR,
691 show_fan_div, store_fan_div, 0);
692static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR,
693 show_fan_div, store_fan_div, 1);
694static SENSOR_DEVICE_ATTR(fan3_div, S_IRUGO | S_IWUSR,
695 show_fan_div, store_fan_div, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697static ssize_t
Jean Delvare34875332007-05-08 17:22:03 +0200698show_pwm(struct device *dev, struct device_attribute *da, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699{
Jean Delvare34875332007-05-08 17:22:03 +0200700 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 struct w83781d_data *data = w83781d_update_device(dev);
Jean Delvare34875332007-05-08 17:22:03 +0200702 return sprintf(buf, "%d\n", (int)data->pwm[attr->index]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703}
704
705static ssize_t
Jean Delvare34875332007-05-08 17:22:03 +0200706show_pwm2_enable(struct device *dev, struct device_attribute *da, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707{
708 struct w83781d_data *data = w83781d_update_device(dev);
Jean Delvare34875332007-05-08 17:22:03 +0200709 return sprintf(buf, "%d\n", (int)data->pwm2_enable);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710}
711
712static ssize_t
Jean Delvare34875332007-05-08 17:22:03 +0200713store_pwm(struct device *dev, struct device_attribute *da, const char *buf,
714 size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715{
Jean Delvare34875332007-05-08 17:22:03 +0200716 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
Jean Delvare7666c132007-05-08 17:22:02 +0200717 struct w83781d_data *data = dev_get_drvdata(dev);
Jean Delvare34875332007-05-08 17:22:03 +0200718 int nr = attr->index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 u32 val;
720
721 val = simple_strtoul(buf, NULL, 10);
722
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100723 mutex_lock(&data->update_lock);
Jean Delvare34875332007-05-08 17:22:03 +0200724 data->pwm[nr] = SENSORS_LIMIT(val, 0, 255);
725 w83781d_write_value(data, W83781D_REG_PWM[nr], data->pwm[nr]);
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100726 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 return count;
728}
729
730static ssize_t
Jean Delvare34875332007-05-08 17:22:03 +0200731store_pwm2_enable(struct device *dev, struct device_attribute *da,
732 const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733{
Jean Delvare7666c132007-05-08 17:22:02 +0200734 struct w83781d_data *data = dev_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 u32 val, reg;
736
737 val = simple_strtoul(buf, NULL, 10);
738
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100739 mutex_lock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740
741 switch (val) {
742 case 0:
743 case 1:
Jean Delvare31b8dc42007-05-08 17:22:03 +0200744 reg = w83781d_read_value(data, W83781D_REG_PWMCLK12);
745 w83781d_write_value(data, W83781D_REG_PWMCLK12,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 (reg & 0xf7) | (val << 3));
747
Jean Delvare31b8dc42007-05-08 17:22:03 +0200748 reg = w83781d_read_value(data, W83781D_REG_BEEP_CONFIG);
749 w83781d_write_value(data, W83781D_REG_BEEP_CONFIG,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 (reg & 0xef) | (!val << 4));
751
Jean Delvare34875332007-05-08 17:22:03 +0200752 data->pwm2_enable = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 break;
754
755 default:
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100756 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 return -EINVAL;
758 }
759
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100760 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 return count;
762}
763
Jean Delvare34875332007-05-08 17:22:03 +0200764static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 0);
765static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 1);
766static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 2);
767static SENSOR_DEVICE_ATTR(pwm4, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 3);
768/* only PWM2 can be enabled/disabled */
769static DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR,
770 show_pwm2_enable, store_pwm2_enable);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772static ssize_t
Jean Delvare34875332007-05-08 17:22:03 +0200773show_sensor(struct device *dev, struct device_attribute *da, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774{
Jean Delvare34875332007-05-08 17:22:03 +0200775 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 struct w83781d_data *data = w83781d_update_device(dev);
Jean Delvare34875332007-05-08 17:22:03 +0200777 return sprintf(buf, "%d\n", (int)data->sens[attr->index]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778}
779
780static ssize_t
Jean Delvare34875332007-05-08 17:22:03 +0200781store_sensor(struct device *dev, struct device_attribute *da,
782 const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783{
Jean Delvare34875332007-05-08 17:22:03 +0200784 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
Jean Delvare7666c132007-05-08 17:22:02 +0200785 struct w83781d_data *data = dev_get_drvdata(dev);
Jean Delvare34875332007-05-08 17:22:03 +0200786 int nr = attr->index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 u32 val, tmp;
788
789 val = simple_strtoul(buf, NULL, 10);
790
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100791 mutex_lock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792
793 switch (val) {
794 case 1: /* PII/Celeron diode */
Jean Delvare31b8dc42007-05-08 17:22:03 +0200795 tmp = w83781d_read_value(data, W83781D_REG_SCFG1);
796 w83781d_write_value(data, W83781D_REG_SCFG1,
Jean Delvare34875332007-05-08 17:22:03 +0200797 tmp | BIT_SCFG1[nr]);
Jean Delvare31b8dc42007-05-08 17:22:03 +0200798 tmp = w83781d_read_value(data, W83781D_REG_SCFG2);
799 w83781d_write_value(data, W83781D_REG_SCFG2,
Jean Delvare34875332007-05-08 17:22:03 +0200800 tmp | BIT_SCFG2[nr]);
801 data->sens[nr] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 break;
803 case 2: /* 3904 */
Jean Delvare31b8dc42007-05-08 17:22:03 +0200804 tmp = w83781d_read_value(data, W83781D_REG_SCFG1);
805 w83781d_write_value(data, W83781D_REG_SCFG1,
Jean Delvare34875332007-05-08 17:22:03 +0200806 tmp | BIT_SCFG1[nr]);
Jean Delvare31b8dc42007-05-08 17:22:03 +0200807 tmp = w83781d_read_value(data, W83781D_REG_SCFG2);
808 w83781d_write_value(data, W83781D_REG_SCFG2,
Jean Delvare34875332007-05-08 17:22:03 +0200809 tmp & ~BIT_SCFG2[nr]);
810 data->sens[nr] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 break;
Jean Delvareb26f9332007-08-16 14:30:01 +0200812 case W83781D_DEFAULT_BETA:
813 dev_warn(dev, "Sensor type %d is deprecated, please use 4 "
814 "instead\n", W83781D_DEFAULT_BETA);
815 /* fall through */
816 case 4: /* thermistor */
Jean Delvare31b8dc42007-05-08 17:22:03 +0200817 tmp = w83781d_read_value(data, W83781D_REG_SCFG1);
818 w83781d_write_value(data, W83781D_REG_SCFG1,
Jean Delvare34875332007-05-08 17:22:03 +0200819 tmp & ~BIT_SCFG1[nr]);
820 data->sens[nr] = val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 break;
822 default:
Jean Delvareb26f9332007-08-16 14:30:01 +0200823 dev_err(dev, "Invalid sensor type %ld; must be 1, 2, or 4\n",
824 (long) val);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 break;
826 }
827
Ingo Molnar9a61bf62006-01-18 23:19:26 +0100828 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 return count;
830}
831
Jean Delvare34875332007-05-08 17:22:03 +0200832static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO | S_IWUSR,
833 show_sensor, store_sensor, 0);
834static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO | S_IWUSR,
Mark M. Hoffman393cdad2007-08-09 08:12:46 -0400835 show_sensor, store_sensor, 1);
Jean Delvare34875332007-05-08 17:22:03 +0200836static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO | S_IWUSR,
Mark M. Hoffman393cdad2007-08-09 08:12:46 -0400837 show_sensor, store_sensor, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838
Jean Delvare7666c132007-05-08 17:22:02 +0200839/* I2C devices get this name attribute automatically, but for ISA devices
840 we must create it by ourselves. */
841static ssize_t
842show_name(struct device *dev, struct device_attribute *devattr, char *buf)
843{
844 struct w83781d_data *data = dev_get_drvdata(dev);
845 return sprintf(buf, "%s\n", data->client.name);
846}
847static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
848
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849/* This function is called when:
850 * w83781d_driver is inserted (when this module is loaded), for each
851 available adapter
Jean Delvarec6566202008-10-17 17:51:18 +0200852 * when a new adapter is inserted (and w83781d_driver is still present)
853 We block updates of the ISA device to minimize the risk of concurrent
854 access to the same W83781D chip through different interfaces. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855static int
856w83781d_attach_adapter(struct i2c_adapter *adapter)
857{
Jean Delvarec6566202008-10-17 17:51:18 +0200858 struct w83781d_data *data;
859 int err;
860
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 if (!(adapter->class & I2C_CLASS_HWMON))
862 return 0;
Jean Delvarec6566202008-10-17 17:51:18 +0200863
864 data = pdev ? platform_get_drvdata(pdev) : NULL;
865 if (data)
866 mutex_lock(&data->update_lock);
867 err = i2c_probe(adapter, &addr_data, w83781d_detect);
868 if (data)
869 mutex_unlock(&data->update_lock);
870 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871}
872
873/* Assumes that adapter is of I2C, not ISA variety.
874 * OTHERWISE DON'T CALL THIS
875 */
876static int
877w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
878 struct i2c_client *new_client)
879{
880 int i, val1 = 0, id;
881 int err;
882 const char *client_name = "";
883 struct w83781d_data *data = i2c_get_clientdata(new_client);
884
Deepak Saxenaba9c2e82005-10-17 23:08:32 +0200885 data->lm75[0] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 if (!(data->lm75[0])) {
887 err = -ENOMEM;
888 goto ERROR_SC_0;
889 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890
891 id = i2c_adapter_id(adapter);
892
893 if (force_subclients[0] == id && force_subclients[1] == address) {
894 for (i = 2; i <= 3; i++) {
895 if (force_subclients[i] < 0x48 ||
896 force_subclients[i] > 0x4f) {
897 dev_err(&new_client->dev, "Invalid subclient "
898 "address %d; must be 0x48-0x4f\n",
899 force_subclients[i]);
900 err = -EINVAL;
901 goto ERROR_SC_1;
902 }
903 }
Jean Delvare31b8dc42007-05-08 17:22:03 +0200904 w83781d_write_value(data, W83781D_REG_I2C_SUBADDR,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 (force_subclients[2] & 0x07) |
906 ((force_subclients[3] & 0x07) << 4));
907 data->lm75[0]->addr = force_subclients[2];
908 } else {
Jean Delvare31b8dc42007-05-08 17:22:03 +0200909 val1 = w83781d_read_value(data, W83781D_REG_I2C_SUBADDR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 data->lm75[0]->addr = 0x48 + (val1 & 0x07);
911 }
912
913 if (kind != w83783s) {
Deepak Saxenaba9c2e82005-10-17 23:08:32 +0200914 data->lm75[1] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 if (!(data->lm75[1])) {
916 err = -ENOMEM;
917 goto ERROR_SC_1;
918 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919
920 if (force_subclients[0] == id &&
921 force_subclients[1] == address) {
922 data->lm75[1]->addr = force_subclients[3];
923 } else {
924 data->lm75[1]->addr = 0x48 + ((val1 >> 4) & 0x07);
925 }
926 if (data->lm75[0]->addr == data->lm75[1]->addr) {
927 dev_err(&new_client->dev,
928 "Duplicate addresses 0x%x for subclients.\n",
929 data->lm75[0]->addr);
930 err = -EBUSY;
931 goto ERROR_SC_2;
932 }
933 }
934
935 if (kind == w83781d)
936 client_name = "w83781d subclient";
937 else if (kind == w83782d)
938 client_name = "w83782d subclient";
939 else if (kind == w83783s)
940 client_name = "w83783s subclient";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 else if (kind == as99127f)
942 client_name = "as99127f subclient";
943
944 for (i = 0; i <= 1; i++) {
945 /* store all data in w83781d */
946 i2c_set_clientdata(data->lm75[i], NULL);
947 data->lm75[i]->adapter = adapter;
948 data->lm75[i]->driver = &w83781d_driver;
949 data->lm75[i]->flags = 0;
950 strlcpy(data->lm75[i]->name, client_name,
951 I2C_NAME_SIZE);
952 if ((err = i2c_attach_client(data->lm75[i]))) {
953 dev_err(&new_client->dev, "Subclient %d "
954 "registration at address 0x%x "
955 "failed.\n", i, data->lm75[i]->addr);
956 if (i == 1)
957 goto ERROR_SC_3;
958 goto ERROR_SC_2;
959 }
960 if (kind == w83783s)
961 break;
962 }
963
964 return 0;
965
966/* Undo inits in case of errors */
967ERROR_SC_3:
968 i2c_detach_client(data->lm75[0]);
969ERROR_SC_2:
Jesper Juhl6044ec82005-11-07 01:01:32 -0800970 kfree(data->lm75[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971ERROR_SC_1:
Jesper Juhl6044ec82005-11-07 01:01:32 -0800972 kfree(data->lm75[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973ERROR_SC_0:
974 return err;
975}
976
Jean Delvare34875332007-05-08 17:22:03 +0200977#define IN_UNIT_ATTRS(X) \
978 &sensor_dev_attr_in##X##_input.dev_attr.attr, \
979 &sensor_dev_attr_in##X##_min.dev_attr.attr, \
Jean Delvare293c0992007-11-30 23:52:44 +0100980 &sensor_dev_attr_in##X##_max.dev_attr.attr, \
Jean Delvare7d4a1372007-10-08 18:29:43 +0200981 &sensor_dev_attr_in##X##_alarm.dev_attr.attr, \
982 &sensor_dev_attr_in##X##_beep.dev_attr.attr
Jim Cromie311ce2e2006-09-24 21:22:52 +0200983
Jean Delvare34875332007-05-08 17:22:03 +0200984#define FAN_UNIT_ATTRS(X) \
985 &sensor_dev_attr_fan##X##_input.dev_attr.attr, \
986 &sensor_dev_attr_fan##X##_min.dev_attr.attr, \
Jean Delvare7d4a1372007-10-08 18:29:43 +0200987 &sensor_dev_attr_fan##X##_div.dev_attr.attr, \
988 &sensor_dev_attr_fan##X##_alarm.dev_attr.attr, \
989 &sensor_dev_attr_fan##X##_beep.dev_attr.attr
Jim Cromie311ce2e2006-09-24 21:22:52 +0200990
Jean Delvare34875332007-05-08 17:22:03 +0200991#define TEMP_UNIT_ATTRS(X) \
992 &sensor_dev_attr_temp##X##_input.dev_attr.attr, \
993 &sensor_dev_attr_temp##X##_max.dev_attr.attr, \
Jean Delvare7d4a1372007-10-08 18:29:43 +0200994 &sensor_dev_attr_temp##X##_max_hyst.dev_attr.attr, \
995 &sensor_dev_attr_temp##X##_alarm.dev_attr.attr, \
996 &sensor_dev_attr_temp##X##_beep.dev_attr.attr
Jim Cromie311ce2e2006-09-24 21:22:52 +0200997
998static struct attribute* w83781d_attributes[] = {
999 IN_UNIT_ATTRS(0),
1000 IN_UNIT_ATTRS(2),
1001 IN_UNIT_ATTRS(3),
1002 IN_UNIT_ATTRS(4),
1003 IN_UNIT_ATTRS(5),
1004 IN_UNIT_ATTRS(6),
1005 FAN_UNIT_ATTRS(1),
1006 FAN_UNIT_ATTRS(2),
1007 FAN_UNIT_ATTRS(3),
1008 TEMP_UNIT_ATTRS(1),
1009 TEMP_UNIT_ATTRS(2),
1010 &dev_attr_cpu0_vid.attr,
1011 &dev_attr_vrm.attr,
1012 &dev_attr_alarms.attr,
1013 &dev_attr_beep_mask.attr,
Jean Delvare2fbbbf12008-10-17 17:51:18 +02001014 &sensor_dev_attr_beep_enable.dev_attr.attr,
Jim Cromie311ce2e2006-09-24 21:22:52 +02001015 NULL
1016};
1017static const struct attribute_group w83781d_group = {
1018 .attrs = w83781d_attributes,
1019};
1020
1021static struct attribute *w83781d_attributes_opt[] = {
1022 IN_UNIT_ATTRS(1),
1023 IN_UNIT_ATTRS(7),
1024 IN_UNIT_ATTRS(8),
1025 TEMP_UNIT_ATTRS(3),
Jean Delvare34875332007-05-08 17:22:03 +02001026 &sensor_dev_attr_pwm1.dev_attr.attr,
1027 &sensor_dev_attr_pwm2.dev_attr.attr,
1028 &sensor_dev_attr_pwm3.dev_attr.attr,
1029 &sensor_dev_attr_pwm4.dev_attr.attr,
Jim Cromie311ce2e2006-09-24 21:22:52 +02001030 &dev_attr_pwm2_enable.attr,
Jean Delvare34875332007-05-08 17:22:03 +02001031 &sensor_dev_attr_temp1_type.dev_attr.attr,
1032 &sensor_dev_attr_temp2_type.dev_attr.attr,
1033 &sensor_dev_attr_temp3_type.dev_attr.attr,
Jim Cromie311ce2e2006-09-24 21:22:52 +02001034 NULL
1035};
1036static const struct attribute_group w83781d_group_opt = {
1037 .attrs = w83781d_attributes_opt,
1038};
1039
Jean Delvarec6566202008-10-17 17:51:18 +02001040/* Returns 1 if the I2C chip appears to be an alias of the ISA chip */
1041static int w83781d_alias_detect(struct i2c_client *client, u8 chipid)
1042{
1043 struct w83781d_data *i2c, *isa;
1044 int i;
1045
1046 if (!pdev) /* No ISA chip */
1047 return 0;
1048
1049 i2c = i2c_get_clientdata(client);
1050 isa = platform_get_drvdata(pdev);
1051
1052 if (w83781d_read_value(isa, W83781D_REG_I2C_ADDR) != client->addr)
1053 return 0; /* Address doesn't match */
1054 if (w83781d_read_value(isa, W83781D_REG_WCHIPID) != chipid)
1055 return 0; /* Chip type doesn't match */
1056
1057 /* We compare all the limit registers, the config register and the
1058 * interrupt mask registers */
1059 for (i = 0x2b; i <= 0x3d; i++) {
1060 if (w83781d_read_value(isa, i) != w83781d_read_value(i2c, i))
1061 return 0;
1062 }
1063 if (w83781d_read_value(isa, W83781D_REG_CONFIG) !=
1064 w83781d_read_value(i2c, W83781D_REG_CONFIG))
1065 return 0;
1066 for (i = 0x43; i <= 0x46; i++) {
1067 if (w83781d_read_value(isa, i) != w83781d_read_value(i2c, i))
1068 return 0;
1069 }
1070
1071 return 1;
1072}
1073
Jean Delvare7666c132007-05-08 17:22:02 +02001074/* No clean up is done on error, it's up to the caller */
1075static int
1076w83781d_create_files(struct device *dev, int kind, int is_isa)
1077{
1078 int err;
1079
1080 if ((err = sysfs_create_group(&dev->kobj, &w83781d_group)))
1081 return err;
1082
1083 if (kind != w83783s) {
Jean Delvare34875332007-05-08 17:22:03 +02001084 if ((err = device_create_file(dev,
1085 &sensor_dev_attr_in1_input.dev_attr))
1086 || (err = device_create_file(dev,
1087 &sensor_dev_attr_in1_min.dev_attr))
1088 || (err = device_create_file(dev,
Jean Delvare7d4a1372007-10-08 18:29:43 +02001089 &sensor_dev_attr_in1_max.dev_attr))
1090 || (err = device_create_file(dev,
1091 &sensor_dev_attr_in1_alarm.dev_attr))
1092 || (err = device_create_file(dev,
1093 &sensor_dev_attr_in1_beep.dev_attr)))
Jean Delvare7666c132007-05-08 17:22:02 +02001094 return err;
1095 }
1096 if (kind != as99127f && kind != w83781d && kind != w83783s) {
Jean Delvare34875332007-05-08 17:22:03 +02001097 if ((err = device_create_file(dev,
1098 &sensor_dev_attr_in7_input.dev_attr))
1099 || (err = device_create_file(dev,
1100 &sensor_dev_attr_in7_min.dev_attr))
1101 || (err = device_create_file(dev,
1102 &sensor_dev_attr_in7_max.dev_attr))
1103 || (err = device_create_file(dev,
Jean Delvare7d4a1372007-10-08 18:29:43 +02001104 &sensor_dev_attr_in7_alarm.dev_attr))
1105 || (err = device_create_file(dev,
1106 &sensor_dev_attr_in7_beep.dev_attr))
1107 || (err = device_create_file(dev,
Jean Delvare34875332007-05-08 17:22:03 +02001108 &sensor_dev_attr_in8_input.dev_attr))
1109 || (err = device_create_file(dev,
1110 &sensor_dev_attr_in8_min.dev_attr))
1111 || (err = device_create_file(dev,
Jean Delvare7d4a1372007-10-08 18:29:43 +02001112 &sensor_dev_attr_in8_max.dev_attr))
1113 || (err = device_create_file(dev,
1114 &sensor_dev_attr_in8_alarm.dev_attr))
1115 || (err = device_create_file(dev,
1116 &sensor_dev_attr_in8_beep.dev_attr)))
Jean Delvare7666c132007-05-08 17:22:02 +02001117 return err;
1118 }
1119 if (kind != w83783s) {
Jean Delvare34875332007-05-08 17:22:03 +02001120 if ((err = device_create_file(dev,
1121 &sensor_dev_attr_temp3_input.dev_attr))
Jean Delvare7666c132007-05-08 17:22:02 +02001122 || (err = device_create_file(dev,
Jean Delvare34875332007-05-08 17:22:03 +02001123 &sensor_dev_attr_temp3_max.dev_attr))
1124 || (err = device_create_file(dev,
Jean Delvare7d4a1372007-10-08 18:29:43 +02001125 &sensor_dev_attr_temp3_max_hyst.dev_attr))
1126 || (err = device_create_file(dev,
1127 &sensor_dev_attr_temp3_alarm.dev_attr))
1128 || (err = device_create_file(dev,
1129 &sensor_dev_attr_temp3_beep.dev_attr)))
Jean Delvare7666c132007-05-08 17:22:02 +02001130 return err;
Jean Delvare7d4a1372007-10-08 18:29:43 +02001131
Jean Delvare7768aa72007-10-25 13:11:01 +02001132 if (kind != w83781d) {
Jean Delvare7d4a1372007-10-08 18:29:43 +02001133 err = sysfs_chmod_file(&dev->kobj,
1134 &sensor_dev_attr_temp3_alarm.dev_attr.attr,
1135 S_IRUGO | S_IWUSR);
1136 if (err)
1137 return err;
Jean Delvare7768aa72007-10-25 13:11:01 +02001138 }
Jean Delvare7666c132007-05-08 17:22:02 +02001139 }
1140
1141 if (kind != w83781d && kind != as99127f) {
Jean Delvare34875332007-05-08 17:22:03 +02001142 if ((err = device_create_file(dev,
1143 &sensor_dev_attr_pwm1.dev_attr))
1144 || (err = device_create_file(dev,
1145 &sensor_dev_attr_pwm2.dev_attr))
Jean Delvare7666c132007-05-08 17:22:02 +02001146 || (err = device_create_file(dev, &dev_attr_pwm2_enable)))
1147 return err;
1148 }
1149 if (kind == w83782d && !is_isa) {
Jean Delvare34875332007-05-08 17:22:03 +02001150 if ((err = device_create_file(dev,
1151 &sensor_dev_attr_pwm3.dev_attr))
1152 || (err = device_create_file(dev,
1153 &sensor_dev_attr_pwm4.dev_attr)))
Jean Delvare7666c132007-05-08 17:22:02 +02001154 return err;
1155 }
1156
1157 if (kind != as99127f && kind != w83781d) {
Jean Delvare34875332007-05-08 17:22:03 +02001158 if ((err = device_create_file(dev,
1159 &sensor_dev_attr_temp1_type.dev_attr))
Jean Delvare7666c132007-05-08 17:22:02 +02001160 || (err = device_create_file(dev,
Jean Delvare34875332007-05-08 17:22:03 +02001161 &sensor_dev_attr_temp2_type.dev_attr)))
Jean Delvare7666c132007-05-08 17:22:02 +02001162 return err;
1163 if (kind != w83783s) {
1164 if ((err = device_create_file(dev,
Jean Delvare34875332007-05-08 17:22:03 +02001165 &sensor_dev_attr_temp3_type.dev_attr)))
Jean Delvare7666c132007-05-08 17:22:02 +02001166 return err;
1167 }
1168 }
1169
1170 if (is_isa) {
1171 err = device_create_file(&pdev->dev, &dev_attr_name);
1172 if (err)
1173 return err;
1174 }
1175
1176 return 0;
1177}
1178
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179static int
1180w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
1181{
Jean Delvare7666c132007-05-08 17:22:02 +02001182 int val1 = 0, val2;
Jim Cromie311ce2e2006-09-24 21:22:52 +02001183 struct i2c_client *client;
1184 struct device *dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185 struct w83781d_data *data;
1186 int err;
1187 const char *client_name = "";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 enum vendor { winbond, asus } vendid;
1189
Jean Delvare7666c132007-05-08 17:22:02 +02001190 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191 err = -EINVAL;
Jean Delvare7666c132007-05-08 17:22:02 +02001192 goto ERROR1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193 }
1194
1195 /* OK. For now, we presume we have a valid client. We now create the
1196 client structure, even though we cannot fill it completely yet.
1197 But it allows us to access w83781d_{read,write}_value. */
1198
Deepak Saxenaba9c2e82005-10-17 23:08:32 +02001199 if (!(data = kzalloc(sizeof(struct w83781d_data), GFP_KERNEL))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 err = -ENOMEM;
1201 goto ERROR1;
1202 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203
Jim Cromie311ce2e2006-09-24 21:22:52 +02001204 client = &data->client;
1205 i2c_set_clientdata(client, data);
1206 client->addr = address;
Ingo Molnar9a61bf62006-01-18 23:19:26 +01001207 mutex_init(&data->lock);
Jim Cromie311ce2e2006-09-24 21:22:52 +02001208 client->adapter = adapter;
Jean Delvare7666c132007-05-08 17:22:02 +02001209 client->driver = &w83781d_driver;
Jim Cromie311ce2e2006-09-24 21:22:52 +02001210 dev = &client->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211
1212 /* Now, we do the remaining detection. */
1213
1214 /* The w8378?d may be stuck in some other bank than bank 0. This may
1215 make reading other information impossible. Specify a force=... or
1216 force_*=... parameter, and the Winbond will be reset to the right
1217 bank. */
1218 if (kind < 0) {
Jean Delvare31b8dc42007-05-08 17:22:03 +02001219 if (w83781d_read_value(data, W83781D_REG_CONFIG) & 0x80) {
Jean Delvarebd452e62006-10-13 17:03:42 +02001220 dev_dbg(&adapter->dev, "Detection of w83781d chip "
1221 "failed at step 3\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 err = -ENODEV;
1223 goto ERROR2;
1224 }
Jean Delvare31b8dc42007-05-08 17:22:03 +02001225 val1 = w83781d_read_value(data, W83781D_REG_BANK);
1226 val2 = w83781d_read_value(data, W83781D_REG_CHIPMAN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 /* Check for Winbond or Asus ID if in bank 0 */
1228 if ((!(val1 & 0x07)) &&
1229 (((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3))
1230 || ((val1 & 0x80) && (val2 != 0x5c) && (val2 != 0x12)))) {
Jean Delvarebd452e62006-10-13 17:03:42 +02001231 dev_dbg(&adapter->dev, "Detection of w83781d chip "
1232 "failed at step 4\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233 err = -ENODEV;
1234 goto ERROR2;
1235 }
1236 /* If Winbond SMBus, check address at 0x48.
1237 Asus doesn't support, except for as99127f rev.2 */
Jean Delvare7666c132007-05-08 17:22:02 +02001238 if ((!(val1 & 0x80) && (val2 == 0xa3)) ||
1239 ((val1 & 0x80) && (val2 == 0x5c))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240 if (w83781d_read_value
Jean Delvare31b8dc42007-05-08 17:22:03 +02001241 (data, W83781D_REG_I2C_ADDR) != address) {
Jean Delvarebd452e62006-10-13 17:03:42 +02001242 dev_dbg(&adapter->dev, "Detection of w83781d "
1243 "chip failed at step 5\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 err = -ENODEV;
1245 goto ERROR2;
1246 }
1247 }
1248 }
1249
1250 /* We have either had a force parameter, or we have already detected the
1251 Winbond. Put it now into bank 0 and Vendor ID High Byte */
Jean Delvare31b8dc42007-05-08 17:22:03 +02001252 w83781d_write_value(data, W83781D_REG_BANK,
1253 (w83781d_read_value(data, W83781D_REG_BANK)
Jim Cromie311ce2e2006-09-24 21:22:52 +02001254 & 0x78) | 0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255
1256 /* Determine the chip type. */
1257 if (kind <= 0) {
1258 /* get vendor ID */
Jean Delvare31b8dc42007-05-08 17:22:03 +02001259 val2 = w83781d_read_value(data, W83781D_REG_CHIPMAN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260 if (val2 == 0x5c)
1261 vendid = winbond;
1262 else if (val2 == 0x12)
1263 vendid = asus;
1264 else {
Jean Delvarebd452e62006-10-13 17:03:42 +02001265 dev_dbg(&adapter->dev, "w83781d chip vendor is "
1266 "neither Winbond nor Asus\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267 err = -ENODEV;
1268 goto ERROR2;
1269 }
1270
Jean Delvare31b8dc42007-05-08 17:22:03 +02001271 val1 = w83781d_read_value(data, W83781D_REG_WCHIPID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272 if ((val1 == 0x10 || val1 == 0x11) && vendid == winbond)
1273 kind = w83781d;
1274 else if (val1 == 0x30 && vendid == winbond)
1275 kind = w83782d;
Jean Delvare7666c132007-05-08 17:22:02 +02001276 else if (val1 == 0x40 && vendid == winbond && address == 0x2d)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277 kind = w83783s;
Jean Delvare6722fea2007-10-07 12:25:46 +02001278 else if (val1 == 0x31)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279 kind = as99127f;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 else {
1281 if (kind == 0)
Jean Delvarebd452e62006-10-13 17:03:42 +02001282 dev_warn(&adapter->dev, "Ignoring 'force' "
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283 "parameter for unknown chip at "
Jean Delvarebd452e62006-10-13 17:03:42 +02001284 "address 0x%02x\n", address);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285 err = -EINVAL;
1286 goto ERROR2;
1287 }
Jean Delvarec6566202008-10-17 17:51:18 +02001288
1289 if ((kind == w83781d || kind == w83782d)
1290 && w83781d_alias_detect(client, val1)) {
1291 dev_dbg(&adapter->dev, "Device at 0x%02x appears to "
1292 "be the same as ISA device\n", address);
1293 err = -ENODEV;
1294 goto ERROR2;
1295 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 }
1297
1298 if (kind == w83781d) {
1299 client_name = "w83781d";
1300 } else if (kind == w83782d) {
1301 client_name = "w83782d";
1302 } else if (kind == w83783s) {
1303 client_name = "w83783s";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304 } else if (kind == as99127f) {
1305 client_name = "as99127f";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306 }
1307
1308 /* Fill in the remaining client fields and put into the global list */
Jim Cromie311ce2e2006-09-24 21:22:52 +02001309 strlcpy(client->name, client_name, I2C_NAME_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310 data->type = kind;
1311
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312 /* Tell the I2C layer a new client has arrived */
Jim Cromie311ce2e2006-09-24 21:22:52 +02001313 if ((err = i2c_attach_client(client)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 goto ERROR2;
1315
1316 /* attach secondary i2c lm75-like clients */
Jean Delvare7666c132007-05-08 17:22:02 +02001317 if ((err = w83781d_detect_subclients(adapter, address,
1318 kind, client)))
1319 goto ERROR3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320
1321 /* Initialize the chip */
Jean Delvare7666c132007-05-08 17:22:02 +02001322 w83781d_init_device(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323
1324 /* Register sysfs hooks */
Jean Delvare7666c132007-05-08 17:22:02 +02001325 err = w83781d_create_files(dev, kind, 0);
1326 if (err)
Jim Cromie311ce2e2006-09-24 21:22:52 +02001327 goto ERROR4;
1328
Tony Jones1beeffe2007-08-20 13:46:20 -07001329 data->hwmon_dev = hwmon_device_register(dev);
1330 if (IS_ERR(data->hwmon_dev)) {
1331 err = PTR_ERR(data->hwmon_dev);
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001332 goto ERROR4;
1333 }
1334
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335 return 0;
1336
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001337ERROR4:
Jim Cromie311ce2e2006-09-24 21:22:52 +02001338 sysfs_remove_group(&dev->kobj, &w83781d_group);
1339 sysfs_remove_group(&dev->kobj, &w83781d_group_opt);
1340
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001341 if (data->lm75[1]) {
1342 i2c_detach_client(data->lm75[1]);
1343 kfree(data->lm75[1]);
1344 }
1345 if (data->lm75[0]) {
1346 i2c_detach_client(data->lm75[0]);
1347 kfree(data->lm75[0]);
1348 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349ERROR3:
Jim Cromie311ce2e2006-09-24 21:22:52 +02001350 i2c_detach_client(client);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351ERROR2:
1352 kfree(data);
1353ERROR1:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 return err;
1355}
1356
1357static int
1358w83781d_detach_client(struct i2c_client *client)
1359{
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001360 struct w83781d_data *data = i2c_get_clientdata(client);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 int err;
1362
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001363 /* main client */
Jim Cromie311ce2e2006-09-24 21:22:52 +02001364 if (data) {
Tony Jones1beeffe2007-08-20 13:46:20 -07001365 hwmon_device_unregister(data->hwmon_dev);
Jim Cromie311ce2e2006-09-24 21:22:52 +02001366 sysfs_remove_group(&client->dev.kobj, &w83781d_group);
1367 sysfs_remove_group(&client->dev.kobj, &w83781d_group_opt);
1368 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369
Jean Delvare7bef5592005-07-27 22:14:49 +02001370 if ((err = i2c_detach_client(client)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372
Mark M. Hoffman943b0832005-07-15 21:39:18 -04001373 /* main client */
1374 if (data)
1375 kfree(data);
1376
1377 /* subclient */
1378 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379 kfree(client);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380
1381 return 0;
1382}
1383
Jean Delvare7666c132007-05-08 17:22:02 +02001384static int __devinit
1385w83781d_isa_probe(struct platform_device *pdev)
1386{
1387 int err, reg;
1388 struct w83781d_data *data;
1389 struct resource *res;
1390 const char *name;
1391
1392 /* Reserve the ISA region */
1393 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
Jean Delvare2961cb22008-03-09 13:34:28 +01001394 if (!request_region(res->start + W83781D_ADDR_REG_OFFSET, 2,
1395 "w83781d")) {
Jean Delvare7666c132007-05-08 17:22:02 +02001396 err = -EBUSY;
1397 goto exit;
1398 }
1399
1400 if (!(data = kzalloc(sizeof(struct w83781d_data), GFP_KERNEL))) {
1401 err = -ENOMEM;
1402 goto exit_release_region;
1403 }
1404 mutex_init(&data->lock);
1405 data->client.addr = res->start;
1406 i2c_set_clientdata(&data->client, data);
1407 platform_set_drvdata(pdev, data);
1408
Jean Delvare31b8dc42007-05-08 17:22:03 +02001409 reg = w83781d_read_value(data, W83781D_REG_WCHIPID);
Jean Delvare7666c132007-05-08 17:22:02 +02001410 switch (reg) {
Jean Delvare7666c132007-05-08 17:22:02 +02001411 case 0x30:
1412 data->type = w83782d;
1413 name = "w83782d";
1414 break;
1415 default:
1416 data->type = w83781d;
1417 name = "w83781d";
1418 }
1419 strlcpy(data->client.name, name, I2C_NAME_SIZE);
1420
1421 /* Initialize the W83781D chip */
1422 w83781d_init_device(&pdev->dev);
1423
1424 /* Register sysfs hooks */
1425 err = w83781d_create_files(&pdev->dev, data->type, 1);
1426 if (err)
1427 goto exit_remove_files;
1428
Tony Jones1beeffe2007-08-20 13:46:20 -07001429 data->hwmon_dev = hwmon_device_register(&pdev->dev);
1430 if (IS_ERR(data->hwmon_dev)) {
1431 err = PTR_ERR(data->hwmon_dev);
Jean Delvare7666c132007-05-08 17:22:02 +02001432 goto exit_remove_files;
1433 }
1434
1435 return 0;
1436
1437 exit_remove_files:
1438 sysfs_remove_group(&pdev->dev.kobj, &w83781d_group);
1439 sysfs_remove_group(&pdev->dev.kobj, &w83781d_group_opt);
1440 device_remove_file(&pdev->dev, &dev_attr_name);
1441 kfree(data);
1442 exit_release_region:
Jean Delvare2961cb22008-03-09 13:34:28 +01001443 release_region(res->start + W83781D_ADDR_REG_OFFSET, 2);
Jean Delvare7666c132007-05-08 17:22:02 +02001444 exit:
1445 return err;
1446}
1447
1448static int __devexit
1449w83781d_isa_remove(struct platform_device *pdev)
1450{
1451 struct w83781d_data *data = platform_get_drvdata(pdev);
1452
Tony Jones1beeffe2007-08-20 13:46:20 -07001453 hwmon_device_unregister(data->hwmon_dev);
Jean Delvare7666c132007-05-08 17:22:02 +02001454 sysfs_remove_group(&pdev->dev.kobj, &w83781d_group);
1455 sysfs_remove_group(&pdev->dev.kobj, &w83781d_group_opt);
1456 device_remove_file(&pdev->dev, &dev_attr_name);
Jean Delvare2961cb22008-03-09 13:34:28 +01001457 release_region(data->client.addr + W83781D_ADDR_REG_OFFSET, 2);
Jean Delvare7666c132007-05-08 17:22:02 +02001458 kfree(data);
1459
1460 return 0;
1461}
1462
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463/* The SMBus locks itself, usually, but nothing may access the Winbond between
Jean Delvare293c0992007-11-30 23:52:44 +01001464 bank switches. ISA access must always be locked explicitly!
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks,
Jean Delvare293c0992007-11-30 23:52:44 +01001466 would slow down the W83781D access and should not be necessary.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467 There are some ugly typecasts here, but the good news is - they should
1468 nowhere else be necessary! */
1469static int
Jean Delvare31b8dc42007-05-08 17:22:03 +02001470w83781d_read_value(struct w83781d_data *data, u16 reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471{
Jean Delvare31b8dc42007-05-08 17:22:03 +02001472 struct i2c_client *client = &data->client;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 int res, word_sized, bank;
1474 struct i2c_client *cl;
1475
Ingo Molnar9a61bf62006-01-18 23:19:26 +01001476 mutex_lock(&data->lock);
Jean Delvare7666c132007-05-08 17:22:02 +02001477 if (!client->driver) { /* ISA device */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478 word_sized = (((reg & 0xff00) == 0x100)
1479 || ((reg & 0xff00) == 0x200))
1480 && (((reg & 0x00ff) == 0x50)
1481 || ((reg & 0x00ff) == 0x53)
1482 || ((reg & 0x00ff) == 0x55));
1483 if (reg & 0xff00) {
1484 outb_p(W83781D_REG_BANK,
1485 client->addr + W83781D_ADDR_REG_OFFSET);
1486 outb_p(reg >> 8,
1487 client->addr + W83781D_DATA_REG_OFFSET);
1488 }
1489 outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET);
1490 res = inb_p(client->addr + W83781D_DATA_REG_OFFSET);
1491 if (word_sized) {
1492 outb_p((reg & 0xff) + 1,
1493 client->addr + W83781D_ADDR_REG_OFFSET);
1494 res =
1495 (res << 8) + inb_p(client->addr +
1496 W83781D_DATA_REG_OFFSET);
1497 }
1498 if (reg & 0xff00) {
1499 outb_p(W83781D_REG_BANK,
1500 client->addr + W83781D_ADDR_REG_OFFSET);
1501 outb_p(0, client->addr + W83781D_DATA_REG_OFFSET);
1502 }
1503 } else {
1504 bank = (reg >> 8) & 0x0f;
1505 if (bank > 2)
1506 /* switch banks */
1507 i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
1508 bank);
1509 if (bank == 0 || bank > 2) {
1510 res = i2c_smbus_read_byte_data(client, reg & 0xff);
1511 } else {
1512 /* switch to subclient */
1513 cl = data->lm75[bank - 1];
1514 /* convert from ISA to LM75 I2C addresses */
1515 switch (reg & 0xff) {
1516 case 0x50: /* TEMP */
1517 res = swab16(i2c_smbus_read_word_data(cl, 0));
1518 break;
1519 case 0x52: /* CONFIG */
1520 res = i2c_smbus_read_byte_data(cl, 1);
1521 break;
1522 case 0x53: /* HYST */
1523 res = swab16(i2c_smbus_read_word_data(cl, 2));
1524 break;
1525 case 0x55: /* OVER */
1526 default:
1527 res = swab16(i2c_smbus_read_word_data(cl, 3));
1528 break;
1529 }
1530 }
1531 if (bank > 2)
1532 i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0);
1533 }
Ingo Molnar9a61bf62006-01-18 23:19:26 +01001534 mutex_unlock(&data->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535 return res;
1536}
1537
1538static int
Jean Delvare31b8dc42007-05-08 17:22:03 +02001539w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540{
Jean Delvare31b8dc42007-05-08 17:22:03 +02001541 struct i2c_client *client = &data->client;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542 int word_sized, bank;
1543 struct i2c_client *cl;
1544
Ingo Molnar9a61bf62006-01-18 23:19:26 +01001545 mutex_lock(&data->lock);
Jean Delvare7666c132007-05-08 17:22:02 +02001546 if (!client->driver) { /* ISA device */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547 word_sized = (((reg & 0xff00) == 0x100)
1548 || ((reg & 0xff00) == 0x200))
1549 && (((reg & 0x00ff) == 0x53)
1550 || ((reg & 0x00ff) == 0x55));
1551 if (reg & 0xff00) {
1552 outb_p(W83781D_REG_BANK,
1553 client->addr + W83781D_ADDR_REG_OFFSET);
1554 outb_p(reg >> 8,
1555 client->addr + W83781D_DATA_REG_OFFSET);
1556 }
1557 outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET);
1558 if (word_sized) {
1559 outb_p(value >> 8,
1560 client->addr + W83781D_DATA_REG_OFFSET);
1561 outb_p((reg & 0xff) + 1,
1562 client->addr + W83781D_ADDR_REG_OFFSET);
1563 }
1564 outb_p(value & 0xff, client->addr + W83781D_DATA_REG_OFFSET);
1565 if (reg & 0xff00) {
1566 outb_p(W83781D_REG_BANK,
1567 client->addr + W83781D_ADDR_REG_OFFSET);
1568 outb_p(0, client->addr + W83781D_DATA_REG_OFFSET);
1569 }
1570 } else {
1571 bank = (reg >> 8) & 0x0f;
1572 if (bank > 2)
1573 /* switch banks */
1574 i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
1575 bank);
1576 if (bank == 0 || bank > 2) {
1577 i2c_smbus_write_byte_data(client, reg & 0xff,
1578 value & 0xff);
1579 } else {
1580 /* switch to subclient */
1581 cl = data->lm75[bank - 1];
1582 /* convert from ISA to LM75 I2C addresses */
1583 switch (reg & 0xff) {
1584 case 0x52: /* CONFIG */
1585 i2c_smbus_write_byte_data(cl, 1, value & 0xff);
1586 break;
1587 case 0x53: /* HYST */
1588 i2c_smbus_write_word_data(cl, 2, swab16(value));
1589 break;
1590 case 0x55: /* OVER */
1591 i2c_smbus_write_word_data(cl, 3, swab16(value));
1592 break;
1593 }
1594 }
1595 if (bank > 2)
1596 i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0);
1597 }
Ingo Molnar9a61bf62006-01-18 23:19:26 +01001598 mutex_unlock(&data->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599 return 0;
1600}
1601
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602static void
Jean Delvare7666c132007-05-08 17:22:02 +02001603w83781d_init_device(struct device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604{
Jean Delvare7666c132007-05-08 17:22:02 +02001605 struct w83781d_data *data = dev_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 int i, p;
1607 int type = data->type;
1608 u8 tmp;
1609
Jean Delvarefabddcd2006-02-05 23:26:51 +01001610 if (reset && type != as99127f) { /* this resets registers we don't have
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611 documentation for on the as99127f */
Jean Delvarefabddcd2006-02-05 23:26:51 +01001612 /* Resetting the chip has been the default for a long time,
1613 but it causes the BIOS initializations (fan clock dividers,
1614 thermal sensor types...) to be lost, so it is now optional.
1615 It might even go away if nobody reports it as being useful,
1616 as I see very little reason why this would be needed at
1617 all. */
Jean Delvare7666c132007-05-08 17:22:02 +02001618 dev_info(dev, "If reset=1 solved a problem you were "
Jean Delvarefabddcd2006-02-05 23:26:51 +01001619 "having, please report!\n");
1620
Linus Torvalds1da177e2005-04-16 15:20:36 -07001621 /* save these registers */
Jean Delvare31b8dc42007-05-08 17:22:03 +02001622 i = w83781d_read_value(data, W83781D_REG_BEEP_CONFIG);
1623 p = w83781d_read_value(data, W83781D_REG_PWMCLK12);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624 /* Reset all except Watchdog values and last conversion values
1625 This sets fan-divs to 2, among others */
Jean Delvare31b8dc42007-05-08 17:22:03 +02001626 w83781d_write_value(data, W83781D_REG_CONFIG, 0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627 /* Restore the registers and disable power-on abnormal beep.
1628 This saves FAN 1/2/3 input/output values set by BIOS. */
Jean Delvare31b8dc42007-05-08 17:22:03 +02001629 w83781d_write_value(data, W83781D_REG_BEEP_CONFIG, i | 0x80);
1630 w83781d_write_value(data, W83781D_REG_PWMCLK12, p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 /* Disable master beep-enable (reset turns it on).
1632 Individual beep_mask should be reset to off but for some reason
1633 disabling this bit helps some people not get beeped */
Jean Delvare31b8dc42007-05-08 17:22:03 +02001634 w83781d_write_value(data, W83781D_REG_BEEP_INTS2, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635 }
1636
Jean Delvarefabddcd2006-02-05 23:26:51 +01001637 /* Disable power-on abnormal beep, as advised by the datasheet.
1638 Already done if reset=1. */
1639 if (init && !reset && type != as99127f) {
Jean Delvare31b8dc42007-05-08 17:22:03 +02001640 i = w83781d_read_value(data, W83781D_REG_BEEP_CONFIG);
1641 w83781d_write_value(data, W83781D_REG_BEEP_CONFIG, i | 0x80);
Jean Delvarefabddcd2006-02-05 23:26:51 +01001642 }
1643
Jean Delvare303760b2005-07-31 21:52:01 +02001644 data->vrm = vid_which_vrm();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645
1646 if ((type != w83781d) && (type != as99127f)) {
Jean Delvare31b8dc42007-05-08 17:22:03 +02001647 tmp = w83781d_read_value(data, W83781D_REG_SCFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648 for (i = 1; i <= 3; i++) {
1649 if (!(tmp & BIT_SCFG1[i - 1])) {
Jean Delvareb26f9332007-08-16 14:30:01 +02001650 data->sens[i - 1] = 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651 } else {
1652 if (w83781d_read_value
Jean Delvare31b8dc42007-05-08 17:22:03 +02001653 (data,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654 W83781D_REG_SCFG2) & BIT_SCFG2[i - 1])
1655 data->sens[i - 1] = 1;
1656 else
1657 data->sens[i - 1] = 2;
1658 }
Jean Delvare7c7a5302005-06-16 19:24:14 +02001659 if (type == w83783s && i == 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 break;
1661 }
1662 }
1663
1664 if (init && type != as99127f) {
1665 /* Enable temp2 */
Jean Delvare31b8dc42007-05-08 17:22:03 +02001666 tmp = w83781d_read_value(data, W83781D_REG_TEMP2_CONFIG);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667 if (tmp & 0x01) {
Jean Delvare7666c132007-05-08 17:22:02 +02001668 dev_warn(dev, "Enabling temp2, readings "
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669 "might not make sense\n");
Jean Delvare31b8dc42007-05-08 17:22:03 +02001670 w83781d_write_value(data, W83781D_REG_TEMP2_CONFIG,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671 tmp & 0xfe);
1672 }
1673
1674 /* Enable temp3 */
Jean Delvare7c7a5302005-06-16 19:24:14 +02001675 if (type != w83783s) {
Jean Delvare31b8dc42007-05-08 17:22:03 +02001676 tmp = w83781d_read_value(data,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677 W83781D_REG_TEMP3_CONFIG);
1678 if (tmp & 0x01) {
Jean Delvare7666c132007-05-08 17:22:02 +02001679 dev_warn(dev, "Enabling temp3, "
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680 "readings might not make sense\n");
Jean Delvare31b8dc42007-05-08 17:22:03 +02001681 w83781d_write_value(data,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 W83781D_REG_TEMP3_CONFIG, tmp & 0xfe);
1683 }
1684 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685 }
1686
1687 /* Start monitoring */
Jean Delvare31b8dc42007-05-08 17:22:03 +02001688 w83781d_write_value(data, W83781D_REG_CONFIG,
1689 (w83781d_read_value(data,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690 W83781D_REG_CONFIG) & 0xf7)
1691 | 0x01);
Jean Delvare7666c132007-05-08 17:22:02 +02001692
1693 /* A few vars need to be filled upon startup */
Jean Delvare34875332007-05-08 17:22:03 +02001694 for (i = 0; i < 3; i++) {
1695 data->fan_min[i] = w83781d_read_value(data,
Jean Delvare7666c132007-05-08 17:22:02 +02001696 W83781D_REG_FAN_MIN(i));
1697 }
Jean Delvare7666c132007-05-08 17:22:02 +02001698
1699 mutex_init(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700}
1701
1702static struct w83781d_data *w83781d_update_device(struct device *dev)
1703{
Jean Delvare7666c132007-05-08 17:22:02 +02001704 struct w83781d_data *data = dev_get_drvdata(dev);
1705 struct i2c_client *client = &data->client;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 int i;
1707
Ingo Molnar9a61bf62006-01-18 23:19:26 +01001708 mutex_lock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709
1710 if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
1711 || !data->valid) {
1712 dev_dbg(dev, "Starting device update\n");
1713
1714 for (i = 0; i <= 8; i++) {
Jean Delvare7c7a5302005-06-16 19:24:14 +02001715 if (data->type == w83783s && i == 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 continue; /* 783S has no in1 */
1717 data->in[i] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001718 w83781d_read_value(data, W83781D_REG_IN(i));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719 data->in_min[i] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001720 w83781d_read_value(data, W83781D_REG_IN_MIN(i));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721 data->in_max[i] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001722 w83781d_read_value(data, W83781D_REG_IN_MAX(i));
Jean Delvare05663362007-11-30 23:51:24 +01001723 if ((data->type != w83782d) && (i == 6))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724 break;
1725 }
Jean Delvare34875332007-05-08 17:22:03 +02001726 for (i = 0; i < 3; i++) {
1727 data->fan[i] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001728 w83781d_read_value(data, W83781D_REG_FAN(i));
Jean Delvare34875332007-05-08 17:22:03 +02001729 data->fan_min[i] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001730 w83781d_read_value(data, W83781D_REG_FAN_MIN(i));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731 }
1732 if (data->type != w83781d && data->type != as99127f) {
Jean Delvare34875332007-05-08 17:22:03 +02001733 for (i = 0; i < 4; i++) {
1734 data->pwm[i] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001735 w83781d_read_value(data,
Jean Delvare34875332007-05-08 17:22:03 +02001736 W83781D_REG_PWM[i]);
Jean Delvare7666c132007-05-08 17:22:02 +02001737 if ((data->type != w83782d || !client->driver)
Jean Delvare34875332007-05-08 17:22:03 +02001738 && i == 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739 break;
1740 }
1741 /* Only PWM2 can be disabled */
Jean Delvare34875332007-05-08 17:22:03 +02001742 data->pwm2_enable = (w83781d_read_value(data,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001743 W83781D_REG_PWMCLK12) & 0x08) >> 3;
1744 }
1745
Jean Delvare31b8dc42007-05-08 17:22:03 +02001746 data->temp = w83781d_read_value(data, W83781D_REG_TEMP(1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747 data->temp_max =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001748 w83781d_read_value(data, W83781D_REG_TEMP_OVER(1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749 data->temp_max_hyst =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001750 w83781d_read_value(data, W83781D_REG_TEMP_HYST(1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751 data->temp_add[0] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001752 w83781d_read_value(data, W83781D_REG_TEMP(2));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 data->temp_max_add[0] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001754 w83781d_read_value(data, W83781D_REG_TEMP_OVER(2));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755 data->temp_max_hyst_add[0] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001756 w83781d_read_value(data, W83781D_REG_TEMP_HYST(2));
Jean Delvare7c7a5302005-06-16 19:24:14 +02001757 if (data->type != w83783s) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758 data->temp_add[1] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001759 w83781d_read_value(data, W83781D_REG_TEMP(3));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760 data->temp_max_add[1] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001761 w83781d_read_value(data,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762 W83781D_REG_TEMP_OVER(3));
1763 data->temp_max_hyst_add[1] =
Jean Delvare31b8dc42007-05-08 17:22:03 +02001764 w83781d_read_value(data,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765 W83781D_REG_TEMP_HYST(3));
1766 }
Jean Delvare31b8dc42007-05-08 17:22:03 +02001767 i = w83781d_read_value(data, W83781D_REG_VID_FANDIV);
Jean Delvare7c7a5302005-06-16 19:24:14 +02001768 data->vid = i & 0x0f;
Jean Delvare31b8dc42007-05-08 17:22:03 +02001769 data->vid |= (w83781d_read_value(data,
Jean Delvare7c7a5302005-06-16 19:24:14 +02001770 W83781D_REG_CHIPID) & 0x01) << 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771 data->fan_div[0] = (i >> 4) & 0x03;
1772 data->fan_div[1] = (i >> 6) & 0x03;
Jean Delvare31b8dc42007-05-08 17:22:03 +02001773 data->fan_div[2] = (w83781d_read_value(data,
Jean Delvare7c7a5302005-06-16 19:24:14 +02001774 W83781D_REG_PIN) >> 6) & 0x03;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775 if ((data->type != w83781d) && (data->type != as99127f)) {
Jean Delvare31b8dc42007-05-08 17:22:03 +02001776 i = w83781d_read_value(data, W83781D_REG_VBAT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777 data->fan_div[0] |= (i >> 3) & 0x04;
1778 data->fan_div[1] |= (i >> 4) & 0x04;
Jean Delvare7c7a5302005-06-16 19:24:14 +02001779 data->fan_div[2] |= (i >> 5) & 0x04;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780 }
Jean Delvare05663362007-11-30 23:51:24 +01001781 if (data->type == w83782d) {
Jean Delvare31b8dc42007-05-08 17:22:03 +02001782 data->alarms = w83781d_read_value(data,
Jean Delvarec7f5d7e2006-02-05 23:13:48 +01001783 W83782D_REG_ALARM1)
Jean Delvare31b8dc42007-05-08 17:22:03 +02001784 | (w83781d_read_value(data,
Jean Delvarec7f5d7e2006-02-05 23:13:48 +01001785 W83782D_REG_ALARM2) << 8)
Jean Delvare31b8dc42007-05-08 17:22:03 +02001786 | (w83781d_read_value(data,
Jean Delvarec7f5d7e2006-02-05 23:13:48 +01001787 W83782D_REG_ALARM3) << 16);
1788 } else if (data->type == w83783s) {
Jean Delvare31b8dc42007-05-08 17:22:03 +02001789 data->alarms = w83781d_read_value(data,
Jean Delvarec7f5d7e2006-02-05 23:13:48 +01001790 W83782D_REG_ALARM1)
Jean Delvare31b8dc42007-05-08 17:22:03 +02001791 | (w83781d_read_value(data,
Jean Delvarec7f5d7e2006-02-05 23:13:48 +01001792 W83782D_REG_ALARM2) << 8);
1793 } else {
1794 /* No real-time status registers, fall back to
1795 interrupt status registers */
Jean Delvare31b8dc42007-05-08 17:22:03 +02001796 data->alarms = w83781d_read_value(data,
Jean Delvarec7f5d7e2006-02-05 23:13:48 +01001797 W83781D_REG_ALARM1)
Jean Delvare31b8dc42007-05-08 17:22:03 +02001798 | (w83781d_read_value(data,
Jean Delvarec7f5d7e2006-02-05 23:13:48 +01001799 W83781D_REG_ALARM2) << 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800 }
Jean Delvare31b8dc42007-05-08 17:22:03 +02001801 i = w83781d_read_value(data, W83781D_REG_BEEP_INTS2);
Jean Delvare2fbbbf12008-10-17 17:51:18 +02001802 data->beep_mask = (i << 8) +
Jean Delvare31b8dc42007-05-08 17:22:03 +02001803 w83781d_read_value(data, W83781D_REG_BEEP_INTS1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804 if ((data->type != w83781d) && (data->type != as99127f)) {
1805 data->beep_mask |=
Jean Delvare31b8dc42007-05-08 17:22:03 +02001806 w83781d_read_value(data,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807 W83781D_REG_BEEP_INTS3) << 16;
1808 }
1809 data->last_updated = jiffies;
1810 data->valid = 1;
1811 }
1812
Ingo Molnar9a61bf62006-01-18 23:19:26 +01001813 mutex_unlock(&data->update_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814
1815 return data;
1816}
1817
Jean Delvare7666c132007-05-08 17:22:02 +02001818/* return 1 if a supported chip is found, 0 otherwise */
1819static int __init
1820w83781d_isa_found(unsigned short address)
1821{
1822 int val, save, found = 0;
1823
Jean Delvare2961cb22008-03-09 13:34:28 +01001824 /* We have to request the region in two parts because some
1825 boards declare base+4 to base+7 as a PNP device */
1826 if (!request_region(address, 4, "w83781d")) {
1827 pr_debug("w83781d: Failed to request low part of region\n");
Jean Delvare7666c132007-05-08 17:22:02 +02001828 return 0;
Jean Delvare2961cb22008-03-09 13:34:28 +01001829 }
1830 if (!request_region(address + 4, 4, "w83781d")) {
1831 pr_debug("w83781d: Failed to request high part of region\n");
1832 release_region(address, 4);
1833 return 0;
1834 }
Jean Delvare7666c132007-05-08 17:22:02 +02001835
1836#define REALLY_SLOW_IO
1837 /* We need the timeouts for at least some W83781D-like
1838 chips. But only if we read 'undefined' registers. */
1839 val = inb_p(address + 1);
1840 if (inb_p(address + 2) != val
1841 || inb_p(address + 3) != val
1842 || inb_p(address + 7) != val) {
1843 pr_debug("w83781d: Detection failed at step 1\n");
1844 goto release;
1845 }
1846#undef REALLY_SLOW_IO
1847
1848 /* We should be able to change the 7 LSB of the address port. The
1849 MSB (busy flag) should be clear initially, set after the write. */
1850 save = inb_p(address + W83781D_ADDR_REG_OFFSET);
1851 if (save & 0x80) {
1852 pr_debug("w83781d: Detection failed at step 2\n");
1853 goto release;
1854 }
1855 val = ~save & 0x7f;
1856 outb_p(val, address + W83781D_ADDR_REG_OFFSET);
1857 if (inb_p(address + W83781D_ADDR_REG_OFFSET) != (val | 0x80)) {
1858 outb_p(save, address + W83781D_ADDR_REG_OFFSET);
1859 pr_debug("w83781d: Detection failed at step 3\n");
1860 goto release;
1861 }
1862
1863 /* We found a device, now see if it could be a W83781D */
1864 outb_p(W83781D_REG_CONFIG, address + W83781D_ADDR_REG_OFFSET);
1865 val = inb_p(address + W83781D_DATA_REG_OFFSET);
1866 if (val & 0x80) {
1867 pr_debug("w83781d: Detection failed at step 4\n");
1868 goto release;
1869 }
1870 outb_p(W83781D_REG_BANK, address + W83781D_ADDR_REG_OFFSET);
1871 save = inb_p(address + W83781D_DATA_REG_OFFSET);
1872 outb_p(W83781D_REG_CHIPMAN, address + W83781D_ADDR_REG_OFFSET);
1873 val = inb_p(address + W83781D_DATA_REG_OFFSET);
1874 if ((!(save & 0x80) && (val != 0xa3))
1875 || ((save & 0x80) && (val != 0x5c))) {
1876 pr_debug("w83781d: Detection failed at step 5\n");
1877 goto release;
1878 }
1879 outb_p(W83781D_REG_I2C_ADDR, address + W83781D_ADDR_REG_OFFSET);
1880 val = inb_p(address + W83781D_DATA_REG_OFFSET);
1881 if (val < 0x03 || val > 0x77) { /* Not a valid I2C address */
1882 pr_debug("w83781d: Detection failed at step 6\n");
1883 goto release;
1884 }
1885
1886 /* The busy flag should be clear again */
1887 if (inb_p(address + W83781D_ADDR_REG_OFFSET) & 0x80) {
1888 pr_debug("w83781d: Detection failed at step 7\n");
1889 goto release;
1890 }
1891
1892 /* Determine the chip type */
1893 outb_p(W83781D_REG_BANK, address + W83781D_ADDR_REG_OFFSET);
1894 save = inb_p(address + W83781D_DATA_REG_OFFSET);
1895 outb_p(save & 0xf8, address + W83781D_DATA_REG_OFFSET);
1896 outb_p(W83781D_REG_WCHIPID, address + W83781D_ADDR_REG_OFFSET);
1897 val = inb_p(address + W83781D_DATA_REG_OFFSET);
1898 if ((val & 0xfe) == 0x10 /* W83781D */
Jean Delvare05663362007-11-30 23:51:24 +01001899 || val == 0x30) /* W83782D */
Jean Delvare7666c132007-05-08 17:22:02 +02001900 found = 1;
1901
1902 if (found)
1903 pr_info("w83781d: Found a %s chip at %#x\n",
Jean Delvare7666c132007-05-08 17:22:02 +02001904 val == 0x30 ? "W83782D" : "W83781D", (int)address);
1905
1906 release:
Jean Delvare2961cb22008-03-09 13:34:28 +01001907 release_region(address + 4, 4);
1908 release_region(address, 4);
Jean Delvare7666c132007-05-08 17:22:02 +02001909 return found;
1910}
1911
1912static int __init
1913w83781d_isa_device_add(unsigned short address)
1914{
1915 struct resource res = {
1916 .start = address,
Jean Delvare15bde2f2007-08-29 10:39:57 +02001917 .end = address + W83781D_EXTENT - 1,
Jean Delvare7666c132007-05-08 17:22:02 +02001918 .name = "w83781d",
1919 .flags = IORESOURCE_IO,
1920 };
1921 int err;
1922
1923 pdev = platform_device_alloc("w83781d", address);
1924 if (!pdev) {
1925 err = -ENOMEM;
1926 printk(KERN_ERR "w83781d: Device allocation failed\n");
1927 goto exit;
1928 }
1929
1930 err = platform_device_add_resources(pdev, &res, 1);
1931 if (err) {
1932 printk(KERN_ERR "w83781d: Device resource addition failed "
1933 "(%d)\n", err);
1934 goto exit_device_put;
1935 }
1936
1937 err = platform_device_add(pdev);
1938 if (err) {
1939 printk(KERN_ERR "w83781d: Device addition failed (%d)\n",
1940 err);
1941 goto exit_device_put;
1942 }
1943
1944 return 0;
1945
1946 exit_device_put:
1947 platform_device_put(pdev);
1948 exit:
1949 pdev = NULL;
1950 return err;
1951}
1952
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953static int __init
1954sensors_w83781d_init(void)
1955{
Jean Delvarefde09502005-07-19 23:51:07 +02001956 int res;
1957
Jean Delvarec6566202008-10-17 17:51:18 +02001958 /* We register the ISA device first, so that we can skip the
1959 * registration of an I2C interface to the same device. */
Jean Delvare7666c132007-05-08 17:22:02 +02001960 if (w83781d_isa_found(isa_address)) {
1961 res = platform_driver_register(&w83781d_isa_driver);
1962 if (res)
Jean Delvarec6566202008-10-17 17:51:18 +02001963 goto exit;
Jean Delvare7666c132007-05-08 17:22:02 +02001964
1965 /* Sets global pdev as a side effect */
1966 res = w83781d_isa_device_add(isa_address);
1967 if (res)
1968 goto exit_unreg_isa_driver;
1969 }
Jean Delvarefde09502005-07-19 23:51:07 +02001970
Jean Delvarec6566202008-10-17 17:51:18 +02001971 res = i2c_add_driver(&w83781d_driver);
1972 if (res)
1973 goto exit_unreg_isa_device;
1974
Jean Delvarefde09502005-07-19 23:51:07 +02001975 return 0;
Jean Delvare7666c132007-05-08 17:22:02 +02001976
Jean Delvarec6566202008-10-17 17:51:18 +02001977 exit_unreg_isa_device:
1978 platform_device_unregister(pdev);
Jean Delvare7666c132007-05-08 17:22:02 +02001979 exit_unreg_isa_driver:
1980 platform_driver_unregister(&w83781d_isa_driver);
Jean Delvare7666c132007-05-08 17:22:02 +02001981 exit:
1982 return res;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983}
1984
1985static void __exit
1986sensors_w83781d_exit(void)
1987{
Jean Delvare7666c132007-05-08 17:22:02 +02001988 if (pdev) {
1989 platform_device_unregister(pdev);
1990 platform_driver_unregister(&w83781d_isa_driver);
1991 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992 i2c_del_driver(&w83781d_driver);
1993}
1994
1995MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
1996 "Philip Edelbrock <phil@netroedge.com>, "
1997 "and Mark Studebaker <mdsxyz123@yahoo.com>");
1998MODULE_DESCRIPTION("W83781D driver");
1999MODULE_LICENSE("GPL");
2000
2001module_init(sensors_w83781d_init);
2002module_exit(sensors_w83781d_exit);