Changeset 121

Show
Ignore:
Timestamp:
12/26/98 02:18:58 (14 years ago)
Author:
frodo
Message:

Winbond driver enhancements (untested)

* Force the Winbond into bank 0 before anything else is done
* Copied fan_div patch from lm78.c
* Copied IN_{FROM,TO}_REG patch from lm78.c
* Copied alarms computation bug fix from lm78.c
* Nicer way of managing banks: the bank number to access is now the high

byte of the (as u16 declared) register number. Only
w38781d_{read,write}_value needs now to be aware of banks. Also, the
w38781d_{read,write}_value functions now know that sensors 2 and temp, hyst
and over registers are word-sized.

* Introduced fan_div for FAN3 and 9-bit temperature readings.
* Made beep file work like the gl518sm one
* Corrected small VID problem (bit 4 was read from the wrong register)

Location:
lm-sensors/trunk
Files:
5 modified

Legend:

Unmodified
Added
Removed
  • lm-sensors/trunk/kernel/chips/w83781d.c

    r96 r121  
    1  
    21/* 
    32    w83781d.c - Part of lm_sensors, Linux kernel modules for hardware 
     
    5352#define W83781D_REG_FAN(nr) (0x27 + (nr)) 
    5453 
    55 #define W83781D_REG_TEMP23 0x50 
    56 #define W83781D_REG_TEMP_HYST23 0x53 
    57 #define W83781D_REG_TEMP_CONFIG23 0x52 
    58 #define W83781D_REG_TEMP_OVER23 0x55 
     54#define W83781D_REG_TEMP2 0x0150 
     55#define W83781D_REG_TEMP3 0x0250 
     56#define W83781D_REG_TEMP2_HYST 0x153 
     57#define W83781D_REG_TEMP3_HYST 0x253 
     58#define W83781D_REG_TEMP2_CONFIG 0x152 
     59#define W83781D_REG_TEMP3_CONFIG 0x252 
     60#define W83781D_REG_TEMP2_OVER 0x155 
     61#define W83781D_REG_TEMP3_OVER 0x255 
     62 
    5963#define W83781D_REG_TEMP 0x27 
    6064#define W83781D_REG_TEMP_OVER 0x39 
    6165#define W83781D_REG_TEMP_HYST 0x3A 
    6266#define W83781D_REG_TEMP_CONFIG 0x52 
    63 #define W83781D_REG_TEMP_SEL 0x4E 
     67#define W83781D_REG_BANK 0x4E 
    6468 
    6569#define W83781D_REG_CONFIG 0x40 
     
    7377#define W83781D_REG_VID_FANDIV 0x47 
    7478 
    75 #define W83781D_REG_CHIPID 0x58 
     79#define W83781D_REG_CHIPID 0x49 
     80#define W83781D_REG_WCHIPID 0x58 
    7681#define W83781D_REG_CHIPMAN 0x4F 
     82#define W83781D_REG_PIN 0x4B 
    7783 
    7884 
    7985/* Conversions. Rounding is only done on the TO_REG variants. */ 
    80 static int w83781d_in_conv[7] = {10000, 10000, 10000, 16892, 38000,  
    81                               -34768, -15050 }; 
    82 #define IN_TO_REG(val,nr) (((((val) * 100000 / w83781d_in_conv[nr]) + 8) / 16) \ 
    83                            & 0xff) 
    84 #define IN_FROM_REG(val,nr) (((val) *  16 * w83781d_in_conv[nr]) / 100000) 
    85  
    86 #define FAN_TO_REG(val) ((val)==0?255:((1350000+(val))/((val)*2)) & 0xff) 
    87 #define FAN_FROM_REG(val) ((val)==0?-1:(val)==255?0:1350000/((val)*2)) 
     86#define IN_TO_REG(val,nr) (((val) * 10 + 8)/16) 
     87#define IN_FROM_REG(val,nr) (((val) * 16) / 10) 
     88 
     89#define FAN_TO_REG(val,div) ((val)==0?255:((1350000+(val))/\ 
     90                            ((val)*2*(div))) & 0xff) 
     91#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*2*(div))) 
    8892 
    8993#define TEMP_TO_REG(val) (((val)<0?(((val)-5)/10)&0xff:((val)+5)/10) & 0xff) 
    9094#define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*10) 
     95 
     96#define TEMP_ADD_TO_REG(val)   (((((val) + 2) / 5) << 7) & 0xff80) 
     97#define TEMP_ADD_FROM_REG(val) (((val) >> 7) * 5) 
    9198 
    9299#define VID_FROM_REG(val) ((val)==0x1f?0:(val)>=0x10?510-(val)*10:\ 
    93100                           (val)>=0x06?0:205-(val)*5) 
    94101#define ALARMS_FROM_REG(val) (val) 
     102#define BEEPS_FROM_REG(val) (val) 
     103#define BEEPS_TO_REG(val) ((val) & 0xffff) 
     104 
     105#define BEEP_ENABLE_TO_REG(val) (val) 
     106#define BEEP_ENABLE_FROM_REG(val) ((val)?1:0) 
    95107 
    96108#define DIV_FROM_REG(val) (1 << (val)) 
     
    101113#define W83781D_INIT_IN_1 (vid==350?280:vid) 
    102114#define W83781D_INIT_IN_2 330 
    103 #define W83781D_INIT_IN_3 500 
    104 #define W83781D_INIT_IN_4 1200 
    105 #define W83781D_INIT_IN_5 -1200 
    106 #define W83781D_INIT_IN_6 -500 
     115#define W83781D_INIT_IN_3 (((500)   * 100)/168) 
     116#define W83781D_INIT_IN_4 (((1200)  * 10)/38) 
     117#define W83781D_INIT_IN_5 (((-1200) * -604)/2100) 
     118#define W83781D_INIT_IN_6 (((-500)  * -604)/909) 
    107119 
    108120#define W83781D_INIT_IN_PERCENTAGE 10 
    109121 
    110122#define W83781D_INIT_IN_MIN_0 \ 
    111         (W83781D_INIT_IN_0 - W83781D_INIT_IN_0 * W83781D_INIT_IN_PERCENTAGE / 100)  
     123        (W83781D_INIT_IN_0 - W83781D_INIT_IN_0 * W83781D_INIT_IN_PERCENTAGE \ 
     124         / 100)  
    112125#define W83781D_INIT_IN_MAX_0 \ 
    113         (W83781D_INIT_IN_0 + W83781D_INIT_IN_0 * W83781D_INIT_IN_PERCENTAGE / 100)  
     126        (W83781D_INIT_IN_0 + W83781D_INIT_IN_0 * W83781D_INIT_IN_PERCENTAGE \ 
     127         / 100)  
    114128#define W83781D_INIT_IN_MIN_1 \ 
    115         (W83781D_INIT_IN_1 - W83781D_INIT_IN_1 * W83781D_INIT_IN_PERCENTAGE / 100)  
     129        (W83781D_INIT_IN_1 - W83781D_INIT_IN_1 * W83781D_INIT_IN_PERCENTAGE \ 
     130         / 100)  
    116131#define W83781D_INIT_IN_MAX_1 \ 
    117         (W83781D_INIT_IN_1 + W83781D_INIT_IN_1 * W83781D_INIT_IN_PERCENTAGE / 100)  
     132        (W83781D_INIT_IN_1 + W83781D_INIT_IN_1 * W83781D_INIT_IN_PERCENTAGE \ 
     133         / 100)  
    118134#define W83781D_INIT_IN_MIN_2 \ 
    119         (W83781D_INIT_IN_2 - W83781D_INIT_IN_2 * W83781D_INIT_IN_PERCENTAGE / 100)  
     135        (W83781D_INIT_IN_2 - W83781D_INIT_IN_2 * W83781D_INIT_IN_PERCENTAGE \ 
     136         / 100)  
    120137#define W83781D_INIT_IN_MAX_2 \ 
    121         (W83781D_INIT_IN_2 + W83781D_INIT_IN_2 * W83781D_INIT_IN_PERCENTAGE / 100)  
     138        (W83781D_INIT_IN_2 + W83781D_INIT_IN_2 * W83781D_INIT_IN_PERCENTAGE \ 
     139         / 100)  
    122140#define W83781D_INIT_IN_MIN_3 \ 
    123         (W83781D_INIT_IN_3 - W83781D_INIT_IN_3 * W83781D_INIT_IN_PERCENTAGE / 100)  
     141        (W83781D_INIT_IN_3 - W83781D_INIT_IN_3 * W83781D_INIT_IN_PERCENTAGE \ 
     142         / 100)  
    124143#define W83781D_INIT_IN_MAX_3 \ 
    125         (W83781D_INIT_IN_3 + W83781D_INIT_IN_3 * W83781D_INIT_IN_PERCENTAGE / 100)  
     144        (W83781D_INIT_IN_3 + W83781D_INIT_IN_3 * W83781D_INIT_IN_PERCENTAGE \ 
     145         / 100)  
    126146#define W83781D_INIT_IN_MIN_4 \ 
    127         (W83781D_INIT_IN_4 - W83781D_INIT_IN_4 * W83781D_INIT_IN_PERCENTAGE / 100)  
     147        (W83781D_INIT_IN_4 - W83781D_INIT_IN_4 * W83781D_INIT_IN_PERCENTAGE \ 
     148         / 100)  
    128149#define W83781D_INIT_IN_MAX_4 \ 
    129         (W83781D_INIT_IN_4 + W83781D_INIT_IN_4 * W83781D_INIT_IN_PERCENTAGE / 100)  
     150        (W83781D_INIT_IN_4 + W83781D_INIT_IN_4 * W83781D_INIT_IN_PERCENTAGE \ 
     151         / 100)  
    130152#define W83781D_INIT_IN_MIN_5 \ 
    131         (W83781D_INIT_IN_5 - W83781D_INIT_IN_5 * W83781D_INIT_IN_PERCENTAGE / 100)  
     153        (W83781D_INIT_IN_5 - W83781D_INIT_IN_5 * W83781D_INIT_IN_PERCENTAGE \ 
     154         / 100)  
    132155#define W83781D_INIT_IN_MAX_5 \ 
    133         (W83781D_INIT_IN_5 + W83781D_INIT_IN_5 * W83781D_INIT_IN_PERCENTAGE / 100)  
     156        (W83781D_INIT_IN_5 + W83781D_INIT_IN_5 * W83781D_INIT_IN_PERCENTAGE \ 
     157         / 100)  
    134158#define W83781D_INIT_IN_MIN_6 \ 
    135         (W83781D_INIT_IN_6 - W83781D_INIT_IN_6 * W83781D_INIT_IN_PERCENTAGE / 100)  
     159        (W83781D_INIT_IN_6 - W83781D_INIT_IN_6 * W83781D_INIT_IN_PERCENTAGE \ 
     160         / 100)  
    136161#define W83781D_INIT_IN_MAX_6 \ 
    137         (W83781D_INIT_IN_6 + W83781D_INIT_IN_6 * W83781D_INIT_IN_PERCENTAGE / 100)  
     162        (W83781D_INIT_IN_6 + W83781D_INIT_IN_6 * W83781D_INIT_IN_PERCENTAGE \ 
     163         / 100)  
    138164 
    139165#define W83781D_INIT_FAN_MIN_1 3000 
     
    181207         u8 fan[3];                  /* Register value */ 
    182208         u8 fan_min[3];              /* Register value */ 
    183          u8 temp[3];                    /* Register value */ 
    184          u8 temp_over[3];               /* Register value */ 
    185          u8 temp_hyst[3];               /* Register value */ 
    186          u8 fan_div[2];              /* Register encoding, shifted right */ 
     209         u8 temp; 
     210         u8 temp_over;               /* Register value */ 
     211         u8 temp_hyst;               /* Register value */ 
     212         u8 temp_add[2];             /* Register value */ 
     213         u16 temp_add_over[2];       /* Register value */ 
     214         u16 temp_add_hyst[2];       /* Register value */ 
     215         u8 fan_div[3];              /* Register encoding, shifted right */ 
    187216         u8 vid;                     /* Register encoding, combined */ 
    188217         u16 alarms;                 /* Register encoding, combined */ 
    189          u8 beep[3];                    /* Register value of config and interrupt masks */ 
     218         u16 beeps;                  /* Register encoding, combined */ 
     219         u8 beep_enable;             /* Boolean */ 
    190220}; 
    191221 
     
    208238static void w83781d_dec_use (struct i2c_client *client); 
    209239 
    210 static int w83781d_read_value(struct i2c_client *client, u8 register); 
    211 static int w83781d_write_value(struct i2c_client *client, u8 register, u8 value); 
     240static int w83781d_read_value(struct i2c_client *client, u16 register); 
     241static int w83781d_write_value(struct i2c_client *client, u16 register,  
     242                               u16 value); 
    212243static void w83781d_update_client(struct i2c_client *client); 
    213244static void w83781d_init_client(struct i2c_client *client); 
     
    218249static void w83781d_fan(struct i2c_client *client, int operation, int ctl_name, 
    219250                     int *nrels_mag, long *results); 
    220 static void w83781d_temp(struct i2c_client *client, int operation, int ctl_name, 
    221                       int *nrels_mag, long *results,int tempnum); 
    222 static void w83781d_temp1(struct i2c_client *client, int operation, int ctl_name, 
    223                       int *nrels_mag, long *results); 
    224 static void w83781d_temp2(struct i2c_client *client, int operation, int ctl_name, 
    225                       int *nrels_mag, long *results); 
    226 static void w83781d_temp3(struct i2c_client *client, int operation, int ctl_name, 
    227                       int *nrels_mag, long *results); 
     251static void w83781d_temp(struct i2c_client *client, int operation,  
     252                          int ctl_name, int *nrels_mag, long *results); 
     253static void w83781d_temp_add(struct i2c_client *client, int operation,  
     254                          int ctl_name, int *nrels_mag, long *results); 
    228255static void w83781d_vid(struct i2c_client *client, int operation, int ctl_name, 
    229                      int *nrels_mag, long *results); 
    230 static void w83781d_alarms(struct i2c_client *client, int operation, int ctl_name, 
    231                         int *nrels_mag, long *results); 
     256                         int *nrels_mag, long *results); 
     257static void w83781d_alarms(struct i2c_client *client, int operation, 
     258                           int ctl_name, int *nrels_mag, long *results); 
    232259static void w83781d_beep(struct i2c_client *client, int operation, int ctl_name, 
    233260                      int *nrels_mag, long *results); 
    234 static void w83781d_fan_div(struct i2c_client *client, int operation, int ctl_name, 
    235                          int *nrels_mag, long *results); 
     261static void w83781d_fan_div(struct i2c_client *client, int operation, 
     262                            int ctl_name, int *nrels_mag, long *results); 
    236263 
    237264/* I choose here for semi-static W83781D allocation. Complete dynamic 
     
    284311  { W83781D_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &sensors_proc_real, 
    285312    &sensors_sysctl_real, NULL, &w83781d_fan }, 
    286   { W83781D_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &sensors_proc_real, 
    287     &sensors_sysctl_real, NULL, &w83781d_temp1 }, 
     313  { W83781D_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL, &sensors_proc_real, 
     314    &sensors_sysctl_real, NULL, &w83781d_temp }, 
    288315  { W83781D_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL, &sensors_proc_real, 
    289     &sensors_sysctl_real, NULL, &w83781d_temp2 }, 
     316    &sensors_sysctl_real, NULL, &w83781d_temp_add }, 
    290317  { W83781D_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL, &sensors_proc_real, 
    291     &sensors_sysctl_real, NULL, &w83781d_temp3 }, 
     318    &sensors_sysctl_real, NULL, &w83781d_temp_add }, 
    292319  { W83781D_SYSCTL_VID, "vid", NULL, 0, 0644, NULL, &sensors_proc_real, 
    293320    &sensors_sysctl_real, NULL, &w83781d_vid }, 
     
    355382    /* Real detection code goes here */ 
    356383 
    357     outb_p(W83781D_REG_CHIPID,address + W83781D_ADDR_REG_OFFSET); 
     384    /* The Winbond may be stuck in bank 1 or 2. This should reset it.  
     385       We really need some nifty detection code, because this can lead 
     386       to a lot of problems if there is no Winbond present! */ 
     387    outb_p(W83781D_REG_BANK,address + W83781D_ADDR_REG_OFFSET); 
     388    outb_p(0x00,address + W83781D_DATA_REG_OFFSET); 
     389 
     390    outb_p(W83781D_REG_WCHIPID,address + W83781D_ADDR_REG_OFFSET); 
    358391    err = inb_p(address + W83781D_DATA_REG_OFFSET) & 0xfe; 
    359392 
     
    461494      continue; 
    462495 
    463     err = smbus_read_byte_data(adapter,address,W83781D_REG_CHIPID); 
     496    smbus_write_byte_data(adapter,address,W83781D_REG_BANK,0x00); 
     497 
     498    err = smbus_read_byte_data(adapter,address,W83781D_REG_WCHIPID); 
    464499     
    465500    if (err == 0x20) { 
     
    600635  
    601636 
    602 /* The SMBus locks itself, but ISA access must be locked explicitely!  
     637/* The SMBus locks itself, usually, but nothing may access the Winbond between 
     638   bank switches. ISA access must always be locked explicitely!  
    603639   We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks, 
    604640   would slow down the W83781D access and should not be necessary.  
    605641   There are some ugly typecasts here, but the good new is - they should 
    606642   nowhere else be necessary! */ 
    607 int w83781d_read_value(struct i2c_client *client, u8 reg) 
    608 { 
    609   int res; 
     643int w83781d_read_value(struct i2c_client *client, u16 reg) 
     644{ 
     645  int res,word_sized; 
     646 
     647  word_sized = (reg & 0x0ff) && (((reg && 0x00ff) == 0x50) ||  
     648                                 ((reg && 0x00ff) == 0x53) ||  
     649                                 ((reg && 0x00ff) == 0x55)); 
     650  down((struct semaphore *) (client->data)); 
    610651  if (i2c_is_isa_client(client)) { 
    611     down((struct semaphore *) (client->data)); 
    612     outb_p(reg,(((struct isa_client *) client)->isa_addr) +  
    613                W83781D_ADDR_REG_OFFSET); 
    614     res = inb_p((((struct isa_client *) client)->isa_addr) +  
     652    if (reg & 0xff00) { 
     653      outb_p(W83781D_REG_BANK,(((struct isa_client *) client)->isa_addr) + 
     654                              W83781D_ADDR_REG_OFFSET); 
     655      outb_p(reg >> 8,(((struct isa_client *) client)->isa_addr) + 
     656                      W83781D_DATA_REG_OFFSET); 
     657    } 
     658    outb_p(reg & 0xff,(((struct isa_client *) client)->isa_addr) + 
     659                      W83781D_ADDR_REG_OFFSET); 
     660    res = inb_p((((struct isa_client *) client)->isa_addr) + 
    615661                W83781D_DATA_REG_OFFSET); 
    616     up((struct semaphore *) (client->data)); 
    617     return res; 
    618   } else 
    619     return smbus_read_byte_data(client->adapter,client->addr, reg); 
    620 } 
    621  
    622 /* The SMBus locks itself, but ISA access muse be locked explicitely!  
     662    if (word_sized) { 
     663      outb_p((reg & 0xff)+1,(((struct isa_client *) client)->isa_addr) + 
     664                        W83781D_ADDR_REG_OFFSET); 
     665      res = (res << 8) + inb_p((((struct isa_client *) client)->isa_addr) + 
     666                         W83781D_DATA_REG_OFFSET); 
     667    } 
     668    if (reg & 0xff00) { 
     669      outb_p(W83781D_REG_BANK,(((struct isa_client *) client)->isa_addr) + 
     670                              W83781D_ADDR_REG_OFFSET); 
     671      outb_p(0,(((struct isa_client *) client)->isa_addr) + 
     672               W83781D_DATA_REG_OFFSET); 
     673    } 
     674  } else { 
     675    if (reg & 0xff00) 
     676      smbus_write_byte_data(client->adapter,client->addr,W83781D_REG_BANK, 
     677                            reg >> 8); 
     678    res = smbus_read_byte_data(client->adapter,client->addr, reg); 
     679    if (word_sized) 
     680      res = (res << 8) + smbus_read_byte_data(client->adapter,client->addr,  
     681                                              reg); 
     682    if (reg & 0xff00) 
     683      smbus_write_byte_data(client->adapter,client->addr,W83781D_REG_BANK,0); 
     684  } 
     685  up((struct semaphore *) (client->data)); 
     686  return res; 
     687} 
     688 
     689/* The SMBus locks itself, usually, but nothing may access the Winbond between 
     690   bank switches. ISA access must always be locked explicitely!  
    623691   We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks, 
    624692   would slow down the W83781D access and should not be necessary.  
    625693   There are some ugly typecasts here, but the good new is - they should 
    626694   nowhere else be necessary! */ 
    627 int w83781d_write_value(struct i2c_client *client, u8 reg, u8 value) 
    628 { 
     695int w83781d_write_value(struct i2c_client *client, u16 reg, u16 value) 
     696{ 
     697  int word_sized; 
     698 
     699  word_sized = (reg & 0x0ff) && (((reg && 0x00ff) == 0x50) ||  
     700                                 ((reg && 0x00ff) == 0x53) ||  
     701                                 ((reg && 0x00ff) == 0x55)); 
     702  down((struct semaphore *) (client->data)); 
    629703  if (i2c_is_isa_client(client)) { 
    630     down((struct semaphore *) (client->data)); 
    631     outb_p(reg,((struct isa_client *) client)->isa_addr + W83781D_ADDR_REG_OFFSET); 
    632     outb_p(value,((struct isa_client *) client)->isa_addr + W83781D_DATA_REG_OFFSET); 
    633     up((struct semaphore *) (client->data)); 
    634     return 0; 
    635   } else 
    636     return smbus_write_byte_data(client->adapter, client->addr, reg,value); 
     704    if (reg & 0xff00) { 
     705      outb_p(W83781D_REG_BANK,(((struct isa_client *) client)->isa_addr) + 
     706                              W83781D_ADDR_REG_OFFSET); 
     707      outb_p(reg >> 8,(((struct isa_client *) client)->isa_addr) + 
     708                      W83781D_DATA_REG_OFFSET); 
     709    } 
     710    outb_p(reg & 0xff,(((struct isa_client *) client)->isa_addr) + 
     711                      W83781D_ADDR_REG_OFFSET); 
     712    if (word_sized) { 
     713      outb_p(value >> 8,(((struct isa_client *) client)->isa_addr) + 
     714                        W83781D_DATA_REG_OFFSET); 
     715      outb_p((reg & 0xff)+1,(((struct isa_client *) client)->isa_addr) + 
     716                        W83781D_ADDR_REG_OFFSET); 
     717    } 
     718    outb_p(value &0xff,(((struct isa_client *) client)->isa_addr) + 
     719                       W83781D_DATA_REG_OFFSET); 
     720    if (reg & 0xff00) { 
     721      outb_p(W83781D_REG_BANK,(((struct isa_client *) client)->isa_addr) + 
     722                              W83781D_ADDR_REG_OFFSET); 
     723      outb_p(0,(((struct isa_client *) client)->isa_addr) + 
     724               W83781D_DATA_REG_OFFSET); 
     725    } 
     726  } else { 
     727    if (reg & 0xff00) 
     728      smbus_write_byte_data(client->adapter,client->addr,W83781D_REG_BANK, 
     729                            reg >> 8); 
     730    if (word_sized) { 
     731       smbus_write_byte_data(client->adapter,client->addr, reg, value >> 8); 
     732       smbus_write_byte_data(client->adapter,client->addr, reg+1, value &0xff); 
     733    } else 
     734      smbus_write_byte_data(client->adapter,client->addr, reg, value &0xff); 
     735    if (reg & 0xff00) 
     736      smbus_write_byte_data(client->adapter,client->addr,W83781D_REG_BANK,0); 
     737  } 
     738  up((struct semaphore *) (client->data)); 
     739  return 0; 
    637740} 
    638741 
     
    650753  vid = VID_FROM_REG(vid); 
    651754 
    652   w83781d_write_value(client,W83781D_REG_IN_MIN(0),IN_TO_REG(W83781D_INIT_IN_MIN_0,0)); 
    653   w83781d_write_value(client,W83781D_REG_IN_MAX(0),IN_TO_REG(W83781D_INIT_IN_MAX_0,0)); 
    654   w83781d_write_value(client,W83781D_REG_IN_MIN(1),IN_TO_REG(W83781D_INIT_IN_MIN_1,1)); 
    655   w83781d_write_value(client,W83781D_REG_IN_MAX(1),IN_TO_REG(W83781D_INIT_IN_MAX_1,1)); 
    656   w83781d_write_value(client,W83781D_REG_IN_MIN(2),IN_TO_REG(W83781D_INIT_IN_MIN_2,2)); 
    657   w83781d_write_value(client,W83781D_REG_IN_MAX(2),IN_TO_REG(W83781D_INIT_IN_MAX_2,2)); 
    658   w83781d_write_value(client,W83781D_REG_IN_MIN(3),IN_TO_REG(W83781D_INIT_IN_MIN_3,3)); 
    659   w83781d_write_value(client,W83781D_REG_IN_MAX(3),IN_TO_REG(W83781D_INIT_IN_MAX_3,3)); 
    660   w83781d_write_value(client,W83781D_REG_IN_MIN(4),IN_TO_REG(W83781D_INIT_IN_MIN_4,4)); 
    661   w83781d_write_value(client,W83781D_REG_IN_MAX(4),IN_TO_REG(W83781D_INIT_IN_MAX_4,4)); 
    662   w83781d_write_value(client,W83781D_REG_IN_MIN(5),IN_TO_REG(W83781D_INIT_IN_MIN_5,5)); 
    663   w83781d_write_value(client,W83781D_REG_IN_MAX(5),IN_TO_REG(W83781D_INIT_IN_MAX_5,5)); 
    664   w83781d_write_value(client,W83781D_REG_IN_MIN(6),IN_TO_REG(W83781D_INIT_IN_MIN_6,6)); 
    665   w83781d_write_value(client,W83781D_REG_IN_MAX(6),IN_TO_REG(W83781D_INIT_IN_MAX_6,6)); 
    666   w83781d_write_value(client,W83781D_REG_FAN_MIN(1),FAN_TO_REG(W83781D_INIT_FAN_MIN_1)); 
    667   w83781d_write_value(client,W83781D_REG_FAN_MIN(2),FAN_TO_REG(W83781D_INIT_FAN_MIN_2)); 
    668   w83781d_write_value(client,W83781D_REG_FAN_MIN(3),FAN_TO_REG(W83781D_INIT_FAN_MIN_3)); 
    669   /* Init Temp Sensor1 */ 
    670   w83781d_write_value(client,W83781D_REG_TEMP_SEL,0x00);/* Switch Banks! */ 
    671   w83781d_write_value(client,W83781D_REG_TEMP_OVER,TEMP_TO_REG(W83781D_INIT_TEMP_OVER)); 
    672   w83781d_write_value(client,W83781D_REG_TEMP_HYST,TEMP_TO_REG(W83781D_INIT_TEMP_HYST)); 
     755  w83781d_write_value(client,W83781D_REG_IN_MIN(0), 
     756                      IN_TO_REG(W83781D_INIT_IN_MIN_0,0)); 
     757  w83781d_write_value(client,W83781D_REG_IN_MAX(0), 
     758                      IN_TO_REG(W83781D_INIT_IN_MAX_0,0)); 
     759  w83781d_write_value(client,W83781D_REG_IN_MIN(1), 
     760                      IN_TO_REG(W83781D_INIT_IN_MIN_1,1)); 
     761  w83781d_write_value(client,W83781D_REG_IN_MAX(1), 
     762                      IN_TO_REG(W83781D_INIT_IN_MAX_1,1)); 
     763  w83781d_write_value(client,W83781D_REG_IN_MIN(2), 
     764                      IN_TO_REG(W83781D_INIT_IN_MIN_2,2)); 
     765  w83781d_write_value(client,W83781D_REG_IN_MAX(2), 
     766                      IN_TO_REG(W83781D_INIT_IN_MAX_2,2)); 
     767  w83781d_write_value(client,W83781D_REG_IN_MIN(3), 
     768                      IN_TO_REG(W83781D_INIT_IN_MIN_3,3)); 
     769  w83781d_write_value(client,W83781D_REG_IN_MAX(3), 
     770                      IN_TO_REG(W83781D_INIT_IN_MAX_3,3)); 
     771  w83781d_write_value(client,W83781D_REG_IN_MIN(4), 
     772                      IN_TO_REG(W83781D_INIT_IN_MIN_4,4)); 
     773  w83781d_write_value(client,W83781D_REG_IN_MAX(4), 
     774                      IN_TO_REG(W83781D_INIT_IN_MAX_4,4)); 
     775  w83781d_write_value(client,W83781D_REG_IN_MIN(5), 
     776                      IN_TO_REG(W83781D_INIT_IN_MIN_5,5)); 
     777  w83781d_write_value(client,W83781D_REG_IN_MAX(5), 
     778                      IN_TO_REG(W83781D_INIT_IN_MAX_5,5)); 
     779  w83781d_write_value(client,W83781D_REG_IN_MIN(6), 
     780                      IN_TO_REG(W83781D_INIT_IN_MIN_6,6)); 
     781  w83781d_write_value(client,W83781D_REG_IN_MAX(6), 
     782                      IN_TO_REG(W83781D_INIT_IN_MAX_6,6)); 
     783  w83781d_write_value(client,W83781D_REG_FAN_MIN(1), 
     784                      FAN_TO_REG(W83781D_INIT_FAN_MIN_1,2)); 
     785  w83781d_write_value(client,W83781D_REG_FAN_MIN(2), 
     786                      FAN_TO_REG(W83781D_INIT_FAN_MIN_2,2)); 
     787  w83781d_write_value(client,W83781D_REG_FAN_MIN(3), 
     788                      FAN_TO_REG(W83781D_INIT_FAN_MIN_3,2)); 
     789 
     790  w83781d_write_value(client,W83781D_REG_TEMP_OVER, 
     791                      TEMP_TO_REG(W83781D_INIT_TEMP_OVER)); 
     792  w83781d_write_value(client,W83781D_REG_TEMP_HYST, 
     793                      TEMP_TO_REG(W83781D_INIT_TEMP_HYST)); 
    673794  w83781d_write_value(client,W83781D_REG_TEMP_CONFIG,0x00); 
    674   /* Init Temp Sensor2 */ 
    675   w83781d_write_value(client,W83781D_REG_TEMP_SEL,0x01);/* Switch Banks! */ 
    676   w83781d_write_value(client,W83781D_REG_TEMP_OVER23,TEMP_TO_REG(W83781D_INIT_TEMP_OVER)); 
    677   w83781d_write_value(client,W83781D_REG_TEMP_OVER23 + 1,0); 
    678   w83781d_write_value(client,W83781D_REG_TEMP_HYST23,TEMP_TO_REG(W83781D_INIT_TEMP_HYST)); 
    679   w83781d_write_value(client,W83781D_REG_TEMP_HYST23 + 1,0); 
    680   w83781d_write_value(client,W83781D_REG_TEMP_CONFIG23,0x00); 
    681   /* Init Temp Sensor3 */ 
    682   w83781d_write_value(client,W83781D_REG_TEMP_SEL,0x02);/* Switch Banks! */ 
    683   w83781d_write_value(client,W83781D_REG_TEMP_OVER23,TEMP_TO_REG(W83781D_INIT_TEMP_OVER)); 
    684   w83781d_write_value(client,W83781D_REG_TEMP_OVER23 + 1,0); 
    685   w83781d_write_value(client,W83781D_REG_TEMP_HYST23,TEMP_TO_REG(W83781D_INIT_TEMP_HYST)); 
    686   w83781d_write_value(client,W83781D_REG_TEMP_HYST23 + 1,0); 
    687   w83781d_write_value(client,W83781D_REG_TEMP_CONFIG23,0x00); 
    688   w83781d_write_value(client,W83781D_REG_TEMP_SEL,0x00);/* Switch Banks! */ 
     795 
     796  w83781d_write_value(client,W83781D_REG_TEMP2_OVER, 
     797                      TEMP_ADD_TO_REG(W83781D_INIT_TEMP_OVER)); 
     798  w83781d_write_value(client,W83781D_REG_TEMP2_HYST, 
     799                      TEMP_ADD_TO_REG(W83781D_INIT_TEMP_HYST)); 
     800  w83781d_write_value(client,W83781D_REG_TEMP2_CONFIG,0x00); 
     801 
     802  w83781d_write_value(client,W83781D_REG_TEMP3_OVER, 
     803                      TEMP_ADD_TO_REG(W83781D_INIT_TEMP_OVER)); 
     804  w83781d_write_value(client,W83781D_REG_TEMP3_HYST, 
     805                      TEMP_ADD_TO_REG(W83781D_INIT_TEMP_HYST)); 
     806  w83781d_write_value(client,W83781D_REG_TEMP3_CONFIG,0x00); 
    689807 
    690808  /* Start monitoring */ 
    691809  w83781d_write_value(client,W83781D_REG_CONFIG, 
    692                    (w83781d_read_value(client,W83781D_REG_CONFIG) & 0xf7) | 0x01); 
    693    
     810                   (w83781d_read_value(client, 
     811                                       W83781D_REG_CONFIG) & 0xf7) | 0x01); 
    694812} 
    695813 
     
    716834      data->fan_min[i-1] = w83781d_read_value(client,W83781D_REG_FAN_MIN(i)); 
    717835    } 
    718     data->temp[0] = w83781d_read_value(client,W83781D_REG_TEMP); 
    719     data->temp_over[0] = w83781d_read_value(client,W83781D_REG_TEMP_OVER); 
    720     data->temp_hyst[0] = w83781d_read_value(client,W83781D_REG_TEMP_HYST); 
    721     w83781d_write_value(client,W83781D_REG_TEMP_SEL,1);/* Switch Banks!! */ 
    722     data->temp[1] = w83781d_read_value(client,W83781D_REG_TEMP23); 
    723     data->temp_over[1] = w83781d_read_value(client,W83781D_REG_TEMP_OVER23); 
    724     data->temp_hyst[1] = w83781d_read_value(client,W83781D_REG_TEMP_HYST23); 
    725     w83781d_write_value(client,W83781D_REG_TEMP_SEL,2);/* Switch Banks!! */ 
    726     data->temp[2] = w83781d_read_value(client,W83781D_REG_TEMP23); 
    727     data->temp_over[2] = w83781d_read_value(client,W83781D_REG_TEMP_OVER23); 
    728     data->temp_hyst[2] = w83781d_read_value(client,W83781D_REG_TEMP_HYST23); 
    729     w83781d_write_value(client,W83781D_REG_TEMP_SEL,0);/* Switch Banks!! */ 
     836    data->temp = w83781d_read_value(client,W83781D_REG_TEMP); 
     837    data->temp_over = w83781d_read_value(client,W83781D_REG_TEMP_OVER); 
     838    data->temp_hyst = w83781d_read_value(client,W83781D_REG_TEMP_HYST); 
     839    data->temp_add[0] = w83781d_read_value(client,W83781D_REG_TEMP2); 
     840    data->temp_add_over[0] = w83781d_read_value(client,W83781D_REG_TEMP2_OVER); 
     841    data->temp_add_hyst[0] = w83781d_read_value(client,W83781D_REG_TEMP2_HYST); 
     842    data->temp_add[1] = w83781d_read_value(client,W83781D_REG_TEMP3); 
     843    data->temp_add_over[1] = w83781d_read_value(client,W83781D_REG_TEMP3_OVER); 
     844    data->temp_add_hyst[1] = w83781d_read_value(client,W83781D_REG_TEMP3_HYST); 
    730845    i = w83781d_read_value(client,W83781D_REG_VID_FANDIV); 
    731846    data->vid = i & 0x0f; 
     
    733848    data->fan_div[0] = (i >> 4) & 0x03; 
    734849    data->fan_div[1] = i >> 6; 
     850    data->fan_div[2] = (w83781d_read_value(client,W83781D_REG_PIN) >> 6) & 0x03; 
    735851    data->alarms = w83781d_read_value(client,W83781D_REG_ALARM1) + 
    736                    (w83781d_read_value(client,W83781D_REG_ALARM2) >> 8); 
    737     data->beep[0] = w83781d_read_value(client,W83781D_REG_BEEP_CONFIG); 
    738     data->beep[1] = w83781d_read_value(client,W83781D_REG_BEEP_INTS1); 
    739     data->beep[2] = w83781d_read_value(client,W83781D_REG_BEEP_INTS2); 
     852                   (w83781d_read_value(client,W83781D_REG_ALARM2) << 8); 
     853    i = w83781d_read_value(client,W83781D_REG_BEEP_INTS2); 
     854    data->beep_enable = i >> 7; 
     855    data->beeps = ((i & 0x7f) << 8) +  
     856                  w83781d_read_value(client,W83781D_REG_BEEP_INTS1); 
    740857    data->last_updated = jiffies; 
    741858    data->valid = 1; 
     
    795912  else if (operation == SENSORS_PROC_REAL_READ) { 
    796913    w83781d_update_client(client); 
    797     results[0] = FAN_FROM_REG(data->fan_min[nr-1]); 
    798     results[1] = FAN_FROM_REG(data->fan[nr-1]); 
     914    results[0] = FAN_FROM_REG(data->fan_min[nr-1],data->fan_div[nr-1]); 
     915    results[1] = FAN_FROM_REG(data->fan[nr-1],data->fan_div[nr-1]); 
    799916    *nrels_mag = 2; 
    800917  } else if (operation == SENSORS_PROC_REAL_WRITE) { 
    801918    if (*nrels_mag >= 1) { 
    802       data->fan_min[nr-1] = FAN_TO_REG(results[0]); 
     919      data->fan_min[nr-1] = FAN_TO_REG(results[0],data->fan_div[nr-1]); 
    803920      w83781d_write_value(client,W83781D_REG_FAN_MIN(nr),data->fan_min[nr-1]); 
    804921    } 
     
    808925 
    809926void w83781d_temp(struct i2c_client *client, int operation, int ctl_name, 
    810                int *nrels_mag, long *results,int tempnum ) 
     927               int *nrels_mag, long *results) 
    811928{ 
    812929  struct w83781d_data *data = client->data; 
     
    815932  else if (operation == SENSORS_PROC_REAL_READ) { 
    816933    w83781d_update_client(client); 
    817     results[0] = TEMP_FROM_REG(data->temp_over[tempnum - 1]); 
    818     results[1] = TEMP_FROM_REG(data->temp_hyst[tempnum - 1]); 
    819     results[2] = TEMP_FROM_REG(data->temp[tempnum - 1]); 
     934    results[0] = TEMP_FROM_REG(data->temp_over); 
     935    results[1] = TEMP_FROM_REG(data->temp_hyst); 
     936    results[2] = TEMP_FROM_REG(data->temp); 
    820937    *nrels_mag = 3; 
    821938  } else if (operation == SENSORS_PROC_REAL_WRITE) { 
    822     if (tempnum == 3) { 
    823      w83781d_write_value(client,W83781D_REG_TEMP_SEL,0x02);/* Switch Banks!! */ 
    824      if (*nrels_mag >= 1) { 
    825        data->temp_over[2] = TEMP_TO_REG(results[0]); 
    826        w83781d_write_value(client,W83781D_REG_TEMP_OVER23,data->temp_over[2]); 
    827        w83781d_write_value(client,W83781D_REG_TEMP_OVER23 + 1,0); 
    828      } 
    829      if (*nrels_mag >= 2) { 
    830        data->temp_hyst[2] = TEMP_TO_REG(results[1]); 
    831        w83781d_write_value(client,W83781D_REG_TEMP_HYST23,data->temp_hyst[2]); 
    832        w83781d_write_value(client,W83781D_REG_TEMP_HYST23 + 1,0); 
    833      } 
    834      w83781d_write_value(client,W83781D_REG_TEMP_SEL,0x0);/* Switch Banks!! */ 
    835     } else if (tempnum == 2) { 
    836      w83781d_write_value(client,W83781D_REG_TEMP_SEL,0x01);/* Switch Banks!! */ 
    837      if (*nrels_mag >= 1) { 
    838        data->temp_over[1] = TEMP_TO_REG(results[0]); 
    839        w83781d_write_value(client,W83781D_REG_TEMP_OVER23,data->temp_over[1]); 
    840        w83781d_write_value(client,W83781D_REG_TEMP_OVER23 + 1,0); 
    841      } 
    842      if (*nrels_mag >= 2) { 
    843        data->temp_hyst[1] = TEMP_TO_REG(results[1]); 
    844        w83781d_write_value(client,W83781D_REG_TEMP_HYST23,data->temp_hyst[1]); 
    845        w83781d_write_value(client,W83781D_REG_TEMP_HYST23 + 1,0); 
    846      } 
    847      w83781d_write_value(client,W83781D_REG_TEMP_SEL,0x0);/* Switch Banks!! */ 
    848     } else { 
    849      if (*nrels_mag >= 1) { 
    850        data->temp_over[0] = TEMP_TO_REG(results[0]); 
    851        w83781d_write_value(client,W83781D_REG_TEMP_OVER,data->temp_over[0]); 
    852      } 
    853      if (*nrels_mag >= 2) { 
    854        data->temp_hyst[0] = TEMP_TO_REG(results[1]); 
    855        w83781d_write_value(client,W83781D_REG_TEMP_HYST,data->temp_hyst[0]); 
    856      } 
    857     } 
    858   } 
    859 } 
    860  
    861  
    862 void w83781d_temp1(struct i2c_client *client, int operation, int ctl_name, 
    863                int *nrels_mag, long *results) { 
    864  
    865   w83781d_temp(client,operation,ctl_name,nrels_mag,results,1); 
    866 } 
    867  
    868  
    869 void w83781d_temp2(struct i2c_client *client, int operation, int ctl_name, 
    870                int *nrels_mag, long *results) { 
    871                 
    872   w83781d_temp(client,operation,ctl_name,nrels_mag,results,2); 
    873 } 
    874  
    875  
    876 void w83781d_temp3(struct i2c_client *client, int operation, int ctl_name, 
    877                int *nrels_mag, long *results) { 
    878                 
    879   w83781d_temp(client,operation,ctl_name,nrels_mag,results,3); 
     939    if (*nrels_mag >= 1) { 
     940      data->temp_over = TEMP_TO_REG(results[0]); 
     941      w83781d_write_value(client,W83781D_REG_TEMP_OVER,data->temp_over); 
     942    } 
     943    if (*nrels_mag >= 2) { 
     944      data->temp_hyst = TEMP_TO_REG(results[1]); 
     945      w83781d_write_value(client,W83781D_REG_TEMP_HYST,data->temp_hyst); 
     946    } 
     947  } 
     948} 
     949 
     950 
     951void w83781d_temp_add(struct i2c_client *client, int operation, int ctl_name, 
     952                      int *nrels_mag, long *results) 
     953{ 
     954  struct w83781d_data *data = client->data; 
     955  int nr = ctl_name - W83781D_SYSCTL_TEMP2; 
     956 
     957  if (operation == SENSORS_PROC_REAL_INFO) 
     958    *nrels_mag = 1; 
     959  else if (operation == SENSORS_PROC_REAL_READ) { 
     960    w83781d_update_client(client); 
     961    results[0] = TEMP_ADD_FROM_REG(data->temp_add_over[nr]); 
     962    results[1] = TEMP_ADD_FROM_REG(data->temp_add_hyst[nr]); 
     963    results[2] = TEMP_ADD_FROM_REG(data->temp_add[nr]); 
     964    *nrels_mag = 3; 
     965  } else if (operation == SENSORS_PROC_REAL_WRITE) { 
     966    if (*nrels_mag >= 1) { 
     967      data->temp_add_over[nr] = TEMP_ADD_TO_REG(results[0]); 
     968      w83781d_write_value(client, 
     969                          nr?W83781D_REG_TEMP3_OVER:W83781D_REG_TEMP2_OVER, 
     970                          data->temp_add_over[nr]); 
     971    } 
     972    if (*nrels_mag >= 2) { 
     973      data->temp_add_hyst[nr] = TEMP_ADD_TO_REG(results[1]); 
     974      w83781d_write_value(client, 
     975                          nr?W83781D_REG_TEMP3_HYST:W83781D_REG_TEMP2_HYST, 
     976                          data->temp_add_hyst[nr]); 
     977    } 
     978  } 
    880979} 
    881980 
     
    9111010{ 
    9121011  struct w83781d_data *data = client->data; 
     1012  int val; 
     1013 
    9131014  if (operation == SENSORS_PROC_REAL_INFO) 
    9141015    *nrels_mag = 0; 
    9151016  else if (operation == SENSORS_PROC_REAL_READ) { 
    9161017    w83781d_update_client(client); 
    917     results[0] = data->beep[0]; 
    918     results[1] = data->beep[1]; 
    919     results[2] = data->beep[2]; 
    920     *nrels_mag = 3; 
     1018    results[0] = BEEP_ENABLE_FROM_REG(data->beep_enable); 
     1019    results[1] = BEEPS_FROM_REG(data->beeps); 
     1020    *nrels_mag = 2; 
    9211021  } else if (operation == SENSORS_PROC_REAL_WRITE) { 
    922     data->beep[0] = results[0]; 
    923     w83781d_write_value(client,W83781D_REG_BEEP_CONFIG,data->beep[0]); 
    924     data->beep[1] = results[1]; 
    925     w83781d_write_value(client,W83781D_REG_BEEP_INTS1,data->beep[1]); 
    926     data->beep[2] = results[2]; 
    927     w83781d_write_value(client,W83781D_REG_BEEP_INTS2,data->beep[2]); 
     1022    if (*nrels_mag >= 2) { 
     1023      data->beeps = BEEPS_TO_REG(results[1]); 
     1024      w83781d_write_value(client,W83781D_REG_BEEP_INTS1,data->beeps & 0xff); 
     1025      val = data->beeps >> 8; 
     1026    } else if (*nrels_mag >= 1) 
     1027      val = w83781d_read_value(client,W83781D_REG_BEEP_INTS1) & 0x7f; 
     1028    if (*nrels_mag >= 1) { 
     1029      data->beep_enable = BEEP_ENABLE_TO_REG(results[0]); 
     1030      w83781d_write_value(client,W83781D_REG_BEEP_INTS2, 
     1031                          val | data->beep_enable << 7); 
     1032    } 
    9281033  } 
    9291034} 
     
    9411046    results[0] = DIV_FROM_REG(data->fan_div[0]); 
    9421047    results[1] = DIV_FROM_REG(data->fan_div[1]); 
    943     results[2] = 2; 
     1048    results[2] = DIV_FROM_REG(data->fan_div[2]); 
    9441049    *nrels_mag = 3; 
    9451050  } else if (operation == SENSORS_PROC_REAL_WRITE) { 
     
    9541059      w83781d_write_value(client,W83781D_REG_VID_FANDIV,old); 
    9551060    } 
     1061    if (*nrels_mag >= 3) { 
     1062      data->fan_div[2] = DIV_TO_REG(results[2]); 
     1063      w83781d_write_value(client,W83781D_REG_PIN, 
     1064                          w83781d_read_value(client,W83781D_REG_PIN)); 
     1065    } 
    9561066  } 
    9571067} 
  • lm-sensors/trunk/kernel/include/sensors.h

    r115 r121  
    145145#define W83781D_SYSCTL_FAN2 1102 
    146146#define W83781D_SYSCTL_FAN3 1103 
    147 #define W83781D_SYSCTL_TEMP 1200 /* Degrees Celcius * 10 */ 
     147#define W83781D_SYSCTL_TEMP1 1200 /* Degrees Celcius * 10 */ 
    148148#define W83781D_SYSCTL_TEMP2 1201 /* Degrees Celcius * 10 */ 
    149149#define W83781D_SYSCTL_TEMP3 1202 /* Degrees Celcius * 10 */ 
     
    163163#define W83781D_ALARM_FAN2 0x0080 
    164164#define W83781D_ALARM_FAN3 0x0800 
    165 #define W83781D_ALARM_TEMP 0x0010 
    166 #define W83781D_ALARM_BTI 0x0020 
     165#define W83781D_ALARM_TEMP1 0x0010 
     166#define W83781D_ALARM_TEMP23 0x0020 
    167167#define W83781D_ALARM_CHAS 0x1000 
    168 #define W83781D_ALARM_FIFO 0x2000 
    169 #define W83781D_ALARM_SMI_IN 0x4000 
    170168 
    171169#define LM75_SYSCTL_TEMP 1200 /* Degrees Celcius * 10 */ 
  • lm-sensors/trunk/prog/sensors/chips.c

    r117 r121  
    509509      !sensors_get_feature(*name,SENSORS_LM80_TEMP_OS_MAX,&max2)) { 
    510510    print_label(label,10); 
    511     printf("%+3.0f C (hot:limit = %+3.0f C,  hysteris = %+3.0f C) %s\n", 
     511    printf("%+3.2f C (hot:limit = %+3.0f C,  hysteris = %+3.0f C) %s\n", 
    512512           cur,max,min, alarms&LM80_ALARM_TEMP_HOT?"ALARM":""); 
    513513    printf("         (os: limit = %+3.0f C,  hysteris = %+3.0f C) %s\n", 
  • lm-sensors/trunk/src/sensors.h

    r115 r121  
    145145#define W83781D_SYSCTL_FAN2 1102 
    146146#define W83781D_SYSCTL_FAN3 1103 
    147 #define W83781D_SYSCTL_TEMP 1200 /* Degrees Celcius * 10 */ 
     147#define W83781D_SYSCTL_TEMP1 1200 /* Degrees Celcius * 10 */ 
    148148#define W83781D_SYSCTL_TEMP2 1201 /* Degrees Celcius * 10 */ 
    149149#define W83781D_SYSCTL_TEMP3 1202 /* Degrees Celcius * 10 */ 
     
    163163#define W83781D_ALARM_FAN2 0x0080 
    164164#define W83781D_ALARM_FAN3 0x0800 
    165 #define W83781D_ALARM_TEMP 0x0010 
    166 #define W83781D_ALARM_BTI 0x0020 
     165#define W83781D_ALARM_TEMP1 0x0010 
     166#define W83781D_ALARM_TEMP23 0x0020 
    167167#define W83781D_ALARM_CHAS 0x1000 
    168 #define W83781D_ALARM_FIFO 0x2000 
    169 #define W83781D_ALARM_SMI_IN 0x4000 
    170168 
    171169#define LM75_SYSCTL_TEMP 1200 /* Degrees Celcius * 10 */ 
  • lm-sensors/trunk/src/w83781d.c

    r96 r121  
    1  
    21/* 
    32    w83781d.c - Part of lm_sensors, Linux kernel modules for hardware 
     
    5352#define W83781D_REG_FAN(nr) (0x27 + (nr)) 
    5453 
    55 #define W83781D_REG_TEMP23 0x50 
    56 #define W83781D_REG_TEMP_HYST23 0x53 
    57 #define W83781D_REG_TEMP_CONFIG23 0x52 
    58 #define W83781D_REG_TEMP_OVER23 0x55 
     54#define W83781D_REG_TEMP2 0x0150 
     55#define W83781D_REG_TEMP3 0x0250 
     56#define W83781D_REG_TEMP2_HYST 0x153 
     57#define W83781D_REG_TEMP3_HYST 0x253 
     58#define W83781D_REG_TEMP2_CONFIG 0x152 
     59#define W83781D_REG_TEMP3_CONFIG 0x252 
     60#define W83781D_REG_TEMP2_OVER 0x155 
     61#define W83781D_REG_TEMP3_OVER 0x255 
     62 
    5963#define W83781D_REG_TEMP 0x27 
    6064#define W83781D_REG_TEMP_OVER 0x39 
    6165#define W83781D_REG_TEMP_HYST 0x3A 
    6266#define W83781D_REG_TEMP_CONFIG 0x52 
    63 #define W83781D_REG_TEMP_SEL 0x4E 
     67#define W83781D_REG_BANK 0x4E 
    6468 
    6569#define W83781D_REG_CONFIG 0x40 
     
    7377#define W83781D_REG_VID_FANDIV 0x47 
    7478 
    75 #define W83781D_REG_CHIPID 0x58 
     79#define W83781D_REG_CHIPID 0x49 
     80#define W83781D_REG_WCHIPID 0x58 
    7681#define W83781D_REG_CHIPMAN 0x4F 
     82#define W83781D_REG_PIN 0x4B 
    7783 
    7884 
    7985/* Conversions. Rounding is only done on the TO_REG variants. */ 
    80 static int w83781d_in_conv[7] = {10000, 10000, 10000, 16892, 38000,  
    81                               -34768, -15050 }; 
    82 #define IN_TO_REG(val,nr) (((((val) * 100000 / w83781d_in_conv[nr]) + 8) / 16) \ 
    83                            & 0xff) 
    84 #define IN_FROM_REG(val,nr) (((val) *  16 * w83781d_in_conv[nr]) / 100000) 
    85  
    86 #define FAN_TO_REG(val) ((val)==0?255:((1350000+(val))/((val)*2)) & 0xff) 
    87 #define FAN_FROM_REG(val) ((val)==0?-1:(val)==255?0:1350000/((val)*2)) 
     86#define IN_TO_REG(val,nr) (((val) * 10 + 8)/16) 
     87#define IN_FROM_REG(val,nr) (((val) * 16) / 10) 
     88 
     89#define FAN_TO_REG(val,div) ((val)==0?255:((1350000+(val))/\ 
     90                            ((val)*2*(div))) & 0xff) 
     91#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*2*(div))) 
    8892 
    8993#define TEMP_TO_REG(val) (((val)<0?(((val)-5)/10)&0xff:((val)+5)/10) & 0xff) 
    9094#define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*10) 
     95 
     96#define TEMP_ADD_TO_REG(val)   (((((val) + 2) / 5) << 7) & 0xff80) 
     97#define TEMP_ADD_FROM_REG(val) (((val) >> 7) * 5) 
    9198 
    9299#define VID_FROM_REG(val) ((val)==0x1f?0:(val)>=0x10?510-(val)*10:\ 
    93100                           (val)>=0x06?0:205-(val)*5) 
    94101#define ALARMS_FROM_REG(val) (val) 
     102#define BEEPS_FROM_REG(val) (val) 
     103#define BEEPS_TO_REG(val) ((val) & 0xffff) 
     104 
     105#define BEEP_ENABLE_TO_REG(val) (val) 
     106#define BEEP_ENABLE_FROM_REG(val) ((val)?1:0) 
    95107 
    96108#define DIV_FROM_REG(val) (1 << (val)) 
     
    101113#define W83781D_INIT_IN_1 (vid==350?280:vid) 
    102114#define W83781D_INIT_IN_2 330 
    103 #define W83781D_INIT_IN_3 500 
    104 #define W83781D_INIT_IN_4 1200 
    105 #define W83781D_INIT_IN_5 -1200 
    106 #define W83781D_INIT_IN_6 -500 
     115#define W83781D_INIT_IN_3 (((500)   * 100)/168) 
     116#define W83781D_INIT_IN_4 (((1200)  * 10)/38) 
     117#define W83781D_INIT_IN_5 (((-1200) * -604)/2100) 
     118#define W83781D_INIT_IN_6 (((-500)  * -604)/909) 
    107119 
    108120#define W83781D_INIT_IN_PERCENTAGE 10 
    109121 
    110122#define W83781D_INIT_IN_MIN_0 \ 
    111         (W83781D_INIT_IN_0 - W83781D_INIT_IN_0 * W83781D_INIT_IN_PERCENTAGE / 100)  
     123        (W83781D_INIT_IN_0 - W83781D_INIT_IN_0 * W83781D_INIT_IN_PERCENTAGE \ 
     124         / 100)  
    112125#define W83781D_INIT_IN_MAX_0 \ 
    113         (W83781D_INIT_IN_0 + W83781D_INIT_IN_0 * W83781D_INIT_IN_PERCENTAGE / 100)  
     126        (W83781D_INIT_IN_0 + W83781D_INIT_IN_0 * W83781D_INIT_IN_PERCENTAGE \ 
     127         / 100)  
    114128#define W83781D_INIT_IN_MIN_1 \ 
    115         (W83781D_INIT_IN_1 - W83781D_INIT_IN_1 * W83781D_INIT_IN_PERCENTAGE / 100)  
     129        (W83781D_INIT_IN_1 - W83781D_INIT_IN_1 * W83781D_INIT_IN_PERCENTAGE \ 
     130         / 100)  
    116131#define W83781D_INIT_IN_MAX_1 \ 
    117         (W83781D_INIT_IN_1 + W83781D_INIT_IN_1 * W83781D_INIT_IN_PERCENTAGE / 100)  
     132        (W83781D_INIT_IN_1 + W83781D_INIT_IN_1 * W83781D_INIT_IN_PERCENTAGE \ 
     133         / 100)  
    118134#define W83781D_INIT_IN_MIN_2 \ 
    119         (W83781D_INIT_IN_2 - W83781D_INIT_IN_2 * W83781D_INIT_IN_PERCENTAGE / 100)  
     135        (W83781D_INIT_IN_2 - W83781D_INIT_IN_2 * W83781D_INIT_IN_PERCENTAGE \ 
     136         / 100)  
    120137#define W83781D_INIT_IN_MAX_2 \ 
    121         (W83781D_INIT_IN_2 + W83781D_INIT_IN_2 * W83781D_INIT_IN_PERCENTAGE / 100)  
     138        (W83781D_INIT_IN_2 + W83781D_INIT_IN_2 * W83781D_INIT_IN_PERCENTAGE \ 
     139         / 100)  
    122140#define W83781D_INIT_IN_MIN_3 \ 
    123         (W83781D_INIT_IN_3 - W83781D_INIT_IN_3 * W83781D_INIT_IN_PERCENTAGE / 100)  
     141        (W83781D_INIT_IN_3 - W83781D_INIT_IN_3 * W83781D_INIT_IN_PERCENTAGE \ 
     142         / 100)  
    124143#define W83781D_INIT_IN_MAX_3 \ 
    125         (W83781D_INIT_IN_3 + W83781D_INIT_IN_3 * W83781D_INIT_IN_PERCENTAGE / 100)  
     144        (W83781D_INIT_IN_3 + W83781D_INIT_IN_3 * W83781D_INIT_IN_PERCENTAGE \ 
     145         / 100)  
    126146#define W83781D_INIT_IN_MIN_4 \ 
    127         (W83781D_INIT_IN_4 - W83781D_INIT_IN_4 * W83781D_INIT_IN_PERCENTAGE / 100)  
     147        (W83781D_INIT_IN_4 - W83781D_INIT_IN_4 * W83781D_INIT_IN_PERCENTAGE \ 
     148         / 100)  
    128149#define W83781D_INIT_IN_MAX_4 \ 
    129         (W83781D_INIT_IN_4 + W83781D_INIT_IN_4 * W83781D_INIT_IN_PERCENTAGE / 100)  
     150        (W83781D_INIT_IN_4 + W83781D_INIT_IN_4 * W83781D_INIT_IN_PERCENTAGE \ 
     151         / 100)  
    130152#define W83781D_INIT_IN_MIN_5 \ 
    131         (W83781D_INIT_IN_5 - W83781D_INIT_IN_5 * W83781D_INIT_IN_PERCENTAGE / 100)  
     153        (W83781D_INIT_IN_5 - W83781D_INIT_IN_5 * W83781D_INIT_IN_PERCENTAGE \ 
     154         / 100)  
    132155#define W83781D_INIT_IN_MAX_5 \ 
    133         (W83781D_INIT_IN_5 + W83781D_INIT_IN_5 * W83781D_INIT_IN_PERCENTAGE / 100)  
     156        (W83781D_INIT_IN_5 + W83781D_INIT_IN_5 * W83781D_INIT_IN_PERCENTAGE \ 
     157         / 100)  
    134158#define W83781D_INIT_IN_MIN_6 \ 
    135         (W83781D_INIT_IN_6 - W83781D_INIT_IN_6 * W83781D_INIT_IN_PERCENTAGE / 100)  
     159        (W83781D_INIT_IN_6 - W83781D_INIT_IN_6 * W83781D_INIT_IN_PERCENTAGE \ 
     160         / 100)  
    136161#define W83781D_INIT_IN_MAX_6 \ 
    137         (W83781D_INIT_IN_6 + W83781D_INIT_IN_6 * W83781D_INIT_IN_PERCENTAGE / 100)  
     162        (W83781D_INIT_IN_6 + W83781D_INIT_IN_6 * W83781D_INIT_IN_PERCENTAGE \ 
     163         / 100)  
    138164 
    139165#define W83781D_INIT_FAN_MIN_1 3000 
     
    181207         u8 fan[3];                  /* Register value */ 
    182208         u8 fan_min[3];              /* Register value */ 
    183          u8 temp[3];                    /* Register value */ 
    184          u8 temp_over[3];               /* Register value */ 
    185          u8 temp_hyst[3];               /* Register value */ 
    186          u8 fan_div[2];              /* Register encoding, shifted right */ 
     209         u8 temp; 
     210         u8 temp_over;               /* Register value */ 
     211         u8 temp_hyst;               /* Register value */ 
     212         u8 temp_add[2];             /* Register value */ 
     213         u16 temp_add_over[2];       /* Register value */ 
     214         u16 temp_add_hyst[2];       /* Register value */ 
     215         u8 fan_div[3];              /* Register encoding, shifted right */ 
    187216         u8 vid;                     /* Register encoding, combined */ 
    188217         u16 alarms;                 /* Register encoding, combined */ 
    189          u8 beep[3];                    /* Register value of config and interrupt masks */ 
     218         u16 beeps;                  /* Register encoding, combined */ 
     219         u8 beep_enable;             /* Boolean */ 
    190220}; 
    191221 
     
    208238static void w83781d_dec_use (struct i2c_client *client); 
    209239 
    210 static int w83781d_read_value(struct i2c_client *client, u8 register); 
    211 static int w83781d_write_value(struct i2c_client *client, u8 register, u8 value); 
     240static int w83781d_read_value(struct i2c_client *client, u16 register); 
     241static int w83781d_write_value(struct i2c_client *client, u16 register,  
     242                               u16 value); 
    212243static void w83781d_update_client(struct i2c_client *client); 
    213244static void w83781d_init_client(struct i2c_client *client); 
     
    218249static void w83781d_fan(struct i2c_client *client, int operation, int ctl_name, 
    219250                     int *nrels_mag, long *results); 
    220 static void w83781d_temp(struct i2c_client *client, int operation, int ctl_name, 
    221                       int *nrels_mag, long *results,int tempnum); 
    222 static void w83781d_temp1(struct i2c_client *client, int operation, int ctl_name, 
    223                       int *nrels_mag, long *results); 
    224 static void w83781d_temp2(struct i2c_client *client, int operation, int ctl_name, 
    225                       int *nrels_mag, long *results); 
    226 static void w83781d_temp3(struct i2c_client *client, int operation, int ctl_name, 
    227                       int *nrels_mag, long *results); 
     251static void w83781d_temp(struct i2c_client *client, int operation,  
     252                          int ctl_name, int *nrels_mag, long *results); 
     253static void w83781d_temp_add(struct i2c_client *client, int operation,  
     254                          int ctl_name, int *nrels_mag, long *results); 
    228255static void w83781d_vid(struct i2c_client *client, int operation, int ctl_name, 
    229                      int *nrels_mag, long *results); 
    230 static void w83781d_alarms(struct i2c_client *client, int operation, int ctl_name, 
    231                         int *nrels_mag, long *results); 
     256                         int *nrels_mag, long *results); 
     257static void w83781d_alarms(struct i2c_client *client, int operation, 
     258                           int ctl_name, int *nrels_mag, long *results); 
    232259static void w83781d_beep(struct i2c_client *client, int operation, int ctl_name, 
    233260                      int *nrels_mag, long *results); 
    234 static void w83781d_fan_div(struct i2c_client *client, int operation, int ctl_name, 
    235                          int *nrels_mag, long *results); 
     261static void w83781d_fan_div(struct i2c_client *client, int operation, 
     262                            int ctl_name, int *nrels_mag, long *results); 
    236263 
    237264/* I choose here for semi-static W83781D allocation. Complete dynamic 
     
    284311  { W83781D_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &sensors_proc_real, 
    285312    &sensors_sysctl_real, NULL, &w83781d_fan }, 
    286   { W83781D_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &sensors_proc_real, 
    287     &sensors_sysctl_real, NULL, &w83781d_temp1 }, 
     313  { W83781D_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL, &sensors_proc_real, 
     314    &sensors_sysctl_real, NULL, &w83781d_temp }, 
    288315  { W83781D_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL, &sensors_proc_real, 
    289     &sensors_sysctl_real, NULL, &w83781d_temp2 }, 
     316    &sensors_sysctl_real, NULL, &w83781d_temp_add }, 
    290317  { W83781D_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL, &sensors_proc_real, 
    291     &sensors_sysctl_real, NULL, &w83781d_temp3 }, 
     318    &sensors_sysctl_real, NULL, &w83781d_temp_add }, 
    292319  { W83781D_SYSCTL_VID, "vid", NULL, 0, 0644, NULL, &sensors_proc_real, 
    293320    &sensors_sysctl_real, NULL, &w83781d_vid }, 
     
    355382    /* Real detection code goes here */ 
    356383 
    357     outb_p(W83781D_REG_CHIPID,address + W83781D_ADDR_REG_OFFSET); 
     384    /* The Winbond may be stuck in bank 1 or 2. This should reset it.  
     385       We really need some nifty detection code, because this can lead 
     386       to a lot of problems if there is no Winbond present! */ 
     387    outb_p(W83781D_REG_BANK,address + W83781D_ADDR_REG_OFFSET); 
     388    outb_p(0x00,address + W83781D_DATA_REG_OFFSET); 
     389 
     390    outb_p(W83781D_REG_WCHIPID,address + W83781D_ADDR_REG_OFFSET); 
    358391    err = inb_p(address + W83781D_DATA_REG_OFFSET) & 0xfe; 
    359392 
     
    461494      continue; 
    462495 
    463     err = smbus_read_byte_data(adapter,address,W83781D_REG_CHIPID); 
     496    smbus_write_byte_data(adapter,address,W83781D_REG_BANK,0x00); 
     497 
     498    err = smbus_read_byte_data(adapter,address,W83781D_REG_WCHIPID); 
    464499     
    465500    if (err == 0x20) { 
     
    600635  
    601636 
    602 /* The SMBus locks itself, but ISA access must be locked explicitely!  
     637/* The SMBus locks itself, usually, but nothing may access the Winbond between 
     638   bank switches. ISA access must always be locked explicitely!  
    603639   We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks, 
    604640   would slow down the W83781D access and should not be necessary.  
    605641   There are some ugly typecasts here, but the good new is - they should 
    606642   nowhere else be necessary! */ 
    607 int w83781d_read_value(struct i2c_client *client, u8 reg) 
    608 { 
    609   int res; 
     643int w83781d_read_value(struct i2c_client *client, u16 reg) 
     644{ 
     645  int res,word_sized; 
     646 
     647  word_sized = (reg & 0x0ff) && (((reg && 0x00ff) == 0x50) ||  
     648                                 ((reg && 0x00ff) == 0x53) ||  
     649                                 ((reg && 0x00ff) == 0x55)); 
     650  down((struct semaphore *) (client->data)); 
    610651  if (i2c_is_isa_client(client)) { 
    611     down((struct semaphore *) (client->data)); 
    612     outb_p(reg,(((struct isa_client *) client)->isa_addr) +  
    613                W83781D_ADDR_REG_OFFSET); 
    614     res = inb_p((((struct isa_client *) client)->isa_addr) +  
     652    if (reg & 0xff00) { 
     653      outb_p(W83781D_REG_BANK,(((struct isa_client *) client)->isa_addr) + 
     654                              W83781D_ADDR_REG_OFFSET); 
     655      outb_p(reg >> 8,(((struct isa_client *) client)->isa_addr) + 
     656                      W83781D_DATA_REG_OFFSET); 
     657    } 
     658    outb_p(reg & 0xff,(((struct isa_client *) client)->isa_addr) + 
     659                      W83781D_ADDR_REG_OFFSET); 
     660    res = inb_p((((struct isa_client *) client)->isa_addr) + 
    615661                W83781D_DATA_REG_OFFSET); 
    616     up((struct semaphore *) (client->data)); 
    617     return res; 
    618   } else 
    619     return smbus_read_byte_data(client->adapter,client->addr, reg); 
    620 } 
    621  
    622 /* The SMBus locks itself, but ISA access muse be locked explicitely!  
     662    if (word_sized) { 
     663      outb_p((reg & 0xff)+1,(((struct isa_client *) client)->isa_addr) + 
     664                        W83781D_ADDR_REG_OFFSET); 
     665      res = (res << 8) + inb_p((((struct isa_client *) client)->isa_addr) + 
     666                         W83781D_DATA_REG_OFFSET); 
     667    } 
     668    if (reg & 0xff00) { 
     669      outb_p(W83781D_REG_BANK,(((struct isa_client *) client)->isa_addr) + 
     670                              W83781D_ADDR_REG_OFFSET); 
     671      outb_p(0,(((struct isa_client *) client)->isa_addr) + 
     672               W83781D_DATA_REG_OFFSET); 
     673    } 
     674  } else { 
     675    if (reg & 0xff00) 
     676      smbus_write_byte_data(client->adapter,client->addr,W83781D_REG_BANK, 
     677                            reg >> 8); 
     678    res = smbus_read_byte_data(client->adapter,client->addr, reg); 
     679    if (word_sized) 
     680      res = (res << 8) + smbus_read_byte_data(client->adapter,client->addr,  
     681                                              reg); 
     682    if (reg & 0xff00) 
     683      smbus_write_byte_data(client->adapter,client->addr,W83781D_REG_BANK,0); 
     684  } 
     685  up((struct semaphore *) (client->data)); 
     686  return res; 
     687} 
     688 
     689/* The SMBus locks itself, usually, but nothing may access the Winbond between 
     690   bank switches. ISA access must always be locked explicitely!  
    623691   We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks, 
    624692   would slow down the W83781D access and should not be necessary.  
    625693   There are some ugly typecasts here, but the good new is - they should 
    626694   nowhere else be necessary! */ 
    627 int w83781d_write_value(struct i2c_client *client, u8 reg, u8 value) 
    628 { 
     695int w83781d_write_value(struct i2c_client *client, u16 reg, u16 value) 
     696{ 
     697  int word_sized; 
     698 
     699  word_sized = (reg & 0x0ff) && (((reg && 0x00ff) == 0x50) ||  
     700                                 ((reg && 0x00ff) == 0x53) ||  
     701                                 ((reg && 0x00ff) == 0x55)); 
     702  down((struct semaphore *) (client->data)); 
    629703  if (i2c_is_isa_client(client)) { 
    630     down((struct semaphore *) (client->data)); 
    631     outb_p(reg,((struct isa_client *) client)->isa_addr + W83781D_ADDR_REG_OFFSET); 
    632     outb_p(value,((struct isa_client *) client)->isa_addr + W83781D_DATA_REG_OFFSET); 
    633     up((struct semaphore *) (client->data)); 
    634     return 0; 
    635   } else 
    636     return smbus_write_byte_data(client->adapter, client->addr, reg,value); 
     704    if (reg & 0xff00) { 
     705      outb_p(W83781D_REG_BANK,(((struct isa_client *) client)->isa_addr) + 
     706                              W83781D_ADDR_REG_OFFSET); 
     707      outb_p(reg >> 8,(((struct isa_client *) client)->isa_addr) + 
     708                      W83781D_DATA_REG_OFFSET); 
     709    } 
     710    outb_p(reg & 0xff,(((struct isa_client *) client)->isa_addr) + 
     711                      W83781D_ADDR_REG_OFFSET); 
     712    if (word_sized) { 
     713      outb_p(value >> 8,(((struct isa_client *) client)->isa_addr) + 
     714                        W83781D_DATA_REG_OFFSET); 
     715      outb_p((reg & 0xff)+1,(((struct isa_client *) client)->isa_addr) + 
     716                        W83781D_ADDR_REG_OFFSET); 
     717    } 
     718    outb_p(value &0xff,(((struct isa_client *) client)->isa_addr) + 
     719                       W83781D_DATA_REG_OFFSET); 
     720    if (reg & 0xff00) { 
     721      outb_p(W83781D_REG_BANK,(((struct isa_client *) client)->isa_addr) + 
     722                              W83781D_ADDR_REG_OFFSET); 
     723      outb_p(0,(((struct isa_client *) client)->isa_addr) + 
     724               W83781D_DATA_REG_OFFSET); 
     725    } 
     726  } else { 
     727    if (reg & 0xff00) 
     728      smbus_write_byte_data(client->adapter,client->addr,W83781D_REG_BANK, 
     729                            reg >> 8); 
     730    if (word_sized) { 
     731       smbus_write_byte_data(client->adapter,client->addr, reg, value >> 8); 
     732       smbus_write_byte_data(client->adapter,client->addr, reg+1, value &0xff); 
     733    } else 
     734      smbus_write_byte_data(client->adapter,client->addr, reg, value &0xff); 
     735    if (reg & 0xff00) 
     736      smbus_write_byte_data(client->adapter,client->addr,W83781D_REG_BANK,0); 
     737  } 
     738  up((struct semaphore *) (client->data)); 
     739  return 0; 
    637740} 
    638741 
     
    650753  vid = VID_FROM_REG(vid); 
    651754 
    652   w83781d_write_value(client,W83781D_REG_IN_MIN(0),IN_TO_REG(W83781D_INIT_IN_MIN_0,0)); 
    653   w83781d_write_value(client,W83781D_REG_IN_MAX(0),IN_TO_REG(W83781D_INIT_IN_MAX_0,0)); 
    654   w83781d_write_value(client,W83781D_REG_IN_MIN(1),IN_TO_REG(W83781D_INIT_IN_MIN_1,1)); 
    655   w83781d_write_value(client,W83781D_REG_IN_MAX(1),IN_TO_REG(W83781D_INIT_IN_MAX_1,1)); 
    656   w83781d_write_value(client,W83781D_REG_IN_MIN(2),IN_TO_REG(W83781D_INIT_IN_MIN_2,2)); 
    657   w83781d_write_value(client,W83781D_REG_IN_MAX(2),IN_TO_REG(W83781D_INIT_IN_MAX_2,2)); 
    658   w83781d_write_value(client,W83781D_REG_IN_MIN(3),IN_TO_REG(W83781D_INIT_IN_MIN_3,3)); 
    659   w83781d_write_value(client,W83781D_REG_IN_MAX(3),IN_TO_REG(W83781D_INIT_IN_MAX_3,3)); 
    660   w83781d_write_value(client,W83781D_REG_IN_MIN(4),IN_TO_REG(W83781D_INIT_IN_MIN_4,4)); 
    661   w83781d_write_value(client,W83781D_REG_IN_MAX(4),IN_TO_REG(W83781D_INIT_IN_MAX_4,4)); 
    662   w83781d_write_value(client,W83781D_REG_IN_MIN(5),IN_TO_REG(W83781D_INIT_IN_MIN_5,5)); 
    663   w83781d_write_value(client,W83781D_REG_IN_MAX(5),IN_TO_REG(W83781D_INIT_IN_MAX_5,5)); 
    664   w83781d_write_value(client,W83781D_REG_IN_MIN(6),IN_TO_REG(W83781D_INIT_IN_MIN_6,6)); 
    665   w83781d_write_value(client,W83781D_REG_IN_MAX(6),IN_TO_REG(W83781D_INIT_IN_MAX_6,6)); 
    666   w83781d_write_value(client,W83781D_REG_FAN_MIN(1),FAN_TO_REG(W83781D_INIT_FAN_MIN_1)); 
    667   w83781d_write_value(client,W83781D_REG_FAN_MIN(2),FAN_TO_REG(W83781D_INIT_FAN_MIN_2)); 
    668   w83781d_write_value(client,W83781D_REG_FAN_MIN(3),FAN_TO_REG(W83781D_INIT_FAN_MIN_3)); 
    669   /* Init Temp Sensor1 */ 
    670   w83781d_write_value(client,W83781D_REG_TEMP_SEL,0x00);/* Switch Banks! */ 
    671   w83781d_write_value(client,W83781D_REG_TEMP_OVER,TEMP_TO_REG(W83781D_INIT_TEMP_OVER)); 
    672   w83781d_write_value(client,W83781D_REG_TEMP_HYST,TEMP_TO_REG(W83781D_INIT_TEMP_HYST)); 
     755  w83781d_write_value(client,W83781D_REG_IN_MIN(0), 
     756                      IN_TO_REG(W83781D_INIT_IN_MIN_0,0)); 
     757  w83781d_write_value(client,W83781D_REG_IN_MAX(0), 
     758                      IN_TO_REG(W83781D_INIT_IN_MAX_0,0)); 
     759  w83781d_write_value(client,W83781D_REG_IN_MIN(1), 
     760                      IN_TO_REG(W83781D_INIT_IN_MIN_1,1)); 
     761  w83781d_write_value(client,W83781D_REG_IN_MAX(1), 
     762                      IN_TO_REG(W83781D_INIT_IN_MAX_1,1)); 
     763  w83781d_write_value(client,W83781D_REG_IN_MIN(2), 
     764                      IN_TO_REG(W83781D_INIT_IN_MIN_2,2)); 
     765  w83781d_write_value(client,W83781D_REG_IN_MAX(2), 
     766                      IN_TO_REG(W83781D_INIT_IN_MAX_2,2)); 
     767  w83781d_write_value(client,W83781D_REG_IN_MIN(3), 
     768                      IN_TO_REG(W83781D_INIT_IN_MIN_3,3)); 
     769  w83781d_write_value(client,W83781D_REG_IN_MAX(3), 
     770                      IN_TO_REG(W83781D_INIT_IN_MAX_3,3)); 
     771  w83781d_write_value(client,W83781D_REG_IN_MIN(4), 
     772                      IN_TO_REG(W83781D_INIT_IN_MIN_4,4)); 
     773  w83781d_write_value(client,W83781D_REG_IN_MAX(4), 
     774                      IN_TO_REG(W83781D_INIT_IN_MAX_4,4)); 
     775  w83781d_write_value(client,W83781D_REG_IN_MIN(5), 
     776                      IN_TO_REG(W83781D_INIT_IN_MIN_5,5)); 
     777  w83781d_write_value(client,W83781D_REG_IN_MAX(5), 
     778                      IN_TO_REG(W83781D_INIT_IN_MAX_5,5)); 
     779  w83781d_write_value(client,W83781D_REG_IN_MIN(6), 
     780                      IN_TO_REG(W83781D_INIT_IN_MIN_6,6)); 
     781  w83781d_write_value(client,W83781D_REG_IN_MAX(6), 
     782                      IN_TO_REG(W83781D_INIT_IN_MAX_6,6)); 
     783  w83781d_write_value(client,W83781D_REG_FAN_MIN(1), 
     784                      FAN_TO_REG(W83781D_INIT_FAN_MIN_1,2)); 
     785  w83781d_write_value(client,W83781D_REG_FAN_MIN(2), 
     786                      FAN_TO_REG(W83781D_INIT_FAN_MIN_2,2)); 
     787  w83781d_write_value(client,W83781D_REG_FAN_MIN(3), 
     788                      FAN_TO_REG(W83781D_INIT_FAN_MIN_3,2)); 
     789 
     790  w83781d_write_value(client,W83781D_REG_TEMP_OVER, 
     791                      TEMP_TO_REG(W83781D_INIT_TEMP_OVER)); 
     792  w83781d_write_value(client,W83781D_REG_TEMP_HYST, 
     793                      TEMP_TO_REG(W83781D_INIT_TEMP_HYST)); 
    673794  w83781d_write_value(client,W83781D_REG_TEMP_CONFIG,0x00); 
    674   /* Init Temp Sensor2 */ 
    675   w83781d_write_value(client,W83781D_REG_TEMP_SEL,0x01);/* Switch Banks! */ 
    676   w83781d_write_value(client,W83781D_REG_TEMP_OVER23,TEMP_TO_REG(W83781D_INIT_TEMP_OVER)); 
    677   w83781d_write_value(client,W83781D_REG_TEMP_OVER23 + 1,0); 
    678   w83781d_write_value(client,W83781D_REG_TEMP_HYST23,TEMP_TO_REG(W83781D_INIT_TEMP_HYST)); 
    679   w83781d_write_value(client,W83781D_REG_TEMP_HYST23 + 1,0); 
    680   w83781d_write_value(client,W83781D_REG_TEMP_CONFIG23,0x00); 
    681   /* Init Temp Sensor3 */ 
    682   w83781d_write_value(client,W83781D_REG_TEMP_SEL,0x02);/* Switch Banks! */ 
    683   w83781d_write_value(client,W83781D_REG_TEMP_OVER23,TEMP_TO_REG(W83781D_INIT_TEMP_OVER)); 
    684   w83781d_write_value(client,W83781D_REG_TEMP_OVER23 + 1,0); 
    685   w83781d_write_value(client,W83781D_REG_TEMP_HYST23,TEMP_TO_REG(W83781D_INIT_TEMP_HYST)); 
    686   w83781d_write_value(client,W83781D_REG_TEMP_HYST23 + 1,0); 
    687   w83781d_write_value(client,W83781D_REG_TEMP_CONFIG23,0x00); 
    688   w83781d_write_value(client,W83781D_REG_TEMP_SEL,0x00);/* Switch Banks! */ 
     795 
     796  w83781d_write_value(client,W83781D_REG_TEMP2_OVER, 
     797                      TEMP_ADD_TO_REG(W83781D_INIT_TEMP_OVER)); 
     798  w83781d_write_value(client,W83781D_REG_TEMP2_HYST, 
     799                      TEMP_ADD_TO_REG(W83781D_INIT_TEMP_HYST)); 
     800  w83781d_write_value(client,W83781D_REG_TEMP2_CONFIG,0x00); 
     801 
     802  w83781d_write_value(client,W83781D_REG_TEMP3_OVER, 
     803                      TEMP_ADD_TO_REG(W83781D_INIT_TEMP_OVER)); 
     804  w83781d_write_value(client,W83781D_REG_TEMP3_HYST, 
     805                      TEMP_ADD_TO_REG(W83781D_INIT_TEMP_HYST)); 
     806  w83781d_write_value(client,W83781D_REG_TEMP3_CONFIG,0x00); 
    689807 
    690808  /* Start monitoring */ 
    691809  w83781d_write_value(client,W83781D_REG_CONFIG, 
    692                    (w83781d_read_value(client,W83781D_REG_CONFIG) & 0xf7) | 0x01); 
    693    
     810                   (w83781d_read_value(client, 
     811                                       W83781D_REG_CONFIG) & 0xf7) | 0x01); 
    694812} 
    695813 
     
    716834      data->fan_min[i-1] = w83781d_read_value(client,W83781D_REG_FAN_MIN(i)); 
    717835    } 
    718     data->temp[0] = w83781d_read_value(client,W83781D_REG_TEMP); 
    719     data->temp_over[0] = w83781d_read_value(client,W83781D_REG_TEMP_OVER); 
    720     data->temp_hyst[0] = w83781d_read_value(client,W83781D_REG_TEMP_HYST); 
    721     w83781d_write_value(client,W83781D_REG_TEMP_SEL,1);/* Switch Banks!! */ 
    722     data->temp[1] = w83781d_read_value(client,W83781D_REG_TEMP23); 
    723     data->temp_over[1] = w83781d_read_value(client,W83781D_REG_TEMP_OVER23); 
    724     data->temp_hyst[1] = w83781d_read_value(client,W83781D_REG_TEMP_HYST23); 
    725     w83781d_write_value(client,W83781D_REG_TEMP_SEL,2);/* Switch Banks!! */ 
    726     data->temp[2] = w83781d_read_value(client,W83781D_REG_TEMP23); 
    727     data->temp_over[2] = w83781d_read_value(client,W83781D_REG_TEMP_OVER23); 
    728     data->temp_hyst[2] = w83781d_read_value(client,W83781D_REG_TEMP_HYST23); 
    729     w83781d_write_value(client,W83781D_REG_TEMP_SEL,0);/* Switch Banks!! */ 
     836    data->temp = w83781d_read_value(client,W83781D_REG_TEMP); 
     837    data->temp_over = w83781d_read_value(client,W83781D_REG_TEMP_OVER); 
     838    data->temp_hyst = w83781d_read_value(client,W83781D_REG_TEMP_HYST); 
     839    data->temp_add[0] = w83781d_read_value(client,W83781D_REG_TEMP2); 
     840    data->temp_add_over[0] = w83781d_read_value(client,W83781D_REG_TEMP2_OVER); 
     841    data->temp_add_hyst[0] = w83781d_read_value(client,W83781D_REG_TEMP2_HYST); 
     842    data->temp_add[1] = w83781d_read_value(client,W83781D_REG_TEMP3); 
     843    data->temp_add_over[1] = w83781d_read_value(client,W83781D_REG_TEMP3_OVER); 
     844    data->temp_add_hyst[1] = w83781d_read_value(client,W83781D_REG_TEMP3_HYST); 
    730845    i = w83781d_read_value(client,W83781D_REG_VID_FANDIV); 
    731846    data->vid = i & 0x0f; 
     
    733848    data->fan_div[0] = (i >> 4) & 0x03; 
    734849    data->fan_div[1] = i >> 6; 
     850    data->fan_div[2] = (w83781d_read_value(client,W83781D_REG_PIN) >> 6) & 0x03; 
    735851    data->alarms = w83781d_read_value(client,W83781D_REG_ALARM1) + 
    736                    (w83781d_read_value(client,W83781D_REG_ALARM2) >> 8); 
    737     data->beep[0] = w83781d_read_value(client,W83781D_REG_BEEP_CONFIG); 
    738     data->beep[1] = w83781d_read_value(client,W83781D_REG_BEEP_INTS1); 
    739     data->beep[2] = w83781d_read_value(client,W83781D_REG_BEEP_INTS2); 
     852                   (w83781d_read_value(client,W83781D_REG_ALARM2) << 8); 
     853    i = w83781d_read_value(client,W83781D_REG_BEEP_INTS2); 
     854    data->beep_enable = i >> 7; 
     855    data->beeps = ((i & 0x7f) << 8) +  
     856                  w83781d_read_value(client,W83781D_REG_BEEP_INTS1); 
    740857    data->last_updated = jiffies; 
    741858    data->valid = 1; 
     
    795912  else if (operation == SENSORS_PROC_REAL_READ) { 
    796913    w83781d_update_client(client); 
    797     results[0] = FAN_FROM_REG(data->fan_min[nr-1]); 
    798     results[1] = FAN_FROM_REG(data->fan[nr-1]); 
     914    results[0] = FAN_FROM_REG(data->fan_min[nr-1],data->fan_div[nr-1]); 
     915    results[1] = FAN_FROM_REG(data->fan[nr-1],data->fan_div[nr-1]); 
    799916    *nrels_mag = 2; 
    800917  } else if (operation == SENSORS_PROC_REAL_WRITE) { 
    801918    if (*nrels_mag >= 1) { 
    802       data->fan_min[nr-1] = FAN_TO_REG(results[0]); 
     919      data->fan_min[nr-1] = FAN_TO_REG(results[0],data->fan_div[nr-1]); 
    803920      w83781d_write_value(client,W83781D_REG_FAN_MIN(nr),data->fan_min[nr-1]); 
    804921    } 
     
    808925 
    809926void w83781d_temp(struct i2c_client *client, int operation, int ctl_name, 
    810                int *nrels_mag, long *results,int tempnum ) 
     927               int *nrels_mag, long *results) 
    811928{ 
    812929  struct w83781d_data *data = client->data; 
     
    815932  else if (operation == SENSORS_PROC_REAL_READ) { 
    816933    w83781d_update_client(client); 
    817     results[0] = TEMP_FROM_REG(data->temp_over[tempnum - 1]); 
    818     results[1] = TEMP_FROM_REG(data->temp_hyst[tempnum - 1]); 
    819     results[2] = TEMP_FROM_REG(data->temp[tempnum - 1]); 
     934    results[0] = TEMP_FROM_REG(data->temp_over); 
     935    results[1] = TEMP_FROM_REG(data->temp_hyst); 
     936    results[2] = TEMP_FROM_REG(data->temp); 
    820937    *nrels_mag = 3; 
    821938  } else if (operation == SENSORS_PROC_REAL_WRITE) { 
    822     if (tempnum == 3) { 
    823      w83781d_write_value(client,W83781D_REG_TEMP_SEL,0x02);/* Switch Banks!! */ 
    824      if (*nrels_mag >= 1) { 
    825        data->temp_over[2] = TEMP_TO_REG(results[0]); 
    826        w83781d_write_value(client,W83781D_REG_TEMP_OVER23,data->temp_over[2]); 
    827        w83781d_write_value(client,W83781D_REG_TEMP_OVER23 + 1,0); 
    828      } 
    829      if (*nrels_mag >= 2) { 
    830        data->temp_hyst[2] = TEMP_TO_REG(results[1]); 
    831        w83781d_write_value(client,W83781D_REG_TEMP_HYST23,data->temp_hyst[2]); 
    832        w83781d_write_value(client,W83781D_REG_TEMP_HYST23 + 1,0); 
    833      } 
    834      w83781d_write_value(client,W83781D_REG_TEMP_SEL,0x0);/* Switch Banks!! */ 
    835     } else if (tempnum == 2) { 
    836      w83781d_write_value(client,W83781D_REG_TEMP_SEL,0x01);/* Switch Banks!! */ 
    837      if (*nrels_mag >= 1) { 
    838        data->temp_over[1] = TEMP_TO_REG(results[0]); 
    839        w83781d_write_value(client,W83781D_REG_TEMP_OVER23,data->temp_over[1]); 
    840        w83781d_write_value(client,W83781D_REG_TEMP_OVER23 + 1,0); 
    841      } 
    842      if (*nrels_mag >= 2) { 
    843        data->temp_hyst[1] = TEMP_TO_REG(results[1]); 
    844        w83781d_write_value(client,W83781D_REG_TEMP_HYST23,data->temp_hyst[1]); 
    845        w83781d_write_value(client,W83781D_REG_TEMP_HYST23 + 1,0); 
    846      } 
    847      w83781d_write_value(client,W83781D_REG_TEMP_SEL,0x0);/* Switch Banks!! */ 
    848     } else { 
    849      if (*nrels_mag >= 1) { 
    850        data->temp_over[0] = TEMP_TO_REG(results[0]); 
    851        w83781d_write_value(client,W83781D_REG_TEMP_OVER,data->temp_over[0]); 
    852      } 
    853      if (*nrels_mag >= 2) { 
    854        data->temp_hyst[0] = TEMP_TO_REG(results[1]); 
    855        w83781d_write_value(client,W83781D_REG_TEMP_HYST,data->temp_hyst[0]); 
    856      } 
    857     } 
    858   } 
    859 } 
    860  
    861  
    862 void w83781d_temp1(struct i2c_client *client, int operation, int ctl_name, 
    863                int *nrels_mag, long *results) { 
    864  
    865   w83781d_temp(client,operation,ctl_name,nrels_mag,results,1); 
    866 } 
    867  
    868  
    869 void w83781d_temp2(struct i2c_client *client, int operation, int ctl_name, 
    870                int *nrels_mag, long *results) { 
    871                 
    872   w83781d_temp(client,operation,ctl_name,nrels_mag,results,2); 
    873 } 
    874  
    875  
    876 void w83781d_temp3(struct i2c_client *client, int operation, int ctl_name, 
    877                int *nrels_mag, long *results) { 
    878                 
    879   w83781d_temp(client,operation,ctl_name,nrels_mag,results,3); 
     939    if (*nrels_mag >= 1) { 
     940      data->temp_over = TEMP_TO_REG(results[0]); 
     941      w83781d_write_value(client,W83781D_REG_TEMP_OVER,data->temp_over); 
     942    } 
     943    if (*nrels_mag >= 2) { 
     944      data->temp_hyst = TEMP_TO_REG(results[1]); 
     945      w83781d_write_value(client,W83781D_REG_TEMP_HYST,data->temp_hyst); 
     946    } 
     947  } 
     948} 
     949 
     950 
     951void w83781d_temp_add(struct i2c_client *client, int operation, int ctl_name, 
     952                      int *nrels_mag, long *results) 
     953{ 
     954  struct w83781d_data *data = client->data; 
     955  int nr = ctl_name - W83781D_SYSCTL_TEMP2; 
     956 
     957  if (operation == SENSORS_PROC_REAL_INFO) 
     958    *nrels_mag = 1; 
     959  else if (operation == SENSORS_PROC_REAL_READ) { 
     960    w83781d_update_client(client); 
     961    results[0] = TEMP_ADD_FROM_REG(data->temp_add_over[nr]); 
     962    results[1] = TEMP_ADD_FROM_REG(data->temp_add_hyst[nr]); 
     963    results[2] = TEMP_ADD_FROM_REG(data->temp_add[nr]); 
     964    *nrels_mag = 3; 
     965  } else if (operation == SENSORS_PROC_REAL_WRITE) { 
     966    if (*nrels_mag >= 1) { 
     967      data->temp_add_over[nr] = TEMP_ADD_TO_REG(results[0]); 
     968      w83781d_write_value(client, 
     969                          nr?W83781D_REG_TEMP3_OVER:W83781D_REG_TEMP2_OVER, 
     970                          data->temp_add_over[nr]); 
     971    } 
     972    if (*nrels_mag >= 2) { 
     973      data->temp_add_hyst[nr] = TEMP_ADD_TO_REG(results[1]); 
     974      w83781d_write_value(client, 
     975                          nr?W83781D_REG_TEMP3_HYST:W83781D_REG_TEMP2_HYST, 
     976                          data->temp_add_hyst[nr]); 
     977    } 
     978  } 
    880979} 
    881980 
     
    9111010{ 
    9121011  struct w83781d_data *data = client->data; 
     1012  int val; 
     1013 
    9131014  if (operation == SENSORS_PROC_REAL_INFO) 
    9141015    *nrels_mag = 0; 
    9151016  else if (operation == SENSORS_PROC_REAL_READ) { 
    9161017    w83781d_update_client(client); 
    917     results[0] = data->beep[0]; 
    918     results[1] = data->beep[1]; 
    919     results[2] = data->beep[2]; 
    920     *nrels_mag = 3; 
     1018    results[0] = BEEP_ENABLE_FROM_REG(data->beep_enable); 
     1019    results[1] = BEEPS_FROM_REG(data->beeps); 
     1020    *nrels_mag = 2; 
    9211021  } else if (operation == SENSORS_PROC_REAL_WRITE) { 
    922     data->beep[0] = results[0]; 
    923     w83781d_write_value(client,W83781D_REG_BEEP_CONFIG,data->beep[0]); 
    924     data->beep[1] = results[1]; 
    925     w83781d_write_value(client,W83781D_REG_BEEP_INTS1,data->beep[1]); 
    926     data->beep[2] = results[2]; 
    927     w83781d_write_value(client,W83781D_REG_BEEP_INTS2,data->beep[2]); 
     1022    if (*nrels_mag >= 2) { 
     1023      data->beeps = BEEPS_TO_REG(results[1]); 
     1024      w83781d_write_value(client,W83781D_REG_BEEP_INTS1,data->beeps & 0xff); 
     1025      val = data->beeps >> 8; 
     1026    } else if (*nrels_mag >= 1) 
     1027      val = w83781d_read_value(client,W83781D_REG_BEEP_INTS1) & 0x7f; 
     1028    if (*nrels_mag >= 1) { 
     1029      data->beep_enable = BEEP_ENABLE_TO_REG(results[0]); 
     1030      w83781d_write_value(client,W83781D_REG_BEEP_INTS2, 
     1031                          val | data->beep_enable << 7); 
     1032    } 
    9281033  } 
    9291034} 
     
    9411046    results[0] = DIV_FROM_REG(data->fan_div[0]); 
    9421047    results[1] = DIV_FROM_REG(data->fan_div[1]); 
    943     results[2] = 2; 
     1048    results[2] = DIV_FROM_REG(data->fan_div[2]); 
    9441049    *nrels_mag = 3; 
    9451050  } else if (operation == SENSORS_PROC_REAL_WRITE) { 
     
    9541059      w83781d_write_value(client,W83781D_REG_VID_FANDIV,old); 
    9551060    } 
     1061    if (*nrels_mag >= 3) { 
     1062      data->fan_div[2] = DIV_TO_REG(results[2]); 
     1063      w83781d_write_value(client,W83781D_REG_PIN, 
     1064                          w83781d_read_value(client,W83781D_REG_PIN)); 
     1065    } 
    9561066  } 
    9571067}