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