mirror of
https://github.com/lm-sensors/lm-sensors.git
synced 2026-11-11 16:40:16 +00:00
pwm and smart guardian fan patch from
Michael Hufer <michael.hufer@freenet.de> ------------------------ > First, I added a new mod parameter "reset_it87" which controls whether > or not the chip is reset on module load (modprobe it87 reset_it=1, > default) or not(modprobe it87 reset_it87=0). > Since this worked out quiet nicely I decided to go one step further > and also add the chips manual and automatic temperature controlled fan > speed features (PWM etc.). > > Finally I also updated the doc to document the new features. > > Attached is a diff against the current cvs version. ------------------------ Subject: Re: fan speed for it87?? chips added Date: Fri, 26 Sep 2003 23:28:35 +0200 From: Michael Hufer <michael.hufer@freenet.de> To: sensors@Stimpy.netroedge.com, Jean Delvare <khali@linux-fr.org> On Friday 26 September 2003 22:40, Jean Delvare wrote: > > I found and fixed the little problem I had with the original chip > > initialization. I can now load the module with reset_it87=0 and > > init=1 without messing up the settings of the power supply fan > > from the BIOS. It was quite simple after all. > > I'm interested in details, can you tell us what it was? Sure, it actually was something I introduced myself :-(. I initialized the fan_ctl register with (read_value & 0x8f | 0x77) to enable the smart guardian feature for all 3 fans. But the power supply fan does not support pwm. It can only be operated in on/off mode, i.e. bit 0 must be clear. I switched it back to the original (rv & 0x8f | 0x70 ) and everything is back to working. > > Do you want me to send the latest diff? > > Sure I want. Here it comes. git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@2033 7894878c-1315-0410-8ee3-d5d059ff63e0
This commit is contained in:
1 parent
fac06872b8
commit
34076ded72
2 files changed
+374
-84
No files matched your search
+67
-1
@@ -62,7 +62,18 @@ Module Parameters
|
||||
thermistor diode thermistor 0x2a ** default
|
||||
thermistor thermistor diode 0x1c
|
||||
thermistor thermistor thermistor 0x38
|
||||
|
||||
* reset_it87: integer 1 if the registers of the chip should be reset at
|
||||
module load time, 0 to not reset the registers. Default is 0.
|
||||
* init: integer 1 if the registers should be initialized with the module's
|
||||
default values, 0 skip the initialization. Default is 1.
|
||||
On some boards (e.g. the Shuttle FN41 from the Shuttle XPC Barebone)
|
||||
the BIOS configures it87's smart temperature monitoring fan power
|
||||
adjust feature. A reset/init would unset this and set the power of the
|
||||
fan to maximum speed (which is very noisy). Set 'reset_it87=0' to
|
||||
keep the registers at the preconfigured values.
|
||||
Note: If the registers weren't preconfigured for monitoring by the BIOS
|
||||
the monitoring will not work if you do not reset and initialize the chip's
|
||||
registers at module load time.
|
||||
|
||||
Description
|
||||
-----------
|
||||
@@ -112,6 +123,61 @@ miss once-only alarms.
|
||||
The IT87xx only updates its values each 1.5 seconds; reading it more often
|
||||
will do no harm, but will return 'old' values.
|
||||
|
||||
The fan speed control features can be enabled by setting the bits 0-2 of
|
||||
the fan_ctl register to 1. (Note: bits 6-4 of this register must be set to
|
||||
1 to enable the fan monitoring).
|
||||
0x40 : enable fan speed monitoring for fan3
|
||||
0x20 : enable fan speed monitoring for fan2
|
||||
0x10 : enable fan speed monitoring for fan1
|
||||
0x04 : enable fan smart guardian mode for fan3
|
||||
0x02 : enable fan smart guardian mode for fan2
|
||||
0x01 : enable fan smart guardian mode for fan1
|
||||
If a fans smart guardian bit is not set this fan is in on-off mode
|
||||
it can be switched on or off by setting/clearing the corresponding bit 0-2
|
||||
of the second fan control register fan_on_off. This register has no effect if
|
||||
a fan is in smart guardian mode.
|
||||
0x04 : fan3 is on
|
||||
0x02 : fan2 is on
|
||||
0x01 : fan1 is on
|
||||
Bit 7 of the pwm[1-3] registers enables/disables the chips automatic
|
||||
temperature control mode for the specified fan. If Bit 7 is set the bits
|
||||
1 and 0 encode the number of the temperature sensor used for this feature.
|
||||
Possible register values are:
|
||||
0x00-0x7f direct power control for the fan speed
|
||||
0x80 automatic smart guardian mode use temperatur sensor 1,
|
||||
0x81 automatic smart guardian mode use temperatur sensor 2,
|
||||
0x82 automatic smart guardian mode use temperatur sensor 3
|
||||
In automatic smart guardian mode pwm values for low, medium and high speed
|
||||
can be set in sg_pwm[1-3]. The temperature limits for fan off, low, medium,
|
||||
hi speed and over temperature are set in sg_tl[1-3]. While the sensors
|
||||
temperature is between the low and medium speed value the fan will run in
|
||||
low speed. When the sensors temperature is between the medium and high speed
|
||||
value the fan spins in medium speed. When the sensors temperature is between
|
||||
the high speed and over temperature value the fan spins in high speed.
|
||||
If the sensors temperature is higher than the over temperature limit the
|
||||
fan will spin with the highest possible speed.
|
||||
Example:
|
||||
The preconfigured (BIOS set) values of the Shuttle XPC SN41G2 Barebone.
|
||||
The MB uses temp2 to monitor the CPU temperature and fan3 as the fan for their
|
||||
special ICE heatpipe cooling system.
|
||||
---
|
||||
$ cat fan_ctl
|
||||
116
|
||||
$ cat tan_on_off
|
||||
215
|
||||
$ cat pwm3
|
||||
129
|
||||
$ cat sg_tl3
|
||||
16.0 16.0 48.0 54.0 58.0
|
||||
$ cat sg_pwm3
|
||||
3 4 9
|
||||
---
|
||||
Explanation:
|
||||
fan_ctl -> 116 = 0x74 = 01110100 : fan monitoring on for all fans, and fan3 is in smart guardian mode.
|
||||
fan_on_off -> 215 = 0xd7 =11010111 : all fans are on this setting is ignored for fan3 which is in smart guardian mode
|
||||
pwm3 -> 129 = 0x81 = 10000001 : fan3 is in automatic mode and uses temp2 for speed control
|
||||
sg_tl3 -> 16.0 16.0 48.0 54.0 58.0 : off, low, med, high, and over temperature limits of fan3
|
||||
sg_pwm3 -> 3 4 9 : pwm values for low, medium and high fan speed of fan3.
|
||||
|
||||
Chip features
|
||||
-------------
|
||||
|
||||
+307
-83
@@ -31,6 +31,13 @@
|
||||
type at module load time.
|
||||
*/
|
||||
|
||||
/*
|
||||
michael.hufer@gmx.de Michael Hufer 09/07/03
|
||||
Modified configure (enable/disable) chip reset at module load time.
|
||||
Added ability to read and set fan pwm registers and the smart
|
||||
guardian (sg) features of the chip.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/proc_fs.h>
|
||||
@@ -65,6 +72,12 @@ static int update_vbat = 0;
|
||||
/* Enable Temp3 as thermal resistor */
|
||||
static int temp_type = 0x2a;
|
||||
|
||||
/* Reset the registers on init */
|
||||
static int reset_it87 = 0;
|
||||
|
||||
/* Initialize the registers to default values on init */
|
||||
static int init = 1;
|
||||
|
||||
/* Many IT87 constants specified below */
|
||||
|
||||
/* Length of ISA address segment */
|
||||
@@ -85,12 +98,25 @@ static int temp_type = 0x2a;
|
||||
#define IT87_REG_VID 0x0a
|
||||
#define IT87_REG_FAN_DIV 0x0b
|
||||
|
||||
/* Monitors: 9 voltage (0 to 7, battery), 3 temp (1 to 3), 3 fan (1 to 3) */
|
||||
|
||||
#define IT87_REG_FAN(nr) (0x0c + (nr))
|
||||
#define IT87_REG_FAN_MIN(nr) (0x0f + (nr))
|
||||
#define IT87_REG_FAN_CTRL 0x13
|
||||
|
||||
/* pwm and smart guardian registers */
|
||||
|
||||
#define IT87_REG_FAN_ONOFF 0x14
|
||||
#define IT87_REG_PWM(nr) (0x14 + (nr))
|
||||
#define IT87_REG_SG_TL_OFF(nr) (0x58 + (nr)*8)
|
||||
#define IT87_REG_SG_TL_LOW(nr) (0x59 + (nr)*8)
|
||||
#define IT87_REG_SG_TL_MED(nr) (0x5a + (nr)*8)
|
||||
#define IT87_REG_SG_TL_HI(nr) (0x5b + (nr)*8)
|
||||
#define IT87_REG_SG_TL_OVR(nr) (0x5c + (nr)*8)
|
||||
#define IT87_REG_SG_PWM_LOW(nr) (0x5d + (nr)*8)
|
||||
#define IT87_REG_SG_PWM_MED(nr) (0x5e + (nr)*8)
|
||||
#define IT87_REG_SG_PWM_HI(nr) (0x5f + (nr)*8)
|
||||
|
||||
/* Monitors: 9 voltage (0 to 7, battery), 3 temp (1 to 3), 3 fan (1 to 3) */
|
||||
|
||||
#define IT87_REG_VIN(nr) (0x20 + (nr))
|
||||
#define IT87_REG_TEMP(nr) (0x28 + (nr))
|
||||
|
||||
@@ -133,7 +159,17 @@ static inline u8 FAN_TO_REG(long rpm, int div)
|
||||
205-(val)*5)
|
||||
#define ALARMS_FROM_REG(val) (val)
|
||||
|
||||
#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
|
||||
extern inline u8 DIV_TO_REG(long val)
|
||||
{
|
||||
u8 i;
|
||||
for( i = 0; i <= 7; i++ )
|
||||
{
|
||||
if( val>>i == 1 )
|
||||
return i;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)*/
|
||||
#define DIV_FROM_REG(val) (1 << (val))
|
||||
|
||||
/* Initial limits. Use the config file to set better limits. */
|
||||
@@ -186,12 +222,23 @@ static inline u8 FAN_TO_REG(long rpm, int div)
|
||||
#define IT87_INIT_FAN_MIN_3 3000
|
||||
|
||||
#define IT87_INIT_TEMP_HIGH_1 600
|
||||
#define IT87_INIT_TEMP_LOW_1 200
|
||||
#define IT87_INIT_TEMP_LOW_1 540
|
||||
#define IT87_INIT_TEMP_HIGH_2 600
|
||||
#define IT87_INIT_TEMP_LOW_2 200
|
||||
#define IT87_INIT_TEMP_HIGH_3 600
|
||||
#define IT87_INIT_TEMP_HIGH_3 600
|
||||
#define IT87_INIT_TEMP_LOW_3 200
|
||||
|
||||
#define IT87_INIT_PWR_TL_OFF 160
|
||||
#define IT87_INIT_PWR_TL_LOW 160
|
||||
#define IT87_INIT_PWR_TL_MED 480
|
||||
#define IT87_INIT_PWR_TL_HI 540
|
||||
#define IT87_INIT_PWR_TL_OVR 580
|
||||
|
||||
#define IT87_INIT_PWR_LOW 3
|
||||
#define IT87_INIT_PWR_MED 4
|
||||
#define IT87_INIT_PWR_HI 9
|
||||
|
||||
|
||||
/* For each registered IT87, we need to keep some data in memory. That
|
||||
data is pointed to by it87_list[NR]->data. The structure itself is
|
||||
dynamically allocated, at the same time when a new it87 client is
|
||||
@@ -216,6 +263,10 @@ struct it87_data {
|
||||
u8 fan_div[3]; /* Register encoding, shifted right */
|
||||
u8 vid; /* Register encoding, combined */
|
||||
u32 alarms; /* Register encoding, combined */
|
||||
u8 pwm[3]; /* Register value */
|
||||
u8 fan_ctl[2]; /* Register encoding */
|
||||
u8 sg_tl[3][5]; /* Register value */
|
||||
u8 sg_pwm[3][3]; /* Register value */
|
||||
};
|
||||
|
||||
|
||||
@@ -243,6 +294,14 @@ static void it87_alarms(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results);
|
||||
static void it87_fan_div(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results);
|
||||
static void it87_fan_ctl(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results);
|
||||
static void it87_pwm(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results);
|
||||
static void it87_sgpwm(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results);
|
||||
static void it87_sgtl(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results);
|
||||
|
||||
static struct i2c_driver it87_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
@@ -277,6 +336,13 @@ static int it87_id = 0;
|
||||
#define IT87_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */
|
||||
#define IT87_SYSCTL_ALARMS 2004 /* bitvector */
|
||||
|
||||
#define IT87_SYSCTL_PWM1 1401
|
||||
#define IT87_SYSCTL_PWM2 1402
|
||||
#define IT87_SYSCTL_PWM3 1403
|
||||
#define IT87_SYSCTL_FAN_CTL 1501
|
||||
#define IT87_SYSCTL_FAN_ON_OFF 1502
|
||||
|
||||
|
||||
#define IT87_ALARM_IN0 0x000100
|
||||
#define IT87_ALARM_IN1 0x000200
|
||||
#define IT87_ALARM_IN2 0x000400
|
||||
@@ -336,6 +402,28 @@ static ctl_table it87_dir_table_template[] = {
|
||||
&i2c_sysctl_real, NULL, &it87_fan_div},
|
||||
{IT87_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
|
||||
&i2c_sysctl_real, NULL, &it87_alarms},
|
||||
{IT87_SYSCTL_FAN_CTL, "fan_ctl", NULL, 0, 0644, NULL, &i2c_proc_real,
|
||||
&i2c_sysctl_real, NULL, &it87_fan_ctl},
|
||||
{IT87_SYSCTL_FAN_ON_OFF, "fan_on_off", NULL, 0, 0644, NULL, &i2c_proc_real,
|
||||
&i2c_sysctl_real, NULL, &it87_fan_ctl},
|
||||
{IT87_SYSCTL_PWM1, "pwm1", NULL, 0, 0444, NULL, &i2c_proc_real,
|
||||
&i2c_sysctl_real, NULL, &it87_pwm},
|
||||
{IT87_SYSCTL_PWM2, "pwm2", NULL, 0, 0444, NULL, &i2c_proc_real,
|
||||
&i2c_sysctl_real, NULL, &it87_pwm},
|
||||
{IT87_SYSCTL_PWM3, "pwm3", NULL, 0, 0444, NULL, &i2c_proc_real,
|
||||
&i2c_sysctl_real, NULL, &it87_pwm},
|
||||
{IT87_SYSCTL_PWM1, "sg_pwm1", NULL, 0, 0444, NULL, &i2c_proc_real,
|
||||
&i2c_sysctl_real, NULL, &it87_sgpwm},
|
||||
{IT87_SYSCTL_PWM2, "sg_pwm2", NULL, 0, 0444, NULL, &i2c_proc_real,
|
||||
&i2c_sysctl_real, NULL, &it87_sgpwm},
|
||||
{IT87_SYSCTL_PWM3, "sg_pwm3", NULL, 0, 0444, NULL, &i2c_proc_real,
|
||||
&i2c_sysctl_real, NULL, &it87_sgpwm},
|
||||
{IT87_SYSCTL_PWM1, "sg_tl1", NULL, 0, 0444, NULL, &i2c_proc_real,
|
||||
&i2c_sysctl_real, NULL, &it87_sgtl},
|
||||
{IT87_SYSCTL_PWM2, "sg_tl2", NULL, 0, 0444, NULL, &i2c_proc_real,
|
||||
&i2c_sysctl_real, NULL, &it87_sgtl},
|
||||
{IT87_SYSCTL_PWM3, "sg_tl3", NULL, 0, 0444, NULL, &i2c_proc_real,
|
||||
&i2c_sysctl_real, NULL, &it87_sgtl},
|
||||
{0}
|
||||
};
|
||||
|
||||
@@ -563,74 +651,81 @@ static int it87_write_value(struct i2c_client *client, u8 reg, u8 value)
|
||||
/* Called when we have found a new IT87. It should set limits, etc. */
|
||||
static void it87_init_client(struct i2c_client *client)
|
||||
{
|
||||
if( init )
|
||||
{
|
||||
/* Reset all except Watchdog values and last conversion values
|
||||
This sets fan-divs to 2, among others */
|
||||
it87_write_value(client, IT87_REG_CONFIG, 0x80);
|
||||
it87_write_value(client, IT87_REG_VIN_MIN(0),
|
||||
IN_TO_REG(IT87_INIT_IN_MIN_0));
|
||||
it87_write_value(client, IT87_REG_VIN_MAX(0),
|
||||
IN_TO_REG(IT87_INIT_IN_MAX_0));
|
||||
it87_write_value(client, IT87_REG_VIN_MIN(1),
|
||||
IN_TO_REG(IT87_INIT_IN_MIN_1));
|
||||
it87_write_value(client, IT87_REG_VIN_MAX(1),
|
||||
IN_TO_REG(IT87_INIT_IN_MAX_1));
|
||||
it87_write_value(client, IT87_REG_VIN_MIN(2),
|
||||
IN_TO_REG(IT87_INIT_IN_MIN_2));
|
||||
it87_write_value(client, IT87_REG_VIN_MAX(2),
|
||||
IN_TO_REG(IT87_INIT_IN_MAX_2));
|
||||
it87_write_value(client, IT87_REG_VIN_MIN(3),
|
||||
IN_TO_REG(IT87_INIT_IN_MIN_3));
|
||||
it87_write_value(client, IT87_REG_VIN_MAX(3),
|
||||
IN_TO_REG(IT87_INIT_IN_MAX_3));
|
||||
it87_write_value(client, IT87_REG_VIN_MIN(4),
|
||||
IN_TO_REG(IT87_INIT_IN_MIN_4));
|
||||
it87_write_value(client, IT87_REG_VIN_MAX(4),
|
||||
IN_TO_REG(IT87_INIT_IN_MAX_4));
|
||||
it87_write_value(client, IT87_REG_VIN_MIN(5),
|
||||
IN_TO_REG(IT87_INIT_IN_MIN_5));
|
||||
it87_write_value(client, IT87_REG_VIN_MAX(5),
|
||||
IN_TO_REG(IT87_INIT_IN_MAX_5));
|
||||
it87_write_value(client, IT87_REG_VIN_MIN(6),
|
||||
IN_TO_REG(IT87_INIT_IN_MIN_6));
|
||||
it87_write_value(client, IT87_REG_VIN_MAX(6),
|
||||
IN_TO_REG(IT87_INIT_IN_MAX_6));
|
||||
it87_write_value(client, IT87_REG_VIN_MIN(7),
|
||||
IN_TO_REG(IT87_INIT_IN_MIN_7));
|
||||
it87_write_value(client, IT87_REG_VIN_MAX(7),
|
||||
IN_TO_REG(IT87_INIT_IN_MAX_7));
|
||||
/* Note: Battery voltage does not have limit registers */
|
||||
it87_write_value(client, IT87_REG_FAN_MIN(1),
|
||||
FAN_TO_REG(IT87_INIT_FAN_MIN_1, 2));
|
||||
it87_write_value(client, IT87_REG_FAN_MIN(2),
|
||||
FAN_TO_REG(IT87_INIT_FAN_MIN_2, 2));
|
||||
it87_write_value(client, IT87_REG_FAN_MIN(3),
|
||||
FAN_TO_REG(IT87_INIT_FAN_MIN_3, 2));
|
||||
it87_write_value(client, IT87_REG_TEMP_HIGH(1),
|
||||
TEMP_TO_REG(IT87_INIT_TEMP_HIGH_1));
|
||||
it87_write_value(client, IT87_REG_TEMP_LOW(1),
|
||||
TEMP_TO_REG(IT87_INIT_TEMP_LOW_1));
|
||||
it87_write_value(client, IT87_REG_TEMP_HIGH(2),
|
||||
TEMP_TO_REG(IT87_INIT_TEMP_HIGH_2));
|
||||
it87_write_value(client, IT87_REG_TEMP_LOW(2),
|
||||
TEMP_TO_REG(IT87_INIT_TEMP_LOW_2));
|
||||
it87_write_value(client, IT87_REG_TEMP_HIGH(3),
|
||||
TEMP_TO_REG(IT87_INIT_TEMP_HIGH_3));
|
||||
it87_write_value(client, IT87_REG_TEMP_LOW(3),
|
||||
TEMP_TO_REG(IT87_INIT_TEMP_LOW_3));
|
||||
This sets fan-divs to 2, among others.
|
||||
It will also reset the automatic temperature controlled fan
|
||||
speed (noise) control the BIOS configured on POST and the
|
||||
fan will be set to propably noisy full speed operation */
|
||||
if( reset_it87 ) {
|
||||
it87_write_value(client, IT87_REG_CONFIG, 0x80);
|
||||
}
|
||||
it87_write_value(client, IT87_REG_VIN_MIN(0),
|
||||
IN_TO_REG(IT87_INIT_IN_MIN_0));
|
||||
it87_write_value(client, IT87_REG_VIN_MAX(0),
|
||||
IN_TO_REG(IT87_INIT_IN_MAX_0));
|
||||
it87_write_value(client, IT87_REG_VIN_MIN(1),
|
||||
IN_TO_REG(IT87_INIT_IN_MIN_1));
|
||||
it87_write_value(client, IT87_REG_VIN_MAX(1),
|
||||
IN_TO_REG(IT87_INIT_IN_MAX_1));
|
||||
it87_write_value(client, IT87_REG_VIN_MIN(2),
|
||||
IN_TO_REG(IT87_INIT_IN_MIN_2));
|
||||
it87_write_value(client, IT87_REG_VIN_MAX(2),
|
||||
IN_TO_REG(IT87_INIT_IN_MAX_2));
|
||||
it87_write_value(client, IT87_REG_VIN_MIN(3),
|
||||
IN_TO_REG(IT87_INIT_IN_MIN_3));
|
||||
it87_write_value(client, IT87_REG_VIN_MAX(3),
|
||||
IN_TO_REG(IT87_INIT_IN_MAX_3));
|
||||
it87_write_value(client, IT87_REG_VIN_MIN(4),
|
||||
IN_TO_REG(IT87_INIT_IN_MIN_4));
|
||||
it87_write_value(client, IT87_REG_VIN_MAX(4),
|
||||
IN_TO_REG(IT87_INIT_IN_MAX_4));
|
||||
it87_write_value(client, IT87_REG_VIN_MIN(5),
|
||||
IN_TO_REG(IT87_INIT_IN_MIN_5));
|
||||
it87_write_value(client, IT87_REG_VIN_MAX(5),
|
||||
IN_TO_REG(IT87_INIT_IN_MAX_5));
|
||||
it87_write_value(client, IT87_REG_VIN_MIN(6),
|
||||
IN_TO_REG(IT87_INIT_IN_MIN_6));
|
||||
it87_write_value(client, IT87_REG_VIN_MAX(6),
|
||||
IN_TO_REG(IT87_INIT_IN_MAX_6));
|
||||
it87_write_value(client, IT87_REG_VIN_MIN(7),
|
||||
IN_TO_REG(IT87_INIT_IN_MIN_7));
|
||||
it87_write_value(client, IT87_REG_VIN_MAX(7),
|
||||
IN_TO_REG(IT87_INIT_IN_MAX_7));
|
||||
/* Note: Battery voltage does not have limit registers */
|
||||
it87_write_value(client, IT87_REG_FAN_MIN(1),
|
||||
FAN_TO_REG(IT87_INIT_FAN_MIN_1, 2));
|
||||
it87_write_value(client, IT87_REG_FAN_MIN(2),
|
||||
FAN_TO_REG(IT87_INIT_FAN_MIN_2, 2));
|
||||
it87_write_value(client, IT87_REG_FAN_MIN(3),
|
||||
FAN_TO_REG(IT87_INIT_FAN_MIN_3, 2));
|
||||
it87_write_value(client, IT87_REG_TEMP_HIGH(1),
|
||||
TEMP_TO_REG(IT87_INIT_TEMP_HIGH_1));
|
||||
it87_write_value(client, IT87_REG_TEMP_LOW(1),
|
||||
TEMP_TO_REG(IT87_INIT_TEMP_LOW_1));
|
||||
it87_write_value(client, IT87_REG_TEMP_HIGH(2),
|
||||
TEMP_TO_REG(IT87_INIT_TEMP_HIGH_2));
|
||||
it87_write_value(client, IT87_REG_TEMP_LOW(2),
|
||||
TEMP_TO_REG(IT87_INIT_TEMP_LOW_2));
|
||||
it87_write_value(client, IT87_REG_TEMP_HIGH(3),
|
||||
TEMP_TO_REG(IT87_INIT_TEMP_HIGH_3));
|
||||
it87_write_value(client, IT87_REG_TEMP_LOW(3),
|
||||
TEMP_TO_REG(IT87_INIT_TEMP_LOW_3));
|
||||
|
||||
/* Enable voltage monitors */
|
||||
it87_write_value(client, IT87_REG_VIN_ENABLE, 0xff);
|
||||
/* Enable voltage monitors */
|
||||
it87_write_value(client, IT87_REG_VIN_ENABLE, 0xff);
|
||||
|
||||
/* Enable Temp1-Temp3 */
|
||||
it87_write_value(client, IT87_REG_TEMP_ENABLE,
|
||||
(it87_read_value(client, IT87_REG_TEMP_ENABLE) & 0xc0)
|
||||
| (temp_type & 0x3f));
|
||||
|
||||
/* Enable fans */
|
||||
it87_write_value(client, IT87_REG_FAN_CTRL,
|
||||
(it87_read_value(client, IT87_REG_FAN_CTRL) & 0x8f)
|
||||
| 0x70);
|
||||
/* Enable Temp1-Temp3 */
|
||||
it87_write_value(client, IT87_REG_TEMP_ENABLE,
|
||||
(it87_read_value(client, IT87_REG_TEMP_ENABLE) & 0xc0)
|
||||
| (temp_type & 0x3f));
|
||||
|
||||
/* Enable fans */
|
||||
it87_write_value(client, IT87_REG_FAN_CTRL,
|
||||
(it87_read_value(client, IT87_REG_FAN_CTRL) & 0x8f)
|
||||
| 0x70);
|
||||
}
|
||||
/* Start monitoring */
|
||||
it87_write_value(client, IT87_REG_CONFIG,
|
||||
(it87_read_value(client, IT87_REG_CONFIG) & 0xb7)
|
||||
@@ -648,8 +743,8 @@ static void it87_update_client(struct i2c_client *client)
|
||||
(jiffies < data->last_updated) || !data->valid) {
|
||||
|
||||
if (update_vbat) {
|
||||
/* Cleared after each update, so reenable. Value
|
||||
returned by this read will be previous value */
|
||||
/* Cleared after each update, so reenable. Value
|
||||
returned by this read will be previous value */
|
||||
it87_write_value(client, IT87_REG_CONFIG,
|
||||
it87_read_value(client, IT87_REG_CONFIG) | 0x40);
|
||||
}
|
||||
@@ -663,7 +758,7 @@ static void it87_update_client(struct i2c_client *client)
|
||||
}
|
||||
data->in[8] =
|
||||
it87_read_value(client, IT87_REG_VIN(8));
|
||||
/* Temperature sensor doesn't have limit registers, set
|
||||
/* VBAT sensor doesn't have limit registers, set
|
||||
to min and max value */
|
||||
data->in_min[8] = 0;
|
||||
data->in_max[8] = 255;
|
||||
@@ -695,13 +790,25 @@ static void it87_update_client(struct i2c_client *client)
|
||||
i = it87_read_value(client, IT87_REG_FAN_DIV);
|
||||
data->fan_div[0] = i & 0x07;
|
||||
data->fan_div[1] = (i >> 3) & 0x07;
|
||||
data->fan_div[2] = 1;
|
||||
data->fan_div[2] = ( (i&0x40)==0x40 ? 3 : 1 );
|
||||
|
||||
for( i = 1; i <= 3; i++ ) {
|
||||
data->pwm[i-1] = it87_read_value(client, IT87_REG_PWM(i));
|
||||
data->sg_tl[i-1][0] = it87_read_value(client, IT87_REG_SG_TL_OFF(i));
|
||||
data->sg_tl[i-1][1] = it87_read_value(client, IT87_REG_SG_TL_LOW(i));
|
||||
data->sg_tl[i-1][2] = it87_read_value(client, IT87_REG_SG_TL_MED(i));
|
||||
data->sg_tl[i-1][3] = it87_read_value(client, IT87_REG_SG_TL_HI(i));
|
||||
data->sg_tl[i-1][4] = it87_read_value(client, IT87_REG_SG_TL_OVR(i));
|
||||
data->sg_pwm[i-1][0] = it87_read_value(client, IT87_REG_SG_PWM_LOW(i));
|
||||
data->sg_pwm[i-1][1] = it87_read_value(client, IT87_REG_SG_PWM_MED(i));
|
||||
data->sg_pwm[i-1][2] = it87_read_value(client, IT87_REG_SG_PWM_HI(i));
|
||||
}
|
||||
data->alarms =
|
||||
it87_read_value(client, IT87_REG_ALARM1) |
|
||||
(it87_read_value(client, IT87_REG_ALARM2) << 8) |
|
||||
(it87_read_value(client, IT87_REG_ALARM3) << 16);
|
||||
|
||||
data->fan_ctl[0] = it87_read_value(client, IT87_REG_FAN_CTRL);
|
||||
data->fan_ctl[1] = it87_read_value(client, IT87_REG_FAN_ONOFF);
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
}
|
||||
@@ -763,19 +870,14 @@ void it87_fan(struct i2c_client *client, int operation, int ctl_name,
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
it87_update_client(client);
|
||||
results[0] = FAN_FROM_REG(data->fan_min[nr - 1],
|
||||
DIV_FROM_REG(data->
|
||||
fan_div[nr - 1]));
|
||||
results[1] =
|
||||
FAN_FROM_REG(data->fan[nr - 1],
|
||||
DIV_FROM_REG(data->fan_div[nr - 1]));
|
||||
results[1] = FAN_FROM_REG(data->fan[nr - 1],
|
||||
DIV_FROM_REG(data->fan_div[nr - 1]));
|
||||
*nrels_mag = 2;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->fan_min[nr - 1] = FAN_TO_REG(results[0],
|
||||
DIV_FROM_REG
|
||||
(data->
|
||||
fan_div[nr -
|
||||
1]));
|
||||
DIV_FROM_REG(data->fan_div[nr - 1]));
|
||||
it87_write_value(client, IT87_REG_FAN_MIN(nr),
|
||||
data->fan_min[nr - 1]);
|
||||
}
|
||||
@@ -810,6 +912,93 @@ void it87_temp(struct i2c_client *client, int operation, int ctl_name,
|
||||
}
|
||||
}
|
||||
|
||||
void it87_pwm(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results)
|
||||
{
|
||||
struct it87_data *data = client->data;
|
||||
int nr = ctl_name - IT87_SYSCTL_PWM1 + 1;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
it87_update_client(client);
|
||||
results[0] = data->pwm[nr - 1];
|
||||
*nrels_mag = 1;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->pwm[nr - 1] = results[0];
|
||||
it87_write_value(client, IT87_REG_PWM(nr), data->pwm[nr - 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void it87_sgpwm(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results)
|
||||
{
|
||||
struct it87_data *data = client->data;
|
||||
int nr = ctl_name - IT87_SYSCTL_PWM1 + 1;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
it87_update_client(client);
|
||||
results[0] = data->sg_pwm[nr - 1][0];
|
||||
results[1] = data->sg_pwm[nr - 1][1];
|
||||
results[2] = data->sg_pwm[nr - 1][2];
|
||||
*nrels_mag = 3;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->sg_pwm[nr - 1][0] = results[0];
|
||||
it87_write_value(client, IT87_REG_SG_PWM_LOW(nr), data->sg_pwm[nr - 1][0]);
|
||||
}
|
||||
if (*nrels_mag >= 2) {
|
||||
data->sg_pwm[nr - 1][1] = results[1];
|
||||
it87_write_value(client, IT87_REG_SG_PWM_MED(nr), data->sg_pwm[nr - 1][1]);
|
||||
}
|
||||
if (*nrels_mag >= 3) {
|
||||
data->sg_pwm[nr - 1][2] = results[2];
|
||||
it87_write_value(client, IT87_REG_SG_PWM_HI(nr), data->sg_pwm[nr - 1][2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void it87_sgtl(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results)
|
||||
{
|
||||
struct it87_data *data = client->data;
|
||||
int nr = ctl_name - IT87_SYSCTL_PWM1 + 1;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 1;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
it87_update_client(client);
|
||||
results[0] = TEMP_FROM_REG(data->sg_tl[nr - 1][0]);
|
||||
results[1] = TEMP_FROM_REG(data->sg_tl[nr - 1][1]);
|
||||
results[2] = TEMP_FROM_REG(data->sg_tl[nr - 1][2]);
|
||||
results[3] = TEMP_FROM_REG(data->sg_tl[nr - 1][3]);
|
||||
results[4] = TEMP_FROM_REG(data->sg_tl[nr - 1][4]);
|
||||
*nrels_mag = 5;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->sg_tl[nr - 1][0] = TEMP_TO_REG(results[0]);
|
||||
it87_write_value(client, IT87_REG_SG_TL_OFF(nr), data->sg_pwm[nr - 1][0]);
|
||||
}
|
||||
if (*nrels_mag >= 2) {
|
||||
data->sg_tl[nr - 1][1] = TEMP_TO_REG(results[1]);
|
||||
it87_write_value(client, IT87_REG_SG_TL_LOW(nr), data->sg_pwm[nr - 1][1]);
|
||||
}
|
||||
if (*nrels_mag >= 3) {
|
||||
data->sg_tl[nr - 1][2] = TEMP_TO_REG(results[2]);
|
||||
it87_write_value(client, IT87_REG_SG_TL_MED(nr), data->sg_pwm[nr - 1][2]);
|
||||
}
|
||||
if (*nrels_mag >= 4) {
|
||||
data->sg_tl[nr - 1][3] = TEMP_TO_REG(results[3]);
|
||||
it87_write_value(client, IT87_REG_SG_TL_HI(nr), data->sg_pwm[nr - 1][3]);
|
||||
}
|
||||
if (*nrels_mag >= 5) {
|
||||
data->sg_tl[nr - 1][4] = TEMP_TO_REG(results[4]);
|
||||
it87_write_value(client, IT87_REG_SG_TL_OVR(nr), data->sg_pwm[nr - 1][4]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void it87_vid(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results)
|
||||
{
|
||||
@@ -848,10 +1037,19 @@ void it87_fan_div(struct i2c_client *client, int operation, int ctl_name,
|
||||
it87_update_client(client);
|
||||
results[0] = DIV_FROM_REG(data->fan_div[0]);
|
||||
results[1] = DIV_FROM_REG(data->fan_div[1]);
|
||||
results[2] = 2;
|
||||
results[2] = DIV_FROM_REG(data->fan_div[2]);;
|
||||
*nrels_mag = 3;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
old = it87_read_value(client, IT87_REG_FAN_DIV);
|
||||
if (*nrels_mag >= 3) {
|
||||
data->fan_div[2] = DIV_TO_REG(results[2]);
|
||||
if( data->fan[2]!=3 ) {
|
||||
data->fan_div[2] = 1;
|
||||
old = (old & 0xbf);
|
||||
} else {
|
||||
old = (old | 0x40);
|
||||
}
|
||||
}
|
||||
if (*nrels_mag >= 2) {
|
||||
data->fan_div[1] = DIV_TO_REG(results[1]);
|
||||
old = (old & 0xc3) | (data->fan_div[1] << 3);
|
||||
@@ -864,6 +1062,28 @@ void it87_fan_div(struct i2c_client *client, int operation, int ctl_name,
|
||||
}
|
||||
}
|
||||
|
||||
void it87_fan_ctl(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results)
|
||||
{
|
||||
struct it87_data *data = client->data;
|
||||
int index = ctl_name - IT87_SYSCTL_FAN_CTL;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
it87_update_client(client);
|
||||
results[0] = data->fan_ctl[index];
|
||||
*nrels_mag = 1;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->fan_ctl[index] = results[0];
|
||||
if( index == 0 )
|
||||
it87_write_value(client, IT87_REG_FAN_CTRL, data->fan_ctl[index] );
|
||||
else
|
||||
it87_write_value(client, IT87_REG_FAN_ONOFF, data->fan_ctl[index] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int __init sm_it87_init(void)
|
||||
{
|
||||
printk("it87.o version %s (%s)\n", LM_VERSION, LM_DATE);
|
||||
@@ -883,6 +1103,10 @@ MODULE_PARM(update_vbat, "i");
|
||||
MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value");
|
||||
MODULE_PARM(temp_type, "i");
|
||||
MODULE_PARM_DESC(temp_type, "Temperature sensor type, normally leave unset");
|
||||
MODULE_PARM(init, "i");
|
||||
MODULE_PARM_DESC(init, "Initialize the chip's registers, default yes");
|
||||
MODULE_PARM(reset_it87, "i");
|
||||
MODULE_PARM_DESC(reset_it87, "Reset the chip's registers, default no");
|
||||
|
||||
module_init(sm_it87_init);
|
||||
module_exit(sm_it87_exit);
|
||||
Reference in new issue
Block a user