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

Commit cbcdec62 authored by Edward A. James's avatar Edward A. James Committed by Guenter Roeck
Browse files

hwmon: (pmbus): Access word data for STATUS_WORD



Pmbus always reads byte data from the status register, even if
configured to use STATUS_WORD. Use a function pointer to read the
correct amount of data from the registers.
Also switch to try STATUS_WORD first before STATUS_BYTE on init.

Signed-off-by: default avatarEdward A. James <eajames@us.ibm.com>
Signed-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
parent a66a6eb9
Loading
Loading
Loading
Loading
+40 −14
Original line number Diff line number Diff line
@@ -113,7 +113,8 @@ struct pmbus_data {
	 * so we keep them all together.
	 */
	u16 status[PB_NUM_STATUS_REG];
	u8 status_register;

	int (*read_status)(struct i2c_client *client, int page);

	u8 currpage;
};
@@ -324,7 +325,7 @@ 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, data->status_register);
	status = data->read_status(client, -1);
	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))
@@ -348,6 +349,23 @@ static bool pmbus_check_register(struct i2c_client *client,
	return rv >= 0;
}

static bool pmbus_check_status_register(struct i2c_client *client, int page)
{
	int status;
	struct pmbus_data *data = i2c_get_clientdata(client);

	status = data->read_status(client, page);
	if (status >= 0 && !(data->flags & PMBUS_SKIP_STATUS_CHECK) &&
	    (status & PB_STATUS_CML)) {
		status = _pmbus_read_byte_data(client, -1, PMBUS_STATUS_CML);
		if (status < 0 || (status & PB_CML_FAULT_INVALID_COMMAND))
			status = -EIO;
	}

	pmbus_clear_fault_page(client, -1);
	return status >= 0;
}

bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg)
{
	return pmbus_check_register(client, _pmbus_read_byte_data, page, reg);
@@ -394,8 +412,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,
						    data->status_register);
			    = data->read_status(client, i);
			for (j = 0; j < ARRAY_SIZE(pmbus_status); j++) {
				struct _pmbus_status *s = &pmbus_status[j];

@@ -1051,8 +1068,7 @@ static int pmbus_add_sensor_attrs_one(struct i2c_client *client,
		 * the generic status register for this page is accessible.
		 */
		if (!ret && attr->gbit &&
		    pmbus_check_byte_register(client, page,
					      data->status_register)) {
		    pmbus_check_status_register(client, page)) {
			ret = pmbus_add_boolean(data, name, "alarm", index,
						NULL, NULL,
						PB_STATUS_BASE + page,
@@ -1729,6 +1745,16 @@ static int pmbus_identify_common(struct i2c_client *client,
	return 0;
}

static int pmbus_read_status_byte(struct i2c_client *client, int page)
{
	return _pmbus_read_byte_data(client, page, PMBUS_STATUS_BYTE);
}

static int pmbus_read_status_word(struct i2c_client *client, int page)
{
	return _pmbus_read_word_data(client, page, PMBUS_STATUS_WORD);
}

static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data,
			     struct pmbus_driver_info *info)
{
@@ -1736,16 +1762,16 @@ static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data,
	int page, ret;

	/*
	 * Some PMBus chips don't support PMBUS_STATUS_BYTE, so try
	 * to use PMBUS_STATUS_WORD instead if that is the case.
	 * Some PMBus chips don't support PMBUS_STATUS_WORD, so try
	 * to use PMBUS_STATUS_BYTE 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;
	data->read_status = pmbus_read_status_word;
	ret = i2c_smbus_read_word_data(client, PMBUS_STATUS_WORD);
	if (ret < 0 || ret == 0xffff) {
		data->read_status = pmbus_read_status_byte;
		ret = i2c_smbus_read_byte_data(client, PMBUS_STATUS_BYTE);
		if (ret < 0 || ret == 0xff) {
			dev_err(dev, "PMBus status register not found\n");
			return -ENODEV;
		}