Commit 98ac8af4 authored by Guenter Roeck's avatar Guenter Roeck
Browse files

hwmon: (pmbus/adm1275) Prepare for protected write to PMON_CONFIG



According to ADI, changing PMON_CONFIG while ADC is running can have
unexpected results. ADI recommends halting the ADC with PMON_CONTROL
before setting PMON_CONFIG and then resume after.

To prepare for this change, rename adm1275_read_pmon_config()
and adm1275_write_pmon_config() to adm1275_read_samples() and
adm1275_write_samples() to more accurately reflect the functionality
of the code. Introduce new function adm1275_write_pmon_config()
and use it for all code writing into the PMON_CONFIG register.

Signed-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
Link: https://lore.kernel.org/r/20230614163605.3688964-2-linux@roeck-us.net


Signed-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
parent 37f665ff
Loading
Loading
Loading
Loading
+31 −25
Original line number Diff line number Diff line
@@ -173,7 +173,7 @@ static const struct coefficients adm1293_coefficients[] = {
	[18] = { 7658, 0, -3 },		/* power, 21V, irange200 */
};

static int adm1275_read_pmon_config(const struct adm1275_data *data,
static int adm1275_read_samples(const struct adm1275_data *data,
				struct i2c_client *client, bool is_power)
{
	int shift, ret;
@@ -200,6 +200,21 @@ static int adm1275_read_pmon_config(const struct adm1275_data *data,
}

static int adm1275_write_pmon_config(const struct adm1275_data *data,
				     struct i2c_client *client, u16 word)
{
	int ret;

	if (data->have_power_sampling)
		ret = i2c_smbus_write_word_data(client, ADM1275_PMON_CONFIG,
						word);
	else
		ret = i2c_smbus_write_byte_data(client, ADM1275_PMON_CONFIG,
						word);

	return ret;
}

static int adm1275_write_samples(const struct adm1275_data *data,
				 struct i2c_client *client,
				 bool is_power, u16 word)
{
@@ -219,14 +234,8 @@ static int adm1275_write_pmon_config(const struct adm1275_data *data,
		return ret;

	word = (ret & ~mask) | ((word << shift) & mask);
	if (data->have_power_sampling)
		ret = i2c_smbus_write_word_data(client, ADM1275_PMON_CONFIG,
						word);
	else
		ret = i2c_smbus_write_byte_data(client, ADM1275_PMON_CONFIG,
						word);

	return ret;
	return adm1275_write_pmon_config(data, client, word);
}

static int adm1275_read_word_data(struct i2c_client *client, int page,
@@ -321,14 +330,14 @@ static int adm1275_read_word_data(struct i2c_client *client, int page,
	case PMBUS_VIRT_POWER_SAMPLES:
		if (!data->have_power_sampling)
			return -ENXIO;
		ret = adm1275_read_pmon_config(data, client, true);
		ret = adm1275_read_samples(data, client, true);
		if (ret < 0)
			break;
		ret = BIT(ret);
		break;
	case PMBUS_VIRT_IN_SAMPLES:
	case PMBUS_VIRT_CURR_SAMPLES:
		ret = adm1275_read_pmon_config(data, client, false);
		ret = adm1275_read_samples(data, client, false);
		if (ret < 0)
			break;
		ret = BIT(ret);
@@ -381,14 +390,12 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg,
		if (!data->have_power_sampling)
			return -ENXIO;
		word = clamp_val(word, 1, ADM1275_SAMPLES_AVG_MAX);
		ret = adm1275_write_pmon_config(data, client, true,
						ilog2(word));
		ret = adm1275_write_samples(data, client, true, ilog2(word));
		break;
	case PMBUS_VIRT_IN_SAMPLES:
	case PMBUS_VIRT_CURR_SAMPLES:
		word = clamp_val(word, 1, ADM1275_SAMPLES_AVG_MAX);
		ret = adm1275_write_pmon_config(data, client, false,
						ilog2(word));
		ret = adm1275_write_samples(data, client, false, ilog2(word));
		break;
	default:
		ret = -ENODATA;
@@ -466,13 +473,14 @@ static const struct i2c_device_id adm1275_id[] = {
MODULE_DEVICE_TABLE(i2c, adm1275_id);

/* Enable VOUT & TEMP1 if not enabled (disabled by default) */
static int adm1275_enable_vout_temp(struct i2c_client *client, int config)
static int adm1275_enable_vout_temp(struct adm1275_data *data,
				    struct i2c_client *client, int config)
{
	int ret;

	if ((config & ADM1278_PMON_DEFCONFIG) != ADM1278_PMON_DEFCONFIG) {
		config |= ADM1278_PMON_DEFCONFIG;
		ret = i2c_smbus_write_word_data(client, ADM1275_PMON_CONFIG, config);
		ret = adm1275_write_pmon_config(data, client, config);
		if (ret < 0) {
			dev_err(&client->dev, "Failed to enable VOUT/TEMP1 monitoring\n");
			return ret;
@@ -634,7 +642,7 @@ static int adm1275_probe(struct i2c_client *client)
			PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
			PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;

		ret = adm1275_enable_vout_temp(client, config);
		ret = adm1275_enable_vout_temp(data, client, config);
		if (ret)
			return ret;

@@ -694,7 +702,7 @@ static int adm1275_probe(struct i2c_client *client)
			PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
			PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;

		ret = adm1275_enable_vout_temp(client, config);
		ret = adm1275_enable_vout_temp(data, client, config);
		if (ret)
			return ret;

@@ -766,8 +774,7 @@ static int adm1275_probe(struct i2c_client *client)
				"Invalid number of power samples");
			return -EINVAL;
		}
		ret = adm1275_write_pmon_config(data, client, true,
						ilog2(avg));
		ret = adm1275_write_samples(data, client, true, ilog2(avg));
		if (ret < 0) {
			dev_err(&client->dev,
				"Setting power sample averaging failed with error %d",
@@ -784,8 +791,7 @@ static int adm1275_probe(struct i2c_client *client)
				"Invalid number of voltage/current samples");
			return -EINVAL;
		}
		ret = adm1275_write_pmon_config(data, client, false,
						ilog2(avg));
		ret = adm1275_write_samples(data, client, false, ilog2(avg));
		if (ret < 0) {
			dev_err(&client->dev,
				"Setting voltage and current sample averaging failed with error %d",