1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include <linux/module.h>
27#include <linux/init.h>
28#include <linux/slab.h>
29#include <linux/jiffies.h>
30#include <linux/mutex.h>
31#include <linux/err.h>
32#include <linux/delay.h>
33#include <linux/platform_device.h>
34#include <linux/hwmon.h>
35#include <linux/hwmon-sysfs.h>
36#include <linux/dmi.h>
37#include <asm/io.h>
38
39
40#define ABIT_UGURU3_SETTINGS_BANK 0x01
41#define ABIT_UGURU3_SENSORS_BANK 0x08
42#define ABIT_UGURU3_MISC_BANK 0x09
43#define ABIT_UGURU3_ALARMS_START 0x1E
44#define ABIT_UGURU3_SETTINGS_START 0x24
45#define ABIT_UGURU3_VALUES_START 0x80
46#define ABIT_UGURU3_BOARD_ID 0x0A
47
48#define ABIT_UGURU3_TEMP_HIGH_ALARM_ENABLE 0x01
49#define ABIT_UGURU3_VOLT_HIGH_ALARM_ENABLE 0x02
50#define ABIT_UGURU3_VOLT_LOW_ALARM_ENABLE 0x04
51#define ABIT_UGURU3_TEMP_HIGH_ALARM_FLAG 0x10
52#define ABIT_UGURU3_VOLT_HIGH_ALARM_FLAG 0x20
53#define ABIT_UGURU3_VOLT_LOW_ALARM_FLAG 0x40
54#define ABIT_UGURU3_FAN_LOW_ALARM_ENABLE 0x01
55#define ABIT_UGURU3_BEEP_ENABLE 0x08
56#define ABIT_UGURU3_SHUTDOWN_ENABLE 0x80
57
58#define ABIT_UGURU3_IN_SENSOR 0
59#define ABIT_UGURU3_TEMP_SENSOR 1
60#define ABIT_UGURU3_FAN_SENSOR 2
61
62
63
64
65
66#define ABIT_UGURU3_WAIT_TIMEOUT 250
67
68
69#define ABIT_UGURU3_SYNCHRONIZE_TIMEOUT 5
70
71#define ABIT_UGURU3_NAME "abituguru3"
72#define ABIT_UGURU3_DEBUG(format, arg...) \
73 if (verbose) \
74 printk(KERN_DEBUG ABIT_UGURU3_NAME ": " format , ## arg)
75
76
77#define ABIT_UGURU3_MAX_NO_SENSORS 26
78
79
80#define ABIT_UGURU3_IN_NAMES_LENGTH (11 + 2 * 9 + 2 * 15 + 2 * 22 + 10 + 14 + 11)
81
82
83
84#define ABIT_UGURU3_TEMP_NAMES_LENGTH (13 + 11 + 12 + 13 + 20 + 12 + 16 + 13)
85
86
87#define ABIT_UGURU3_FAN_NAMES_LENGTH (12 + 10 + 12 + 19 + 11 + 15 + 12)
88
89
90#define ABIT_UGURU3_SYSFS_NAMES_LENGTH (16 * ABIT_UGURU3_IN_NAMES_LENGTH + \
91 (ABIT_UGURU3_MAX_NO_SENSORS - 16) * ABIT_UGURU3_TEMP_NAMES_LENGTH)
92
93
94
95
96
97
98#define ABIT_UGURU3_BASE 0x00E0
99#define ABIT_UGURU3_CMD 0x00
100#define ABIT_UGURU3_DATA 0x04
101#define ABIT_UGURU3_REGION_LENGTH 5
102
103
104#define ABIT_UGURU3_SUCCESS -1
105
106#define ABIT_UGURU3_STATUS_READY_FOR_READ 0x01
107#define ABIT_UGURU3_STATUS_BUSY 0x02
108
109
110
111struct abituguru3_sensor_info {
112 const char* name;
113 int port;
114 int type;
115 int multiplier;
116 int divisor;
117 int offset;
118};
119
120struct abituguru3_motherboard_info {
121 u16 id;
122 const char *dmi_name;
123
124 struct abituguru3_sensor_info sensors[ABIT_UGURU3_MAX_NO_SENSORS + 1];
125};
126
127
128
129
130struct abituguru3_data {
131 struct device *hwmon_dev;
132 struct mutex update_lock;
133 unsigned short addr;
134 char valid;
135 unsigned long last_updated;
136
137
138
139 struct sensor_device_attribute_2 sysfs_attr[ABIT_UGURU3_MAX_NO_SENSORS
140 * 10];
141
142
143 char sysfs_names[ABIT_UGURU3_SYSFS_NAMES_LENGTH];
144
145
146 const struct abituguru3_sensor_info *sensors;
147
148
149
150
151
152
153 u8 alarms[48/8];
154
155
156 u8 value[48];
157
158
159
160
161 u8 settings[48][3];
162};
163
164
165
166static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
167 { 0x000C, NULL , {
168 { "CPU Core", 0, 0, 10, 1, 0 },
169 { "DDR", 1, 0, 10, 1, 0 },
170 { "DDR VTT", 2, 0, 10, 1, 0 },
171 { "CPU VTT 1.2V", 3, 0, 10, 1, 0 },
172 { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 },
173 { "MCH 2.5V", 5, 0, 20, 1, 0 },
174 { "ICH 1.05V", 6, 0, 10, 1, 0 },
175 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
176 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
177 { "ATX +5V", 9, 0, 30, 1, 0 },
178 { "+3.3V", 10, 0, 20, 1, 0 },
179 { "5VSB", 11, 0, 30, 1, 0 },
180 { "CPU", 24, 1, 1, 1, 0 },
181 { "System", 25, 1, 1, 1, 0 },
182 { "PWM", 26, 1, 1, 1, 0 },
183 { "CPU Fan", 32, 2, 60, 1, 0 },
184 { "NB Fan", 33, 2, 60, 1, 0 },
185 { "SYS FAN", 34, 2, 60, 1, 0 },
186 { "AUX1 Fan", 35, 2, 60, 1, 0 },
187 { NULL, 0, 0, 0, 0, 0 } }
188 },
189 { 0x000D, NULL , {
190 { "CPU Core", 0, 0, 10, 1, 0 },
191 { "DDR", 1, 0, 10, 1, 0 },
192 { "DDR VTT", 2, 0, 10, 1, 0 },
193 { "CPU VTT 1.2V", 3, 0, 10, 1, 0 },
194 { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 },
195 { "MCH 2.5V", 5, 0, 20, 1, 0 },
196 { "ICH 1.05V", 6, 0, 10, 1, 0 },
197 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
198 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
199 { "ATX +5V", 9, 0, 30, 1, 0 },
200 { "+3.3V", 10, 0, 20, 1, 0 },
201 { "5VSB", 11, 0, 30, 1, 0 },
202 { "CPU", 24, 1, 1, 1, 0 },
203 { "System", 25, 1, 1, 1, 0 },
204 { "PWM1", 26, 1, 1, 1, 0 },
205 { "PWM2", 27, 1, 1, 1, 0 },
206 { "PWM3", 28, 1, 1, 1, 0 },
207 { "PWM4", 29, 1, 1, 1, 0 },
208 { "CPU Fan", 32, 2, 60, 1, 0 },
209 { "NB Fan", 33, 2, 60, 1, 0 },
210 { "SYS Fan", 34, 2, 60, 1, 0 },
211 { "AUX1 Fan", 35, 2, 60, 1, 0 },
212 { "AUX2 Fan", 36, 2, 60, 1, 0 },
213 { "AUX3 Fan", 37, 2, 60, 1, 0 },
214 { "AUX4 Fan", 38, 2, 60, 1, 0 },
215 { "AUX5 Fan", 39, 2, 60, 1, 0 },
216 { NULL, 0, 0, 0, 0, 0 } }
217 },
218 { 0x000E, NULL , {
219 { "CPU Core", 0, 0, 10, 1, 0 },
220 { "DDR", 1, 0, 10, 1, 0 },
221 { "DDR VTT", 2, 0, 10, 1, 0 },
222 { "CPU VTT 1.2V", 3, 0, 10, 1, 0 },
223 { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 },
224 { "MCH 2.5V", 5, 0, 20, 1, 0 },
225 { "ICH 1.05V", 6, 0, 10, 1, 0 },
226 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
227 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
228 { "ATX +5V", 9, 0, 30, 1, 0 },
229 { "+3.3V", 10, 0, 20, 1, 0 },
230 { "5VSB", 11, 0, 30, 1, 0 },
231 { "CPU", 24, 1, 1, 1, 0 },
232 { "System", 25, 1, 1, 1, 0 },
233 { "PWM", 26, 1, 1, 1, 0 },
234 { "CPU Fan", 32, 2, 60, 1, 0 },
235 { "NB Fan", 33, 2, 60, 1, 0 },
236 { "SYS Fan", 34, 2, 60, 1, 0 },
237 { NULL, 0, 0, 0, 0, 0 } }
238 },
239 { 0x000F, NULL , {
240 { "CPU Core", 0, 0, 10, 1, 0 },
241 { "DDR", 1, 0, 10, 1, 0 },
242 { "DDR VTT", 2, 0, 10, 1, 0 },
243 { "CPU VTT 1.2V", 3, 0, 10, 1, 0 },
244 { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 },
245 { "MCH 2.5V", 5, 0, 20, 1, 0 },
246 { "ICH 1.05V", 6, 0, 10, 1, 0 },
247 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
248 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
249 { "ATX +5V", 9, 0, 30, 1, 0 },
250 { "+3.3V", 10, 0, 20, 1, 0 },
251 { "5VSB", 11, 0, 30, 1, 0 },
252 { "CPU", 24, 1, 1, 1, 0 },
253 { "System", 25, 1, 1, 1, 0 },
254 { "PWM", 26, 1, 1, 1, 0 },
255 { "CPU Fan", 32, 2, 60, 1, 0 },
256 { "NB Fan", 33, 2, 60, 1, 0 },
257 { "SYS Fan", 34, 2, 60, 1, 0 },
258 { NULL, 0, 0, 0, 0, 0 } }
259 },
260 { 0x0010, NULL , {
261 { "CPU Core", 0, 0, 10, 1, 0 },
262 { "DDR", 1, 0, 10, 1, 0 },
263 { "DDR VTT", 2, 0, 10, 1, 0 },
264 { "CPU VTT 1.2V", 3, 0, 10, 1, 0 },
265 { "NB 1.4V", 4, 0, 10, 1, 0 },
266 { "SB 1.5V", 6, 0, 10, 1, 0 },
267 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
268 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
269 { "ATX +5V", 9, 0, 30, 1, 0 },
270 { "+3.3V", 10, 0, 20, 1, 0 },
271 { "5VSB", 11, 0, 30, 1, 0 },
272 { "CPU", 24, 1, 1, 1, 0 },
273 { "SYS", 25, 1, 1, 1, 0 },
274 { "PWM", 26, 1, 1, 1, 0 },
275 { "CPU Fan", 32, 2, 60, 1, 0 },
276 { "NB Fan", 33, 2, 60, 1, 0 },
277 { "SYS Fan", 34, 2, 60, 1, 0 },
278 { "AUX1 Fan", 35, 2, 60, 1, 0 },
279 { "OTES1 Fan", 36, 2, 60, 1, 0 },
280 { NULL, 0, 0, 0, 0, 0 } }
281 },
282 { 0x0011, "AT8 32X(ATI RD580-ULI M1575)", {
283 { "CPU Core", 0, 0, 10, 1, 0 },
284 { "DDR", 1, 0, 20, 1, 0 },
285 { "DDR VTT", 2, 0, 10, 1, 0 },
286 { "CPU VDDA 2.5V", 6, 0, 20, 1, 0 },
287 { "NB 1.8V", 4, 0, 10, 1, 0 },
288 { "NB 1.8V Dual", 5, 0, 10, 1, 0 },
289 { "HTV 1.2", 3, 0, 10, 1, 0 },
290 { "PCIE 1.2V", 12, 0, 10, 1, 0 },
291 { "NB 1.2V", 13, 0, 10, 1, 0 },
292 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
293 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
294 { "ATX +5V", 9, 0, 30, 1, 0 },
295 { "+3.3V", 10, 0, 20, 1, 0 },
296 { "5VSB", 11, 0, 30, 1, 0 },
297 { "CPU", 24, 1, 1, 1, 0 },
298 { "NB", 25, 1, 1, 1, 0 },
299 { "System", 26, 1, 1, 1, 0 },
300 { "PWM", 27, 1, 1, 1, 0 },
301 { "CPU Fan", 32, 2, 60, 1, 0 },
302 { "NB Fan", 33, 2, 60, 1, 0 },
303 { "SYS Fan", 34, 2, 60, 1, 0 },
304 { "AUX1 Fan", 35, 2, 60, 1, 0 },
305 { "AUX2 Fan", 36, 2, 60, 1, 0 },
306 { "AUX3 Fan", 37, 2, 60, 1, 0 },
307 { NULL, 0, 0, 0, 0, 0 } }
308 },
309 { 0x0012, NULL , {
310 { "CPU Core", 0, 0, 10, 1, 0 },
311 { "DDR", 1, 0, 20, 1, 0 },
312 { "DDR VTT", 2, 0, 10, 1, 0 },
313 { "HyperTransport", 3, 0, 10, 1, 0 },
314 { "CPU VDDA 2.5V", 5, 0, 20, 1, 0 },
315 { "NB", 4, 0, 10, 1, 0 },
316 { "SB", 6, 0, 10, 1, 0 },
317 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
318 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
319 { "ATX +5V", 9, 0, 30, 1, 0 },
320 { "+3.3V", 10, 0, 20, 1, 0 },
321 { "5VSB", 11, 0, 30, 1, 0 },
322 { "CPU", 24, 1, 1, 1, 0 },
323 { "SYS", 25, 1, 1, 1, 0 },
324 { "PWM", 26, 1, 1, 1, 0 },
325 { "CPU Fan", 32, 2, 60, 1, 0 },
326 { "NB Fan", 33, 2, 60, 1, 0 },
327 { "SYS Fan", 34, 2, 60, 1, 0 },
328 { "AUX1 Fan", 36, 2, 60, 1, 0 },
329 { NULL, 0, 0, 0, 0, 0 } }
330 },
331 { 0x0013, NULL , {
332 { "CPU Core", 0, 0, 10, 1, 0 },
333 { "DDR", 1, 0, 10, 1, 0 },
334 { "DDR VTT", 2, 0, 10, 1, 0 },
335 { "CPU VTT 1.2V", 3, 0, 10, 1, 0 },
336 { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 },
337 { "MCH 2.5V", 5, 0, 20, 1, 0 },
338 { "ICH 1.05V", 6, 0, 10, 1, 0 },
339 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
340 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
341 { "ATX +5V", 9, 0, 30, 1, 0 },
342 { "+3.3V", 10, 0, 20, 1, 0 },
343 { "5VSB", 11, 0, 30, 1, 0 },
344 { "CPU", 24, 1, 1, 1, 0 },
345 { "System", 25, 1, 1, 1, 0 },
346 { "PWM1", 26, 1, 1, 1, 0 },
347 { "PWM2", 27, 1, 1, 1, 0 },
348 { "PWM3", 28, 1, 1, 1, 0 },
349 { "PWM4", 29, 1, 1, 1, 0 },
350 { "CPU Fan", 32, 2, 60, 1, 0 },
351 { "NB Fan", 33, 2, 60, 1, 0 },
352 { "SYS Fan", 34, 2, 60, 1, 0 },
353 { "AUX1 Fan", 35, 2, 60, 1, 0 },
354 { "AUX2 Fan", 36, 2, 60, 1, 0 },
355 { "AUX3 Fan", 37, 2, 60, 1, 0 },
356 { "AUX4 Fan", 38, 2, 60, 1, 0 },
357 { "AUX5 Fan", 39, 2, 60, 1, 0 },
358 { NULL, 0, 0, 0, 0, 0 } }
359 },
360 { 0x0014, NULL , {
361 { "CPU Core", 0, 0, 10, 1, 0 },
362 { "DDR", 1, 0, 10, 1, 0 },
363 { "DDR VTT", 2, 0, 10, 1, 0 },
364 { "CPU VTT 1.2V", 3, 0, 10, 1, 0 },
365 { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 },
366 { "MCH 2.5V", 5, 0, 20, 1, 0 },
367 { "ICH 1.05V", 6, 0, 10, 1, 0 },
368 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
369 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
370 { "ATX +5V", 9, 0, 30, 1, 0 },
371 { "+3.3V", 10, 0, 20, 1, 0 },
372 { "5VSB", 11, 0, 30, 1, 0 },
373 { "CPU", 24, 1, 1, 1, 0 },
374 { "System", 25, 1, 1, 1, 0 },
375 { "PWM", 26, 1, 1, 1, 0 },
376 { "CPU Fan", 32, 2, 60, 1, 0 },
377 { "NB Fan", 33, 2, 60, 1, 0 },
378 { "SYS Fan", 34, 2, 60, 1, 0 },
379 { NULL, 0, 0, 0, 0, 0 } }
380 },
381 { 0x0015, NULL , {
382 { "CPU Core", 0, 0, 10, 1, 0 },
383 { "DDR", 1, 0, 20, 1, 0 },
384 { "DDR VTT", 2, 0, 10, 1, 0 },
385 { "HyperTransport", 3, 0, 10, 1, 0 },
386 { "CPU VDDA 2.5V", 5, 0, 20, 1, 0 },
387 { "NB", 4, 0, 10, 1, 0 },
388 { "SB", 6, 0, 10, 1, 0 },
389 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
390 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
391 { "ATX +5V", 9, 0, 30, 1, 0 },
392 { "+3.3V", 10, 0, 20, 1, 0 },
393 { "5VSB", 11, 0, 30, 1, 0 },
394 { "CPU", 24, 1, 1, 1, 0 },
395 { "SYS", 25, 1, 1, 1, 0 },
396 { "PWM", 26, 1, 1, 1, 0 },
397 { "CPU Fan", 32, 2, 60, 1, 0 },
398 { "NB Fan", 33, 2, 60, 1, 0 },
399 { "SYS Fan", 34, 2, 60, 1, 0 },
400 { "AUX1 Fan", 33, 2, 60, 1, 0 },
401 { "AUX2 Fan", 35, 2, 60, 1, 0 },
402 { "AUX3 Fan", 36, 2, 60, 1, 0 },
403 { NULL, 0, 0, 0, 0, 0 } }
404 },
405 { 0x0016, "AW9D-MAX (Intel i975-ICH7)", {
406 { "CPU Core", 0, 0, 10, 1, 0 },
407 { "DDR2", 1, 0, 20, 1, 0 },
408 { "DDR2 VTT", 2, 0, 10, 1, 0 },
409 { "CPU VTT 1.2V", 3, 0, 10, 1, 0 },
410 { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 },
411 { "MCH 2.5V", 5, 0, 20, 1, 0 },
412 { "ICH 1.05V", 6, 0, 10, 1, 0 },
413 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
414 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
415 { "ATX +5V", 9, 0, 30, 1, 0 },
416 { "+3.3V", 10, 0, 20, 1, 0 },
417 { "5VSB", 11, 0, 30, 1, 0 },
418 { "CPU", 24, 1, 1, 1, 0 },
419 { "System", 25, 1, 1, 1, 0 },
420 { "PWM1", 26, 1, 1, 1, 0 },
421 { "PWM2", 27, 1, 1, 1, 0 },
422 { "PWM3", 28, 1, 1, 1, 0 },
423 { "PWM4", 29, 1, 1, 1, 0 },
424 { "CPU Fan", 32, 2, 60, 1, 0 },
425 { "NB Fan", 33, 2, 60, 1, 0 },
426 { "SYS Fan", 34, 2, 60, 1, 0 },
427 { "AUX1 Fan", 35, 2, 60, 1, 0 },
428 { "AUX2 Fan", 36, 2, 60, 1, 0 },
429 { "AUX3 Fan", 37, 2, 60, 1, 0 },
430 { "OTES1 Fan", 38, 2, 60, 1, 0 },
431 { NULL, 0, 0, 0, 0, 0 } }
432 },
433 { 0x0017, NULL , {
434 { "CPU Core", 0, 0, 10, 1, 0 },
435 { "DDR2", 1, 0, 20, 1, 0 },
436 { "DDR2 VTT", 2, 0, 10, 1, 0 },
437 { "HyperTransport", 3, 0, 10, 1, 0 },
438 { "CPU VDDA 2.5V", 6, 0, 20, 1, 0 },
439 { "NB 1.8V", 4, 0, 10, 1, 0 },
440 { "NB 1.2V ", 13, 0, 10, 1, 0 },
441 { "SB 1.2V", 5, 0, 10, 1, 0 },
442 { "PCIE 1.2V", 12, 0, 10, 1, 0 },
443 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
444 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
445 { "ATX +5V", 9, 0, 30, 1, 0 },
446 { "ATX +3.3V", 10, 0, 20, 1, 0 },
447 { "ATX 5VSB", 11, 0, 30, 1, 0 },
448 { "CPU", 24, 1, 1, 1, 0 },
449 { "System", 26, 1, 1, 1, 0 },
450 { "PWM", 27, 1, 1, 1, 0 },
451 { "CPU FAN", 32, 2, 60, 1, 0 },
452 { "SYS FAN", 34, 2, 60, 1, 0 },
453 { "AUX1 FAN", 35, 2, 60, 1, 0 },
454 { "AUX2 FAN", 36, 2, 60, 1, 0 },
455 { "AUX3 FAN", 37, 2, 60, 1, 0 },
456 { NULL, 0, 0, 0, 0, 0 } }
457 },
458 { 0x0018, NULL , {
459 { "CPU Core", 0, 0, 10, 1, 0 },
460 { "DDR2", 1, 0, 20, 1, 0 },
461 { "DDR2 VTT", 2, 0, 10, 1, 0 },
462 { "CPU VTT", 3, 0, 10, 1, 0 },
463 { "MCH 1.25V", 4, 0, 10, 1, 0 },
464 { "ICHIO 1.5V", 5, 0, 10, 1, 0 },
465 { "ICH 1.05V", 6, 0, 10, 1, 0 },
466 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
467 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
468 { "ATX +5V", 9, 0, 30, 1, 0 },
469 { "+3.3V", 10, 0, 20, 1, 0 },
470 { "5VSB", 11, 0, 30, 1, 0 },
471 { "CPU", 24, 1, 1, 1, 0 },
472 { "System", 25, 1, 1, 1, 0 },
473 { "PWM Phase1", 26, 1, 1, 1, 0 },
474 { "PWM Phase2", 27, 1, 1, 1, 0 },
475 { "PWM Phase3", 28, 1, 1, 1, 0 },
476 { "PWM Phase4", 29, 1, 1, 1, 0 },
477 { "PWM Phase5", 30, 1, 1, 1, 0 },
478 { "CPU Fan", 32, 2, 60, 1, 0 },
479 { "SYS Fan", 34, 2, 60, 1, 0 },
480 { "AUX1 Fan", 33, 2, 60, 1, 0 },
481 { "AUX2 Fan", 35, 2, 60, 1, 0 },
482 { "AUX3 Fan", 36, 2, 60, 1, 0 },
483 { NULL, 0, 0, 0, 0, 0 } }
484 },
485 { 0x0019, NULL , {
486 { "CPU Core", 7, 0, 10, 1, 0 },
487 { "DDR2", 13, 0, 20, 1, 0 },
488 { "DDR2 VTT", 14, 0, 10, 1, 0 },
489 { "CPU VTT", 3, 0, 20, 1, 0 },
490 { "NB 1.2V", 4, 0, 10, 1, 0 },
491 { "SB 1.5V", 6, 0, 10, 1, 0 },
492 { "HyperTransport", 5, 0, 10, 1, 0 },
493 { "ATX +12V (24-Pin)", 12, 0, 60, 1, 0 },
494 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
495 { "ATX +5V", 9, 0, 30, 1, 0 },
496 { "ATX +3.3V", 10, 0, 20, 1, 0 },
497 { "ATX 5VSB", 11, 0, 30, 1, 0 },
498 { "CPU", 24, 1, 1, 1, 0 },
499 { "System", 25, 1, 1, 1, 0 },
500 { "PWM Phase1", 26, 1, 1, 1, 0 },
501 { "PWM Phase2", 27, 1, 1, 1, 0 },
502 { "PWM Phase3", 28, 1, 1, 1, 0 },
503 { "PWM Phase4", 29, 1, 1, 1, 0 },
504 { "PWM Phase5", 30, 1, 1, 1, 0 },
505 { "CPU FAN", 32, 2, 60, 1, 0 },
506 { "SYS FAN", 34, 2, 60, 1, 0 },
507 { "AUX1 FAN", 33, 2, 60, 1, 0 },
508 { "AUX2 FAN", 35, 2, 60, 1, 0 },
509 { "AUX3 FAN", 36, 2, 60, 1, 0 },
510 { NULL, 0, 0, 0, 0, 0 } }
511 },
512 { 0x001A, "IP35 Pro(Intel P35-ICH9R)", {
513 { "CPU Core", 0, 0, 10, 1, 0 },
514 { "DDR2", 1, 0, 20, 1, 0 },
515 { "DDR2 VTT", 2, 0, 10, 1, 0 },
516 { "CPU VTT 1.2V", 3, 0, 10, 1, 0 },
517 { "MCH 1.25V", 4, 0, 10, 1, 0 },
518 { "ICHIO 1.5V", 5, 0, 10, 1, 0 },
519 { "ICH 1.05V", 6, 0, 10, 1, 0 },
520 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
521 { "ATX +12V (8-pin)", 8, 0, 60, 1, 0 },
522 { "ATX +5V", 9, 0, 30, 1, 0 },
523 { "+3.3V", 10, 0, 20, 1, 0 },
524 { "5VSB", 11, 0, 30, 1, 0 },
525 { "CPU", 24, 1, 1, 1, 0 },
526 { "System", 25, 1, 1, 1, 0 },
527 { "PWM", 26, 1, 1, 1, 0 },
528 { "PWM Phase2", 27, 1, 1, 1, 0 },
529 { "PWM Phase3", 28, 1, 1, 1, 0 },
530 { "PWM Phase4", 29, 1, 1, 1, 0 },
531 { "PWM Phase5", 30, 1, 1, 1, 0 },
532 { "CPU Fan", 32, 2, 60, 1, 0 },
533 { "SYS Fan", 34, 2, 60, 1, 0 },
534 { "AUX1 Fan", 33, 2, 60, 1, 0 },
535 { "AUX2 Fan", 35, 2, 60, 1, 0 },
536 { "AUX3 Fan", 36, 2, 60, 1, 0 },
537 { "AUX4 Fan", 37, 2, 60, 1, 0 },
538 { NULL, 0, 0, 0, 0, 0 } }
539 },
540 { 0x001B, NULL , {
541 { "CPU Core", 0, 0, 10, 1, 0 },
542 { "DDR3", 1, 0, 20, 1, 0 },
543 { "DDR3 VTT", 2, 0, 10, 1, 0 },
544 { "CPU VTT", 3, 0, 10, 1, 0 },
545 { "MCH 1.25V", 4, 0, 10, 1, 0 },
546 { "ICHIO 1.5V", 5, 0, 10, 1, 0 },
547 { "ICH 1.05V", 6, 0, 10, 1, 0 },
548 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
549 { "ATX +12V (8-pin)", 8, 0, 60, 1, 0 },
550 { "ATX +5V", 9, 0, 30, 1, 0 },
551 { "+3.3V", 10, 0, 20, 1, 0 },
552 { "5VSB", 11, 0, 30, 1, 0 },
553 { "CPU", 24, 1, 1, 1, 0 },
554 { "System", 25, 1, 1, 1, 0 },
555 { "PWM Phase1", 26, 1, 1, 1, 0 },
556 { "PWM Phase2", 27, 1, 1, 1, 0 },
557 { "PWM Phase3", 28, 1, 1, 1, 0 },
558 { "PWM Phase4", 29, 1, 1, 1, 0 },
559 { "PWM Phase5", 30, 1, 1, 1, 0 },
560 { "CPU Fan", 32, 2, 60, 1, 0 },
561 { "SYS Fan", 34, 2, 60, 1, 0 },
562 { "AUX1 Fan", 33, 2, 60, 1, 0 },
563 { "AUX2 Fan", 35, 2, 60, 1, 0 },
564 { "AUX3 Fan", 36, 2, 60, 1, 0 },
565 { NULL, 0, 0, 0, 0, 0 } }
566 },
567 { 0x001C, NULL , {
568 { "CPU Core", 0, 0, 10, 1, 0 },
569 { "DDR2", 1, 0, 20, 1, 0 },
570 { "DDR2 VTT", 2, 0, 10, 1, 0 },
571 { "CPU VTT", 3, 0, 10, 1, 0 },
572 { "MCH 1.25V", 4, 0, 10, 1, 0 },
573 { "ICHIO 1.5V", 5, 0, 10, 1, 0 },
574 { "ICH 1.05V", 6, 0, 10, 1, 0 },
575 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
576 { "ATX +12V (8-pin)", 8, 0, 60, 1, 0 },
577 { "ATX +5V", 9, 0, 30, 1, 0 },
578 { "+3.3V", 10, 0, 20, 1, 0 },
579 { "5VSB", 11, 0, 30, 1, 0 },
580 { "CPU", 24, 1, 1, 1, 0 },
581 { "System", 25, 1, 1, 1, 0 },
582 { "PWM Phase1", 26, 1, 1, 1, 0 },
583 { "PWM Phase2", 27, 1, 1, 1, 0 },
584 { "PWM Phase3", 28, 1, 1, 1, 0 },
585 { "PWM Phase4", 29, 1, 1, 1, 0 },
586 { "PWM Phase5", 30, 1, 1, 1, 0 },
587 { "CPU Fan", 32, 2, 60, 1, 0 },
588 { "SYS Fan", 34, 2, 60, 1, 0 },
589 { "AUX1 Fan", 33, 2, 60, 1, 0 },
590 { "AUX2 Fan", 35, 2, 60, 1, 0 },
591 { "AUX3 Fan", 36, 2, 60, 1, 0 },
592 { NULL, 0, 0, 0, 0, 0 } }
593 },
594 { 0x0000, NULL, { { NULL, 0, 0, 0, 0, 0 } } }
595};
596
597
598
599static int force;
600module_param(force, bool, 0);
601MODULE_PARM_DESC(force, "Set to one to force detection.");
602
603static int verbose = 1;
604module_param(verbose, bool, 0644);
605MODULE_PARM_DESC(verbose, "Enable/disable verbose error reporting");
606
607
608
609static int abituguru3_wait_while_busy(struct abituguru3_data *data)
610{
611 u8 x;
612 int timeout = ABIT_UGURU3_WAIT_TIMEOUT;
613
614 while ((x = inb_p(data->addr + ABIT_UGURU3_DATA)) &
615 ABIT_UGURU3_STATUS_BUSY) {
616 timeout--;
617 if (timeout == 0)
618 return x;
619
620
621 if (timeout == 1)
622 msleep(1);
623 }
624 return ABIT_UGURU3_SUCCESS;
625}
626
627
628static int abituguru3_wait_for_read(struct abituguru3_data *data)
629{
630 u8 x;
631 int timeout = ABIT_UGURU3_WAIT_TIMEOUT;
632
633 while (!((x = inb_p(data->addr + ABIT_UGURU3_DATA)) &
634 ABIT_UGURU3_STATUS_READY_FOR_READ)) {
635 timeout--;
636 if (timeout == 0)
637 return x;
638
639
640 if (timeout == 1)
641 msleep(1);
642 }
643 return ABIT_UGURU3_SUCCESS;
644}
645
646
647
648static int abituguru3_synchronize(struct abituguru3_data *data)
649{
650 int x, timeout = ABIT_UGURU3_SYNCHRONIZE_TIMEOUT;
651
652 if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
653 ABIT_UGURU3_DEBUG("synchronize timeout during initial busy "
654 "wait, status: 0x%02x\n", x);
655 return -EIO;
656 }
657
658 outb(0x20, data->addr + ABIT_UGURU3_DATA);
659 if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
660 ABIT_UGURU3_DEBUG("synchronize timeout after sending 0x20, "
661 "status: 0x%02x\n", x);
662 return -EIO;
663 }
664
665 outb(0x10, data->addr + ABIT_UGURU3_CMD);
666 if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
667 ABIT_UGURU3_DEBUG("synchronize timeout after sending 0x10, "
668 "status: 0x%02x\n", x);
669 return -EIO;
670 }
671
672 outb(0x00, data->addr + ABIT_UGURU3_CMD);
673 if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
674 ABIT_UGURU3_DEBUG("synchronize timeout after sending 0x00, "
675 "status: 0x%02x\n", x);
676 return -EIO;
677 }
678
679 if ((x = abituguru3_wait_for_read(data)) != ABIT_UGURU3_SUCCESS) {
680 ABIT_UGURU3_DEBUG("synchronize timeout waiting for read, "
681 "status: 0x%02x\n", x);
682 return -EIO;
683 }
684
685 while ((x = inb(data->addr + ABIT_UGURU3_CMD)) != 0xAC) {
686 timeout--;
687 if (timeout == 0) {
688 ABIT_UGURU3_DEBUG("synchronize timeout cmd does not "
689 "hold 0xAC after synchronize, cmd: 0x%02x\n",
690 x);
691 return -EIO;
692 }
693 msleep(1);
694 }
695 return 0;
696}
697
698
699
700static int abituguru3_read(struct abituguru3_data *data, u8 bank, u8 offset,
701 u8 count, u8 *buf)
702{
703 int i, x;
704
705 if ((x = abituguru3_synchronize(data)))
706 return x;
707
708 outb(0x1A, data->addr + ABIT_UGURU3_DATA);
709 if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
710 ABIT_UGURU3_DEBUG("read from 0x%02x:0x%02x timed out after "
711 "sending 0x1A, status: 0x%02x\n", (unsigned int)bank,
712 (unsigned int)offset, x);
713 return -EIO;
714 }
715
716 outb(bank, data->addr + ABIT_UGURU3_CMD);
717 if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
718 ABIT_UGURU3_DEBUG("read from 0x%02x:0x%02x timed out after "
719 "sending the bank, status: 0x%02x\n",
720 (unsigned int)bank, (unsigned int)offset, x);
721 return -EIO;
722 }
723
724 outb(offset, data->addr + ABIT_UGURU3_CMD);
725 if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
726 ABIT_UGURU3_DEBUG("read from 0x%02x:0x%02x timed out after "
727 "sending the offset, status: 0x%02x\n",
728 (unsigned int)bank, (unsigned int)offset, x);
729 return -EIO;
730 }
731
732 outb(count, data->addr + ABIT_UGURU3_CMD);
733 if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
734 ABIT_UGURU3_DEBUG("read from 0x%02x:0x%02x timed out after "
735 "sending the count, status: 0x%02x\n",
736 (unsigned int)bank, (unsigned int)offset, x);
737 return -EIO;
738 }
739
740 for (i = 0; i < count; i++) {
741 if ((x = abituguru3_wait_for_read(data)) !=
742 ABIT_UGURU3_SUCCESS) {
743 ABIT_UGURU3_DEBUG("timeout reading byte %d from "
744 "0x%02x:0x%02x, status: 0x%02x\n", i,
745 (unsigned int)bank, (unsigned int)offset, x);
746 break;
747 }
748 buf[i] = inb(data->addr + ABIT_UGURU3_CMD);
749 }
750 return i;
751}
752
753
754
755static int abituguru3_read_increment_offset(struct abituguru3_data *data,
756 u8 bank, u8 offset, u8 count,
757 u8 *buf, int offset_count)
758{
759 int i, x;
760
761 for (i = 0; i < offset_count; i++)
762 if ((x = abituguru3_read(data, bank, offset + i, count,
763 buf + i * count)) != count)
764 return i * count + (i && (x < 0)) ? 0 : x;
765
766 return i * count;
767}
768
769
770
771
772static struct abituguru3_data *abituguru3_update_device(struct device *dev);
773
774static ssize_t show_value(struct device *dev,
775 struct device_attribute *devattr, char *buf)
776{
777 int value;
778 struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
779 struct abituguru3_data *data = abituguru3_update_device(dev);
780 const struct abituguru3_sensor_info *sensor;
781
782 if (!data)
783 return -EIO;
784
785 sensor = &data->sensors[attr->index];
786
787
788 if (attr->nr)
789 value = data->settings[sensor->port][attr->nr];
790 else
791 value = data->value[sensor->port];
792
793
794 value = (value * sensor->multiplier) / sensor->divisor +
795 sensor->offset;
796
797
798
799 if (sensor->type == ABIT_UGURU3_TEMP_SENSOR)
800 value *= 1000;
801
802 return sprintf(buf, "%d\n", value);
803}
804
805static ssize_t show_alarm(struct device *dev,
806 struct device_attribute *devattr, char *buf)
807{
808 int port;
809 struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
810 struct abituguru3_data *data = abituguru3_update_device(dev);
811
812 if (!data)
813 return -EIO;
814
815 port = data->sensors[attr->index].port;
816
817
818
819
820
821 if ((data->alarms[port / 8] & (0x01 << (port % 8))) &&
822 (!attr->nr || (data->settings[port][0] & attr->nr)))
823 return sprintf(buf, "1\n");
824 else
825 return sprintf(buf, "0\n");
826}
827
828static ssize_t show_mask(struct device *dev,
829 struct device_attribute *devattr, char *buf)
830{
831 struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
832 struct abituguru3_data *data = dev_get_drvdata(dev);
833
834 if (data->settings[data->sensors[attr->index].port][0] & attr->nr)
835 return sprintf(buf, "1\n");
836 else
837 return sprintf(buf, "0\n");
838}
839
840static ssize_t show_label(struct device *dev,
841 struct device_attribute *devattr, char *buf)
842{
843 struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
844 struct abituguru3_data *data = dev_get_drvdata(dev);
845
846 return sprintf(buf, "%s\n", data->sensors[attr->index].name);
847}
848
849static ssize_t show_name(struct device *dev,
850 struct device_attribute *devattr, char *buf)
851{
852 return sprintf(buf, "%s\n", ABIT_UGURU3_NAME);
853}
854
855
856static const
857struct sensor_device_attribute_2 abituguru3_sysfs_templ[3][10] = { {
858 SENSOR_ATTR_2(in%d_input, 0444, show_value, NULL, 0, 0),
859 SENSOR_ATTR_2(in%d_min, 0444, show_value, NULL, 1, 0),
860 SENSOR_ATTR_2(in%d_max, 0444, show_value, NULL, 2, 0),
861 SENSOR_ATTR_2(in%d_min_alarm, 0444, show_alarm, NULL,
862 ABIT_UGURU3_VOLT_LOW_ALARM_FLAG, 0),
863 SENSOR_ATTR_2(in%d_max_alarm, 0444, show_alarm, NULL,
864 ABIT_UGURU3_VOLT_HIGH_ALARM_FLAG, 0),
865 SENSOR_ATTR_2(in%d_beep, 0444, show_mask, NULL,
866 ABIT_UGURU3_BEEP_ENABLE, 0),
867 SENSOR_ATTR_2(in%d_shutdown, 0444, show_mask, NULL,
868 ABIT_UGURU3_SHUTDOWN_ENABLE, 0),
869 SENSOR_ATTR_2(in%d_min_alarm_enable, 0444, show_mask, NULL,
870 ABIT_UGURU3_VOLT_LOW_ALARM_ENABLE, 0),
871 SENSOR_ATTR_2(in%d_max_alarm_enable, 0444, show_mask, NULL,
872 ABIT_UGURU3_VOLT_HIGH_ALARM_ENABLE, 0),
873 SENSOR_ATTR_2(in%d_label, 0444, show_label, NULL, 0, 0)
874 }, {
875 SENSOR_ATTR_2(temp%d_input, 0444, show_value, NULL, 0, 0),
876 SENSOR_ATTR_2(temp%d_max, 0444, show_value, NULL, 1, 0),
877 SENSOR_ATTR_2(temp%d_crit, 0444, show_value, NULL, 2, 0),
878 SENSOR_ATTR_2(temp%d_alarm, 0444, show_alarm, NULL, 0, 0),
879 SENSOR_ATTR_2(temp%d_beep, 0444, show_mask, NULL,
880 ABIT_UGURU3_BEEP_ENABLE, 0),
881 SENSOR_ATTR_2(temp%d_shutdown, 0444, show_mask, NULL,
882 ABIT_UGURU3_SHUTDOWN_ENABLE, 0),
883 SENSOR_ATTR_2(temp%d_alarm_enable, 0444, show_mask, NULL,
884 ABIT_UGURU3_TEMP_HIGH_ALARM_ENABLE, 0),
885 SENSOR_ATTR_2(temp%d_label, 0444, show_label, NULL, 0, 0)
886 }, {
887 SENSOR_ATTR_2(fan%d_input, 0444, show_value, NULL, 0, 0),
888 SENSOR_ATTR_2(fan%d_min, 0444, show_value, NULL, 1, 0),
889 SENSOR_ATTR_2(fan%d_alarm, 0444, show_alarm, NULL, 0, 0),
890 SENSOR_ATTR_2(fan%d_beep, 0444, show_mask, NULL,
891 ABIT_UGURU3_BEEP_ENABLE, 0),
892 SENSOR_ATTR_2(fan%d_shutdown, 0444, show_mask, NULL,
893 ABIT_UGURU3_SHUTDOWN_ENABLE, 0),
894 SENSOR_ATTR_2(fan%d_alarm_enable, 0444, show_mask, NULL,
895 ABIT_UGURU3_FAN_LOW_ALARM_ENABLE, 0),
896 SENSOR_ATTR_2(fan%d_label, 0444, show_label, NULL, 0, 0)
897} };
898
899static struct sensor_device_attribute_2 abituguru3_sysfs_attr[] = {
900 SENSOR_ATTR_2(name, 0444, show_name, NULL, 0, 0),
901};
902
903static int __devinit abituguru3_probe(struct platform_device *pdev)
904{
905 const int no_sysfs_attr[3] = { 10, 8, 7 };
906 int sensor_index[3] = { 0, 1, 1 };
907 struct abituguru3_data *data;
908 int i, j, type, used, sysfs_names_free, sysfs_attr_i, res = -ENODEV;
909 char *sysfs_filename;
910 u8 buf[2];
911 u16 id;
912
913 if (!(data = kzalloc(sizeof(struct abituguru3_data), GFP_KERNEL)))
914 return -ENOMEM;
915
916 data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
917 mutex_init(&data->update_lock);
918 platform_set_drvdata(pdev, data);
919
920
921 if ((i = abituguru3_read(data, ABIT_UGURU3_MISC_BANK,
922 ABIT_UGURU3_BOARD_ID, 2, buf)) != 2) {
923 goto abituguru3_probe_error;
924 }
925
926
927 if (!abituguru3_update_device(&pdev->dev))
928 goto abituguru3_probe_error;
929
930
931 id = ((u16)buf[0] << 8) | (u16)buf[1];
932 for (i = 0; abituguru3_motherboards[i].id; i++)
933 if (abituguru3_motherboards[i].id == id)
934 break;
935 if (!abituguru3_motherboards[i].id) {
936 printk(KERN_ERR ABIT_UGURU3_NAME ": error unknown motherboard "
937 "ID: %04X. Please report this to the abituguru3 "
938 "maintainer (see MAINTAINERS)\n", (unsigned int)id);
939 goto abituguru3_probe_error;
940 }
941 data->sensors = abituguru3_motherboards[i].sensors;
942
943 printk(KERN_INFO ABIT_UGURU3_NAME ": found Abit uGuru3, motherboard "
944 "ID: %04X\n", (unsigned int)id);
945
946#ifdef CONFIG_DMI
947 if (!abituguru3_motherboards[i].dmi_name) {
948 printk(KERN_WARNING ABIT_UGURU3_NAME ": this motherboard was "
949 "not detected using DMI. Please send the output of "
950 "\"dmidecode\" to the abituguru3 maintainer "
951 "(see MAINTAINERS)\n");
952 }
953#endif
954
955
956 sysfs_attr_i = 0;
957 sysfs_filename = data->sysfs_names;
958 sysfs_names_free = ABIT_UGURU3_SYSFS_NAMES_LENGTH;
959 for (i = 0; data->sensors[i].name; i++) {
960
961 if (i >= ABIT_UGURU3_MAX_NO_SENSORS) {
962 printk(KERN_ERR ABIT_UGURU3_NAME
963 ": Fatal error motherboard has more sensors "
964 "then ABIT_UGURU3_MAX_NO_SENSORS. This should "
965 "never happen please report to the abituguru3 "
966 "maintainer (see MAINTAINERS)\n");
967 res = -ENAMETOOLONG;
968 goto abituguru3_probe_error;
969 }
970 type = data->sensors[i].type;
971 for (j = 0; j < no_sysfs_attr[type]; j++) {
972 used = snprintf(sysfs_filename, sysfs_names_free,
973 abituguru3_sysfs_templ[type][j].dev_attr.attr.
974 name, sensor_index[type]) + 1;
975 data->sysfs_attr[sysfs_attr_i] =
976 abituguru3_sysfs_templ[type][j];
977 data->sysfs_attr[sysfs_attr_i].dev_attr.attr.name =
978 sysfs_filename;
979 data->sysfs_attr[sysfs_attr_i].index = i;
980 sysfs_filename += used;
981 sysfs_names_free -= used;
982 sysfs_attr_i++;
983 }
984 sensor_index[type]++;
985 }
986
987 if (sysfs_names_free < 0) {
988 printk(KERN_ERR ABIT_UGURU3_NAME
989 ": Fatal error ran out of space for sysfs attr names. "
990 "This should never happen please report to the "
991 "abituguru3 maintainer (see MAINTAINERS)\n");
992 res = -ENAMETOOLONG;
993 goto abituguru3_probe_error;
994 }
995
996
997 for (i = 0; i < sysfs_attr_i; i++)
998 if (device_create_file(&pdev->dev,
999 &data->sysfs_attr[i].dev_attr))
1000 goto abituguru3_probe_error;
1001 for (i = 0; i < ARRAY_SIZE(abituguru3_sysfs_attr); i++)
1002 if (device_create_file(&pdev->dev,
1003 &abituguru3_sysfs_attr[i].dev_attr))
1004 goto abituguru3_probe_error;
1005
1006 data->hwmon_dev = hwmon_device_register(&pdev->dev);
1007 if (IS_ERR(data->hwmon_dev)) {
1008 res = PTR_ERR(data->hwmon_dev);
1009 goto abituguru3_probe_error;
1010 }
1011
1012 return 0;
1013
1014abituguru3_probe_error:
1015 for (i = 0; data->sysfs_attr[i].dev_attr.attr.name; i++)
1016 device_remove_file(&pdev->dev, &data->sysfs_attr[i].dev_attr);
1017 for (i = 0; i < ARRAY_SIZE(abituguru3_sysfs_attr); i++)
1018 device_remove_file(&pdev->dev,
1019 &abituguru3_sysfs_attr[i].dev_attr);
1020 kfree(data);
1021 return res;
1022}
1023
1024static int __devexit abituguru3_remove(struct platform_device *pdev)
1025{
1026 int i;
1027 struct abituguru3_data *data = platform_get_drvdata(pdev);
1028
1029 platform_set_drvdata(pdev, NULL);
1030 hwmon_device_unregister(data->hwmon_dev);
1031 for (i = 0; data->sysfs_attr[i].dev_attr.attr.name; i++)
1032 device_remove_file(&pdev->dev, &data->sysfs_attr[i].dev_attr);
1033 for (i = 0; i < ARRAY_SIZE(abituguru3_sysfs_attr); i++)
1034 device_remove_file(&pdev->dev,
1035 &abituguru3_sysfs_attr[i].dev_attr);
1036 kfree(data);
1037
1038 return 0;
1039}
1040
1041static struct abituguru3_data *abituguru3_update_device(struct device *dev)
1042{
1043 int i;
1044 struct abituguru3_data *data = dev_get_drvdata(dev);
1045
1046 mutex_lock(&data->update_lock);
1047 if (!data->valid || time_after(jiffies, data->last_updated + HZ)) {
1048
1049 data->valid = 0;
1050
1051 if (abituguru3_read_increment_offset(data,
1052 ABIT_UGURU3_SETTINGS_BANK,
1053 ABIT_UGURU3_ALARMS_START,
1054 1, data->alarms, 48/8) != (48/8))
1055 goto LEAVE_UPDATE;
1056
1057 for (i = 0; i < 32; i++) {
1058 if (abituguru3_read(data, ABIT_UGURU3_SENSORS_BANK,
1059 ABIT_UGURU3_VALUES_START + i,
1060 1, &data->value[i]) != 1)
1061 goto LEAVE_UPDATE;
1062 if (abituguru3_read_increment_offset(data,
1063 ABIT_UGURU3_SETTINGS_BANK,
1064 ABIT_UGURU3_SETTINGS_START + i * 3,
1065 1,
1066 data->settings[i], 3) != 3)
1067 goto LEAVE_UPDATE;
1068 }
1069
1070 for (i = 0; i < 16; i++) {
1071 if (abituguru3_read(data, ABIT_UGURU3_SENSORS_BANK,
1072 ABIT_UGURU3_VALUES_START + 32 + i,
1073 1, &data->value[32 + i]) != 1)
1074 goto LEAVE_UPDATE;
1075 if (abituguru3_read_increment_offset(data,
1076 ABIT_UGURU3_SETTINGS_BANK,
1077 ABIT_UGURU3_SETTINGS_START + 32 * 3 +
1078 i * 2, 1,
1079 data->settings[32 + i], 2) != 2)
1080 goto LEAVE_UPDATE;
1081 }
1082 data->last_updated = jiffies;
1083 data->valid = 1;
1084 }
1085LEAVE_UPDATE:
1086 mutex_unlock(&data->update_lock);
1087 if (data->valid)
1088 return data;
1089 else
1090 return NULL;
1091}
1092
1093#ifdef CONFIG_PM
1094static int abituguru3_suspend(struct platform_device *pdev, pm_message_t state)
1095{
1096 struct abituguru3_data *data = platform_get_drvdata(pdev);
1097
1098
1099 mutex_lock(&data->update_lock);
1100 return 0;
1101}
1102
1103static int abituguru3_resume(struct platform_device *pdev)
1104{
1105 struct abituguru3_data *data = platform_get_drvdata(pdev);
1106 mutex_unlock(&data->update_lock);
1107 return 0;
1108}
1109#else
1110#define abituguru3_suspend NULL
1111#define abituguru3_resume NULL
1112#endif
1113
1114static struct platform_driver abituguru3_driver = {
1115 .driver = {
1116 .owner = THIS_MODULE,
1117 .name = ABIT_UGURU3_NAME,
1118 },
1119 .probe = abituguru3_probe,
1120 .remove = __devexit_p(abituguru3_remove),
1121 .suspend = abituguru3_suspend,
1122 .resume = abituguru3_resume
1123};
1124
1125#ifdef CONFIG_DMI
1126
1127static int __init abituguru3_dmi_detect(void)
1128{
1129 const char *board_vendor, *board_name;
1130 int i, err = (force) ? 1 : -ENODEV;
1131
1132 board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
1133 if (!board_vendor || strcmp(board_vendor, "http://www.abit.com.tw/"))
1134 return err;
1135
1136 board_name = dmi_get_system_info(DMI_BOARD_NAME);
1137 if (!board_name)
1138 return err;
1139
1140 for (i = 0; abituguru3_motherboards[i].id; i++) {
1141 const char *dmi_name = abituguru3_motherboards[i].dmi_name;
1142 if (dmi_name && !strcmp(dmi_name, board_name))
1143 break;
1144 }
1145
1146 if (!abituguru3_motherboards[i].id)
1147 return 1;
1148
1149 return 0;
1150}
1151
1152#else
1153
1154static inline int abituguru3_dmi_detect(void)
1155{
1156 return -ENODEV;
1157}
1158
1159#endif
1160
1161
1162
1163
1164
1165static int __init abituguru3_detect(void)
1166{
1167
1168
1169
1170 u8 data_val = inb_p(ABIT_UGURU3_BASE + ABIT_UGURU3_DATA);
1171 u8 cmd_val = inb_p(ABIT_UGURU3_BASE + ABIT_UGURU3_CMD);
1172 if (((data_val == 0x00) || (data_val == 0x08)) &&
1173 ((cmd_val == 0xAC) || (cmd_val == 0x05) ||
1174 (cmd_val == 0x55)))
1175 return 0;
1176
1177 ABIT_UGURU3_DEBUG("no Abit uGuru3 found, data = 0x%02X, cmd = "
1178 "0x%02X\n", (unsigned int)data_val, (unsigned int)cmd_val);
1179
1180 if (force) {
1181 printk(KERN_INFO ABIT_UGURU3_NAME ": Assuming Abit uGuru3 is "
1182 "present because of \"force\" parameter\n");
1183 return 0;
1184 }
1185
1186
1187 return -ENODEV;
1188}
1189
1190static struct platform_device *abituguru3_pdev;
1191
1192static int __init abituguru3_init(void)
1193{
1194 struct resource res = { .flags = IORESOURCE_IO };
1195 int err;
1196
1197
1198 err = abituguru3_dmi_detect();
1199 if (err < 0)
1200 return err;
1201
1202
1203
1204
1205 if (err > 0) {
1206 err = abituguru3_detect();
1207 if (err)
1208 return err;
1209 }
1210
1211 err = platform_driver_register(&abituguru3_driver);
1212 if (err)
1213 goto exit;
1214
1215 abituguru3_pdev = platform_device_alloc(ABIT_UGURU3_NAME,
1216 ABIT_UGURU3_BASE);
1217 if (!abituguru3_pdev) {
1218 printk(KERN_ERR ABIT_UGURU3_NAME
1219 ": Device allocation failed\n");
1220 err = -ENOMEM;
1221 goto exit_driver_unregister;
1222 }
1223
1224 res.start = ABIT_UGURU3_BASE;
1225 res.end = ABIT_UGURU3_BASE + ABIT_UGURU3_REGION_LENGTH - 1;
1226 res.name = ABIT_UGURU3_NAME;
1227
1228 err = platform_device_add_resources(abituguru3_pdev, &res, 1);
1229 if (err) {
1230 printk(KERN_ERR ABIT_UGURU3_NAME
1231 ": Device resource addition failed (%d)\n", err);
1232 goto exit_device_put;
1233 }
1234
1235 err = platform_device_add(abituguru3_pdev);
1236 if (err) {
1237 printk(KERN_ERR ABIT_UGURU3_NAME
1238 ": Device addition failed (%d)\n", err);
1239 goto exit_device_put;
1240 }
1241
1242 return 0;
1243
1244exit_device_put:
1245 platform_device_put(abituguru3_pdev);
1246exit_driver_unregister:
1247 platform_driver_unregister(&abituguru3_driver);
1248exit:
1249 return err;
1250}
1251
1252static void __exit abituguru3_exit(void)
1253{
1254 platform_device_unregister(abituguru3_pdev);
1255 platform_driver_unregister(&abituguru3_driver);
1256}
1257
1258MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>");
1259MODULE_DESCRIPTION("Abit uGuru3 Sensor device");
1260MODULE_LICENSE("GPL");
1261
1262module_init(abituguru3_init);
1263module_exit(abituguru3_exit);