mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-24 19:45:06 +08:00
hwmon: (lm90) Rework detect function
The detect function is getting larger and larger and difficult to understand or review. Split it into per-manufacturer detect functions to improve readability. Signed-off-by: Guenter Roeck <linux@roeck-us.net>
This commit is contained in:
parent
b977ed27c4
commit
c7cebce984
@ -1500,78 +1500,88 @@ static umode_t lm90_is_visible(const void *data, enum hwmon_sensor_types type,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return 0 if detection is successful, -ENODEV otherwise */
|
/*
|
||||||
static int lm90_detect(struct i2c_client *client,
|
* Per-manufacturer chip detect functions.
|
||||||
struct i2c_board_info *info)
|
* Functions are expected to return a pointer to the chip name or NULL
|
||||||
|
* if detection was not successful.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const char *lm90_detect_national(struct i2c_client *client, int chip_id,
|
||||||
|
int config1, int convrate)
|
||||||
{
|
{
|
||||||
struct i2c_adapter *adapter = client->adapter;
|
int config2 = i2c_smbus_read_byte_data(client, LM90_REG_CONFIG2);
|
||||||
int address = client->addr;
|
int address = client->addr;
|
||||||
const char *name = NULL;
|
const char *name = NULL;
|
||||||
int man_id, chip_id, config1, config2, convrate;
|
|
||||||
|
|
||||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
if (config2 < 0)
|
||||||
return -ENODEV;
|
return NULL;
|
||||||
|
|
||||||
/* detection and identification */
|
if ((config1 & 0x2a) || (config2 & 0xf8) || convrate > 0x09)
|
||||||
man_id = i2c_smbus_read_byte_data(client, LM90_REG_MAN_ID);
|
return NULL;
|
||||||
chip_id = i2c_smbus_read_byte_data(client, LM90_REG_CHIP_ID);
|
|
||||||
config1 = i2c_smbus_read_byte_data(client, LM90_REG_CONFIG1);
|
|
||||||
convrate = i2c_smbus_read_byte_data(client, LM90_REG_CONVRATE);
|
|
||||||
if (man_id < 0 || chip_id < 0 || config1 < 0 || convrate < 0)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
if (man_id == 0x01 || man_id == 0x5C || man_id == 0xA1) {
|
if (address != 0x4c && address != 0x4d)
|
||||||
config2 = i2c_smbus_read_byte_data(client, LM90_REG_CONFIG2);
|
return NULL;
|
||||||
if (config2 < 0)
|
|
||||||
return -ENODEV;
|
switch (chip_id & 0xf0) {
|
||||||
|
case 0x10: /* LM86 */
|
||||||
|
if (address == 0x4c)
|
||||||
|
name = "lm86";
|
||||||
|
break;
|
||||||
|
case 0x20: /* LM90 */
|
||||||
|
if (address == 0x4c)
|
||||||
|
name = "lm90";
|
||||||
|
break;
|
||||||
|
case 0x30: /* LM89/LM99 */
|
||||||
|
name = "lm99"; /* detect LM89 as LM99 */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((address == 0x4C || address == 0x4D)
|
return name;
|
||||||
&& man_id == 0x01) { /* National Semiconductor */
|
}
|
||||||
if ((config1 & 0x2A) == 0x00
|
|
||||||
&& (config2 & 0xF8) == 0x00
|
|
||||||
&& convrate <= 0x09) {
|
|
||||||
if (address == 0x4C
|
|
||||||
&& (chip_id & 0xF0) == 0x20) { /* LM90 */
|
|
||||||
name = "lm90";
|
|
||||||
} else
|
|
||||||
if ((chip_id & 0xF0) == 0x30) { /* LM89/LM99 */
|
|
||||||
name = "lm99";
|
|
||||||
dev_info(&adapter->dev,
|
|
||||||
"Assuming LM99 chip at 0x%02x\n",
|
|
||||||
address);
|
|
||||||
dev_info(&adapter->dev,
|
|
||||||
"If it is an LM89, instantiate it "
|
|
||||||
"with the new_device sysfs "
|
|
||||||
"interface\n");
|
|
||||||
} else
|
|
||||||
if (address == 0x4C
|
|
||||||
&& (chip_id & 0xF0) == 0x10) { /* LM86 */
|
|
||||||
name = "lm86";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
if ((address == 0x4C || address == 0x4D)
|
|
||||||
&& man_id == 0x41) { /* Analog Devices */
|
|
||||||
if ((chip_id & 0xF0) == 0x40 /* ADM1032 */
|
|
||||||
&& (config1 & 0x3F) == 0x00
|
|
||||||
&& convrate <= 0x0A) {
|
|
||||||
name = "adm1032";
|
|
||||||
} else
|
|
||||||
if (chip_id == 0x51 /* ADT7461 */
|
|
||||||
&& (config1 & 0x1B) == 0x00
|
|
||||||
&& convrate <= 0x0A) {
|
|
||||||
name = "adt7461";
|
|
||||||
} else
|
|
||||||
if (chip_id == 0x57 /* ADT7461A, NCT1008 */
|
|
||||||
&& (config1 & 0x1B) == 0x00
|
|
||||||
&& convrate <= 0x0A) {
|
|
||||||
name = "adt7461a";
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
if (man_id == 0x4D) { /* Maxim */
|
|
||||||
int emerg, emerg2, status2;
|
|
||||||
|
|
||||||
|
static const char *lm90_detect_analog(struct i2c_client *client, int chip_id,
|
||||||
|
int config1, int convrate)
|
||||||
|
{
|
||||||
|
int address = client->addr;
|
||||||
|
const char *name = NULL;
|
||||||
|
|
||||||
|
switch (chip_id) {
|
||||||
|
case 0x40 ... 0x4f: /* ADM1032 */
|
||||||
|
if ((address == 0x4c || address == 0x4d) && !(config1 & 0x3f) &&
|
||||||
|
convrate <= 0x0a)
|
||||||
|
name = "adm1032";
|
||||||
|
break;
|
||||||
|
case 0x51: /* ADT7461 */
|
||||||
|
if ((address == 0x4c || address == 0x4d) && !(config1 & 0x1b) &&
|
||||||
|
convrate <= 0x0a)
|
||||||
|
name = "adt7461";
|
||||||
|
break;
|
||||||
|
case 0x57: /* ADT7461A, NCT1008 */
|
||||||
|
if ((address == 0x4c || address == 0x4d) && !(config1 & 0x1b) &&
|
||||||
|
convrate <= 0x0a)
|
||||||
|
name = "adt7461a";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *lm90_detect_maxim(struct i2c_client *client, int chip_id,
|
||||||
|
int config1, int convrate)
|
||||||
|
{
|
||||||
|
int man_id, emerg, emerg2, status2;
|
||||||
|
int address = client->addr;
|
||||||
|
const char *name = NULL;
|
||||||
|
|
||||||
|
if ((address >= 0x48 && address <= 0x4b) || address == 0x4f)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
switch (chip_id) {
|
||||||
|
case 0x01:
|
||||||
/*
|
/*
|
||||||
* We read MAX6659_REG_REMOTE_EMERG twice, and re-read
|
* We read MAX6659_REG_REMOTE_EMERG twice, and re-read
|
||||||
* LM90_REG_MAN_ID in between. If MAX6659_REG_REMOTE_EMERG
|
* LM90_REG_MAN_ID in between. If MAX6659_REG_REMOTE_EMERG
|
||||||
@ -1587,30 +1597,8 @@ static int lm90_detect(struct i2c_client *client,
|
|||||||
status2 = i2c_smbus_read_byte_data(client,
|
status2 = i2c_smbus_read_byte_data(client,
|
||||||
MAX6696_REG_STATUS2);
|
MAX6696_REG_STATUS2);
|
||||||
if (emerg < 0 || man_id < 0 || emerg2 < 0 || status2 < 0)
|
if (emerg < 0 || man_id < 0 || emerg2 < 0 || status2 < 0)
|
||||||
return -ENODEV;
|
return NULL;
|
||||||
|
|
||||||
/*
|
|
||||||
* The MAX6657, MAX6658 and MAX6659 do NOT have a chip_id
|
|
||||||
* register. Reading from that address will return the last
|
|
||||||
* read value, which in our case is those of the man_id
|
|
||||||
* register. Likewise, the config1 register seems to lack a
|
|
||||||
* low nibble, so the value will be those of the previous
|
|
||||||
* read, so in our case those of the man_id register.
|
|
||||||
* MAX6659 has a third set of upper temperature limit registers.
|
|
||||||
* Those registers also return values on MAX6657 and MAX6658,
|
|
||||||
* thus the only way to detect MAX6659 is by its address.
|
|
||||||
* For this reason it will be mis-detected as MAX6657 if its
|
|
||||||
* address is 0x4C.
|
|
||||||
*/
|
|
||||||
if (chip_id == man_id
|
|
||||||
&& (address == 0x4C || address == 0x4D || address == 0x4E)
|
|
||||||
&& (config1 & 0x1F) == (man_id & 0x0F)
|
|
||||||
&& convrate <= 0x09) {
|
|
||||||
if (address == 0x4C)
|
|
||||||
name = "max6657";
|
|
||||||
else
|
|
||||||
name = "max6659";
|
|
||||||
} else
|
|
||||||
/*
|
/*
|
||||||
* Even though MAX6695 and MAX6696 do not have a chip ID
|
* Even though MAX6695 and MAX6696 do not have a chip ID
|
||||||
* register, reading it returns 0x01. Bit 4 of the config1
|
* register, reading it returns 0x01. Bit 4 of the config1
|
||||||
@ -1622,77 +1610,137 @@ static int lm90_detect(struct i2c_client *client,
|
|||||||
* limit registers. We can detect those chips by checking if
|
* limit registers. We can detect those chips by checking if
|
||||||
* one of those registers exists.
|
* one of those registers exists.
|
||||||
*/
|
*/
|
||||||
if (chip_id == 0x01
|
if (!(config1 & 0x10) && !(status2 & 0x01) && emerg == emerg2 &&
|
||||||
&& (config1 & 0x10) == 0x00
|
convrate <= 0x07)
|
||||||
&& (status2 & 0x01) == 0x00
|
|
||||||
&& emerg == emerg2
|
|
||||||
&& convrate <= 0x07) {
|
|
||||||
name = "max6696";
|
name = "max6696";
|
||||||
} else
|
|
||||||
/*
|
/*
|
||||||
* The chip_id register of the MAX6680 and MAX6681 holds the
|
* The chip_id register of the MAX6680 and MAX6681 holds the
|
||||||
* revision of the chip. The lowest bit of the config1 register
|
* revision of the chip. The lowest bit of the config1 register
|
||||||
* is unused and should return zero when read, so should the
|
* is unused and should return zero when read, so should the
|
||||||
* second to last bit of config1 (software reset).
|
* second to last bit of config1 (software reset).
|
||||||
*/
|
*/
|
||||||
if (chip_id == 0x01
|
else if (!(config1 & 0x03) && convrate <= 0x07)
|
||||||
&& (config1 & 0x03) == 0x00
|
|
||||||
&& convrate <= 0x07) {
|
|
||||||
name = "max6680";
|
name = "max6680";
|
||||||
} else
|
break;
|
||||||
/*
|
case 0x08:
|
||||||
* The chip_id register of the MAX6646/6647/6649 holds the
|
|
||||||
* revision of the chip. The lowest 6 bits of the config1
|
|
||||||
* register are unused and should return zero when read.
|
|
||||||
*/
|
|
||||||
if (chip_id == 0x59
|
|
||||||
&& (config1 & 0x3f) == 0x00
|
|
||||||
&& convrate <= 0x07) {
|
|
||||||
name = "max6646";
|
|
||||||
} else
|
|
||||||
/*
|
/*
|
||||||
* The chip_id of the MAX6654 holds the revision of the chip.
|
* The chip_id of the MAX6654 holds the revision of the chip.
|
||||||
* The lowest 3 bits of the config1 register are unused and
|
* The lowest 3 bits of the config1 register are unused and
|
||||||
* should return zero when read.
|
* should return zero when read.
|
||||||
*/
|
*/
|
||||||
if (chip_id == 0x08
|
if (!(config1 & 0x07) && convrate <= 0x07)
|
||||||
&& (config1 & 0x07) == 0x00
|
|
||||||
&& convrate <= 0x07) {
|
|
||||||
name = "max6654";
|
name = "max6654";
|
||||||
|
break;
|
||||||
|
case 0x4d:
|
||||||
|
/*
|
||||||
|
* The MAX6657, MAX6658 and MAX6659 do NOT have a chip_id
|
||||||
|
* register. Reading from that address will return the last
|
||||||
|
* read value, which in our case is those of the man_id
|
||||||
|
* register, or 0x4d. Likewise, the config1 register seems to
|
||||||
|
* lack a low nibble, so the value will be those of the previous
|
||||||
|
* read, so in our case again those of the man_id register.
|
||||||
|
* MAX6659 has a third set of upper temperature limit registers.
|
||||||
|
* Those registers also return values on MAX6657 and MAX6658,
|
||||||
|
* thus the only way to detect MAX6659 is by its address.
|
||||||
|
* For this reason it will be mis-detected as MAX6657 if its
|
||||||
|
* address is 0x4c.
|
||||||
|
*/
|
||||||
|
if ((address == 0x4c || address == 0x4d || address == 0x4e) &&
|
||||||
|
(config1 & 0x1f) == 0x0d && convrate <= 0x09) {
|
||||||
|
if (address == 0x4c)
|
||||||
|
name = "max6657";
|
||||||
|
else
|
||||||
|
name = "max6659";
|
||||||
}
|
}
|
||||||
} else
|
break;
|
||||||
if (address == 0x4C
|
case 0x59:
|
||||||
&& man_id == 0x5C) { /* Winbond/Nuvoton */
|
/*
|
||||||
if ((config1 & 0x2A) == 0x00
|
* The chip_id register of the MAX6646/6647/6649 holds the
|
||||||
&& (config2 & 0xF8) == 0x00) {
|
* revision of the chip. The lowest 6 bits of the config1
|
||||||
if (chip_id == 0x01 /* W83L771W/G */
|
* register are unused and should return zero when read.
|
||||||
&& convrate <= 0x09) {
|
*/
|
||||||
name = "w83l771";
|
if (!(config1 & 0x3f) && convrate <= 0x07) {
|
||||||
} else
|
switch (address) {
|
||||||
if ((chip_id & 0xFE) == 0x10 /* W83L771AWG/ASG */
|
case 0x4c:
|
||||||
&& convrate <= 0x08) {
|
name = "max6649";
|
||||||
name = "w83l771";
|
break;
|
||||||
|
case 0x4d:
|
||||||
|
name = "max6646";
|
||||||
|
break;
|
||||||
|
case 0x4e:
|
||||||
|
name = "max6647";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else
|
break;
|
||||||
if (address >= 0x48 && address <= 0x4F
|
default:
|
||||||
&& man_id == 0xA1) { /* NXP Semiconductor/Philips */
|
break;
|
||||||
if (chip_id == 0x00
|
}
|
||||||
&& (config1 & 0x2A) == 0x00
|
|
||||||
&& (config2 & 0xFE) == 0x00
|
return name;
|
||||||
&& convrate <= 0x09) {
|
}
|
||||||
name = "sa56004";
|
|
||||||
|
static const char *lm90_detect_nuvoton(struct i2c_client *client, int chip_id,
|
||||||
|
int config1, int convrate)
|
||||||
|
{
|
||||||
|
int config2 = i2c_smbus_read_byte_data(client, LM90_REG_CONFIG2);
|
||||||
|
int address = client->addr;
|
||||||
|
const char *name = NULL;
|
||||||
|
|
||||||
|
if (config2 < 0)
|
||||||
|
return ERR_PTR(-ENODEV);
|
||||||
|
|
||||||
|
if (address == 0x4c && !(config1 & 0x2a) && !(config2 & 0xf8)) {
|
||||||
|
if (chip_id == 0x01 && convrate <= 0x09) {
|
||||||
|
/* W83L771W/G */
|
||||||
|
name = "w83l771";
|
||||||
|
} else if ((chip_id & 0xfe) == 0x10 && convrate <= 0x08) {
|
||||||
|
/* W83L771AWG/ASG */
|
||||||
|
name = "w83l771";
|
||||||
}
|
}
|
||||||
} else
|
}
|
||||||
if ((address == 0x4C || address == 0x4D)
|
return name;
|
||||||
&& man_id == 0x47) { /* GMT */
|
}
|
||||||
if (chip_id == 0x01 /* G781 */
|
|
||||||
&& (config1 & 0x3F) == 0x00
|
static const char *lm90_detect_nxp(struct i2c_client *client, int chip_id,
|
||||||
&& convrate <= 0x08)
|
int config1, int convrate)
|
||||||
name = "g781";
|
{
|
||||||
} else
|
int config2 = i2c_smbus_read_byte_data(client, LM90_REG_CONFIG2);
|
||||||
if (man_id == 0x55 && chip_id == 0x00 &&
|
int address = client->addr;
|
||||||
(config1 & 0x1B) == 0x00 && convrate <= 0x09) {
|
const char *name = NULL;
|
||||||
|
|
||||||
|
if (config2 < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (address >= 0x48 && address <= 0x4f && chip_id == 0x00 &&
|
||||||
|
!(config1 & 0x2a) && !(config2 & 0xfe) && convrate <= 0x09)
|
||||||
|
name = "sa56004";
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *lm90_detect_gmt(struct i2c_client *client, int chip_id,
|
||||||
|
int config1, int convrate)
|
||||||
|
{
|
||||||
|
int address = client->addr;
|
||||||
|
const char *name = NULL;
|
||||||
|
|
||||||
|
if ((address == 0x4c || address == 0x4d) && chip_id == 0x01 &&
|
||||||
|
!(config1 & 0x3f) && convrate <= 0x08)
|
||||||
|
name = "g781";
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *lm90_detect_ti(struct i2c_client *client, int chip_id,
|
||||||
|
int config1, int convrate)
|
||||||
|
{
|
||||||
|
int address = client->addr;
|
||||||
|
const char *name = NULL;
|
||||||
|
|
||||||
|
if (chip_id == 0x00 && !(config1 & 0x1b) && convrate <= 0x09) {
|
||||||
int local_ext, conalert, chen, dfc;
|
int local_ext, conalert, chen, dfc;
|
||||||
|
|
||||||
local_ext = i2c_smbus_read_byte_data(client,
|
local_ext = i2c_smbus_read_byte_data(client,
|
||||||
@ -1702,10 +1750,8 @@ static int lm90_detect(struct i2c_client *client,
|
|||||||
chen = i2c_smbus_read_byte_data(client, TMP461_REG_CHEN);
|
chen = i2c_smbus_read_byte_data(client, TMP461_REG_CHEN);
|
||||||
dfc = i2c_smbus_read_byte_data(client, TMP461_REG_DFC);
|
dfc = i2c_smbus_read_byte_data(client, TMP461_REG_DFC);
|
||||||
|
|
||||||
if ((local_ext & 0x0F) == 0x00 &&
|
if (!(local_ext & 0x0f) && (conalert & 0xf1) == 0x01 &&
|
||||||
(conalert & 0xf1) == 0x01 &&
|
(chen & 0xfc) == 0x00 && (dfc & 0xfc) == 0x00) {
|
||||||
(chen & 0xfc) == 0x00 &&
|
|
||||||
(dfc & 0xfc) == 0x00) {
|
|
||||||
if (address == 0x4c && !(chen & 0x03))
|
if (address == 0x4c && !(chen & 0x03))
|
||||||
name = "tmp451";
|
name = "tmp451";
|
||||||
else if (address >= 0x48 && address <= 0x4f)
|
else if (address >= 0x48 && address <= 0x4f)
|
||||||
@ -1713,10 +1759,57 @@ static int lm90_detect(struct i2c_client *client,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!name) { /* identification failed */
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return 0 if detection is successful, -ENODEV otherwise */
|
||||||
|
static int lm90_detect(struct i2c_client *client, struct i2c_board_info *info)
|
||||||
|
{
|
||||||
|
struct i2c_adapter *adapter = client->adapter;
|
||||||
|
int man_id, chip_id, config1, convrate;
|
||||||
|
const char *name = NULL;
|
||||||
|
|
||||||
|
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
/* detection and identification */
|
||||||
|
man_id = i2c_smbus_read_byte_data(client, LM90_REG_MAN_ID);
|
||||||
|
chip_id = i2c_smbus_read_byte_data(client, LM90_REG_CHIP_ID);
|
||||||
|
config1 = i2c_smbus_read_byte_data(client, LM90_REG_CONFIG1);
|
||||||
|
convrate = i2c_smbus_read_byte_data(client, LM90_REG_CONVRATE);
|
||||||
|
if (man_id < 0 || chip_id < 0 || config1 < 0 || convrate < 0)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
switch (man_id) {
|
||||||
|
case 0x01: /* National Semiconductor */
|
||||||
|
name = lm90_detect_national(client, chip_id, config1, convrate);
|
||||||
|
break;
|
||||||
|
case 0x41: /* Analog Devices */
|
||||||
|
name = lm90_detect_analog(client, chip_id, config1, convrate);
|
||||||
|
break;
|
||||||
|
case 0x47: /* GMT */
|
||||||
|
name = lm90_detect_gmt(client, chip_id, config1, convrate);
|
||||||
|
break;
|
||||||
|
case 0x4d: /* Maxim Integrated */
|
||||||
|
name = lm90_detect_maxim(client, chip_id, config1, convrate);
|
||||||
|
break;
|
||||||
|
case 0x55: /* TI */
|
||||||
|
name = lm90_detect_ti(client, chip_id, config1, convrate);
|
||||||
|
break;
|
||||||
|
case 0x5c: /* Winbond/Nuvoton */
|
||||||
|
name = lm90_detect_nuvoton(client, chip_id, config1, convrate);
|
||||||
|
break;
|
||||||
|
case 0xa1: /* NXP Semiconductor/Philips */
|
||||||
|
name = lm90_detect_nxp(client, chip_id, config1, convrate);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!name) { /* identification failed */
|
||||||
dev_dbg(&adapter->dev,
|
dev_dbg(&adapter->dev,
|
||||||
"Unsupported chip at 0x%02x (man_id=0x%02X, "
|
"Unsupported chip at 0x%02x (man_id=0x%02X, chip_id=0x%02X)\n",
|
||||||
"chip_id=0x%02X)\n", address, man_id, chip_id);
|
client->addr, man_id, chip_id);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user