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