2007-06-17 02:28:45 +04:00
/*
2012-01-19 23:02:13 +04:00
* abituguru3 . c
*
* Copyright ( c ) 2006 - 2008 Hans de Goede < hdegoede @ redhat . com >
* Copyright ( c ) 2008 Alistair John Strachan < alistair @ devzero . co . uk >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
2007-06-17 02:28:45 +04:00
/*
2012-01-19 23:02:13 +04:00
* This driver supports the sensor part of revision 3 of the custom Abit uGuru
* chip found on newer Abit uGuru motherboards . Note : because of lack of specs
* only reading the sensors and their settings is supported .
*/
2010-10-20 10:51:26 +04:00
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2007-06-17 02:28:45 +04:00
# include <linux/module.h>
# include <linux/init.h>
# include <linux/slab.h>
# include <linux/jiffies.h>
# include <linux/mutex.h>
# include <linux/err.h>
# include <linux/delay.h>
# include <linux/platform_device.h>
# include <linux/hwmon.h>
# include <linux/hwmon-sysfs.h>
2008-05-23 18:10:41 +04:00
# include <linux/dmi.h>
2009-09-15 19:18:13 +04:00
# include <linux/io.h>
2007-06-17 02:28:45 +04:00
/* uGuru3 bank addresses */
# define ABIT_UGURU3_SETTINGS_BANK 0x01
# define ABIT_UGURU3_SENSORS_BANK 0x08
# define ABIT_UGURU3_MISC_BANK 0x09
# define ABIT_UGURU3_ALARMS_START 0x1E
# define ABIT_UGURU3_SETTINGS_START 0x24
# define ABIT_UGURU3_VALUES_START 0x80
# define ABIT_UGURU3_BOARD_ID 0x0A
/* uGuru3 sensor bank flags */ /* Alarm if: */
# define ABIT_UGURU3_TEMP_HIGH_ALARM_ENABLE 0x01 /* temp over warn */
# define ABIT_UGURU3_VOLT_HIGH_ALARM_ENABLE 0x02 /* volt over max */
# define ABIT_UGURU3_VOLT_LOW_ALARM_ENABLE 0x04 /* volt under min */
# define ABIT_UGURU3_TEMP_HIGH_ALARM_FLAG 0x10 /* temp is over warn */
# define ABIT_UGURU3_VOLT_HIGH_ALARM_FLAG 0x20 /* volt is over max */
# define ABIT_UGURU3_VOLT_LOW_ALARM_FLAG 0x40 /* volt is under min */
# define ABIT_UGURU3_FAN_LOW_ALARM_ENABLE 0x01 /* fan under min */
# define ABIT_UGURU3_BEEP_ENABLE 0x08 /* beep if alarm */
# define ABIT_UGURU3_SHUTDOWN_ENABLE 0x80 /* shutdown if alarm */
/* sensor types */
# define ABIT_UGURU3_IN_SENSOR 0
# define ABIT_UGURU3_TEMP_SENSOR 1
# define ABIT_UGURU3_FAN_SENSOR 2
2012-01-19 23:02:13 +04:00
/*
* Timeouts / Retries , if these turn out to need a lot of fiddling we could
* convert them to params . Determined by trial and error . I assume this is
* cpu - speed independent , since the ISA - bus and not the CPU should be the
* bottleneck .
*/
2007-06-17 02:28:45 +04:00
# define ABIT_UGURU3_WAIT_TIMEOUT 250
2012-01-19 23:02:13 +04:00
/*
* Normally the 0xAC at the end of synchronize ( ) is reported after the
* first read , but sometimes not and we need to poll
*/
2007-06-17 02:28:45 +04:00
# define ABIT_UGURU3_SYNCHRONIZE_TIMEOUT 5
/* utility macros */
# define ABIT_UGURU3_NAME "abituguru3"
2013-01-10 17:54:40 +04:00
# define ABIT_UGURU3_DEBUG(format, arg...) \
do { \
if ( verbose ) \
pr_debug ( format , # # arg ) ; \
} while ( 0 )
2007-06-17 02:28:45 +04:00
/* Macros to help calculate the sysfs_names array length */
# define ABIT_UGURU3_MAX_NO_SENSORS 26
2012-01-19 23:02:13 +04:00
/*
* sum of strlen + 1 of : in ? ? _input \ 0 , in ? ? _ { min , max } \ 0 , in ? ? _ { min , max } _alarm \ 0 ,
* in ? ? _ { min , max } _alarm_enable \ 0 , in ? ? _beep \ 0 , in ? ? _shutdown \ 0 , in ? ? _label \ 0
*/
2012-01-15 00:40:05 +04:00
# define ABIT_UGURU3_IN_NAMES_LENGTH \
( 11 + 2 * 9 + 2 * 15 + 2 * 22 + 10 + 14 + 11 )
2012-01-19 23:02:13 +04:00
/*
* sum of strlen + 1 of : temp ? ? _input \ 0 , temp ? ? _max \ 0 , temp ? ? _crit \ 0 ,
* temp ? ? _alarm \ 0 , temp ? ? _alarm_enable \ 0 , temp ? ? _beep \ 0 , temp ? ? _shutdown \ 0 ,
* temp ? ? _label \ 0
*/
2007-06-17 02:28:45 +04:00
# define ABIT_UGURU3_TEMP_NAMES_LENGTH (13 + 11 + 12 + 13 + 20 + 12 + 16 + 13)
2012-01-19 23:02:13 +04:00
/*
* sum of strlen + 1 of : fan ? ? _input \ 0 , fan ? ? _min \ 0 , fan ? ? _alarm \ 0 ,
* fan ? ? _alarm_enable \ 0 , fan ? ? _beep \ 0 , fan ? ? _shutdown \ 0 , fan ? ? _label \ 0
*/
2007-06-17 02:28:45 +04:00
# define ABIT_UGURU3_FAN_NAMES_LENGTH (12 + 10 + 12 + 19 + 11 + 15 + 12)
2012-01-19 23:02:13 +04:00
/*
* Worst case scenario 16 in sensors ( longest names_length ) and the rest
* temp sensors ( second longest names_length ) .
*/
2007-06-17 02:28:45 +04:00
# define ABIT_UGURU3_SYSFS_NAMES_LENGTH (16 * ABIT_UGURU3_IN_NAMES_LENGTH + \
( ABIT_UGURU3_MAX_NO_SENSORS - 16 ) * ABIT_UGURU3_TEMP_NAMES_LENGTH )
2012-01-19 23:02:13 +04:00
/*
* All the macros below are named identical to the openguru2 program
* reverse engineered by Louis Kruger , hence the names might not be 100 %
* logical . I could come up with better names , but I prefer keeping the names
* identical so that this driver can be compared with his work more easily .
*/
2007-06-17 02:28:45 +04:00
/* Two i/o-ports are used by uGuru */
# define ABIT_UGURU3_BASE 0x00E0
# define ABIT_UGURU3_CMD 0x00
# define ABIT_UGURU3_DATA 0x04
# define ABIT_UGURU3_REGION_LENGTH 5
2012-01-19 23:02:13 +04:00
/*
* The wait_xxx functions return this on success and the last contents
* of the DATA register ( 0 - 255 ) on failure .
*/
2007-06-17 02:28:45 +04:00
# define ABIT_UGURU3_SUCCESS -1
/* uGuru status flags */
# define ABIT_UGURU3_STATUS_READY_FOR_READ 0x01
# define ABIT_UGURU3_STATUS_BUSY 0x02
/* Structures */
struct abituguru3_sensor_info {
2012-01-15 00:40:05 +04:00
const char * name ;
2007-06-17 02:28:45 +04:00
int port ;
int type ;
int multiplier ;
int divisor ;
int offset ;
} ;
2009-09-15 19:18:10 +04:00
/* Avoid use of flexible array members */
# define ABIT_UGURU3_MAX_DMI_NAMES 2
2007-06-17 02:28:45 +04:00
struct abituguru3_motherboard_info {
u16 id ;
2009-09-15 19:18:10 +04:00
const char * dmi_name [ ABIT_UGURU3_MAX_DMI_NAMES + 1 ] ;
2007-06-17 02:28:45 +04:00
/* + 1 -> end of sensors indicated by a sensor with name == NULL */
struct abituguru3_sensor_info sensors [ ABIT_UGURU3_MAX_NO_SENSORS + 1 ] ;
} ;
2012-01-19 23:02:13 +04:00
/*
* For the Abit uGuru , we need to keep some data in memory .
* The structure is dynamically allocated , at the same time when a new
* abituguru3 device is allocated .
*/
2007-06-17 02:28:45 +04:00
struct abituguru3_data {
2007-08-21 00:46:20 +04:00
struct device * hwmon_dev ; /* hwmon registered device */
2007-06-17 02:28:45 +04:00
struct mutex update_lock ; /* protect access to data and uGuru */
unsigned short addr ; /* uguru base address */
char valid ; /* !=0 if following fields are valid */
unsigned long last_updated ; /* In jiffies */
2012-01-19 23:02:13 +04:00
/*
* For convenience the sysfs attr and their names are generated
* automatically . We have max 10 entries per sensor ( for in sensors )
*/
2007-06-17 02:28:45 +04:00
struct sensor_device_attribute_2 sysfs_attr [ ABIT_UGURU3_MAX_NO_SENSORS
* 10 ] ;
/* Buffer to store the dynamically generated sysfs names */
char sysfs_names [ ABIT_UGURU3_SYSFS_NAMES_LENGTH ] ;
/* Pointer to the sensors info for the detected motherboard */
const struct abituguru3_sensor_info * sensors ;
2012-01-19 23:02:13 +04:00
/*
* The abituguru3 supports up to 48 sensors , and thus has registers
2013-09-27 16:36:04 +04:00
* sets for 48 sensors , for convenience reasons / simplicity of the
2012-01-19 23:02:13 +04:00
* code we always read and store all registers for all 48 sensors
*/
2007-06-17 02:28:45 +04:00
/* Alarms for all 48 sensors (1 bit per sensor) */
u8 alarms [ 48 / 8 ] ;
/* Value of all 48 sensors */
u8 value [ 48 ] ;
2012-01-19 23:02:13 +04:00
/*
* Settings of all 48 sensors , note in and temp sensors ( the first 32
* sensors ) have 3 bytes of settings , while fans only have 2 bytes ,
* for convenience we use 3 bytes for all sensors
*/
2007-06-17 02:28:45 +04:00
u8 settings [ 48 ] [ 3 ] ;
} ;
/* Constants */
static const struct abituguru3_motherboard_info abituguru3_motherboards [ ] = {
2009-09-15 19:18:10 +04:00
{ 0x000C , { NULL } /* Unknown, need DMI string */ , {
2007-06-17 02:28:45 +04:00
{ " CPU Core " , 0 , 0 , 10 , 1 , 0 } ,
{ " DDR " , 1 , 0 , 10 , 1 , 0 } ,
{ " DDR VTT " , 2 , 0 , 10 , 1 , 0 } ,
{ " CPU VTT 1.2V " , 3 , 0 , 10 , 1 , 0 } ,
{ " MCH & PCIE 1.5V " , 4 , 0 , 10 , 1 , 0 } ,
{ " MCH 2.5V " , 5 , 0 , 20 , 1 , 0 } ,
{ " ICH 1.05V " , 6 , 0 , 10 , 1 , 0 } ,
{ " ATX +12V (24-Pin) " , 7 , 0 , 60 , 1 , 0 } ,
{ " ATX +12V (4-pin) " , 8 , 0 , 60 , 1 , 0 } ,
{ " ATX +5V " , 9 , 0 , 30 , 1 , 0 } ,
{ " +3.3V " , 10 , 0 , 20 , 1 , 0 } ,
{ " 5VSB " , 11 , 0 , 30 , 1 , 0 } ,
{ " CPU " , 24 , 1 , 1 , 1 , 0 } ,
2008-10-26 19:04:40 +03:00
{ " System " , 25 , 1 , 1 , 1 , 0 } ,
2007-06-17 02:28:45 +04:00
{ " PWM " , 26 , 1 , 1 , 1 , 0 } ,
{ " CPU Fan " , 32 , 2 , 60 , 1 , 0 } ,
{ " NB Fan " , 33 , 2 , 60 , 1 , 0 } ,
{ " SYS FAN " , 34 , 2 , 60 , 1 , 0 } ,
{ " AUX1 Fan " , 35 , 2 , 60 , 1 , 0 } ,
{ NULL , 0 , 0 , 0 , 0 , 0 } }
} ,
2009-09-15 19:18:10 +04:00
{ 0x000D , { NULL } /* Abit AW8, need DMI string */ , {
2007-06-17 02:28:45 +04:00
{ " CPU Core " , 0 , 0 , 10 , 1 , 0 } ,
{ " DDR " , 1 , 0 , 10 , 1 , 0 } ,
{ " DDR VTT " , 2 , 0 , 10 , 1 , 0 } ,
{ " CPU VTT 1.2V " , 3 , 0 , 10 , 1 , 0 } ,
{ " MCH & PCIE 1.5V " , 4 , 0 , 10 , 1 , 0 } ,
{ " MCH 2.5V " , 5 , 0 , 20 , 1 , 0 } ,
{ " ICH 1.05V " , 6 , 0 , 10 , 1 , 0 } ,
{ " ATX +12V (24-Pin) " , 7 , 0 , 60 , 1 , 0 } ,
{ " ATX +12V (4-pin) " , 8 , 0 , 60 , 1 , 0 } ,
{ " ATX +5V " , 9 , 0 , 30 , 1 , 0 } ,
{ " +3.3V " , 10 , 0 , 20 , 1 , 0 } ,
{ " 5VSB " , 11 , 0 , 30 , 1 , 0 } ,
{ " CPU " , 24 , 1 , 1 , 1 , 0 } ,
2008-10-26 19:04:40 +03:00
{ " System " , 25 , 1 , 1 , 1 , 0 } ,
2007-06-17 02:28:45 +04:00
{ " PWM1 " , 26 , 1 , 1 , 1 , 0 } ,
{ " PWM2 " , 27 , 1 , 1 , 1 , 0 } ,
{ " PWM3 " , 28 , 1 , 1 , 1 , 0 } ,
{ " PWM4 " , 29 , 1 , 1 , 1 , 0 } ,
{ " CPU Fan " , 32 , 2 , 60 , 1 , 0 } ,
{ " NB Fan " , 33 , 2 , 60 , 1 , 0 } ,
{ " SYS Fan " , 34 , 2 , 60 , 1 , 0 } ,
{ " AUX1 Fan " , 35 , 2 , 60 , 1 , 0 } ,
{ " AUX2 Fan " , 36 , 2 , 60 , 1 , 0 } ,
{ " AUX3 Fan " , 37 , 2 , 60 , 1 , 0 } ,
{ " AUX4 Fan " , 38 , 2 , 60 , 1 , 0 } ,
{ " AUX5 Fan " , 39 , 2 , 60 , 1 , 0 } ,
{ NULL , 0 , 0 , 0 , 0 , 0 } }
} ,
2009-09-15 19:18:10 +04:00
{ 0x000E , { NULL } /* AL-8, need DMI string */ , {
2007-06-17 02:28:45 +04:00
{ " CPU Core " , 0 , 0 , 10 , 1 , 0 } ,
{ " DDR " , 1 , 0 , 10 , 1 , 0 } ,
{ " DDR VTT " , 2 , 0 , 10 , 1 , 0 } ,
{ " CPU VTT 1.2V " , 3 , 0 , 10 , 1 , 0 } ,
{ " MCH & PCIE 1.5V " , 4 , 0 , 10 , 1 , 0 } ,
{ " MCH 2.5V " , 5 , 0 , 20 , 1 , 0 } ,
{ " ICH 1.05V " , 6 , 0 , 10 , 1 , 0 } ,
{ " ATX +12V (24-Pin) " , 7 , 0 , 60 , 1 , 0 } ,
{ " ATX +12V (4-pin) " , 8 , 0 , 60 , 1 , 0 } ,
{ " ATX +5V " , 9 , 0 , 30 , 1 , 0 } ,
{ " +3.3V " , 10 , 0 , 20 , 1 , 0 } ,
{ " 5VSB " , 11 , 0 , 30 , 1 , 0 } ,
{ " CPU " , 24 , 1 , 1 , 1 , 0 } ,
2008-10-26 19:04:40 +03:00
{ " System " , 25 , 1 , 1 , 1 , 0 } ,
2007-06-17 02:28:45 +04:00
{ " PWM " , 26 , 1 , 1 , 1 , 0 } ,
{ " CPU Fan " , 32 , 2 , 60 , 1 , 0 } ,
{ " NB Fan " , 33 , 2 , 60 , 1 , 0 } ,
{ " SYS Fan " , 34 , 2 , 60 , 1 , 0 } ,
{ NULL , 0 , 0 , 0 , 0 , 0 } }
} ,
2009-09-15 19:18:10 +04:00
{ 0x000F , { NULL } /* Unknown, need DMI string */ , {
2007-06-17 02:28:45 +04:00
{ " CPU Core " , 0 , 0 , 10 , 1 , 0 } ,
{ " DDR " , 1 , 0 , 10 , 1 , 0 } ,
{ " DDR VTT " , 2 , 0 , 10 , 1 , 0 } ,
{ " CPU VTT 1.2V " , 3 , 0 , 10 , 1 , 0 } ,
{ " MCH & PCIE 1.5V " , 4 , 0 , 10 , 1 , 0 } ,
{ " MCH 2.5V " , 5 , 0 , 20 , 1 , 0 } ,
{ " ICH 1.05V " , 6 , 0 , 10 , 1 , 0 } ,
{ " ATX +12V (24-Pin) " , 7 , 0 , 60 , 1 , 0 } ,
{ " ATX +12V (4-pin) " , 8 , 0 , 60 , 1 , 0 } ,
{ " ATX +5V " , 9 , 0 , 30 , 1 , 0 } ,
{ " +3.3V " , 10 , 0 , 20 , 1 , 0 } ,
{ " 5VSB " , 11 , 0 , 30 , 1 , 0 } ,
{ " CPU " , 24 , 1 , 1 , 1 , 0 } ,
2008-10-26 19:04:40 +03:00
{ " System " , 25 , 1 , 1 , 1 , 0 } ,
2007-06-17 02:28:45 +04:00
{ " PWM " , 26 , 1 , 1 , 1 , 0 } ,
{ " CPU Fan " , 32 , 2 , 60 , 1 , 0 } ,
{ " NB Fan " , 33 , 2 , 60 , 1 , 0 } ,
{ " SYS Fan " , 34 , 2 , 60 , 1 , 0 } ,
{ NULL , 0 , 0 , 0 , 0 , 0 } }
} ,
2009-09-15 19:18:10 +04:00
{ 0x0010 , { NULL } /* Abit NI8 SLI GR, need DMI string */ , {
2007-06-17 02:28:45 +04:00
{ " CPU Core " , 0 , 0 , 10 , 1 , 0 } ,
{ " DDR " , 1 , 0 , 10 , 1 , 0 } ,
{ " DDR VTT " , 2 , 0 , 10 , 1 , 0 } ,
{ " CPU VTT 1.2V " , 3 , 0 , 10 , 1 , 0 } ,
{ " NB 1.4V " , 4 , 0 , 10 , 1 , 0 } ,
{ " SB 1.5V " , 6 , 0 , 10 , 1 , 0 } ,
{ " ATX +12V (24-Pin) " , 7 , 0 , 60 , 1 , 0 } ,
{ " ATX +12V (4-pin) " , 8 , 0 , 60 , 1 , 0 } ,
{ " ATX +5V " , 9 , 0 , 30 , 1 , 0 } ,
{ " +3.3V " , 10 , 0 , 20 , 1 , 0 } ,
{ " 5VSB " , 11 , 0 , 30 , 1 , 0 } ,
{ " CPU " , 24 , 1 , 1 , 1 , 0 } ,
{ " SYS " , 25 , 1 , 1 , 1 , 0 } ,
{ " PWM " , 26 , 1 , 1 , 1 , 0 } ,
{ " CPU Fan " , 32 , 2 , 60 , 1 , 0 } ,
{ " NB Fan " , 33 , 2 , 60 , 1 , 0 } ,
{ " SYS Fan " , 34 , 2 , 60 , 1 , 0 } ,
{ " AUX1 Fan " , 35 , 2 , 60 , 1 , 0 } ,
{ " OTES1 Fan " , 36 , 2 , 60 , 1 , 0 } ,
{ NULL , 0 , 0 , 0 , 0 , 0 } }
} ,
2009-09-15 19:18:10 +04:00
{ 0x0011 , { " AT8 32X " , NULL } , {
2007-06-17 02:28:45 +04:00
{ " CPU Core " , 0 , 0 , 10 , 1 , 0 } ,
{ " DDR " , 1 , 0 , 20 , 1 , 0 } ,
{ " DDR VTT " , 2 , 0 , 10 , 1 , 0 } ,
{ " CPU VDDA 2.5V " , 6 , 0 , 20 , 1 , 0 } ,
{ " NB 1.8V " , 4 , 0 , 10 , 1 , 0 } ,
{ " NB 1.8V Dual " , 5 , 0 , 10 , 1 , 0 } ,
{ " HTV 1.2 " , 3 , 0 , 10 , 1 , 0 } ,
{ " PCIE 1.2V " , 12 , 0 , 10 , 1 , 0 } ,
{ " NB 1.2V " , 13 , 0 , 10 , 1 , 0 } ,
{ " ATX +12V (24-Pin) " , 7 , 0 , 60 , 1 , 0 } ,
{ " ATX +12V (4-pin) " , 8 , 0 , 60 , 1 , 0 } ,
{ " ATX +5V " , 9 , 0 , 30 , 1 , 0 } ,
{ " +3.3V " , 10 , 0 , 20 , 1 , 0 } ,
{ " 5VSB " , 11 , 0 , 30 , 1 , 0 } ,
{ " CPU " , 24 , 1 , 1 , 1 , 0 } ,
{ " NB " , 25 , 1 , 1 , 1 , 0 } ,
{ " System " , 26 , 1 , 1 , 1 , 0 } ,
{ " PWM " , 27 , 1 , 1 , 1 , 0 } ,
{ " CPU Fan " , 32 , 2 , 60 , 1 , 0 } ,
{ " NB Fan " , 33 , 2 , 60 , 1 , 0 } ,
{ " SYS Fan " , 34 , 2 , 60 , 1 , 0 } ,
{ " AUX1 Fan " , 35 , 2 , 60 , 1 , 0 } ,
{ " AUX2 Fan " , 36 , 2 , 60 , 1 , 0 } ,
2008-10-09 17:33:59 +04:00
{ " AUX3 Fan " , 37 , 2 , 60 , 1 , 0 } ,
2007-06-17 02:28:45 +04:00
{ NULL , 0 , 0 , 0 , 0 , 0 } }
} ,
2009-09-15 19:18:10 +04:00
{ 0x0012 , { NULL } /* Abit AN8 32X, need DMI string */ , {
2007-06-17 02:28:45 +04:00
{ " CPU Core " , 0 , 0 , 10 , 1 , 0 } ,
{ " DDR " , 1 , 0 , 20 , 1 , 0 } ,
{ " DDR VTT " , 2 , 0 , 10 , 1 , 0 } ,
{ " HyperTransport " , 3 , 0 , 10 , 1 , 0 } ,
{ " CPU VDDA 2.5V " , 5 , 0 , 20 , 1 , 0 } ,
{ " NB " , 4 , 0 , 10 , 1 , 0 } ,
{ " SB " , 6 , 0 , 10 , 1 , 0 } ,
{ " ATX +12V (24-Pin) " , 7 , 0 , 60 , 1 , 0 } ,
{ " ATX +12V (4-pin) " , 8 , 0 , 60 , 1 , 0 } ,
{ " ATX +5V " , 9 , 0 , 30 , 1 , 0 } ,
{ " +3.3V " , 10 , 0 , 20 , 1 , 0 } ,
{ " 5VSB " , 11 , 0 , 30 , 1 , 0 } ,
{ " CPU " , 24 , 1 , 1 , 1 , 0 } ,
{ " SYS " , 25 , 1 , 1 , 1 , 0 } ,
{ " PWM " , 26 , 1 , 1 , 1 , 0 } ,
{ " CPU Fan " , 32 , 2 , 60 , 1 , 0 } ,
{ " NB Fan " , 33 , 2 , 60 , 1 , 0 } ,
{ " SYS Fan " , 34 , 2 , 60 , 1 , 0 } ,
{ " AUX1 Fan " , 36 , 2 , 60 , 1 , 0 } ,
{ NULL , 0 , 0 , 0 , 0 , 0 } }
} ,
2009-09-15 19:18:10 +04:00
{ 0x0013 , { NULL } /* Abit AW8D, need DMI string */ , {
2007-06-17 02:28:45 +04:00
{ " CPU Core " , 0 , 0 , 10 , 1 , 0 } ,
{ " DDR " , 1 , 0 , 10 , 1 , 0 } ,
{ " DDR VTT " , 2 , 0 , 10 , 1 , 0 } ,
{ " CPU VTT 1.2V " , 3 , 0 , 10 , 1 , 0 } ,
{ " MCH & PCIE 1.5V " , 4 , 0 , 10 , 1 , 0 } ,
{ " MCH 2.5V " , 5 , 0 , 20 , 1 , 0 } ,
{ " ICH 1.05V " , 6 , 0 , 10 , 1 , 0 } ,
{ " ATX +12V (24-Pin) " , 7 , 0 , 60 , 1 , 0 } ,
{ " ATX +12V (4-pin) " , 8 , 0 , 60 , 1 , 0 } ,
{ " ATX +5V " , 9 , 0 , 30 , 1 , 0 } ,
{ " +3.3V " , 10 , 0 , 20 , 1 , 0 } ,
{ " 5VSB " , 11 , 0 , 30 , 1 , 0 } ,
{ " CPU " , 24 , 1 , 1 , 1 , 0 } ,
2008-10-26 19:04:40 +03:00
{ " System " , 25 , 1 , 1 , 1 , 0 } ,
2007-06-17 02:28:45 +04:00
{ " PWM1 " , 26 , 1 , 1 , 1 , 0 } ,
{ " PWM2 " , 27 , 1 , 1 , 1 , 0 } ,
{ " PWM3 " , 28 , 1 , 1 , 1 , 0 } ,
{ " PWM4 " , 29 , 1 , 1 , 1 , 0 } ,
{ " CPU Fan " , 32 , 2 , 60 , 1 , 0 } ,
{ " NB Fan " , 33 , 2 , 60 , 1 , 0 } ,
{ " SYS Fan " , 34 , 2 , 60 , 1 , 0 } ,
{ " AUX1 Fan " , 35 , 2 , 60 , 1 , 0 } ,
{ " AUX2 Fan " , 36 , 2 , 60 , 1 , 0 } ,
{ " AUX3 Fan " , 37 , 2 , 60 , 1 , 0 } ,
{ " AUX4 Fan " , 38 , 2 , 60 , 1 , 0 } ,
2008-02-26 21:34:48 +03:00
{ " AUX5 Fan " , 39 , 2 , 60 , 1 , 0 } ,
2007-06-17 02:28:45 +04:00
{ NULL , 0 , 0 , 0 , 0 , 0 } }
} ,
2009-09-15 19:18:10 +04:00
{ 0x0014 , { " AB9 " , " AB9 Pro " , NULL } , {
2007-06-17 02:28:45 +04:00
{ " CPU Core " , 0 , 0 , 10 , 1 , 0 } ,
{ " DDR " , 1 , 0 , 10 , 1 , 0 } ,
{ " DDR VTT " , 2 , 0 , 10 , 1 , 0 } ,
{ " CPU VTT 1.2V " , 3 , 0 , 10 , 1 , 0 } ,
{ " MCH & PCIE 1.5V " , 4 , 0 , 10 , 1 , 0 } ,
{ " MCH 2.5V " , 5 , 0 , 20 , 1 , 0 } ,
{ " ICH 1.05V " , 6 , 0 , 10 , 1 , 0 } ,
{ " ATX +12V (24-Pin) " , 7 , 0 , 60 , 1 , 0 } ,
{ " ATX +12V (4-pin) " , 8 , 0 , 60 , 1 , 0 } ,
{ " ATX +5V " , 9 , 0 , 30 , 1 , 0 } ,
{ " +3.3V " , 10 , 0 , 20 , 1 , 0 } ,
{ " 5VSB " , 11 , 0 , 30 , 1 , 0 } ,
{ " CPU " , 24 , 1 , 1 , 1 , 0 } ,
2008-10-26 19:04:40 +03:00
{ " System " , 25 , 1 , 1 , 1 , 0 } ,
2007-06-17 02:28:45 +04:00
{ " PWM " , 26 , 1 , 1 , 1 , 0 } ,
{ " CPU Fan " , 32 , 2 , 60 , 1 , 0 } ,
{ " NB Fan " , 33 , 2 , 60 , 1 , 0 } ,
{ " SYS Fan " , 34 , 2 , 60 , 1 , 0 } ,
{ NULL , 0 , 0 , 0 , 0 , 0 } }
} ,
2009-09-15 19:18:10 +04:00
{ 0x0015 , { NULL } /* Unknown, need DMI string */ , {
2007-06-17 02:28:45 +04:00
{ " CPU Core " , 0 , 0 , 10 , 1 , 0 } ,
{ " DDR " , 1 , 0 , 20 , 1 , 0 } ,
{ " DDR VTT " , 2 , 0 , 10 , 1 , 0 } ,
{ " HyperTransport " , 3 , 0 , 10 , 1 , 0 } ,
{ " CPU VDDA 2.5V " , 5 , 0 , 20 , 1 , 0 } ,
{ " NB " , 4 , 0 , 10 , 1 , 0 } ,
{ " SB " , 6 , 0 , 10 , 1 , 0 } ,
{ " ATX +12V (24-Pin) " , 7 , 0 , 60 , 1 , 0 } ,
{ " ATX +12V (4-pin) " , 8 , 0 , 60 , 1 , 0 } ,
{ " ATX +5V " , 9 , 0 , 30 , 1 , 0 } ,
{ " +3.3V " , 10 , 0 , 20 , 1 , 0 } ,
{ " 5VSB " , 11 , 0 , 30 , 1 , 0 } ,
{ " CPU " , 24 , 1 , 1 , 1 , 0 } ,
{ " SYS " , 25 , 1 , 1 , 1 , 0 } ,
{ " PWM " , 26 , 1 , 1 , 1 , 0 } ,
{ " CPU Fan " , 32 , 2 , 60 , 1 , 0 } ,
{ " NB Fan " , 33 , 2 , 60 , 1 , 0 } ,
{ " SYS Fan " , 34 , 2 , 60 , 1 , 0 } ,
{ " AUX1 Fan " , 33 , 2 , 60 , 1 , 0 } ,
{ " AUX2 Fan " , 35 , 2 , 60 , 1 , 0 } ,
{ " AUX3 Fan " , 36 , 2 , 60 , 1 , 0 } ,
{ NULL , 0 , 0 , 0 , 0 , 0 } }
} ,
2009-09-15 19:18:10 +04:00
{ 0x0016 , { " AW9D-MAX " , NULL } , {
2007-06-17 02:28:45 +04:00
{ " CPU Core " , 0 , 0 , 10 , 1 , 0 } ,
{ " DDR2 " , 1 , 0 , 20 , 1 , 0 } ,
{ " DDR2 VTT " , 2 , 0 , 10 , 1 , 0 } ,
{ " CPU VTT 1.2V " , 3 , 0 , 10 , 1 , 0 } ,
{ " MCH & PCIE 1.5V " , 4 , 0 , 10 , 1 , 0 } ,
{ " MCH 2.5V " , 5 , 0 , 20 , 1 , 0 } ,
{ " ICH 1.05V " , 6 , 0 , 10 , 1 , 0 } ,
{ " ATX +12V (24-Pin) " , 7 , 0 , 60 , 1 , 0 } ,
{ " ATX +12V (4-pin) " , 8 , 0 , 60 , 1 , 0 } ,
{ " ATX +5V " , 9 , 0 , 30 , 1 , 0 } ,
{ " +3.3V " , 10 , 0 , 20 , 1 , 0 } ,
{ " 5VSB " , 11 , 0 , 30 , 1 , 0 } ,
{ " CPU " , 24 , 1 , 1 , 1 , 0 } ,
2008-10-26 19:04:40 +03:00
{ " System " , 25 , 1 , 1 , 1 , 0 } ,
2007-06-17 02:28:45 +04:00
{ " PWM1 " , 26 , 1 , 1 , 1 , 0 } ,
{ " PWM2 " , 27 , 1 , 1 , 1 , 0 } ,
{ " PWM3 " , 28 , 1 , 1 , 1 , 0 } ,
{ " PWM4 " , 29 , 1 , 1 , 1 , 0 } ,
{ " CPU Fan " , 32 , 2 , 60 , 1 , 0 } ,
{ " NB Fan " , 33 , 2 , 60 , 1 , 0 } ,
{ " SYS Fan " , 34 , 2 , 60 , 1 , 0 } ,
{ " AUX1 Fan " , 35 , 2 , 60 , 1 , 0 } ,
{ " AUX2 Fan " , 36 , 2 , 60 , 1 , 0 } ,
{ " AUX3 Fan " , 37 , 2 , 60 , 1 , 0 } ,
{ " OTES1 Fan " , 38 , 2 , 60 , 1 , 0 } ,
{ NULL , 0 , 0 , 0 , 0 , 0 } }
} ,
2009-09-15 19:18:10 +04:00
{ 0x0017 , { NULL } /* Unknown, need DMI string */ , {
2007-06-17 02:28:45 +04:00
{ " CPU Core " , 0 , 0 , 10 , 1 , 0 } ,
{ " DDR2 " , 1 , 0 , 20 , 1 , 0 } ,
{ " DDR2 VTT " , 2 , 0 , 10 , 1 , 0 } ,
{ " HyperTransport " , 3 , 0 , 10 , 1 , 0 } ,
{ " CPU VDDA 2.5V " , 6 , 0 , 20 , 1 , 0 } ,
{ " NB 1.8V " , 4 , 0 , 10 , 1 , 0 } ,
{ " NB 1.2V " , 13 , 0 , 10 , 1 , 0 } ,
{ " SB 1.2V " , 5 , 0 , 10 , 1 , 0 } ,
{ " PCIE 1.2V " , 12 , 0 , 10 , 1 , 0 } ,
{ " ATX +12V (24-Pin) " , 7 , 0 , 60 , 1 , 0 } ,
{ " ATX +12V (4-pin) " , 8 , 0 , 60 , 1 , 0 } ,
{ " ATX +5V " , 9 , 0 , 30 , 1 , 0 } ,
{ " ATX +3.3V " , 10 , 0 , 20 , 1 , 0 } ,
{ " ATX 5VSB " , 11 , 0 , 30 , 1 , 0 } ,
{ " CPU " , 24 , 1 , 1 , 1 , 0 } ,
2008-10-26 19:04:40 +03:00
{ " System " , 26 , 1 , 1 , 1 , 0 } ,
2007-06-17 02:28:45 +04:00
{ " PWM " , 27 , 1 , 1 , 1 , 0 } ,
{ " CPU FAN " , 32 , 2 , 60 , 1 , 0 } ,
{ " SYS FAN " , 34 , 2 , 60 , 1 , 0 } ,
{ " AUX1 FAN " , 35 , 2 , 60 , 1 , 0 } ,
{ " AUX2 FAN " , 36 , 2 , 60 , 1 , 0 } ,
{ " AUX3 FAN " , 37 , 2 , 60 , 1 , 0 } ,
{ NULL , 0 , 0 , 0 , 0 , 0 } }
} ,
2009-09-15 19:18:10 +04:00
{ 0x0018 , { " AB9 QuadGT " , NULL } , {
2007-06-17 02:28:45 +04:00
{ " CPU Core " , 0 , 0 , 10 , 1 , 0 } ,
{ " DDR2 " , 1 , 0 , 20 , 1 , 0 } ,
{ " DDR2 VTT " , 2 , 0 , 10 , 1 , 0 } ,
{ " CPU VTT " , 3 , 0 , 10 , 1 , 0 } ,
{ " MCH 1.25V " , 4 , 0 , 10 , 1 , 0 } ,
{ " ICHIO 1.5V " , 5 , 0 , 10 , 1 , 0 } ,
{ " ICH 1.05V " , 6 , 0 , 10 , 1 , 0 } ,
{ " ATX +12V (24-Pin) " , 7 , 0 , 60 , 1 , 0 } ,
{ " ATX +12V (4-pin) " , 8 , 0 , 60 , 1 , 0 } ,
{ " ATX +5V " , 9 , 0 , 30 , 1 , 0 } ,
{ " +3.3V " , 10 , 0 , 20 , 1 , 0 } ,
{ " 5VSB " , 11 , 0 , 30 , 1 , 0 } ,
{ " CPU " , 24 , 1 , 1 , 1 , 0 } ,
2008-10-26 19:04:40 +03:00
{ " System " , 25 , 1 , 1 , 1 , 0 } ,
2007-06-17 02:28:45 +04:00
{ " PWM Phase1 " , 26 , 1 , 1 , 1 , 0 } ,
{ " PWM Phase2 " , 27 , 1 , 1 , 1 , 0 } ,
{ " PWM Phase3 " , 28 , 1 , 1 , 1 , 0 } ,
{ " PWM Phase4 " , 29 , 1 , 1 , 1 , 0 } ,
{ " PWM Phase5 " , 30 , 1 , 1 , 1 , 0 } ,
{ " CPU Fan " , 32 , 2 , 60 , 1 , 0 } ,
{ " SYS Fan " , 34 , 2 , 60 , 1 , 0 } ,
{ " AUX1 Fan " , 33 , 2 , 60 , 1 , 0 } ,
{ " AUX2 Fan " , 35 , 2 , 60 , 1 , 0 } ,
{ " AUX3 Fan " , 36 , 2 , 60 , 1 , 0 } ,
{ NULL , 0 , 0 , 0 , 0 , 0 } }
} ,
2009-09-15 19:18:10 +04:00
{ 0x0019 , { " IN9 32X MAX " , NULL } , {
2007-06-17 02:28:45 +04:00
{ " CPU Core " , 7 , 0 , 10 , 1 , 0 } ,
{ " DDR2 " , 13 , 0 , 20 , 1 , 0 } ,
{ " DDR2 VTT " , 14 , 0 , 10 , 1 , 0 } ,
{ " CPU VTT " , 3 , 0 , 20 , 1 , 0 } ,
2008-10-26 19:04:40 +03:00
{ " NB 1.2V " , 4 , 0 , 10 , 1 , 0 } ,
2007-06-17 02:28:45 +04:00
{ " SB 1.5V " , 6 , 0 , 10 , 1 , 0 } ,
{ " HyperTransport " , 5 , 0 , 10 , 1 , 0 } ,
{ " ATX +12V (24-Pin) " , 12 , 0 , 60 , 1 , 0 } ,
{ " ATX +12V (4-pin) " , 8 , 0 , 60 , 1 , 0 } ,
{ " ATX +5V " , 9 , 0 , 30 , 1 , 0 } ,
{ " ATX +3.3V " , 10 , 0 , 20 , 1 , 0 } ,
{ " ATX 5VSB " , 11 , 0 , 30 , 1 , 0 } ,
{ " CPU " , 24 , 1 , 1 , 1 , 0 } ,
2008-10-26 19:04:40 +03:00
{ " System " , 25 , 1 , 1 , 1 , 0 } ,
2007-06-17 02:28:45 +04:00
{ " PWM Phase1 " , 26 , 1 , 1 , 1 , 0 } ,
{ " PWM Phase2 " , 27 , 1 , 1 , 1 , 0 } ,
{ " PWM Phase3 " , 28 , 1 , 1 , 1 , 0 } ,
{ " PWM Phase4 " , 29 , 1 , 1 , 1 , 0 } ,
{ " PWM Phase5 " , 30 , 1 , 1 , 1 , 0 } ,
{ " CPU FAN " , 32 , 2 , 60 , 1 , 0 } ,
{ " SYS FAN " , 34 , 2 , 60 , 1 , 0 } ,
{ " AUX1 FAN " , 33 , 2 , 60 , 1 , 0 } ,
{ " AUX2 FAN " , 35 , 2 , 60 , 1 , 0 } ,
{ " AUX3 FAN " , 36 , 2 , 60 , 1 , 0 } ,
{ NULL , 0 , 0 , 0 , 0 , 0 } }
} ,
2009-09-15 19:18:10 +04:00
{ 0x001A , { " IP35 Pro " , " IP35 Pro XE " , NULL } , {
2007-06-17 02:28:45 +04:00
{ " CPU Core " , 0 , 0 , 10 , 1 , 0 } ,
{ " DDR2 " , 1 , 0 , 20 , 1 , 0 } ,
{ " DDR2 VTT " , 2 , 0 , 10 , 1 , 0 } ,
{ " CPU VTT 1.2V " , 3 , 0 , 10 , 1 , 0 } ,
{ " MCH 1.25V " , 4 , 0 , 10 , 1 , 0 } ,
{ " ICHIO 1.5V " , 5 , 0 , 10 , 1 , 0 } ,
{ " ICH 1.05V " , 6 , 0 , 10 , 1 , 0 } ,
{ " ATX +12V (24-Pin) " , 7 , 0 , 60 , 1 , 0 } ,
{ " ATX +12V (8-pin) " , 8 , 0 , 60 , 1 , 0 } ,
{ " ATX +5V " , 9 , 0 , 30 , 1 , 0 } ,
{ " +3.3V " , 10 , 0 , 20 , 1 , 0 } ,
{ " 5VSB " , 11 , 0 , 30 , 1 , 0 } ,
{ " CPU " , 24 , 1 , 1 , 1 , 0 } ,
2008-10-26 19:04:40 +03:00
{ " System " , 25 , 1 , 1 , 1 , 0 } ,
{ " PWM " , 26 , 1 , 1 , 1 , 0 } ,
2007-06-17 02:28:45 +04:00
{ " PWM Phase2 " , 27 , 1 , 1 , 1 , 0 } ,
{ " PWM Phase3 " , 28 , 1 , 1 , 1 , 0 } ,
{ " PWM Phase4 " , 29 , 1 , 1 , 1 , 0 } ,
{ " PWM Phase5 " , 30 , 1 , 1 , 1 , 0 } ,
{ " CPU Fan " , 32 , 2 , 60 , 1 , 0 } ,
{ " SYS Fan " , 34 , 2 , 60 , 1 , 0 } ,
{ " AUX1 Fan " , 33 , 2 , 60 , 1 , 0 } ,
{ " AUX2 Fan " , 35 , 2 , 60 , 1 , 0 } ,
{ " AUX3 Fan " , 36 , 2 , 60 , 1 , 0 } ,
2008-01-15 21:57:44 +03:00
{ " AUX4 Fan " , 37 , 2 , 60 , 1 , 0 } ,
2007-06-17 02:28:45 +04:00
{ NULL , 0 , 0 , 0 , 0 , 0 } }
} ,
2009-09-15 19:18:10 +04:00
{ 0x001B , { NULL } /* Unknown, need DMI string */ , {
2007-10-21 02:55:35 +04:00
{ " CPU Core " , 0 , 0 , 10 , 1 , 0 } ,
{ " DDR3 " , 1 , 0 , 20 , 1 , 0 } ,
{ " DDR3 VTT " , 2 , 0 , 10 , 1 , 0 } ,
{ " CPU VTT " , 3 , 0 , 10 , 1 , 0 } ,
{ " MCH 1.25V " , 4 , 0 , 10 , 1 , 0 } ,
{ " ICHIO 1.5V " , 5 , 0 , 10 , 1 , 0 } ,
{ " ICH 1.05V " , 6 , 0 , 10 , 1 , 0 } ,
{ " ATX +12V (24-Pin) " , 7 , 0 , 60 , 1 , 0 } ,
{ " ATX +12V (8-pin) " , 8 , 0 , 60 , 1 , 0 } ,
{ " ATX +5V " , 9 , 0 , 30 , 1 , 0 } ,
{ " +3.3V " , 10 , 0 , 20 , 1 , 0 } ,
{ " 5VSB " , 11 , 0 , 30 , 1 , 0 } ,
{ " CPU " , 24 , 1 , 1 , 1 , 0 } ,
{ " System " , 25 , 1 , 1 , 1 , 0 } ,
{ " PWM Phase1 " , 26 , 1 , 1 , 1 , 0 } ,
{ " PWM Phase2 " , 27 , 1 , 1 , 1 , 0 } ,
{ " PWM Phase3 " , 28 , 1 , 1 , 1 , 0 } ,
{ " PWM Phase4 " , 29 , 1 , 1 , 1 , 0 } ,
{ " PWM Phase5 " , 30 , 1 , 1 , 1 , 0 } ,
{ " CPU Fan " , 32 , 2 , 60 , 1 , 0 } ,
{ " SYS Fan " , 34 , 2 , 60 , 1 , 0 } ,
{ " AUX1 Fan " , 33 , 2 , 60 , 1 , 0 } ,
{ " AUX2 Fan " , 35 , 2 , 60 , 1 , 0 } ,
{ " AUX3 Fan " , 36 , 2 , 60 , 1 , 0 } ,
{ NULL , 0 , 0 , 0 , 0 , 0 } }
} ,
2009-09-15 19:18:10 +04:00
{ 0x001C , { " IX38 QuadGT " , NULL } , {
2007-10-21 02:55:35 +04:00
{ " CPU Core " , 0 , 0 , 10 , 1 , 0 } ,
{ " DDR2 " , 1 , 0 , 20 , 1 , 0 } ,
{ " DDR2 VTT " , 2 , 0 , 10 , 1 , 0 } ,
{ " CPU VTT " , 3 , 0 , 10 , 1 , 0 } ,
{ " MCH 1.25V " , 4 , 0 , 10 , 1 , 0 } ,
{ " ICHIO 1.5V " , 5 , 0 , 10 , 1 , 0 } ,
{ " ICH 1.05V " , 6 , 0 , 10 , 1 , 0 } ,
{ " ATX +12V (24-Pin) " , 7 , 0 , 60 , 1 , 0 } ,
{ " ATX +12V (8-pin) " , 8 , 0 , 60 , 1 , 0 } ,
{ " ATX +5V " , 9 , 0 , 30 , 1 , 0 } ,
{ " +3.3V " , 10 , 0 , 20 , 1 , 0 } ,
{ " 5VSB " , 11 , 0 , 30 , 1 , 0 } ,
{ " CPU " , 24 , 1 , 1 , 1 , 0 } ,
{ " System " , 25 , 1 , 1 , 1 , 0 } ,
{ " PWM Phase1 " , 26 , 1 , 1 , 1 , 0 } ,
{ " PWM Phase2 " , 27 , 1 , 1 , 1 , 0 } ,
{ " PWM Phase3 " , 28 , 1 , 1 , 1 , 0 } ,
{ " PWM Phase4 " , 29 , 1 , 1 , 1 , 0 } ,
{ " PWM Phase5 " , 30 , 1 , 1 , 1 , 0 } ,
{ " CPU Fan " , 32 , 2 , 60 , 1 , 0 } ,
{ " SYS Fan " , 34 , 2 , 60 , 1 , 0 } ,
{ " AUX1 Fan " , 33 , 2 , 60 , 1 , 0 } ,
{ " AUX2 Fan " , 35 , 2 , 60 , 1 , 0 } ,
{ " AUX3 Fan " , 36 , 2 , 60 , 1 , 0 } ,
{ NULL , 0 , 0 , 0 , 0 , 0 } }
} ,
2009-09-15 19:18:10 +04:00
{ 0x0000 , { NULL } , { { NULL , 0 , 0 , 0 , 0 , 0 } } }
2007-06-17 02:28:45 +04:00
} ;
/* Insmod parameters */
2012-01-13 03:02:20 +04:00
static bool force ;
2007-06-17 02:28:45 +04:00
module_param ( force , bool , 0 ) ;
MODULE_PARM_DESC ( force , " Set to one to force detection. " ) ;
/* Default verbose is 1, since this driver is still in the testing phase */
2012-01-13 03:02:20 +04:00
static bool verbose = 1 ;
2007-06-17 02:28:45 +04:00
module_param ( verbose , bool , 0644 ) ;
MODULE_PARM_DESC ( verbose , " Enable/disable verbose error reporting " ) ;
2010-10-20 10:51:26 +04:00
static const char * never_happen = " This should never happen. " ;
static const char * report_this =
" Please report this to the abituguru3 maintainer (see MAINTAINERS) " ;
2007-06-17 02:28:45 +04:00
/* wait while the uguru is busy (usually after a write) */
static int abituguru3_wait_while_busy ( struct abituguru3_data * data )
{
u8 x ;
int timeout = ABIT_UGURU3_WAIT_TIMEOUT ;
while ( ( x = inb_p ( data - > addr + ABIT_UGURU3_DATA ) ) &
ABIT_UGURU3_STATUS_BUSY ) {
timeout - - ;
if ( timeout = = 0 )
return x ;
2012-01-19 23:02:13 +04:00
/*
* sleep a bit before our last try , to give the uGuru3 one
* last chance to respond .
*/
2007-06-17 02:28:45 +04:00
if ( timeout = = 1 )
msleep ( 1 ) ;
}
return ABIT_UGURU3_SUCCESS ;
}
/* wait till uguru is ready to be read */
static int abituguru3_wait_for_read ( struct abituguru3_data * data )
{
u8 x ;
int timeout = ABIT_UGURU3_WAIT_TIMEOUT ;
while ( ! ( ( x = inb_p ( data - > addr + ABIT_UGURU3_DATA ) ) &
ABIT_UGURU3_STATUS_READY_FOR_READ ) ) {
timeout - - ;
if ( timeout = = 0 )
return x ;
2012-01-19 23:02:13 +04:00
/*
* sleep a bit before our last try , to give the uGuru3 one
* last chance to respond .
*/
2007-06-17 02:28:45 +04:00
if ( timeout = = 1 )
msleep ( 1 ) ;
}
return ABIT_UGURU3_SUCCESS ;
}
2012-01-19 23:02:13 +04:00
/*
* This synchronizes us with the uGuru3 ' s protocol state machine , this
* must be done before each command .
*/
2007-06-17 02:28:45 +04:00
static int abituguru3_synchronize ( struct abituguru3_data * data )
{
int x , timeout = ABIT_UGURU3_SYNCHRONIZE_TIMEOUT ;
2012-01-15 00:40:05 +04:00
x = abituguru3_wait_while_busy ( data ) ;
if ( x ! = ABIT_UGURU3_SUCCESS ) {
2007-06-17 02:28:45 +04:00
ABIT_UGURU3_DEBUG ( " synchronize timeout during initial busy "
" wait, status: 0x%02x \n " , x ) ;
return - EIO ;
}
outb ( 0x20 , data - > addr + ABIT_UGURU3_DATA ) ;
2012-01-15 00:40:05 +04:00
x = abituguru3_wait_while_busy ( data ) ;
if ( x ! = ABIT_UGURU3_SUCCESS ) {
2007-06-17 02:28:45 +04:00
ABIT_UGURU3_DEBUG ( " synchronize timeout after sending 0x20, "
" status: 0x%02x \n " , x ) ;
return - EIO ;
}
outb ( 0x10 , data - > addr + ABIT_UGURU3_CMD ) ;
2012-01-15 00:40:05 +04:00
x = abituguru3_wait_while_busy ( data ) ;
if ( x ! = ABIT_UGURU3_SUCCESS ) {
2007-06-17 02:28:45 +04:00
ABIT_UGURU3_DEBUG ( " synchronize timeout after sending 0x10, "
" status: 0x%02x \n " , x ) ;
return - EIO ;
}
outb ( 0x00 , data - > addr + ABIT_UGURU3_CMD ) ;
2012-01-15 00:40:05 +04:00
x = abituguru3_wait_while_busy ( data ) ;
if ( x ! = ABIT_UGURU3_SUCCESS ) {
2007-06-17 02:28:45 +04:00
ABIT_UGURU3_DEBUG ( " synchronize timeout after sending 0x00, "
" status: 0x%02x \n " , x ) ;
return - EIO ;
}
2012-01-15 00:40:05 +04:00
x = abituguru3_wait_for_read ( data ) ;
if ( x ! = ABIT_UGURU3_SUCCESS ) {
2007-06-17 02:28:45 +04:00
ABIT_UGURU3_DEBUG ( " synchronize timeout waiting for read, "
" status: 0x%02x \n " , x ) ;
return - EIO ;
}
while ( ( x = inb ( data - > addr + ABIT_UGURU3_CMD ) ) ! = 0xAC ) {
timeout - - ;
if ( timeout = = 0 ) {
ABIT_UGURU3_DEBUG ( " synchronize timeout cmd does not "
" hold 0xAC after synchronize, cmd: 0x%02x \n " ,
x ) ;
return - EIO ;
}
msleep ( 1 ) ;
}
return 0 ;
}
2012-01-19 23:02:13 +04:00
/*
* Read count bytes from sensor sensor_addr in bank bank_addr and store the
* result in buf
*/
2007-06-17 02:28:45 +04:00
static int abituguru3_read ( struct abituguru3_data * data , u8 bank , u8 offset ,
u8 count , u8 * buf )
{
int i , x ;
2012-01-15 00:40:05 +04:00
x = abituguru3_synchronize ( data ) ;
if ( x )
2007-06-17 02:28:45 +04:00
return x ;
outb ( 0x1A , data - > addr + ABIT_UGURU3_DATA ) ;
2012-01-15 00:40:05 +04:00
x = abituguru3_wait_while_busy ( data ) ;
if ( x ! = ABIT_UGURU3_SUCCESS ) {
2007-06-17 02:28:45 +04:00
ABIT_UGURU3_DEBUG ( " read from 0x%02x:0x%02x timed out after "
" sending 0x1A, status: 0x%02x \n " , ( unsigned int ) bank ,
( unsigned int ) offset , x ) ;
return - EIO ;
}
outb ( bank , data - > addr + ABIT_UGURU3_CMD ) ;
2012-01-15 00:40:05 +04:00
x = abituguru3_wait_while_busy ( data ) ;
if ( x ! = ABIT_UGURU3_SUCCESS ) {
2007-06-17 02:28:45 +04:00
ABIT_UGURU3_DEBUG ( " read from 0x%02x:0x%02x timed out after "
" sending the bank, status: 0x%02x \n " ,
( unsigned int ) bank , ( unsigned int ) offset , x ) ;
return - EIO ;
}
outb ( offset , data - > addr + ABIT_UGURU3_CMD ) ;
2012-01-15 00:40:05 +04:00
x = abituguru3_wait_while_busy ( data ) ;
if ( x ! = ABIT_UGURU3_SUCCESS ) {
2007-06-17 02:28:45 +04:00
ABIT_UGURU3_DEBUG ( " read from 0x%02x:0x%02x timed out after "
" sending the offset, status: 0x%02x \n " ,
( unsigned int ) bank , ( unsigned int ) offset , x ) ;
return - EIO ;
}
outb ( count , data - > addr + ABIT_UGURU3_CMD ) ;
2012-01-15 00:40:05 +04:00
x = abituguru3_wait_while_busy ( data ) ;
if ( x ! = ABIT_UGURU3_SUCCESS ) {
2007-06-17 02:28:45 +04:00
ABIT_UGURU3_DEBUG ( " read from 0x%02x:0x%02x timed out after "
" sending the count, status: 0x%02x \n " ,
( unsigned int ) bank , ( unsigned int ) offset , x ) ;
return - EIO ;
}
for ( i = 0 ; i < count ; i + + ) {
2012-01-15 00:40:05 +04:00
x = abituguru3_wait_for_read ( data ) ;
if ( x ! = ABIT_UGURU3_SUCCESS ) {
2007-06-17 02:28:45 +04:00
ABIT_UGURU3_DEBUG ( " timeout reading byte %d from "
" 0x%02x:0x%02x, status: 0x%02x \n " , i ,
( unsigned int ) bank , ( unsigned int ) offset , x ) ;
break ;
}
buf [ i ] = inb ( data - > addr + ABIT_UGURU3_CMD ) ;
}
return i ;
}
2012-01-19 23:02:13 +04:00
/*
* Sensor settings are stored 1 byte per offset with the bytes
* placed add consecutive offsets .
*/
2007-07-29 18:57:01 +04:00
static int abituguru3_read_increment_offset ( struct abituguru3_data * data ,
u8 bank , u8 offset , u8 count ,
u8 * buf , int offset_count )
2007-06-17 02:28:45 +04:00
{
int i , x ;
2012-01-15 00:40:05 +04:00
for ( i = 0 ; i < offset_count ; i + + ) {
x = abituguru3_read ( data , bank , offset + i , count ,
buf + i * count ) ;
if ( x ! = count ) {
2009-03-12 15:36:38 +03:00
if ( x < 0 )
return x ;
return i * count + x ;
}
2012-01-15 00:40:05 +04:00
}
2007-06-17 02:28:45 +04:00
return i * count ;
}
2012-01-19 23:02:13 +04:00
/*
* Following are the sysfs callback functions . These functions expect :
* sensor_device_attribute_2 - > index : index into the data - > sensors array
* sensor_device_attribute_2 - > nr : register offset , bitmask or NA .
*/
2007-06-17 02:28:45 +04:00
static struct abituguru3_data * abituguru3_update_device ( struct device * dev ) ;
static ssize_t show_value ( struct device * dev ,
struct device_attribute * devattr , char * buf )
{
int value ;
struct sensor_device_attribute_2 * attr = to_sensor_dev_attr_2 ( devattr ) ;
struct abituguru3_data * data = abituguru3_update_device ( dev ) ;
const struct abituguru3_sensor_info * sensor ;
if ( ! data )
return - EIO ;
sensor = & data - > sensors [ attr - > index ] ;
/* are we reading a setting, or is this a normal read? */
if ( attr - > nr )
value = data - > settings [ sensor - > port ] [ attr - > nr ] ;
else
value = data - > value [ sensor - > port ] ;
/* convert the value */
value = ( value * sensor - > multiplier ) / sensor - > divisor +
sensor - > offset ;
2012-01-19 23:02:13 +04:00
/*
* alternatively we could update the sensors settings struct for this ,
* but then its contents would differ from the windows sw ini files
*/
2007-06-17 02:28:45 +04:00
if ( sensor - > type = = ABIT_UGURU3_TEMP_SENSOR )
value * = 1000 ;
return sprintf ( buf , " %d \n " , value ) ;
}
static ssize_t show_alarm ( struct device * dev ,
struct device_attribute * devattr , char * buf )
{
int port ;
struct sensor_device_attribute_2 * attr = to_sensor_dev_attr_2 ( devattr ) ;
struct abituguru3_data * data = abituguru3_update_device ( dev ) ;
if ( ! data )
return - EIO ;
port = data - > sensors [ attr - > index ] . port ;
2012-01-19 23:02:13 +04:00
/*
* See if the alarm bit for this sensor is set and if a bitmask is
* given in attr - > nr also check if the alarm matches the type of alarm
* we ' re looking for ( for volt it can be either low or high ) . The type
* is stored in a few readonly bits in the settings of the sensor .
*/
2007-06-17 02:28:45 +04:00
if ( ( data - > alarms [ port / 8 ] & ( 0x01 < < ( port % 8 ) ) ) & &
( ! attr - > nr | | ( data - > settings [ port ] [ 0 ] & attr - > nr ) ) )
return sprintf ( buf , " 1 \n " ) ;
else
return sprintf ( buf , " 0 \n " ) ;
}
static ssize_t show_mask ( struct device * dev ,
struct device_attribute * devattr , char * buf )
{
struct sensor_device_attribute_2 * attr = to_sensor_dev_attr_2 ( devattr ) ;
struct abituguru3_data * data = dev_get_drvdata ( dev ) ;
if ( data - > settings [ data - > sensors [ attr - > index ] . port ] [ 0 ] & attr - > nr )
return sprintf ( buf , " 1 \n " ) ;
else
return sprintf ( buf , " 0 \n " ) ;
}
static ssize_t show_label ( struct device * dev ,
struct device_attribute * devattr , char * buf )
{
struct sensor_device_attribute_2 * attr = to_sensor_dev_attr_2 ( devattr ) ;
struct abituguru3_data * data = dev_get_drvdata ( dev ) ;
return sprintf ( buf , " %s \n " , data - > sensors [ attr - > index ] . name ) ;
}
static ssize_t show_name ( struct device * dev ,
struct device_attribute * devattr , char * buf )
{
return sprintf ( buf , " %s \n " , ABIT_UGURU3_NAME ) ;
}
/* Sysfs attr templates, the real entries are generated automatically. */
static const
struct sensor_device_attribute_2 abituguru3_sysfs_templ [ 3 ] [ 10 ] = { {
SENSOR_ATTR_2 ( in % d_input , 0444 , show_value , NULL , 0 , 0 ) ,
SENSOR_ATTR_2 ( in % d_min , 0444 , show_value , NULL , 1 , 0 ) ,
SENSOR_ATTR_2 ( in % d_max , 0444 , show_value , NULL , 2 , 0 ) ,
SENSOR_ATTR_2 ( in % d_min_alarm , 0444 , show_alarm , NULL ,
ABIT_UGURU3_VOLT_LOW_ALARM_FLAG , 0 ) ,
SENSOR_ATTR_2 ( in % d_max_alarm , 0444 , show_alarm , NULL ,
ABIT_UGURU3_VOLT_HIGH_ALARM_FLAG , 0 ) ,
SENSOR_ATTR_2 ( in % d_beep , 0444 , show_mask , NULL ,
ABIT_UGURU3_BEEP_ENABLE , 0 ) ,
SENSOR_ATTR_2 ( in % d_shutdown , 0444 , show_mask , NULL ,
ABIT_UGURU3_SHUTDOWN_ENABLE , 0 ) ,
SENSOR_ATTR_2 ( in % d_min_alarm_enable , 0444 , show_mask , NULL ,
ABIT_UGURU3_VOLT_LOW_ALARM_ENABLE , 0 ) ,
SENSOR_ATTR_2 ( in % d_max_alarm_enable , 0444 , show_mask , NULL ,
ABIT_UGURU3_VOLT_HIGH_ALARM_ENABLE , 0 ) ,
SENSOR_ATTR_2 ( in % d_label , 0444 , show_label , NULL , 0 , 0 )
} , {
SENSOR_ATTR_2 ( temp % d_input , 0444 , show_value , NULL , 0 , 0 ) ,
SENSOR_ATTR_2 ( temp % d_max , 0444 , show_value , NULL , 1 , 0 ) ,
SENSOR_ATTR_2 ( temp % d_crit , 0444 , show_value , NULL , 2 , 0 ) ,
SENSOR_ATTR_2 ( temp % d_alarm , 0444 , show_alarm , NULL , 0 , 0 ) ,
SENSOR_ATTR_2 ( temp % d_beep , 0444 , show_mask , NULL ,
ABIT_UGURU3_BEEP_ENABLE , 0 ) ,
SENSOR_ATTR_2 ( temp % d_shutdown , 0444 , show_mask , NULL ,
ABIT_UGURU3_SHUTDOWN_ENABLE , 0 ) ,
SENSOR_ATTR_2 ( temp % d_alarm_enable , 0444 , show_mask , NULL ,
ABIT_UGURU3_TEMP_HIGH_ALARM_ENABLE , 0 ) ,
SENSOR_ATTR_2 ( temp % d_label , 0444 , show_label , NULL , 0 , 0 )
} , {
SENSOR_ATTR_2 ( fan % d_input , 0444 , show_value , NULL , 0 , 0 ) ,
SENSOR_ATTR_2 ( fan % d_min , 0444 , show_value , NULL , 1 , 0 ) ,
SENSOR_ATTR_2 ( fan % d_alarm , 0444 , show_alarm , NULL , 0 , 0 ) ,
SENSOR_ATTR_2 ( fan % d_beep , 0444 , show_mask , NULL ,
ABIT_UGURU3_BEEP_ENABLE , 0 ) ,
SENSOR_ATTR_2 ( fan % d_shutdown , 0444 , show_mask , NULL ,
ABIT_UGURU3_SHUTDOWN_ENABLE , 0 ) ,
SENSOR_ATTR_2 ( fan % d_alarm_enable , 0444 , show_mask , NULL ,
ABIT_UGURU3_FAN_LOW_ALARM_ENABLE , 0 ) ,
SENSOR_ATTR_2 ( fan % d_label , 0444 , show_label , NULL , 0 , 0 )
} } ;
static struct sensor_device_attribute_2 abituguru3_sysfs_attr [ ] = {
SENSOR_ATTR_2 ( name , 0444 , show_name , NULL , 0 , 0 ) ,
} ;
2012-11-19 22:22:35 +04:00
static int abituguru3_probe ( struct platform_device * pdev )
2007-06-17 02:28:45 +04:00
{
const int no_sysfs_attr [ 3 ] = { 10 , 8 , 7 } ;
int sensor_index [ 3 ] = { 0 , 1 , 1 } ;
struct abituguru3_data * data ;
int i , j , type , used , sysfs_names_free , sysfs_attr_i , res = - ENODEV ;
char * sysfs_filename ;
u8 buf [ 2 ] ;
u16 id ;
2012-06-02 20:57:57 +04:00
data = devm_kzalloc ( & pdev - > dev , sizeof ( struct abituguru3_data ) ,
GFP_KERNEL ) ;
2012-01-15 00:40:05 +04:00
if ( ! data )
2007-06-17 02:28:45 +04:00
return - ENOMEM ;
data - > addr = platform_get_resource ( pdev , IORESOURCE_IO , 0 ) - > start ;
mutex_init ( & data - > update_lock ) ;
platform_set_drvdata ( pdev , data ) ;
/* Read the motherboard ID */
2012-01-15 00:40:05 +04:00
i = abituguru3_read ( data , ABIT_UGURU3_MISC_BANK , ABIT_UGURU3_BOARD_ID ,
2 , buf ) ;
if ( i ! = 2 )
2007-06-17 02:28:45 +04:00
goto abituguru3_probe_error ;
/* Completely read the uGuru to see if one really is there */
if ( ! abituguru3_update_device ( & pdev - > dev ) )
goto abituguru3_probe_error ;
/* lookup the ID in our motherboard table */
id = ( ( u16 ) buf [ 0 ] < < 8 ) | ( u16 ) buf [ 1 ] ;
for ( i = 0 ; abituguru3_motherboards [ i ] . id ; i + + )
if ( abituguru3_motherboards [ i ] . id = = id )
break ;
if ( ! abituguru3_motherboards [ i ] . id ) {
2010-10-20 10:51:26 +04:00
pr_err ( " error unknown motherboard ID: %04X. %s \n " ,
( unsigned int ) id , report_this ) ;
2007-06-17 02:28:45 +04:00
goto abituguru3_probe_error ;
}
data - > sensors = abituguru3_motherboards [ i ] . sensors ;
2008-08-15 11:40:39 +04:00
2010-10-20 10:51:26 +04:00
pr_info ( " found Abit uGuru3, motherboard ID: %04X \n " , ( unsigned int ) id ) ;
2008-08-15 11:40:39 +04:00
2007-06-17 02:28:45 +04:00
/* Fill the sysfs attr array */
sysfs_attr_i = 0 ;
sysfs_filename = data - > sysfs_names ;
sysfs_names_free = ABIT_UGURU3_SYSFS_NAMES_LENGTH ;
for ( i = 0 ; data - > sensors [ i ] . name ; i + + ) {
/* Fail safe check, this should never happen! */
if ( i > = ABIT_UGURU3_MAX_NO_SENSORS ) {
2010-10-20 10:51:26 +04:00
pr_err ( " Fatal error motherboard has more sensors then ABIT_UGURU3_MAX_NO_SENSORS. %s %s \n " ,
never_happen , report_this ) ;
2007-06-17 02:28:45 +04:00
res = - ENAMETOOLONG ;
goto abituguru3_probe_error ;
}
type = data - > sensors [ i ] . type ;
for ( j = 0 ; j < no_sysfs_attr [ type ] ; j + + ) {
used = snprintf ( sysfs_filename , sysfs_names_free ,
abituguru3_sysfs_templ [ type ] [ j ] . dev_attr . attr .
name , sensor_index [ type ] ) + 1 ;
data - > sysfs_attr [ sysfs_attr_i ] =
abituguru3_sysfs_templ [ type ] [ j ] ;
data - > sysfs_attr [ sysfs_attr_i ] . dev_attr . attr . name =
sysfs_filename ;
data - > sysfs_attr [ sysfs_attr_i ] . index = i ;
sysfs_filename + = used ;
sysfs_names_free - = used ;
sysfs_attr_i + + ;
}
sensor_index [ type ] + + ;
}
/* Fail safe check, this should never happen! */
if ( sysfs_names_free < 0 ) {
2010-10-20 10:51:26 +04:00
pr_err ( " Fatal error ran out of space for sysfs attr names. %s %s \n " ,
never_happen , report_this ) ;
2007-06-17 02:28:45 +04:00
res = - ENAMETOOLONG ;
goto abituguru3_probe_error ;
}
/* Register sysfs hooks */
for ( i = 0 ; i < sysfs_attr_i ; i + + )
if ( device_create_file ( & pdev - > dev ,
& data - > sysfs_attr [ i ] . dev_attr ) )
goto abituguru3_probe_error ;
for ( i = 0 ; i < ARRAY_SIZE ( abituguru3_sysfs_attr ) ; i + + )
if ( device_create_file ( & pdev - > dev ,
& abituguru3_sysfs_attr [ i ] . dev_attr ) )
goto abituguru3_probe_error ;
2007-08-21 00:46:20 +04:00
data - > hwmon_dev = hwmon_device_register ( & pdev - > dev ) ;
if ( IS_ERR ( data - > hwmon_dev ) ) {
res = PTR_ERR ( data - > hwmon_dev ) ;
2007-06-17 02:28:45 +04:00
goto abituguru3_probe_error ;
}
return 0 ; /* success */
abituguru3_probe_error :
for ( i = 0 ; data - > sysfs_attr [ i ] . dev_attr . attr . name ; i + + )
device_remove_file ( & pdev - > dev , & data - > sysfs_attr [ i ] . dev_attr ) ;
for ( i = 0 ; i < ARRAY_SIZE ( abituguru3_sysfs_attr ) ; i + + )
device_remove_file ( & pdev - > dev ,
& abituguru3_sysfs_attr [ i ] . dev_attr ) ;
return res ;
}
2012-11-19 22:25:51 +04:00
static int abituguru3_remove ( struct platform_device * pdev )
2007-06-17 02:28:45 +04:00
{
int i ;
struct abituguru3_data * data = platform_get_drvdata ( pdev ) ;
2007-08-21 00:46:20 +04:00
hwmon_device_unregister ( data - > hwmon_dev ) ;
2007-06-17 02:28:45 +04:00
for ( i = 0 ; data - > sysfs_attr [ i ] . dev_attr . attr . name ; i + + )
device_remove_file ( & pdev - > dev , & data - > sysfs_attr [ i ] . dev_attr ) ;
for ( i = 0 ; i < ARRAY_SIZE ( abituguru3_sysfs_attr ) ; i + + )
device_remove_file ( & pdev - > dev ,
& abituguru3_sysfs_attr [ i ] . dev_attr ) ;
return 0 ;
}
static struct abituguru3_data * abituguru3_update_device ( struct device * dev )
{
int i ;
struct abituguru3_data * data = dev_get_drvdata ( dev ) ;
mutex_lock ( & data - > update_lock ) ;
if ( ! data - > valid | | time_after ( jiffies , data - > last_updated + HZ ) ) {
/* Clear data->valid while updating */
data - > valid = 0 ;
/* Read alarms */
if ( abituguru3_read_increment_offset ( data ,
ABIT_UGURU3_SETTINGS_BANK ,
ABIT_UGURU3_ALARMS_START ,
1 , data - > alarms , 48 / 8 ) ! = ( 48 / 8 ) )
goto LEAVE_UPDATE ;
/* Read in and temp sensors (3 byte settings / sensor) */
for ( i = 0 ; i < 32 ; i + + ) {
if ( abituguru3_read ( data , ABIT_UGURU3_SENSORS_BANK ,
ABIT_UGURU3_VALUES_START + i ,
1 , & data - > value [ i ] ) ! = 1 )
goto LEAVE_UPDATE ;
if ( abituguru3_read_increment_offset ( data ,
ABIT_UGURU3_SETTINGS_BANK ,
ABIT_UGURU3_SETTINGS_START + i * 3 ,
1 ,
data - > settings [ i ] , 3 ) ! = 3 )
goto LEAVE_UPDATE ;
}
/* Read temp sensors (2 byte settings / sensor) */
for ( i = 0 ; i < 16 ; i + + ) {
if ( abituguru3_read ( data , ABIT_UGURU3_SENSORS_BANK ,
ABIT_UGURU3_VALUES_START + 32 + i ,
1 , & data - > value [ 32 + i ] ) ! = 1 )
goto LEAVE_UPDATE ;
if ( abituguru3_read_increment_offset ( data ,
ABIT_UGURU3_SETTINGS_BANK ,
ABIT_UGURU3_SETTINGS_START + 32 * 3 +
i * 2 , 1 ,
data - > settings [ 32 + i ] , 2 ) ! = 2 )
goto LEAVE_UPDATE ;
}
data - > last_updated = jiffies ;
data - > valid = 1 ;
}
LEAVE_UPDATE :
mutex_unlock ( & data - > update_lock ) ;
if ( data - > valid )
return data ;
else
return NULL ;
}
2012-07-08 02:00:01 +04:00
# ifdef CONFIG_PM_SLEEP
static int abituguru3_suspend ( struct device * dev )
2007-06-17 02:28:45 +04:00
{
2012-07-08 02:00:01 +04:00
struct abituguru3_data * data = dev_get_drvdata ( dev ) ;
2012-01-19 23:02:13 +04:00
/*
* make sure all communications with the uguru3 are done and no new
* ones are started
*/
2007-06-17 02:28:45 +04:00
mutex_lock ( & data - > update_lock ) ;
return 0 ;
}
2012-07-08 02:00:01 +04:00
static int abituguru3_resume ( struct device * dev )
2007-06-17 02:28:45 +04:00
{
2012-07-08 02:00:01 +04:00
struct abituguru3_data * data = dev_get_drvdata ( dev ) ;
2007-06-17 02:28:45 +04:00
mutex_unlock ( & data - > update_lock ) ;
return 0 ;
}
2012-07-08 02:00:01 +04:00
static SIMPLE_DEV_PM_OPS ( abituguru3_pm , abituguru3_suspend , abituguru3_resume ) ;
2013-01-10 17:54:40 +04:00
# define ABIT_UGURU3_PM (&abituguru3_pm)
2007-06-17 02:28:45 +04:00
# else
2012-07-08 02:00:01 +04:00
# define ABIT_UGURU3_PM NULL
2007-06-17 02:28:45 +04:00
# endif /* CONFIG_PM */
static struct platform_driver abituguru3_driver = {
. driver = {
. name = ABIT_UGURU3_NAME ,
2012-07-08 02:00:01 +04:00
. pm = ABIT_UGURU3_PM
2007-06-17 02:28:45 +04:00
} ,
. probe = abituguru3_probe ,
2012-11-19 22:21:20 +04:00
. remove = abituguru3_remove ,
2007-06-17 02:28:45 +04:00
} ;
2008-08-15 11:40:39 +04:00
static int __init abituguru3_dmi_detect ( void )
{
const char * board_vendor , * board_name ;
int i , err = ( force ) ? 1 : - ENODEV ;
2009-09-15 19:18:10 +04:00
const char * const * dmi_name ;
2009-01-16 00:27:47 +03:00
size_t sublen ;
2008-08-15 11:40:39 +04:00
board_vendor = dmi_get_system_info ( DMI_BOARD_VENDOR ) ;
if ( ! board_vendor | | strcmp ( board_vendor , " http://www.abit.com.tw/ " ) )
return err ;
board_name = dmi_get_system_info ( DMI_BOARD_NAME ) ;
if ( ! board_name )
return err ;
2012-01-19 23:02:13 +04:00
/*
* At the moment , we don ' t care about the part of the vendor
2009-01-16 00:27:47 +03:00
* DMI string contained in brackets . Truncate the string at
* the first occurrence of a bracket . Trim any trailing space
* from the substring .
*/
sublen = strcspn ( board_name , " ( " ) ;
while ( sublen > 0 & & board_name [ sublen - 1 ] = = ' ' )
sublen - - ;
2008-08-15 11:40:39 +04:00
for ( i = 0 ; abituguru3_motherboards [ i ] . id ; i + + ) {
2009-09-15 19:18:10 +04:00
dmi_name = abituguru3_motherboards [ i ] . dmi_name ;
for ( ; * dmi_name ; dmi_name + + ) {
if ( strlen ( * dmi_name ) ! = sublen )
continue ;
if ( ! strncasecmp ( board_name , * dmi_name , sublen ) )
return 0 ;
}
2008-08-15 11:40:39 +04:00
}
2009-09-15 19:18:10 +04:00
/* No match found */
return 1 ;
2008-08-15 11:40:39 +04:00
}
2012-01-19 23:02:13 +04:00
/*
* FIXME : Manual detection should die eventually ; we need to collect stable
2008-08-15 11:40:39 +04:00
* DMI model names first before we can rely entirely on CONFIG_DMI .
*/
2007-06-17 02:28:45 +04:00
static int __init abituguru3_detect ( void )
{
2012-01-19 23:02:13 +04:00
/*
* See if there is an uguru3 there . An idle uGuru3 will hold 0x00 or
* 0x08 at DATA and 0xAC at CMD . Sometimes the uGuru3 will hold 0x05
* or 0x55 at CMD instead , why is unknown .
*/
2007-06-17 02:28:45 +04:00
u8 data_val = inb_p ( ABIT_UGURU3_BASE + ABIT_UGURU3_DATA ) ;
u8 cmd_val = inb_p ( ABIT_UGURU3_BASE + ABIT_UGURU3_CMD ) ;
2007-07-03 01:08:26 +04:00
if ( ( ( data_val = = 0x00 ) | | ( data_val = = 0x08 ) ) & &
2008-05-23 18:10:41 +04:00
( ( cmd_val = = 0xAC ) | | ( cmd_val = = 0x05 ) | |
( cmd_val = = 0x55 ) ) )
2008-08-15 11:40:39 +04:00
return 0 ;
2007-06-17 02:28:45 +04:00
ABIT_UGURU3_DEBUG ( " no Abit uGuru3 found, data = 0x%02X, cmd = "
" 0x%02X \n " , ( unsigned int ) data_val , ( unsigned int ) cmd_val ) ;
if ( force ) {
2010-10-20 10:51:26 +04:00
pr_info ( " Assuming Abit uGuru3 is present because of \" force \" parameter \n " ) ;
2008-08-15 11:40:39 +04:00
return 0 ;
2007-06-17 02:28:45 +04:00
}
/* No uGuru3 found */
return - ENODEV ;
}
static struct platform_device * abituguru3_pdev ;
static int __init abituguru3_init ( void )
{
struct resource res = { . flags = IORESOURCE_IO } ;
2008-08-15 11:40:39 +04:00
int err ;
/* Attempt DMI detection first */
err = abituguru3_dmi_detect ( ) ;
if ( err < 0 )
return err ;
2012-01-19 23:02:13 +04:00
/*
* Fall back to manual detection if there was no exact
2008-08-15 11:40:39 +04:00
* board name match , or force was specified .
*/
if ( err > 0 ) {
err = abituguru3_detect ( ) ;
if ( err )
return err ;
2009-09-15 19:18:10 +04:00
2010-10-20 10:51:26 +04:00
pr_warn ( " this motherboard was not detected using DMI. "
" Please send the output of \" dmidecode \" to the abituguru3 maintainer (see MAINTAINERS) \n " ) ;
2008-08-15 11:40:39 +04:00
}
2007-06-17 02:28:45 +04:00
err = platform_driver_register ( & abituguru3_driver ) ;
if ( err )
goto exit ;
2008-08-15 11:40:39 +04:00
abituguru3_pdev = platform_device_alloc ( ABIT_UGURU3_NAME ,
ABIT_UGURU3_BASE ) ;
2007-06-17 02:28:45 +04:00
if ( ! abituguru3_pdev ) {
2010-10-20 10:51:26 +04:00
pr_err ( " Device allocation failed \n " ) ;
2007-06-17 02:28:45 +04:00
err = - ENOMEM ;
goto exit_driver_unregister ;
}
2008-08-15 11:40:39 +04:00
res . start = ABIT_UGURU3_BASE ;
res . end = ABIT_UGURU3_BASE + ABIT_UGURU3_REGION_LENGTH - 1 ;
2007-06-17 02:28:45 +04:00
res . name = ABIT_UGURU3_NAME ;
err = platform_device_add_resources ( abituguru3_pdev , & res , 1 ) ;
if ( err ) {
2010-10-20 10:51:26 +04:00
pr_err ( " Device resource addition failed (%d) \n " , err ) ;
2007-06-17 02:28:45 +04:00
goto exit_device_put ;
}
err = platform_device_add ( abituguru3_pdev ) ;
if ( err ) {
2010-10-20 10:51:26 +04:00
pr_err ( " Device addition failed (%d) \n " , err ) ;
2007-06-17 02:28:45 +04:00
goto exit_device_put ;
}
return 0 ;
exit_device_put :
platform_device_put ( abituguru3_pdev ) ;
exit_driver_unregister :
platform_driver_unregister ( & abituguru3_driver ) ;
exit :
return err ;
}
static void __exit abituguru3_exit ( void )
{
platform_device_unregister ( abituguru3_pdev ) ;
platform_driver_unregister ( & abituguru3_driver ) ;
}
2011-03-21 19:59:36 +03:00
MODULE_AUTHOR ( " Hans de Goede <hdegoede@redhat.com> " ) ;
2007-06-17 02:28:45 +04:00
MODULE_DESCRIPTION ( " Abit uGuru3 Sensor device " ) ;
MODULE_LICENSE ( " GPL " ) ;
module_init ( abituguru3_init ) ;
module_exit ( abituguru3_exit ) ;