OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [hwmon/] [abituguru3.c] - Blame information for rev 78

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
    abituguru3.c Copyright (c) 2006 Hans de Goede <j.w.r.degoede@hhs.nl>
3
 
4
    This program is free software; you can redistribute it and/or modify
5
    it under the terms of the GNU General Public License as published by
6
    the Free Software Foundation; either version 2 of the License, or
7
    (at your option) any later version.
8
 
9
    This program is distributed in the hope that it will be useful,
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
    GNU General Public License for more details.
13
 
14
    You should have received a copy of the GNU General Public License
15
    along with this program; if not, write to the Free Software
16
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
*/
18
/*
19
    This driver supports the sensor part of revision 3 of the custom Abit uGuru
20
    chip found on newer Abit uGuru motherboards. Note: because of lack of specs
21
    only reading the sensors and their settings is supported.
22
*/
23
#include <linux/module.h>
24
#include <linux/init.h>
25
#include <linux/slab.h>
26
#include <linux/jiffies.h>
27
#include <linux/mutex.h>
28
#include <linux/err.h>
29
#include <linux/delay.h>
30
#include <linux/platform_device.h>
31
#include <linux/hwmon.h>
32
#include <linux/hwmon-sysfs.h>
33
#include <asm/io.h>
34
 
35
/* uGuru3 bank addresses */
36
#define ABIT_UGURU3_SETTINGS_BANK               0x01
37
#define ABIT_UGURU3_SENSORS_BANK                0x08
38
#define ABIT_UGURU3_MISC_BANK                   0x09
39
#define ABIT_UGURU3_ALARMS_START                0x1E
40
#define ABIT_UGURU3_SETTINGS_START              0x24
41
#define ABIT_UGURU3_VALUES_START                0x80
42
#define ABIT_UGURU3_BOARD_ID                    0x0A
43
/* uGuru3 sensor bank flags */                       /* Alarm if: */
44
#define ABIT_UGURU3_TEMP_HIGH_ALARM_ENABLE      0x01 /*  temp over warn */
45
#define ABIT_UGURU3_VOLT_HIGH_ALARM_ENABLE      0x02 /*  volt over max */
46
#define ABIT_UGURU3_VOLT_LOW_ALARM_ENABLE       0x04 /*  volt under min */
47
#define ABIT_UGURU3_TEMP_HIGH_ALARM_FLAG        0x10 /* temp is over warn */
48
#define ABIT_UGURU3_VOLT_HIGH_ALARM_FLAG        0x20 /* volt is over max */
49
#define ABIT_UGURU3_VOLT_LOW_ALARM_FLAG         0x40 /* volt is under min */
50
#define ABIT_UGURU3_FAN_LOW_ALARM_ENABLE        0x01 /*   fan under min */
51
#define ABIT_UGURU3_BEEP_ENABLE                 0x08 /* beep if alarm */
52
#define ABIT_UGURU3_SHUTDOWN_ENABLE             0x80 /* shutdown if alarm */
53
/* sensor types */
54
#define ABIT_UGURU3_IN_SENSOR                   0
55
#define ABIT_UGURU3_TEMP_SENSOR                 1
56
#define ABIT_UGURU3_FAN_SENSOR                  2
57
 
58
/* Timeouts / Retries, if these turn out to need a lot of fiddling we could
59
   convert them to params. Determined by trial and error. I assume this is
60
   cpu-speed independent, since the ISA-bus and not the CPU should be the
61
   bottleneck. */
62
#define ABIT_UGURU3_WAIT_TIMEOUT                250
63
/* Normally the 0xAC at the end of synchronize() is reported after the
64
   first read, but sometimes not and we need to poll */
65
#define ABIT_UGURU3_SYNCHRONIZE_TIMEOUT         5
66
/* utility macros */
67
#define ABIT_UGURU3_NAME                        "abituguru3"
68
#define ABIT_UGURU3_DEBUG(format, arg...)       \
69
        if (verbose)                            \
70
                printk(KERN_DEBUG ABIT_UGURU3_NAME ": " format , ## arg)
71
 
72
/* Macros to help calculate the sysfs_names array length */
73
#define ABIT_UGURU3_MAX_NO_SENSORS 26
74
/* sum of strlen +1 of: in??_input\0, in??_{min,max}\0, in??_{min,max}_alarm\0,
75
   in??_{min,max}_alarm_enable\0, in??_beep\0, in??_shutdown\0, in??_label\0 */
76
#define ABIT_UGURU3_IN_NAMES_LENGTH (11 + 2 * 9 + 2 * 15 + 2 * 22 + 10 + 14 + 11)
77
/* sum of strlen +1 of: temp??_input\0, temp??_max\0, temp??_crit\0,
78
   temp??_alarm\0, temp??_alarm_enable\0, temp??_beep\0, temp??_shutdown\0,
79
   temp??_label\0 */
80
#define ABIT_UGURU3_TEMP_NAMES_LENGTH (13 + 11 + 12 + 13 + 20 + 12 + 16 + 13)
81
/* sum of strlen +1 of: fan??_input\0, fan??_min\0, fan??_alarm\0,
82
   fan??_alarm_enable\0, fan??_beep\0, fan??_shutdown\0, fan??_label\0 */
83
#define ABIT_UGURU3_FAN_NAMES_LENGTH (12 + 10 + 12 + 19 + 11 + 15 + 12)
84
/* Worst case scenario 16 in sensors (longest names_length) and the rest
85
   temp sensors (second longest names_length). */
86
#define ABIT_UGURU3_SYSFS_NAMES_LENGTH (16 * ABIT_UGURU3_IN_NAMES_LENGTH + \
87
        (ABIT_UGURU3_MAX_NO_SENSORS - 16) * ABIT_UGURU3_TEMP_NAMES_LENGTH)
88
 
89
/* All the macros below are named identical to the openguru2 program
90
   reverse engineered by Louis Kruger, hence the names might not be 100%
91
   logical. I could come up with better names, but I prefer keeping the names
92
   identical so that this driver can be compared with his work more easily. */
93
/* Two i/o-ports are used by uGuru */
94
#define ABIT_UGURU3_BASE                        0x00E0
95
#define ABIT_UGURU3_CMD                         0x00
96
#define ABIT_UGURU3_DATA                        0x04
97
#define ABIT_UGURU3_REGION_LENGTH               5
98
/* The wait_xxx functions return this on success and the last contents
99
   of the DATA register (0-255) on failure. */
100
#define ABIT_UGURU3_SUCCESS                     -1
101
/* uGuru status flags */
102
#define ABIT_UGURU3_STATUS_READY_FOR_READ       0x01
103
#define ABIT_UGURU3_STATUS_BUSY                 0x02
104
 
105
 
106
/* Structures */
107
struct abituguru3_sensor_info {
108
        const char* name;
109
        int port;
110
        int type;
111
        int multiplier;
112
        int divisor;
113
        int offset;
114
};
115
 
116
struct abituguru3_motherboard_info {
117
        u16 id;
118
        const char *name;
119
        /* + 1 -> end of sensors indicated by a sensor with name == NULL */
120
        struct abituguru3_sensor_info sensors[ABIT_UGURU3_MAX_NO_SENSORS + 1];
121
};
122
 
123
/* For the Abit uGuru, we need to keep some data in memory.
124
   The structure is dynamically allocated, at the same time when a new
125
   abituguru3 device is allocated. */
126
struct abituguru3_data {
127
        struct device *hwmon_dev;       /* hwmon registered device */
128
        struct mutex update_lock;       /* protect access to data and uGuru */
129
        unsigned short addr;            /* uguru base address */
130
        char valid;                     /* !=0 if following fields are valid */
131
        unsigned long last_updated;     /* In jiffies */
132
 
133
        /* For convenience the sysfs attr and their names are generated
134
           automatically. We have max 10 entries per sensor (for in sensors) */
135
        struct sensor_device_attribute_2 sysfs_attr[ABIT_UGURU3_MAX_NO_SENSORS
136
                * 10];
137
 
138
        /* Buffer to store the dynamically generated sysfs names */
139
        char sysfs_names[ABIT_UGURU3_SYSFS_NAMES_LENGTH];
140
 
141
        /* Pointer to the sensors info for the detected motherboard */
142
        const struct abituguru3_sensor_info *sensors;
143
 
144
        /* The abituguru3 supports upto 48 sensors, and thus has registers
145
           sets for 48 sensors, for convienence reasons / simplicity of the
146
           code we always read and store all registers for all 48 sensors */
147
 
148
        /* Alarms for all 48 sensors (1 bit per sensor) */
149
        u8 alarms[48/8];
150
 
151
        /* Value of all 48 sensors */
152
        u8 value[48];
153
 
154
        /* Settings of all 48 sensors, note in and temp sensors (the first 32
155
           sensors) have 3 bytes of settings, while fans only have 2 bytes,
156
           for convenience we use 3 bytes for all sensors */
157
        u8 settings[48][3];
158
};
159
 
160
 
161
/* Constants */
162
static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
163
        { 0x000C, "unknown", {
164
                { "CPU Core",            0, 0, 10, 1, 0 },
165
                { "DDR",                 1, 0, 10, 1, 0 },
166
                { "DDR VTT",             2, 0, 10, 1, 0 },
167
                { "CPU VTT 1.2V",        3, 0, 10, 1, 0 },
168
                { "MCH & PCIE 1.5V",     4, 0, 10, 1, 0 },
169
                { "MCH 2.5V",            5, 0, 20, 1, 0 },
170
                { "ICH 1.05V",           6, 0, 10, 1, 0 },
171
                { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
172
                { "ATX +12V (4-pin)",    8, 0, 60, 1, 0 },
173
                { "ATX +5V",             9, 0, 30, 1, 0 },
174
                { "+3.3V",              10, 0, 20, 1, 0 },
175
                { "5VSB",               11, 0, 30, 1, 0 },
176
                { "CPU",                24, 1, 1, 1, 0 },
177
                { "System ",            25, 1, 1, 1, 0 },
178
                { "PWM",                26, 1, 1, 1, 0 },
179
                { "CPU Fan",            32, 2, 60, 1, 0 },
180
                { "NB Fan",             33, 2, 60, 1, 0 },
181
                { "SYS FAN",            34, 2, 60, 1, 0 },
182
                { "AUX1 Fan",           35, 2, 60, 1, 0 },
183
                { NULL, 0, 0, 0, 0, 0 } }
184
        },
185
        { 0x000D, "Abit AW8", {
186
                { "CPU Core",            0, 0, 10, 1, 0 },
187
                { "DDR",                 1, 0, 10, 1, 0 },
188
                { "DDR VTT",             2, 0, 10, 1, 0 },
189
                { "CPU VTT 1.2V",        3, 0, 10, 1, 0 },
190
                { "MCH & PCIE 1.5V",     4, 0, 10, 1, 0 },
191
                { "MCH 2.5V",            5, 0, 20, 1, 0 },
192
                { "ICH 1.05V",           6, 0, 10, 1, 0 },
193
                { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
194
                { "ATX +12V (4-pin)",    8, 0, 60, 1, 0 },
195
                { "ATX +5V",             9, 0, 30, 1, 0 },
196
                { "+3.3V",              10, 0, 20, 1, 0 },
197
                { "5VSB",               11, 0, 30, 1, 0 },
198
                { "CPU",                24, 1, 1, 1, 0 },
199
                { "System ",            25, 1, 1, 1, 0 },
200
                { "PWM1",               26, 1, 1, 1, 0 },
201
                { "PWM2",               27, 1, 1, 1, 0 },
202
                { "PWM3",               28, 1, 1, 1, 0 },
203
                { "PWM4",               29, 1, 1, 1, 0 },
204
                { "CPU Fan",            32, 2, 60, 1, 0 },
205
                { "NB Fan",             33, 2, 60, 1, 0 },
206
                { "SYS Fan",            34, 2, 60, 1, 0 },
207
                { "AUX1 Fan",           35, 2, 60, 1, 0 },
208
                { "AUX2 Fan",           36, 2, 60, 1, 0 },
209
                { "AUX3 Fan",           37, 2, 60, 1, 0 },
210
                { "AUX4 Fan",           38, 2, 60, 1, 0 },
211
                { "AUX5 Fan",           39, 2, 60, 1, 0 },
212
                { NULL, 0, 0, 0, 0, 0 } }
213
        },
214
        { 0x000E, "AL-8", {
215
                { "CPU Core",            0, 0, 10, 1, 0 },
216
                { "DDR",                 1, 0, 10, 1, 0 },
217
                { "DDR VTT",             2, 0, 10, 1, 0 },
218
                { "CPU VTT 1.2V",        3, 0, 10, 1, 0 },
219
                { "MCH & PCIE 1.5V",     4, 0, 10, 1, 0 },
220
                { "MCH 2.5V",            5, 0, 20, 1, 0 },
221
                { "ICH 1.05V",           6, 0, 10, 1, 0 },
222
                { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
223
                { "ATX +12V (4-pin)",    8, 0, 60, 1, 0 },
224
                { "ATX +5V",             9, 0, 30, 1, 0 },
225
                { "+3.3V",              10, 0, 20, 1, 0 },
226
                { "5VSB",               11, 0, 30, 1, 0 },
227
                { "CPU",                24, 1, 1, 1, 0 },
228
                { "System ",            25, 1, 1, 1, 0 },
229
                { "PWM",                26, 1, 1, 1, 0 },
230
                { "CPU Fan",            32, 2, 60, 1, 0 },
231
                { "NB Fan",             33, 2, 60, 1, 0 },
232
                { "SYS Fan",            34, 2, 60, 1, 0 },
233
                { NULL, 0, 0, 0, 0, 0 } }
234
        },
235
        { 0x000F, "unknown", {
236
                { "CPU Core",            0, 0, 10, 1, 0 },
237
                { "DDR",                 1, 0, 10, 1, 0 },
238
                { "DDR VTT",             2, 0, 10, 1, 0 },
239
                { "CPU VTT 1.2V",        3, 0, 10, 1, 0 },
240
                { "MCH & PCIE 1.5V",     4, 0, 10, 1, 0 },
241
                { "MCH 2.5V",            5, 0, 20, 1, 0 },
242
                { "ICH 1.05V",           6, 0, 10, 1, 0 },
243
                { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
244
                { "ATX +12V (4-pin)",    8, 0, 60, 1, 0 },
245
                { "ATX +5V",             9, 0, 30, 1, 0 },
246
                { "+3.3V",              10, 0, 20, 1, 0 },
247
                { "5VSB",               11, 0, 30, 1, 0 },
248
                { "CPU",                24, 1, 1, 1, 0 },
249
                { "System ",            25, 1, 1, 1, 0 },
250
                { "PWM",                26, 1, 1, 1, 0 },
251
                { "CPU Fan",            32, 2, 60, 1, 0 },
252
                { "NB Fan",             33, 2, 60, 1, 0 },
253
                { "SYS Fan",            34, 2, 60, 1, 0 },
254
                { NULL, 0, 0, 0, 0, 0 } }
255
        },
256
        { 0x0010, "Abit NI8 SLI GR", {
257
                { "CPU Core",            0, 0, 10, 1, 0 },
258
                { "DDR",                 1, 0, 10, 1, 0 },
259
                { "DDR VTT",             2, 0, 10, 1, 0 },
260
                { "CPU VTT 1.2V",        3, 0, 10, 1, 0 },
261
                { "NB 1.4V",             4, 0, 10, 1, 0 },
262
                { "SB 1.5V",             6, 0, 10, 1, 0 },
263
                { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
264
                { "ATX +12V (4-pin)",    8, 0, 60, 1, 0 },
265
                { "ATX +5V",             9, 0, 30, 1, 0 },
266
                { "+3.3V",              10, 0, 20, 1, 0 },
267
                { "5VSB",               11, 0, 30, 1, 0 },
268
                { "CPU",                24, 1, 1, 1, 0 },
269
                { "SYS",                25, 1, 1, 1, 0 },
270
                { "PWM",                26, 1, 1, 1, 0 },
271
                { "CPU Fan",            32, 2, 60, 1, 0 },
272
                { "NB Fan",             33, 2, 60, 1, 0 },
273
                { "SYS Fan",            34, 2, 60, 1, 0 },
274
                { "AUX1 Fan",           35, 2, 60, 1, 0 },
275
                { "OTES1 Fan",          36, 2, 60, 1, 0 },
276
                { NULL, 0, 0, 0, 0, 0 } }
277
        },
278
        { 0x0011, "Abit AT8 32X", {
279
                { "CPU Core",            0, 0, 10, 1, 0 },
280
                { "DDR",                 1, 0, 20, 1, 0 },
281
                { "DDR VTT",             2, 0, 10, 1, 0 },
282
                { "CPU VDDA 2.5V",       6, 0, 20, 1, 0 },
283
                { "NB 1.8V",             4, 0, 10, 1, 0 },
284
                { "NB 1.8V Dual",        5, 0, 10, 1, 0 },
285
                { "HTV 1.2",             3, 0, 10, 1, 0 },
286
                { "PCIE 1.2V",          12, 0, 10, 1, 0 },
287
                { "NB 1.2V",            13, 0, 10, 1, 0 },
288
                { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
289
                { "ATX +12V (4-pin)",    8, 0, 60, 1, 0 },
290
                { "ATX +5V",             9, 0, 30, 1, 0 },
291
                { "+3.3V",              10, 0, 20, 1, 0 },
292
                { "5VSB",               11, 0, 30, 1, 0 },
293
                { "CPU",                24, 1, 1, 1, 0 },
294
                { "NB",                 25, 1, 1, 1, 0 },
295
                { "System",             26, 1, 1, 1, 0 },
296
                { "PWM",                27, 1, 1, 1, 0 },
297
                { "CPU Fan",            32, 2, 60, 1, 0 },
298
                { "NB Fan",             33, 2, 60, 1, 0 },
299
                { "SYS Fan",            34, 2, 60, 1, 0 },
300
                { "AUX1 Fan",           35, 2, 60, 1, 0 },
301
                { "AUX2 Fan",           36, 2, 60, 1, 0 },
302
                { NULL, 0, 0, 0, 0, 0 } }
303
        },
304
        { 0x0012, "Abit AN8 32X", {
305
                { "CPU Core",            0, 0, 10, 1, 0 },
306
                { "DDR",                 1, 0, 20, 1, 0 },
307
                { "DDR VTT",             2, 0, 10, 1, 0 },
308
                { "HyperTransport",      3, 0, 10, 1, 0 },
309
                { "CPU VDDA 2.5V",       5, 0, 20, 1, 0 },
310
                { "NB",                  4, 0, 10, 1, 0 },
311
                { "SB",                  6, 0, 10, 1, 0 },
312
                { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
313
                { "ATX +12V (4-pin)",    8, 0, 60, 1, 0 },
314
                { "ATX +5V",             9, 0, 30, 1, 0 },
315
                { "+3.3V",              10, 0, 20, 1, 0 },
316
                { "5VSB",               11, 0, 30, 1, 0 },
317
                { "CPU",                24, 1, 1, 1, 0 },
318
                { "SYS",                25, 1, 1, 1, 0 },
319
                { "PWM",                26, 1, 1, 1, 0 },
320
                { "CPU Fan",            32, 2, 60, 1, 0 },
321
                { "NB Fan",             33, 2, 60, 1, 0 },
322
                { "SYS Fan",            34, 2, 60, 1, 0 },
323
                { "AUX1 Fan",           36, 2, 60, 1, 0 },
324
                { NULL, 0, 0, 0, 0, 0 } }
325
        },
326
        { 0x0013, "unknown", {
327
                { "CPU Core",            0, 0, 10, 1, 0 },
328
                { "DDR",                 1, 0, 10, 1, 0 },
329
                { "DDR VTT",             2, 0, 10, 1, 0 },
330
                { "CPU VTT 1.2V",        3, 0, 10, 1, 0 },
331
                { "MCH & PCIE 1.5V",     4, 0, 10, 1, 0 },
332
                { "MCH 2.5V",            5, 0, 20, 1, 0 },
333
                { "ICH 1.05V",           6, 0, 10, 1, 0 },
334
                { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
335
                { "ATX +12V (4-pin)",    8, 0, 60, 1, 0 },
336
                { "ATX +5V",             9, 0, 30, 1, 0 },
337
                { "+3.3V",              10, 0, 20, 1, 0 },
338
                { "5VSB",               11, 0, 30, 1, 0 },
339
                { "CPU",                24, 1, 1, 1, 0 },
340
                { "System ",            25, 1, 1, 1, 0 },
341
                { "PWM1",               26, 1, 1, 1, 0 },
342
                { "PWM2",               27, 1, 1, 1, 0 },
343
                { "PWM3",               28, 1, 1, 1, 0 },
344
                { "PWM4",               29, 1, 1, 1, 0 },
345
                { "CPU Fan",            32, 2, 60, 1, 0 },
346
                { "NB Fan",             33, 2, 60, 1, 0 },
347
                { "SYS Fan",            34, 2, 60, 1, 0 },
348
                { "AUX1 Fan",           35, 2, 60, 1, 0 },
349
                { "AUX2 Fan",           36, 2, 60, 1, 0 },
350
                { "AUX3 Fan",           37, 2, 60, 1, 0 },
351
                { "AUX4 Fan",           38, 2, 60, 1, 0 },
352
                { NULL, 0, 0, 0, 0, 0 } }
353
        },
354
        { 0x0014, "Abit AB9 Pro", {
355
                { "CPU Core",            0, 0, 10, 1, 0 },
356
                { "DDR",                 1, 0, 10, 1, 0 },
357
                { "DDR VTT",             2, 0, 10, 1, 0 },
358
                { "CPU VTT 1.2V",        3, 0, 10, 1, 0 },
359
                { "MCH & PCIE 1.5V",     4, 0, 10, 1, 0 },
360
                { "MCH 2.5V",            5, 0, 20, 1, 0 },
361
                { "ICH 1.05V",           6, 0, 10, 1, 0 },
362
                { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
363
                { "ATX +12V (4-pin)",    8, 0, 60, 1, 0 },
364
                { "ATX +5V",             9, 0, 30, 1, 0 },
365
                { "+3.3V",              10, 0, 20, 1, 0 },
366
                { "5VSB",               11, 0, 30, 1, 0 },
367
                { "CPU",                24, 1, 1, 1, 0 },
368
                { "System ",            25, 1, 1, 1, 0 },
369
                { "PWM",                26, 1, 1, 1, 0 },
370
                { "CPU Fan",            32, 2, 60, 1, 0 },
371
                { "NB Fan",             33, 2, 60, 1, 0 },
372
                { "SYS Fan",            34, 2, 60, 1, 0 },
373
                { NULL, 0, 0, 0, 0, 0 } }
374
        },
375
        { 0x0015, "unknown", {
376
                { "CPU Core",            0, 0, 10, 1, 0 },
377
                { "DDR",                 1, 0, 20, 1, 0 },
378
                { "DDR VTT",             2, 0, 10, 1, 0 },
379
                { "HyperTransport",      3, 0, 10, 1, 0 },
380
                { "CPU VDDA 2.5V",       5, 0, 20, 1, 0 },
381
                { "NB",                  4, 0, 10, 1, 0 },
382
                { "SB",                  6, 0, 10, 1, 0 },
383
                { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
384
                { "ATX +12V (4-pin)",    8, 0, 60, 1, 0 },
385
                { "ATX +5V",             9, 0, 30, 1, 0 },
386
                { "+3.3V",              10, 0, 20, 1, 0 },
387
                { "5VSB",               11, 0, 30, 1, 0 },
388
                { "CPU",                24, 1, 1, 1, 0 },
389
                { "SYS",                25, 1, 1, 1, 0 },
390
                { "PWM",                26, 1, 1, 1, 0 },
391
                { "CPU Fan",            32, 2, 60, 1, 0 },
392
                { "NB Fan",             33, 2, 60, 1, 0 },
393
                { "SYS Fan",            34, 2, 60, 1, 0 },
394
                { "AUX1 Fan",           33, 2, 60, 1, 0 },
395
                { "AUX2 Fan",           35, 2, 60, 1, 0 },
396
                { "AUX3 Fan",           36, 2, 60, 1, 0 },
397
                { NULL, 0, 0, 0, 0, 0 } }
398
        },
399
        { 0x0016, "AW9D-MAX", {
400
                { "CPU Core",            0, 0, 10, 1, 0 },
401
                { "DDR2",                1, 0, 20, 1, 0 },
402
                { "DDR2 VTT",            2, 0, 10, 1, 0 },
403
                { "CPU VTT 1.2V",        3, 0, 10, 1, 0 },
404
                { "MCH & PCIE 1.5V",     4, 0, 10, 1, 0 },
405
                { "MCH 2.5V",            5, 0, 20, 1, 0 },
406
                { "ICH 1.05V",           6, 0, 10, 1, 0 },
407
                { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
408
                { "ATX +12V (4-pin)",    8, 0, 60, 1, 0 },
409
                { "ATX +5V",             9, 0, 30, 1, 0 },
410
                { "+3.3V",              10, 0, 20, 1, 0 },
411
                { "5VSB",               11, 0, 30, 1, 0 },
412
                { "CPU",                24, 1, 1, 1, 0 },
413
                { "System ",            25, 1, 1, 1, 0 },
414
                { "PWM1",               26, 1, 1, 1, 0 },
415
                { "PWM2",               27, 1, 1, 1, 0 },
416
                { "PWM3",               28, 1, 1, 1, 0 },
417
                { "PWM4",               29, 1, 1, 1, 0 },
418
                { "CPU Fan",            32, 2, 60, 1, 0 },
419
                { "NB Fan",             33, 2, 60, 1, 0 },
420
                { "SYS Fan",            34, 2, 60, 1, 0 },
421
                { "AUX1 Fan",           35, 2, 60, 1, 0 },
422
                { "AUX2 Fan",           36, 2, 60, 1, 0 },
423
                { "AUX3 Fan",           37, 2, 60, 1, 0 },
424
                { "OTES1 Fan",          38, 2, 60, 1, 0 },
425
                { NULL, 0, 0, 0, 0, 0 } }
426
        },
427
        { 0x0017, "unknown", {
428
                { "CPU Core",            0, 0, 10, 1, 0 },
429
                { "DDR2",                1, 0, 20, 1, 0 },
430
                { "DDR2 VTT",            2, 0, 10, 1, 0 },
431
                { "HyperTransport",      3, 0, 10, 1, 0 },
432
                { "CPU VDDA 2.5V",       6, 0, 20, 1, 0 },
433
                { "NB 1.8V",             4, 0, 10, 1, 0 },
434
                { "NB 1.2V ",           13, 0, 10, 1, 0 },
435
                { "SB 1.2V",             5, 0, 10, 1, 0 },
436
                { "PCIE 1.2V",          12, 0, 10, 1, 0 },
437
                { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
438
                { "ATX +12V (4-pin)",    8, 0, 60, 1, 0 },
439
                { "ATX +5V",             9, 0, 30, 1, 0 },
440
                { "ATX +3.3V",          10, 0, 20, 1, 0 },
441
                { "ATX 5VSB",           11, 0, 30, 1, 0 },
442
                { "CPU",                24, 1, 1, 1, 0 },
443
                { "System ",            26, 1, 1, 1, 0 },
444
                { "PWM",                27, 1, 1, 1, 0 },
445
                { "CPU FAN",            32, 2, 60, 1, 0 },
446
                { "SYS FAN",            34, 2, 60, 1, 0 },
447
                { "AUX1 FAN",           35, 2, 60, 1, 0 },
448
                { "AUX2 FAN",           36, 2, 60, 1, 0 },
449
                { "AUX3 FAN",           37, 2, 60, 1, 0 },
450
                { NULL, 0, 0, 0, 0, 0 } }
451
        },
452
        { 0x0018, "unknown", {
453
                { "CPU Core",            0, 0, 10, 1, 0 },
454
                { "DDR2",                1, 0, 20, 1, 0 },
455
                { "DDR2 VTT",            2, 0, 10, 1, 0 },
456
                { "CPU VTT",             3, 0, 10, 1, 0 },
457
                { "MCH 1.25V",           4, 0, 10, 1, 0 },
458
                { "ICHIO 1.5V",          5, 0, 10, 1, 0 },
459
                { "ICH 1.05V",           6, 0, 10, 1, 0 },
460
                { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
461
                { "ATX +12V (4-pin)",    8, 0, 60, 1, 0 },
462
                { "ATX +5V",             9, 0, 30, 1, 0 },
463
                { "+3.3V",              10, 0, 20, 1, 0 },
464
                { "5VSB",               11, 0, 30, 1, 0 },
465
                { "CPU",                24, 1, 1, 1, 0 },
466
                { "System ",            25, 1, 1, 1, 0 },
467
                { "PWM Phase1",         26, 1, 1, 1, 0 },
468
                { "PWM Phase2",         27, 1, 1, 1, 0 },
469
                { "PWM Phase3",         28, 1, 1, 1, 0 },
470
                { "PWM Phase4",         29, 1, 1, 1, 0 },
471
                { "PWM Phase5",         30, 1, 1, 1, 0 },
472
                { "CPU Fan",            32, 2, 60, 1, 0 },
473
                { "SYS Fan",            34, 2, 60, 1, 0 },
474
                { "AUX1 Fan",           33, 2, 60, 1, 0 },
475
                { "AUX2 Fan",           35, 2, 60, 1, 0 },
476
                { "AUX3 Fan",           36, 2, 60, 1, 0 },
477
                { NULL, 0, 0, 0, 0, 0 } }
478
        },
479
        { 0x0019, "unknown", {
480
                { "CPU Core",            7, 0, 10, 1, 0 },
481
                { "DDR2",               13, 0, 20, 1, 0 },
482
                { "DDR2 VTT",           14, 0, 10, 1, 0 },
483
                { "CPU VTT",             3, 0, 20, 1, 0 },
484
                { "NB 1.2V ",            4, 0, 10, 1, 0 },
485
                { "SB 1.5V",             6, 0, 10, 1, 0 },
486
                { "HyperTransport",      5, 0, 10, 1, 0 },
487
                { "ATX +12V (24-Pin)",  12, 0, 60, 1, 0 },
488
                { "ATX +12V (4-pin)",    8, 0, 60, 1, 0 },
489
                { "ATX +5V",             9, 0, 30, 1, 0 },
490
                { "ATX +3.3V",          10, 0, 20, 1, 0 },
491
                { "ATX 5VSB",           11, 0, 30, 1, 0 },
492
                { "CPU",                24, 1, 1, 1, 0 },
493
                { "System ",            25, 1, 1, 1, 0 },
494
                { "PWM Phase1",         26, 1, 1, 1, 0 },
495
                { "PWM Phase2",         27, 1, 1, 1, 0 },
496
                { "PWM Phase3",         28, 1, 1, 1, 0 },
497
                { "PWM Phase4",         29, 1, 1, 1, 0 },
498
                { "PWM Phase5",         30, 1, 1, 1, 0 },
499
                { "CPU FAN",            32, 2, 60, 1, 0 },
500
                { "SYS FAN",            34, 2, 60, 1, 0 },
501
                { "AUX1 FAN",           33, 2, 60, 1, 0 },
502
                { "AUX2 FAN",           35, 2, 60, 1, 0 },
503
                { "AUX3 FAN",           36, 2, 60, 1, 0 },
504
                { NULL, 0, 0, 0, 0, 0 } }
505
        },
506
        { 0x001A, "Abit IP35 Pro", {
507
                { "CPU Core",            0, 0, 10, 1, 0 },
508
                { "DDR2",                1, 0, 20, 1, 0 },
509
                { "DDR2 VTT",            2, 0, 10, 1, 0 },
510
                { "CPU VTT 1.2V",        3, 0, 10, 1, 0 },
511
                { "MCH 1.25V",           4, 0, 10, 1, 0 },
512
                { "ICHIO 1.5V",          5, 0, 10, 1, 0 },
513
                { "ICH 1.05V",           6, 0, 10, 1, 0 },
514
                { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
515
                { "ATX +12V (8-pin)",    8, 0, 60, 1, 0 },
516
                { "ATX +5V",             9, 0, 30, 1, 0 },
517
                { "+3.3V",              10, 0, 20, 1, 0 },
518
                { "5VSB",               11, 0, 30, 1, 0 },
519
                { "CPU",                24, 1, 1, 1, 0 },
520
                { "System ",            25, 1, 1, 1, 0 },
521
                { "PWM ",               26, 1, 1, 1, 0 },
522
                { "PWM Phase2",         27, 1, 1, 1, 0 },
523
                { "PWM Phase3",         28, 1, 1, 1, 0 },
524
                { "PWM Phase4",         29, 1, 1, 1, 0 },
525
                { "PWM Phase5",         30, 1, 1, 1, 0 },
526
                { "CPU Fan",            32, 2, 60, 1, 0 },
527
                { "SYS Fan",            34, 2, 60, 1, 0 },
528
                { "AUX1 Fan",           33, 2, 60, 1, 0 },
529
                { "AUX2 Fan",           35, 2, 60, 1, 0 },
530
                { "AUX3 Fan",           36, 2, 60, 1, 0 },
531
                { NULL, 0, 0, 0, 0, 0 } }
532
        },
533
        { 0x001B, "unknown", {
534
                { "CPU Core",            0, 0, 10, 1, 0 },
535
                { "DDR3",                1, 0, 20, 1, 0 },
536
                { "DDR3 VTT",            2, 0, 10, 1, 0 },
537
                { "CPU VTT",             3, 0, 10, 1, 0 },
538
                { "MCH 1.25V",           4, 0, 10, 1, 0 },
539
                { "ICHIO 1.5V",          5, 0, 10, 1, 0 },
540
                { "ICH 1.05V",           6, 0, 10, 1, 0 },
541
                { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
542
                { "ATX +12V (8-pin)",    8, 0, 60, 1, 0 },
543
                { "ATX +5V",             9, 0, 30, 1, 0 },
544
                { "+3.3V",              10, 0, 20, 1, 0 },
545
                { "5VSB",               11, 0, 30, 1, 0 },
546
                { "CPU",                24, 1, 1, 1, 0 },
547
                { "System",             25, 1, 1, 1, 0 },
548
                { "PWM Phase1",         26, 1, 1, 1, 0 },
549
                { "PWM Phase2",         27, 1, 1, 1, 0 },
550
                { "PWM Phase3",         28, 1, 1, 1, 0 },
551
                { "PWM Phase4",         29, 1, 1, 1, 0 },
552
                { "PWM Phase5",         30, 1, 1, 1, 0 },
553
                { "CPU Fan",            32, 2, 60, 1, 0 },
554
                { "SYS Fan",            34, 2, 60, 1, 0 },
555
                { "AUX1 Fan",           33, 2, 60, 1, 0 },
556
                { "AUX2 Fan",           35, 2, 60, 1, 0 },
557
                { "AUX3 Fan",           36, 2, 60, 1, 0 },
558
                { NULL, 0, 0, 0, 0, 0 } }
559
        },
560
        { 0x001C, "unknown", {
561
                { "CPU Core",            0, 0, 10, 1, 0 },
562
                { "DDR2",                1, 0, 20, 1, 0 },
563
                { "DDR2 VTT",            2, 0, 10, 1, 0 },
564
                { "CPU VTT",             3, 0, 10, 1, 0 },
565
                { "MCH 1.25V",           4, 0, 10, 1, 0 },
566
                { "ICHIO 1.5V",          5, 0, 10, 1, 0 },
567
                { "ICH 1.05V",           6, 0, 10, 1, 0 },
568
                { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
569
                { "ATX +12V (8-pin)",    8, 0, 60, 1, 0 },
570
                { "ATX +5V",             9, 0, 30, 1, 0 },
571
                { "+3.3V",              10, 0, 20, 1, 0 },
572
                { "5VSB",               11, 0, 30, 1, 0 },
573
                { "CPU",                24, 1, 1, 1, 0 },
574
                { "System",             25, 1, 1, 1, 0 },
575
                { "PWM Phase1",         26, 1, 1, 1, 0 },
576
                { "PWM Phase2",         27, 1, 1, 1, 0 },
577
                { "PWM Phase3",         28, 1, 1, 1, 0 },
578
                { "PWM Phase4",         29, 1, 1, 1, 0 },
579
                { "PWM Phase5",         30, 1, 1, 1, 0 },
580
                { "CPU Fan",            32, 2, 60, 1, 0 },
581
                { "SYS Fan",            34, 2, 60, 1, 0 },
582
                { "AUX1 Fan",           33, 2, 60, 1, 0 },
583
                { "AUX2 Fan",           35, 2, 60, 1, 0 },
584
                { "AUX3 Fan",           36, 2, 60, 1, 0 },
585
                { NULL, 0, 0, 0, 0, 0 } }
586
        },
587
        { 0x0000, NULL, { { NULL, 0, 0, 0, 0, 0 } } }
588
};
589
 
590
 
591
/* Insmod parameters */
592
static int force;
593
module_param(force, bool, 0);
594
MODULE_PARM_DESC(force, "Set to one to force detection.");
595
/* Default verbose is 1, since this driver is still in the testing phase */
596
static int verbose = 1;
597
module_param(verbose, bool, 0644);
598
MODULE_PARM_DESC(verbose, "Enable/disable verbose error reporting");
599
 
600
 
601
/* wait while the uguru is busy (usually after a write) */
602
static int abituguru3_wait_while_busy(struct abituguru3_data *data)
603
{
604
        u8 x;
605
        int timeout = ABIT_UGURU3_WAIT_TIMEOUT;
606
 
607
        while ((x = inb_p(data->addr + ABIT_UGURU3_DATA)) &
608
                        ABIT_UGURU3_STATUS_BUSY) {
609
                timeout--;
610
                if (timeout == 0)
611
                        return x;
612
                /* sleep a bit before our last try, to give the uGuru3 one
613
                   last chance to respond. */
614
                if (timeout == 1)
615
                        msleep(1);
616
        }
617
        return ABIT_UGURU3_SUCCESS;
618
}
619
 
620
/* wait till uguru is ready to be read */
621
static int abituguru3_wait_for_read(struct abituguru3_data *data)
622
{
623
        u8 x;
624
        int timeout = ABIT_UGURU3_WAIT_TIMEOUT;
625
 
626
        while (!((x = inb_p(data->addr + ABIT_UGURU3_DATA)) &
627
                        ABIT_UGURU3_STATUS_READY_FOR_READ)) {
628
                timeout--;
629
                if (timeout == 0)
630
                        return x;
631
                /* sleep a bit before our last try, to give the uGuru3 one
632
                   last chance to respond. */
633
                if (timeout == 1)
634
                        msleep(1);
635
        }
636
        return ABIT_UGURU3_SUCCESS;
637
}
638
 
639
/* This synchronizes us with the uGuru3's protocol state machine, this
640
   must be done before each command. */
641
static int abituguru3_synchronize(struct abituguru3_data *data)
642
{
643
        int x, timeout = ABIT_UGURU3_SYNCHRONIZE_TIMEOUT;
644
 
645
        if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
646
                ABIT_UGURU3_DEBUG("synchronize timeout during initial busy "
647
                        "wait, status: 0x%02x\n", x);
648
                return -EIO;
649
        }
650
 
651
        outb(0x20, data->addr + ABIT_UGURU3_DATA);
652
        if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
653
                ABIT_UGURU3_DEBUG("synchronize timeout after sending 0x20, "
654
                        "status: 0x%02x\n", x);
655
                return -EIO;
656
        }
657
 
658
        outb(0x10, data->addr + ABIT_UGURU3_CMD);
659
        if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
660
                ABIT_UGURU3_DEBUG("synchronize timeout after sending 0x10, "
661
                        "status: 0x%02x\n", x);
662
                return -EIO;
663
        }
664
 
665
        outb(0x00, data->addr + ABIT_UGURU3_CMD);
666
        if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
667
                ABIT_UGURU3_DEBUG("synchronize timeout after sending 0x00, "
668
                        "status: 0x%02x\n", x);
669
                return -EIO;
670
        }
671
 
672
        if ((x = abituguru3_wait_for_read(data)) != ABIT_UGURU3_SUCCESS) {
673
                ABIT_UGURU3_DEBUG("synchronize timeout waiting for read, "
674
                        "status: 0x%02x\n", x);
675
                return -EIO;
676
        }
677
 
678
        while ((x = inb(data->addr + ABIT_UGURU3_CMD)) != 0xAC) {
679
                timeout--;
680
                if (timeout == 0) {
681
                        ABIT_UGURU3_DEBUG("synchronize timeout cmd does not "
682
                                "hold 0xAC after synchronize, cmd: 0x%02x\n",
683
                                x);
684
                        return -EIO;
685
                }
686
                msleep(1);
687
        }
688
        return 0;
689
}
690
 
691
/* Read count bytes from sensor sensor_addr in bank bank_addr and store the
692
   result in buf */
693
static int abituguru3_read(struct abituguru3_data *data, u8 bank, u8 offset,
694
        u8 count, u8 *buf)
695
{
696
        int i, x;
697
 
698
        if ((x = abituguru3_synchronize(data)))
699
                return x;
700
 
701
        outb(0x1A, data->addr + ABIT_UGURU3_DATA);
702
        if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
703
                ABIT_UGURU3_DEBUG("read from 0x%02x:0x%02x timed out after "
704
                        "sending 0x1A, status: 0x%02x\n", (unsigned int)bank,
705
                        (unsigned int)offset, x);
706
                return -EIO;
707
        }
708
 
709
        outb(bank, data->addr + ABIT_UGURU3_CMD);
710
        if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
711
                ABIT_UGURU3_DEBUG("read from 0x%02x:0x%02x timed out after "
712
                        "sending the bank, status: 0x%02x\n",
713
                        (unsigned int)bank, (unsigned int)offset, x);
714
                return -EIO;
715
        }
716
 
717
        outb(offset, data->addr + ABIT_UGURU3_CMD);
718
        if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
719
                ABIT_UGURU3_DEBUG("read from 0x%02x:0x%02x timed out after "
720
                        "sending the offset, status: 0x%02x\n",
721
                        (unsigned int)bank, (unsigned int)offset, x);
722
                return -EIO;
723
        }
724
 
725
        outb(count, data->addr + ABIT_UGURU3_CMD);
726
        if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
727
                ABIT_UGURU3_DEBUG("read from 0x%02x:0x%02x timed out after "
728
                        "sending the count, status: 0x%02x\n",
729
                        (unsigned int)bank, (unsigned int)offset, x);
730
                return -EIO;
731
        }
732
 
733
        for (i = 0; i < count; i++) {
734
                if ((x = abituguru3_wait_for_read(data)) !=
735
                                ABIT_UGURU3_SUCCESS) {
736
                        ABIT_UGURU3_DEBUG("timeout reading byte %d from "
737
                                "0x%02x:0x%02x, status: 0x%02x\n", i,
738
                                (unsigned int)bank, (unsigned int)offset, x);
739
                        break;
740
                }
741
                buf[i] = inb(data->addr + ABIT_UGURU3_CMD);
742
        }
743
        return i;
744
}
745
 
746
/* Sensor settings are stored 1 byte per offset with the bytes
747
   placed add consecutive offsets. */
748
static int abituguru3_read_increment_offset(struct abituguru3_data *data,
749
                                            u8 bank, u8 offset, u8 count,
750
                                            u8 *buf, int offset_count)
751
{
752
        int i, x;
753
 
754
        for (i = 0; i < offset_count; i++)
755
                if ((x = abituguru3_read(data, bank, offset + i, count,
756
                                buf + i * count)) != count)
757
                        return i * count + (i && (x < 0)) ? 0 : x;
758
 
759
        return i * count;
760
}
761
 
762
/* Following are the sysfs callback functions. These functions expect:
763
   sensor_device_attribute_2->index:   index into the data->sensors array
764
   sensor_device_attribute_2->nr:      register offset, bitmask or NA. */
765
static struct abituguru3_data *abituguru3_update_device(struct device *dev);
766
 
767
static ssize_t show_value(struct device *dev,
768
        struct device_attribute *devattr, char *buf)
769
{
770
        int value;
771
        struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
772
        struct abituguru3_data *data = abituguru3_update_device(dev);
773
        const struct abituguru3_sensor_info *sensor;
774
 
775
        if (!data)
776
                return -EIO;
777
 
778
        sensor = &data->sensors[attr->index];
779
 
780
        /* are we reading a setting, or is this a normal read? */
781
        if (attr->nr)
782
                value = data->settings[sensor->port][attr->nr];
783
        else
784
                value = data->value[sensor->port];
785
 
786
        /* convert the value */
787
        value = (value * sensor->multiplier) / sensor->divisor +
788
                sensor->offset;
789
 
790
        /* alternatively we could update the sensors settings struct for this,
791
           but then its contents would differ from the windows sw ini files */
792
        if (sensor->type == ABIT_UGURU3_TEMP_SENSOR)
793
                value *= 1000;
794
 
795
        return sprintf(buf, "%d\n", value);
796
}
797
 
798
static ssize_t show_alarm(struct device *dev,
799
        struct device_attribute *devattr, char *buf)
800
{
801
        int port;
802
        struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
803
        struct abituguru3_data *data = abituguru3_update_device(dev);
804
 
805
        if (!data)
806
                return -EIO;
807
 
808
        port = data->sensors[attr->index].port;
809
 
810
        /* See if the alarm bit for this sensor is set and if a bitmask is
811
           given in attr->nr also check if the alarm matches the type of alarm
812
           we're looking for (for volt it can be either low or high). The type
813
           is stored in a few readonly bits in the settings of the sensor. */
814
        if ((data->alarms[port / 8] & (0x01 << (port % 8))) &&
815
                        (!attr->nr || (data->settings[port][0] & attr->nr)))
816
                return sprintf(buf, "1\n");
817
        else
818
                return sprintf(buf, "0\n");
819
}
820
 
821
static ssize_t show_mask(struct device *dev,
822
        struct device_attribute *devattr, char *buf)
823
{
824
        struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
825
        struct abituguru3_data *data = dev_get_drvdata(dev);
826
 
827
        if (data->settings[data->sensors[attr->index].port][0] & attr->nr)
828
                return sprintf(buf, "1\n");
829
        else
830
                return sprintf(buf, "0\n");
831
}
832
 
833
static ssize_t show_label(struct device *dev,
834
        struct device_attribute *devattr, char *buf)
835
{
836
        struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
837
        struct abituguru3_data *data = dev_get_drvdata(dev);
838
 
839
        return sprintf(buf, "%s\n", data->sensors[attr->index].name);
840
}
841
 
842
static ssize_t show_name(struct device *dev,
843
        struct device_attribute *devattr, char *buf)
844
{
845
        return sprintf(buf, "%s\n", ABIT_UGURU3_NAME);
846
}
847
 
848
/* Sysfs attr templates, the real entries are generated automatically. */
849
static const
850
struct sensor_device_attribute_2 abituguru3_sysfs_templ[3][10] = { {
851
        SENSOR_ATTR_2(in%d_input, 0444, show_value, NULL, 0, 0),
852
        SENSOR_ATTR_2(in%d_min, 0444, show_value, NULL, 1, 0),
853
        SENSOR_ATTR_2(in%d_max, 0444, show_value, NULL, 2, 0),
854
        SENSOR_ATTR_2(in%d_min_alarm, 0444, show_alarm, NULL,
855
                ABIT_UGURU3_VOLT_LOW_ALARM_FLAG, 0),
856
        SENSOR_ATTR_2(in%d_max_alarm, 0444, show_alarm, NULL,
857
                ABIT_UGURU3_VOLT_HIGH_ALARM_FLAG, 0),
858
        SENSOR_ATTR_2(in%d_beep, 0444, show_mask, NULL,
859
                ABIT_UGURU3_BEEP_ENABLE, 0),
860
        SENSOR_ATTR_2(in%d_shutdown, 0444, show_mask, NULL,
861
                ABIT_UGURU3_SHUTDOWN_ENABLE, 0),
862
        SENSOR_ATTR_2(in%d_min_alarm_enable, 0444, show_mask, NULL,
863
                ABIT_UGURU3_VOLT_LOW_ALARM_ENABLE, 0),
864
        SENSOR_ATTR_2(in%d_max_alarm_enable, 0444, show_mask, NULL,
865
                ABIT_UGURU3_VOLT_HIGH_ALARM_ENABLE, 0),
866
        SENSOR_ATTR_2(in%d_label, 0444, show_label, NULL, 0, 0)
867
        }, {
868
        SENSOR_ATTR_2(temp%d_input, 0444, show_value, NULL, 0, 0),
869
        SENSOR_ATTR_2(temp%d_max, 0444, show_value, NULL, 1, 0),
870
        SENSOR_ATTR_2(temp%d_crit, 0444, show_value, NULL, 2, 0),
871
        SENSOR_ATTR_2(temp%d_alarm, 0444, show_alarm, NULL, 0, 0),
872
        SENSOR_ATTR_2(temp%d_beep, 0444, show_mask, NULL,
873
                ABIT_UGURU3_BEEP_ENABLE, 0),
874
        SENSOR_ATTR_2(temp%d_shutdown, 0444, show_mask, NULL,
875
                ABIT_UGURU3_SHUTDOWN_ENABLE, 0),
876
        SENSOR_ATTR_2(temp%d_alarm_enable, 0444, show_mask, NULL,
877
                ABIT_UGURU3_TEMP_HIGH_ALARM_ENABLE, 0),
878
        SENSOR_ATTR_2(temp%d_label, 0444, show_label, NULL, 0, 0)
879
        }, {
880
        SENSOR_ATTR_2(fan%d_input, 0444, show_value, NULL, 0, 0),
881
        SENSOR_ATTR_2(fan%d_min, 0444, show_value, NULL, 1, 0),
882
        SENSOR_ATTR_2(fan%d_alarm, 0444, show_alarm, NULL, 0, 0),
883
        SENSOR_ATTR_2(fan%d_beep, 0444, show_mask, NULL,
884
                ABIT_UGURU3_BEEP_ENABLE, 0),
885
        SENSOR_ATTR_2(fan%d_shutdown, 0444, show_mask, NULL,
886
                ABIT_UGURU3_SHUTDOWN_ENABLE, 0),
887
        SENSOR_ATTR_2(fan%d_alarm_enable, 0444, show_mask, NULL,
888
                ABIT_UGURU3_FAN_LOW_ALARM_ENABLE, 0),
889
        SENSOR_ATTR_2(fan%d_label, 0444, show_label, NULL, 0, 0)
890
} };
891
 
892
static struct sensor_device_attribute_2 abituguru3_sysfs_attr[] = {
893
        SENSOR_ATTR_2(name, 0444, show_name, NULL, 0, 0),
894
};
895
 
896
static int __devinit abituguru3_probe(struct platform_device *pdev)
897
{
898
        const int no_sysfs_attr[3] = { 10, 8, 7 };
899
        int sensor_index[3] = { 0, 1, 1 };
900
        struct abituguru3_data *data;
901
        int i, j, type, used, sysfs_names_free, sysfs_attr_i, res = -ENODEV;
902
        char *sysfs_filename;
903
        u8 buf[2];
904
        u16 id;
905
 
906
        if (!(data = kzalloc(sizeof(struct abituguru3_data), GFP_KERNEL)))
907
                return -ENOMEM;
908
 
909
        data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
910
        mutex_init(&data->update_lock);
911
        platform_set_drvdata(pdev, data);
912
 
913
        /* Read the motherboard ID */
914
        if ((i = abituguru3_read(data, ABIT_UGURU3_MISC_BANK,
915
                        ABIT_UGURU3_BOARD_ID, 2, buf)) != 2) {
916
                goto abituguru3_probe_error;
917
        }
918
 
919
        /* Completely read the uGuru to see if one really is there */
920
        if (!abituguru3_update_device(&pdev->dev))
921
                goto abituguru3_probe_error;
922
 
923
        /* lookup the ID in our motherboard table */
924
        id = ((u16)buf[0] << 8) | (u16)buf[1];
925
        for (i = 0; abituguru3_motherboards[i].id; i++)
926
                if (abituguru3_motherboards[i].id == id)
927
                        break;
928
        if (!abituguru3_motherboards[i].id) {
929
                printk(KERN_ERR ABIT_UGURU3_NAME ": error unknown motherboard "
930
                        "ID: %04X. Please report this to the abituguru3 "
931
                        "maintainer (see MAINTAINERS)\n", (unsigned int)id);
932
                goto abituguru3_probe_error;
933
        }
934
        data->sensors = abituguru3_motherboards[i].sensors;
935
        printk(KERN_INFO ABIT_UGURU3_NAME ": found Abit uGuru3, motherboard "
936
                "ID: %04X (%s)\n", (unsigned int)id,
937
                abituguru3_motherboards[i].name);
938
 
939
        /* Fill the sysfs attr array */
940
        sysfs_attr_i = 0;
941
        sysfs_filename = data->sysfs_names;
942
        sysfs_names_free = ABIT_UGURU3_SYSFS_NAMES_LENGTH;
943
        for (i = 0; data->sensors[i].name; i++) {
944
                /* Fail safe check, this should never happen! */
945
                if (i >= ABIT_UGURU3_MAX_NO_SENSORS) {
946
                        printk(KERN_ERR ABIT_UGURU3_NAME
947
                                ": Fatal error motherboard has more sensors "
948
                                "then ABIT_UGURU3_MAX_NO_SENSORS. This should "
949
                                "never happen please report to the abituguru3 "
950
                                "maintainer (see MAINTAINERS)\n");
951
                        res = -ENAMETOOLONG;
952
                        goto abituguru3_probe_error;
953
                }
954
                type = data->sensors[i].type;
955
                for (j = 0; j < no_sysfs_attr[type]; j++) {
956
                        used = snprintf(sysfs_filename, sysfs_names_free,
957
                                abituguru3_sysfs_templ[type][j].dev_attr.attr.
958
                                name, sensor_index[type]) + 1;
959
                        data->sysfs_attr[sysfs_attr_i] =
960
                                abituguru3_sysfs_templ[type][j];
961
                        data->sysfs_attr[sysfs_attr_i].dev_attr.attr.name =
962
                                sysfs_filename;
963
                        data->sysfs_attr[sysfs_attr_i].index = i;
964
                        sysfs_filename += used;
965
                        sysfs_names_free -= used;
966
                        sysfs_attr_i++;
967
                }
968
                sensor_index[type]++;
969
        }
970
        /* Fail safe check, this should never happen! */
971
        if (sysfs_names_free < 0) {
972
                printk(KERN_ERR ABIT_UGURU3_NAME
973
                        ": Fatal error ran out of space for sysfs attr names. "
974
                        "This should never happen please report to the "
975
                        "abituguru3 maintainer (see MAINTAINERS)\n");
976
                res = -ENAMETOOLONG;
977
                goto abituguru3_probe_error;
978
        }
979
 
980
        /* Register sysfs hooks */
981
        for (i = 0; i < sysfs_attr_i; i++)
982
                if (device_create_file(&pdev->dev,
983
                                &data->sysfs_attr[i].dev_attr))
984
                        goto abituguru3_probe_error;
985
        for (i = 0; i < ARRAY_SIZE(abituguru3_sysfs_attr); i++)
986
                if (device_create_file(&pdev->dev,
987
                                &abituguru3_sysfs_attr[i].dev_attr))
988
                        goto abituguru3_probe_error;
989
 
990
        data->hwmon_dev = hwmon_device_register(&pdev->dev);
991
        if (IS_ERR(data->hwmon_dev)) {
992
                res = PTR_ERR(data->hwmon_dev);
993
                goto abituguru3_probe_error;
994
        }
995
 
996
        return 0; /* success */
997
 
998
abituguru3_probe_error:
999
        for (i = 0; data->sysfs_attr[i].dev_attr.attr.name; i++)
1000
                device_remove_file(&pdev->dev, &data->sysfs_attr[i].dev_attr);
1001
        for (i = 0; i < ARRAY_SIZE(abituguru3_sysfs_attr); i++)
1002
                device_remove_file(&pdev->dev,
1003
                        &abituguru3_sysfs_attr[i].dev_attr);
1004
        kfree(data);
1005
        return res;
1006
}
1007
 
1008
static int __devexit abituguru3_remove(struct platform_device *pdev)
1009
{
1010
        int i;
1011
        struct abituguru3_data *data = platform_get_drvdata(pdev);
1012
 
1013
        platform_set_drvdata(pdev, NULL);
1014
        hwmon_device_unregister(data->hwmon_dev);
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
 
1022
        return 0;
1023
}
1024
 
1025
static struct abituguru3_data *abituguru3_update_device(struct device *dev)
1026
{
1027
        int i;
1028
        struct abituguru3_data *data = dev_get_drvdata(dev);
1029
 
1030
        mutex_lock(&data->update_lock);
1031
        if (!data->valid || time_after(jiffies, data->last_updated + HZ)) {
1032
                /* Clear data->valid while updating */
1033
                data->valid = 0;
1034
                /* Read alarms */
1035
                if (abituguru3_read_increment_offset(data,
1036
                                ABIT_UGURU3_SETTINGS_BANK,
1037
                                ABIT_UGURU3_ALARMS_START,
1038
                                1, data->alarms, 48/8) != (48/8))
1039
                        goto LEAVE_UPDATE;
1040
                /* Read in and temp sensors (3 byte settings / sensor) */
1041
                for (i = 0; i < 32; i++) {
1042
                        if (abituguru3_read(data, ABIT_UGURU3_SENSORS_BANK,
1043
                                        ABIT_UGURU3_VALUES_START + i,
1044
                                        1, &data->value[i]) != 1)
1045
                                goto LEAVE_UPDATE;
1046
                        if (abituguru3_read_increment_offset(data,
1047
                                        ABIT_UGURU3_SETTINGS_BANK,
1048
                                        ABIT_UGURU3_SETTINGS_START + i * 3,
1049
                                        1,
1050
                                        data->settings[i], 3) != 3)
1051
                                goto LEAVE_UPDATE;
1052
                }
1053
                /* Read temp sensors (2 byte settings / sensor) */
1054
                for (i = 0; i < 16; i++) {
1055
                        if (abituguru3_read(data, ABIT_UGURU3_SENSORS_BANK,
1056
                                        ABIT_UGURU3_VALUES_START + 32 + i,
1057
                                        1, &data->value[32 + i]) != 1)
1058
                                goto LEAVE_UPDATE;
1059
                        if (abituguru3_read_increment_offset(data,
1060
                                        ABIT_UGURU3_SETTINGS_BANK,
1061
                                        ABIT_UGURU3_SETTINGS_START + 32 * 3 +
1062
                                                i * 2, 1,
1063
                                        data->settings[32 + i], 2) != 2)
1064
                                goto LEAVE_UPDATE;
1065
                }
1066
                data->last_updated = jiffies;
1067
                data->valid = 1;
1068
        }
1069
LEAVE_UPDATE:
1070
        mutex_unlock(&data->update_lock);
1071
        if (data->valid)
1072
                return data;
1073
        else
1074
                return NULL;
1075
}
1076
 
1077
#ifdef CONFIG_PM
1078
static int abituguru3_suspend(struct platform_device *pdev, pm_message_t state)
1079
{
1080
        struct abituguru3_data *data = platform_get_drvdata(pdev);
1081
        /* make sure all communications with the uguru3 are done and no new
1082
           ones are started */
1083
        mutex_lock(&data->update_lock);
1084
        return 0;
1085
}
1086
 
1087
static int abituguru3_resume(struct platform_device *pdev)
1088
{
1089
        struct abituguru3_data *data = platform_get_drvdata(pdev);
1090
        mutex_unlock(&data->update_lock);
1091
        return 0;
1092
}
1093
#else
1094
#define abituguru3_suspend      NULL
1095
#define abituguru3_resume       NULL
1096
#endif /* CONFIG_PM */
1097
 
1098
static struct platform_driver abituguru3_driver = {
1099
        .driver = {
1100
                .owner  = THIS_MODULE,
1101
                .name   = ABIT_UGURU3_NAME,
1102
        },
1103
        .probe  = abituguru3_probe,
1104
        .remove = __devexit_p(abituguru3_remove),
1105
        .suspend = abituguru3_suspend,
1106
        .resume = abituguru3_resume
1107
};
1108
 
1109
static int __init abituguru3_detect(void)
1110
{
1111
        /* See if there is an uguru3 there. An idle uGuru3 will hold 0x00 or
1112
           0x08 at DATA and 0xAC at CMD. Sometimes the uGuru3 will hold 0x05
1113
           at CMD instead, why is unknown. So we test for 0x05 too. */
1114
        u8 data_val = inb_p(ABIT_UGURU3_BASE + ABIT_UGURU3_DATA);
1115
        u8 cmd_val = inb_p(ABIT_UGURU3_BASE + ABIT_UGURU3_CMD);
1116
        if (((data_val == 0x00) || (data_val == 0x08)) &&
1117
                        ((cmd_val == 0xAC) || (cmd_val == 0x05)))
1118
                return ABIT_UGURU3_BASE;
1119
 
1120
        ABIT_UGURU3_DEBUG("no Abit uGuru3 found, data = 0x%02X, cmd = "
1121
                "0x%02X\n", (unsigned int)data_val, (unsigned int)cmd_val);
1122
 
1123
        if (force) {
1124
                printk(KERN_INFO ABIT_UGURU3_NAME ": Assuming Abit uGuru3 is "
1125
                                "present because of \"force\" parameter\n");
1126
                return ABIT_UGURU3_BASE;
1127
        }
1128
 
1129
        /* No uGuru3 found */
1130
        return -ENODEV;
1131
}
1132
 
1133
static struct platform_device *abituguru3_pdev;
1134
 
1135
static int __init abituguru3_init(void)
1136
{
1137
        int address, err;
1138
        struct resource res = { .flags = IORESOURCE_IO };
1139
 
1140
        address = abituguru3_detect();
1141
        if (address < 0)
1142
                return address;
1143
 
1144
        err = platform_driver_register(&abituguru3_driver);
1145
        if (err)
1146
                goto exit;
1147
 
1148
        abituguru3_pdev = platform_device_alloc(ABIT_UGURU3_NAME, address);
1149
        if (!abituguru3_pdev) {
1150
                printk(KERN_ERR ABIT_UGURU3_NAME
1151
                        ": Device allocation failed\n");
1152
                err = -ENOMEM;
1153
                goto exit_driver_unregister;
1154
        }
1155
 
1156
        res.start = address;
1157
        res.end = address + ABIT_UGURU3_REGION_LENGTH - 1;
1158
        res.name = ABIT_UGURU3_NAME;
1159
 
1160
        err = platform_device_add_resources(abituguru3_pdev, &res, 1);
1161
        if (err) {
1162
                printk(KERN_ERR ABIT_UGURU3_NAME
1163
                        ": Device resource addition failed (%d)\n", err);
1164
                goto exit_device_put;
1165
        }
1166
 
1167
        err = platform_device_add(abituguru3_pdev);
1168
        if (err) {
1169
                printk(KERN_ERR ABIT_UGURU3_NAME
1170
                        ": Device addition failed (%d)\n", err);
1171
                goto exit_device_put;
1172
        }
1173
 
1174
        return 0;
1175
 
1176
exit_device_put:
1177
        platform_device_put(abituguru3_pdev);
1178
exit_driver_unregister:
1179
        platform_driver_unregister(&abituguru3_driver);
1180
exit:
1181
        return err;
1182
}
1183
 
1184
static void __exit abituguru3_exit(void)
1185
{
1186
        platform_device_unregister(abituguru3_pdev);
1187
        platform_driver_unregister(&abituguru3_driver);
1188
}
1189
 
1190
MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>");
1191
MODULE_DESCRIPTION("Abit uGuru3 Sensor device");
1192
MODULE_LICENSE("GPL");
1193
 
1194
module_init(abituguru3_init);
1195
module_exit(abituguru3_exit);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.