From b32aa3c716ceb2159cc29fb2a3e238941ea675e5 Mon Sep 17 00:00:00 2001 From: Rudolf Marek Date: Wed, 1 Jun 2005 10:49:04 +0000 Subject: [PATCH] Update from Huang - w83792d_driver-1.0.5.patch, alarms handling fixed git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@3012 7894878c-1315-0410-8ee3-d5d059ff63e0 --- kernel/chips/w83792d.c | 107 +++++++++++++++++++++++++---------------- lib/chips.c | 2 + lib/chips.h | 1 + prog/sensors/chips.c | 14 ++++-- 4 files changed, 80 insertions(+), 44 deletions(-) diff --git a/kernel/chips/w83792d.c b/kernel/chips/w83792d.c index a50124ad..79883e9a 100644 --- a/kernel/chips/w83792d.c +++ b/kernel/chips/w83792d.c @@ -26,12 +26,10 @@ calculation method to in6-in7(measured value, limits) is a little different between C and B version. C or B version can be identified by CR[0x49h]. - 3. Maybe there is some bug in temp3, because temp3 measured value - usually seems wrong. - 4. The function of chassis open detection need further test. - 5. The function of vid and vrm has not been finished, because I'm NOT + 3. The function of chassis open detection need further test. + 4. The function of vid and vrm has not been finished, because I'm NOT very familiar with them. If someone can finish it, that's good, - then please delete this note 5. + then please delete this note 4. */ /* @@ -170,6 +168,7 @@ static const u8 W83792D_REG_FAN_DIV[4] = { 0x9E /* contains FAN7 Divisor. */ }; +#define W83792D_REG_ALARM1 0x41 /* Interrupt Status for Temp1-Temp3 */ #define W83792D_REG_CASE_OPEN 0x42 /* Bit 5: Case Open status bit */ #define W83792D_REG_CASE_OPEN_CLR 0x44 /* Bit 7: Case Open CLR_CHS/Reset bit */ @@ -224,9 +223,9 @@ static inline u8 FAN_TO_REG(long rpm, int div) } #define IN_FROM_REG(nr,val) (((nr)<=1)?(val*2): \ - ((((nr)==6)||((nr)==7))?(val*6):(val*4))) + ((((nr)==6)||((nr)==7))?(val*6):(val*4))) #define IN_TO_REG(nr,val) (((nr)<=1)?(val/2): \ - ((((nr)==6)||((nr)==7))?(val/6):(val/4))) + ((((nr)==6)||((nr)==7))?(val/6):(val/4))) #define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*10) #define TEMP_TO_REG(val) (SENSORS_LIMIT((val>=0)?((val)/10):((val)/10+256), 0, 255)) #define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div))) @@ -268,6 +267,7 @@ struct w83792d_data { although 792 chip has 7 set of pwm. */ u8 pwm_flag[7]; /* indicates PWM or DC mode: 1->PWM; 0->DC */ /* u8 vrm; VRM version */ + u8 alarms; /* interrupt status for temp1-temp3 */ u8 chassis[2]; /* [0]->Chassis status, [1]->CLR_CHS */ u8 thermal_cruise[3]; /* Smart FanI: Fan1,2,3 target value */ u8 fan_tolerance[3]; /* Fan1,2,3 tolerance(Smart Fan I/II) */ @@ -303,6 +303,8 @@ static void w83792d_vrm(struct i2c_client *client, int operation, int ctl_name, int *nrels_mag, long *results); */ static void w83792d_fan_div(struct i2c_client *client, int operation, int ctl_name, int *nrels_mag, long *results); +static void w83792d_alarms(struct i2c_client *client, int operation, + int ctl_name, int *nrels_mag, long *results); static void w83792d_chassis(struct i2c_client *client, int operation, int ctl_name, int *nrels_mag, long *results); static void w83792d_pwm(struct i2c_client *client, int operation, @@ -359,6 +361,7 @@ static struct i2c_driver w83792d_driver = { #define W83792D_SYSCTL_FAN_CFG 1500 /* control Fan Mode */ #define W83792D_SYSCTL_FAN_DIV 1501 #define W83792D_SYSCTL_CHASSIS 1502 /* control Case Open */ +#define W83792D_SYSCTL_ALARMS 1503 /* only for temp1-3 */ #define W83792D_SYSCTL_THERMAL_CRUISE 1600 /* Smart Fan I: target value */ #define W83792D_SYSCTL_FAN_TOLERANCE 1601 /* Smart Fan I/II: tolerance */ @@ -369,6 +372,10 @@ static struct i2c_driver w83792d_driver = { #define W83792D_SYSCTL_SF2_LEVELS_FAN2 1606 /* Smart Fan II: Fan2 levels */ #define W83792D_SYSCTL_SF2_LEVELS_FAN3 1607 /* Smart Fan II: Fan3 levels */ +#define W83792D_ALARM_TEMP1 0x04 +#define W83792D_ALARM_TEMP2 0x08 +#define W83792D_ALARM_TEMP3 0x10 + /* -- SENSORS SYSCTL END -- */ /* These files are created for detected chip, @@ -417,6 +424,8 @@ static ctl_table w83792d_dir_table_template[] = &i2c_sysctl_real, NULL, &w83792d_vid}, */ {W83792D_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real, &i2c_sysctl_real, NULL, &w83792d_fan_div}, + {W83792D_SYSCTL_ALARMS, "alarms", NULL, 0, 0644, NULL, + &i2c_proc_real, &i2c_sysctl_real, NULL, &w83792d_alarms}, {W83792D_SYSCTL_CHASSIS, "chassis", NULL, 0, 0644, NULL, &i2c_proc_real, &i2c_sysctl_real, NULL, &w83792d_chassis}, {W83792D_SYSCTL_PWM1, "pwm1", NULL, 0, 0644, NULL, &i2c_proc_real, @@ -730,11 +739,12 @@ static void w83792d_init_client(struct i2c_client *client) w83792d_write_value(client, W83792D_REG_TEMP_ADD[1][6], temp3_cfg & 0xe6); - /* enable comparator mode for temp2 and temp3 so - alarm indication will work correctly */ + /* Enable comparator mode for temperature sensors so alarm indication + will work correctly. Note that in W83792D, only the temps support + comparator mode, while voltages and fans only support interrupt + mode */ i = w83792d_read_value(client, W83792D_REG_IRQ); - if (!(i & 0x40)) - w83792d_write_value(client, W83792D_REG_IRQ, i|0x40); + w83792d_write_value(client, W83792D_REG_IRQ, i & 0x3f); /* Start monitoring */ w83792d_write_value(client, W83792D_REG_CONFIG, (w83792d_read_value( @@ -814,6 +824,9 @@ static void w83792d_update_client(struct i2c_client *client) (w83792d_read_value(client, W83792D_REG_CHIPID) & 0x01) << 4; */ + /* Update the Interrupt Status of temp1-temp3 */ + data->alarms = w83792d_read_value(client, W83792D_REG_ALARM1); + /* Update CaseOpen status and it's CLR_CHS. */ data->chassis[0] = (w83792d_read_value(client, W83792D_REG_CASE_OPEN) @@ -1102,43 +1115,39 @@ void w83792d_temp_add(struct i2c_client *client, int operation, w83792d_update_client(client); for (i=0; i<3; i++) { j = (i==0) ? 2 : ((i==1)?0:1); - if (((data->temp_add[nr][i*2+1]) && 0x80) == 0) { - results[j] = TEMP_FROM_REG(data->temp_add[nr][i*2]); - } else { + if ((data->temp_add[nr][i*2+1]) & 0x80) { results[j] = TEMP_FROM_REG(data->temp_add[nr][i*2]) + 5; + } else { + results[j] = TEMP_FROM_REG(data->temp_add[nr][i*2]); } } *nrels_mag = 3; } else if (operation == SENSORS_PROC_REAL_WRITE) { - data->temp_add[nr][2] = TEMP_TO_REG(results[0]); - data->temp_add[nr][4] = TEMP_TO_REG(results[1]); - w83792d_write_value(client, - W83792D_REG_TEMP_ADD[nr][2], - data->temp_add[nr][2]); - w83792d_write_value(client, - W83792D_REG_TEMP_ADD[nr][4], - data->temp_add[nr][4]); - if ((results[0]%10) == 0) { + if (*nrels_mag >= 1) { + data->temp_add[nr][2] = TEMP_TO_REG(results[0]); w83792d_write_value(client, - W83792D_REG_TEMP_ADD[nr][3], - w83792d_read_value(client, - W83792D_REG_TEMP_ADD[nr][3])&0x7f); - } else { /* consider the 0.5 degree */ - w83792d_write_value(client, - W83792D_REG_TEMP_ADD[nr][3], - w83792d_read_value(client, - W83792D_REG_TEMP_ADD[nr][3])|0x80); + W83792D_REG_TEMP_ADD[nr][2], + data->temp_add[nr][2]); + if ((results[0]%10) == 0) { + w83792d_write_value(client, + W83792D_REG_TEMP_ADD[nr][3], 0x00); + } else { /* consider the 0.5 degree */ + w83792d_write_value(client, + W83792D_REG_TEMP_ADD[nr][3], 0x80); + } } - if ((results[1]%10) == 0) { + if (*nrels_mag >= 2) { + data->temp_add[nr][4] = TEMP_TO_REG(results[1]); w83792d_write_value(client, - W83792D_REG_TEMP_ADD[nr][5], - w83792d_read_value(client, - W83792D_REG_TEMP_ADD[nr][5])&0x7f); - } else { /* consider the 0.5 degree */ - w83792d_write_value(client, - W83792D_REG_TEMP_ADD[nr][5], - w83792d_read_value(client, - W83792D_REG_TEMP_ADD[nr][5])|0x80); + W83792D_REG_TEMP_ADD[nr][4], + data->temp_add[nr][4]); + if ((results[1]%10) == 0) { + w83792d_write_value(client, + W83792D_REG_TEMP_ADD[nr][5], 0x00); + } else { /* consider the 0.5 degree */ + w83792d_write_value(client, + W83792D_REG_TEMP_ADD[nr][5], 0x80); + } } } } @@ -1356,6 +1365,22 @@ void w83792d_sf2_levels(struct i2c_client *client, int operation, } } +/* Read/Write interrupt status of temperature sensors */ +void w83792d_alarms(struct i2c_client *client, int operation, int ctl_name, + int *nrels_mag, long *results) +{ + struct w83792d_data *data = client->data; + if (operation == SENSORS_PROC_REAL_INFO) + *nrels_mag = 0; + else if (operation == SENSORS_PROC_REAL_READ) { + w83792d_update_client(client); + /* In W83792D, only the temps support comparator mode, + while voltages and fans only support interrupt mode */ + results[0] = (data->alarms) & 0x1c; + *nrels_mag = 1; + } +} + /* Read/Write Chassis status and Reset Chassis. */ void w83792d_chassis(struct i2c_client *client, int operation, int ctl_name, int *nrels_mag, long *results) @@ -1484,7 +1509,7 @@ static void __exit sm_w83792d_exit(void) } -MODULE_AUTHOR("Chunhao Huang @ Winbond"); +MODULE_AUTHOR("Chunhao Huang @ Winbond "); MODULE_DESCRIPTION("W83792AD/D driver for linux-2.4"); MODULE_LICENSE("GPL"); diff --git a/lib/chips.c b/lib/chips.c index 3fdc6d37..dbbea080 100644 --- a/lib/chips.c +++ b/lib/chips.c @@ -1857,6 +1857,8 @@ static sensors_chip_feature w83792d_features[] = { SENSORS_W83792D_FAN7_DIV, "fan7_div", SENSORS_W83792D_FAN7, NOMAP, RW, W83792D_SYSCTL_FAN_DIV, VALUE(7), 0 }, + { SENSORS_W83792D_ALARMS, "alarms", NOMAP, NOMAP, + R, W83792D_SYSCTL_ALARMS, VALUE(1), 0 }, { 0 } }; diff --git a/lib/chips.h b/lib/chips.h index 20bd0136..105ab784 100644 --- a/lib/chips.h +++ b/lib/chips.h @@ -716,6 +716,7 @@ /*#define SENSORS_W83792D_VID 61 */ /* R */ /*#define SENSORS_W83792D_VRM 62 */ /* RW */ #define SENSORS_W83792D_CHASSIS 63 /* R */ +#define SENSORS_W83792D_ALARMS 64 /* R */ #define SENSORS_W83792D_FAN1_DIV 71 /* RW */ #define SENSORS_W83792D_FAN2_DIV 72 /* RW */ diff --git a/prog/sensors/chips.c b/prog/sensors/chips.c index 12ff0041..ae6458cd 100644 --- a/prog/sensors/chips.c +++ b/prog/sensors/chips.c @@ -2516,9 +2516,17 @@ void print_w83781d(const sensors_chip_name *name) void print_w83792d(const sensors_chip_name *name) { char *label = NULL; + int alarms; double cur,min,max,fdiv; int valid = 0; + if (!sensors_get_feature(*name,SENSORS_W83792D_ALARMS,&cur)) + alarms = cur + 0.5; + else { + printf("ERROR: Can't get alarm data!\n"); + alarms = 0; + } + if (!sensors_get_label_and_valid(*name,SENSORS_W83792D_IN0,&label,&valid) && !sensors_get_feature(*name,SENSORS_W83792D_IN0,&cur) && !sensors_get_feature(*name,SENSORS_W83792D_IN0_MIN,&min) && @@ -2738,7 +2746,7 @@ void print_w83792d(const sensors_chip_name *name) printf(" %s\n", (cur>max)?"ALARM":""); }else{ print_temp_info( cur, max, min, HYST, 1, 1); - printf(" %s\n", ((curmax))?"ALARM":""); + printf(" %s\n", (alarms&W83792D_ALARM_TEMP1)?"ALARM":""); } } } else @@ -2752,7 +2760,7 @@ void print_w83792d(const sensors_chip_name *name) if (valid) { print_label(label,10); print_temp_info( cur, max, min, HYST, 1, 1); - printf(" %s\n", ((curmax))?"ALARM":""); + printf(" %s\n", (alarms&W83792D_ALARM_TEMP2)?"ALARM":""); } } else printf("ERROR: Can't get TEMP2 data!\n"); @@ -2765,7 +2773,7 @@ void print_w83792d(const sensors_chip_name *name) if (valid) { print_label(label,10); print_temp_info( cur, max, min, HYST, 1, 1); - printf(" %s\n", ((curmax))?"ALARM":""); + printf(" %s\n", (alarms&W83792D_ALARM_TEMP3)?"ALARM":""); } } else printf("ERROR: Can't get TEMP3 data!\n");