hwmon: (pmbus/ltc2978) Set voltage resolution
authorMårten Lindahl <marten.lindahl@axis.com>
Tue, 14 Jun 2022 09:51:44 +0000 (11:51 +0200)
committerGuenter Roeck <linux@roeck-us.net>
Wed, 13 Jul 2022 15:38:20 +0000 (08:38 -0700)
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>
Link: https://lore.kernel.org/r/20220614095144.3472305-1-marten.lindahl@axis.com
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
drivers/hwmon/pmbus/ltc2978.c
drivers/hwmon/pmbus/pmbus.h

index 531aa674a9283367d6259cb2d0f3e3290d44a042..6d2592731ba3dc1c0b571e8cfbecc417f2f1f25b 100644 (file)
@@ -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
 
index c708b60c1b4841210dbdc0f65c2b8bcf8a2a31b1..7daaf0caf4d30a0dbd9b5669a86f01b0ff1850a2 100644 (file)
@@ -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);