diff mbox series

[v3,1/3] hwmon: (pmbus) Introduce and use cached vout margins

Message ID 20220614093856.3470672-2-marten.lindahl@axis.com (mailing list archive)
State Accepted
Headers show
Series hwmon: (pmbus/ltc2978) Set voltage resolution | expand

Commit Message

Mårten Lindahl June 14, 2022, 9:38 a.m. UTC
When setting a new voltage the voltage boundaries are read every time to
check that the new voltage is within the proper range. Checking these
voltage boundaries consists of reading one of PMBUS_MFR_VOUT_MIN/
PMBUS_VOUT_MARGIN_LOW registers and then PMBUS_MFR_VOUT_MAX/
PMBUS_VOUT_MARGIN_HIGH together with writing the PMBUS_CLEAR_FAULTS
register.

Since these boundaries are never being changed, it can be cached and
thus saving unnecessary smbus transmissions.

Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com>
---
 drivers/hwmon/pmbus/pmbus_core.c | 78 +++++++++++++++++++++++++-------
 1 file changed, 61 insertions(+), 17 deletions(-)

Comments

Guenter Roeck June 20, 2022, 3:13 p.m. UTC | #1
On Tue, Jun 14, 2022 at 11:38:54AM +0200, Mårten Lindahl wrote:
> When setting a new voltage the voltage boundaries are read every time to
> check that the new voltage is within the proper range. Checking these
> voltage boundaries consists of reading one of PMBUS_MFR_VOUT_MIN/
> PMBUS_VOUT_MARGIN_LOW registers and then PMBUS_MFR_VOUT_MAX/
> PMBUS_VOUT_MARGIN_HIGH together with writing the PMBUS_CLEAR_FAULTS
> register.
> 
> Since these boundaries are never being changed, it can be cached and
> thus saving unnecessary smbus transmissions.
> 
> Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com>

Applied to hwmon-next.

Thanks,
Guenter

> ---
>  drivers/hwmon/pmbus/pmbus_core.c | 78 +++++++++++++++++++++++++-------
>  1 file changed, 61 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
> index 02912022853d..5e0d16512fa6 100644
> --- a/drivers/hwmon/pmbus/pmbus_core.c
> +++ b/drivers/hwmon/pmbus/pmbus_core.c
> @@ -104,6 +104,9 @@ struct pmbus_data {
>  
>  	s16 currpage;	/* current page, -1 for unknown/unset */
>  	s16 currphase;	/* current phase, 0xff for all, -1 for unknown/unset */
> +
> +	int vout_low[PMBUS_PAGES];	/* voltage low margin */
> +	int vout_high[PMBUS_PAGES];	/* voltage high margin */
>  };
>  
>  struct pmbus_debugfs_entry {
> @@ -2636,6 +2639,58 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned
>  	return 0;
>  }
>  
> +static int pmbus_regulator_get_low_margin(struct i2c_client *client, int page)
> +{
> +	struct pmbus_data *data = i2c_get_clientdata(client);
> +	struct pmbus_sensor s = {
> +		.page = page,
> +		.class = PSC_VOLTAGE_OUT,
> +		.convert = true,
> +		.data = -1,
> +	};
> +
> +	if (!data->vout_low[page]) {
> +		if (pmbus_check_word_register(client, page, PMBUS_MFR_VOUT_MIN))
> +			s.data = _pmbus_read_word_data(client, page, 0xff,
> +						       PMBUS_MFR_VOUT_MIN);
> +		if (s.data < 0) {
> +			s.data = _pmbus_read_word_data(client, page, 0xff,
> +						       PMBUS_VOUT_MARGIN_LOW);
> +			if (s.data < 0)
> +				return s.data;
> +		}
> +		data->vout_low[page] = pmbus_reg2data(data, &s);
> +	}
> +
> +	return data->vout_low[page];
> +}
> +
> +static int pmbus_regulator_get_high_margin(struct i2c_client *client, int page)
> +{
> +	struct pmbus_data *data = i2c_get_clientdata(client);
> +	struct pmbus_sensor s = {
> +		.page = page,
> +		.class = PSC_VOLTAGE_OUT,
> +		.convert = true,
> +		.data = -1,
> +	};
> +
> +	if (!data->vout_high[page]) {
> +		if (pmbus_check_word_register(client, page, PMBUS_MFR_VOUT_MAX))
> +			s.data = _pmbus_read_word_data(client, page, 0xff,
> +						       PMBUS_MFR_VOUT_MAX);
> +		if (s.data < 0) {
> +			s.data = _pmbus_read_word_data(client, page, 0xff,
> +						       PMBUS_VOUT_MARGIN_HIGH);
> +			if (s.data < 0)
> +				return s.data;
> +		}
> +		data->vout_high[page] = pmbus_reg2data(data, &s);
> +	}
> +
> +	return data->vout_high[page];
> +}
> +
>  static int pmbus_regulator_get_voltage(struct regulator_dev *rdev)
>  {
>  	struct device *dev = rdev_get_dev(rdev);
> @@ -2671,24 +2726,13 @@ static int pmbus_regulator_set_voltage(struct regulator_dev *rdev, int min_uv,
>  
>  	*selector = 0;
>  
> -	if (pmbus_check_word_register(client, s.page, PMBUS_MFR_VOUT_MIN))
> -		s.data = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_MFR_VOUT_MIN);
> -	if (s.data < 0) {
> -		s.data = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_VOUT_MARGIN_LOW);
> -		if (s.data < 0)
> -			return s.data;
> -	}
> -	low = pmbus_reg2data(data, &s);
> +	low = pmbus_regulator_get_low_margin(client, s.page);
> +	if (low < 0)
> +		return low;
>  
> -	s.data = -1;
> -	if (pmbus_check_word_register(client, s.page, PMBUS_MFR_VOUT_MAX))
> -		s.data = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_MFR_VOUT_MAX);
> -	if (s.data < 0) {
> -		s.data = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_VOUT_MARGIN_HIGH);
> -		if (s.data < 0)
> -			return s.data;
> -	}
> -	high = pmbus_reg2data(data, &s);
> +	high = pmbus_regulator_get_high_margin(client, s.page);
> +	if (high < 0)
> +		return high;
>  
>  	/* Make sure we are within margins */
>  	if (low > val)
diff mbox series

Patch

diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index 02912022853d..5e0d16512fa6 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -104,6 +104,9 @@  struct pmbus_data {
 
 	s16 currpage;	/* current page, -1 for unknown/unset */
 	s16 currphase;	/* current phase, 0xff for all, -1 for unknown/unset */
+
+	int vout_low[PMBUS_PAGES];	/* voltage low margin */
+	int vout_high[PMBUS_PAGES];	/* voltage high margin */
 };
 
 struct pmbus_debugfs_entry {
@@ -2636,6 +2639,58 @@  static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned
 	return 0;
 }
 
+static int pmbus_regulator_get_low_margin(struct i2c_client *client, int page)
+{
+	struct pmbus_data *data = i2c_get_clientdata(client);
+	struct pmbus_sensor s = {
+		.page = page,
+		.class = PSC_VOLTAGE_OUT,
+		.convert = true,
+		.data = -1,
+	};
+
+	if (!data->vout_low[page]) {
+		if (pmbus_check_word_register(client, page, PMBUS_MFR_VOUT_MIN))
+			s.data = _pmbus_read_word_data(client, page, 0xff,
+						       PMBUS_MFR_VOUT_MIN);
+		if (s.data < 0) {
+			s.data = _pmbus_read_word_data(client, page, 0xff,
+						       PMBUS_VOUT_MARGIN_LOW);
+			if (s.data < 0)
+				return s.data;
+		}
+		data->vout_low[page] = pmbus_reg2data(data, &s);
+	}
+
+	return data->vout_low[page];
+}
+
+static int pmbus_regulator_get_high_margin(struct i2c_client *client, int page)
+{
+	struct pmbus_data *data = i2c_get_clientdata(client);
+	struct pmbus_sensor s = {
+		.page = page,
+		.class = PSC_VOLTAGE_OUT,
+		.convert = true,
+		.data = -1,
+	};
+
+	if (!data->vout_high[page]) {
+		if (pmbus_check_word_register(client, page, PMBUS_MFR_VOUT_MAX))
+			s.data = _pmbus_read_word_data(client, page, 0xff,
+						       PMBUS_MFR_VOUT_MAX);
+		if (s.data < 0) {
+			s.data = _pmbus_read_word_data(client, page, 0xff,
+						       PMBUS_VOUT_MARGIN_HIGH);
+			if (s.data < 0)
+				return s.data;
+		}
+		data->vout_high[page] = pmbus_reg2data(data, &s);
+	}
+
+	return data->vout_high[page];
+}
+
 static int pmbus_regulator_get_voltage(struct regulator_dev *rdev)
 {
 	struct device *dev = rdev_get_dev(rdev);
@@ -2671,24 +2726,13 @@  static int pmbus_regulator_set_voltage(struct regulator_dev *rdev, int min_uv,
 
 	*selector = 0;
 
-	if (pmbus_check_word_register(client, s.page, PMBUS_MFR_VOUT_MIN))
-		s.data = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_MFR_VOUT_MIN);
-	if (s.data < 0) {
-		s.data = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_VOUT_MARGIN_LOW);
-		if (s.data < 0)
-			return s.data;
-	}
-	low = pmbus_reg2data(data, &s);
+	low = pmbus_regulator_get_low_margin(client, s.page);
+	if (low < 0)
+		return low;
 
-	s.data = -1;
-	if (pmbus_check_word_register(client, s.page, PMBUS_MFR_VOUT_MAX))
-		s.data = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_MFR_VOUT_MAX);
-	if (s.data < 0) {
-		s.data = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_VOUT_MARGIN_HIGH);
-		if (s.data < 0)
-			return s.data;
-	}
-	high = pmbus_reg2data(data, &s);
+	high = pmbus_regulator_get_high_margin(client, s.page);
+	if (high < 0)
+		return high;
 
 	/* Make sure we are within margins */
 	if (low > val)