* [PATCH v3 0/3] hwmon: (pmbus/ltc2978) Set voltage resolution
@ 2022-06-14 9:38 Mårten Lindahl
2022-06-14 9:38 ` [PATCH v3 1/3] hwmon: (pmbus) Introduce and use cached vout margins Mårten Lindahl
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Mårten Lindahl @ 2022-06-14 9:38 UTC (permalink / raw)
To: Guenter Roeck, Jean Delvare; +Cc: linux-hwmon, kernel, Mårten Lindahl
Hi!
When checking if a regulator supports a voltage range, the regulator
needs to have support for listing the range or else -EINVAL will be
returned.
This support does not exist for the LTC2977 regulator, so this change
adds support for list voltage to the pmbus regulators by adding
regulator_list_voltage_linear to the pmbus_regulator_ops. It also
defines the voltage resolution for regulators LTC2972/LTC2974/LTC2975/
LTC2977/LTC2978/LTC2979/LTC2980/LTM2987 based on that they all have the
same stepwise 122.07uV resolution, and scales the resolution to a 1mV
resolution which is easier to handle.
These patches have been tested on an ARTPEC-8 developer board with a group
of LTC2977 power regulators.
Kind regards
Mårten Lindahl
Changes in v3:
- Move read of low/high margins into local functions
- Add check for invalid selector value
- Introduce new macro PMBUS_REGULATOR_STEP(_name, _id, _voltages, _step)
Changes in v2:
- Correct #define format
- Change dev_err to dev_warn
- Add new pmbus_regulator_list_voltage function
- Cache low/high vout margins
Mårten Lindahl (3):
hwmon: (pmbus) Introduce and use cached vout margins
hwmon: (pmbus) Add list_voltage to pmbus ops
hwmon: (pmbus/ltc2978) Set voltage resolution
drivers/hwmon/pmbus/ltc2978.c | 44 +++++++++++--
drivers/hwmon/pmbus/pmbus.h | 8 ++-
drivers/hwmon/pmbus/pmbus_core.c | 108 ++++++++++++++++++++++++++-----
3 files changed, 137 insertions(+), 23 deletions(-)
--
2.30.2
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v3 1/3] hwmon: (pmbus) Introduce and use cached vout margins
2022-06-14 9:38 [PATCH v3 0/3] hwmon: (pmbus/ltc2978) Set voltage resolution Mårten Lindahl
@ 2022-06-14 9:38 ` Mårten Lindahl
2022-06-20 15:13 ` Guenter Roeck
2022-06-14 9:38 ` [PATCH v3 2/3] hwmon: (pmbus) Add list_voltage to pmbus ops Mårten Lindahl
2022-06-14 9:38 ` [PATCH v3 3/3] hwmon: (pmbus/ltc2978) Set voltage resolution Mårten Lindahl
2 siblings, 1 reply; 7+ messages in thread
From: Mårten Lindahl @ 2022-06-14 9:38 UTC (permalink / raw)
To: Guenter Roeck, Jean Delvare; +Cc: linux-hwmon, kernel, Mårten Lindahl
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(-)
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)
--
2.30.2
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v3 2/3] hwmon: (pmbus) Add list_voltage to pmbus ops
2022-06-14 9:38 [PATCH v3 0/3] hwmon: (pmbus/ltc2978) Set voltage resolution Mårten Lindahl
2022-06-14 9:38 ` [PATCH v3 1/3] hwmon: (pmbus) Introduce and use cached vout margins Mårten Lindahl
@ 2022-06-14 9:38 ` Mårten Lindahl
2022-06-20 15:14 ` Guenter Roeck
2022-06-14 9:38 ` [PATCH v3 3/3] hwmon: (pmbus/ltc2978) Set voltage resolution Mårten Lindahl
2 siblings, 1 reply; 7+ messages in thread
From: Mårten Lindahl @ 2022-06-14 9:38 UTC (permalink / raw)
To: Guenter Roeck, Jean Delvare; +Cc: linux-hwmon, kernel, Mårten Lindahl
When checking if a regulator supports a voltage range, the regulator
needs to have a list_voltage callback set to the regulator_ops or else
-EINVAL will be returned. This support does not exist for the pmbus
regulators, so this patch adds pmbus_regulator_list_voltage to the
pmbus_regulator_ops.
Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com>
---
drivers/hwmon/pmbus/pmbus_core.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index 5e0d16512fa6..f303c2598fb5 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -2745,6 +2745,35 @@ static int pmbus_regulator_set_voltage(struct regulator_dev *rdev, int min_uv,
return _pmbus_write_word_data(client, s.page, PMBUS_VOUT_COMMAND, (u16)val);
}
+static int pmbus_regulator_list_voltage(struct regulator_dev *rdev,
+ unsigned int selector)
+{
+ struct device *dev = rdev_get_dev(rdev);
+ struct i2c_client *client = to_i2c_client(dev->parent);
+ int val, low, high;
+
+ if (selector >= rdev->desc->n_voltages ||
+ selector < rdev->desc->linear_min_sel)
+ return -EINVAL;
+
+ selector -= rdev->desc->linear_min_sel;
+ val = DIV_ROUND_CLOSEST(rdev->desc->min_uV +
+ (rdev->desc->uV_step * selector), 1000); /* convert to mV */
+
+ low = pmbus_regulator_get_low_margin(client, rdev_get_id(rdev));
+ if (low < 0)
+ return low;
+
+ high = pmbus_regulator_get_high_margin(client, rdev_get_id(rdev));
+ if (high < 0)
+ return high;
+
+ if (val >= low && val <= high)
+ return val * 1000; /* unit is uV */
+
+ return 0;
+}
+
const struct regulator_ops pmbus_regulator_ops = {
.enable = pmbus_regulator_enable,
.disable = pmbus_regulator_disable,
@@ -2752,6 +2781,7 @@ const struct regulator_ops pmbus_regulator_ops = {
.get_error_flags = pmbus_regulator_get_error_flags,
.get_voltage = pmbus_regulator_get_voltage,
.set_voltage = pmbus_regulator_set_voltage,
+ .list_voltage = pmbus_regulator_list_voltage,
};
EXPORT_SYMBOL_NS_GPL(pmbus_regulator_ops, PMBUS);
--
2.30.2
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v3 3/3] hwmon: (pmbus/ltc2978) Set voltage resolution
2022-06-14 9:38 [PATCH v3 0/3] hwmon: (pmbus/ltc2978) Set voltage resolution Mårten Lindahl
2022-06-14 9:38 ` [PATCH v3 1/3] hwmon: (pmbus) Introduce and use cached vout margins Mårten Lindahl
2022-06-14 9:38 ` [PATCH v3 2/3] hwmon: (pmbus) Add list_voltage to pmbus ops Mårten Lindahl
@ 2022-06-14 9:38 ` Mårten Lindahl
2 siblings, 0 replies; 7+ messages in thread
From: Mårten Lindahl @ 2022-06-14 9:38 UTC (permalink / raw)
To: Guenter Roeck, Jean Delvare; +Cc: linux-hwmon, kernel, Mårten Lindahl
The LTC2977 regulator does not set the regulator_desc .n_voltages value
which is needed in order to let the regulator core list the regulator
voltage range.
This patch defines a regulator_desc with a voltage range, and uses it
for defining voltage resolution for regulators LTC2972/LTC2974/LTC2975/
LTC2977/LTC2978/LTC2979/LTC2980/LTM2987 based on that they all have a 16
bit ADC with the same stepwise 122.07uV resolution. It also scales the
resolution to a 1mV resolution which is easier to handle.
Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com>
---
drivers/hwmon/pmbus/ltc2978.c | 44 +++++++++++++++++++++++++++++++----
drivers/hwmon/pmbus/pmbus.h | 8 +++++--
2 files changed, 46 insertions(+), 6 deletions(-)
diff --git a/drivers/hwmon/pmbus/ltc2978.c b/drivers/hwmon/pmbus/ltc2978.c
index 531aa674a928..6d2592731ba3 100644
--- a/drivers/hwmon/pmbus/ltc2978.c
+++ b/drivers/hwmon/pmbus/ltc2978.c
@@ -562,7 +562,24 @@ static const struct i2c_device_id ltc2978_id[] = {
MODULE_DEVICE_TABLE(i2c, ltc2978_id);
#if IS_ENABLED(CONFIG_SENSORS_LTC2978_REGULATOR)
+#define LTC2978_ADC_RES 0xFFFF
+#define LTC2978_N_ADC 122
+#define LTC2978_MAX_UV (LTC2978_ADC_RES * LTC2978_N_ADC)
+#define LTC2978_UV_STEP 1000
+#define LTC2978_N_VOLTAGES ((LTC2978_MAX_UV / LTC2978_UV_STEP) + 1)
+
static const struct regulator_desc ltc2978_reg_desc[] = {
+ PMBUS_REGULATOR_STEP("vout", 0, LTC2978_N_VOLTAGES, LTC2978_UV_STEP),
+ PMBUS_REGULATOR_STEP("vout", 1, LTC2978_N_VOLTAGES, LTC2978_UV_STEP),
+ PMBUS_REGULATOR_STEP("vout", 2, LTC2978_N_VOLTAGES, LTC2978_UV_STEP),
+ PMBUS_REGULATOR_STEP("vout", 3, LTC2978_N_VOLTAGES, LTC2978_UV_STEP),
+ PMBUS_REGULATOR_STEP("vout", 4, LTC2978_N_VOLTAGES, LTC2978_UV_STEP),
+ PMBUS_REGULATOR_STEP("vout", 5, LTC2978_N_VOLTAGES, LTC2978_UV_STEP),
+ PMBUS_REGULATOR_STEP("vout", 6, LTC2978_N_VOLTAGES, LTC2978_UV_STEP),
+ PMBUS_REGULATOR_STEP("vout", 7, LTC2978_N_VOLTAGES, LTC2978_UV_STEP),
+};
+
+static const struct regulator_desc ltc2978_reg_desc_default[] = {
PMBUS_REGULATOR("vout", 0),
PMBUS_REGULATOR("vout", 1),
PMBUS_REGULATOR("vout", 2),
@@ -839,10 +856,29 @@ static int ltc2978_probe(struct i2c_client *client)
#if IS_ENABLED(CONFIG_SENSORS_LTC2978_REGULATOR)
info->num_regulators = info->pages;
- info->reg_desc = ltc2978_reg_desc;
- if (info->num_regulators > ARRAY_SIZE(ltc2978_reg_desc)) {
- dev_err(&client->dev, "num_regulators too large!");
- info->num_regulators = ARRAY_SIZE(ltc2978_reg_desc);
+ switch (data->id) {
+ case ltc2972:
+ case ltc2974:
+ case ltc2975:
+ case ltc2977:
+ case ltc2978:
+ case ltc2979:
+ case ltc2980:
+ case ltm2987:
+ info->reg_desc = ltc2978_reg_desc;
+ if (info->num_regulators > ARRAY_SIZE(ltc2978_reg_desc)) {
+ dev_warn(&client->dev, "num_regulators too large!");
+ info->num_regulators = ARRAY_SIZE(ltc2978_reg_desc);
+ }
+ break;
+ default:
+ info->reg_desc = ltc2978_reg_desc_default;
+ if (info->num_regulators > ARRAY_SIZE(ltc2978_reg_desc_default)) {
+ dev_warn(&client->dev, "num_regulators too large!");
+ info->num_regulators =
+ ARRAY_SIZE(ltc2978_reg_desc_default);
+ }
+ break;
}
#endif
diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h
index c031a9700ace..4a4689c4ab7f 100644
--- a/drivers/hwmon/pmbus/pmbus.h
+++ b/drivers/hwmon/pmbus/pmbus.h
@@ -463,8 +463,8 @@ struct pmbus_driver_info {
extern const struct regulator_ops pmbus_regulator_ops;
-/* Macro for filling in array of struct regulator_desc */
-#define PMBUS_REGULATOR(_name, _id) \
+/* Macros for filling in array of struct regulator_desc */
+#define PMBUS_REGULATOR_STEP(_name, _id, _voltages, _step) \
[_id] = { \
.name = (_name # _id), \
.supply_name = "vin", \
@@ -474,8 +474,12 @@ extern const struct regulator_ops pmbus_regulator_ops;
.ops = &pmbus_regulator_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
+ .n_voltages = _voltages, \
+ .uV_step = _step, \
}
+#define PMBUS_REGULATOR(_name, _id) PMBUS_REGULATOR_STEP(_name, _id, 0, 0)
+
/* Function declarations */
void pmbus_clear_cache(struct i2c_client *client);
--
2.30.2
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v3 1/3] hwmon: (pmbus) Introduce and use cached vout margins
2022-06-14 9:38 ` [PATCH v3 1/3] hwmon: (pmbus) Introduce and use cached vout margins Mårten Lindahl
@ 2022-06-20 15:13 ` Guenter Roeck
0 siblings, 0 replies; 7+ messages in thread
From: Guenter Roeck @ 2022-06-20 15:13 UTC (permalink / raw)
To: Mårten Lindahl; +Cc: Jean Delvare, linux-hwmon, kernel
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)
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v3 2/3] hwmon: (pmbus) Add list_voltage to pmbus ops
2022-06-14 9:38 ` [PATCH v3 2/3] hwmon: (pmbus) Add list_voltage to pmbus ops Mårten Lindahl
@ 2022-06-20 15:14 ` Guenter Roeck
0 siblings, 0 replies; 7+ messages in thread
From: Guenter Roeck @ 2022-06-20 15:14 UTC (permalink / raw)
To: Mårten Lindahl; +Cc: Jean Delvare, linux-hwmon, kernel
On Tue, Jun 14, 2022 at 11:38:55AM +0200, Mårten Lindahl wrote:
> When checking if a regulator supports a voltage range, the regulator
> needs to have a list_voltage callback set to the regulator_ops or else
> -EINVAL will be returned. This support does not exist for the pmbus
> regulators, so this patch adds pmbus_regulator_list_voltage to the
> pmbus_regulator_ops.
>
> Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com>
Applied to hwmon-next.
Thanks,
Guenter
> ---
> drivers/hwmon/pmbus/pmbus_core.c | 30 ++++++++++++++++++++++++++++++
> 1 file changed, 30 insertions(+)
>
> diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
> index 5e0d16512fa6..f303c2598fb5 100644
> --- a/drivers/hwmon/pmbus/pmbus_core.c
> +++ b/drivers/hwmon/pmbus/pmbus_core.c
> @@ -2745,6 +2745,35 @@ static int pmbus_regulator_set_voltage(struct regulator_dev *rdev, int min_uv,
> return _pmbus_write_word_data(client, s.page, PMBUS_VOUT_COMMAND, (u16)val);
> }
>
> +static int pmbus_regulator_list_voltage(struct regulator_dev *rdev,
> + unsigned int selector)
> +{
> + struct device *dev = rdev_get_dev(rdev);
> + struct i2c_client *client = to_i2c_client(dev->parent);
> + int val, low, high;
> +
> + if (selector >= rdev->desc->n_voltages ||
> + selector < rdev->desc->linear_min_sel)
> + return -EINVAL;
> +
> + selector -= rdev->desc->linear_min_sel;
> + val = DIV_ROUND_CLOSEST(rdev->desc->min_uV +
> + (rdev->desc->uV_step * selector), 1000); /* convert to mV */
> +
> + low = pmbus_regulator_get_low_margin(client, rdev_get_id(rdev));
> + if (low < 0)
> + return low;
> +
> + high = pmbus_regulator_get_high_margin(client, rdev_get_id(rdev));
> + if (high < 0)
> + return high;
> +
> + if (val >= low && val <= high)
> + return val * 1000; /* unit is uV */
> +
> + return 0;
> +}
> +
> const struct regulator_ops pmbus_regulator_ops = {
> .enable = pmbus_regulator_enable,
> .disable = pmbus_regulator_disable,
> @@ -2752,6 +2781,7 @@ const struct regulator_ops pmbus_regulator_ops = {
> .get_error_flags = pmbus_regulator_get_error_flags,
> .get_voltage = pmbus_regulator_get_voltage,
> .set_voltage = pmbus_regulator_set_voltage,
> + .list_voltage = pmbus_regulator_list_voltage,
> };
> EXPORT_SYMBOL_NS_GPL(pmbus_regulator_ops, PMBUS);
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v3 0/3] hwmon: (pmbus/ltc2978) Set voltage resolution
@ 2022-06-14 9:51 Mårten Lindahl
0 siblings, 0 replies; 7+ messages in thread
From: Mårten Lindahl @ 2022-06-14 9:51 UTC (permalink / raw)
To: Guenter Roeck, Jean Delvare; +Cc: linux-hwmon, kernel, Mårten Lindahl
Hi!
When checking if a regulator supports a voltage range, the regulator
needs to have support for listing the range or else -EINVAL will be
returned.
This support does not exist for the LTC2977 regulator, so this change
adds support for list voltage to the pmbus regulators by adding
regulator_list_voltage_linear to the pmbus_regulator_ops. It also
defines the voltage resolution for regulators LTC2972/LTC2974/LTC2975/
LTC2977/LTC2978/LTC2979/LTC2980/LTM2987 based on that they all have the
same stepwise 122.07uV resolution, and scales the resolution to a 1mV
resolution which is easier to handle.
These patches have been tested on an ARTPEC-8 developer board with a group
of LTC2977 power regulators.
Kind regards
Mårten Lindahl
Changes in v3:
- Move read of low/high margins into local functions
- Add check for invalid selector value
- Introduce new macro PMBUS_REGULATOR_STEP(_name, _id, _voltages, _step)
Changes in v2:
- Correct #define format
- Change dev_err to dev_warn
- Add new pmbus_regulator_list_voltage function
- Cache low/high vout margins
Mårten Lindahl (3):
hwmon: (pmbus) Introduce and use cached vout margins
hwmon: (pmbus) Add list_voltage to pmbus ops
hwmon: (pmbus/ltc2978) Set voltage resolution
drivers/hwmon/pmbus/ltc2978.c | 44 +++++++++++--
drivers/hwmon/pmbus/pmbus.h | 8 ++-
drivers/hwmon/pmbus/pmbus_core.c | 108 ++++++++++++++++++++++++++-----
3 files changed, 137 insertions(+), 23 deletions(-)
--
2.30.2
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2022-06-20 15:21 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-14 9:38 [PATCH v3 0/3] hwmon: (pmbus/ltc2978) Set voltage resolution Mårten Lindahl
2022-06-14 9:38 ` [PATCH v3 1/3] hwmon: (pmbus) Introduce and use cached vout margins Mårten Lindahl
2022-06-20 15:13 ` Guenter Roeck
2022-06-14 9:38 ` [PATCH v3 2/3] hwmon: (pmbus) Add list_voltage to pmbus ops Mårten Lindahl
2022-06-20 15:14 ` Guenter Roeck
2022-06-14 9:38 ` [PATCH v3 3/3] hwmon: (pmbus/ltc2978) Set voltage resolution Mårten Lindahl
2022-06-14 9:51 [PATCH v3 0/3] " Mårten Lindahl
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.