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 <[email protected]>
>Cc: Alexander Sverdlin <[email protected]>
>Signed-off-by: Guenter Roeck <[email protected]>

Reviewed-by: Krzysztof Adamski <[email protected]>

>---
>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 via email to