Commit c83529c1 authored by Adamski, Krzysztof (Nokia - PL/Wroclaw)'s avatar Adamski, Krzysztof (Nokia - PL/Wroclaw) Committed by Guenter Roeck
Browse files

hwmon: (pmbus/adm1275) support PMBUS_VIRT_*_SAMPLES



The device supports setting the number of samples for averaging the
measurements. There are two separate settings - PWR_AVG for averaging
PIN and VI_AVG for averaging VIN/VAUX/IOUT, both being part of
PMON_CONFIG register. The values are stored as exponent of base 2 of the
actual number of samples that will be taken.

Signed-off-by: default avatarKrzysztof Adamski <krzysztof.adamski@nokia.com>
Reviewed-by: default avatarAlexander Sverdlin <alexander.sverdlin@nokia.com>
[groeck: Dropped unused variables]
Signed-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
parent 5696e4aa
Loading
Loading
Loading
Loading
+58 −1
Original line number Diff line number Diff line
@@ -14,6 +14,8 @@
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/bitops.h>
#include <linux/bitfield.h>
#include <linux/log2.h>
#include "pmbus.h"

enum chips { adm1075, adm1272, adm1275, adm1276, adm1278, adm1293, adm1294 };
@@ -69,6 +71,10 @@ enum chips { adm1075, adm1272, adm1275, adm1276, adm1278, adm1293, adm1294 };
#define ADM1075_VAUX_OV_WARN		BIT(7)
#define ADM1075_VAUX_UV_WARN		BIT(6)

#define ADM1275_PWR_AVG_MASK		GENMASK(13, 11)
#define ADM1275_VI_AVG_MASK		GENMASK(10, 8)
#define ADM1275_SAMPLES_AVG_MAX	128

struct adm1275_data {
	int id;
	bool have_oc_fault;
@@ -155,6 +161,32 @@ static const struct coefficients adm1293_coefficients[] = {
	[18] = { 7658, 0, -3 },		/* power, 21V, irange200 */
};

static inline int adm1275_read_pmon_config(struct i2c_client *client, u16 mask)
{
	int ret;

	ret = i2c_smbus_read_word_data(client, ADM1275_PMON_CONFIG);
	if (ret < 0)
		return ret;

	return FIELD_GET(mask, (u16)ret);
}

static inline int adm1275_write_pmon_config(struct i2c_client *client, u16 mask,
					    u16 word)
{
	int ret;

	ret = i2c_smbus_read_word_data(client, ADM1275_PMON_CONFIG);
	if (ret < 0)
		return ret;

	word = FIELD_PREP(mask, word) | (ret & ~mask);
	ret = i2c_smbus_write_word_data(client, ADM1275_PMON_CONFIG, word);

	return ret;
}

static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
{
	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
@@ -233,6 +265,19 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
		if (!data->have_temp_max)
			return -ENXIO;
		break;
	case PMBUS_VIRT_POWER_SAMPLES:
		ret = adm1275_read_pmon_config(client, ADM1275_PWR_AVG_MASK);
		if (ret < 0)
			break;
		ret = BIT(ret);
		break;
	case PMBUS_VIRT_IN_SAMPLES:
	case PMBUS_VIRT_CURR_SAMPLES:
		ret = adm1275_read_pmon_config(client, ADM1275_VI_AVG_MASK);
		if (ret < 0)
			break;
		ret = BIT(ret);
		break;
	default:
		ret = -ENODATA;
		break;
@@ -277,6 +322,17 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg,
	case PMBUS_VIRT_RESET_TEMP_HISTORY:
		ret = pmbus_write_word_data(client, 0, ADM1278_PEAK_TEMP, 0);
		break;
	case PMBUS_VIRT_POWER_SAMPLES:
		word = clamp_val(word, 1, ADM1275_SAMPLES_AVG_MAX);
		ret = adm1275_write_pmon_config(client, ADM1275_PWR_AVG_MASK,
						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(client, ADM1275_VI_AVG_MASK,
						ilog2(word));
		break;
	default:
		ret = -ENODATA;
		break;
@@ -430,7 +486,8 @@ static int adm1275_probe(struct i2c_client *client,
	info->format[PSC_CURRENT_OUT] = direct;
	info->format[PSC_POWER] = direct;
	info->format[PSC_TEMPERATURE] = direct;
	info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
	info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
			PMBUS_HAVE_SAMPLES;

	info->read_word_data = adm1275_read_word_data;
	info->read_byte_data = adm1275_read_byte_data;