Changeset 484
- Timestamp:
- 06/17/99 00:16:48 (9 years ago)
- Files:
-
- lm-sensors/trunk/TODO (modified) (2 diffs)
- lm-sensors/trunk/doc/chips/gl518sm (modified) (4 diffs)
- lm-sensors/trunk/kernel/chips/gl518sm.c (modified) (14 diffs)
- lm-sensors/trunk/kernel/include/sensors.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
lm-sensors/trunk/TODO
r467 r484 38 38 * Test SIS5595(/91/98) sensor support. Write generic i2c support. 39 39 Thomas Dickel <Thomas.Dickel@mni.fh-giessen.de> owns one SIS5595. 40 * Make GL518SM rev 00 voltage iteration run as a kernel thread.41 Add libsensors support for the new readable registers.42 40 * adm9240: check whether the current voltage computations are correct. 43 41 Probably not, as they are different from the datasheet specifications. … … 45 43 * lm80: Check how OS alarms work. At page 17 of the sheet, it tells 46 44 something completely different from the description at page 25. 47 * gl518sm: Update binary search to 'trinary' search: because we have 48 both upper and lower limits, you can see the difference between three 49 pieces of the current range. 50 Also, you can assume that new values are close to old values, so start 51 with trying to use a small range near the old values (already partially 52 done?) 45 * gl518sm: Assume that new values are close to old values, so start with 46 trying to use a small range near the old values (already partially done) 53 47 54 48 LIBRARY lm-sensors/trunk/doc/chips/gl518sm
r403 r484 12 12 Prefix `gl518sm-r80' 13 13 Addresses scanned: I2C 0x2c and 0x2d 14 Datasheet: Not available at all, as far as we know14 Datasheet: Not available 15 15 16 16 Author: Frodo Looijaard <frodol@dds.nl> … … 36 36 * probe_range: short array (min = 1, max = 48) 37 37 List of adapter,start-addr,end-addr triples to scan additionally 38 * readall: int39 Enable the experimental code, which tries to find the voltages of40 revision zero chips by slow (10 seconds) interpolation41 42 38 43 39 Description … … 59 55 60 56 FAN rotation speeds are reported in RPM (rotations per minute). An alarm is 61 triggered if the rotation speed has dropped below a programmable limit. FAN 62 readings can be divided by a programmable divider (1, 2, 4 or 8) to give 57 triggered if the rotation speed has dropped below a programmable limit. 58 In case when you have selected to turn Fan1 off, no Fan1 alarm is triggered 59 if measured temperature is below 'over temperature' limit. 60 61 FAN readings can be divided by a programmable divider (1, 2, 4 or 8) to give 63 62 the readings more range or accuracy. This is important because some FANs 64 report only one 'tick' each rotation, while others report two - making 65 all readings twice as high. Not all RPM values can accurately be represented, 66 so some rounding is done. With a divider of 2, the lowest representable 67 value is around 1900 RPM. 68 69 Voltage sensors (also known as VIN sensors) report their values in volts. 70 An alarm is triggered if the voltage has crossed a programmable minimum 71 or maximum limit. Note that minimum in this case always means 'closest to 63 report only one 'tick' each rotation, while others report two. 64 Not all RPM values can accurately be represented, so some rounding is done. 65 With a divider of 2, the lowest representable value is around 1900 RPM. 66 67 Voltage sensors (also known as VIN sensors) report their values in volts. An 68 alarm is triggered if the voltage has crossed a programmable minimum or 69 maximum limit. Note that minimum in this case always means 'closest to 72 70 zero'; this is important for negative voltage measurements. The VDD input 73 71 measures voltages between 0.000 and 5.865 volt, with a resolution of 0.023 74 volt. The other inputs measure voltages between 0.000 and 4.845 volt, with 75 a resolution of 0.019 volt. Note that revision 0x00 chips do not support 76 reading the current voltage of any input except for VIN3; limit setting 77 and alarms work fine, though. Yes, this is weird. There is experimental 78 code to compute them by interpolation; see the 'readall' module parameter. 72 volt. The other inputs measure voltages between 0.000 and 4.845 volt, with a 73 resolution of 0.019 volt. Note that revision 0x00 chips do not support 74 reading the current voltage of any input except for VIN3; limit setting and 75 alarms work fine, though. There is code to compute them by iterating. 79 76 80 77 When an alarm goes off, you can be warned by a beeping signal through … … 91 88 The GL518SM only updates its values each 1.5 seconds; reading it more often 92 89 will do no harm, but will return 'old' values. 93 94 Not supported is the option to use only one fan, and to enable/disable the95 speed of that fan automatically as function of the current temperature.96 97 90 98 91 Chip Features lm-sensors/trunk/kernel/chips/gl518sm.c
r478 r484 159 159 u8 fan_div[2]; /* Register encoding, shifted right */ 160 160 u8 beep_enable; /* Boolean */ 161 u8 sw_alarm_mask; /* Mask unwanted HW alarms */ 161 u8 iterate; /* Voltage iteration mode */ 162 u8 fan1conf; /* Fan1 on/off control */ 162 163 }; 163 164 … … 172 173 MODULE_PARM_DESC(readall,"Enable the experimental code, which tries to find " 173 174 "the voltages of revision zero chips by " 174 "slow (10 seconds) i nterpolation");175 "slow (10 seconds) iteration"); 175 176 #endif /* MODULE */ 176 177 … … 203 204 static void gl518_beep(struct i2c_client *client, int operation, int ctl_name, 204 205 int *nrels_mag, long *results); 206 static void gl518_fan1off(struct i2c_client *client, int operation, 207 int ctl_name, int *nrels_mag, long *results); 208 static void gl518_iterate(struct i2c_client *client, int operation, 209 int ctl_name, int *nrels_mag, long *results); 205 210 206 211 /* This is the driver that will be inserted */ … … 242 247 { GL518_SYSCTL_BEEP, "beep", NULL, 0, 0644, NULL, &sensors_proc_real, 243 248 &sensors_sysctl_real, NULL, &gl518_beep }, 249 { GL518_SYSCTL_FAN1OFF, "fan1off", NULL, 0, 0644, NULL, &sensors_proc_real, 250 &sensors_sysctl_real, NULL, &gl518_fan1off }, 251 { GL518_SYSCTL_ITERATE, "iterate", NULL, 0, 0644, NULL, &sensors_proc_real, 252 &sensors_sysctl_real, NULL, &gl518_iterate }, 244 253 { 0 } 245 254 }; … … 427 436 gl518_write_value(client,GL518_REG_CONF,0x44); 428 437 429 /* Sometimes we want to report no alarm, even when 430 the hardware tells the opposite */ 431 data->sw_alarm_mask = 0xff; 438 data->iterate=readall; 432 439 } 433 440 … … 538 545 data->voltage_max[3] = (val >> 8) & 0xff; 539 546 547 data->voltage[3] = gl518_read_value(client,GL518_REG_VIN3); 548 #ifndef DEBUG_VIN 540 549 if (data->type != gl518sm_r00) { 541 550 data->voltage[0] = gl518_read_value(client,GL518_REG_VDD); 542 551 data->voltage[1] = gl518_read_value(client,GL518_REG_VIN1); 543 552 data->voltage[2] = gl518_read_value(client,GL518_REG_VIN2); 544 } else {545 if (!readall) {546 data->voltage[0] = 0; 547 data->voltage[1] = 0;548 data->voltage[2] = 0;549 }550 }551 data->voltage[3] = gl518_read_value(client,GL518_REG_VIN3); 553 } else 554 gl518_update_client_rev00(client); 555 #else 556 data->voltage[0] = gl518_read_value(client,GL518_REG_VDD); 557 data->voltage[1] = gl518_read_value(client,GL518_REG_VIN1); 558 data->voltage[2] = gl518_read_value(client,GL518_REG_VIN2); 559 gl518_update_client_rev00(client); 560 #endif 552 561 553 562 val = gl518_read_value(client,GL518_REG_FAN_COUNT); … … 566 575 data->fan_div[0] = (val >> 6) & 0x03; 567 576 data->fan_div[1] = (val >> 4) & 0x03; 568 data->beep_enable = (gl518_read_value(client,GL518_REG_CONF) >> 2) & 1; 577 data->fan1conf = (val >> 3) & 1; 578 579 if (((data->fan1conf) && (data->temp < data->temp_over)) || 580 (data->fan_min[0]==0xff)) 581 data->alarms &= ~GL518_ALARM_FAN1; 582 583 if (data->fan_min[1]==0xff) 584 data->alarms &= ~GL518_ALARM_FAN2; 585 586 val = gl518_read_value(client, GL518_REG_CONF); 587 data->beep_enable = (val >> 2) & 1; 569 588 570 589 data->last_updated = jiffies; … … 575 594 } 576 595 577 /* Similar to gl518_update_client() but updates vdd, vin1, vin2 values 578 by doing slow and multiple comparisons for the GL518SM rev 00 that 579 lacks support for direct reading of these values. 580 (added by Ludovic Drolez (ldrolez@usa.net) */ 596 /* This updates vdd, vin1, vin2 values by doing slow and multiple 597 comparisons for the GL518SM rev 00 that lacks support for direct 598 reading of these values. */ 581 599 582 600 void gl518_update_client_rev00(struct i2c_client *client) 583 601 { 584 602 struct gl518_data *data = client->data; 585 int j, min, max[3], delta; 586 587 down(&data->update_lock); 603 int i, j, loop_more=1, min[3], max[3], delta[3]; 604 int alarm, config; 605 606 #define VIN_REG(c) c==0?GL518_REG_VDD_LIMIT:\ 607 c==1?GL518_REG_VIN1_LIMIT:\ 608 GL518_REG_VIN2_LIMIT 609 610 config = gl518_read_value(client, GL518_REG_CONF) & 0xfb; 611 alarm = data->alarms; 612 613 if (data->iterate==0) { 614 for (i=0; i<3; i++) 615 data->voltage[i]=0; 616 return; 617 } 588 618 589 619 #ifndef DEBUG_VIN 590 620 /* as that update is slow, we consider the data valid for 30 seconds */ 591 if ( jiffies - data->last_updated_v00 > 30*HZ) {621 if ((jiffies - data->last_updated_v00 > 30*HZ) || (alarm & 7)) { 592 622 #else 593 623 if (jiffies - data->last_updated_v00 > HZ+HZ/2 ) { 594 624 #endif 595 625 596 /* disable audible alarm */ 597 gl518_write_value(client,GL518_REG_CONF, 598 (gl518_read_value(client,GL518_REG_CONF) & 0xfb)); 599 600 min = 1; 601 max[0] = VDD_TO_REG(GL518_INIT_VDD); 602 max[1] = IN_TO_REG(GL518_INIT_VIN_1); 603 max[2] = IN_TO_REG(GL518_INIT_VIN_2); 604 delta = 32; 605 do { 606 gl518_write_value(client,GL518_REG_VDD_LIMIT,(max[0] << 8) | min); 607 gl518_write_value(client,GL518_REG_VIN1_LIMIT,(max[1] << 8) | min); 608 gl518_write_value(client,GL518_REG_VIN2_LIMIT,(max[2] << 8) | min); 626 for (i=0; i<3; i++) { 627 if (alarm & (1<<i)) { 628 min[i] = 0; 629 max[i] = 127; 630 } else { 631 min[i] = data->voltage_min[i]; 632 max[i] = (data->voltage_max[i]+data->voltage_min[i]) / 2; 633 } 634 delta[i] = (max[i] - min[i]) / 2; 635 } 636 637 /* disable beeps */ 638 gl518_write_value(client,GL518_REG_CONF,config); 639 640 for (j=0; (j<10 && loop_more); j++) { 641 642 for (i=0; i<3; i++) 643 gl518_write_value(client, VIN_REG(i), max[i] << 8 | min[i]); 609 644 610 645 /* we wait now 1.5 seconds before comparing */ 611 646 current->state = TASK_INTERRUPTIBLE; 612 647 schedule_timeout(HZ + HZ/2); 613 614 /* read comparators */ 615 j = gl518_read_value(client,GL518_REG_INT); 616 if ((j & 1) == 0) { 617 max[0] = max[0] - delta; 618 } else { 619 max[0] = max[0] + delta; 648 alarm = gl518_read_value(client,GL518_REG_INT); 649 650 #ifdef DEBUG_VIN 651 printk("gl518sm: iteration %2d: %4d%c %4d%c %4d%c\n", j, 652 max[0], (alarm&1)?'!':' ', 653 max[1], (alarm&2)?'!':' ', 654 max[2], (alarm&4)?'!':' '); 655 #endif 656 657 for (loop_more=0, i=0; i<3; i++) { 658 if (alarm & (1<<i)) 659 max[i] += delta[i]; 660 else 661 max[i] -= delta[i]; 662 663 if (delta[i]) 664 loop_more++; 665 delta[i] >>= 1; 620 666 } 621 if ((j & 2) == 0) { 622 max[1] = max[1] - delta; 623 } else { 624 max[1] = max[1] + delta; 625 } 626 if ((j & 4) == 0) { 627 max[2] = max[2] - delta; 628 } else { 629 max[2] = max[2] + delta; 630 } 631 delta >>= 1; 632 #ifdef DEBUG_VIN 633 printk("Iterations: %3d %3d %3d \n", max[0], max[1], max[2]); 667 } 668 669 for (i=0; i<3; i++) 670 if (alarm & (1<<i)) 671 max[i]++; 672 673 #ifdef DEBUG_VIN 674 printk("gl518sm: final :%5d %5d %5d\n", max[0], max[1], max[2]); 675 printk("gl518sm: meter :%5d %5d %5d\n", data->voltage[0], 676 data->voltage[1], data->voltage[2]); 634 677 #endif 635 } while (delta != 0);636 637 /* do a final comparison to get to least significant bit */638 gl518_write_value(client,GL518_REG_VDD_LIMIT,(max[0] << 8) | min);639 gl518_write_value(client,GL518_REG_VIN1_LIMIT,(max[1] << 8) | min);640 gl518_write_value(client,GL518_REG_VIN2_LIMIT,(max[2] << 8) | min);641 642 /* we wait now 1.5 seconds before comparing */643 current->state = TASK_INTERRUPTIBLE;644 schedule_timeout(HZ + HZ/2);645 646 /* read comparators */647 j = gl518_read_value(client,GL518_REG_INT);648 if ((j & 1) == 0) max[0]--;649 if ((j & 2) == 0) max[1]--;650 if ((j & 4) == 0) max[2]--;651 652 #ifdef DEBUG_VIN653 if (data->type == gl518sm_r00) {654 printk("Avdd: Meter: %3d, Search: %3d, Diff: %3d mV\n",655 data->voltage[0], max[0], (max[0] - data->voltage[0]) * 23);656 printk("Vin1: Meter: %3d, Search: %3d, Diff: %3d mV\n",657 data->voltage[1], max[1], (max[1] - data->voltage[1]) * 19);658 printk("Vin2: Meter: %3d, Search: %3d, Diff: %3d mV\n",659 data->voltage[2], max[2], (max[2] - data->voltage[2]) * 19);660 } else661 printk("No voltage meter to read on rev 00 ICs\n");662 #endif663 664 /* update voltages values */665 data->voltage[0] = max[0];666 data->voltage[1] = max[1];667 data->voltage[2] = max[2];668 669 /* restore original comparator values */670 gl518_write_value(client,GL518_REG_VDD_LIMIT,671 (data->voltage_max[0] << 8) | data->voltage_min[0]);672 gl518_write_value(client,GL518_REG_VIN1_LIMIT,673 (data->voltage_max[1] << 8) | data->voltage_min[1]);674 gl518_write_value(client,GL518_REG_VIN2_LIMIT,675 (data->voltage_max[2] << 8) | data->voltage_min[2]);676 678 677 679 data->last_updated_v00 = jiffies; 678 679 /* reset audible alarm state */ 680 gl518_write_value(client,GL518_REG_CONF, 681 (gl518_read_value(client,GL518_REG_CONF) & 0xfb) | 682 (data->beep_enable << 2)); 683 } 684 up(&data->update_lock); 680 681 /* reset beeps */ 682 gl518_write_value(client, GL518_REG_CONF, 683 (config | (data->beep_enable << 2))); 684 685 /* reset values */ 686 for (i=0; i<3; i++) { 687 data->voltage[i] = max[i]; 688 gl518_write_value(client, VIN_REG(i), 689 data->voltage_max[i] << 8 | data->voltage_min[i]); 690 } 691 } 692 #undef VIN_REG 685 693 } 686 694 … … 720 728 else if (operation == SENSORS_PROC_REAL_READ) { 721 729 gl518_update_client(client); 722 #ifndef DEBUG_VIN723 if ((data->type == gl518sm_r00) && (nr != 3) && readall)724 /* only update VDD, VIN1, VIN2 voltages */725 gl518_update_client_rev00(client);726 #else727 gl518_update_client_rev00(client);728 #endif729 730 results[0] = nr?IN_FROM_REG(data->voltage_min[nr]): 730 731 VDD_FROM_REG(data->voltage_min[nr]); … … 778 779 old = (old & 0xff00) | data->fan_min[nr]; 779 780 780 if (results[0])781 data->sw_alarm_mask |= (nr ? GL518_ALARM_FAN2 : GL518_ALARM_FAN1);782 else783 data->sw_alarm_mask &= ~(nr ? GL518_ALARM_FAN2 : GL518_ALARM_FAN1);784 785 781 gl518_write_value(client,GL518_REG_FAN_LIMIT,old); 786 782 } … … 797 793 else if (operation == SENSORS_PROC_REAL_READ) { 798 794 gl518_update_client(client); 799 results[0] = ALARMS_FROM_REG(data->alarms & data->sw_alarm_mask);795 results[0] = ALARMS_FROM_REG(data->alarms); 800 796 *nrels_mag = 1; 801 797 } … … 827 823 } 828 824 825 829 826 void gl518_fan_div(struct i2c_client *client, int operation, int ctl_name, 830 827 int *nrels_mag, long *results) … … 853 850 } 854 851 852 void gl518_fan1off(struct i2c_client *client, int operation, int ctl_name, 853 int *nrels_mag, long *results) 854 { 855 int old; 856 if (operation == SENSORS_PROC_REAL_INFO) 857 *nrels_mag = 0; 858 else if (operation == SENSORS_PROC_REAL_READ) { 859 results[0] = ((gl518_read_value(client, GL518_REG_MISC) & 0x08) !=0); 860 results[1] = ((gl518_read_value(client, GL518_REG_CONF) & 0x10) !=0); 861 *nrels_mag = 2; 862 } else if (operation == SENSORS_PROC_REAL_WRITE) { 863 if (*nrels_mag >= 1) { 864 old = gl518_read_value(client, GL518_REG_MISC) & 0xf7; 865 if (results[0]) 866 old |= 0x08; 867 gl518_write_value(client,GL518_REG_MISC,old); 868 } 869 if (*nrels_mag >= 2) { 870 old = gl518_read_value(client, GL518_REG_CONF) & 0xef; 871 if (results[1]) 872 old |= 0x10; 873 gl518_write_value(client,GL518_REG_CONF,old); 874 } 875 } 876 } 877 878 void gl518_iterate(struct i2c_client *client, int operation, int ctl_name, 879 int *nrels_mag, long *results) 880 { 881 struct gl518_data *data = client->data; 882 if (operation == SENSORS_PROC_REAL_INFO) 883 *nrels_mag = 0; 884 else if (operation == SENSORS_PROC_REAL_READ) { 885 results[0] = data->iterate; 886 *nrels_mag = 1; 887 } else if (operation == SENSORS_PROC_REAL_WRITE) { 888 if (*nrels_mag >= 1) 889 data->iterate=results[0]; 890 } 891 } 855 892 856 893 int gl518_init(void) … … 901 938 902 939 #endif /* MODULE */ 940 lm-sensors/trunk/kernel/include/sensors.h
r464 r484 435 435 #define GL518_SYSCTL_ALARMS 2001 /* bitvector */ 436 436 #define GL518_SYSCTL_BEEP 2002 /* bitvector */ 437 #define GL518_SYSCTL_FAN1OFF 2003 438 #define GL518_SYSCTL_ITERATE 2004 437 439 438 440 #define GL518_ALARM_VDD 0x01
