diff options
Diffstat (limited to 'drivers/hwmon/abituguru3.c')
| -rw-r--r-- | drivers/hwmon/abituguru3.c | 500 |
1 files changed, 313 insertions, 187 deletions
diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c index ed33fddc4de..4ae74aa8cdc 100644 --- a/drivers/hwmon/abituguru3.c +++ b/drivers/hwmon/abituguru3.c @@ -1,25 +1,31 @@ /* - abituguru3.c Copyright (c) 2006 Hans de Goede <j.w.r.degoede@hhs.nl> - - 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 02139, USA. -*/ + * 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 02139, USA. + */ /* - 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. -*/ + * 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. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> @@ -30,7 +36,8 @@ #include <linux/platform_device.h> #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> -#include <asm/io.h> +#include <linux/dmi.h> +#include <linux/io.h> /* uGuru3 bank addresses */ #define ABIT_UGURU3_SETTINGS_BANK 0x01 @@ -55,48 +62,67 @@ #define ABIT_UGURU3_TEMP_SENSOR 1 #define ABIT_UGURU3_FAN_SENSOR 2 -/* 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. */ +/* + * 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. + */ #define ABIT_UGURU3_WAIT_TIMEOUT 250 -/* Normally the 0xAC at the end of synchronize() is reported after the - first read, but sometimes not and we need to poll */ +/* + * Normally the 0xAC at the end of synchronize() is reported after the + * first read, but sometimes not and we need to poll + */ #define ABIT_UGURU3_SYNCHRONIZE_TIMEOUT 5 /* utility macros */ #define ABIT_UGURU3_NAME "abituguru3" -#define ABIT_UGURU3_DEBUG(format, arg...) \ - if (verbose) \ - printk(KERN_DEBUG ABIT_UGURU3_NAME ": " format , ## arg) +#define ABIT_UGURU3_DEBUG(format, arg...) \ + do { \ + if (verbose) \ + pr_debug(format , ## arg); \ + } while (0) /* Macros to help calculate the sysfs_names array length */ #define ABIT_UGURU3_MAX_NO_SENSORS 26 -/* 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 */ -#define ABIT_UGURU3_IN_NAMES_LENGTH (11 + 2 * 9 + 2 * 15 + 2 * 22 + 10 + 14 + 11) -/* 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 */ +/* + * 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 + */ +#define ABIT_UGURU3_IN_NAMES_LENGTH \ + (11 + 2 * 9 + 2 * 15 + 2 * 22 + 10 + 14 + 11) +/* + * 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 + */ #define ABIT_UGURU3_TEMP_NAMES_LENGTH (13 + 11 + 12 + 13 + 20 + 12 + 16 + 13) -/* 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 */ +/* + * 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 + */ #define ABIT_UGURU3_FAN_NAMES_LENGTH (12 + 10 + 12 + 19 + 11 + 15 + 12) -/* Worst case scenario 16 in sensors (longest names_length) and the rest - temp sensors (second longest names_length). */ +/* + * Worst case scenario 16 in sensors (longest names_length) and the rest + * temp sensors (second longest names_length). + */ #define ABIT_UGURU3_SYSFS_NAMES_LENGTH (16 * ABIT_UGURU3_IN_NAMES_LENGTH + \ (ABIT_UGURU3_MAX_NO_SENSORS - 16) * ABIT_UGURU3_TEMP_NAMES_LENGTH) -/* 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. */ +/* + * 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. + */ /* 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 -/* The wait_xxx functions return this on success and the last contents - of the DATA register (0-255) on failure. */ +/* + * The wait_xxx functions return this on success and the last contents + * of the DATA register (0-255) on failure. + */ #define ABIT_UGURU3_SUCCESS -1 /* uGuru status flags */ #define ABIT_UGURU3_STATUS_READY_FOR_READ 0x01 @@ -105,7 +131,7 @@ /* Structures */ struct abituguru3_sensor_info { - const char* name; + const char *name; int port; int type; int multiplier; @@ -113,16 +139,21 @@ struct abituguru3_sensor_info { int offset; }; +/* Avoid use of flexible array members */ +#define ABIT_UGURU3_MAX_DMI_NAMES 2 + struct abituguru3_motherboard_info { u16 id; - const char *name; + const char *dmi_name[ABIT_UGURU3_MAX_DMI_NAMES + 1]; /* + 1 -> end of sensors indicated by a sensor with name == NULL */ struct abituguru3_sensor_info sensors[ABIT_UGURU3_MAX_NO_SENSORS + 1]; }; -/* 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. */ +/* + * 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. + */ struct abituguru3_data { struct device *hwmon_dev; /* hwmon registered device */ struct mutex update_lock; /* protect access to data and uGuru */ @@ -130,8 +161,10 @@ struct abituguru3_data { char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ - /* For convenience the sysfs attr and their names are generated - automatically. We have max 10 entries per sensor (for in sensors) */ + /* + * For convenience the sysfs attr and their names are generated + * automatically. We have max 10 entries per sensor (for in sensors) + */ struct sensor_device_attribute_2 sysfs_attr[ABIT_UGURU3_MAX_NO_SENSORS * 10]; @@ -141,9 +174,11 @@ struct abituguru3_data { /* Pointer to the sensors info for the detected motherboard */ const struct abituguru3_sensor_info *sensors; - /* The abituguru3 supports upto 48 sensors, and thus has registers - sets for 48 sensors, for convienence reasons / simplicity of the - code we always read and store all registers for all 48 sensors */ + /* + * The abituguru3 supports up to 48 sensors, and thus has registers + * sets for 48 sensors, for convenience reasons / simplicity of the + * code we always read and store all registers for all 48 sensors + */ /* Alarms for all 48 sensors (1 bit per sensor) */ u8 alarms[48/8]; @@ -151,16 +186,18 @@ struct abituguru3_data { /* Value of all 48 sensors */ u8 value[48]; - /* 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 */ + /* + * 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 + */ u8 settings[48][3]; }; /* Constants */ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { - { 0x000C, "unknown", { + { 0x000C, { NULL } /* Unknown, need DMI string */, { { "CPU Core", 0, 0, 10, 1, 0 }, { "DDR", 1, 0, 10, 1, 0 }, { "DDR VTT", 2, 0, 10, 1, 0 }, @@ -174,7 +211,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "+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 }, + { "System", 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 }, @@ -182,7 +219,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "AUX1 Fan", 35, 2, 60, 1, 0 }, { NULL, 0, 0, 0, 0, 0 } } }, - { 0x000D, "Abit AW8", { + { 0x000D, { NULL } /* Abit AW8, need DMI string */, { { "CPU Core", 0, 0, 10, 1, 0 }, { "DDR", 1, 0, 10, 1, 0 }, { "DDR VTT", 2, 0, 10, 1, 0 }, @@ -196,7 +233,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "+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 }, + { "System", 25, 1, 1, 1, 0 }, { "PWM1", 26, 1, 1, 1, 0 }, { "PWM2", 27, 1, 1, 1, 0 }, { "PWM3", 28, 1, 1, 1, 0 }, @@ -211,7 +248,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "AUX5 Fan", 39, 2, 60, 1, 0 }, { NULL, 0, 0, 0, 0, 0 } } }, - { 0x000E, "AL-8", { + { 0x000E, { NULL } /* AL-8, need DMI string */, { { "CPU Core", 0, 0, 10, 1, 0 }, { "DDR", 1, 0, 10, 1, 0 }, { "DDR VTT", 2, 0, 10, 1, 0 }, @@ -225,14 +262,15 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "+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 }, + { "System", 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 }, { NULL, 0, 0, 0, 0, 0 } } }, - { 0x000F, "unknown", { + { 0x000F, { NULL } /* Unknown, need DMI string */, { + { "CPU Core", 0, 0, 10, 1, 0 }, { "DDR", 1, 0, 10, 1, 0 }, { "DDR VTT", 2, 0, 10, 1, 0 }, @@ -246,14 +284,14 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "+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 }, + { "System", 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 }, { NULL, 0, 0, 0, 0, 0 } } }, - { 0x0010, "Abit NI8 SLI GR", { + { 0x0010, { NULL } /* Abit NI8 SLI GR, need DMI string */, { { "CPU Core", 0, 0, 10, 1, 0 }, { "DDR", 1, 0, 10, 1, 0 }, { "DDR VTT", 2, 0, 10, 1, 0 }, @@ -275,7 +313,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "OTES1 Fan", 36, 2, 60, 1, 0 }, { NULL, 0, 0, 0, 0, 0 } } }, - { 0x0011, "Abit AT8 32X", { + { 0x0011, { "AT8 32X", NULL }, { { "CPU Core", 0, 0, 10, 1, 0 }, { "DDR", 1, 0, 20, 1, 0 }, { "DDR VTT", 2, 0, 10, 1, 0 }, @@ -299,9 +337,10 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "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 } } }, - { 0x0012, "Abit AN8 32X", { + { 0x0012, { NULL } /* Abit AN8 32X, need DMI string */, { { "CPU Core", 0, 0, 10, 1, 0 }, { "DDR", 1, 0, 20, 1, 0 }, { "DDR VTT", 2, 0, 10, 1, 0 }, @@ -323,7 +362,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "AUX1 Fan", 36, 2, 60, 1, 0 }, { NULL, 0, 0, 0, 0, 0 } } }, - { 0x0013, "unknown", { + { 0x0013, { NULL } /* Abit AW8D, need DMI string */, { { "CPU Core", 0, 0, 10, 1, 0 }, { "DDR", 1, 0, 10, 1, 0 }, { "DDR VTT", 2, 0, 10, 1, 0 }, @@ -337,7 +376,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "+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 }, + { "System", 25, 1, 1, 1, 0 }, { "PWM1", 26, 1, 1, 1, 0 }, { "PWM2", 27, 1, 1, 1, 0 }, { "PWM3", 28, 1, 1, 1, 0 }, @@ -349,9 +388,10 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "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 } } }, - { 0x0014, "Abit AB9 Pro", { + { 0x0014, { "AB9", "AB9 Pro", NULL }, { { "CPU Core", 0, 0, 10, 1, 0 }, { "DDR", 1, 0, 10, 1, 0 }, { "DDR VTT", 2, 0, 10, 1, 0 }, @@ -365,14 +405,14 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "+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 }, + { "System", 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 }, { NULL, 0, 0, 0, 0, 0 } } }, - { 0x0015, "unknown", { + { 0x0015, { NULL } /* Unknown, need DMI string */, { { "CPU Core", 0, 0, 10, 1, 0 }, { "DDR", 1, 0, 20, 1, 0 }, { "DDR VTT", 2, 0, 10, 1, 0 }, @@ -396,7 +436,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "AUX3 Fan", 36, 2, 60, 1, 0 }, { NULL, 0, 0, 0, 0, 0 } } }, - { 0x0016, "AW9D-MAX", { + { 0x0016, { "AW9D-MAX", NULL }, { { "CPU Core", 0, 0, 10, 1, 0 }, { "DDR2", 1, 0, 20, 1, 0 }, { "DDR2 VTT", 2, 0, 10, 1, 0 }, @@ -410,7 +450,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "+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 }, + { "System", 25, 1, 1, 1, 0 }, { "PWM1", 26, 1, 1, 1, 0 }, { "PWM2", 27, 1, 1, 1, 0 }, { "PWM3", 28, 1, 1, 1, 0 }, @@ -424,7 +464,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "OTES1 Fan", 38, 2, 60, 1, 0 }, { NULL, 0, 0, 0, 0, 0 } } }, - { 0x0017, "unknown", { + { 0x0017, { NULL } /* Unknown, need DMI string */, { { "CPU Core", 0, 0, 10, 1, 0 }, { "DDR2", 1, 0, 20, 1, 0 }, { "DDR2 VTT", 2, 0, 10, 1, 0 }, @@ -440,7 +480,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "ATX +3.3V", 10, 0, 20, 1, 0 }, { "ATX 5VSB", 11, 0, 30, 1, 0 }, { "CPU", 24, 1, 1, 1, 0 }, - { "System ", 26, 1, 1, 1, 0 }, + { "System", 26, 1, 1, 1, 0 }, { "PWM", 27, 1, 1, 1, 0 }, { "CPU FAN", 32, 2, 60, 1, 0 }, { "SYS FAN", 34, 2, 60, 1, 0 }, @@ -449,7 +489,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "AUX3 FAN", 37, 2, 60, 1, 0 }, { NULL, 0, 0, 0, 0, 0 } } }, - { 0x0018, "unknown", { + { 0x0018, { "AB9 QuadGT", NULL }, { { "CPU Core", 0, 0, 10, 1, 0 }, { "DDR2", 1, 0, 20, 1, 0 }, { "DDR2 VTT", 2, 0, 10, 1, 0 }, @@ -463,7 +503,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "+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 }, + { "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 }, @@ -476,12 +516,12 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "AUX3 Fan", 36, 2, 60, 1, 0 }, { NULL, 0, 0, 0, 0, 0 } } }, - { 0x0019, "unknown", { + { 0x0019, { "IN9 32X MAX", NULL }, { { "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 }, - { "NB 1.2V ", 4, 0, 10, 1, 0 }, + { "NB 1.2V", 4, 0, 10, 1, 0 }, { "SB 1.5V", 6, 0, 10, 1, 0 }, { "HyperTransport", 5, 0, 10, 1, 0 }, { "ATX +12V (24-Pin)", 12, 0, 60, 1, 0 }, @@ -490,7 +530,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "ATX +3.3V", 10, 0, 20, 1, 0 }, { "ATX 5VSB", 11, 0, 30, 1, 0 }, { "CPU", 24, 1, 1, 1, 0 }, - { "System ", 25, 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 }, @@ -503,7 +543,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "AUX3 FAN", 36, 2, 60, 1, 0 }, { NULL, 0, 0, 0, 0, 0 } } }, - { 0x001A, "Abit IP35 Pro", { + { 0x001A, { "IP35 Pro", "IP35 Pro XE", NULL }, { { "CPU Core", 0, 0, 10, 1, 0 }, { "DDR2", 1, 0, 20, 1, 0 }, { "DDR2 VTT", 2, 0, 10, 1, 0 }, @@ -517,8 +557,8 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "+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 ", 26, 1, 1, 1, 0 }, + { "System", 25, 1, 1, 1, 0 }, + { "PWM", 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 }, @@ -531,7 +571,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "AUX4 Fan", 37, 2, 60, 1, 0 }, { NULL, 0, 0, 0, 0, 0 } } }, - { 0x001B, "unknown", { + { 0x001B, { NULL } /* Unknown, need DMI string */, { { "CPU Core", 0, 0, 10, 1, 0 }, { "DDR3", 1, 0, 20, 1, 0 }, { "DDR3 VTT", 2, 0, 10, 1, 0 }, @@ -558,7 +598,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "AUX3 Fan", 36, 2, 60, 1, 0 }, { NULL, 0, 0, 0, 0, 0 } } }, - { 0x001C, "unknown", { + { 0x001C, { "IX38 QuadGT", NULL }, { { "CPU Core", 0, 0, 10, 1, 0 }, { "DDR2", 1, 0, 20, 1, 0 }, { "DDR2 VTT", 2, 0, 10, 1, 0 }, @@ -585,19 +625,22 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "AUX3 Fan", 36, 2, 60, 1, 0 }, { NULL, 0, 0, 0, 0, 0 } } }, - { 0x0000, NULL, { { NULL, 0, 0, 0, 0, 0 } } } + { 0x0000, { NULL }, { { NULL, 0, 0, 0, 0, 0 } } } }; /* Insmod parameters */ -static int force; +static bool force; 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 */ -static int verbose = 1; +static bool verbose = 1; module_param(verbose, bool, 0644); MODULE_PARM_DESC(verbose, "Enable/disable verbose error reporting"); +static const char *never_happen = "This should never happen."; +static const char *report_this = + "Please report this to the abituguru3 maintainer (see MAINTAINERS)"; /* wait while the uguru is busy (usually after a write) */ static int abituguru3_wait_while_busy(struct abituguru3_data *data) @@ -610,8 +653,10 @@ static int abituguru3_wait_while_busy(struct abituguru3_data *data) timeout--; if (timeout == 0) return x; - /* sleep a bit before our last try, to give the uGuru3 one - last chance to respond. */ + /* + * sleep a bit before our last try, to give the uGuru3 one + * last chance to respond. + */ if (timeout == 1) msleep(1); } @@ -629,48 +674,57 @@ static int abituguru3_wait_for_read(struct abituguru3_data *data) timeout--; if (timeout == 0) return x; - /* sleep a bit before our last try, to give the uGuru3 one - last chance to respond. */ + /* + * sleep a bit before our last try, to give the uGuru3 one + * last chance to respond. + */ if (timeout == 1) msleep(1); } return ABIT_UGURU3_SUCCESS; } -/* This synchronizes us with the uGuru3's protocol state machine, this - must be done before each command. */ +/* + * This synchronizes us with the uGuru3's protocol state machine, this + * must be done before each command. + */ static int abituguru3_synchronize(struct abituguru3_data *data) { int x, timeout = ABIT_UGURU3_SYNCHRONIZE_TIMEOUT; - if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) { + x = abituguru3_wait_while_busy(data); + if (x != ABIT_UGURU3_SUCCESS) { ABIT_UGURU3_DEBUG("synchronize timeout during initial busy " "wait, status: 0x%02x\n", x); return -EIO; } outb(0x20, data->addr + ABIT_UGURU3_DATA); - if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) { + x = abituguru3_wait_while_busy(data); + if (x != ABIT_UGURU3_SUCCESS) { ABIT_UGURU3_DEBUG("synchronize timeout after sending 0x20, " "status: 0x%02x\n", x); return -EIO; } outb(0x10, data->addr + ABIT_UGURU3_CMD); - if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) { + x = abituguru3_wait_while_busy(data); + if (x != ABIT_UGURU3_SUCCESS) { ABIT_UGURU3_DEBUG("synchronize timeout after sending 0x10, " "status: 0x%02x\n", x); return -EIO; } outb(0x00, data->addr + ABIT_UGURU3_CMD); - if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) { + x = abituguru3_wait_while_busy(data); + if (x != ABIT_UGURU3_SUCCESS) { ABIT_UGURU3_DEBUG("synchronize timeout after sending 0x00, " "status: 0x%02x\n", x); return -EIO; } - if ((x = abituguru3_wait_for_read(data)) != ABIT_UGURU3_SUCCESS) { + x = abituguru3_wait_for_read(data); + if (x != ABIT_UGURU3_SUCCESS) { ABIT_UGURU3_DEBUG("synchronize timeout waiting for read, " "status: 0x%02x\n", x); return -EIO; @@ -689,18 +743,22 @@ static int abituguru3_synchronize(struct abituguru3_data *data) return 0; } -/* Read count bytes from sensor sensor_addr in bank bank_addr and store the - result in buf */ +/* + * Read count bytes from sensor sensor_addr in bank bank_addr and store the + * result in buf + */ static int abituguru3_read(struct abituguru3_data *data, u8 bank, u8 offset, u8 count, u8 *buf) { int i, x; - if ((x = abituguru3_synchronize(data))) + x = abituguru3_synchronize(data); + if (x) return x; outb(0x1A, data->addr + ABIT_UGURU3_DATA); - if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) { + x = abituguru3_wait_while_busy(data); + if (x != ABIT_UGURU3_SUCCESS) { 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); @@ -708,7 +766,8 @@ static int abituguru3_read(struct abituguru3_data *data, u8 bank, u8 offset, } outb(bank, data->addr + ABIT_UGURU3_CMD); - if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) { + x = abituguru3_wait_while_busy(data); + if (x != ABIT_UGURU3_SUCCESS) { 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); @@ -716,7 +775,8 @@ static int abituguru3_read(struct abituguru3_data *data, u8 bank, u8 offset, } outb(offset, data->addr + ABIT_UGURU3_CMD); - if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) { + x = abituguru3_wait_while_busy(data); + if (x != ABIT_UGURU3_SUCCESS) { 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); @@ -724,7 +784,8 @@ static int abituguru3_read(struct abituguru3_data *data, u8 bank, u8 offset, } outb(count, data->addr + ABIT_UGURU3_CMD); - if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) { + x = abituguru3_wait_while_busy(data); + if (x != ABIT_UGURU3_SUCCESS) { 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); @@ -732,8 +793,8 @@ static int abituguru3_read(struct abituguru3_data *data, u8 bank, u8 offset, } for (i = 0; i < count; i++) { - if ((x = abituguru3_wait_for_read(data)) != - ABIT_UGURU3_SUCCESS) { + x = abituguru3_wait_for_read(data); + if (x != ABIT_UGURU3_SUCCESS) { ABIT_UGURU3_DEBUG("timeout reading byte %d from " "0x%02x:0x%02x, status: 0x%02x\n", i, (unsigned int)bank, (unsigned int)offset, x); @@ -744,25 +805,34 @@ static int abituguru3_read(struct abituguru3_data *data, u8 bank, u8 offset, return i; } -/* Sensor settings are stored 1 byte per offset with the bytes - placed add consecutive offsets. */ +/* + * Sensor settings are stored 1 byte per offset with the bytes + * placed add consecutive offsets. + */ static int abituguru3_read_increment_offset(struct abituguru3_data *data, u8 bank, u8 offset, u8 count, u8 *buf, int offset_count) { int i, x; - for (i = 0; i < offset_count; i++) - if ((x = abituguru3_read(data, bank, offset + i, count, - buf + i * count)) != count) - return i * count + (i && (x < 0)) ? 0 : x; + for (i = 0; i < offset_count; i++) { + x = abituguru3_read(data, bank, offset + i, count, + buf + i * count); + if (x != count) { + if (x < 0) + return x; + return i * count + x; + } + } return i * count; } -/* 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. */ +/* + * 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. + */ static struct abituguru3_data *abituguru3_update_device(struct device *dev); static ssize_t show_value(struct device *dev, @@ -788,8 +858,10 @@ static ssize_t show_value(struct device *dev, value = (value * sensor->multiplier) / sensor->divisor + sensor->offset; - /* alternatively we could update the sensors settings struct for this, - but then its contents would differ from the windows sw ini files */ + /* + * alternatively we could update the sensors settings struct for this, + * but then its contents would differ from the windows sw ini files + */ if (sensor->type == ABIT_UGURU3_TEMP_SENSOR) value *= 1000; @@ -808,10 +880,12 @@ static ssize_t show_alarm(struct device *dev, port = data->sensors[attr->index].port; - /* 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. */ + /* + * 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. + */ if ((data->alarms[port / 8] & (0x01 << (port % 8))) && (!attr->nr || (data->settings[port][0] & attr->nr))) return sprintf(buf, "1\n"); @@ -894,7 +968,7 @@ static struct sensor_device_attribute_2 abituguru3_sysfs_attr[] = { SENSOR_ATTR_2(name, 0444, show_name, NULL, 0, 0), }; -static int __devinit abituguru3_probe(struct platform_device *pdev) +static int abituguru3_probe(struct platform_device *pdev) { const int no_sysfs_attr[3] = { 10, 8, 7 }; int sensor_index[3] = { 0, 1, 1 }; @@ -904,7 +978,9 @@ static int __devinit abituguru3_probe(struct platform_device *pdev) u8 buf[2]; u16 id; - if (!(data = kzalloc(sizeof(struct abituguru3_data), GFP_KERNEL))) + data = devm_kzalloc(&pdev->dev, sizeof(struct abituguru3_data), + GFP_KERNEL); + if (!data) return -ENOMEM; data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start; @@ -912,10 +988,10 @@ static int __devinit abituguru3_probe(struct platform_device *pdev) platform_set_drvdata(pdev, data); /* Read the motherboard ID */ - if ((i = abituguru3_read(data, ABIT_UGURU3_MISC_BANK, - ABIT_UGURU3_BOARD_ID, 2, buf)) != 2) { + i = abituguru3_read(data, ABIT_UGURU3_MISC_BANK, ABIT_UGURU3_BOARD_ID, + 2, buf); + if (i != 2) goto abituguru3_probe_error; - } /* Completely read the uGuru to see if one really is there */ if (!abituguru3_update_device(&pdev->dev)) @@ -927,15 +1003,13 @@ static int __devinit abituguru3_probe(struct platform_device *pdev) if (abituguru3_motherboards[i].id == id) break; if (!abituguru3_motherboards[i].id) { - printk(KERN_ERR ABIT_UGURU3_NAME ": error unknown motherboard " - "ID: %04X. Please report this to the abituguru3 " - "maintainer (see MAINTAINERS)\n", (unsigned int)id); + pr_err("error unknown motherboard ID: %04X. %s\n", + (unsigned int)id, report_this); goto abituguru3_probe_error; } data->sensors = abituguru3_motherboards[i].sensors; - printk(KERN_INFO ABIT_UGURU3_NAME ": found Abit uGuru3, motherboard " - "ID: %04X (%s)\n", (unsigned int)id, - abituguru3_motherboards[i].name); + + pr_info("found Abit uGuru3, motherboard ID: %04X\n", (unsigned int)id); /* Fill the sysfs attr array */ sysfs_attr_i = 0; @@ -944,11 +1018,8 @@ static int __devinit abituguru3_probe(struct platform_device *pdev) for (i = 0; data->sensors[i].name; i++) { /* Fail safe check, this should never happen! */ if (i >= ABIT_UGURU3_MAX_NO_SENSORS) { - printk(KERN_ERR ABIT_UGURU3_NAME - ": Fatal error motherboard has more sensors " - "then ABIT_UGURU3_MAX_NO_SENSORS. This should " - "never happen please report to the abituguru3 " - "maintainer (see MAINTAINERS)\n"); + pr_err("Fatal error motherboard has more sensors then ABIT_UGURU3_MAX_NO_SENSORS. %s %s\n", + never_happen, report_this); res = -ENAMETOOLONG; goto abituguru3_probe_error; } @@ -970,10 +1041,8 @@ static int __devinit abituguru3_probe(struct platform_device *pdev) } /* Fail safe check, this should never happen! */ if (sysfs_names_free < 0) { - printk(KERN_ERR ABIT_UGURU3_NAME - ": Fatal error ran out of space for sysfs attr names. " - "This should never happen please report to the " - "abituguru3 maintainer (see MAINTAINERS)\n"); + pr_err("Fatal error ran out of space for sysfs attr names. %s %s\n", + never_happen, report_this); res = -ENAMETOOLONG; goto abituguru3_probe_error; } @@ -1002,24 +1071,20 @@ abituguru3_probe_error: for (i = 0; i < ARRAY_SIZE(abituguru3_sysfs_attr); i++) device_remove_file(&pdev->dev, &abituguru3_sysfs_attr[i].dev_attr); - kfree(data); return res; } -static int __devexit abituguru3_remove(struct platform_device *pdev) +static int abituguru3_remove(struct platform_device *pdev) { int i; struct abituguru3_data *data = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); hwmon_device_unregister(data->hwmon_dev); 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); - kfree(data); - return 0; } @@ -1075,56 +1140,105 @@ LEAVE_UPDATE: return NULL; } -#ifdef CONFIG_PM -static int abituguru3_suspend(struct platform_device *pdev, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int abituguru3_suspend(struct device *dev) { - struct abituguru3_data *data = platform_get_drvdata(pdev); - /* make sure all communications with the uguru3 are done and no new - ones are started */ + struct abituguru3_data *data = dev_get_drvdata(dev); + /* + * make sure all communications with the uguru3 are done and no new + * ones are started + */ mutex_lock(&data->update_lock); return 0; } -static int abituguru3_resume(struct platform_device *pdev) +static int abituguru3_resume(struct device *dev) { - struct abituguru3_data *data = platform_get_drvdata(pdev); + struct abituguru3_data *data = dev_get_drvdata(dev); mutex_unlock(&data->update_lock); return 0; } + +static SIMPLE_DEV_PM_OPS(abituguru3_pm, abituguru3_suspend, abituguru3_resume); +#define ABIT_UGURU3_PM (&abituguru3_pm) #else -#define abituguru3_suspend NULL -#define abituguru3_resume NULL +#define ABIT_UGURU3_PM NULL #endif /* CONFIG_PM */ static struct platform_driver abituguru3_driver = { .driver = { .owner = THIS_MODULE, .name = ABIT_UGURU3_NAME, + .pm = ABIT_UGURU3_PM }, .probe = abituguru3_probe, - .remove = __devexit_p(abituguru3_remove), - .suspend = abituguru3_suspend, - .resume = abituguru3_resume + .remove = abituguru3_remove, }; +static int __init abituguru3_dmi_detect(void) +{ + const char *board_vendor, *board_name; + int i, err = (force) ? 1 : -ENODEV; + const char *const *dmi_name; + size_t sublen; + + 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; + + /* + * At the moment, we don't care about the part of the vendor + * 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--; + + for (i = 0; abituguru3_motherboards[i].id; i++) { + 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; + } + } + + /* No match found */ + return 1; +} + +/* + * FIXME: Manual detection should die eventually; we need to collect stable + * DMI model names first before we can rely entirely on CONFIG_DMI. + */ + static int __init abituguru3_detect(void) { - /* 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 - at CMD instead, why is unknown. So we test for 0x05 too. */ + /* + * 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. + */ u8 data_val = inb_p(ABIT_UGURU3_BASE + ABIT_UGURU3_DATA); u8 cmd_val = inb_p(ABIT_UGURU3_BASE + ABIT_UGURU3_CMD); if (((data_val == 0x00) || (data_val == 0x08)) && - ((cmd_val == 0xAC) || (cmd_val == 0x05))) - return ABIT_UGURU3_BASE; + ((cmd_val == 0xAC) || (cmd_val == 0x05) || + (cmd_val == 0x55))) + return 0; ABIT_UGURU3_DEBUG("no Abit uGuru3 found, data = 0x%02X, cmd = " "0x%02X\n", (unsigned int)data_val, (unsigned int)cmd_val); if (force) { - printk(KERN_INFO ABIT_UGURU3_NAME ": Assuming Abit uGuru3 is " - "present because of \"force\" parameter\n"); - return ABIT_UGURU3_BASE; + pr_info("Assuming Abit uGuru3 is present because of \"force\" parameter\n"); + return 0; } /* No uGuru3 found */ @@ -1135,40 +1249,52 @@ static struct platform_device *abituguru3_pdev; static int __init abituguru3_init(void) { - int address, err; struct resource res = { .flags = IORESOURCE_IO }; - - address = abituguru3_detect(); - if (address < 0) - return address; + int err; + + /* Attempt DMI detection first */ + err = abituguru3_dmi_detect(); + if (err < 0) + return err; + + /* + * Fall back to manual detection if there was no exact + * board name match, or force was specified. + */ + if (err > 0) { + err = abituguru3_detect(); + if (err) + return err; + + pr_warn("this motherboard was not detected using DMI. " + "Please send the output of \"dmidecode\" to the abituguru3 maintainer (see MAINTAINERS)\n"); + } err = platform_driver_register(&abituguru3_driver); if (err) goto exit; - abituguru3_pdev = platform_device_alloc(ABIT_UGURU3_NAME, address); + abituguru3_pdev = platform_device_alloc(ABIT_UGURU3_NAME, + ABIT_UGURU3_BASE); if (!abituguru3_pdev) { - printk(KERN_ERR ABIT_UGURU3_NAME - ": Device allocation failed\n"); + pr_err("Device allocation failed\n"); err = -ENOMEM; goto exit_driver_unregister; } - res.start = address; - res.end = address + ABIT_UGURU3_REGION_LENGTH - 1; + res.start = ABIT_UGURU3_BASE; + res.end = ABIT_UGURU3_BASE + ABIT_UGURU3_REGION_LENGTH - 1; res.name = ABIT_UGURU3_NAME; err = platform_device_add_resources(abituguru3_pdev, &res, 1); if (err) { - printk(KERN_ERR ABIT_UGURU3_NAME - ": Device resource addition failed (%d)\n", err); + pr_err("Device resource addition failed (%d)\n", err); goto exit_device_put; } err = platform_device_add(abituguru3_pdev); if (err) { - printk(KERN_ERR ABIT_UGURU3_NAME - ": Device addition failed (%d)\n", err); + pr_err("Device addition failed (%d)\n", err); goto exit_device_put; } @@ -1188,7 +1314,7 @@ static void __exit abituguru3_exit(void) platform_driver_unregister(&abituguru3_driver); } -MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>"); +MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); MODULE_DESCRIPTION("Abit uGuru3 Sensor device"); MODULE_LICENSE("GPL"); |
