Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2be381de authored by Jean Delvare's avatar Jean Delvare Committed by Jean Delvare
Browse files

hwmon: (w83795) Improve detection routine



Check for additional identification registers. Improve debugging
messages on failed detection.

Signed-off-by: default avatarJean Delvare <khali@linux-fr.org>
parent b2469f42
Loading
Loading
Loading
Loading
+57 −23
Original line number Original line Diff line number Diff line
@@ -48,6 +48,7 @@ MODULE_PARM_DESC(reset, "Set to 1 to reset chip, not recommended");
#define W83795_REG_VENDORID		0xfd
#define W83795_REG_VENDORID		0xfd
#define W83795_REG_CHIPID		0xfe
#define W83795_REG_CHIPID		0xfe
#define W83795_REG_DEVICEID		0xfb
#define W83795_REG_DEVICEID		0xfb
#define W83795_REG_DEVICEID_A		0xff


#define W83795_REG_I2C_ADDR		0xfc
#define W83795_REG_I2C_ADDR		0xfc
#define W83795_REG_CONFIG		0x01
#define W83795_REG_CONFIG		0x01
@@ -1684,11 +1685,31 @@ static void w83795_init_client(struct i2c_client *client)
		     w83795_read(client, W83795_REG_CONFIG) | 0x01);
		     w83795_read(client, W83795_REG_CONFIG) | 0x01);
}
}


static int w83795_get_device_id(struct i2c_client *client)
{
	int device_id;

	device_id = i2c_smbus_read_byte_data(client, W83795_REG_DEVICEID);

	/* Special case for rev. A chips; can't be checked first because later
	   revisions emulate this for compatibility */
	if (device_id < 0 || (device_id & 0xf0) != 0x50) {
		int alt_id;

		alt_id = i2c_smbus_read_byte_data(client,
						  W83795_REG_DEVICEID_A);
		if (alt_id == 0x50)
			device_id = alt_id;
	}

	return device_id;
}

/* Return 0 if detection is successful, -ENODEV otherwise */
/* Return 0 if detection is successful, -ENODEV otherwise */
static int w83795_detect(struct i2c_client *client,
static int w83795_detect(struct i2c_client *client,
			 struct i2c_board_info *info)
			 struct i2c_board_info *info)
{
{
	u8 tmp, bank;
	int bank, vendor_id, device_id, expected, i2c_addr, config;
	struct i2c_adapter *adapter = client->adapter;
	struct i2c_adapter *adapter = client->adapter;
	unsigned short address = client->addr;
	unsigned short address = client->addr;
	const char *chip_name;
	const char *chip_name;
@@ -1696,33 +1717,45 @@ static int w83795_detect(struct i2c_client *client,
	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
		return -ENODEV;
		return -ENODEV;
	bank = i2c_smbus_read_byte_data(client, W83795_REG_BANKSEL);
	bank = i2c_smbus_read_byte_data(client, W83795_REG_BANKSEL);
	if (bank < 0 || (bank & 0x7c)) {
		dev_dbg(&adapter->dev,
			"w83795: Detection failed at addr 0x%02hx, check %s\n",
			address, "bank");
		return -ENODEV;
	}


	tmp = bank & 0x80 ? 0x5c : 0xa3;
	/* Check Nuvoton vendor ID */
	/* Check Nuvoton vendor ID */
	if (tmp != i2c_smbus_read_byte_data(client,
	vendor_id = i2c_smbus_read_byte_data(client, W83795_REG_VENDORID);
						W83795_REG_VENDORID)) {
	expected = bank & 0x80 ? 0x5c : 0xa3;
		pr_debug("w83795: Detection failed at check "
	if (vendor_id != expected) {
			 "vendor id\n");
		dev_dbg(&adapter->dev,
			"w83795: Detection failed at addr 0x%02hx, check %s\n",
			address, "vendor id");
		return -ENODEV;
		return -ENODEV;
	}
	}


	/* If Nuvoton chip, address of chip and W83795_REG_I2C_ADDR
	/* Check device ID */
	   should match */
	device_id = w83795_get_device_id(client) |
	if ((bank & 0x07) == 0
		    (i2c_smbus_read_byte_data(client, W83795_REG_CHIPID) << 8);
	 && (i2c_smbus_read_byte_data(client, W83795_REG_I2C_ADDR) & 0x7f) !=
	if ((device_id >> 4) != 0x795) {
	    address) {
		dev_dbg(&adapter->dev,
		pr_debug("w83795: Detection failed at check "
			"w83795: Detection failed at addr 0x%02hx, check %s\n",
			 "i2c addr\n");
			address, "device id\n");
		return -ENODEV;
		return -ENODEV;
	}
	}


	/* Determine the chip type now */
	/* If Nuvoton chip, address of chip and W83795_REG_I2C_ADDR
	if (0x79 != i2c_smbus_read_byte_data(client,
	   should match */
					     W83795_REG_CHIPID)) {
	if ((bank & 0x07) == 0) {
		pr_debug("w83795: Detection failed at check "
		i2c_addr = i2c_smbus_read_byte_data(client,
			 "chip id\n");
						    W83795_REG_I2C_ADDR);
		if ((i2c_addr & 0x7f) != address) {
			dev_dbg(&adapter->dev,
				"w83795: Detection failed at addr 0x%02hx, "
				"check %s\n", address, "i2c addr");
			return -ENODEV;
			return -ENODEV;
		}
		}
	}


	/* Check 795 chip type: 795G or 795ADG
	/* Check 795 chip type: 795G or 795ADG
	   Usually we don't write to chips during detection, but here we don't
	   Usually we don't write to chips during detection, but here we don't
@@ -1731,14 +1764,15 @@ static int w83795_detect(struct i2c_client *client,
	if ((bank & 0x07) != 0)
	if ((bank & 0x07) != 0)
		i2c_smbus_write_byte_data(client, W83795_REG_BANKSEL,
		i2c_smbus_write_byte_data(client, W83795_REG_BANKSEL,
					  bank & ~0x07);
					  bank & ~0x07);
	if (W83795_REG_CONFIG_CONFIG48 &
	config = i2c_smbus_read_byte_data(client, W83795_REG_CONFIG);
		  i2c_smbus_read_byte_data(client, W83795_REG_CONFIG)) {
	if (config & W83795_REG_CONFIG_CONFIG48)
		chip_name = "w83795adg";
		chip_name = "w83795adg";
	} else {
	else
		chip_name = "w83795g";
		chip_name = "w83795g";
	}


	strlcpy(info->type, chip_name, I2C_NAME_SIZE);
	strlcpy(info->type, chip_name, I2C_NAME_SIZE);
	dev_info(&adapter->dev, "Found %s rev. %c at 0x%02hx\n", chip_name,
		 'A' + (device_id & 0xf), address);


	return 0;
	return 0;
}
}