Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * abituguru3.c
0004  *
0005  * Copyright (c) 2006-2008 Hans de Goede <hdegoede@redhat.com>
0006  * Copyright (c) 2008 Alistair John Strachan <alistair@devzero.co.uk>
0007  */
0008 /*
0009  * This driver supports the sensor part of revision 3 of the custom Abit uGuru
0010  * chip found on newer Abit uGuru motherboards. Note: because of lack of specs
0011  * only reading the sensors and their settings is supported.
0012  */
0013 
0014 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0015 
0016 #include <linux/module.h>
0017 #include <linux/init.h>
0018 #include <linux/slab.h>
0019 #include <linux/jiffies.h>
0020 #include <linux/mutex.h>
0021 #include <linux/err.h>
0022 #include <linux/delay.h>
0023 #include <linux/platform_device.h>
0024 #include <linux/hwmon.h>
0025 #include <linux/hwmon-sysfs.h>
0026 #include <linux/dmi.h>
0027 #include <linux/io.h>
0028 
0029 /* uGuru3 bank addresses */
0030 #define ABIT_UGURU3_SETTINGS_BANK       0x01
0031 #define ABIT_UGURU3_SENSORS_BANK        0x08
0032 #define ABIT_UGURU3_MISC_BANK           0x09
0033 #define ABIT_UGURU3_ALARMS_START        0x1E
0034 #define ABIT_UGURU3_SETTINGS_START      0x24
0035 #define ABIT_UGURU3_VALUES_START        0x80
0036 #define ABIT_UGURU3_BOARD_ID            0x0A
0037 /* uGuru3 sensor bank flags */               /* Alarm if: */
0038 #define ABIT_UGURU3_TEMP_HIGH_ALARM_ENABLE  0x01 /*  temp over warn */
0039 #define ABIT_UGURU3_VOLT_HIGH_ALARM_ENABLE  0x02 /*  volt over max */
0040 #define ABIT_UGURU3_VOLT_LOW_ALARM_ENABLE   0x04 /*  volt under min */
0041 #define ABIT_UGURU3_TEMP_HIGH_ALARM_FLAG    0x10 /* temp is over warn */
0042 #define ABIT_UGURU3_VOLT_HIGH_ALARM_FLAG    0x20 /* volt is over max */
0043 #define ABIT_UGURU3_VOLT_LOW_ALARM_FLAG     0x40 /* volt is under min */
0044 #define ABIT_UGURU3_FAN_LOW_ALARM_ENABLE    0x01 /*   fan under min */
0045 #define ABIT_UGURU3_BEEP_ENABLE         0x08 /* beep if alarm */
0046 #define ABIT_UGURU3_SHUTDOWN_ENABLE     0x80 /* shutdown if alarm */
0047 /* sensor types */
0048 #define ABIT_UGURU3_IN_SENSOR           0
0049 #define ABIT_UGURU3_TEMP_SENSOR         1
0050 #define ABIT_UGURU3_FAN_SENSOR          2
0051 
0052 /*
0053  * Timeouts / Retries, if these turn out to need a lot of fiddling we could
0054  * convert them to params. Determined by trial and error. I assume this is
0055  * cpu-speed independent, since the ISA-bus and not the CPU should be the
0056  * bottleneck.
0057  */
0058 #define ABIT_UGURU3_WAIT_TIMEOUT        250
0059 /*
0060  * Normally the 0xAC at the end of synchronize() is reported after the
0061  * first read, but sometimes not and we need to poll
0062  */
0063 #define ABIT_UGURU3_SYNCHRONIZE_TIMEOUT     5
0064 /* utility macros */
0065 #define ABIT_UGURU3_NAME            "abituguru3"
0066 #define ABIT_UGURU3_DEBUG(format, arg...)       \
0067     do {                        \
0068         if (verbose)                \
0069             pr_debug(format , ## arg);  \
0070     } while (0)
0071 
0072 /* Macros to help calculate the sysfs_names array length */
0073 #define ABIT_UGURU3_MAX_NO_SENSORS 26
0074 /*
0075  * sum of strlen +1 of: in??_input\0, in??_{min,max}\0, in??_{min,max}_alarm\0,
0076  * in??_{min,max}_alarm_enable\0, in??_beep\0, in??_shutdown\0, in??_label\0
0077  */
0078 #define ABIT_UGURU3_IN_NAMES_LENGTH \
0079                 (11 + 2 * 9 + 2 * 15 + 2 * 22 + 10 + 14 + 11)
0080 /*
0081  * sum of strlen +1 of: temp??_input\0, temp??_max\0, temp??_crit\0,
0082  * temp??_alarm\0, temp??_alarm_enable\0, temp??_beep\0, temp??_shutdown\0,
0083  * temp??_label\0
0084  */
0085 #define ABIT_UGURU3_TEMP_NAMES_LENGTH (13 + 11 + 12 + 13 + 20 + 12 + 16 + 13)
0086 /*
0087  * sum of strlen +1 of: fan??_input\0, fan??_min\0, fan??_alarm\0,
0088  * fan??_alarm_enable\0, fan??_beep\0, fan??_shutdown\0, fan??_label\0
0089  */
0090 #define ABIT_UGURU3_FAN_NAMES_LENGTH (12 + 10 + 12 + 19 + 11 + 15 + 12)
0091 /*
0092  * Worst case scenario 16 in sensors (longest names_length) and the rest
0093  * temp sensors (second longest names_length).
0094  */
0095 #define ABIT_UGURU3_SYSFS_NAMES_LENGTH (16 * ABIT_UGURU3_IN_NAMES_LENGTH + \
0096     (ABIT_UGURU3_MAX_NO_SENSORS - 16) * ABIT_UGURU3_TEMP_NAMES_LENGTH)
0097 
0098 /*
0099  * All the macros below are named identical to the openguru2 program
0100  * reverse engineered by Louis Kruger, hence the names might not be 100%
0101  * logical. I could come up with better names, but I prefer keeping the names
0102  * identical so that this driver can be compared with his work more easily.
0103  */
0104 /* Two i/o-ports are used by uGuru */
0105 #define ABIT_UGURU3_BASE            0x00E0
0106 #define ABIT_UGURU3_CMD             0x00
0107 #define ABIT_UGURU3_DATA            0x04
0108 #define ABIT_UGURU3_REGION_LENGTH       5
0109 /*
0110  * The wait_xxx functions return this on success and the last contents
0111  * of the DATA register (0-255) on failure.
0112  */
0113 #define ABIT_UGURU3_SUCCESS         -1
0114 /* uGuru status flags */
0115 #define ABIT_UGURU3_STATUS_READY_FOR_READ   0x01
0116 #define ABIT_UGURU3_STATUS_BUSY         0x02
0117 
0118 
0119 /* Structures */
0120 struct abituguru3_sensor_info {
0121     const char *name;
0122     int port;
0123     int type;
0124     int multiplier;
0125     int divisor;
0126     int offset;
0127 };
0128 
0129 /* Avoid use of flexible array members */
0130 #define ABIT_UGURU3_MAX_DMI_NAMES 2
0131 
0132 struct abituguru3_motherboard_info {
0133     u16 id;
0134     const char *dmi_name[ABIT_UGURU3_MAX_DMI_NAMES + 1];
0135     /* + 1 -> end of sensors indicated by a sensor with name == NULL */
0136     struct abituguru3_sensor_info sensors[ABIT_UGURU3_MAX_NO_SENSORS + 1];
0137 };
0138 
0139 /*
0140  * For the Abit uGuru, we need to keep some data in memory.
0141  * The structure is dynamically allocated, at the same time when a new
0142  * abituguru3 device is allocated.
0143  */
0144 struct abituguru3_data {
0145     struct device *hwmon_dev;   /* hwmon registered device */
0146     struct mutex update_lock;   /* protect access to data and uGuru */
0147     unsigned short addr;        /* uguru base address */
0148     bool valid;         /* true if following fields are valid */
0149     unsigned long last_updated; /* In jiffies */
0150 
0151     /*
0152      * For convenience the sysfs attr and their names are generated
0153      * automatically. We have max 10 entries per sensor (for in sensors)
0154      */
0155     struct sensor_device_attribute_2 sysfs_attr[ABIT_UGURU3_MAX_NO_SENSORS
0156         * 10];
0157 
0158     /* Buffer to store the dynamically generated sysfs names */
0159     char sysfs_names[ABIT_UGURU3_SYSFS_NAMES_LENGTH];
0160 
0161     /* Pointer to the sensors info for the detected motherboard */
0162     const struct abituguru3_sensor_info *sensors;
0163 
0164     /*
0165      * The abituguru3 supports up to 48 sensors, and thus has registers
0166      * sets for 48 sensors, for convenience reasons / simplicity of the
0167      * code we always read and store all registers for all 48 sensors
0168      */
0169 
0170     /* Alarms for all 48 sensors (1 bit per sensor) */
0171     u8 alarms[48/8];
0172 
0173     /* Value of all 48 sensors */
0174     u8 value[48];
0175 
0176     /*
0177      * Settings of all 48 sensors, note in and temp sensors (the first 32
0178      * sensors) have 3 bytes of settings, while fans only have 2 bytes,
0179      * for convenience we use 3 bytes for all sensors
0180      */
0181     u8 settings[48][3];
0182 };
0183 
0184 
0185 /* Constants */
0186 static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
0187     { 0x000C, { NULL } /* Unknown, need DMI string */, {
0188         { "CPU Core",        0, 0, 10, 1, 0 },
0189         { "DDR",         1, 0, 10, 1, 0 },
0190         { "DDR VTT",         2, 0, 10, 1, 0 },
0191         { "CPU VTT 1.2V",    3, 0, 10, 1, 0 },
0192         { "MCH & PCIE 1.5V",     4, 0, 10, 1, 0 },
0193         { "MCH 2.5V",        5, 0, 20, 1, 0 },
0194         { "ICH 1.05V",       6, 0, 10, 1, 0 },
0195         { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
0196         { "ATX +12V (4-pin)",    8, 0, 60, 1, 0 },
0197         { "ATX +5V",         9, 0, 30, 1, 0 },
0198         { "+3.3V",      10, 0, 20, 1, 0 },
0199         { "5VSB",       11, 0, 30, 1, 0 },
0200         { "CPU",        24, 1, 1, 1, 0 },
0201         { "System",     25, 1, 1, 1, 0 },
0202         { "PWM",        26, 1, 1, 1, 0 },
0203         { "CPU Fan",        32, 2, 60, 1, 0 },
0204         { "NB Fan",     33, 2, 60, 1, 0 },
0205         { "SYS FAN",        34, 2, 60, 1, 0 },
0206         { "AUX1 Fan",       35, 2, 60, 1, 0 },
0207         { NULL, 0, 0, 0, 0, 0 } }
0208     },
0209     { 0x000D, { NULL } /* Abit AW8, need DMI string */, {
0210         { "CPU Core",        0, 0, 10, 1, 0 },
0211         { "DDR",         1, 0, 10, 1, 0 },
0212         { "DDR VTT",         2, 0, 10, 1, 0 },
0213         { "CPU VTT 1.2V",    3, 0, 10, 1, 0 },
0214         { "MCH & PCIE 1.5V",     4, 0, 10, 1, 0 },
0215         { "MCH 2.5V",        5, 0, 20, 1, 0 },
0216         { "ICH 1.05V",       6, 0, 10, 1, 0 },
0217         { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
0218         { "ATX +12V (4-pin)",    8, 0, 60, 1, 0 },
0219         { "ATX +5V",         9, 0, 30, 1, 0 },
0220         { "+3.3V",      10, 0, 20, 1, 0 },
0221         { "5VSB",       11, 0, 30, 1, 0 },
0222         { "CPU",        24, 1, 1, 1, 0 },
0223         { "System",     25, 1, 1, 1, 0 },
0224         { "PWM1",       26, 1, 1, 1, 0 },
0225         { "PWM2",       27, 1, 1, 1, 0 },
0226         { "PWM3",       28, 1, 1, 1, 0 },
0227         { "PWM4",       29, 1, 1, 1, 0 },
0228         { "CPU Fan",        32, 2, 60, 1, 0 },
0229         { "NB Fan",     33, 2, 60, 1, 0 },
0230         { "SYS Fan",        34, 2, 60, 1, 0 },
0231         { "AUX1 Fan",       35, 2, 60, 1, 0 },
0232         { "AUX2 Fan",       36, 2, 60, 1, 0 },
0233         { "AUX3 Fan",       37, 2, 60, 1, 0 },
0234         { "AUX4 Fan",       38, 2, 60, 1, 0 },
0235         { "AUX5 Fan",       39, 2, 60, 1, 0 },
0236         { NULL, 0, 0, 0, 0, 0 } }
0237     },
0238     { 0x000E, { NULL } /* AL-8, need DMI string */, {
0239         { "CPU Core",        0, 0, 10, 1, 0 },
0240         { "DDR",         1, 0, 10, 1, 0 },
0241         { "DDR VTT",         2, 0, 10, 1, 0 },
0242         { "CPU VTT 1.2V",    3, 0, 10, 1, 0 },
0243         { "MCH & PCIE 1.5V",     4, 0, 10, 1, 0 },
0244         { "MCH 2.5V",        5, 0, 20, 1, 0 },
0245         { "ICH 1.05V",       6, 0, 10, 1, 0 },
0246         { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
0247         { "ATX +12V (4-pin)",    8, 0, 60, 1, 0 },
0248         { "ATX +5V",         9, 0, 30, 1, 0 },
0249         { "+3.3V",      10, 0, 20, 1, 0 },
0250         { "5VSB",       11, 0, 30, 1, 0 },
0251         { "CPU",        24, 1, 1, 1, 0 },
0252         { "System",     25, 1, 1, 1, 0 },
0253         { "PWM",        26, 1, 1, 1, 0 },
0254         { "CPU Fan",        32, 2, 60, 1, 0 },
0255         { "NB Fan",     33, 2, 60, 1, 0 },
0256         { "SYS Fan",        34, 2, 60, 1, 0 },
0257         { NULL, 0, 0, 0, 0, 0 } }
0258     },
0259     { 0x000F, { NULL } /* Unknown, need DMI string */, {
0260 
0261         { "CPU Core",        0, 0, 10, 1, 0 },
0262         { "DDR",         1, 0, 10, 1, 0 },
0263         { "DDR VTT",         2, 0, 10, 1, 0 },
0264         { "CPU VTT 1.2V",    3, 0, 10, 1, 0 },
0265         { "MCH & PCIE 1.5V",     4, 0, 10, 1, 0 },
0266         { "MCH 2.5V",        5, 0, 20, 1, 0 },
0267         { "ICH 1.05V",       6, 0, 10, 1, 0 },
0268         { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
0269         { "ATX +12V (4-pin)",    8, 0, 60, 1, 0 },
0270         { "ATX +5V",         9, 0, 30, 1, 0 },
0271         { "+3.3V",      10, 0, 20, 1, 0 },
0272         { "5VSB",       11, 0, 30, 1, 0 },
0273         { "CPU",        24, 1, 1, 1, 0 },
0274         { "System",     25, 1, 1, 1, 0 },
0275         { "PWM",        26, 1, 1, 1, 0 },
0276         { "CPU Fan",        32, 2, 60, 1, 0 },
0277         { "NB Fan",     33, 2, 60, 1, 0 },
0278         { "SYS Fan",        34, 2, 60, 1, 0 },
0279         { NULL, 0, 0, 0, 0, 0 } }
0280     },
0281     { 0x0010, { NULL } /* Abit NI8 SLI GR, need DMI string */, {
0282         { "CPU Core",        0, 0, 10, 1, 0 },
0283         { "DDR",         1, 0, 10, 1, 0 },
0284         { "DDR VTT",         2, 0, 10, 1, 0 },
0285         { "CPU VTT 1.2V",    3, 0, 10, 1, 0 },
0286         { "NB 1.4V",         4, 0, 10, 1, 0 },
0287         { "SB 1.5V",         6, 0, 10, 1, 0 },
0288         { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
0289         { "ATX +12V (4-pin)",    8, 0, 60, 1, 0 },
0290         { "ATX +5V",         9, 0, 30, 1, 0 },
0291         { "+3.3V",      10, 0, 20, 1, 0 },
0292         { "5VSB",       11, 0, 30, 1, 0 },
0293         { "CPU",        24, 1, 1, 1, 0 },
0294         { "SYS",        25, 1, 1, 1, 0 },
0295         { "PWM",        26, 1, 1, 1, 0 },
0296         { "CPU Fan",        32, 2, 60, 1, 0 },
0297         { "NB Fan",     33, 2, 60, 1, 0 },
0298         { "SYS Fan",        34, 2, 60, 1, 0 },
0299         { "AUX1 Fan",       35, 2, 60, 1, 0 },
0300         { "OTES1 Fan",      36, 2, 60, 1, 0 },
0301         { NULL, 0, 0, 0, 0, 0 } }
0302     },
0303     { 0x0011, { "AT8 32X", NULL }, {
0304         { "CPU Core",        0, 0, 10, 1, 0 },
0305         { "DDR",         1, 0, 20, 1, 0 },
0306         { "DDR VTT",         2, 0, 10, 1, 0 },
0307         { "CPU VDDA 2.5V",   6, 0, 20, 1, 0 },
0308         { "NB 1.8V",         4, 0, 10, 1, 0 },
0309         { "NB 1.8V Dual",    5, 0, 10, 1, 0 },
0310         { "HTV 1.2",         3, 0, 10, 1, 0 },
0311         { "PCIE 1.2V",      12, 0, 10, 1, 0 },
0312         { "NB 1.2V",        13, 0, 10, 1, 0 },
0313         { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
0314         { "ATX +12V (4-pin)",    8, 0, 60, 1, 0 },
0315         { "ATX +5V",         9, 0, 30, 1, 0 },
0316         { "+3.3V",      10, 0, 20, 1, 0 },
0317         { "5VSB",       11, 0, 30, 1, 0 },
0318         { "CPU",        24, 1, 1, 1, 0 },
0319         { "NB",         25, 1, 1, 1, 0 },
0320         { "System",     26, 1, 1, 1, 0 },
0321         { "PWM",        27, 1, 1, 1, 0 },
0322         { "CPU Fan",        32, 2, 60, 1, 0 },
0323         { "NB Fan",     33, 2, 60, 1, 0 },
0324         { "SYS Fan",        34, 2, 60, 1, 0 },
0325         { "AUX1 Fan",       35, 2, 60, 1, 0 },
0326         { "AUX2 Fan",       36, 2, 60, 1, 0 },
0327         { "AUX3 Fan",       37, 2, 60, 1, 0 },
0328         { NULL, 0, 0, 0, 0, 0 } }
0329     },
0330     { 0x0012, { NULL } /* Abit AN8 32X, need DMI string */, {
0331         { "CPU Core",        0, 0, 10, 1, 0 },
0332         { "DDR",         1, 0, 20, 1, 0 },
0333         { "DDR VTT",         2, 0, 10, 1, 0 },
0334         { "HyperTransport",  3, 0, 10, 1, 0 },
0335         { "CPU VDDA 2.5V",   5, 0, 20, 1, 0 },
0336         { "NB",          4, 0, 10, 1, 0 },
0337         { "SB",          6, 0, 10, 1, 0 },
0338         { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
0339         { "ATX +12V (4-pin)",    8, 0, 60, 1, 0 },
0340         { "ATX +5V",         9, 0, 30, 1, 0 },
0341         { "+3.3V",      10, 0, 20, 1, 0 },
0342         { "5VSB",       11, 0, 30, 1, 0 },
0343         { "CPU",        24, 1, 1, 1, 0 },
0344         { "SYS",        25, 1, 1, 1, 0 },
0345         { "PWM",        26, 1, 1, 1, 0 },
0346         { "CPU Fan",        32, 2, 60, 1, 0 },
0347         { "NB Fan",     33, 2, 60, 1, 0 },
0348         { "SYS Fan",        34, 2, 60, 1, 0 },
0349         { "AUX1 Fan",       36, 2, 60, 1, 0 },
0350         { NULL, 0, 0, 0, 0, 0 } }
0351     },
0352     { 0x0013, { NULL } /* Abit AW8D, need DMI string */, {
0353         { "CPU Core",        0, 0, 10, 1, 0 },
0354         { "DDR",         1, 0, 10, 1, 0 },
0355         { "DDR VTT",         2, 0, 10, 1, 0 },
0356         { "CPU VTT 1.2V",    3, 0, 10, 1, 0 },
0357         { "MCH & PCIE 1.5V",     4, 0, 10, 1, 0 },
0358         { "MCH 2.5V",        5, 0, 20, 1, 0 },
0359         { "ICH 1.05V",       6, 0, 10, 1, 0 },
0360         { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
0361         { "ATX +12V (4-pin)",    8, 0, 60, 1, 0 },
0362         { "ATX +5V",         9, 0, 30, 1, 0 },
0363         { "+3.3V",      10, 0, 20, 1, 0 },
0364         { "5VSB",       11, 0, 30, 1, 0 },
0365         { "CPU",        24, 1, 1, 1, 0 },
0366         { "System",     25, 1, 1, 1, 0 },
0367         { "PWM1",       26, 1, 1, 1, 0 },
0368         { "PWM2",       27, 1, 1, 1, 0 },
0369         { "PWM3",       28, 1, 1, 1, 0 },
0370         { "PWM4",       29, 1, 1, 1, 0 },
0371         { "CPU Fan",        32, 2, 60, 1, 0 },
0372         { "NB Fan",     33, 2, 60, 1, 0 },
0373         { "SYS Fan",        34, 2, 60, 1, 0 },
0374         { "AUX1 Fan",       35, 2, 60, 1, 0 },
0375         { "AUX2 Fan",       36, 2, 60, 1, 0 },
0376         { "AUX3 Fan",       37, 2, 60, 1, 0 },
0377         { "AUX4 Fan",       38, 2, 60, 1, 0 },
0378         { "AUX5 Fan",       39, 2, 60, 1, 0 },
0379         { NULL, 0, 0, 0, 0, 0 } }
0380     },
0381     { 0x0014, { "AB9", "AB9 Pro", NULL }, {
0382         { "CPU Core",        0, 0, 10, 1, 0 },
0383         { "DDR",         1, 0, 10, 1, 0 },
0384         { "DDR VTT",         2, 0, 10, 1, 0 },
0385         { "CPU VTT 1.2V",    3, 0, 10, 1, 0 },
0386         { "MCH & PCIE 1.5V",     4, 0, 10, 1, 0 },
0387         { "MCH 2.5V",        5, 0, 20, 1, 0 },
0388         { "ICH 1.05V",       6, 0, 10, 1, 0 },
0389         { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
0390         { "ATX +12V (4-pin)",    8, 0, 60, 1, 0 },
0391         { "ATX +5V",         9, 0, 30, 1, 0 },
0392         { "+3.3V",      10, 0, 20, 1, 0 },
0393         { "5VSB",       11, 0, 30, 1, 0 },
0394         { "CPU",        24, 1, 1, 1, 0 },
0395         { "System",     25, 1, 1, 1, 0 },
0396         { "PWM",        26, 1, 1, 1, 0 },
0397         { "CPU Fan",        32, 2, 60, 1, 0 },
0398         { "NB Fan",     33, 2, 60, 1, 0 },
0399         { "SYS Fan",        34, 2, 60, 1, 0 },
0400         { NULL, 0, 0, 0, 0, 0 } }
0401     },
0402     { 0x0015, { NULL } /* Unknown, need DMI string */, {
0403         { "CPU Core",        0, 0, 10, 1, 0 },
0404         { "DDR",         1, 0, 20, 1, 0 },
0405         { "DDR VTT",         2, 0, 10, 1, 0 },
0406         { "HyperTransport",  3, 0, 10, 1, 0 },
0407         { "CPU VDDA 2.5V",   5, 0, 20, 1, 0 },
0408         { "NB",          4, 0, 10, 1, 0 },
0409         { "SB",          6, 0, 10, 1, 0 },
0410         { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
0411         { "ATX +12V (4-pin)",    8, 0, 60, 1, 0 },
0412         { "ATX +5V",         9, 0, 30, 1, 0 },
0413         { "+3.3V",      10, 0, 20, 1, 0 },
0414         { "5VSB",       11, 0, 30, 1, 0 },
0415         { "CPU",        24, 1, 1, 1, 0 },
0416         { "SYS",        25, 1, 1, 1, 0 },
0417         { "PWM",        26, 1, 1, 1, 0 },
0418         { "CPU Fan",        32, 2, 60, 1, 0 },
0419         { "NB Fan",     33, 2, 60, 1, 0 },
0420         { "SYS Fan",        34, 2, 60, 1, 0 },
0421         { "AUX1 Fan",       33, 2, 60, 1, 0 },
0422         { "AUX2 Fan",       35, 2, 60, 1, 0 },
0423         { "AUX3 Fan",       36, 2, 60, 1, 0 },
0424         { NULL, 0, 0, 0, 0, 0 } }
0425     },
0426     { 0x0016, { "AW9D-MAX", NULL }, {
0427         { "CPU Core",        0, 0, 10, 1, 0 },
0428         { "DDR2",        1, 0, 20, 1, 0 },
0429         { "DDR2 VTT",        2, 0, 10, 1, 0 },
0430         { "CPU VTT 1.2V",    3, 0, 10, 1, 0 },
0431         { "MCH & PCIE 1.5V",     4, 0, 10, 1, 0 },
0432         { "MCH 2.5V",        5, 0, 20, 1, 0 },
0433         { "ICH 1.05V",       6, 0, 10, 1, 0 },
0434         { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
0435         { "ATX +12V (4-pin)",    8, 0, 60, 1, 0 },
0436         { "ATX +5V",         9, 0, 30, 1, 0 },
0437         { "+3.3V",      10, 0, 20, 1, 0 },
0438         { "5VSB",       11, 0, 30, 1, 0 },
0439         { "CPU",        24, 1, 1, 1, 0 },
0440         { "System",     25, 1, 1, 1, 0 },
0441         { "PWM1",       26, 1, 1, 1, 0 },
0442         { "PWM2",       27, 1, 1, 1, 0 },
0443         { "PWM3",       28, 1, 1, 1, 0 },
0444         { "PWM4",       29, 1, 1, 1, 0 },
0445         { "CPU Fan",        32, 2, 60, 1, 0 },
0446         { "NB Fan",     33, 2, 60, 1, 0 },
0447         { "SYS Fan",        34, 2, 60, 1, 0 },
0448         { "AUX1 Fan",       35, 2, 60, 1, 0 },
0449         { "AUX2 Fan",       36, 2, 60, 1, 0 },
0450         { "AUX3 Fan",       37, 2, 60, 1, 0 },
0451         { "OTES1 Fan",      38, 2, 60, 1, 0 },
0452         { NULL, 0, 0, 0, 0, 0 } }
0453     },
0454     { 0x0017, { NULL } /* Unknown, need DMI string */, {
0455         { "CPU Core",        0, 0, 10, 1, 0 },
0456         { "DDR2",        1, 0, 20, 1, 0 },
0457         { "DDR2 VTT",        2, 0, 10, 1, 0 },
0458         { "HyperTransport",  3, 0, 10, 1, 0 },
0459         { "CPU VDDA 2.5V",   6, 0, 20, 1, 0 },
0460         { "NB 1.8V",         4, 0, 10, 1, 0 },
0461         { "NB 1.2V ",       13, 0, 10, 1, 0 },
0462         { "SB 1.2V",         5, 0, 10, 1, 0 },
0463         { "PCIE 1.2V",      12, 0, 10, 1, 0 },
0464         { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
0465         { "ATX +12V (4-pin)",    8, 0, 60, 1, 0 },
0466         { "ATX +5V",         9, 0, 30, 1, 0 },
0467         { "ATX +3.3V",      10, 0, 20, 1, 0 },
0468         { "ATX 5VSB",       11, 0, 30, 1, 0 },
0469         { "CPU",        24, 1, 1, 1, 0 },
0470         { "System",     26, 1, 1, 1, 0 },
0471         { "PWM",        27, 1, 1, 1, 0 },
0472         { "CPU FAN",        32, 2, 60, 1, 0 },
0473         { "SYS FAN",        34, 2, 60, 1, 0 },
0474         { "AUX1 FAN",       35, 2, 60, 1, 0 },
0475         { "AUX2 FAN",       36, 2, 60, 1, 0 },
0476         { "AUX3 FAN",       37, 2, 60, 1, 0 },
0477         { NULL, 0, 0, 0, 0, 0 } }
0478     },
0479     { 0x0018, { "AB9 QuadGT", NULL }, {
0480         { "CPU Core",        0, 0, 10, 1, 0 },
0481         { "DDR2",        1, 0, 20, 1, 0 },
0482         { "DDR2 VTT",        2, 0, 10, 1, 0 },
0483         { "CPU VTT",         3, 0, 10, 1, 0 },
0484         { "MCH 1.25V",       4, 0, 10, 1, 0 },
0485         { "ICHIO 1.5V",      5, 0, 10, 1, 0 },
0486         { "ICH 1.05V",       6, 0, 10, 1, 0 },
0487         { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
0488         { "ATX +12V (4-pin)",    8, 0, 60, 1, 0 },
0489         { "ATX +5V",         9, 0, 30, 1, 0 },
0490         { "+3.3V",      10, 0, 20, 1, 0 },
0491         { "5VSB",       11, 0, 30, 1, 0 },
0492         { "CPU",        24, 1, 1, 1, 0 },
0493         { "System",     25, 1, 1, 1, 0 },
0494         { "PWM Phase1",     26, 1, 1, 1, 0 },
0495         { "PWM Phase2",     27, 1, 1, 1, 0 },
0496         { "PWM Phase3",     28, 1, 1, 1, 0 },
0497         { "PWM Phase4",     29, 1, 1, 1, 0 },
0498         { "PWM Phase5",     30, 1, 1, 1, 0 },
0499         { "CPU Fan",        32, 2, 60, 1, 0 },
0500         { "SYS Fan",        34, 2, 60, 1, 0 },
0501         { "AUX1 Fan",       33, 2, 60, 1, 0 },
0502         { "AUX2 Fan",       35, 2, 60, 1, 0 },
0503         { "AUX3 Fan",       36, 2, 60, 1, 0 },
0504         { NULL, 0, 0, 0, 0, 0 } }
0505     },
0506     { 0x0019, { "IN9 32X MAX", NULL }, {
0507         { "CPU Core",        7, 0, 10, 1, 0 },
0508         { "DDR2",       13, 0, 20, 1, 0 },
0509         { "DDR2 VTT",       14, 0, 10, 1, 0 },
0510         { "CPU VTT",         3, 0, 20, 1, 0 },
0511         { "NB 1.2V",         4, 0, 10, 1, 0 },
0512         { "SB 1.5V",         6, 0, 10, 1, 0 },
0513         { "HyperTransport",  5, 0, 10, 1, 0 },
0514         { "ATX +12V (24-Pin)",  12, 0, 60, 1, 0 },
0515         { "ATX +12V (4-pin)",    8, 0, 60, 1, 0 },
0516         { "ATX +5V",         9, 0, 30, 1, 0 },
0517         { "ATX +3.3V",      10, 0, 20, 1, 0 },
0518         { "ATX 5VSB",       11, 0, 30, 1, 0 },
0519         { "CPU",        24, 1, 1, 1, 0 },
0520         { "System",     25, 1, 1, 1, 0 },
0521         { "PWM Phase1",     26, 1, 1, 1, 0 },
0522         { "PWM Phase2",     27, 1, 1, 1, 0 },
0523         { "PWM Phase3",     28, 1, 1, 1, 0 },
0524         { "PWM Phase4",     29, 1, 1, 1, 0 },
0525         { "PWM Phase5",     30, 1, 1, 1, 0 },
0526         { "CPU FAN",        32, 2, 60, 1, 0 },
0527         { "SYS FAN",        34, 2, 60, 1, 0 },
0528         { "AUX1 FAN",       33, 2, 60, 1, 0 },
0529         { "AUX2 FAN",       35, 2, 60, 1, 0 },
0530         { "AUX3 FAN",       36, 2, 60, 1, 0 },
0531         { NULL, 0, 0, 0, 0, 0 } }
0532     },
0533     { 0x001A, { "IP35 Pro", "IP35 Pro XE", NULL }, {
0534         { "CPU Core",        0, 0, 10, 1, 0 },
0535         { "DDR2",        1, 0, 20, 1, 0 },
0536         { "DDR2 VTT",        2, 0, 10, 1, 0 },
0537         { "CPU VTT 1.2V",    3, 0, 10, 1, 0 },
0538         { "MCH 1.25V",       4, 0, 10, 1, 0 },
0539         { "ICHIO 1.5V",      5, 0, 10, 1, 0 },
0540         { "ICH 1.05V",       6, 0, 10, 1, 0 },
0541         { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
0542         { "ATX +12V (8-pin)",    8, 0, 60, 1, 0 },
0543         { "ATX +5V",         9, 0, 30, 1, 0 },
0544         { "+3.3V",      10, 0, 20, 1, 0 },
0545         { "5VSB",       11, 0, 30, 1, 0 },
0546         { "CPU",        24, 1, 1, 1, 0 },
0547         { "System",     25, 1, 1, 1, 0 },
0548         { "PWM",        26, 1, 1, 1, 0 },
0549         { "PWM Phase2",     27, 1, 1, 1, 0 },
0550         { "PWM Phase3",     28, 1, 1, 1, 0 },
0551         { "PWM Phase4",     29, 1, 1, 1, 0 },
0552         { "PWM Phase5",     30, 1, 1, 1, 0 },
0553         { "CPU Fan",        32, 2, 60, 1, 0 },
0554         { "SYS Fan",        34, 2, 60, 1, 0 },
0555         { "AUX1 Fan",       33, 2, 60, 1, 0 },
0556         { "AUX2 Fan",       35, 2, 60, 1, 0 },
0557         { "AUX3 Fan",       36, 2, 60, 1, 0 },
0558         { "AUX4 Fan",       37, 2, 60, 1, 0 },
0559         { NULL, 0, 0, 0, 0, 0 } }
0560     },
0561     { 0x001B, { NULL } /* Unknown, need DMI string */, {
0562         { "CPU Core",        0, 0, 10, 1, 0 },
0563         { "DDR3",        1, 0, 20, 1, 0 },
0564         { "DDR3 VTT",        2, 0, 10, 1, 0 },
0565         { "CPU VTT",         3, 0, 10, 1, 0 },
0566         { "MCH 1.25V",       4, 0, 10, 1, 0 },
0567         { "ICHIO 1.5V",      5, 0, 10, 1, 0 },
0568         { "ICH 1.05V",       6, 0, 10, 1, 0 },
0569         { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
0570         { "ATX +12V (8-pin)",    8, 0, 60, 1, 0 },
0571         { "ATX +5V",         9, 0, 30, 1, 0 },
0572         { "+3.3V",      10, 0, 20, 1, 0 },
0573         { "5VSB",       11, 0, 30, 1, 0 },
0574         { "CPU",        24, 1, 1, 1, 0 },
0575         { "System",     25, 1, 1, 1, 0 },
0576         { "PWM Phase1",     26, 1, 1, 1, 0 },
0577         { "PWM Phase2",     27, 1, 1, 1, 0 },
0578         { "PWM Phase3",     28, 1, 1, 1, 0 },
0579         { "PWM Phase4",     29, 1, 1, 1, 0 },
0580         { "PWM Phase5",     30, 1, 1, 1, 0 },
0581         { "CPU Fan",        32, 2, 60, 1, 0 },
0582         { "SYS Fan",        34, 2, 60, 1, 0 },
0583         { "AUX1 Fan",       33, 2, 60, 1, 0 },
0584         { "AUX2 Fan",       35, 2, 60, 1, 0 },
0585         { "AUX3 Fan",       36, 2, 60, 1, 0 },
0586         { NULL, 0, 0, 0, 0, 0 } }
0587     },
0588     { 0x001C, { "IX38 QuadGT", NULL }, {
0589         { "CPU Core",        0, 0, 10, 1, 0 },
0590         { "DDR2",        1, 0, 20, 1, 0 },
0591         { "DDR2 VTT",        2, 0, 10, 1, 0 },
0592         { "CPU VTT",         3, 0, 10, 1, 0 },
0593         { "MCH 1.25V",       4, 0, 10, 1, 0 },
0594         { "ICHIO 1.5V",      5, 0, 10, 1, 0 },
0595         { "ICH 1.05V",       6, 0, 10, 1, 0 },
0596         { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
0597         { "ATX +12V (8-pin)",    8, 0, 60, 1, 0 },
0598         { "ATX +5V",         9, 0, 30, 1, 0 },
0599         { "+3.3V",      10, 0, 20, 1, 0 },
0600         { "5VSB",       11, 0, 30, 1, 0 },
0601         { "CPU",        24, 1, 1, 1, 0 },
0602         { "System",     25, 1, 1, 1, 0 },
0603         { "PWM Phase1",     26, 1, 1, 1, 0 },
0604         { "PWM Phase2",     27, 1, 1, 1, 0 },
0605         { "PWM Phase3",     28, 1, 1, 1, 0 },
0606         { "PWM Phase4",     29, 1, 1, 1, 0 },
0607         { "PWM Phase5",     30, 1, 1, 1, 0 },
0608         { "CPU Fan",        32, 2, 60, 1, 0 },
0609         { "SYS Fan",        34, 2, 60, 1, 0 },
0610         { "AUX1 Fan",       33, 2, 60, 1, 0 },
0611         { "AUX2 Fan",       35, 2, 60, 1, 0 },
0612         { "AUX3 Fan",       36, 2, 60, 1, 0 },
0613         { NULL, 0, 0, 0, 0, 0 } }
0614     },
0615     { 0x0000, { NULL }, { { NULL, 0, 0, 0, 0, 0 } } }
0616 };
0617 
0618 
0619 /* Insmod parameters */
0620 static bool force;
0621 module_param(force, bool, 0);
0622 MODULE_PARM_DESC(force, "Set to one to force detection.");
0623 /* Default verbose is 1, since this driver is still in the testing phase */
0624 static bool verbose = 1;
0625 module_param(verbose, bool, 0644);
0626 MODULE_PARM_DESC(verbose, "Enable/disable verbose error reporting");
0627 
0628 static const char *never_happen = "This should never happen.";
0629 static const char *report_this =
0630     "Please report this to the abituguru3 maintainer (see MAINTAINERS)";
0631 
0632 /* wait while the uguru is busy (usually after a write) */
0633 static int abituguru3_wait_while_busy(struct abituguru3_data *data)
0634 {
0635     u8 x;
0636     int timeout = ABIT_UGURU3_WAIT_TIMEOUT;
0637 
0638     while ((x = inb_p(data->addr + ABIT_UGURU3_DATA)) &
0639             ABIT_UGURU3_STATUS_BUSY) {
0640         timeout--;
0641         if (timeout == 0)
0642             return x;
0643         /*
0644          * sleep a bit before our last try, to give the uGuru3 one
0645          * last chance to respond.
0646          */
0647         if (timeout == 1)
0648             msleep(1);
0649     }
0650     return ABIT_UGURU3_SUCCESS;
0651 }
0652 
0653 /* wait till uguru is ready to be read */
0654 static int abituguru3_wait_for_read(struct abituguru3_data *data)
0655 {
0656     u8 x;
0657     int timeout = ABIT_UGURU3_WAIT_TIMEOUT;
0658 
0659     while (!((x = inb_p(data->addr + ABIT_UGURU3_DATA)) &
0660             ABIT_UGURU3_STATUS_READY_FOR_READ)) {
0661         timeout--;
0662         if (timeout == 0)
0663             return x;
0664         /*
0665          * sleep a bit before our last try, to give the uGuru3 one
0666          * last chance to respond.
0667          */
0668         if (timeout == 1)
0669             msleep(1);
0670     }
0671     return ABIT_UGURU3_SUCCESS;
0672 }
0673 
0674 /*
0675  * This synchronizes us with the uGuru3's protocol state machine, this
0676  * must be done before each command.
0677  */
0678 static int abituguru3_synchronize(struct abituguru3_data *data)
0679 {
0680     int x, timeout = ABIT_UGURU3_SYNCHRONIZE_TIMEOUT;
0681 
0682     x = abituguru3_wait_while_busy(data);
0683     if (x != ABIT_UGURU3_SUCCESS) {
0684         ABIT_UGURU3_DEBUG("synchronize timeout during initial busy "
0685             "wait, status: 0x%02x\n", x);
0686         return -EIO;
0687     }
0688 
0689     outb(0x20, data->addr + ABIT_UGURU3_DATA);
0690     x = abituguru3_wait_while_busy(data);
0691     if (x != ABIT_UGURU3_SUCCESS) {
0692         ABIT_UGURU3_DEBUG("synchronize timeout after sending 0x20, "
0693             "status: 0x%02x\n", x);
0694         return -EIO;
0695     }
0696 
0697     outb(0x10, data->addr + ABIT_UGURU3_CMD);
0698     x = abituguru3_wait_while_busy(data);
0699     if (x != ABIT_UGURU3_SUCCESS) {
0700         ABIT_UGURU3_DEBUG("synchronize timeout after sending 0x10, "
0701             "status: 0x%02x\n", x);
0702         return -EIO;
0703     }
0704 
0705     outb(0x00, data->addr + ABIT_UGURU3_CMD);
0706     x = abituguru3_wait_while_busy(data);
0707     if (x != ABIT_UGURU3_SUCCESS) {
0708         ABIT_UGURU3_DEBUG("synchronize timeout after sending 0x00, "
0709             "status: 0x%02x\n", x);
0710         return -EIO;
0711     }
0712 
0713     x = abituguru3_wait_for_read(data);
0714     if (x != ABIT_UGURU3_SUCCESS) {
0715         ABIT_UGURU3_DEBUG("synchronize timeout waiting for read, "
0716             "status: 0x%02x\n", x);
0717         return -EIO;
0718     }
0719 
0720     while ((x = inb(data->addr + ABIT_UGURU3_CMD)) != 0xAC) {
0721         timeout--;
0722         if (timeout == 0) {
0723             ABIT_UGURU3_DEBUG("synchronize timeout cmd does not "
0724                 "hold 0xAC after synchronize, cmd: 0x%02x\n",
0725                 x);
0726             return -EIO;
0727         }
0728         msleep(1);
0729     }
0730     return 0;
0731 }
0732 
0733 /*
0734  * Read count bytes from sensor sensor_addr in bank bank_addr and store the
0735  * result in buf
0736  */
0737 static int abituguru3_read(struct abituguru3_data *data, u8 bank, u8 offset,
0738     u8 count, u8 *buf)
0739 {
0740     int i, x;
0741 
0742     x = abituguru3_synchronize(data);
0743     if (x)
0744         return x;
0745 
0746     outb(0x1A, data->addr + ABIT_UGURU3_DATA);
0747     x = abituguru3_wait_while_busy(data);
0748     if (x != ABIT_UGURU3_SUCCESS) {
0749         ABIT_UGURU3_DEBUG("read from 0x%02x:0x%02x timed out after "
0750             "sending 0x1A, status: 0x%02x\n", (unsigned int)bank,
0751             (unsigned int)offset, x);
0752         return -EIO;
0753     }
0754 
0755     outb(bank, data->addr + ABIT_UGURU3_CMD);
0756     x = abituguru3_wait_while_busy(data);
0757     if (x != ABIT_UGURU3_SUCCESS) {
0758         ABIT_UGURU3_DEBUG("read from 0x%02x:0x%02x timed out after "
0759             "sending the bank, status: 0x%02x\n",
0760             (unsigned int)bank, (unsigned int)offset, x);
0761         return -EIO;
0762     }
0763 
0764     outb(offset, data->addr + ABIT_UGURU3_CMD);
0765     x = abituguru3_wait_while_busy(data);
0766     if (x != ABIT_UGURU3_SUCCESS) {
0767         ABIT_UGURU3_DEBUG("read from 0x%02x:0x%02x timed out after "
0768             "sending the offset, status: 0x%02x\n",
0769             (unsigned int)bank, (unsigned int)offset, x);
0770         return -EIO;
0771     }
0772 
0773     outb(count, data->addr + ABIT_UGURU3_CMD);
0774     x = abituguru3_wait_while_busy(data);
0775     if (x != ABIT_UGURU3_SUCCESS) {
0776         ABIT_UGURU3_DEBUG("read from 0x%02x:0x%02x timed out after "
0777             "sending the count, status: 0x%02x\n",
0778             (unsigned int)bank, (unsigned int)offset, x);
0779         return -EIO;
0780     }
0781 
0782     for (i = 0; i < count; i++) {
0783         x = abituguru3_wait_for_read(data);
0784         if (x != ABIT_UGURU3_SUCCESS) {
0785             ABIT_UGURU3_DEBUG("timeout reading byte %d from "
0786                 "0x%02x:0x%02x, status: 0x%02x\n", i,
0787                 (unsigned int)bank, (unsigned int)offset, x);
0788             break;
0789         }
0790         buf[i] = inb(data->addr + ABIT_UGURU3_CMD);
0791     }
0792     return i;
0793 }
0794 
0795 /*
0796  * Sensor settings are stored 1 byte per offset with the bytes
0797  * placed add consecutive offsets.
0798  */
0799 static int abituguru3_read_increment_offset(struct abituguru3_data *data,
0800                         u8 bank, u8 offset, u8 count,
0801                         u8 *buf, int offset_count)
0802 {
0803     int i, x;
0804 
0805     for (i = 0; i < offset_count; i++) {
0806         x = abituguru3_read(data, bank, offset + i, count,
0807                     buf + i * count);
0808         if (x != count) {
0809             if (x < 0)
0810                 return x;
0811             return i * count + x;
0812         }
0813     }
0814 
0815     return i * count;
0816 }
0817 
0818 /*
0819  * Following are the sysfs callback functions. These functions expect:
0820  * sensor_device_attribute_2->index:   index into the data->sensors array
0821  * sensor_device_attribute_2->nr:      register offset, bitmask or NA.
0822  */
0823 static struct abituguru3_data *abituguru3_update_device(struct device *dev);
0824 
0825 static ssize_t show_value(struct device *dev,
0826     struct device_attribute *devattr, char *buf)
0827 {
0828     int value;
0829     struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
0830     struct abituguru3_data *data = abituguru3_update_device(dev);
0831     const struct abituguru3_sensor_info *sensor;
0832 
0833     if (!data)
0834         return -EIO;
0835 
0836     sensor = &data->sensors[attr->index];
0837 
0838     /* are we reading a setting, or is this a normal read? */
0839     if (attr->nr)
0840         value = data->settings[sensor->port][attr->nr];
0841     else
0842         value = data->value[sensor->port];
0843 
0844     /* convert the value */
0845     value = (value * sensor->multiplier) / sensor->divisor +
0846         sensor->offset;
0847 
0848     /*
0849      * alternatively we could update the sensors settings struct for this,
0850      * but then its contents would differ from the windows sw ini files
0851      */
0852     if (sensor->type == ABIT_UGURU3_TEMP_SENSOR)
0853         value *= 1000;
0854 
0855     return sprintf(buf, "%d\n", value);
0856 }
0857 
0858 static ssize_t show_alarm(struct device *dev,
0859     struct device_attribute *devattr, char *buf)
0860 {
0861     int port;
0862     struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
0863     struct abituguru3_data *data = abituguru3_update_device(dev);
0864 
0865     if (!data)
0866         return -EIO;
0867 
0868     port = data->sensors[attr->index].port;
0869 
0870     /*
0871      * See if the alarm bit for this sensor is set and if a bitmask is
0872      * given in attr->nr also check if the alarm matches the type of alarm
0873      * we're looking for (for volt it can be either low or high). The type
0874      * is stored in a few readonly bits in the settings of the sensor.
0875      */
0876     if ((data->alarms[port / 8] & (0x01 << (port % 8))) &&
0877             (!attr->nr || (data->settings[port][0] & attr->nr)))
0878         return sprintf(buf, "1\n");
0879     else
0880         return sprintf(buf, "0\n");
0881 }
0882 
0883 static ssize_t show_mask(struct device *dev,
0884     struct device_attribute *devattr, char *buf)
0885 {
0886     struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
0887     struct abituguru3_data *data = dev_get_drvdata(dev);
0888 
0889     if (data->settings[data->sensors[attr->index].port][0] & attr->nr)
0890         return sprintf(buf, "1\n");
0891     else
0892         return sprintf(buf, "0\n");
0893 }
0894 
0895 static ssize_t show_label(struct device *dev,
0896     struct device_attribute *devattr, char *buf)
0897 {
0898     struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
0899     struct abituguru3_data *data = dev_get_drvdata(dev);
0900 
0901     return sprintf(buf, "%s\n", data->sensors[attr->index].name);
0902 }
0903 
0904 static ssize_t show_name(struct device *dev,
0905     struct device_attribute *devattr, char *buf)
0906 {
0907     return sprintf(buf, "%s\n", ABIT_UGURU3_NAME);
0908 }
0909 
0910 /* Sysfs attr templates, the real entries are generated automatically. */
0911 static const
0912 struct sensor_device_attribute_2 abituguru3_sysfs_templ[3][10] = { {
0913     SENSOR_ATTR_2(in%d_input, 0444, show_value, NULL, 0, 0),
0914     SENSOR_ATTR_2(in%d_min, 0444, show_value, NULL, 1, 0),
0915     SENSOR_ATTR_2(in%d_max, 0444, show_value, NULL, 2, 0),
0916     SENSOR_ATTR_2(in%d_min_alarm, 0444, show_alarm, NULL,
0917         ABIT_UGURU3_VOLT_LOW_ALARM_FLAG, 0),
0918     SENSOR_ATTR_2(in%d_max_alarm, 0444, show_alarm, NULL,
0919         ABIT_UGURU3_VOLT_HIGH_ALARM_FLAG, 0),
0920     SENSOR_ATTR_2(in%d_beep, 0444, show_mask, NULL,
0921         ABIT_UGURU3_BEEP_ENABLE, 0),
0922     SENSOR_ATTR_2(in%d_shutdown, 0444, show_mask, NULL,
0923         ABIT_UGURU3_SHUTDOWN_ENABLE, 0),
0924     SENSOR_ATTR_2(in%d_min_alarm_enable, 0444, show_mask, NULL,
0925         ABIT_UGURU3_VOLT_LOW_ALARM_ENABLE, 0),
0926     SENSOR_ATTR_2(in%d_max_alarm_enable, 0444, show_mask, NULL,
0927         ABIT_UGURU3_VOLT_HIGH_ALARM_ENABLE, 0),
0928     SENSOR_ATTR_2(in%d_label, 0444, show_label, NULL, 0, 0)
0929     }, {
0930     SENSOR_ATTR_2(temp%d_input, 0444, show_value, NULL, 0, 0),
0931     SENSOR_ATTR_2(temp%d_max, 0444, show_value, NULL, 1, 0),
0932     SENSOR_ATTR_2(temp%d_crit, 0444, show_value, NULL, 2, 0),
0933     SENSOR_ATTR_2(temp%d_alarm, 0444, show_alarm, NULL, 0, 0),
0934     SENSOR_ATTR_2(temp%d_beep, 0444, show_mask, NULL,
0935         ABIT_UGURU3_BEEP_ENABLE, 0),
0936     SENSOR_ATTR_2(temp%d_shutdown, 0444, show_mask, NULL,
0937         ABIT_UGURU3_SHUTDOWN_ENABLE, 0),
0938     SENSOR_ATTR_2(temp%d_alarm_enable, 0444, show_mask, NULL,
0939         ABIT_UGURU3_TEMP_HIGH_ALARM_ENABLE, 0),
0940     SENSOR_ATTR_2(temp%d_label, 0444, show_label, NULL, 0, 0)
0941     }, {
0942     SENSOR_ATTR_2(fan%d_input, 0444, show_value, NULL, 0, 0),
0943     SENSOR_ATTR_2(fan%d_min, 0444, show_value, NULL, 1, 0),
0944     SENSOR_ATTR_2(fan%d_alarm, 0444, show_alarm, NULL, 0, 0),
0945     SENSOR_ATTR_2(fan%d_beep, 0444, show_mask, NULL,
0946         ABIT_UGURU3_BEEP_ENABLE, 0),
0947     SENSOR_ATTR_2(fan%d_shutdown, 0444, show_mask, NULL,
0948         ABIT_UGURU3_SHUTDOWN_ENABLE, 0),
0949     SENSOR_ATTR_2(fan%d_alarm_enable, 0444, show_mask, NULL,
0950         ABIT_UGURU3_FAN_LOW_ALARM_ENABLE, 0),
0951     SENSOR_ATTR_2(fan%d_label, 0444, show_label, NULL, 0, 0)
0952 } };
0953 
0954 static struct sensor_device_attribute_2 abituguru3_sysfs_attr[] = {
0955     SENSOR_ATTR_2(name, 0444, show_name, NULL, 0, 0),
0956 };
0957 
0958 static int abituguru3_probe(struct platform_device *pdev)
0959 {
0960     const int no_sysfs_attr[3] = { 10, 8, 7 };
0961     int sensor_index[3] = { 0, 1, 1 };
0962     struct abituguru3_data *data;
0963     int i, j, type, used, sysfs_names_free, sysfs_attr_i, res = -ENODEV;
0964     char *sysfs_filename;
0965     u8 buf[2];
0966     u16 id;
0967 
0968     data = devm_kzalloc(&pdev->dev, sizeof(struct abituguru3_data),
0969                 GFP_KERNEL);
0970     if (!data)
0971         return -ENOMEM;
0972 
0973     data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
0974     mutex_init(&data->update_lock);
0975     platform_set_drvdata(pdev, data);
0976 
0977     /* Read the motherboard ID */
0978     i = abituguru3_read(data, ABIT_UGURU3_MISC_BANK, ABIT_UGURU3_BOARD_ID,
0979                 2, buf);
0980     if (i != 2)
0981         goto abituguru3_probe_error;
0982 
0983     /* Completely read the uGuru to see if one really is there */
0984     if (!abituguru3_update_device(&pdev->dev))
0985         goto abituguru3_probe_error;
0986 
0987     /* lookup the ID in our motherboard table */
0988     id = ((u16)buf[0] << 8) | (u16)buf[1];
0989     for (i = 0; abituguru3_motherboards[i].id; i++)
0990         if (abituguru3_motherboards[i].id == id)
0991             break;
0992     if (!abituguru3_motherboards[i].id) {
0993         pr_err("error unknown motherboard ID: %04X. %s\n",
0994                (unsigned int)id, report_this);
0995         goto abituguru3_probe_error;
0996     }
0997     data->sensors = abituguru3_motherboards[i].sensors;
0998 
0999     pr_info("found Abit uGuru3, motherboard ID: %04X\n", (unsigned int)id);
1000 
1001     /* Fill the sysfs attr array */
1002     sysfs_attr_i = 0;
1003     sysfs_filename = data->sysfs_names;
1004     sysfs_names_free = ABIT_UGURU3_SYSFS_NAMES_LENGTH;
1005     for (i = 0; data->sensors[i].name; i++) {
1006         /* Fail safe check, this should never happen! */
1007         if (i >= ABIT_UGURU3_MAX_NO_SENSORS) {
1008             pr_err("Fatal error motherboard has more sensors then ABIT_UGURU3_MAX_NO_SENSORS. %s %s\n",
1009                    never_happen, report_this);
1010             res = -ENAMETOOLONG;
1011             goto abituguru3_probe_error;
1012         }
1013         type = data->sensors[i].type;
1014         for (j = 0; j < no_sysfs_attr[type]; j++) {
1015             used = snprintf(sysfs_filename, sysfs_names_free,
1016                 abituguru3_sysfs_templ[type][j].dev_attr.attr.
1017                 name, sensor_index[type]) + 1;
1018             data->sysfs_attr[sysfs_attr_i] =
1019                 abituguru3_sysfs_templ[type][j];
1020             data->sysfs_attr[sysfs_attr_i].dev_attr.attr.name =
1021                 sysfs_filename;
1022             data->sysfs_attr[sysfs_attr_i].index = i;
1023             sysfs_filename += used;
1024             sysfs_names_free -= used;
1025             sysfs_attr_i++;
1026         }
1027         sensor_index[type]++;
1028     }
1029     /* Fail safe check, this should never happen! */
1030     if (sysfs_names_free < 0) {
1031         pr_err("Fatal error ran out of space for sysfs attr names. %s %s\n",
1032                never_happen, report_this);
1033         res = -ENAMETOOLONG;
1034         goto abituguru3_probe_error;
1035     }
1036 
1037     /* Register sysfs hooks */
1038     for (i = 0; i < sysfs_attr_i; i++)
1039         if (device_create_file(&pdev->dev,
1040                 &data->sysfs_attr[i].dev_attr))
1041             goto abituguru3_probe_error;
1042     for (i = 0; i < ARRAY_SIZE(abituguru3_sysfs_attr); i++)
1043         if (device_create_file(&pdev->dev,
1044                 &abituguru3_sysfs_attr[i].dev_attr))
1045             goto abituguru3_probe_error;
1046 
1047     data->hwmon_dev = hwmon_device_register(&pdev->dev);
1048     if (IS_ERR(data->hwmon_dev)) {
1049         res = PTR_ERR(data->hwmon_dev);
1050         goto abituguru3_probe_error;
1051     }
1052 
1053     return 0; /* success */
1054 
1055 abituguru3_probe_error:
1056     for (i = 0; data->sysfs_attr[i].dev_attr.attr.name; i++)
1057         device_remove_file(&pdev->dev, &data->sysfs_attr[i].dev_attr);
1058     for (i = 0; i < ARRAY_SIZE(abituguru3_sysfs_attr); i++)
1059         device_remove_file(&pdev->dev,
1060             &abituguru3_sysfs_attr[i].dev_attr);
1061     return res;
1062 }
1063 
1064 static int abituguru3_remove(struct platform_device *pdev)
1065 {
1066     int i;
1067     struct abituguru3_data *data = platform_get_drvdata(pdev);
1068 
1069     hwmon_device_unregister(data->hwmon_dev);
1070     for (i = 0; data->sysfs_attr[i].dev_attr.attr.name; i++)
1071         device_remove_file(&pdev->dev, &data->sysfs_attr[i].dev_attr);
1072     for (i = 0; i < ARRAY_SIZE(abituguru3_sysfs_attr); i++)
1073         device_remove_file(&pdev->dev,
1074             &abituguru3_sysfs_attr[i].dev_attr);
1075     return 0;
1076 }
1077 
1078 static struct abituguru3_data *abituguru3_update_device(struct device *dev)
1079 {
1080     int i;
1081     struct abituguru3_data *data = dev_get_drvdata(dev);
1082 
1083     mutex_lock(&data->update_lock);
1084     if (!data->valid || time_after(jiffies, data->last_updated + HZ)) {
1085         /* Clear data->valid while updating */
1086         data->valid = false;
1087         /* Read alarms */
1088         if (abituguru3_read_increment_offset(data,
1089                 ABIT_UGURU3_SETTINGS_BANK,
1090                 ABIT_UGURU3_ALARMS_START,
1091                 1, data->alarms, 48/8) != (48/8))
1092             goto LEAVE_UPDATE;
1093         /* Read in and temp sensors (3 byte settings / sensor) */
1094         for (i = 0; i < 32; i++) {
1095             if (abituguru3_read(data, ABIT_UGURU3_SENSORS_BANK,
1096                     ABIT_UGURU3_VALUES_START + i,
1097                     1, &data->value[i]) != 1)
1098                 goto LEAVE_UPDATE;
1099             if (abituguru3_read_increment_offset(data,
1100                     ABIT_UGURU3_SETTINGS_BANK,
1101                     ABIT_UGURU3_SETTINGS_START + i * 3,
1102                     1,
1103                     data->settings[i], 3) != 3)
1104                 goto LEAVE_UPDATE;
1105         }
1106         /* Read temp sensors (2 byte settings / sensor) */
1107         for (i = 0; i < 16; i++) {
1108             if (abituguru3_read(data, ABIT_UGURU3_SENSORS_BANK,
1109                     ABIT_UGURU3_VALUES_START + 32 + i,
1110                     1, &data->value[32 + i]) != 1)
1111                 goto LEAVE_UPDATE;
1112             if (abituguru3_read_increment_offset(data,
1113                     ABIT_UGURU3_SETTINGS_BANK,
1114                     ABIT_UGURU3_SETTINGS_START + 32 * 3 +
1115                         i * 2, 1,
1116                     data->settings[32 + i], 2) != 2)
1117                 goto LEAVE_UPDATE;
1118         }
1119         data->last_updated = jiffies;
1120         data->valid = true;
1121     }
1122 LEAVE_UPDATE:
1123     mutex_unlock(&data->update_lock);
1124     if (data->valid)
1125         return data;
1126     else
1127         return NULL;
1128 }
1129 
1130 #ifdef CONFIG_PM_SLEEP
1131 static int abituguru3_suspend(struct device *dev)
1132 {
1133     struct abituguru3_data *data = dev_get_drvdata(dev);
1134     /*
1135      * make sure all communications with the uguru3 are done and no new
1136      * ones are started
1137      */
1138     mutex_lock(&data->update_lock);
1139     return 0;
1140 }
1141 
1142 static int abituguru3_resume(struct device *dev)
1143 {
1144     struct abituguru3_data *data = dev_get_drvdata(dev);
1145     mutex_unlock(&data->update_lock);
1146     return 0;
1147 }
1148 
1149 static SIMPLE_DEV_PM_OPS(abituguru3_pm, abituguru3_suspend, abituguru3_resume);
1150 #define ABIT_UGURU3_PM  (&abituguru3_pm)
1151 #else
1152 #define ABIT_UGURU3_PM  NULL
1153 #endif /* CONFIG_PM */
1154 
1155 static struct platform_driver abituguru3_driver = {
1156     .driver = {
1157         .name   = ABIT_UGURU3_NAME,
1158         .pm = ABIT_UGURU3_PM
1159     },
1160     .probe  = abituguru3_probe,
1161     .remove = abituguru3_remove,
1162 };
1163 
1164 static int __init abituguru3_dmi_detect(void)
1165 {
1166     const char *board_vendor, *board_name;
1167     int i, err = (force) ? 1 : -ENODEV;
1168     const char *const *dmi_name;
1169     size_t sublen;
1170 
1171     board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
1172     if (!board_vendor || strcmp(board_vendor, "http://www.abit.com.tw/"))
1173         return err;
1174 
1175     board_name = dmi_get_system_info(DMI_BOARD_NAME);
1176     if (!board_name)
1177         return err;
1178 
1179     /*
1180      * At the moment, we don't care about the part of the vendor
1181      * DMI string contained in brackets. Truncate the string at
1182      * the first occurrence of a bracket. Trim any trailing space
1183      * from the substring.
1184      */
1185     sublen = strcspn(board_name, "(");
1186     while (sublen > 0 && board_name[sublen - 1] == ' ')
1187         sublen--;
1188 
1189     for (i = 0; abituguru3_motherboards[i].id; i++) {
1190         dmi_name = abituguru3_motherboards[i].dmi_name;
1191         for ( ; *dmi_name; dmi_name++) {
1192             if (strlen(*dmi_name) != sublen)
1193                 continue;
1194             if (!strncasecmp(board_name, *dmi_name, sublen))
1195                 return 0;
1196         }
1197     }
1198 
1199     /* No match found */
1200     return 1;
1201 }
1202 
1203 /*
1204  * FIXME: Manual detection should die eventually; we need to collect stable
1205  *        DMI model names first before we can rely entirely on CONFIG_DMI.
1206  */
1207 
1208 static int __init abituguru3_detect(void)
1209 {
1210     /*
1211      * See if there is an uguru3 there. An idle uGuru3 will hold 0x00 or
1212      * 0x08 at DATA and 0xAC at CMD. Sometimes the uGuru3 will hold 0x05
1213      * or 0x55 at CMD instead, why is unknown.
1214      */
1215     u8 data_val = inb_p(ABIT_UGURU3_BASE + ABIT_UGURU3_DATA);
1216     u8 cmd_val = inb_p(ABIT_UGURU3_BASE + ABIT_UGURU3_CMD);
1217     if (((data_val == 0x00) || (data_val == 0x08)) &&
1218             ((cmd_val == 0xAC) || (cmd_val == 0x05) ||
1219              (cmd_val == 0x55)))
1220         return 0;
1221 
1222     ABIT_UGURU3_DEBUG("no Abit uGuru3 found, data = 0x%02X, cmd = "
1223         "0x%02X\n", (unsigned int)data_val, (unsigned int)cmd_val);
1224 
1225     if (force) {
1226         pr_info("Assuming Abit uGuru3 is present because of \"force\" parameter\n");
1227         return 0;
1228     }
1229 
1230     /* No uGuru3 found */
1231     return -ENODEV;
1232 }
1233 
1234 static struct platform_device *abituguru3_pdev;
1235 
1236 static int __init abituguru3_init(void)
1237 {
1238     struct resource res = { .flags = IORESOURCE_IO };
1239     int err;
1240 
1241     /* Attempt DMI detection first */
1242     err = abituguru3_dmi_detect();
1243     if (err < 0)
1244         return err;
1245 
1246     /*
1247      * Fall back to manual detection if there was no exact
1248      * board name match, or force was specified.
1249      */
1250     if (err > 0) {
1251         err = abituguru3_detect();
1252         if (err)
1253             return err;
1254 
1255         pr_warn("this motherboard was not detected using DMI. "
1256             "Please send the output of \"dmidecode\" to the abituguru3 maintainer (see MAINTAINERS)\n");
1257     }
1258 
1259     err = platform_driver_register(&abituguru3_driver);
1260     if (err)
1261         goto exit;
1262 
1263     abituguru3_pdev = platform_device_alloc(ABIT_UGURU3_NAME,
1264                         ABIT_UGURU3_BASE);
1265     if (!abituguru3_pdev) {
1266         pr_err("Device allocation failed\n");
1267         err = -ENOMEM;
1268         goto exit_driver_unregister;
1269     }
1270 
1271     res.start = ABIT_UGURU3_BASE;
1272     res.end = ABIT_UGURU3_BASE + ABIT_UGURU3_REGION_LENGTH - 1;
1273     res.name = ABIT_UGURU3_NAME;
1274 
1275     err = platform_device_add_resources(abituguru3_pdev, &res, 1);
1276     if (err) {
1277         pr_err("Device resource addition failed (%d)\n", err);
1278         goto exit_device_put;
1279     }
1280 
1281     err = platform_device_add(abituguru3_pdev);
1282     if (err) {
1283         pr_err("Device addition failed (%d)\n", err);
1284         goto exit_device_put;
1285     }
1286 
1287     return 0;
1288 
1289 exit_device_put:
1290     platform_device_put(abituguru3_pdev);
1291 exit_driver_unregister:
1292     platform_driver_unregister(&abituguru3_driver);
1293 exit:
1294     return err;
1295 }
1296 
1297 static void __exit abituguru3_exit(void)
1298 {
1299     platform_device_unregister(abituguru3_pdev);
1300     platform_driver_unregister(&abituguru3_driver);
1301 }
1302 
1303 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
1304 MODULE_DESCRIPTION("Abit uGuru3 Sensor device");
1305 MODULE_LICENSE("GPL");
1306 
1307 module_init(abituguru3_init);
1308 module_exit(abituguru3_exit);