Re: [PATCH v2] hwmon: (pmbus/adm1275) Fix power sampling support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Jun 13, 2019 at 05:42:34AM -0700, Guenter Roeck wrote:
>Not every chip supported by this driver supports setting the number
>of samples for power averaging. Also, the power monitoring register
>is not always a 16-bit register, and the configuration bits used for
>voltage sampling are different depending on the register width.
>Some conditional code is needed to fix the problem.
>
>On top of all that, the compiler complains about problems with
>FIELD_GET and FIELD_PREP macros if the file is built with W=1.
>Avoid using those macros to silence the warning.
>
>Cc: Krzysztof Adamski <krzysztof.adamski@xxxxxxxxx>
>Cc: Alexander Sverdlin <alexander.sverdlin@xxxxxxxxx>
>Signed-off-by: Guenter Roeck <linux@xxxxxxxxxxxx>

Reviewed-by: Krzysztof Adamski <krzysztof.adamski@xxxxxxxxx>

>---
>v2: s/PRW/PWR/g
>    Drop inline from function declarations
>
> drivers/hwmon/pmbus/adm1275.c | 84 +++++++++++++++++++++++++++++++++----------
> 1 file changed, 65 insertions(+), 19 deletions(-)
>
>diff --git a/drivers/hwmon/pmbus/adm1275.c b/drivers/hwmon/pmbus/adm1275.c
>index a477ce0474bb..5caa37fbfc18 100644
>--- a/drivers/hwmon/pmbus/adm1275.c
>+++ b/drivers/hwmon/pmbus/adm1275.c
>@@ -71,9 +71,17 @@ 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
>+#define ADM1275_VI_AVG_SHIFT		0
>+#define ADM1275_VI_AVG_MASK		GENMASK(ADM1275_VI_AVG_SHIFT + 2, \
>+						ADM1275_VI_AVG_SHIFT)
>+#define ADM1275_SAMPLES_AVG_MAX		128
>+
>+#define ADM1278_PWR_AVG_SHIFT		11
>+#define ADM1278_PWR_AVG_MASK		GENMASK(ADM1278_PWR_AVG_SHIFT + 2, \
>+						ADM1278_PWR_AVG_SHIFT)
>+#define ADM1278_VI_AVG_SHIFT		8
>+#define ADM1278_VI_AVG_MASK		GENMASK(ADM1278_VI_AVG_SHIFT + 2, \
>+						ADM1278_VI_AVG_SHIFT)
>
> struct adm1275_data {
> 	int id;
>@@ -86,6 +94,7 @@ struct adm1275_data {
> 	bool have_pin_min;
> 	bool have_pin_max;
> 	bool have_temp_max;
>+	bool have_power_sampling;
> 	struct pmbus_driver_info info;
> };
>
>@@ -161,28 +170,58 @@ 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)
>+static int adm1275_read_pmon_config(const struct adm1275_data *data,
>+				    struct i2c_client *client, bool is_power)
> {
>-	int ret;
>-
>-	ret = i2c_smbus_read_word_data(client, ADM1275_PMON_CONFIG);
>+	int shift, ret;
>+	u16 mask;
>+
>+	/*
>+	 * The PMON configuration register is a 16-bit register only on chips
>+	 * supporting power average sampling. On other chips it is an 8-bit
>+	 * register.
>+	 */
>+	if (data->have_power_sampling) {
>+		ret = i2c_smbus_read_word_data(client, ADM1275_PMON_CONFIG);
>+		mask = is_power ? ADM1278_PWR_AVG_MASK : ADM1278_VI_AVG_MASK;
>+		shift = is_power ? ADM1278_PWR_AVG_SHIFT : ADM1278_VI_AVG_SHIFT;
>+	} else {
>+		ret = i2c_smbus_read_byte_data(client, ADM1275_PMON_CONFIG);
>+		mask = ADM1275_VI_AVG_MASK;
>+		shift = ADM1275_VI_AVG_SHIFT;
>+	}
> 	if (ret < 0)
> 		return ret;
>
>-	return FIELD_GET(mask, (u16)ret);
>+	return (ret & mask) >> shift;
> }
>
>-static inline int adm1275_write_pmon_config(struct i2c_client *client, u16 mask,
>-					    u16 word)
>+static int adm1275_write_pmon_config(const struct adm1275_data *data,
>+				     struct i2c_client *client,
>+				     bool is_power, u16 word)
> {
>-	int ret;
>-
>-	ret = i2c_smbus_read_word_data(client, ADM1275_PMON_CONFIG);
>+	int shift, ret;
>+	u16 mask;
>+
>+	if (data->have_power_sampling) {
>+		ret = i2c_smbus_read_word_data(client, ADM1275_PMON_CONFIG);
>+		mask = is_power ? ADM1278_PWR_AVG_MASK : ADM1278_VI_AVG_MASK;
>+		shift = is_power ? ADM1278_PWR_AVG_SHIFT : ADM1278_VI_AVG_SHIFT;
>+	} else {
>+		ret = i2c_smbus_read_byte_data(client, ADM1275_PMON_CONFIG);
>+		mask = ADM1275_VI_AVG_MASK;
>+		shift = ADM1275_VI_AVG_SHIFT;
>+	}
> 	if (ret < 0)
> 		return ret;
>
>-	word = FIELD_PREP(mask, word) | (ret & ~mask);
>-	ret = i2c_smbus_write_word_data(client, ADM1275_PMON_CONFIG, word);
>+	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;
> }
>@@ -266,14 +305,16 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
> 			return -ENXIO;
> 		break;
> 	case PMBUS_VIRT_POWER_SAMPLES:
>-		ret = adm1275_read_pmon_config(client, ADM1275_PWR_AVG_MASK);
>+		if (!data->have_power_sampling)
>+			return -ENXIO;
>+		ret = adm1275_read_pmon_config(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(client, ADM1275_VI_AVG_MASK);
>+		ret = adm1275_read_pmon_config(data, client, false);
> 		if (ret < 0)
> 			break;
> 		ret = BIT(ret);
>@@ -323,14 +364,16 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg,
> 		ret = pmbus_write_word_data(client, 0, ADM1278_PEAK_TEMP, 0);
> 		break;
> 	case PMBUS_VIRT_POWER_SAMPLES:
>+		if (!data->have_power_sampling)
>+			return -ENXIO;
> 		word = clamp_val(word, 1, ADM1275_SAMPLES_AVG_MAX);
>-		ret = adm1275_write_pmon_config(client, ADM1275_PWR_AVG_MASK,
>+		ret = adm1275_write_pmon_config(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(client, ADM1275_VI_AVG_MASK,
>+		ret = adm1275_write_pmon_config(data, client, false,
> 						ilog2(word));
> 		break;
> 	default:
>@@ -528,6 +571,7 @@ static int adm1275_probe(struct i2c_client *client,
> 		data->have_vout = true;
> 		data->have_pin_max = true;
> 		data->have_temp_max = true;
>+		data->have_power_sampling = true;
>
> 		coefficients = adm1272_coefficients;
> 		vindex = (config & ADM1275_VRANGE) ? 1 : 0;
>@@ -613,6 +657,7 @@ static int adm1275_probe(struct i2c_client *client,
> 		data->have_vout = true;
> 		data->have_pin_max = true;
> 		data->have_temp_max = true;
>+		data->have_power_sampling = true;
>
> 		coefficients = adm1278_coefficients;
> 		vindex = 0;
>@@ -648,6 +693,7 @@ static int adm1275_probe(struct i2c_client *client,
> 		data->have_pin_min = true;
> 		data->have_pin_max = true;
> 		data->have_mfr_vaux_status = true;
>+		data->have_power_sampling = true;
>
> 		coefficients = adm1293_coefficients;
>
>-- 
>2.7.4
>




[Index of Archives]     [LM Sensors]     [Linux Sound]     [ALSA Users]     [ALSA Devel]     [Linux Audio Users]     [Linux Media]     [Kernel]     [Gimp]     [Yosemite News]     [Linux Media]

  Powered by Linux