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