Commit 19932f84 authored by Alexis Czezar Torreno's avatar Alexis Czezar Torreno Committed by Guenter Roeck
Browse files

hwmon: (pmbus/max34440) Fix support for max34451



The max344** family has an issue with some PMBUS address being switched.
This includes max34451 however version MAX34451-NA6 and later has this
issue fixed and this commit supports that update.

Signed-off-by: default avatarAlexis Czezar Torreno <alexisczezar.torreno@analog.com>
Link: https://lore.kernel.org/r/20250407-dev_adpm12160-v3-1-9cd3095445c8@analog.com


Signed-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
parent 9c47e45d
Loading
Loading
Loading
Loading
+44 −4
Original line number Diff line number Diff line
@@ -34,16 +34,21 @@ enum chips { max34440, max34441, max34446, max34451, max34460, max34461 };
/*
 * The whole max344* family have IOUT_OC_WARN_LIMIT and IOUT_OC_FAULT_LIMIT
 * swapped from the standard pmbus spec addresses.
 * For max34451, version MAX34451ETNA6+ and later has this issue fixed.
 */
#define MAX34440_IOUT_OC_WARN_LIMIT	0x46
#define MAX34440_IOUT_OC_FAULT_LIMIT	0x4A

#define MAX34451ETNA6_MFR_REV		0x0012

#define MAX34451_MFR_CHANNEL_CONFIG	0xe4
#define MAX34451_MFR_CHANNEL_CONFIG_SEL_MASK	0x3f

struct max34440_data {
	int id;
	struct pmbus_driver_info info;
	u8 iout_oc_warn_limit;
	u8 iout_oc_fault_limit;
};

#define to_max34440_data(x)  container_of(x, struct max34440_data, info)
@@ -60,11 +65,11 @@ static int max34440_read_word_data(struct i2c_client *client, int page,
	switch (reg) {
	case PMBUS_IOUT_OC_FAULT_LIMIT:
		ret = pmbus_read_word_data(client, page, phase,
					   MAX34440_IOUT_OC_FAULT_LIMIT);
					   data->iout_oc_fault_limit);
		break;
	case PMBUS_IOUT_OC_WARN_LIMIT:
		ret = pmbus_read_word_data(client, page, phase,
					   MAX34440_IOUT_OC_WARN_LIMIT);
					   data->iout_oc_warn_limit);
		break;
	case PMBUS_VIRT_READ_VOUT_MIN:
		ret = pmbus_read_word_data(client, page, phase,
@@ -133,11 +138,11 @@ static int max34440_write_word_data(struct i2c_client *client, int page,

	switch (reg) {
	case PMBUS_IOUT_OC_FAULT_LIMIT:
		ret = pmbus_write_word_data(client, page, MAX34440_IOUT_OC_FAULT_LIMIT,
		ret = pmbus_write_word_data(client, page, data->iout_oc_fault_limit,
					    word);
		break;
	case PMBUS_IOUT_OC_WARN_LIMIT:
		ret = pmbus_write_word_data(client, page, MAX34440_IOUT_OC_WARN_LIMIT,
		ret = pmbus_write_word_data(client, page, data->iout_oc_warn_limit,
					    word);
		break;
	case PMBUS_VIRT_RESET_POUT_HISTORY:
@@ -235,6 +240,25 @@ static int max34451_set_supported_funcs(struct i2c_client *client,
	 */

	int page, rv;
	bool max34451_na6 = false;

	rv = i2c_smbus_read_word_data(client, PMBUS_MFR_REVISION);
	if (rv < 0)
		return rv;

	if (rv >= MAX34451ETNA6_MFR_REV) {
		max34451_na6 = true;
		data->info.format[PSC_VOLTAGE_IN] = direct;
		data->info.format[PSC_CURRENT_IN] = direct;
		data->info.m[PSC_VOLTAGE_IN] = 1;
		data->info.b[PSC_VOLTAGE_IN] = 0;
		data->info.R[PSC_VOLTAGE_IN] = 3;
		data->info.m[PSC_CURRENT_IN] = 1;
		data->info.b[PSC_CURRENT_IN] = 0;
		data->info.R[PSC_CURRENT_IN] = 2;
		data->iout_oc_fault_limit = PMBUS_IOUT_OC_FAULT_LIMIT;
		data->iout_oc_warn_limit = PMBUS_IOUT_OC_WARN_LIMIT;
	}

	for (page = 0; page < 16; page++) {
		rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page);
@@ -251,16 +275,30 @@ static int max34451_set_supported_funcs(struct i2c_client *client,
		case 0x20:
			data->info.func[page] = PMBUS_HAVE_VOUT |
				PMBUS_HAVE_STATUS_VOUT;

			if (max34451_na6)
				data->info.func[page] |= PMBUS_HAVE_VIN |
					PMBUS_HAVE_STATUS_INPUT;
			break;
		case 0x21:
			data->info.func[page] = PMBUS_HAVE_VOUT;

			if (max34451_na6)
				data->info.func[page] |= PMBUS_HAVE_VIN;
			break;
		case 0x22:
			data->info.func[page] = PMBUS_HAVE_IOUT |
				PMBUS_HAVE_STATUS_IOUT;

			if (max34451_na6)
				data->info.func[page] |= PMBUS_HAVE_IIN |
					PMBUS_HAVE_STATUS_INPUT;
			break;
		case 0x23:
			data->info.func[page] = PMBUS_HAVE_IOUT;

			if (max34451_na6)
				data->info.func[page] |= PMBUS_HAVE_IIN;
			break;
		default:
			break;
@@ -494,6 +532,8 @@ static int max34440_probe(struct i2c_client *client)
		return -ENOMEM;
	data->id = i2c_match_id(max34440_id, client)->driver_data;
	data->info = max34440_info[data->id];
	data->iout_oc_fault_limit = MAX34440_IOUT_OC_FAULT_LIMIT;
	data->iout_oc_warn_limit = MAX34440_IOUT_OC_WARN_LIMIT;

	if (data->id == max34451) {
		rv = max34451_set_supported_funcs(client, data);