Commit 41e1a1ee authored by Jean Delvare's avatar Jean Delvare Committed by Greg Kroah-Hartman

[PATCH] I2C: Refine detection of LM75 chips

The LM75 detection method was a bit loose so far and would accept
non-LM75-compatible chips from times to times. It should be better now.
Additionally, the help for the lm75 driver was reworked because we now
know that the LM75 and the LM77 are not compatible.


Signed-off-by: Jean Delvare <khali at linux-fr dot org>
Signed-off-by: default avatarGreg Kroah-Hartman <greg@kroah.com>
parent 1fcab19d
......@@ -103,8 +103,12 @@ config SENSORS_LM75
select I2C_SENSOR
help
If you say yes here you get support for National Semiconductor LM75
sensor chips and clones: Dallas Semi DS75 and DS1775, TelCon
TCN75, and National Semiconductor LM77.
sensor chips and clones: Dallas Semiconductor DS75 and DS1775 (in
9-bit precision mode), and TelCom (now Microchip) TCN75.
The DS75 and DS1775 in 10- to 12-bit precision modes will require
a force module parameter. The driver will not handle the extra
precision anyhow.
This driver can also be built as a module. If so, the module
will be called lm75.
......
......@@ -113,7 +113,7 @@ static int lm75_attach_adapter(struct i2c_adapter *adapter)
/* This function is called by i2c_detect */
static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
{
int i, cur, conf, hyst, os;
int i;
struct i2c_client *new_client;
struct lm75_data *data;
int err = 0;
......@@ -149,16 +149,41 @@ static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
new_client->driver = &lm75_driver;
new_client->flags = 0;
/* Now, we do the remaining detection. It is lousy. */
/* Now, we do the remaining detection. There is no identification-
dedicated register so we have to rely on several tricks:
unused bits, registers cycling over 8-address boundaries,
addresses 0x04-0x07 returning the last read value.
The cycling+unused addresses combination is not tested,
since it would significantly slow the detection down and would
hardly add any value. */
if (kind < 0) {
int cur, conf, hyst, os;
/* Unused addresses */
cur = i2c_smbus_read_word_data(new_client, 0);
conf = i2c_smbus_read_byte_data(new_client, 1);
hyst = i2c_smbus_read_word_data(new_client, 2);
if (i2c_smbus_read_word_data(new_client, 4) != hyst
|| i2c_smbus_read_word_data(new_client, 5) != hyst
|| i2c_smbus_read_word_data(new_client, 6) != hyst
|| i2c_smbus_read_word_data(new_client, 7) != hyst)
goto exit_free;
os = i2c_smbus_read_word_data(new_client, 3);
for (i = 0; i <= 0x1f; i++)
if ((i2c_smbus_read_byte_data(new_client, i * 8 + 1) != conf) ||
(i2c_smbus_read_word_data(new_client, i * 8 + 2) != hyst) ||
(i2c_smbus_read_word_data(new_client, i * 8 + 3) != os))
if (i2c_smbus_read_word_data(new_client, 4) != os
|| i2c_smbus_read_word_data(new_client, 5) != os
|| i2c_smbus_read_word_data(new_client, 6) != os
|| i2c_smbus_read_word_data(new_client, 7) != os)
goto exit_free;
/* Unused bits */
if (conf & 0xe0)
goto exit_free;
/* Addresses cycling */
for (i = 8; i < 0xff; i += 8)
if (i2c_smbus_read_byte_data(new_client, i + 1) != conf
|| i2c_smbus_read_word_data(new_client, i + 2) != hyst
|| i2c_smbus_read_word_data(new_client, i + 3) != os)
goto exit_free;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment