Linux-Hwmon Archive on lore.kernel.org
 help / color / Atom feed
From: "Adamski, Krzysztof (Nokia - PL/Wroclaw)"  <krzysztof.adamski@nokia.com>
To: Guenter Roeck <linux@roeck-us.net>
Cc: Hardware Monitoring <linux-hwmon@vger.kernel.org>,
	Jean Delvare <jdelvare@suse.com>,
	"Sverdlin,
	Alexander (Nokia - DE/Ulm)" <alexander.sverdlin@nokia.com>
Subject: Re: [PATCH v2] hwmon: (pmbus/adm1275) Fix power sampling support
Date: Fri, 14 Jun 2019 06:11:25 +0000
Message-ID: <20190614061118.GB26525@localhost.localdomain> (raw)
In-Reply-To: <1560429754-17510-1-git-send-email-linux@roeck-us.net>

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@nokia.com>
>Cc: Alexander Sverdlin <alexander.sverdlin@nokia.com>
>Signed-off-by: Guenter Roeck <linux@roeck-us.net>

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

>---
>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
>

      reply index

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-06-13 12:42 Guenter Roeck
2019-06-14  6:11 ` Adamski, Krzysztof (Nokia - PL/Wroclaw) [this message]

Reply instructions:

You may reply publically to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190614061118.GB26525@localhost.localdomain \
    --to=krzysztof.adamski@nokia.com \
    --cc=alexander.sverdlin@nokia.com \
    --cc=jdelvare@suse.com \
    --cc=linux-hwmon@vger.kernel.org \
    --cc=linux@roeck-us.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Linux-Hwmon Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-hwmon/0 linux-hwmon/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-hwmon linux-hwmon/ https://lore.kernel.org/linux-hwmon \
		linux-hwmon@vger.kernel.org linux-hwmon@archiver.kernel.org
	public-inbox-index linux-hwmon


Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-hwmon


AGPL code for this site: git clone https://public-inbox.org/ public-inbox