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

Commit 16c6d01f authored by Guenter Roeck's avatar Guenter Roeck
Browse files

hwmon: (pmbus) Add support for word status register



Not all PMBus devices support the byte status register at 0x78.
Try to use the word status register at 0x79 instead if that is the case.

Signed-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
parent 1640eaec
Loading
Loading
Loading
Loading
+52 −28
Original line number Diff line number Diff line
@@ -109,6 +109,7 @@ struct pmbus_data {
	 * so we keep them all together.
	 */
	u8 status[PB_NUM_STATUS_REG];
	u8 status_register;

	u8 currpage;
};
@@ -285,9 +286,10 @@ EXPORT_SYMBOL_GPL(pmbus_clear_faults);

static int pmbus_check_status_cml(struct i2c_client *client)
{
	struct pmbus_data *data = i2c_get_clientdata(client);
	int status, status2;

	status = _pmbus_read_byte_data(client, -1, PMBUS_STATUS_BYTE);
	status = _pmbus_read_byte_data(client, -1, data->status_register);
	if (status < 0 || (status & PB_STATUS_CML)) {
		status2 = _pmbus_read_byte_data(client, -1, PMBUS_STATUS_CML);
		if (status2 < 0 || (status2 & PB_CML_FAULT_INVALID_COMMAND))
@@ -344,7 +346,7 @@ static struct pmbus_data *pmbus_update_device(struct device *dev)
		for (i = 0; i < info->pages; i++)
			data->status[PB_STATUS_BASE + i]
			    = _pmbus_read_byte_data(client, i,
						    PMBUS_STATUS_BYTE);
						    data->status_register);
		for (i = 0; i < info->pages; i++) {
			if (!(info->func[i] & PMBUS_HAVE_STATUS_VOUT))
				continue;
@@ -1015,7 +1017,7 @@ static int pmbus_add_sensor_attrs_one(struct i2c_client *client,
		 */
		if (!ret && attr->gbit &&
		    pmbus_check_byte_register(client, page,
					      PMBUS_STATUS_BYTE)) {
					      data->status_register)) {
			ret = pmbus_add_boolean(data, name, "alarm", index,
						NULL, NULL,
						PB_STATUS_BASE + page,
@@ -1683,39 +1685,27 @@ static int pmbus_identify_common(struct i2c_client *client,
	return 0;
}

int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data,
			     struct pmbus_driver_info *info)
{
	struct device *dev = &client->dev;
	const struct pmbus_platform_data *pdata = dev->platform_data;
	struct pmbus_data *data;
	int ret;

	if (!info)
		return -ENODEV;

	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE
				     | I2C_FUNC_SMBUS_BYTE_DATA
				     | I2C_FUNC_SMBUS_WORD_DATA))
		return -ENODEV;

	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	i2c_set_clientdata(client, data);
	mutex_init(&data->update_lock);
	data->dev = dev;

	/* Bail out if PMBus status register does not exist. */
	if (i2c_smbus_read_byte_data(client, PMBUS_STATUS_BYTE) < 0) {
	/*
	 * Some PMBus chips don't support PMBUS_STATUS_BYTE, so try
	 * to use PMBUS_STATUS_WORD instead if that is the case.
	 * Bail out if both registers are not supported.
	 */
	data->status_register = PMBUS_STATUS_BYTE;
	ret = i2c_smbus_read_byte_data(client, PMBUS_STATUS_BYTE);
	if (ret < 0 || ret == 0xff) {
		data->status_register = PMBUS_STATUS_WORD;
		ret = i2c_smbus_read_word_data(client, PMBUS_STATUS_WORD);
		if (ret < 0 || ret == 0xffff) {
			dev_err(dev, "PMBus status register not found\n");
			return -ENODEV;
		}

	if (pdata)
		data->flags = pdata->flags;
	data->info = info;
	}

	pmbus_clear_faults(client);

@@ -1737,6 +1727,40 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
		dev_err(dev, "Failed to identify chip capabilities\n");
		return ret;
	}
	return 0;
}

int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
		   struct pmbus_driver_info *info)
{
	struct device *dev = &client->dev;
	const struct pmbus_platform_data *pdata = dev->platform_data;
	struct pmbus_data *data;
	int ret;

	if (!info)
		return -ENODEV;

	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE
				     | I2C_FUNC_SMBUS_BYTE_DATA
				     | I2C_FUNC_SMBUS_WORD_DATA))
		return -ENODEV;

	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	i2c_set_clientdata(client, data);
	mutex_init(&data->update_lock);
	data->dev = dev;

	if (pdata)
		data->flags = pdata->flags;
	data->info = info;

	ret = pmbus_init_common(client, data, info);
	if (ret < 0)
		return ret;

	ret = pmbus_find_attributes(client, data);
	if (ret)