Root/
1 | /* |
2 | * w83792d.c - Part of lm_sensors, Linux kernel modules for hardware |
3 | * monitoring |
4 | * Copyright (C) 2004, 2005 Winbond Electronics Corp. |
5 | * Chunhao Huang <DZShen@Winbond.com.tw>, |
6 | * Rudolf Marek <r.marek@assembler.cz> |
7 | * |
8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by |
10 | * the Free Software Foundation; either version 2 of the License, or |
11 | * (at your option) any later version. |
12 | * |
13 | * This program is distributed in the hope that it will be useful, |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | * GNU General Public License for more details. |
17 | * |
18 | * You should have received a copy of the GNU General Public License |
19 | * along with this program; if not, write to the Free Software |
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
21 | * |
22 | * Note: |
23 | * 1. This driver is only for 2.6 kernel, 2.4 kernel need a different driver. |
24 | * 2. This driver is only for Winbond W83792D C version device, there |
25 | * are also some motherboards with B version W83792D device. The |
26 | * calculation method to in6-in7(measured value, limits) is a little |
27 | * different between C and B version. C or B version can be identified |
28 | * by CR[0x49h]. |
29 | */ |
30 | |
31 | /* |
32 | * Supports following chips: |
33 | * |
34 | * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA |
35 | * w83792d 9 7 7 3 0x7a 0x5ca3 yes no |
36 | */ |
37 | |
38 | #include <linux/module.h> |
39 | #include <linux/init.h> |
40 | #include <linux/slab.h> |
41 | #include <linux/i2c.h> |
42 | #include <linux/hwmon.h> |
43 | #include <linux/hwmon-sysfs.h> |
44 | #include <linux/err.h> |
45 | #include <linux/mutex.h> |
46 | #include <linux/sysfs.h> |
47 | #include <linux/jiffies.h> |
48 | |
49 | /* Addresses to scan */ |
50 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, |
51 | I2C_CLIENT_END }; |
52 | |
53 | /* Insmod parameters */ |
54 | |
55 | static unsigned short force_subclients[4]; |
56 | module_param_array(force_subclients, short, NULL, 0); |
57 | MODULE_PARM_DESC(force_subclients, "List of subclient addresses: " |
58 | "{bus, clientaddr, subclientaddr1, subclientaddr2}"); |
59 | |
60 | static bool init; |
61 | module_param(init, bool, 0); |
62 | MODULE_PARM_DESC(init, "Set to one to force chip initialization"); |
63 | |
64 | /* The W83792D registers */ |
65 | static const u8 W83792D_REG_IN[9] = { |
66 | 0x20, /* Vcore A in DataSheet */ |
67 | 0x21, /* Vcore B in DataSheet */ |
68 | 0x22, /* VIN0 in DataSheet */ |
69 | 0x23, /* VIN1 in DataSheet */ |
70 | 0x24, /* VIN2 in DataSheet */ |
71 | 0x25, /* VIN3 in DataSheet */ |
72 | 0x26, /* 5VCC in DataSheet */ |
73 | 0xB0, /* 5VSB in DataSheet */ |
74 | 0xB1 /* VBAT in DataSheet */ |
75 | }; |
76 | #define W83792D_REG_LOW_BITS1 0x3E /* Low Bits I in DataSheet */ |
77 | #define W83792D_REG_LOW_BITS2 0x3F /* Low Bits II in DataSheet */ |
78 | static const u8 W83792D_REG_IN_MAX[9] = { |
79 | 0x2B, /* Vcore A High Limit in DataSheet */ |
80 | 0x2D, /* Vcore B High Limit in DataSheet */ |
81 | 0x2F, /* VIN0 High Limit in DataSheet */ |
82 | 0x31, /* VIN1 High Limit in DataSheet */ |
83 | 0x33, /* VIN2 High Limit in DataSheet */ |
84 | 0x35, /* VIN3 High Limit in DataSheet */ |
85 | 0x37, /* 5VCC High Limit in DataSheet */ |
86 | 0xB4, /* 5VSB High Limit in DataSheet */ |
87 | 0xB6 /* VBAT High Limit in DataSheet */ |
88 | }; |
89 | static const u8 W83792D_REG_IN_MIN[9] = { |
90 | 0x2C, /* Vcore A Low Limit in DataSheet */ |
91 | 0x2E, /* Vcore B Low Limit in DataSheet */ |
92 | 0x30, /* VIN0 Low Limit in DataSheet */ |
93 | 0x32, /* VIN1 Low Limit in DataSheet */ |
94 | 0x34, /* VIN2 Low Limit in DataSheet */ |
95 | 0x36, /* VIN3 Low Limit in DataSheet */ |
96 | 0x38, /* 5VCC Low Limit in DataSheet */ |
97 | 0xB5, /* 5VSB Low Limit in DataSheet */ |
98 | 0xB7 /* VBAT Low Limit in DataSheet */ |
99 | }; |
100 | static const u8 W83792D_REG_FAN[7] = { |
101 | 0x28, /* FAN 1 Count in DataSheet */ |
102 | 0x29, /* FAN 2 Count in DataSheet */ |
103 | 0x2A, /* FAN 3 Count in DataSheet */ |
104 | 0xB8, /* FAN 4 Count in DataSheet */ |
105 | 0xB9, /* FAN 5 Count in DataSheet */ |
106 | 0xBA, /* FAN 6 Count in DataSheet */ |
107 | 0xBE /* FAN 7 Count in DataSheet */ |
108 | }; |
109 | static const u8 W83792D_REG_FAN_MIN[7] = { |
110 | 0x3B, /* FAN 1 Count Low Limit in DataSheet */ |
111 | 0x3C, /* FAN 2 Count Low Limit in DataSheet */ |
112 | 0x3D, /* FAN 3 Count Low Limit in DataSheet */ |
113 | 0xBB, /* FAN 4 Count Low Limit in DataSheet */ |
114 | 0xBC, /* FAN 5 Count Low Limit in DataSheet */ |
115 | 0xBD, /* FAN 6 Count Low Limit in DataSheet */ |
116 | 0xBF /* FAN 7 Count Low Limit in DataSheet */ |
117 | }; |
118 | #define W83792D_REG_FAN_CFG 0x84 /* FAN Configuration in DataSheet */ |
119 | static const u8 W83792D_REG_FAN_DIV[4] = { |
120 | 0x47, /* contains FAN2 and FAN1 Divisor */ |
121 | 0x5B, /* contains FAN4 and FAN3 Divisor */ |
122 | 0x5C, /* contains FAN6 and FAN5 Divisor */ |
123 | 0x9E /* contains FAN7 Divisor. */ |
124 | }; |
125 | static const u8 W83792D_REG_PWM[7] = { |
126 | 0x81, /* FAN 1 Duty Cycle, be used to control */ |
127 | 0x83, /* FAN 2 Duty Cycle, be used to control */ |
128 | 0x94, /* FAN 3 Duty Cycle, be used to control */ |
129 | 0xA3, /* FAN 4 Duty Cycle, be used to control */ |
130 | 0xA4, /* FAN 5 Duty Cycle, be used to control */ |
131 | 0xA5, /* FAN 6 Duty Cycle, be used to control */ |
132 | 0xA6 /* FAN 7 Duty Cycle, be used to control */ |
133 | }; |
134 | #define W83792D_REG_BANK 0x4E |
135 | #define W83792D_REG_TEMP2_CONFIG 0xC2 |
136 | #define W83792D_REG_TEMP3_CONFIG 0xCA |
137 | |
138 | static const u8 W83792D_REG_TEMP1[3] = { |
139 | 0x27, /* TEMP 1 in DataSheet */ |
140 | 0x39, /* TEMP 1 Over in DataSheet */ |
141 | 0x3A, /* TEMP 1 Hyst in DataSheet */ |
142 | }; |
143 | |
144 | static const u8 W83792D_REG_TEMP_ADD[2][6] = { |
145 | { 0xC0, /* TEMP 2 in DataSheet */ |
146 | 0xC1, /* TEMP 2(0.5 deg) in DataSheet */ |
147 | 0xC5, /* TEMP 2 Over High part in DataSheet */ |
148 | 0xC6, /* TEMP 2 Over Low part in DataSheet */ |
149 | 0xC3, /* TEMP 2 Thyst High part in DataSheet */ |
150 | 0xC4 }, /* TEMP 2 Thyst Low part in DataSheet */ |
151 | { 0xC8, /* TEMP 3 in DataSheet */ |
152 | 0xC9, /* TEMP 3(0.5 deg) in DataSheet */ |
153 | 0xCD, /* TEMP 3 Over High part in DataSheet */ |
154 | 0xCE, /* TEMP 3 Over Low part in DataSheet */ |
155 | 0xCB, /* TEMP 3 Thyst High part in DataSheet */ |
156 | 0xCC } /* TEMP 3 Thyst Low part in DataSheet */ |
157 | }; |
158 | |
159 | static const u8 W83792D_REG_THERMAL[3] = { |
160 | 0x85, /* SmartFanI: Fan1 target value */ |
161 | 0x86, /* SmartFanI: Fan2 target value */ |
162 | 0x96 /* SmartFanI: Fan3 target value */ |
163 | }; |
164 | |
165 | static const u8 W83792D_REG_TOLERANCE[3] = { |
166 | 0x87, /* (bit3-0)SmartFan Fan1 tolerance */ |
167 | 0x87, /* (bit7-4)SmartFan Fan2 tolerance */ |
168 | 0x97 /* (bit3-0)SmartFan Fan3 tolerance */ |
169 | }; |
170 | |
171 | static const u8 W83792D_REG_POINTS[3][4] = { |
172 | { 0x85, /* SmartFanII: Fan1 temp point 1 */ |
173 | 0xE3, /* SmartFanII: Fan1 temp point 2 */ |
174 | 0xE4, /* SmartFanII: Fan1 temp point 3 */ |
175 | 0xE5 }, /* SmartFanII: Fan1 temp point 4 */ |
176 | { 0x86, /* SmartFanII: Fan2 temp point 1 */ |
177 | 0xE6, /* SmartFanII: Fan2 temp point 2 */ |
178 | 0xE7, /* SmartFanII: Fan2 temp point 3 */ |
179 | 0xE8 }, /* SmartFanII: Fan2 temp point 4 */ |
180 | { 0x96, /* SmartFanII: Fan3 temp point 1 */ |
181 | 0xE9, /* SmartFanII: Fan3 temp point 2 */ |
182 | 0xEA, /* SmartFanII: Fan3 temp point 3 */ |
183 | 0xEB } /* SmartFanII: Fan3 temp point 4 */ |
184 | }; |
185 | |
186 | static const u8 W83792D_REG_LEVELS[3][4] = { |
187 | { 0x88, /* (bit3-0) SmartFanII: Fan1 Non-Stop */ |
188 | 0x88, /* (bit7-4) SmartFanII: Fan1 Level 1 */ |
189 | 0xE0, /* (bit7-4) SmartFanII: Fan1 Level 2 */ |
190 | 0xE0 }, /* (bit3-0) SmartFanII: Fan1 Level 3 */ |
191 | { 0x89, /* (bit3-0) SmartFanII: Fan2 Non-Stop */ |
192 | 0x89, /* (bit7-4) SmartFanII: Fan2 Level 1 */ |
193 | 0xE1, /* (bit7-4) SmartFanII: Fan2 Level 2 */ |
194 | 0xE1 }, /* (bit3-0) SmartFanII: Fan2 Level 3 */ |
195 | { 0x98, /* (bit3-0) SmartFanII: Fan3 Non-Stop */ |
196 | 0x98, /* (bit7-4) SmartFanII: Fan3 Level 1 */ |
197 | 0xE2, /* (bit7-4) SmartFanII: Fan3 Level 2 */ |
198 | 0xE2 } /* (bit3-0) SmartFanII: Fan3 Level 3 */ |
199 | }; |
200 | |
201 | #define W83792D_REG_GPIO_EN 0x1A |
202 | #define W83792D_REG_CONFIG 0x40 |
203 | #define W83792D_REG_VID_FANDIV 0x47 |
204 | #define W83792D_REG_CHIPID 0x49 |
205 | #define W83792D_REG_WCHIPID 0x58 |
206 | #define W83792D_REG_CHIPMAN 0x4F |
207 | #define W83792D_REG_PIN 0x4B |
208 | #define W83792D_REG_I2C_SUBADDR 0x4A |
209 | |
210 | #define W83792D_REG_ALARM1 0xA9 /* realtime status register1 */ |
211 | #define W83792D_REG_ALARM2 0xAA /* realtime status register2 */ |
212 | #define W83792D_REG_ALARM3 0xAB /* realtime status register3 */ |
213 | #define W83792D_REG_CHASSIS 0x42 /* Bit 5: Case Open status bit */ |
214 | #define W83792D_REG_CHASSIS_CLR 0x44 /* Bit 7: Case Open CLR_CHS/Reset bit */ |
215 | |
216 | /* control in0/in1 's limit modifiability */ |
217 | #define W83792D_REG_VID_IN_B 0x17 |
218 | |
219 | #define W83792D_REG_VBAT 0x5D |
220 | #define W83792D_REG_I2C_ADDR 0x48 |
221 | |
222 | /* |
223 | * Conversions. Rounding and limit checking is only done on the TO_REG |
224 | * variants. Note that you should be a bit careful with which arguments |
225 | * these macros are called: arguments may be evaluated more than once. |
226 | * Fixing this is just not worth it. |
227 | */ |
228 | #define IN_FROM_REG(nr, val) (((nr) <= 1) ? ((val) * 2) : \ |
229 | ((((nr) == 6) || ((nr) == 7)) ? ((val) * 6) : ((val) * 4))) |
230 | #define IN_TO_REG(nr, val) (((nr) <= 1) ? ((val) / 2) : \ |
231 | ((((nr) == 6) || ((nr) == 7)) ? ((val) / 6) : ((val) / 4))) |
232 | |
233 | static inline u8 |
234 | FAN_TO_REG(long rpm, int div) |
235 | { |
236 | if (rpm == 0) |
237 | return 255; |
238 | rpm = clamp_val(rpm, 1, 1000000); |
239 | return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254); |
240 | } |
241 | |
242 | #define FAN_FROM_REG(val, div) ((val) == 0 ? -1 : \ |
243 | ((val) == 255 ? 0 : \ |
244 | 1350000 / ((val) * (div)))) |
245 | |
246 | /* for temp1 */ |
247 | #define TEMP1_TO_REG(val) (clamp_val(((val) < 0 ? (val) + 0x100 * 1000 \ |
248 | : (val)) / 1000, 0, 0xff)) |
249 | #define TEMP1_FROM_REG(val) (((val) & 0x80 ? (val)-0x100 : (val)) * 1000) |
250 | /* for temp2 and temp3, because they need additional resolution */ |
251 | #define TEMP_ADD_FROM_REG(val1, val2) \ |
252 | ((((val1) & 0x80 ? (val1)-0x100 \ |
253 | : (val1)) * 1000) + ((val2 & 0x80) ? 500 : 0)) |
254 | #define TEMP_ADD_TO_REG_HIGH(val) \ |
255 | (clamp_val(((val) < 0 ? (val) + 0x100 * 1000 : (val)) / 1000, 0, 0xff)) |
256 | #define TEMP_ADD_TO_REG_LOW(val) ((val%1000) ? 0x80 : 0x00) |
257 | |
258 | #define DIV_FROM_REG(val) (1 << (val)) |
259 | |
260 | static inline u8 |
261 | DIV_TO_REG(long val) |
262 | { |
263 | int i; |
264 | val = clamp_val(val, 1, 128) >> 1; |
265 | for (i = 0; i < 7; i++) { |
266 | if (val == 0) |
267 | break; |
268 | val >>= 1; |
269 | } |
270 | return (u8)i; |
271 | } |
272 | |
273 | struct w83792d_data { |
274 | struct device *hwmon_dev; |
275 | |
276 | struct mutex update_lock; |
277 | char valid; /* !=0 if following fields are valid */ |
278 | unsigned long last_updated; /* In jiffies */ |
279 | |
280 | /* array of 2 pointers to subclients */ |
281 | struct i2c_client *lm75[2]; |
282 | |
283 | u8 in[9]; /* Register value */ |
284 | u8 in_max[9]; /* Register value */ |
285 | u8 in_min[9]; /* Register value */ |
286 | u16 low_bits; /* Additional resolution to voltage in6-0 */ |
287 | u8 fan[7]; /* Register value */ |
288 | u8 fan_min[7]; /* Register value */ |
289 | u8 temp1[3]; /* current, over, thyst */ |
290 | u8 temp_add[2][6]; /* Register value */ |
291 | u8 fan_div[7]; /* Register encoding, shifted right */ |
292 | u8 pwm[7]; /* |
293 | * We only consider the first 3 set of pwm, |
294 | * although 792 chip has 7 set of pwm. |
295 | */ |
296 | u8 pwmenable[3]; |
297 | u32 alarms; /* realtime status register encoding,combined */ |
298 | u8 chassis; /* Chassis status */ |
299 | u8 thermal_cruise[3]; /* Smart FanI: Fan1,2,3 target value */ |
300 | u8 tolerance[3]; /* Fan1,2,3 tolerance(Smart Fan I/II) */ |
301 | u8 sf2_points[3][4]; /* Smart FanII: Fan1,2,3 temperature points */ |
302 | u8 sf2_levels[3][4]; /* Smart FanII: Fan1,2,3 duty cycle levels */ |
303 | }; |
304 | |
305 | static int w83792d_probe(struct i2c_client *client, |
306 | const struct i2c_device_id *id); |
307 | static int w83792d_detect(struct i2c_client *client, |
308 | struct i2c_board_info *info); |
309 | static int w83792d_remove(struct i2c_client *client); |
310 | static struct w83792d_data *w83792d_update_device(struct device *dev); |
311 | |
312 | #ifdef DEBUG |
313 | static void w83792d_print_debug(struct w83792d_data *data, struct device *dev); |
314 | #endif |
315 | |
316 | static void w83792d_init_client(struct i2c_client *client); |
317 | |
318 | static const struct i2c_device_id w83792d_id[] = { |
319 | { "w83792d", 0 }, |
320 | { } |
321 | }; |
322 | MODULE_DEVICE_TABLE(i2c, w83792d_id); |
323 | |
324 | static struct i2c_driver w83792d_driver = { |
325 | .class = I2C_CLASS_HWMON, |
326 | .driver = { |
327 | .name = "w83792d", |
328 | }, |
329 | .probe = w83792d_probe, |
330 | .remove = w83792d_remove, |
331 | .id_table = w83792d_id, |
332 | .detect = w83792d_detect, |
333 | .address_list = normal_i2c, |
334 | }; |
335 | |
336 | static inline long in_count_from_reg(int nr, struct w83792d_data *data) |
337 | { |
338 | /* in7 and in8 do not have low bits, but the formula still works */ |
339 | return (data->in[nr] << 2) | ((data->low_bits >> (2 * nr)) & 0x03); |
340 | } |
341 | |
342 | /* |
343 | * The SMBus locks itself. The Winbond W83792D chip has a bank register, |
344 | * but the driver only accesses registers in bank 0, so we don't have |
345 | * to switch banks and lock access between switches. |
346 | */ |
347 | static inline int w83792d_read_value(struct i2c_client *client, u8 reg) |
348 | { |
349 | return i2c_smbus_read_byte_data(client, reg); |
350 | } |
351 | |
352 | static inline int |
353 | w83792d_write_value(struct i2c_client *client, u8 reg, u8 value) |
354 | { |
355 | return i2c_smbus_write_byte_data(client, reg, value); |
356 | } |
357 | |
358 | /* following are the sysfs callback functions */ |
359 | static ssize_t show_in(struct device *dev, struct device_attribute *attr, |
360 | char *buf) |
361 | { |
362 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); |
363 | int nr = sensor_attr->index; |
364 | struct w83792d_data *data = w83792d_update_device(dev); |
365 | return sprintf(buf, "%ld\n", |
366 | IN_FROM_REG(nr, in_count_from_reg(nr, data))); |
367 | } |
368 | |
369 | #define show_in_reg(reg) \ |
370 | static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ |
371 | char *buf) \ |
372 | { \ |
373 | struct sensor_device_attribute *sensor_attr \ |
374 | = to_sensor_dev_attr(attr); \ |
375 | int nr = sensor_attr->index; \ |
376 | struct w83792d_data *data = w83792d_update_device(dev); \ |
377 | return sprintf(buf, "%ld\n", \ |
378 | (long)(IN_FROM_REG(nr, data->reg[nr]) * 4)); \ |
379 | } |
380 | |
381 | show_in_reg(in_min); |
382 | show_in_reg(in_max); |
383 | |
384 | #define store_in_reg(REG, reg) \ |
385 | static ssize_t store_in_##reg(struct device *dev, \ |
386 | struct device_attribute *attr, \ |
387 | const char *buf, size_t count) \ |
388 | { \ |
389 | struct sensor_device_attribute *sensor_attr \ |
390 | = to_sensor_dev_attr(attr); \ |
391 | int nr = sensor_attr->index; \ |
392 | struct i2c_client *client = to_i2c_client(dev); \ |
393 | struct w83792d_data *data = i2c_get_clientdata(client); \ |
394 | unsigned long val; \ |
395 | int err = kstrtoul(buf, 10, &val); \ |
396 | if (err) \ |
397 | return err; \ |
398 | mutex_lock(&data->update_lock); \ |
399 | data->in_##reg[nr] = clamp_val(IN_TO_REG(nr, val) / 4, 0, 255); \ |
400 | w83792d_write_value(client, W83792D_REG_IN_##REG[nr], \ |
401 | data->in_##reg[nr]); \ |
402 | mutex_unlock(&data->update_lock); \ |
403 | \ |
404 | return count; \ |
405 | } |
406 | store_in_reg(MIN, min); |
407 | store_in_reg(MAX, max); |
408 | |
409 | #define show_fan_reg(reg) \ |
410 | static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ |
411 | char *buf) \ |
412 | { \ |
413 | struct sensor_device_attribute *sensor_attr \ |
414 | = to_sensor_dev_attr(attr); \ |
415 | int nr = sensor_attr->index - 1; \ |
416 | struct w83792d_data *data = w83792d_update_device(dev); \ |
417 | return sprintf(buf, "%d\n", \ |
418 | FAN_FROM_REG(data->reg[nr], DIV_FROM_REG(data->fan_div[nr]))); \ |
419 | } |
420 | |
421 | show_fan_reg(fan); |
422 | show_fan_reg(fan_min); |
423 | |
424 | static ssize_t |
425 | store_fan_min(struct device *dev, struct device_attribute *attr, |
426 | const char *buf, size_t count) |
427 | { |
428 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); |
429 | int nr = sensor_attr->index - 1; |
430 | struct i2c_client *client = to_i2c_client(dev); |
431 | struct w83792d_data *data = i2c_get_clientdata(client); |
432 | unsigned long val; |
433 | int err; |
434 | |
435 | err = kstrtoul(buf, 10, &val); |
436 | if (err) |
437 | return err; |
438 | |
439 | mutex_lock(&data->update_lock); |
440 | data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); |
441 | w83792d_write_value(client, W83792D_REG_FAN_MIN[nr], |
442 | data->fan_min[nr]); |
443 | mutex_unlock(&data->update_lock); |
444 | |
445 | return count; |
446 | } |
447 | |
448 | static ssize_t |
449 | show_fan_div(struct device *dev, struct device_attribute *attr, |
450 | char *buf) |
451 | { |
452 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); |
453 | int nr = sensor_attr->index; |
454 | struct w83792d_data *data = w83792d_update_device(dev); |
455 | return sprintf(buf, "%u\n", DIV_FROM_REG(data->fan_div[nr - 1])); |
456 | } |
457 | |
458 | /* |
459 | * Note: we save and restore the fan minimum here, because its value is |
460 | * determined in part by the fan divisor. This follows the principle of |
461 | * least surprise; the user doesn't expect the fan minimum to change just |
462 | * because the divisor changed. |
463 | */ |
464 | static ssize_t |
465 | store_fan_div(struct device *dev, struct device_attribute *attr, |
466 | const char *buf, size_t count) |
467 | { |
468 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); |
469 | int nr = sensor_attr->index - 1; |
470 | struct i2c_client *client = to_i2c_client(dev); |
471 | struct w83792d_data *data = i2c_get_clientdata(client); |
472 | unsigned long min; |
473 | /*u8 reg;*/ |
474 | u8 fan_div_reg = 0; |
475 | u8 tmp_fan_div; |
476 | unsigned long val; |
477 | int err; |
478 | |
479 | err = kstrtoul(buf, 10, &val); |
480 | if (err) |
481 | return err; |
482 | |
483 | /* Save fan_min */ |
484 | mutex_lock(&data->update_lock); |
485 | min = FAN_FROM_REG(data->fan_min[nr], |
486 | DIV_FROM_REG(data->fan_div[nr])); |
487 | |
488 | data->fan_div[nr] = DIV_TO_REG(val); |
489 | |
490 | fan_div_reg = w83792d_read_value(client, W83792D_REG_FAN_DIV[nr >> 1]); |
491 | fan_div_reg &= (nr & 0x01) ? 0x8f : 0xf8; |
492 | tmp_fan_div = (nr & 0x01) ? (((data->fan_div[nr]) << 4) & 0x70) |
493 | : ((data->fan_div[nr]) & 0x07); |
494 | w83792d_write_value(client, W83792D_REG_FAN_DIV[nr >> 1], |
495 | fan_div_reg | tmp_fan_div); |
496 | |
497 | /* Restore fan_min */ |
498 | data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); |
499 | w83792d_write_value(client, W83792D_REG_FAN_MIN[nr], data->fan_min[nr]); |
500 | mutex_unlock(&data->update_lock); |
501 | |
502 | return count; |
503 | } |
504 | |
505 | /* read/write the temperature1, includes measured value and limits */ |
506 | |
507 | static ssize_t show_temp1(struct device *dev, struct device_attribute *attr, |
508 | char *buf) |
509 | { |
510 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); |
511 | int nr = sensor_attr->index; |
512 | struct w83792d_data *data = w83792d_update_device(dev); |
513 | return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp1[nr])); |
514 | } |
515 | |
516 | static ssize_t store_temp1(struct device *dev, struct device_attribute *attr, |
517 | const char *buf, size_t count) |
518 | { |
519 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); |
520 | int nr = sensor_attr->index; |
521 | struct i2c_client *client = to_i2c_client(dev); |
522 | struct w83792d_data *data = i2c_get_clientdata(client); |
523 | long val; |
524 | int err; |
525 | |
526 | err = kstrtol(buf, 10, &val); |
527 | if (err) |
528 | return err; |
529 | |
530 | mutex_lock(&data->update_lock); |
531 | data->temp1[nr] = TEMP1_TO_REG(val); |
532 | w83792d_write_value(client, W83792D_REG_TEMP1[nr], |
533 | data->temp1[nr]); |
534 | mutex_unlock(&data->update_lock); |
535 | |
536 | return count; |
537 | } |
538 | |
539 | /* read/write the temperature2-3, includes measured value and limits */ |
540 | |
541 | static ssize_t show_temp23(struct device *dev, struct device_attribute *attr, |
542 | char *buf) |
543 | { |
544 | struct sensor_device_attribute_2 *sensor_attr |
545 | = to_sensor_dev_attr_2(attr); |
546 | int nr = sensor_attr->nr; |
547 | int index = sensor_attr->index; |
548 | struct w83792d_data *data = w83792d_update_device(dev); |
549 | return sprintf(buf, "%ld\n", |
550 | (long)TEMP_ADD_FROM_REG(data->temp_add[nr][index], |
551 | data->temp_add[nr][index+1])); |
552 | } |
553 | |
554 | static ssize_t store_temp23(struct device *dev, struct device_attribute *attr, |
555 | const char *buf, size_t count) |
556 | { |
557 | struct sensor_device_attribute_2 *sensor_attr |
558 | = to_sensor_dev_attr_2(attr); |
559 | int nr = sensor_attr->nr; |
560 | int index = sensor_attr->index; |
561 | struct i2c_client *client = to_i2c_client(dev); |
562 | struct w83792d_data *data = i2c_get_clientdata(client); |
563 | long val; |
564 | int err; |
565 | |
566 | err = kstrtol(buf, 10, &val); |
567 | if (err) |
568 | return err; |
569 | |
570 | mutex_lock(&data->update_lock); |
571 | data->temp_add[nr][index] = TEMP_ADD_TO_REG_HIGH(val); |
572 | data->temp_add[nr][index+1] = TEMP_ADD_TO_REG_LOW(val); |
573 | w83792d_write_value(client, W83792D_REG_TEMP_ADD[nr][index], |
574 | data->temp_add[nr][index]); |
575 | w83792d_write_value(client, W83792D_REG_TEMP_ADD[nr][index+1], |
576 | data->temp_add[nr][index+1]); |
577 | mutex_unlock(&data->update_lock); |
578 | |
579 | return count; |
580 | } |
581 | |
582 | /* get reatime status of all sensors items: voltage, temp, fan */ |
583 | static ssize_t |
584 | show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf) |
585 | { |
586 | struct w83792d_data *data = w83792d_update_device(dev); |
587 | return sprintf(buf, "%d\n", data->alarms); |
588 | } |
589 | |
590 | static ssize_t show_alarm(struct device *dev, |
591 | struct device_attribute *attr, char *buf) |
592 | { |
593 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); |
594 | int nr = sensor_attr->index; |
595 | struct w83792d_data *data = w83792d_update_device(dev); |
596 | return sprintf(buf, "%d\n", (data->alarms >> nr) & 1); |
597 | } |
598 | |
599 | static ssize_t |
600 | show_pwm(struct device *dev, struct device_attribute *attr, |
601 | char *buf) |
602 | { |
603 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); |
604 | int nr = sensor_attr->index; |
605 | struct w83792d_data *data = w83792d_update_device(dev); |
606 | return sprintf(buf, "%d\n", (data->pwm[nr] & 0x0f) << 4); |
607 | } |
608 | |
609 | static ssize_t |
610 | show_pwmenable(struct device *dev, struct device_attribute *attr, |
611 | char *buf) |
612 | { |
613 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); |
614 | int nr = sensor_attr->index - 1; |
615 | struct w83792d_data *data = w83792d_update_device(dev); |
616 | long pwm_enable_tmp = 1; |
617 | |
618 | switch (data->pwmenable[nr]) { |
619 | case 0: |
620 | pwm_enable_tmp = 1; /* manual mode */ |
621 | break; |
622 | case 1: |
623 | pwm_enable_tmp = 3; /*thermal cruise/Smart Fan I */ |
624 | break; |
625 | case 2: |
626 | pwm_enable_tmp = 2; /* Smart Fan II */ |
627 | break; |
628 | } |
629 | |
630 | return sprintf(buf, "%ld\n", pwm_enable_tmp); |
631 | } |
632 | |
633 | static ssize_t |
634 | store_pwm(struct device *dev, struct device_attribute *attr, |
635 | const char *buf, size_t count) |
636 | { |
637 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); |
638 | int nr = sensor_attr->index; |
639 | struct i2c_client *client = to_i2c_client(dev); |
640 | struct w83792d_data *data = i2c_get_clientdata(client); |
641 | unsigned long val; |
642 | int err; |
643 | |
644 | err = kstrtoul(buf, 10, &val); |
645 | if (err) |
646 | return err; |
647 | val = clamp_val(val, 0, 255) >> 4; |
648 | |
649 | mutex_lock(&data->update_lock); |
650 | val |= w83792d_read_value(client, W83792D_REG_PWM[nr]) & 0xf0; |
651 | data->pwm[nr] = val; |
652 | w83792d_write_value(client, W83792D_REG_PWM[nr], data->pwm[nr]); |
653 | mutex_unlock(&data->update_lock); |
654 | |
655 | return count; |
656 | } |
657 | |
658 | static ssize_t |
659 | store_pwmenable(struct device *dev, struct device_attribute *attr, |
660 | const char *buf, size_t count) |
661 | { |
662 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); |
663 | int nr = sensor_attr->index - 1; |
664 | struct i2c_client *client = to_i2c_client(dev); |
665 | struct w83792d_data *data = i2c_get_clientdata(client); |
666 | u8 fan_cfg_tmp, cfg1_tmp, cfg2_tmp, cfg3_tmp, cfg4_tmp; |
667 | unsigned long val; |
668 | int err; |
669 | |
670 | err = kstrtoul(buf, 10, &val); |
671 | if (err) |
672 | return err; |
673 | |
674 | if (val < 1 || val > 3) |
675 | return -EINVAL; |
676 | |
677 | mutex_lock(&data->update_lock); |
678 | switch (val) { |
679 | case 1: |
680 | data->pwmenable[nr] = 0; /* manual mode */ |
681 | break; |
682 | case 2: |
683 | data->pwmenable[nr] = 2; /* Smart Fan II */ |
684 | break; |
685 | case 3: |
686 | data->pwmenable[nr] = 1; /* thermal cruise/Smart Fan I */ |
687 | break; |
688 | } |
689 | cfg1_tmp = data->pwmenable[0]; |
690 | cfg2_tmp = (data->pwmenable[1]) << 2; |
691 | cfg3_tmp = (data->pwmenable[2]) << 4; |
692 | cfg4_tmp = w83792d_read_value(client, W83792D_REG_FAN_CFG) & 0xc0; |
693 | fan_cfg_tmp = ((cfg4_tmp | cfg3_tmp) | cfg2_tmp) | cfg1_tmp; |
694 | w83792d_write_value(client, W83792D_REG_FAN_CFG, fan_cfg_tmp); |
695 | mutex_unlock(&data->update_lock); |
696 | |
697 | return count; |
698 | } |
699 | |
700 | static ssize_t |
701 | show_pwm_mode(struct device *dev, struct device_attribute *attr, |
702 | char *buf) |
703 | { |
704 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); |
705 | int nr = sensor_attr->index; |
706 | struct w83792d_data *data = w83792d_update_device(dev); |
707 | return sprintf(buf, "%d\n", data->pwm[nr] >> 7); |
708 | } |
709 | |
710 | static ssize_t |
711 | store_pwm_mode(struct device *dev, struct device_attribute *attr, |
712 | const char *buf, size_t count) |
713 | { |
714 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); |
715 | int nr = sensor_attr->index; |
716 | struct i2c_client *client = to_i2c_client(dev); |
717 | struct w83792d_data *data = i2c_get_clientdata(client); |
718 | unsigned long val; |
719 | int err; |
720 | |
721 | err = kstrtoul(buf, 10, &val); |
722 | if (err) |
723 | return err; |
724 | if (val > 1) |
725 | return -EINVAL; |
726 | |
727 | mutex_lock(&data->update_lock); |
728 | data->pwm[nr] = w83792d_read_value(client, W83792D_REG_PWM[nr]); |
729 | if (val) { /* PWM mode */ |
730 | data->pwm[nr] |= 0x80; |
731 | } else { /* DC mode */ |
732 | data->pwm[nr] &= 0x7f; |
733 | } |
734 | w83792d_write_value(client, W83792D_REG_PWM[nr], data->pwm[nr]); |
735 | mutex_unlock(&data->update_lock); |
736 | |
737 | return count; |
738 | } |
739 | |
740 | static ssize_t |
741 | show_chassis_clear(struct device *dev, struct device_attribute *attr, |
742 | char *buf) |
743 | { |
744 | struct w83792d_data *data = w83792d_update_device(dev); |
745 | return sprintf(buf, "%d\n", data->chassis); |
746 | } |
747 | |
748 | static ssize_t |
749 | store_chassis_clear(struct device *dev, struct device_attribute *attr, |
750 | const char *buf, size_t count) |
751 | { |
752 | struct i2c_client *client = to_i2c_client(dev); |
753 | struct w83792d_data *data = i2c_get_clientdata(client); |
754 | unsigned long val; |
755 | u8 reg; |
756 | |
757 | if (kstrtoul(buf, 10, &val) || val != 0) |
758 | return -EINVAL; |
759 | |
760 | mutex_lock(&data->update_lock); |
761 | reg = w83792d_read_value(client, W83792D_REG_CHASSIS_CLR); |
762 | w83792d_write_value(client, W83792D_REG_CHASSIS_CLR, reg | 0x80); |
763 | data->valid = 0; /* Force cache refresh */ |
764 | mutex_unlock(&data->update_lock); |
765 | |
766 | return count; |
767 | } |
768 | |
769 | /* For Smart Fan I / Thermal Cruise */ |
770 | static ssize_t |
771 | show_thermal_cruise(struct device *dev, struct device_attribute *attr, |
772 | char *buf) |
773 | { |
774 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); |
775 | int nr = sensor_attr->index; |
776 | struct w83792d_data *data = w83792d_update_device(dev); |
777 | return sprintf(buf, "%ld\n", (long)data->thermal_cruise[nr-1]); |
778 | } |
779 | |
780 | static ssize_t |
781 | store_thermal_cruise(struct device *dev, struct device_attribute *attr, |
782 | const char *buf, size_t count) |
783 | { |
784 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); |
785 | int nr = sensor_attr->index - 1; |
786 | struct i2c_client *client = to_i2c_client(dev); |
787 | struct w83792d_data *data = i2c_get_clientdata(client); |
788 | u8 target_tmp = 0, target_mask = 0; |
789 | unsigned long val; |
790 | int err; |
791 | |
792 | err = kstrtoul(buf, 10, &val); |
793 | if (err) |
794 | return err; |
795 | |
796 | target_tmp = val; |
797 | target_tmp = target_tmp & 0x7f; |
798 | mutex_lock(&data->update_lock); |
799 | target_mask = w83792d_read_value(client, |
800 | W83792D_REG_THERMAL[nr]) & 0x80; |
801 | data->thermal_cruise[nr] = clamp_val(target_tmp, 0, 255); |
802 | w83792d_write_value(client, W83792D_REG_THERMAL[nr], |
803 | (data->thermal_cruise[nr]) | target_mask); |
804 | mutex_unlock(&data->update_lock); |
805 | |
806 | return count; |
807 | } |
808 | |
809 | /* For Smart Fan I/Thermal Cruise and Smart Fan II */ |
810 | static ssize_t |
811 | show_tolerance(struct device *dev, struct device_attribute *attr, |
812 | char *buf) |
813 | { |
814 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); |
815 | int nr = sensor_attr->index; |
816 | struct w83792d_data *data = w83792d_update_device(dev); |
817 | return sprintf(buf, "%ld\n", (long)data->tolerance[nr-1]); |
818 | } |
819 | |
820 | static ssize_t |
821 | store_tolerance(struct device *dev, struct device_attribute *attr, |
822 | const char *buf, size_t count) |
823 | { |
824 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); |
825 | int nr = sensor_attr->index - 1; |
826 | struct i2c_client *client = to_i2c_client(dev); |
827 | struct w83792d_data *data = i2c_get_clientdata(client); |
828 | u8 tol_tmp, tol_mask; |
829 | unsigned long val; |
830 | int err; |
831 | |
832 | err = kstrtoul(buf, 10, &val); |
833 | if (err) |
834 | return err; |
835 | |
836 | mutex_lock(&data->update_lock); |
837 | tol_mask = w83792d_read_value(client, |
838 | W83792D_REG_TOLERANCE[nr]) & ((nr == 1) ? 0x0f : 0xf0); |
839 | tol_tmp = clamp_val(val, 0, 15); |
840 | tol_tmp &= 0x0f; |
841 | data->tolerance[nr] = tol_tmp; |
842 | if (nr == 1) |
843 | tol_tmp <<= 4; |
844 | w83792d_write_value(client, W83792D_REG_TOLERANCE[nr], |
845 | tol_mask | tol_tmp); |
846 | mutex_unlock(&data->update_lock); |
847 | |
848 | return count; |
849 | } |
850 | |
851 | /* For Smart Fan II */ |
852 | static ssize_t |
853 | show_sf2_point(struct device *dev, struct device_attribute *attr, |
854 | char *buf) |
855 | { |
856 | struct sensor_device_attribute_2 *sensor_attr |
857 | = to_sensor_dev_attr_2(attr); |
858 | int nr = sensor_attr->nr; |
859 | int index = sensor_attr->index; |
860 | struct w83792d_data *data = w83792d_update_device(dev); |
861 | return sprintf(buf, "%ld\n", (long)data->sf2_points[index-1][nr-1]); |
862 | } |
863 | |
864 | static ssize_t |
865 | store_sf2_point(struct device *dev, struct device_attribute *attr, |
866 | const char *buf, size_t count) |
867 | { |
868 | struct sensor_device_attribute_2 *sensor_attr |
869 | = to_sensor_dev_attr_2(attr); |
870 | int nr = sensor_attr->nr - 1; |
871 | int index = sensor_attr->index - 1; |
872 | struct i2c_client *client = to_i2c_client(dev); |
873 | struct w83792d_data *data = i2c_get_clientdata(client); |
874 | u8 mask_tmp = 0; |
875 | unsigned long val; |
876 | int err; |
877 | |
878 | err = kstrtoul(buf, 10, &val); |
879 | if (err) |
880 | return err; |
881 | |
882 | mutex_lock(&data->update_lock); |
883 | data->sf2_points[index][nr] = clamp_val(val, 0, 127); |
884 | mask_tmp = w83792d_read_value(client, |
885 | W83792D_REG_POINTS[index][nr]) & 0x80; |
886 | w83792d_write_value(client, W83792D_REG_POINTS[index][nr], |
887 | mask_tmp|data->sf2_points[index][nr]); |
888 | mutex_unlock(&data->update_lock); |
889 | |
890 | return count; |
891 | } |
892 | |
893 | static ssize_t |
894 | show_sf2_level(struct device *dev, struct device_attribute *attr, |
895 | char *buf) |
896 | { |
897 | struct sensor_device_attribute_2 *sensor_attr |
898 | = to_sensor_dev_attr_2(attr); |
899 | int nr = sensor_attr->nr; |
900 | int index = sensor_attr->index; |
901 | struct w83792d_data *data = w83792d_update_device(dev); |
902 | return sprintf(buf, "%d\n", |
903 | (((data->sf2_levels[index-1][nr]) * 100) / 15)); |
904 | } |
905 | |
906 | static ssize_t |
907 | store_sf2_level(struct device *dev, struct device_attribute *attr, |
908 | const char *buf, size_t count) |
909 | { |
910 | struct sensor_device_attribute_2 *sensor_attr |
911 | = to_sensor_dev_attr_2(attr); |
912 | int nr = sensor_attr->nr; |
913 | int index = sensor_attr->index - 1; |
914 | struct i2c_client *client = to_i2c_client(dev); |
915 | struct w83792d_data *data = i2c_get_clientdata(client); |
916 | u8 mask_tmp = 0, level_tmp = 0; |
917 | unsigned long val; |
918 | int err; |
919 | |
920 | err = kstrtoul(buf, 10, &val); |
921 | if (err) |
922 | return err; |
923 | |
924 | mutex_lock(&data->update_lock); |
925 | data->sf2_levels[index][nr] = clamp_val((val * 15) / 100, 0, 15); |
926 | mask_tmp = w83792d_read_value(client, W83792D_REG_LEVELS[index][nr]) |
927 | & ((nr == 3) ? 0xf0 : 0x0f); |
928 | if (nr == 3) |
929 | level_tmp = data->sf2_levels[index][nr]; |
930 | else |
931 | level_tmp = data->sf2_levels[index][nr] << 4; |
932 | w83792d_write_value(client, W83792D_REG_LEVELS[index][nr], |
933 | level_tmp | mask_tmp); |
934 | mutex_unlock(&data->update_lock); |
935 | |
936 | return count; |
937 | } |
938 | |
939 | |
940 | static int |
941 | w83792d_detect_subclients(struct i2c_client *new_client) |
942 | { |
943 | int i, id, err; |
944 | int address = new_client->addr; |
945 | u8 val; |
946 | struct i2c_adapter *adapter = new_client->adapter; |
947 | struct w83792d_data *data = i2c_get_clientdata(new_client); |
948 | |
949 | id = i2c_adapter_id(adapter); |
950 | if (force_subclients[0] == id && force_subclients[1] == address) { |
951 | for (i = 2; i <= 3; i++) { |
952 | if (force_subclients[i] < 0x48 || |
953 | force_subclients[i] > 0x4f) { |
954 | dev_err(&new_client->dev, "invalid subclient " |
955 | "address %d; must be 0x48-0x4f\n", |
956 | force_subclients[i]); |
957 | err = -ENODEV; |
958 | goto ERROR_SC_0; |
959 | } |
960 | } |
961 | w83792d_write_value(new_client, W83792D_REG_I2C_SUBADDR, |
962 | (force_subclients[2] & 0x07) | |
963 | ((force_subclients[3] & 0x07) << 4)); |
964 | } |
965 | |
966 | val = w83792d_read_value(new_client, W83792D_REG_I2C_SUBADDR); |
967 | if (!(val & 0x08)) |
968 | data->lm75[0] = i2c_new_dummy(adapter, 0x48 + (val & 0x7)); |
969 | if (!(val & 0x80)) { |
970 | if ((data->lm75[0] != NULL) && |
971 | ((val & 0x7) == ((val >> 4) & 0x7))) { |
972 | dev_err(&new_client->dev, "duplicate addresses 0x%x, " |
973 | "use force_subclient\n", data->lm75[0]->addr); |
974 | err = -ENODEV; |
975 | goto ERROR_SC_1; |
976 | } |
977 | data->lm75[1] = i2c_new_dummy(adapter, |
978 | 0x48 + ((val >> 4) & 0x7)); |
979 | } |
980 | |
981 | return 0; |
982 | |
983 | /* Undo inits in case of errors */ |
984 | |
985 | ERROR_SC_1: |
986 | if (data->lm75[0] != NULL) |
987 | i2c_unregister_device(data->lm75[0]); |
988 | ERROR_SC_0: |
989 | return err; |
990 | } |
991 | |
992 | static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_in, NULL, 0); |
993 | static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 1); |
994 | static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 2); |
995 | static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in, NULL, 3); |
996 | static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in, NULL, 4); |
997 | static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_in, NULL, 5); |
998 | static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_in, NULL, 6); |
999 | static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_in, NULL, 7); |
1000 | static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_in, NULL, 8); |
1001 | static SENSOR_DEVICE_ATTR(in0_min, S_IWUSR | S_IRUGO, |
1002 | show_in_min, store_in_min, 0); |
1003 | static SENSOR_DEVICE_ATTR(in1_min, S_IWUSR | S_IRUGO, |
1004 | show_in_min, store_in_min, 1); |
1005 | static SENSOR_DEVICE_ATTR(in2_min, S_IWUSR | S_IRUGO, |
1006 | show_in_min, store_in_min, 2); |
1007 | static SENSOR_DEVICE_ATTR(in3_min, S_IWUSR | S_IRUGO, |
1008 | show_in_min, store_in_min, 3); |
1009 | static SENSOR_DEVICE_ATTR(in4_min, S_IWUSR | S_IRUGO, |
1010 | show_in_min, store_in_min, 4); |
1011 | static SENSOR_DEVICE_ATTR(in5_min, S_IWUSR | S_IRUGO, |
1012 | show_in_min, store_in_min, 5); |
1013 | static SENSOR_DEVICE_ATTR(in6_min, S_IWUSR | S_IRUGO, |
1014 | show_in_min, store_in_min, 6); |
1015 | static SENSOR_DEVICE_ATTR(in7_min, S_IWUSR | S_IRUGO, |
1016 | show_in_min, store_in_min, 7); |
1017 | static SENSOR_DEVICE_ATTR(in8_min, S_IWUSR | S_IRUGO, |
1018 | show_in_min, store_in_min, 8); |
1019 | static SENSOR_DEVICE_ATTR(in0_max, S_IWUSR | S_IRUGO, |
1020 | show_in_max, store_in_max, 0); |
1021 | static SENSOR_DEVICE_ATTR(in1_max, S_IWUSR | S_IRUGO, |
1022 | show_in_max, store_in_max, 1); |
1023 | static SENSOR_DEVICE_ATTR(in2_max, S_IWUSR | S_IRUGO, |
1024 | show_in_max, store_in_max, 2); |
1025 | static SENSOR_DEVICE_ATTR(in3_max, S_IWUSR | S_IRUGO, |
1026 | show_in_max, store_in_max, 3); |
1027 | static SENSOR_DEVICE_ATTR(in4_max, S_IWUSR | S_IRUGO, |
1028 | show_in_max, store_in_max, 4); |
1029 | static SENSOR_DEVICE_ATTR(in5_max, S_IWUSR | S_IRUGO, |
1030 | show_in_max, store_in_max, 5); |
1031 | static SENSOR_DEVICE_ATTR(in6_max, S_IWUSR | S_IRUGO, |
1032 | show_in_max, store_in_max, 6); |
1033 | static SENSOR_DEVICE_ATTR(in7_max, S_IWUSR | S_IRUGO, |
1034 | show_in_max, store_in_max, 7); |
1035 | static SENSOR_DEVICE_ATTR(in8_max, S_IWUSR | S_IRUGO, |
1036 | show_in_max, store_in_max, 8); |
1037 | static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp1, NULL, 0, 0); |
1038 | static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp23, NULL, 0, 0); |
1039 | static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp23, NULL, 1, 0); |
1040 | static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, |
1041 | show_temp1, store_temp1, 0, 1); |
1042 | static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp23, |
1043 | store_temp23, 0, 2); |
1044 | static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp23, |
1045 | store_temp23, 1, 2); |
1046 | static SENSOR_DEVICE_ATTR_2(temp1_max_hyst, S_IRUGO | S_IWUSR, |
1047 | show_temp1, store_temp1, 0, 2); |
1048 | static SENSOR_DEVICE_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR, |
1049 | show_temp23, store_temp23, 0, 4); |
1050 | static SENSOR_DEVICE_ATTR_2(temp3_max_hyst, S_IRUGO | S_IWUSR, |
1051 | show_temp23, store_temp23, 1, 4); |
1052 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); |
1053 | static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0); |
1054 | static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1); |
1055 | static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 2); |
1056 | static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 3); |
1057 | static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 4); |
1058 | static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 5); |
1059 | static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 6); |
1060 | static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 7); |
1061 | static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 8); |
1062 | static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 9); |
1063 | static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 10); |
1064 | static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 11); |
1065 | static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 12); |
1066 | static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_alarm, NULL, 15); |
1067 | static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 19); |
1068 | static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 20); |
1069 | static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 21); |
1070 | static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 22); |
1071 | static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_alarm, NULL, 23); |
1072 | static DEVICE_ATTR(intrusion0_alarm, S_IRUGO | S_IWUSR, |
1073 | show_chassis_clear, store_chassis_clear); |
1074 | static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0); |
1075 | static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1); |
1076 | static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2); |
1077 | static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, |
1078 | show_pwmenable, store_pwmenable, 1); |
1079 | static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, |
1080 | show_pwmenable, store_pwmenable, 2); |
1081 | static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, |
1082 | show_pwmenable, store_pwmenable, 3); |
1083 | static SENSOR_DEVICE_ATTR(pwm1_mode, S_IWUSR | S_IRUGO, |
1084 | show_pwm_mode, store_pwm_mode, 0); |
1085 | static SENSOR_DEVICE_ATTR(pwm2_mode, S_IWUSR | S_IRUGO, |
1086 | show_pwm_mode, store_pwm_mode, 1); |
1087 | static SENSOR_DEVICE_ATTR(pwm3_mode, S_IWUSR | S_IRUGO, |
1088 | show_pwm_mode, store_pwm_mode, 2); |
1089 | static SENSOR_DEVICE_ATTR(tolerance1, S_IWUSR | S_IRUGO, |
1090 | show_tolerance, store_tolerance, 1); |
1091 | static SENSOR_DEVICE_ATTR(tolerance2, S_IWUSR | S_IRUGO, |
1092 | show_tolerance, store_tolerance, 2); |
1093 | static SENSOR_DEVICE_ATTR(tolerance3, S_IWUSR | S_IRUGO, |
1094 | show_tolerance, store_tolerance, 3); |
1095 | static SENSOR_DEVICE_ATTR(thermal_cruise1, S_IWUSR | S_IRUGO, |
1096 | show_thermal_cruise, store_thermal_cruise, 1); |
1097 | static SENSOR_DEVICE_ATTR(thermal_cruise2, S_IWUSR | S_IRUGO, |
1098 | show_thermal_cruise, store_thermal_cruise, 2); |
1099 | static SENSOR_DEVICE_ATTR(thermal_cruise3, S_IWUSR | S_IRUGO, |
1100 | show_thermal_cruise, store_thermal_cruise, 3); |
1101 | static SENSOR_DEVICE_ATTR_2(sf2_point1_fan1, S_IRUGO | S_IWUSR, |
1102 | show_sf2_point, store_sf2_point, 1, 1); |
1103 | static SENSOR_DEVICE_ATTR_2(sf2_point2_fan1, S_IRUGO | S_IWUSR, |
1104 | show_sf2_point, store_sf2_point, 2, 1); |
1105 | static SENSOR_DEVICE_ATTR_2(sf2_point3_fan1, S_IRUGO | S_IWUSR, |
1106 | show_sf2_point, store_sf2_point, 3, 1); |
1107 | static SENSOR_DEVICE_ATTR_2(sf2_point4_fan1, S_IRUGO | S_IWUSR, |
1108 | show_sf2_point, store_sf2_point, 4, 1); |
1109 | static SENSOR_DEVICE_ATTR_2(sf2_point1_fan2, S_IRUGO | S_IWUSR, |
1110 | show_sf2_point, store_sf2_point, 1, 2); |
1111 | static SENSOR_DEVICE_ATTR_2(sf2_point2_fan2, S_IRUGO | S_IWUSR, |
1112 | show_sf2_point, store_sf2_point, 2, 2); |
1113 | static SENSOR_DEVICE_ATTR_2(sf2_point3_fan2, S_IRUGO | S_IWUSR, |
1114 | show_sf2_point, store_sf2_point, 3, 2); |
1115 | static SENSOR_DEVICE_ATTR_2(sf2_point4_fan2, S_IRUGO | S_IWUSR, |
1116 | show_sf2_point, store_sf2_point, 4, 2); |
1117 | static SENSOR_DEVICE_ATTR_2(sf2_point1_fan3, S_IRUGO | S_IWUSR, |
1118 | show_sf2_point, store_sf2_point, 1, 3); |
1119 | static SENSOR_DEVICE_ATTR_2(sf2_point2_fan3, S_IRUGO | S_IWUSR, |
1120 | show_sf2_point, store_sf2_point, 2, 3); |
1121 | static SENSOR_DEVICE_ATTR_2(sf2_point3_fan3, S_IRUGO | S_IWUSR, |
1122 | show_sf2_point, store_sf2_point, 3, 3); |
1123 | static SENSOR_DEVICE_ATTR_2(sf2_point4_fan3, S_IRUGO | S_IWUSR, |
1124 | show_sf2_point, store_sf2_point, 4, 3); |
1125 | static SENSOR_DEVICE_ATTR_2(sf2_level1_fan1, S_IRUGO | S_IWUSR, |
1126 | show_sf2_level, store_sf2_level, 1, 1); |
1127 | static SENSOR_DEVICE_ATTR_2(sf2_level2_fan1, S_IRUGO | S_IWUSR, |
1128 | show_sf2_level, store_sf2_level, 2, 1); |
1129 | static SENSOR_DEVICE_ATTR_2(sf2_level3_fan1, S_IRUGO | S_IWUSR, |
1130 | show_sf2_level, store_sf2_level, 3, 1); |
1131 | static SENSOR_DEVICE_ATTR_2(sf2_level1_fan2, S_IRUGO | S_IWUSR, |
1132 | show_sf2_level, store_sf2_level, 1, 2); |
1133 | static SENSOR_DEVICE_ATTR_2(sf2_level2_fan2, S_IRUGO | S_IWUSR, |
1134 | show_sf2_level, store_sf2_level, 2, 2); |
1135 | static SENSOR_DEVICE_ATTR_2(sf2_level3_fan2, S_IRUGO | S_IWUSR, |
1136 | show_sf2_level, store_sf2_level, 3, 2); |
1137 | static SENSOR_DEVICE_ATTR_2(sf2_level1_fan3, S_IRUGO | S_IWUSR, |
1138 | show_sf2_level, store_sf2_level, 1, 3); |
1139 | static SENSOR_DEVICE_ATTR_2(sf2_level2_fan3, S_IRUGO | S_IWUSR, |
1140 | show_sf2_level, store_sf2_level, 2, 3); |
1141 | static SENSOR_DEVICE_ATTR_2(sf2_level3_fan3, S_IRUGO | S_IWUSR, |
1142 | show_sf2_level, store_sf2_level, 3, 3); |
1143 | static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 1); |
1144 | static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 2); |
1145 | static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 3); |
1146 | static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 4); |
1147 | static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 5); |
1148 | static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan, NULL, 6); |
1149 | static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan, NULL, 7); |
1150 | static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, |
1151 | show_fan_min, store_fan_min, 1); |
1152 | static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, |
1153 | show_fan_min, store_fan_min, 2); |
1154 | static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO, |
1155 | show_fan_min, store_fan_min, 3); |
1156 | static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO, |
1157 | show_fan_min, store_fan_min, 4); |
1158 | static SENSOR_DEVICE_ATTR(fan5_min, S_IWUSR | S_IRUGO, |
1159 | show_fan_min, store_fan_min, 5); |
1160 | static SENSOR_DEVICE_ATTR(fan6_min, S_IWUSR | S_IRUGO, |
1161 | show_fan_min, store_fan_min, 6); |
1162 | static SENSOR_DEVICE_ATTR(fan7_min, S_IWUSR | S_IRUGO, |
1163 | show_fan_min, store_fan_min, 7); |
1164 | static SENSOR_DEVICE_ATTR(fan1_div, S_IWUSR | S_IRUGO, |
1165 | show_fan_div, store_fan_div, 1); |
1166 | static SENSOR_DEVICE_ATTR(fan2_div, S_IWUSR | S_IRUGO, |
1167 | show_fan_div, store_fan_div, 2); |
1168 | static SENSOR_DEVICE_ATTR(fan3_div, S_IWUSR | S_IRUGO, |
1169 | show_fan_div, store_fan_div, 3); |
1170 | static SENSOR_DEVICE_ATTR(fan4_div, S_IWUSR | S_IRUGO, |
1171 | show_fan_div, store_fan_div, 4); |
1172 | static SENSOR_DEVICE_ATTR(fan5_div, S_IWUSR | S_IRUGO, |
1173 | show_fan_div, store_fan_div, 5); |
1174 | static SENSOR_DEVICE_ATTR(fan6_div, S_IWUSR | S_IRUGO, |
1175 | show_fan_div, store_fan_div, 6); |
1176 | static SENSOR_DEVICE_ATTR(fan7_div, S_IWUSR | S_IRUGO, |
1177 | show_fan_div, store_fan_div, 7); |
1178 | |
1179 | static struct attribute *w83792d_attributes_fan[4][5] = { |
1180 | { |
1181 | &sensor_dev_attr_fan4_input.dev_attr.attr, |
1182 | &sensor_dev_attr_fan4_min.dev_attr.attr, |
1183 | &sensor_dev_attr_fan4_div.dev_attr.attr, |
1184 | &sensor_dev_attr_fan4_alarm.dev_attr.attr, |
1185 | NULL |
1186 | }, { |
1187 | &sensor_dev_attr_fan5_input.dev_attr.attr, |
1188 | &sensor_dev_attr_fan5_min.dev_attr.attr, |
1189 | &sensor_dev_attr_fan5_div.dev_attr.attr, |
1190 | &sensor_dev_attr_fan5_alarm.dev_attr.attr, |
1191 | NULL |
1192 | }, { |
1193 | &sensor_dev_attr_fan6_input.dev_attr.attr, |
1194 | &sensor_dev_attr_fan6_min.dev_attr.attr, |
1195 | &sensor_dev_attr_fan6_div.dev_attr.attr, |
1196 | &sensor_dev_attr_fan6_alarm.dev_attr.attr, |
1197 | NULL |
1198 | }, { |
1199 | &sensor_dev_attr_fan7_input.dev_attr.attr, |
1200 | &sensor_dev_attr_fan7_min.dev_attr.attr, |
1201 | &sensor_dev_attr_fan7_div.dev_attr.attr, |
1202 | &sensor_dev_attr_fan7_alarm.dev_attr.attr, |
1203 | NULL |
1204 | } |
1205 | }; |
1206 | |
1207 | static const struct attribute_group w83792d_group_fan[4] = { |
1208 | { .attrs = w83792d_attributes_fan[0] }, |
1209 | { .attrs = w83792d_attributes_fan[1] }, |
1210 | { .attrs = w83792d_attributes_fan[2] }, |
1211 | { .attrs = w83792d_attributes_fan[3] }, |
1212 | }; |
1213 | |
1214 | static struct attribute *w83792d_attributes[] = { |
1215 | &sensor_dev_attr_in0_input.dev_attr.attr, |
1216 | &sensor_dev_attr_in0_max.dev_attr.attr, |
1217 | &sensor_dev_attr_in0_min.dev_attr.attr, |
1218 | &sensor_dev_attr_in1_input.dev_attr.attr, |
1219 | &sensor_dev_attr_in1_max.dev_attr.attr, |
1220 | &sensor_dev_attr_in1_min.dev_attr.attr, |
1221 | &sensor_dev_attr_in2_input.dev_attr.attr, |
1222 | &sensor_dev_attr_in2_max.dev_attr.attr, |
1223 | &sensor_dev_attr_in2_min.dev_attr.attr, |
1224 | &sensor_dev_attr_in3_input.dev_attr.attr, |
1225 | &sensor_dev_attr_in3_max.dev_attr.attr, |
1226 | &sensor_dev_attr_in3_min.dev_attr.attr, |
1227 | &sensor_dev_attr_in4_input.dev_attr.attr, |
1228 | &sensor_dev_attr_in4_max.dev_attr.attr, |
1229 | &sensor_dev_attr_in4_min.dev_attr.attr, |
1230 | &sensor_dev_attr_in5_input.dev_attr.attr, |
1231 | &sensor_dev_attr_in5_max.dev_attr.attr, |
1232 | &sensor_dev_attr_in5_min.dev_attr.attr, |
1233 | &sensor_dev_attr_in6_input.dev_attr.attr, |
1234 | &sensor_dev_attr_in6_max.dev_attr.attr, |
1235 | &sensor_dev_attr_in6_min.dev_attr.attr, |
1236 | &sensor_dev_attr_in7_input.dev_attr.attr, |
1237 | &sensor_dev_attr_in7_max.dev_attr.attr, |
1238 | &sensor_dev_attr_in7_min.dev_attr.attr, |
1239 | &sensor_dev_attr_in8_input.dev_attr.attr, |
1240 | &sensor_dev_attr_in8_max.dev_attr.attr, |
1241 | &sensor_dev_attr_in8_min.dev_attr.attr, |
1242 | &sensor_dev_attr_in0_alarm.dev_attr.attr, |
1243 | &sensor_dev_attr_in1_alarm.dev_attr.attr, |
1244 | &sensor_dev_attr_in2_alarm.dev_attr.attr, |
1245 | &sensor_dev_attr_in3_alarm.dev_attr.attr, |
1246 | &sensor_dev_attr_in4_alarm.dev_attr.attr, |
1247 | &sensor_dev_attr_in5_alarm.dev_attr.attr, |
1248 | &sensor_dev_attr_in6_alarm.dev_attr.attr, |
1249 | &sensor_dev_attr_in7_alarm.dev_attr.attr, |
1250 | &sensor_dev_attr_in8_alarm.dev_attr.attr, |
1251 | &sensor_dev_attr_temp1_input.dev_attr.attr, |
1252 | &sensor_dev_attr_temp1_max.dev_attr.attr, |
1253 | &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, |
1254 | &sensor_dev_attr_temp2_input.dev_attr.attr, |
1255 | &sensor_dev_attr_temp2_max.dev_attr.attr, |
1256 | &sensor_dev_attr_temp2_max_hyst.dev_attr.attr, |
1257 | &sensor_dev_attr_temp3_input.dev_attr.attr, |
1258 | &sensor_dev_attr_temp3_max.dev_attr.attr, |
1259 | &sensor_dev_attr_temp3_max_hyst.dev_attr.attr, |
1260 | &sensor_dev_attr_temp1_alarm.dev_attr.attr, |
1261 | &sensor_dev_attr_temp2_alarm.dev_attr.attr, |
1262 | &sensor_dev_attr_temp3_alarm.dev_attr.attr, |
1263 | &sensor_dev_attr_pwm1.dev_attr.attr, |
1264 | &sensor_dev_attr_pwm1_mode.dev_attr.attr, |
1265 | &sensor_dev_attr_pwm1_enable.dev_attr.attr, |
1266 | &sensor_dev_attr_pwm2.dev_attr.attr, |
1267 | &sensor_dev_attr_pwm2_mode.dev_attr.attr, |
1268 | &sensor_dev_attr_pwm2_enable.dev_attr.attr, |
1269 | &sensor_dev_attr_pwm3.dev_attr.attr, |
1270 | &sensor_dev_attr_pwm3_mode.dev_attr.attr, |
1271 | &sensor_dev_attr_pwm3_enable.dev_attr.attr, |
1272 | &dev_attr_alarms.attr, |
1273 | &dev_attr_intrusion0_alarm.attr, |
1274 | &sensor_dev_attr_tolerance1.dev_attr.attr, |
1275 | &sensor_dev_attr_thermal_cruise1.dev_attr.attr, |
1276 | &sensor_dev_attr_tolerance2.dev_attr.attr, |
1277 | &sensor_dev_attr_thermal_cruise2.dev_attr.attr, |
1278 | &sensor_dev_attr_tolerance3.dev_attr.attr, |
1279 | &sensor_dev_attr_thermal_cruise3.dev_attr.attr, |
1280 | &sensor_dev_attr_sf2_point1_fan1.dev_attr.attr, |
1281 | &sensor_dev_attr_sf2_point2_fan1.dev_attr.attr, |
1282 | &sensor_dev_attr_sf2_point3_fan1.dev_attr.attr, |
1283 | &sensor_dev_attr_sf2_point4_fan1.dev_attr.attr, |
1284 | &sensor_dev_attr_sf2_point1_fan2.dev_attr.attr, |
1285 | &sensor_dev_attr_sf2_point2_fan2.dev_attr.attr, |
1286 | &sensor_dev_attr_sf2_point3_fan2.dev_attr.attr, |
1287 | &sensor_dev_attr_sf2_point4_fan2.dev_attr.attr, |
1288 | &sensor_dev_attr_sf2_point1_fan3.dev_attr.attr, |
1289 | &sensor_dev_attr_sf2_point2_fan3.dev_attr.attr, |
1290 | &sensor_dev_attr_sf2_point3_fan3.dev_attr.attr, |
1291 | &sensor_dev_attr_sf2_point4_fan3.dev_attr.attr, |
1292 | &sensor_dev_attr_sf2_level1_fan1.dev_attr.attr, |
1293 | &sensor_dev_attr_sf2_level2_fan1.dev_attr.attr, |
1294 | &sensor_dev_attr_sf2_level3_fan1.dev_attr.attr, |
1295 | &sensor_dev_attr_sf2_level1_fan2.dev_attr.attr, |
1296 | &sensor_dev_attr_sf2_level2_fan2.dev_attr.attr, |
1297 | &sensor_dev_attr_sf2_level3_fan2.dev_attr.attr, |
1298 | &sensor_dev_attr_sf2_level1_fan3.dev_attr.attr, |
1299 | &sensor_dev_attr_sf2_level2_fan3.dev_attr.attr, |
1300 | &sensor_dev_attr_sf2_level3_fan3.dev_attr.attr, |
1301 | &sensor_dev_attr_fan1_input.dev_attr.attr, |
1302 | &sensor_dev_attr_fan1_min.dev_attr.attr, |
1303 | &sensor_dev_attr_fan1_div.dev_attr.attr, |
1304 | &sensor_dev_attr_fan1_alarm.dev_attr.attr, |
1305 | &sensor_dev_attr_fan2_input.dev_attr.attr, |
1306 | &sensor_dev_attr_fan2_min.dev_attr.attr, |
1307 | &sensor_dev_attr_fan2_div.dev_attr.attr, |
1308 | &sensor_dev_attr_fan2_alarm.dev_attr.attr, |
1309 | &sensor_dev_attr_fan3_input.dev_attr.attr, |
1310 | &sensor_dev_attr_fan3_min.dev_attr.attr, |
1311 | &sensor_dev_attr_fan3_div.dev_attr.attr, |
1312 | &sensor_dev_attr_fan3_alarm.dev_attr.attr, |
1313 | NULL |
1314 | }; |
1315 | |
1316 | static const struct attribute_group w83792d_group = { |
1317 | .attrs = w83792d_attributes, |
1318 | }; |
1319 | |
1320 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
1321 | static int |
1322 | w83792d_detect(struct i2c_client *client, struct i2c_board_info *info) |
1323 | { |
1324 | struct i2c_adapter *adapter = client->adapter; |
1325 | int val1, val2; |
1326 | unsigned short address = client->addr; |
1327 | |
1328 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
1329 | return -ENODEV; |
1330 | |
1331 | if (w83792d_read_value(client, W83792D_REG_CONFIG) & 0x80) |
1332 | return -ENODEV; |
1333 | |
1334 | val1 = w83792d_read_value(client, W83792D_REG_BANK); |
1335 | val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN); |
1336 | /* Check for Winbond ID if in bank 0 */ |
1337 | if (!(val1 & 0x07)) { /* is Bank0 */ |
1338 | if ((!(val1 & 0x80) && val2 != 0xa3) || |
1339 | ((val1 & 0x80) && val2 != 0x5c)) |
1340 | return -ENODEV; |
1341 | } |
1342 | /* |
1343 | * If Winbond chip, address of chip and W83792D_REG_I2C_ADDR |
1344 | * should match |
1345 | */ |
1346 | if (w83792d_read_value(client, W83792D_REG_I2C_ADDR) != address) |
1347 | return -ENODEV; |
1348 | |
1349 | /* Put it now into bank 0 and Vendor ID High Byte */ |
1350 | w83792d_write_value(client, |
1351 | W83792D_REG_BANK, |
1352 | (w83792d_read_value(client, |
1353 | W83792D_REG_BANK) & 0x78) | 0x80); |
1354 | |
1355 | /* Determine the chip type. */ |
1356 | val1 = w83792d_read_value(client, W83792D_REG_WCHIPID); |
1357 | val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN); |
1358 | if (val1 != 0x7a || val2 != 0x5c) |
1359 | return -ENODEV; |
1360 | |
1361 | strlcpy(info->type, "w83792d", I2C_NAME_SIZE); |
1362 | |
1363 | return 0; |
1364 | } |
1365 | |
1366 | static int |
1367 | w83792d_probe(struct i2c_client *client, const struct i2c_device_id *id) |
1368 | { |
1369 | struct w83792d_data *data; |
1370 | struct device *dev = &client->dev; |
1371 | int i, val1, err; |
1372 | |
1373 | data = devm_kzalloc(dev, sizeof(struct w83792d_data), GFP_KERNEL); |
1374 | if (!data) |
1375 | return -ENOMEM; |
1376 | |
1377 | i2c_set_clientdata(client, data); |
1378 | data->valid = 0; |
1379 | mutex_init(&data->update_lock); |
1380 | |
1381 | err = w83792d_detect_subclients(client); |
1382 | if (err) |
1383 | return err; |
1384 | |
1385 | /* Initialize the chip */ |
1386 | w83792d_init_client(client); |
1387 | |
1388 | /* A few vars need to be filled upon startup */ |
1389 | for (i = 0; i < 7; i++) { |
1390 | data->fan_min[i] = w83792d_read_value(client, |
1391 | W83792D_REG_FAN_MIN[i]); |
1392 | } |
1393 | |
1394 | /* Register sysfs hooks */ |
1395 | err = sysfs_create_group(&dev->kobj, &w83792d_group); |
1396 | if (err) |
1397 | goto exit_i2c_unregister; |
1398 | |
1399 | /* |
1400 | * Read GPIO enable register to check if pins for fan 4,5 are used as |
1401 | * GPIO |
1402 | */ |
1403 | val1 = w83792d_read_value(client, W83792D_REG_GPIO_EN); |
1404 | |
1405 | if (!(val1 & 0x40)) { |
1406 | err = sysfs_create_group(&dev->kobj, &w83792d_group_fan[0]); |
1407 | if (err) |
1408 | goto exit_remove_files; |
1409 | } |
1410 | |
1411 | if (!(val1 & 0x20)) { |
1412 | err = sysfs_create_group(&dev->kobj, &w83792d_group_fan[1]); |
1413 | if (err) |
1414 | goto exit_remove_files; |
1415 | } |
1416 | |
1417 | val1 = w83792d_read_value(client, W83792D_REG_PIN); |
1418 | if (val1 & 0x40) { |
1419 | err = sysfs_create_group(&dev->kobj, &w83792d_group_fan[2]); |
1420 | if (err) |
1421 | goto exit_remove_files; |
1422 | } |
1423 | |
1424 | if (val1 & 0x04) { |
1425 | err = sysfs_create_group(&dev->kobj, &w83792d_group_fan[3]); |
1426 | if (err) |
1427 | goto exit_remove_files; |
1428 | } |
1429 | |
1430 | data->hwmon_dev = hwmon_device_register(dev); |
1431 | if (IS_ERR(data->hwmon_dev)) { |
1432 | err = PTR_ERR(data->hwmon_dev); |
1433 | goto exit_remove_files; |
1434 | } |
1435 | |
1436 | return 0; |
1437 | |
1438 | exit_remove_files: |
1439 | sysfs_remove_group(&dev->kobj, &w83792d_group); |
1440 | for (i = 0; i < ARRAY_SIZE(w83792d_group_fan); i++) |
1441 | sysfs_remove_group(&dev->kobj, &w83792d_group_fan[i]); |
1442 | exit_i2c_unregister: |
1443 | if (data->lm75[0] != NULL) |
1444 | i2c_unregister_device(data->lm75[0]); |
1445 | if (data->lm75[1] != NULL) |
1446 | i2c_unregister_device(data->lm75[1]); |
1447 | return err; |
1448 | } |
1449 | |
1450 | static int |
1451 | w83792d_remove(struct i2c_client *client) |
1452 | { |
1453 | struct w83792d_data *data = i2c_get_clientdata(client); |
1454 | int i; |
1455 | |
1456 | hwmon_device_unregister(data->hwmon_dev); |
1457 | sysfs_remove_group(&client->dev.kobj, &w83792d_group); |
1458 | for (i = 0; i < ARRAY_SIZE(w83792d_group_fan); i++) |
1459 | sysfs_remove_group(&client->dev.kobj, |
1460 | &w83792d_group_fan[i]); |
1461 | |
1462 | if (data->lm75[0] != NULL) |
1463 | i2c_unregister_device(data->lm75[0]); |
1464 | if (data->lm75[1] != NULL) |
1465 | i2c_unregister_device(data->lm75[1]); |
1466 | |
1467 | return 0; |
1468 | } |
1469 | |
1470 | static void |
1471 | w83792d_init_client(struct i2c_client *client) |
1472 | { |
1473 | u8 temp2_cfg, temp3_cfg, vid_in_b; |
1474 | |
1475 | if (init) |
1476 | w83792d_write_value(client, W83792D_REG_CONFIG, 0x80); |
1477 | |
1478 | /* |
1479 | * Clear the bit6 of W83792D_REG_VID_IN_B(set it into 0): |
1480 | * W83792D_REG_VID_IN_B bit6 = 0: the high/low limit of |
1481 | * vin0/vin1 can be modified by user; |
1482 | * W83792D_REG_VID_IN_B bit6 = 1: the high/low limit of |
1483 | * vin0/vin1 auto-updated, can NOT be modified by user. |
1484 | */ |
1485 | vid_in_b = w83792d_read_value(client, W83792D_REG_VID_IN_B); |
1486 | w83792d_write_value(client, W83792D_REG_VID_IN_B, |
1487 | vid_in_b & 0xbf); |
1488 | |
1489 | temp2_cfg = w83792d_read_value(client, W83792D_REG_TEMP2_CONFIG); |
1490 | temp3_cfg = w83792d_read_value(client, W83792D_REG_TEMP3_CONFIG); |
1491 | w83792d_write_value(client, W83792D_REG_TEMP2_CONFIG, |
1492 | temp2_cfg & 0xe6); |
1493 | w83792d_write_value(client, W83792D_REG_TEMP3_CONFIG, |
1494 | temp3_cfg & 0xe6); |
1495 | |
1496 | /* Start monitoring */ |
1497 | w83792d_write_value(client, W83792D_REG_CONFIG, |
1498 | (w83792d_read_value(client, |
1499 | W83792D_REG_CONFIG) & 0xf7) |
1500 | | 0x01); |
1501 | } |
1502 | |
1503 | static struct w83792d_data *w83792d_update_device(struct device *dev) |
1504 | { |
1505 | struct i2c_client *client = to_i2c_client(dev); |
1506 | struct w83792d_data *data = i2c_get_clientdata(client); |
1507 | int i, j; |
1508 | u8 reg_array_tmp[4], reg_tmp; |
1509 | |
1510 | mutex_lock(&data->update_lock); |
1511 | |
1512 | if (time_after |
1513 | (jiffies - data->last_updated, (unsigned long) (HZ * 3)) |
1514 | || time_before(jiffies, data->last_updated) || !data->valid) { |
1515 | dev_dbg(dev, "Starting device update\n"); |
1516 | |
1517 | /* Update the voltages measured value and limits */ |
1518 | for (i = 0; i < 9; i++) { |
1519 | data->in[i] = w83792d_read_value(client, |
1520 | W83792D_REG_IN[i]); |
1521 | data->in_max[i] = w83792d_read_value(client, |
1522 | W83792D_REG_IN_MAX[i]); |
1523 | data->in_min[i] = w83792d_read_value(client, |
1524 | W83792D_REG_IN_MIN[i]); |
1525 | } |
1526 | data->low_bits = w83792d_read_value(client, |
1527 | W83792D_REG_LOW_BITS1) + |
1528 | (w83792d_read_value(client, |
1529 | W83792D_REG_LOW_BITS2) << 8); |
1530 | for (i = 0; i < 7; i++) { |
1531 | /* Update the Fan measured value and limits */ |
1532 | data->fan[i] = w83792d_read_value(client, |
1533 | W83792D_REG_FAN[i]); |
1534 | data->fan_min[i] = w83792d_read_value(client, |
1535 | W83792D_REG_FAN_MIN[i]); |
1536 | /* Update the PWM/DC Value and PWM/DC flag */ |
1537 | data->pwm[i] = w83792d_read_value(client, |
1538 | W83792D_REG_PWM[i]); |
1539 | } |
1540 | |
1541 | reg_tmp = w83792d_read_value(client, W83792D_REG_FAN_CFG); |
1542 | data->pwmenable[0] = reg_tmp & 0x03; |
1543 | data->pwmenable[1] = (reg_tmp>>2) & 0x03; |
1544 | data->pwmenable[2] = (reg_tmp>>4) & 0x03; |
1545 | |
1546 | for (i = 0; i < 3; i++) { |
1547 | data->temp1[i] = w83792d_read_value(client, |
1548 | W83792D_REG_TEMP1[i]); |
1549 | } |
1550 | for (i = 0; i < 2; i++) { |
1551 | for (j = 0; j < 6; j++) { |
1552 | data->temp_add[i][j] = w83792d_read_value( |
1553 | client, W83792D_REG_TEMP_ADD[i][j]); |
1554 | } |
1555 | } |
1556 | |
1557 | /* Update the Fan Divisor */ |
1558 | for (i = 0; i < 4; i++) { |
1559 | reg_array_tmp[i] = w83792d_read_value(client, |
1560 | W83792D_REG_FAN_DIV[i]); |
1561 | } |
1562 | data->fan_div[0] = reg_array_tmp[0] & 0x07; |
1563 | data->fan_div[1] = (reg_array_tmp[0] >> 4) & 0x07; |
1564 | data->fan_div[2] = reg_array_tmp[1] & 0x07; |
1565 | data->fan_div[3] = (reg_array_tmp[1] >> 4) & 0x07; |
1566 | data->fan_div[4] = reg_array_tmp[2] & 0x07; |
1567 | data->fan_div[5] = (reg_array_tmp[2] >> 4) & 0x07; |
1568 | data->fan_div[6] = reg_array_tmp[3] & 0x07; |
1569 | |
1570 | /* Update the realtime status */ |
1571 | data->alarms = w83792d_read_value(client, W83792D_REG_ALARM1) + |
1572 | (w83792d_read_value(client, W83792D_REG_ALARM2) << 8) + |
1573 | (w83792d_read_value(client, W83792D_REG_ALARM3) << 16); |
1574 | |
1575 | /* Update CaseOpen status and it's CLR_CHS. */ |
1576 | data->chassis = (w83792d_read_value(client, |
1577 | W83792D_REG_CHASSIS) >> 5) & 0x01; |
1578 | |
1579 | /* Update Thermal Cruise/Smart Fan I target value */ |
1580 | for (i = 0; i < 3; i++) { |
1581 | data->thermal_cruise[i] = |
1582 | w83792d_read_value(client, |
1583 | W83792D_REG_THERMAL[i]) & 0x7f; |
1584 | } |
1585 | |
1586 | /* Update Smart Fan I/II tolerance */ |
1587 | reg_tmp = w83792d_read_value(client, W83792D_REG_TOLERANCE[0]); |
1588 | data->tolerance[0] = reg_tmp & 0x0f; |
1589 | data->tolerance[1] = (reg_tmp >> 4) & 0x0f; |
1590 | data->tolerance[2] = w83792d_read_value(client, |
1591 | W83792D_REG_TOLERANCE[2]) & 0x0f; |
1592 | |
1593 | /* Update Smart Fan II temperature points */ |
1594 | for (i = 0; i < 3; i++) { |
1595 | for (j = 0; j < 4; j++) { |
1596 | data->sf2_points[i][j] |
1597 | = w83792d_read_value(client, |
1598 | W83792D_REG_POINTS[i][j]) & 0x7f; |
1599 | } |
1600 | } |
1601 | |
1602 | /* Update Smart Fan II duty cycle levels */ |
1603 | for (i = 0; i < 3; i++) { |
1604 | reg_tmp = w83792d_read_value(client, |
1605 | W83792D_REG_LEVELS[i][0]); |
1606 | data->sf2_levels[i][0] = reg_tmp & 0x0f; |
1607 | data->sf2_levels[i][1] = (reg_tmp >> 4) & 0x0f; |
1608 | reg_tmp = w83792d_read_value(client, |
1609 | W83792D_REG_LEVELS[i][2]); |
1610 | data->sf2_levels[i][2] = (reg_tmp >> 4) & 0x0f; |
1611 | data->sf2_levels[i][3] = reg_tmp & 0x0f; |
1612 | } |
1613 | |
1614 | data->last_updated = jiffies; |
1615 | data->valid = 1; |
1616 | } |
1617 | |
1618 | mutex_unlock(&data->update_lock); |
1619 | |
1620 | #ifdef DEBUG |
1621 | w83792d_print_debug(data, dev); |
1622 | #endif |
1623 | |
1624 | return data; |
1625 | } |
1626 | |
1627 | #ifdef DEBUG |
1628 | static void w83792d_print_debug(struct w83792d_data *data, struct device *dev) |
1629 | { |
1630 | int i = 0, j = 0; |
1631 | dev_dbg(dev, "==========The following is the debug message...========\n"); |
1632 | dev_dbg(dev, "9 set of Voltages: =====>\n"); |
1633 | for (i = 0; i < 9; i++) { |
1634 | dev_dbg(dev, "vin[%d] is: 0x%x\n", i, data->in[i]); |
1635 | dev_dbg(dev, "vin[%d] max is: 0x%x\n", i, data->in_max[i]); |
1636 | dev_dbg(dev, "vin[%d] min is: 0x%x\n", i, data->in_min[i]); |
1637 | } |
1638 | dev_dbg(dev, "Low Bit1 is: 0x%x\n", data->low_bits & 0xff); |
1639 | dev_dbg(dev, "Low Bit2 is: 0x%x\n", data->low_bits >> 8); |
1640 | dev_dbg(dev, "7 set of Fan Counts and Duty Cycles: =====>\n"); |
1641 | for (i = 0; i < 7; i++) { |
1642 | dev_dbg(dev, "fan[%d] is: 0x%x\n", i, data->fan[i]); |
1643 | dev_dbg(dev, "fan[%d] min is: 0x%x\n", i, data->fan_min[i]); |
1644 | dev_dbg(dev, "pwm[%d] is: 0x%x\n", i, data->pwm[i]); |
1645 | } |
1646 | dev_dbg(dev, "3 set of Temperatures: =====>\n"); |
1647 | for (i = 0; i < 3; i++) |
1648 | dev_dbg(dev, "temp1[%d] is: 0x%x\n", i, data->temp1[i]); |
1649 | |
1650 | for (i = 0; i < 2; i++) { |
1651 | for (j = 0; j < 6; j++) { |
1652 | dev_dbg(dev, "temp_add[%d][%d] is: 0x%x\n", i, j, |
1653 | data->temp_add[i][j]); |
1654 | } |
1655 | } |
1656 | |
1657 | for (i = 0; i < 7; i++) |
1658 | dev_dbg(dev, "fan_div[%d] is: 0x%x\n", i, data->fan_div[i]); |
1659 | |
1660 | dev_dbg(dev, "==========End of the debug message...================\n"); |
1661 | dev_dbg(dev, "\n"); |
1662 | } |
1663 | #endif |
1664 | |
1665 | module_i2c_driver(w83792d_driver); |
1666 | |
1667 | MODULE_AUTHOR("Chunhao Huang @ Winbond <DZShen@Winbond.com.tw>"); |
1668 | MODULE_DESCRIPTION("W83792AD/D driver for linux-2.6"); |
1669 | MODULE_LICENSE("GPL"); |
1670 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9