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