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