* [PATCH v5 1/4] hwmon: (pmbus) Introduce and use write_byte_data callback
2022-05-02 11:13 [PATCH v5 0/4] hwmon: (pmbus/ltc2978) Add regulator ops Mårten Lindahl
@ 2022-05-02 11:13 ` Mårten Lindahl
2022-05-02 11:13 ` [PATCH v5 2/4] hwmon: (pmbus) Use _pmbus_read_byte_data with callback Mårten Lindahl
` (2 subsequent siblings)
3 siblings, 0 replies; 7+ messages in thread
From: Mårten Lindahl @ 2022-05-02 11:13 UTC (permalink / raw)
To: Guenter Roeck, Jean Delvare; +Cc: linux-hwmon, kernel, Mårten Lindahl
Some of the pmbus core functions uses pmbus_write_byte_data, which does
not support driver callbacks for chip specific write operations. This
could potentially influence some specific regulator chips that for
example need a time delay before each data access.
Lets add support for driver callback with _pmbus_write_byte_data.
Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com>
---
drivers/hwmon/pmbus/pmbus.h | 2 ++
drivers/hwmon/pmbus/pmbus_core.c | 24 +++++++++++++++++++++---
2 files changed, 23 insertions(+), 3 deletions(-)
diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h
index e74b6ef070f3..c031a9700ace 100644
--- a/drivers/hwmon/pmbus/pmbus.h
+++ b/drivers/hwmon/pmbus/pmbus.h
@@ -438,6 +438,8 @@ struct pmbus_driver_info {
int (*read_byte_data)(struct i2c_client *client, int page, int reg);
int (*read_word_data)(struct i2c_client *client, int page, int phase,
int reg);
+ int (*write_byte_data)(struct i2c_client *client, int page, int reg,
+ u8 byte);
int (*write_word_data)(struct i2c_client *client, int page, int reg,
u16 word);
int (*write_byte)(struct i2c_client *client, int page, u8 value);
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index b2618b1d529e..98da2db3f831 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -276,6 +276,24 @@ static int _pmbus_write_word_data(struct i2c_client *client, int page, int reg,
return pmbus_write_word_data(client, page, reg, word);
}
+/*
+ * _pmbus_write_byte_data() is similar to pmbus_write_byte_data(), but checks if
+ * a device specific mapping function exists and calls it if necessary.
+ */
+static int _pmbus_write_byte_data(struct i2c_client *client, int page, int reg, u8 value)
+{
+ struct pmbus_data *data = i2c_get_clientdata(client);
+ const struct pmbus_driver_info *info = data->info;
+ int status;
+
+ if (info->write_byte_data) {
+ status = info->write_byte_data(client, page, reg, value);
+ if (status != -ENODATA)
+ return status;
+ }
+ return pmbus_write_byte_data(client, page, reg, value);
+}
+
int pmbus_update_fan(struct i2c_client *client, int page, int id,
u8 config, u8 mask, u16 command)
{
@@ -290,7 +308,7 @@ int pmbus_update_fan(struct i2c_client *client, int page, int id,
to = (from & ~mask) | (config & mask);
if (to != from) {
- rv = pmbus_write_byte_data(client, page,
+ rv = _pmbus_write_byte_data(client, page,
pmbus_fan_config_registers[id], to);
if (rv < 0)
return rv;
@@ -397,7 +415,7 @@ int pmbus_update_byte_data(struct i2c_client *client, int page, u8 reg,
tmp = (rv & ~mask) | (value & mask);
if (tmp != rv)
- rv = pmbus_write_byte_data(client, page, reg, tmp);
+ rv = _pmbus_write_byte_data(client, page, reg, tmp);
return rv;
}
@@ -912,7 +930,7 @@ static int pmbus_get_boolean(struct i2c_client *client, struct pmbus_boolean *b,
regval = status & mask;
if (regval) {
- ret = pmbus_write_byte_data(client, page, reg, regval);
+ ret = _pmbus_write_byte_data(client, page, reg, regval);
if (ret)
goto unlock;
}
--
2.30.2
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v5 2/4] hwmon: (pmbus) Use _pmbus_read_byte_data with callback
2022-05-02 11:13 [PATCH v5 0/4] hwmon: (pmbus/ltc2978) Add regulator ops Mårten Lindahl
2022-05-02 11:13 ` [PATCH v5 1/4] hwmon: (pmbus) Introduce and use write_byte_data callback Mårten Lindahl
@ 2022-05-02 11:13 ` Mårten Lindahl
2022-05-02 11:13 ` [PATCH v5 3/4] hwmon: (pmbus/ltc2978) Add chip specific write_byte_data Mårten Lindahl
2022-05-02 11:13 ` [PATCH v5 4/4] hwmon: (pmbus) Add get_voltage/set_voltage ops Mårten Lindahl
3 siblings, 0 replies; 7+ messages in thread
From: Mårten Lindahl @ 2022-05-02 11:13 UTC (permalink / raw)
To: Guenter Roeck, Jean Delvare; +Cc: linux-hwmon, kernel, Mårten Lindahl
Some of the pmbus core functions uses pmbus_read_byte_data, which does
not support driver callbacks for chip specific write operations. This
could potentially influence some specific regulator chips that for
example need a time delay before each data access.
Lets use _pmbus_read_byte_data with callback check.
Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com>
---
drivers/hwmon/pmbus/pmbus_core.c | 46 ++++++++++++++++----------------
1 file changed, 23 insertions(+), 23 deletions(-)
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index 98da2db3f831..bd143ca0c320 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -294,6 +294,24 @@ static int _pmbus_write_byte_data(struct i2c_client *client, int page, int reg,
return pmbus_write_byte_data(client, page, reg, value);
}
+/*
+ * _pmbus_read_byte_data() is similar to pmbus_read_byte_data(), but checks if
+ * a device specific mapping function exists and calls it if necessary.
+ */
+static int _pmbus_read_byte_data(struct i2c_client *client, int page, int reg)
+{
+ struct pmbus_data *data = i2c_get_clientdata(client);
+ const struct pmbus_driver_info *info = data->info;
+ int status;
+
+ if (info->read_byte_data) {
+ status = info->read_byte_data(client, page, reg);
+ if (status != -ENODATA)
+ return status;
+ }
+ return pmbus_read_byte_data(client, page, reg);
+}
+
int pmbus_update_fan(struct i2c_client *client, int page, int id,
u8 config, u8 mask, u16 command)
{
@@ -301,7 +319,7 @@ int pmbus_update_fan(struct i2c_client *client, int page, int id,
int rv;
u8 to;
- from = pmbus_read_byte_data(client, page,
+ from = _pmbus_read_byte_data(client, page,
pmbus_fan_config_registers[id]);
if (from < 0)
return from;
@@ -408,7 +426,7 @@ int pmbus_update_byte_data(struct i2c_client *client, int page, u8 reg,
unsigned int tmp;
int rv;
- rv = pmbus_read_byte_data(client, page, reg);
+ rv = _pmbus_read_byte_data(client, page, reg);
if (rv < 0)
return rv;
@@ -421,24 +439,6 @@ int pmbus_update_byte_data(struct i2c_client *client, int page, u8 reg,
}
EXPORT_SYMBOL_NS_GPL(pmbus_update_byte_data, PMBUS);
-/*
- * _pmbus_read_byte_data() is similar to pmbus_read_byte_data(), but checks if
- * a device specific mapping function exists and calls it if necessary.
- */
-static int _pmbus_read_byte_data(struct i2c_client *client, int page, int reg)
-{
- struct pmbus_data *data = i2c_get_clientdata(client);
- const struct pmbus_driver_info *info = data->info;
- int status;
-
- if (info->read_byte_data) {
- status = info->read_byte_data(client, page, reg);
- if (status != -ENODATA)
- return status;
- }
- return pmbus_read_byte_data(client, page, reg);
-}
-
static struct pmbus_sensor *pmbus_find_sensor(struct pmbus_data *data, int page,
int reg)
{
@@ -473,7 +473,7 @@ static int pmbus_get_fan_rate(struct i2c_client *client, int page, int id,
return s->data;
}
- config = pmbus_read_byte_data(client, page,
+ config = _pmbus_read_byte_data(client, page,
pmbus_fan_config_registers[id]);
if (config < 0)
return config;
@@ -2414,7 +2414,7 @@ static int pmbus_regulator_is_enabled(struct regulator_dev *rdev)
int ret;
mutex_lock(&data->update_lock);
- ret = pmbus_read_byte_data(client, page, PMBUS_OPERATION);
+ ret = _pmbus_read_byte_data(client, page, PMBUS_OPERATION);
mutex_unlock(&data->update_lock);
if (ret < 0)
@@ -2513,7 +2513,7 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned
if (!(func & cat->func))
continue;
- status = pmbus_read_byte_data(client, page, cat->reg);
+ status = _pmbus_read_byte_data(client, page, cat->reg);
if (status < 0) {
mutex_unlock(&data->update_lock);
return status;
--
2.30.2
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v5 3/4] hwmon: (pmbus/ltc2978) Add chip specific write_byte_data
2022-05-02 11:13 [PATCH v5 0/4] hwmon: (pmbus/ltc2978) Add regulator ops Mårten Lindahl
2022-05-02 11:13 ` [PATCH v5 1/4] hwmon: (pmbus) Introduce and use write_byte_data callback Mårten Lindahl
2022-05-02 11:13 ` [PATCH v5 2/4] hwmon: (pmbus) Use _pmbus_read_byte_data with callback Mårten Lindahl
@ 2022-05-02 11:13 ` Mårten Lindahl
2022-05-02 11:13 ` [PATCH v5 4/4] hwmon: (pmbus) Add get_voltage/set_voltage ops Mårten Lindahl
3 siblings, 0 replies; 7+ messages in thread
From: Mårten Lindahl @ 2022-05-02 11:13 UTC (permalink / raw)
To: Guenter Roeck, Jean Delvare; +Cc: linux-hwmon, kernel, Mårten Lindahl
Several of the manuals for devices supported by this driver describes
the need for a minimum wait time before the chip is ready to receive
next command.
This wait time is already implemented in the driver as a ltc_wait_ready
function with a driver defined wait time of 100 ms, and is considered
for specific devices before reading/writing data on the pmbus.
Since this driver uses the default pmbus_regulator_ops for the enable/
disable/is_enabled functions we should add a driver specific callback
for write_byte_data to prevent bypassing the wait time recommendations
for the following devices: ltc3880/ltc3882/ltc3883/ltc3884/ltc3886/
ltc3887/ltc3889/ltm4664/ltm4675/ltm4676/ltm4677/ltm4678/ltm4680/ltm4686/
ltm4700/ltc7880.
Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com>
---
drivers/hwmon/pmbus/ltc2978.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/hwmon/pmbus/ltc2978.c b/drivers/hwmon/pmbus/ltc2978.c
index 0127273883f0..531aa674a928 100644
--- a/drivers/hwmon/pmbus/ltc2978.c
+++ b/drivers/hwmon/pmbus/ltc2978.c
@@ -196,6 +196,17 @@ static int ltc_read_byte_data(struct i2c_client *client, int page, int reg)
return pmbus_read_byte_data(client, page, reg);
}
+static int ltc_write_byte_data(struct i2c_client *client, int page, int reg, u8 value)
+{
+ int ret;
+
+ ret = ltc_wait_ready(client);
+ if (ret < 0)
+ return ret;
+
+ return pmbus_write_byte_data(client, page, reg, value);
+}
+
static int ltc_write_byte(struct i2c_client *client, int page, u8 byte)
{
int ret;
@@ -681,6 +692,7 @@ static int ltc2978_probe(struct i2c_client *client)
info = &data->info;
info->write_word_data = ltc2978_write_word_data;
info->write_byte = ltc_write_byte;
+ info->write_byte_data = ltc_write_byte_data;
info->read_word_data = ltc_read_word_data;
info->read_byte_data = ltc_read_byte_data;
--
2.30.2
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v5 4/4] hwmon: (pmbus) Add get_voltage/set_voltage ops
2022-05-02 11:13 [PATCH v5 0/4] hwmon: (pmbus/ltc2978) Add regulator ops Mårten Lindahl
` (2 preceding siblings ...)
2022-05-02 11:13 ` [PATCH v5 3/4] hwmon: (pmbus/ltc2978) Add chip specific write_byte_data Mårten Lindahl
@ 2022-05-02 11:13 ` Mårten Lindahl
2022-05-02 16:48 ` Guenter Roeck
3 siblings, 1 reply; 7+ messages in thread
From: Mårten Lindahl @ 2022-05-02 11:13 UTC (permalink / raw)
To: Guenter Roeck, Jean Delvare; +Cc: linux-hwmon, kernel, Mårten Lindahl
The pmbus core does not have operations for getting or setting voltage.
Add functions get/set voltage for the dynamic regulator framework.
Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com>
---
drivers/hwmon/pmbus/pmbus_core.c | 63 ++++++++++++++++++++++++++++++++
1 file changed, 63 insertions(+)
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index bd143ca0c320..455d06ba5fdf 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -2563,11 +2563,74 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned
return 0;
}
+static int pmbus_regulator_get_voltage(struct regulator_dev *rdev)
+{
+ struct device *dev = rdev_get_dev(rdev);
+ struct i2c_client *client = to_i2c_client(dev->parent);
+ struct pmbus_data *data = i2c_get_clientdata(client);
+ struct pmbus_sensor s = {
+ .page = rdev_get_id(rdev),
+ .class = PSC_VOLTAGE_OUT,
+ .convert = true,
+ };
+
+ s.data = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_READ_VOUT);
+ if (s.data < 0)
+ return s.data;
+
+ return (int)pmbus_reg2data(data, &s) * 1000; /* unit is uV */
+}
+
+static int pmbus_regulator_set_voltage(struct regulator_dev *rdev, int min_uV,
+ int max_uV, unsigned int *selector)
+{
+ struct device *dev = rdev_get_dev(rdev);
+ struct i2c_client *client = to_i2c_client(dev->parent);
+ struct pmbus_data *data = i2c_get_clientdata(client);
+ struct pmbus_sensor s = {
+ .page = rdev_get_id(rdev),
+ .class = PSC_VOLTAGE_OUT,
+ .convert = true,
+ };
+ s64 tmp = DIV_ROUND_CLOSEST_ULL(min_uV, 1000); /* convert to mV */
+ int low = -1, high = -1;
+ u16 val;
+ *selector = 0;
+
+ if (pmbus_check_word_register(client, s.page, PMBUS_MFR_VOUT_MIN))
+ low = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_MFR_VOUT_MIN);
+ if (low < 0) {
+ low = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_VOUT_MARGIN_LOW);
+ if (low < 0)
+ return low;
+ }
+
+ if (pmbus_check_word_register(client, s.page, PMBUS_MFR_VOUT_MAX))
+ high = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_MFR_VOUT_MAX);
+ if (high < 0) {
+ high = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_VOUT_MARGIN_HIGH);
+ if (high < 0)
+ return high;
+ }
+
+ val = pmbus_data2reg(data, &s, tmp);
+
+ /* Make sure we are within margins */
+ if (low > val)
+ val = low;
+ if (high < val)
+ val = high;
+
+ return _pmbus_write_word_data(client, s.page, PMBUS_VOUT_COMMAND, val);
+}
+
const struct regulator_ops pmbus_regulator_ops = {
.enable = pmbus_regulator_enable,
.disable = pmbus_regulator_disable,
.is_enabled = pmbus_regulator_is_enabled,
.get_error_flags = pmbus_regulator_get_error_flags,
+ .get_voltage = pmbus_regulator_get_voltage,
+ .set_voltage = pmbus_regulator_set_voltage,
};
EXPORT_SYMBOL_NS_GPL(pmbus_regulator_ops, PMBUS);
--
2.30.2
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH v5 4/4] hwmon: (pmbus) Add get_voltage/set_voltage ops
2022-05-02 11:13 ` [PATCH v5 4/4] hwmon: (pmbus) Add get_voltage/set_voltage ops Mårten Lindahl
@ 2022-05-02 16:48 ` Guenter Roeck
2022-05-03 10:14 ` Marten Lindahl
0 siblings, 1 reply; 7+ messages in thread
From: Guenter Roeck @ 2022-05-02 16:48 UTC (permalink / raw)
To: Mårten Lindahl, Jean Delvare; +Cc: linux-hwmon, kernel
On 5/2/22 04:13, Mårten Lindahl wrote:
> The pmbus core does not have operations for getting or setting voltage.
> Add functions get/set voltage for the dynamic regulator framework.
>
> Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com>
> ---
> drivers/hwmon/pmbus/pmbus_core.c | 63 ++++++++++++++++++++++++++++++++
> 1 file changed, 63 insertions(+)
>
> diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
> index bd143ca0c320..455d06ba5fdf 100644
> --- a/drivers/hwmon/pmbus/pmbus_core.c
> +++ b/drivers/hwmon/pmbus/pmbus_core.c
> @@ -2563,11 +2563,74 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned
> return 0;
> }
>
> +static int pmbus_regulator_get_voltage(struct regulator_dev *rdev)
> +{
> + struct device *dev = rdev_get_dev(rdev);
> + struct i2c_client *client = to_i2c_client(dev->parent);
> + struct pmbus_data *data = i2c_get_clientdata(client);
> + struct pmbus_sensor s = {
> + .page = rdev_get_id(rdev),
> + .class = PSC_VOLTAGE_OUT,
> + .convert = true,
> + };
> +
> + s.data = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_READ_VOUT);
> + if (s.data < 0)
> + return s.data;
> +
> + return (int)pmbus_reg2data(data, &s) * 1000; /* unit is uV */
> +}
> +
> +static int pmbus_regulator_set_voltage(struct regulator_dev *rdev, int min_uV,
> + int max_uV, unsigned int *selector)
Just noticed: Please don't use camelCase.
> +{
> + struct device *dev = rdev_get_dev(rdev);
> + struct i2c_client *client = to_i2c_client(dev->parent);
> + struct pmbus_data *data = i2c_get_clientdata(client);
> + struct pmbus_sensor s = {
> + .page = rdev_get_id(rdev),
> + .class = PSC_VOLTAGE_OUT,
> + .convert = true,
> + };
> + s64 tmp = DIV_ROUND_CLOSEST_ULL(min_uV, 1000); /* convert to mV */
min_uV is already an int, so converting it to s64 will never be
necessary.
> + int low = -1, high = -1;
> + u16 val;
> + *selector = 0;
> +
> + if (pmbus_check_word_register(client, s.page, PMBUS_MFR_VOUT_MIN))
> + low = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_MFR_VOUT_MIN);
> + if (low < 0) {
> + low = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_VOUT_MARGIN_LOW);
> + if (low < 0)
> + return low;
> + }
> +
> + if (pmbus_check_word_register(client, s.page, PMBUS_MFR_VOUT_MAX))
> + high = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_MFR_VOUT_MAX);
> + if (high < 0) {
> + high = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_VOUT_MARGIN_HIGH);
> + if (high < 0)
> + return high;
> + }
> +
> + val = pmbus_data2reg(data, &s, tmp);
> +
> + /* Make sure we are within margins */
> + if (low > val)
> + val = low;
> + if (high < val)
> + val = high;
> +
The above assumes that register values are directly comparable.
Unfortunately that isn't really the case. It happens to work
for ULINEAR16 and DIRECT mode, but chips could also support
IEEE-754 (maybe in the future) or VID mode.
You need to read the limits from the registers, convert to voltages,
compare and adjust the voltage, and as final step convert the adjusted
voltage to a register value.
Thanks,
Guenter
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [PATCH v5 4/4] hwmon: (pmbus) Add get_voltage/set_voltage ops
2022-05-02 16:48 ` Guenter Roeck
@ 2022-05-03 10:14 ` Marten Lindahl
0 siblings, 0 replies; 7+ messages in thread
From: Marten Lindahl @ 2022-05-03 10:14 UTC (permalink / raw)
To: Guenter Roeck
Cc: Mårten Lindahl, Jean Delvare, linux-hwmon@vger.kernel.org,
kernel
On Mon, May 02, 2022 at 06:48:25PM +0200, Guenter Roeck wrote:
> On 5/2/22 04:13, Mårten Lindahl wrote:
> > The pmbus core does not have operations for getting or setting voltage.
> > Add functions get/set voltage for the dynamic regulator framework.
> >
> > Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com>
> > ---
> > drivers/hwmon/pmbus/pmbus_core.c | 63 ++++++++++++++++++++++++++++++++
> > 1 file changed, 63 insertions(+)
> >
> > diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
> > index bd143ca0c320..455d06ba5fdf 100644
> > --- a/drivers/hwmon/pmbus/pmbus_core.c
> > +++ b/drivers/hwmon/pmbus/pmbus_core.c
> > @@ -2563,11 +2563,74 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned
> > return 0;
> > }
> >
> > +static int pmbus_regulator_get_voltage(struct regulator_dev *rdev)
> > +{
> > + struct device *dev = rdev_get_dev(rdev);
> > + struct i2c_client *client = to_i2c_client(dev->parent);
> > + struct pmbus_data *data = i2c_get_clientdata(client);
> > + struct pmbus_sensor s = {
> > + .page = rdev_get_id(rdev),
> > + .class = PSC_VOLTAGE_OUT,
> > + .convert = true,
> > + };
> > +
> > + s.data = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_READ_VOUT);
> > + if (s.data < 0)
> > + return s.data;
> > +
> > + return (int)pmbus_reg2data(data, &s) * 1000; /* unit is uV */
> > +}
> > +
> > +static int pmbus_regulator_set_voltage(struct regulator_dev *rdev, int min_uV,
> > + int max_uV, unsigned int *selector)
>
> Just noticed: Please don't use camelCase.
Ok, I will change it. But for this I blame include/linux/regulator/driver.h:
struct regulator_ops {
...
/* get/set regulator voltage */
int (*set_voltage) (struct regulator_dev *, int min_uV, int max_uV,
unsigned *selector);
>
> > +{
> > + struct device *dev = rdev_get_dev(rdev);
> > + struct i2c_client *client = to_i2c_client(dev->parent);
> > + struct pmbus_data *data = i2c_get_clientdata(client);
> > + struct pmbus_sensor s = {
> > + .page = rdev_get_id(rdev),
> > + .class = PSC_VOLTAGE_OUT,
> > + .convert = true,
> > + };
> > + s64 tmp = DIV_ROUND_CLOSEST_ULL(min_uV, 1000); /* convert to mV */
>
> min_uV is already an int, so converting it to s64 will never be
> necessary.
True. Will change.
>
> > + int low = -1, high = -1;
> > + u16 val;
> > + *selector = 0;
> > +
> > + if (pmbus_check_word_register(client, s.page, PMBUS_MFR_VOUT_MIN))
> > + low = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_MFR_VOUT_MIN);
> > + if (low < 0) {
> > + low = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_VOUT_MARGIN_LOW);
> > + if (low < 0)
> > + return low;
> > + }
> > +
> > + if (pmbus_check_word_register(client, s.page, PMBUS_MFR_VOUT_MAX))
> > + high = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_MFR_VOUT_MAX);
> > + if (high < 0) {
> > + high = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_VOUT_MARGIN_HIGH);
> > + if (high < 0)
> > + return high;
> > + }
> > +
> > + val = pmbus_data2reg(data, &s, tmp);
> > +
> > + /* Make sure we are within margins */
> > + if (low > val)
> > + val = low;
> > + if (high < val)
> > + val = high;
> > +
>
> The above assumes that register values are directly comparable.
> Unfortunately that isn't really the case. It happens to work
> for ULINEAR16 and DIRECT mode, but chips could also support
> IEEE-754 (maybe in the future) or VID mode.
>
> You need to read the limits from the registers, convert to voltages,
> compare and adjust the voltage, and as final step convert the adjusted
> voltage to a register value.
Thanks. That is a good observation.
Kind regards
Mårten
>
> Thanks,
> Guenter
^ permalink raw reply [flat|nested] 7+ messages in thread