diff options
author | Jean Delvare <khali@linux-fr.org> | 2010-10-28 14:31:45 -0400 |
---|---|---|
committer | Jean Delvare <khali@endymion.delvare> | 2010-10-28 14:31:45 -0400 |
commit | 2be381de0f1e5e0324e8b373e7a84fc9d25d05d3 (patch) | |
tree | 5211865f27cc643d7ec3c867a668740d66a48b60 | |
parent | b2469f422f9ee2054359c4ec609c3bdb1f2d52f5 (diff) |
hwmon: (w83795) Improve detection routine
Check for additional identification registers. Improve debugging
messages on failed detection.
Signed-off-by: Jean Delvare <khali@linux-fr.org>
-rw-r--r-- | drivers/hwmon/w83795.c | 80 |
1 files changed, 57 insertions, 23 deletions
diff --git a/drivers/hwmon/w83795.c b/drivers/hwmon/w83795.c index c7f6b1fd0899..6596303566e1 100644 --- a/drivers/hwmon/w83795.c +++ b/drivers/hwmon/w83795.c | |||
@@ -48,6 +48,7 @@ MODULE_PARM_DESC(reset, "Set to 1 to reset chip, not recommended"); | |||
48 | #define W83795_REG_VENDORID 0xfd | 48 | #define W83795_REG_VENDORID 0xfd |
49 | #define W83795_REG_CHIPID 0xfe | 49 | #define W83795_REG_CHIPID 0xfe |
50 | #define W83795_REG_DEVICEID 0xfb | 50 | #define W83795_REG_DEVICEID 0xfb |
51 | #define W83795_REG_DEVICEID_A 0xff | ||
51 | 52 | ||
52 | #define W83795_REG_I2C_ADDR 0xfc | 53 | #define W83795_REG_I2C_ADDR 0xfc |
53 | #define W83795_REG_CONFIG 0x01 | 54 | #define W83795_REG_CONFIG 0x01 |
@@ -1684,11 +1685,31 @@ static void w83795_init_client(struct i2c_client *client) | |||
1684 | w83795_read(client, W83795_REG_CONFIG) | 0x01); | 1685 | w83795_read(client, W83795_REG_CONFIG) | 0x01); |
1685 | } | 1686 | } |
1686 | 1687 | ||
1688 | static int w83795_get_device_id(struct i2c_client *client) | ||
1689 | { | ||
1690 | int device_id; | ||
1691 | |||
1692 | device_id = i2c_smbus_read_byte_data(client, W83795_REG_DEVICEID); | ||
1693 | |||
1694 | /* Special case for rev. A chips; can't be checked first because later | ||
1695 | revisions emulate this for compatibility */ | ||
1696 | if (device_id < 0 || (device_id & 0xf0) != 0x50) { | ||
1697 | int alt_id; | ||
1698 | |||
1699 | alt_id = i2c_smbus_read_byte_data(client, | ||
1700 | W83795_REG_DEVICEID_A); | ||
1701 | if (alt_id == 0x50) | ||
1702 | device_id = alt_id; | ||
1703 | } | ||
1704 | |||
1705 | return device_id; | ||
1706 | } | ||
1707 | |||
1687 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 1708 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
1688 | static int w83795_detect(struct i2c_client *client, | 1709 | static int w83795_detect(struct i2c_client *client, |
1689 | struct i2c_board_info *info) | 1710 | struct i2c_board_info *info) |
1690 | { | 1711 | { |
1691 | u8 tmp, bank; | 1712 | int bank, vendor_id, device_id, expected, i2c_addr, config; |
1692 | struct i2c_adapter *adapter = client->adapter; | 1713 | struct i2c_adapter *adapter = client->adapter; |
1693 | unsigned short address = client->addr; | 1714 | unsigned short address = client->addr; |
1694 | const char *chip_name; | 1715 | const char *chip_name; |
@@ -1696,32 +1717,44 @@ static int w83795_detect(struct i2c_client *client, | |||
1696 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 1717 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
1697 | return -ENODEV; | 1718 | return -ENODEV; |
1698 | bank = i2c_smbus_read_byte_data(client, W83795_REG_BANKSEL); | 1719 | bank = i2c_smbus_read_byte_data(client, W83795_REG_BANKSEL); |
1720 | if (bank < 0 || (bank & 0x7c)) { | ||
1721 | dev_dbg(&adapter->dev, | ||
1722 | "w83795: Detection failed at addr 0x%02hx, check %s\n", | ||
1723 | address, "bank"); | ||
1724 | return -ENODEV; | ||
1725 | } | ||
1699 | 1726 | ||
1700 | tmp = bank & 0x80 ? 0x5c : 0xa3; | ||
1701 | /* Check Nuvoton vendor ID */ | 1727 | /* Check Nuvoton vendor ID */ |
1702 | if (tmp != i2c_smbus_read_byte_data(client, | 1728 | vendor_id = i2c_smbus_read_byte_data(client, W83795_REG_VENDORID); |
1703 | W83795_REG_VENDORID)) { | 1729 | expected = bank & 0x80 ? 0x5c : 0xa3; |
1704 | pr_debug("w83795: Detection failed at check " | 1730 | if (vendor_id != expected) { |
1705 | "vendor id\n"); | 1731 | dev_dbg(&adapter->dev, |
1732 | "w83795: Detection failed at addr 0x%02hx, check %s\n", | ||
1733 | address, "vendor id"); | ||
1706 | return -ENODEV; | 1734 | return -ENODEV; |
1707 | } | 1735 | } |
1708 | 1736 | ||
1709 | /* If Nuvoton chip, address of chip and W83795_REG_I2C_ADDR | 1737 | /* Check device ID */ |
1710 | should match */ | 1738 | device_id = w83795_get_device_id(client) | |
1711 | if ((bank & 0x07) == 0 | 1739 | (i2c_smbus_read_byte_data(client, W83795_REG_CHIPID) << 8); |
1712 | && (i2c_smbus_read_byte_data(client, W83795_REG_I2C_ADDR) & 0x7f) != | 1740 | if ((device_id >> 4) != 0x795) { |
1713 | address) { | 1741 | dev_dbg(&adapter->dev, |
1714 | pr_debug("w83795: Detection failed at check " | 1742 | "w83795: Detection failed at addr 0x%02hx, check %s\n", |
1715 | "i2c addr\n"); | 1743 | address, "device id\n"); |
1716 | return -ENODEV; | 1744 | return -ENODEV; |
1717 | } | 1745 | } |
1718 | 1746 | ||
1719 | /* Determine the chip type now */ | 1747 | /* If Nuvoton chip, address of chip and W83795_REG_I2C_ADDR |
1720 | if (0x79 != i2c_smbus_read_byte_data(client, | 1748 | should match */ |
1721 | W83795_REG_CHIPID)) { | 1749 | if ((bank & 0x07) == 0) { |
1722 | pr_debug("w83795: Detection failed at check " | 1750 | i2c_addr = i2c_smbus_read_byte_data(client, |
1723 | "chip id\n"); | 1751 | W83795_REG_I2C_ADDR); |
1724 | return -ENODEV; | 1752 | if ((i2c_addr & 0x7f) != address) { |
1753 | dev_dbg(&adapter->dev, | ||
1754 | "w83795: Detection failed at addr 0x%02hx, " | ||
1755 | "check %s\n", address, "i2c addr"); | ||
1756 | return -ENODEV; | ||
1757 | } | ||
1725 | } | 1758 | } |
1726 | 1759 | ||
1727 | /* Check 795 chip type: 795G or 795ADG | 1760 | /* Check 795 chip type: 795G or 795ADG |
@@ -1731,14 +1764,15 @@ static int w83795_detect(struct i2c_client *client, | |||
1731 | if ((bank & 0x07) != 0) | 1764 | if ((bank & 0x07) != 0) |
1732 | i2c_smbus_write_byte_data(client, W83795_REG_BANKSEL, | 1765 | i2c_smbus_write_byte_data(client, W83795_REG_BANKSEL, |
1733 | bank & ~0x07); | 1766 | bank & ~0x07); |
1734 | if (W83795_REG_CONFIG_CONFIG48 & | 1767 | config = i2c_smbus_read_byte_data(client, W83795_REG_CONFIG); |
1735 | i2c_smbus_read_byte_data(client, W83795_REG_CONFIG)) { | 1768 | if (config & W83795_REG_CONFIG_CONFIG48) |
1736 | chip_name = "w83795adg"; | 1769 | chip_name = "w83795adg"; |
1737 | } else { | 1770 | else |
1738 | chip_name = "w83795g"; | 1771 | chip_name = "w83795g"; |
1739 | } | ||
1740 | 1772 | ||
1741 | strlcpy(info->type, chip_name, I2C_NAME_SIZE); | 1773 | strlcpy(info->type, chip_name, I2C_NAME_SIZE); |
1774 | dev_info(&adapter->dev, "Found %s rev. %c at 0x%02hx\n", chip_name, | ||
1775 | 'A' + (device_id & 0xf), address); | ||
1742 | 1776 | ||
1743 | return 0; | 1777 | return 0; |
1744 | } | 1778 | } |