Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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