gl518sm chip driver for 2.6 kernel
Chew Hong Gunn
hgchew at gunnet.org
Mon Feb 2 17:02:39 CET 2004
Hi Jean,
I have attached the latest patch against rc3. I have fixed up all that
we have discussed on sunday. In particular:
* BOOL and RAW macros
* voltage rounding
* fan speed calculation
* beep_mask for fan_min==0
* driver init code
Hopefully the code is ready now. *phew*
Let me know what you think.
Cheers,
Hong-Gunn
-------------- next part --------------
--- gl518sm.c.rc3 2004-02-01 15:10:06.000000000 +1030
+++ gl518sm.c 2004-02-03 02:25:47.091099754 +1030
@@ -100,22 +100,21 @@
static inline u8 FAN_TO_REG(long rpm, int div)
{
+ long rpmdiv;
if (rpm == 0)
- return 255;
- rpm = SENSORS_LIMIT(rpm, 1, 1000000);
- return SENSORS_LIMIT((960000 + rpm * div / 2) / (rpm * div), 1, 254);
+ return 0;
+ rpmdiv = SENSORS_LIMIT(rpm, 1, 1920000) * div;
+ return SENSORS_LIMIT((960000 + rpmdiv / 2) / rpmdiv, 1, 255);
}
+#define FAN_FROM_REG(val,div) ((val)==0 ? 0 : (960000/((val)*(div))))
-#define FAN_FROM_REG(val,div) ((val)==0 ? 0 : (val)==255 ? 0 : \
- (960000/((val)*(div))))
-
-#define IN_TO_REG(val) (SENSORS_LIMIT((((val)+8)/19),0,255))
+#define IN_TO_REG(val) (SENSORS_LIMIT((((val)+9)/19),0,255))
#define IN_FROM_REG(val) ((val)*19)
-#define VDD_TO_REG(val) (SENSORS_LIMIT((((val)+11)/23),0,255))
-#define VDD_FROM_REG(val) ((val)*23)
+#define VDD_TO_REG(val) (SENSORS_LIMIT((((val)*4+47)/95),0,255))
+#define VDD_FROM_REG(val) ((val)*95/4)
-#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
+#define DIV_TO_REG(val) ((val)==4?2:(val)==2?1:(val)==1?0:3)
#define DIV_FROM_REG(val) (1 << (val))
#define BEEP_MASK_TO_REG(val) ((val) & 0x7f & data->alarm_mask)
@@ -273,11 +272,15 @@
data->fan_min[0] = FAN_TO_REG(simple_strtoul(buf, NULL, 10),
DIV_FROM_REG(data->fan_div[0]));
regvalue = (regvalue & 0x00ff) | (data->fan_min[0] << 8);
+ gl518_write_value(client, GL518_REG_FAN_LIMIT, regvalue);
+
+ data->beep_mask = gl518_read_value(client, GL518_REG_ALARM);
if (data->fan_min[0] == 0)
data->alarm_mask &= ~0x20;
else
data->alarm_mask |= 0x20;
- gl518_write_value(client, GL518_REG_FAN_LIMIT, regvalue);
+ data->beep_mask &= data->alarm_mask;
+ gl518_write_value(client, GL518_REG_ALARM, data->beep_mask);
return count;
}
@@ -291,11 +294,15 @@
data->fan_min[1] = FAN_TO_REG(simple_strtoul(buf, NULL, 10),
DIV_FROM_REG(data->fan_div[1]));
regvalue = (regvalue & 0xff00) | data->fan_min[1];
+ gl518_write_value(client, GL518_REG_FAN_LIMIT, regvalue);
+
+ data->beep_mask = gl518_read_value(client, GL518_REG_ALARM);
if (data->fan_min[1] == 0)
data->alarm_mask &= ~0x40;
else
data->alarm_mask |= 0x40;
- gl518_write_value(client, GL518_REG_FAN_LIMIT, regvalue);
+ data->beep_mask &= data->alarm_mask;
+ gl518_write_value(client, GL518_REG_ALARM, data->beep_mask);
return count;
}
@@ -350,7 +357,7 @@
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA))
- goto exit;
+ goto exit;
/* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet.
@@ -378,7 +385,7 @@
if (kind < 0) {
if ((gl518_read_value(new_client, GL518_REG_CHIP_ID) != 0x80)
|| (gl518_read_value(new_client, GL518_REG_CONF) & 0x80))
- goto exit_free;
+ goto exit_free;
}
/* Determine the chip type. */
@@ -458,19 +465,18 @@
/* Called when we have found a new GL518SM. */
static void gl518_init_client(struct i2c_client *client)
{
- /* Power-on defaults (bit 7=1) */
- gl518_write_value(client, GL518_REG_CONF, 0x80);
+ /* retain D4:NoFan2, D2:beep_enable */
+ u8 regvalue = gl518_read_value(client, GL518_REG_CONF) & 0x14;
- /* No noisy output (bit 2=1), Comparator mode (bit 3=0), two fans (bit4=0),
- standby mode (bit6=0) */
- gl518_write_value(client, GL518_REG_CONF, 0x04);
+ /* Comparator mode (D3=0), standby mode (D6=0) */
+ gl518_write_value(client, GL518_REG_CONF, 0xb7 & regvalue);
/* Never interrupts */
gl518_write_value(client, GL518_REG_MASK, 0x00);
- /* Clear status register (bit 5=1), start (bit6=1) */
- gl518_write_value(client, GL518_REG_CONF, 0x24);
- gl518_write_value(client, GL518_REG_CONF, 0x44);
+ /* Clear status register (D5=1), start (D6=1) */
+ gl518_write_value(client, GL518_REG_CONF, 0x20 | regvalue);
+ gl518_write_value(client, GL518_REG_CONF, 0x40 | regvalue);
}
static int gl518_detach_client(struct i2c_client *client)
More information about the lm-sensors
mailing list