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: Guenter Roeck <linux@roeck-us.net>
Link: https://lore.kernel.org/r/20230614163605.3688964-2-linux@roeck-us.net
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
This commit is contained in:
Guenter Roeck 2023-06-14 09:36:04 -07:00
parent 37f665ffa8
commit 98ac8af4e7
1 changed files with 31 additions and 25 deletions

View File

@ -173,8 +173,8 @@ static const struct coefficients adm1293_coefficients[] = {
[18] = { 7658, 0, -3 }, /* power, 21V, irange200 */
};
static int adm1275_read_pmon_config(const struct adm1275_data *data,
struct i2c_client *client, bool is_power)
static int adm1275_read_samples(const struct adm1275_data *data,
struct i2c_client *client, bool is_power)
{
int shift, ret;
u16 mask;
@ -200,8 +200,23 @@ 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,
bool is_power, u16 word)
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)
{
int shift, ret;
u16 mask;
@ -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",