]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
hwmon: ina3221: refactor ina3221 driver
authorTimo Alho <talho@nvidia.com>
Tue, 17 Dec 2013 22:05:13 +0000 (00:05 +0200)
committerJuha Tukkinen <jtukkinen@nvidia.com>
Wed, 8 Jan 2014 17:49:27 +0000 (09:49 -0800)
This patch refactors the ina3221 hwmon driver by moving the common
parts of code to __locked_do_conversion() function.

Bug 1400509
Bug 1414772

Change-Id: Ibbc58b82d67a1ece3bea258015ff67ee2bb35def
Signed-off-by: Timo Alho <talho@nvidia.com>
Reviewed-on: http://git-master/r/346967
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Juha Tukkinen <jtukkinen@nvidia.com>
drivers/hwmon/ina3221.c
include/linux/ina3221.h

index db31b579e26e6fb56376a31e8a453b13cd1c0e3b..97ac696cb08e83612935d8e3610555278a613bbd 100644 (file)
 #define TRIGGERED 0
 #define CONTINUOUS 1
 
-#define busv_register_to_mv(x) ((x >> 3) * 8)
-#define shuntv_register_to_uv(x) ((x >> 3) * 40)
-#define uv_to_shuntv_register(x) (x/5) /*(x/40) << 3*/
-
 #define CPU_THRESHOLD 2
 #define CPU_FREQ_THRESHOLD 102000
 
-/* Assume power can not exceed +-524W */
-#define MAX_POWER_MW 0x000FFFFF
-#define POWER_SHFT 12
-
 struct ina3221_data {
        struct device *hwmon_dev;
        struct i2c_client *client;
@@ -76,6 +68,23 @@ struct ina3221_data {
        int is_suspended;
 };
 
+static inline s32 shuntv_register_to_uv(u16 reg)
+{
+       s32 ret = (s16)reg;
+       return (ret >> 3) * 40;
+}
+
+static inline u16 uv_to_shuntv_register(s32 uv)
+{
+       return (u16)(uv/5);
+}
+
+static inline s32 busv_register_to_mv(u16 reg)
+{
+       s32 ret = (s16)reg;
+       return (ret >> 3) * 8;
+}
+
 /* convert shunt voltage register value to current (in mA) */
 static s32 shuntv_register_to_ma(u16 reg, s32 resistance)
 {
@@ -102,9 +111,10 @@ u32 index, u32 reg_addr)
                data->plat_data->crit_conf_limits[index] *
                        data->plat_data->shunt_resistor[index];
        shunt_volt_limit = uv_to_shuntv_register(shunt_volt_limit);
+
        DEBUG_INA3221(("Current = %d\n", shunt_volt_limit));
        ret = i2c_smbus_write_word_data(client, reg_addr,
-                               __constant_cpu_to_be16(shunt_volt_limit));
+                               cpu_to_be16(shunt_volt_limit));
        return ret;
 }
 
@@ -120,8 +130,8 @@ static s32 __locked_set_crit_warn_limits(struct i2c_client *client)
                return -EINVAL;
 
        for (i = 0; i < INA3221_NUMBER_OF_RAILS; i++) {
-               crit_reg_addr = (INA3221_CRIT_CHAN1 + (i * 2));
-               warn_reg_addr = (INA3221_WARN_CHAN1 + (i * 2));
+               crit_reg_addr = INA3221_CRIT(i);
+               warn_reg_addr = INA3221_WARN(i);
                if (data->plat_data->crit_conf_limits[i] != -1) {
                        ret = __locked_set_crit_warn_register(client,
                                                        i, crit_reg_addr);
@@ -159,13 +169,69 @@ static s32 __locked_power_up_ina3221(struct i2c_client *client, int config)
        if (data->shutdown_complete)
                return -ENODEV;
        ret = i2c_smbus_write_word_data(client, INA3221_CONFIG,
-                                       __constant_cpu_to_be16(config));
+                                       cpu_to_be16(config));
        if (ret < 0)
                dev_err(&client->dev,
                        "Config data write failed, error: 0x%x", ret);
        return ret;
 }
 
+static s32 __locked_start_conversion(struct i2c_client *client)
+{
+       struct ina3221_data *data = i2c_get_clientdata(client);
+       s32 ret = 0;
+       int config = data->plat_data->trig_conf_data;
+
+       if (data->mode == TRIGGERED)
+               ret = __locked_power_up_ina3221(client, config);
+
+       return ret;
+}
+
+static s32 __locked_end_conversion(struct i2c_client *client)
+{
+       struct ina3221_data *data = i2c_get_clientdata(client);
+       s32 ret = 0;
+
+       if (data->mode == TRIGGERED)
+               ret = __locked_power_down_ina3221(client);
+
+       return ret;
+}
+
+static s32 __locked_do_conversion(struct i2c_client *client, u16 *vsh,
+                                 u16 *vbus, int ch)
+{
+       struct ina3221_data *data = i2c_get_clientdata(client);
+       s32 ret;
+
+       if (data->shutdown_complete)
+               return -ENODEV;
+
+       ret = __locked_start_conversion(client);
+       if (ret < 0)
+               return ret;
+
+       if (vsh) {
+               ret = i2c_smbus_read_word_data(client, INA3221_SHUNT_VOL(ch));
+               if (ret < 0)
+                       return ret;
+               *vsh = be16_to_cpu(ret);
+       }
+
+       if (vbus) {
+               ret = i2c_smbus_read_word_data(client, INA3221_BUS_VOL(ch));
+               if (ret < 0)
+                       return ret;
+               *vbus = be16_to_cpu(ret);
+       }
+
+       ret = __locked_end_conversion(client);
+
+       return ret;
+}
+
+
 static s32 show_mode(struct device *dev, struct device_attribute *attr,
                                                                char *buf)
 {
@@ -196,44 +262,19 @@ static s32 show_voltage(struct device *dev,
        struct i2c_client *client = to_i2c_client(dev);
        struct ina3221_data *data = i2c_get_clientdata(client);
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-       u8 index, bus_volt_reg_addr;
+       u8 index;
+       u16 vbus;
        s32 ret;
        s32 voltage_mv;
 
        mutex_lock(&data->mutex);
-       if (data->shutdown_complete) {
-               ret = -ENODEV;
-               goto error;
-       }
        index = attr->index;
-       bus_volt_reg_addr = (INA3221_BUS_VOL_CHAN1 + (index * 2));
 
-       if (data->mode == TRIGGERED) {
-               ret = __locked_power_up_ina3221(client,
-                               data->plat_data->trig_conf_data);
-               if (ret < 0) {
-                       dev_err(dev,
-                       "Power up failed, status: 0x%x\n", ret);
-                       goto error;
-               }
-       }
-
-       /* getting voltage readings in milli volts*/
-       ret = i2c_smbus_read_word_data(client,
-                       bus_volt_reg_addr);
+       ret = __locked_do_conversion(client, NULL, &vbus, index);
        if (ret < 0)
                goto error;
-       voltage_mv = be16_to_cpu(ret);
-       voltage_mv = (voltage_mv << 16) >> 16;
-       voltage_mv = busv_register_to_mv(voltage_mv);
-       DEBUG_INA3221(("Ina3221 bus voltage in mv: %d\n", voltage_mv));
 
-       if (data->mode == TRIGGERED) {
-               /* set ina3221 to power down mode */
-               ret = __locked_power_down_ina3221(client);
-               if (ret < 0)
-                       goto error;
-       }
+       voltage_mv = busv_register_to_mv(vbus);
 
        DEBUG_INA3221(("%s volt = %d\n", __func__, voltage_mv));
        mutex_unlock(&data->mutex);
@@ -251,44 +292,21 @@ static s32 show_current(struct device *dev,
        struct i2c_client *client = to_i2c_client(dev);
        struct ina3221_data *data = i2c_get_clientdata(client);
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-       u8 index, shunt_volt_reg_addr;
+       u8 index;
+       u16 vsh;
        s32 ret;
        s32 current_ma;
        s32 resistance;
 
        mutex_lock(&data->mutex);
-       if (data->shutdown_complete) {
-               ret = -ENODEV;
-               goto error;
-       }
        index = attr->index;
-       shunt_volt_reg_addr = (INA3221_SHUNT_VOL_CHAN1 + (index * 2));
 
-       if (data->mode == TRIGGERED) {
-               ret = __locked_power_up_ina3221(client,
-                               data->plat_data->trig_conf_data);
-               if (ret < 0) {
-                       dev_err(dev,
-                               "power up failed sts: 0x%x\n", ret);
-                       goto error;
-               }
-       }
-
-       /* getting voltage readings in micro volts*/
-       ret = i2c_smbus_read_word_data(client,
-                       shunt_volt_reg_addr);
+       ret = __locked_do_conversion(client, &vsh, NULL, index);
        if (ret < 0)
                goto error;
 
        resistance = data->plat_data->shunt_resistor[index];
-       current_ma = shuntv_register_to_ma(be16_to_cpu(ret), resistance);
-
-       if (data->mode == TRIGGERED) {
-               /* set ina3221 to power down mode */
-               ret = __locked_power_down_ina3221(client);
-               if (ret < 0)
-                       goto error;
-       }
+       current_ma = shuntv_register_to_ma(vsh, resistance);
 
        DEBUG_INA3221(("%s current = %d\n", __func__, current_ma));
        mutex_unlock(&data->mutex);
@@ -306,7 +324,8 @@ static s32 show_current2(struct device *dev,
        struct i2c_client *client = to_i2c_client(dev);
        struct ina3221_data *data = i2c_get_clientdata(client);
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-       u8 index, shunt_volt_reg_addr;
+       u8 index;
+       u16 vsh;
        s32 ret;
        s32 current_ma;
        s32 resistance;
@@ -324,22 +343,13 @@ static s32 show_current2(struct device *dev,
        }
 
        index = attr->index;
-       shunt_volt_reg_addr = (INA3221_SHUNT_VOL_CHAN1 + (index * 2));
-       /* getting voltage readings in micro volts*/
-       ret = i2c_smbus_read_word_data(client,
-                       shunt_volt_reg_addr);
+
+       ret = __locked_do_conversion(client, &vsh, NULL, index);
        if (ret < 0)
                goto error;
 
        resistance = data->plat_data->shunt_resistor[index];
-       current_ma = shuntv_register_to_ma(be16_to_cpu(ret), resistance);
-
-       if (data->mode == TRIGGERED) {
-               /* set ina3221 to power down mode */
-               ret = __locked_power_down_ina3221(client);
-               if (ret < 0)
-                       goto error;
-       }
+       current_ma = shuntv_register_to_ma(vsh, resistance);
 
        DEBUG_INA3221(("%s current = %d\n", __func__, current_ma));
        mutex_unlock(&data->mutex);
@@ -350,43 +360,6 @@ error:
        return ret;
 }
 
-static s32 __locked_calculate_power(struct i2c_client *client,
-                                       u8 shunt_volt_reg_addr,
-                                       u8 bus_volt_reg_addr,
-                                       int index)
-{
-
-       struct ina3221_data *data = i2c_get_clientdata(client);
-       s32 voltage_mv;
-       s32 resistance;
-       s32 current_ma;
-       s32 power_mw;
-       s32 ret;
-       /* getting voltage readings in micro volts*/
-       ret = i2c_smbus_read_word_data(client,
-                       shunt_volt_reg_addr);
-       if (ret < 0)
-               goto error;
-       resistance = data->plat_data->shunt_resistor[index];
-       current_ma = shuntv_register_to_ma(be16_to_cpu(ret), resistance);
-
-       /* getting voltage readings in milli volts*/
-       ret = i2c_smbus_read_word_data(client,
-                       bus_volt_reg_addr);
-       if (ret < 0)
-               goto error;
-       voltage_mv = be16_to_cpu(ret);
-       DEBUG_INA3221(("Ina3221 bus voltage reg Value: 0x%x\n", voltage_mv));
-       voltage_mv = (voltage_mv << 16) >> 16;
-       voltage_mv = busv_register_to_mv(voltage_mv);
-       DEBUG_INA3221(("Ina3221 bus voltage in mv: %d\n", voltage_mv));
-
-       power_mw = voltage_mv * current_ma / 1000;
-       return power_mw & MAX_POWER_MW;
-error:
-       return -EIO;
-}
-
 static s32 show_power(struct device *dev,
                struct device_attribute *devattr,
                char *buf)
@@ -394,43 +367,26 @@ static s32 show_power(struct device *dev,
        struct i2c_client *client = to_i2c_client(dev);
        struct ina3221_data *data = i2c_get_clientdata(client);
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-       u8 index, bus_volt_reg_addr, shunt_volt_reg_addr;
+       u8 index;
+       u16 vsh, vbus;
        s32 ret;
+       s32 current_ma, voltage_mv;
+       s32 resistance;
        s32 power_mw;
 
        mutex_lock(&data->mutex);
-       if (data->shutdown_complete) {
-               ret = -ENODEV;
-               goto error;
-       }
        index = attr->index;
-       bus_volt_reg_addr = (INA3221_BUS_VOL_CHAN1 + (index * 2));
-       shunt_volt_reg_addr = (INA3221_SHUNT_VOL_CHAN1 + (index * 2));
 
-       if (data->mode == TRIGGERED) {
-               ret = __locked_power_up_ina3221(client,
-                               data->plat_data->trig_conf_data);
-               if (ret < 0) {
-                       dev_err(dev,
-                       "power up failed sts: 0x%x\n", ret);
-                       goto error;
-               }
-       }
-       /*Will get -EIO on error*/
-       power_mw = __locked_calculate_power(client, shunt_volt_reg_addr,
-                                               bus_volt_reg_addr, index);
-       if (power_mw < 0) {
-               ret = power_mw;
+       ret = __locked_do_conversion(client, &vsh, &vbus, index);
+       if (ret < 0)
                goto error;
-       }
 
-       if (data->mode == TRIGGERED) {
-               /* set ina3221 to power down mode */
-               ret = __locked_power_down_ina3221(client);
-               if (ret < 0)
-                       goto error;
-       }
-       power_mw = (power_mw << POWER_SHFT) >> POWER_SHFT;
+       resistance = data->plat_data->shunt_resistor[index];
+       current_ma = shuntv_register_to_ma(vsh, resistance);
+       voltage_mv = busv_register_to_mv(vbus);
+
+       power_mw = voltage_mv * current_ma / 1000;
+
        DEBUG_INA3221(("%s power = %d\n", __func__, power_mw));
        mutex_unlock(&data->mutex);
        return sprintf(buf, "%d mW\n", power_mw);
@@ -447,9 +403,12 @@ static s32 show_power2(struct device *dev,
        struct i2c_client *client = to_i2c_client(dev);
        struct ina3221_data *data = i2c_get_clientdata(client);
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-       u8 index, bus_volt_reg_addr, shunt_volt_reg_addr;
-       s32 power_mw;
+       u8 index;
+       u16 vsh, vbus;
        s32 ret;
+       s32 current_ma, voltage_mv;
+       s32 resistance;
+       s32 power_mw;
 
        mutex_lock(&data->mutex);
        if (data->shutdown_complete) {
@@ -463,16 +422,17 @@ static s32 show_power2(struct device *dev,
                return sprintf(buf, "%d mW\n", 0);
        }
        index = attr->index;
-       bus_volt_reg_addr = (INA3221_BUS_VOL_CHAN1 + (index * 2));
-       shunt_volt_reg_addr = (INA3221_SHUNT_VOL_CHAN1 + (index * 2));
 
-       power_mw = __locked_calculate_power(client, shunt_volt_reg_addr,
-                                               bus_volt_reg_addr, index);
-       if (power_mw < 0) {
-               ret = power_mw;
+       ret = __locked_do_conversion(client, &vsh, &vbus, index);
+       if (ret < 0)
                goto error;
-       }
-       power_mw = (power_mw << POWER_SHFT) >> POWER_SHFT;
+
+       resistance = data->plat_data->shunt_resistor[index];
+       current_ma = shuntv_register_to_ma(vsh, resistance);
+       voltage_mv = busv_register_to_mv(vbus);
+
+       power_mw = voltage_mv * current_ma / 1000;
+
        DEBUG_INA3221(("%s power = %d\n", __func__, power_mw));
        mutex_unlock(&data->mutex);
        return sprintf(buf, "%d mW\n", power_mw);
@@ -611,26 +571,10 @@ static s32 set_crit(struct device *dev,
                goto error;
        }
 
-       if (data->mode == TRIGGERED) {
-               retval = __locked_power_up_ina3221(client,
-                               data->plat_data->trig_conf_data);
-               if (retval < 0) {
-                       dev_err(dev,
-                       "Power up failed, status: 0x%x\n", retval);
-                       goto error;
-               }
-       }
        data->plat_data->crit_conf_limits[index] = curr_limit;
-       crit_reg_addr = (INA3221_CRIT_CHAN1 + (index * 2));
+       crit_reg_addr = INA3221_CRIT(index);
        retval = __locked_set_crit_warn_register(client, index, crit_reg_addr);
 
-       if (data->mode == TRIGGERED) {
-               /* set ina3221 to power down mode */
-               retval = __locked_power_down_ina3221(client);
-               if (retval < 0)
-                       goto error;
-       }
-
 error:
        mutex_unlock(&data->mutex);
        if (retval >= 0)
@@ -647,8 +591,7 @@ static s32 show_crit(struct device *dev,
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
        u8 index, crit_reg_addr;
        s32 ret, current_ma;
-       s32 voltage_uv;
-       s32 inverse_shunt_resistor;
+       s32 resistance;
 
        mutex_lock(&data->mutex);
        if (data->shutdown_complete) {
@@ -657,42 +600,18 @@ static s32 show_crit(struct device *dev,
        }
        index = attr->index;
 
-       if (data->mode == TRIGGERED) {
-               ret = __locked_power_up_ina3221(client,
-                               data->plat_data->trig_conf_data);
-               if (ret < 0) {
-                       dev_err(dev,
-                       "Power up failed, status: 0x%x\n", ret);
-                       goto error;
-               }
-       }
-
-       crit_reg_addr = (INA3221_CRIT_CHAN1 + (index * 2));
+       crit_reg_addr = INA3221_CRIT(index);
 
        /* getting voltage readings in micro volts*/
-       ret = i2c_smbus_read_word_data(client,
-                       crit_reg_addr);
+       ret = i2c_smbus_read_word_data(client, crit_reg_addr);
        if (ret < 0)
                goto error;
-       voltage_uv = be16_to_cpu(ret);
-       DEBUG_INA3221(("Ina3221 crit voltage reg Value: 0x%x\n", voltage_uv));
-       voltage_uv = (voltage_uv << 16) >> 16;
-       voltage_uv = shuntv_register_to_uv(voltage_uv);
-       DEBUG_INA3221(("Ina3221 crit voltage in uv: %d\n", voltage_uv));
 
-       /* shunt_resistor is received in mOhms */
-       inverse_shunt_resistor = 1000 / data->plat_data->shunt_resistor[index];
-       current_ma = (voltage_uv * inverse_shunt_resistor) / 1000;
+       resistance = data->plat_data->shunt_resistor[index];
+       current_ma = shuntv_register_to_ma(be16_to_cpu(ret), resistance);
 
        DEBUG_INA3221(("Ina3221 crit current in mA: %d\n", current_ma));
 
-       if (data->mode == TRIGGERED) {
-               /* set ina3221 to power down mode */
-               ret = __locked_power_down_ina3221(client);
-               if (ret < 0)
-                       goto error;
-       }
-
        mutex_unlock(&data->mutex);
        return sprintf(buf, "%d mA\n", current_ma);
 error:
index 68a3f6f60f0b5786517d9483aff8da984a021f99..d0e0d20878d051c8d363ae71305eb86fc2443c08 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * include/linux/ina3221.h
  *
- * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2013-2014, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 #define INA3221_WARN_CHAN3             0x0C
 #define INA3221_MASK_ENABLE            0x0F
 
+#define INA3221_SHUNT_VOL(i)           (INA3221_SHUNT_VOL_CHAN1 + (i) * 2)
+#define INA3221_BUS_VOL(i)             (INA3221_BUS_VOL_CHAN1 + (i) * 2)
+#define INA3221_CRIT(i)                 (INA3221_CRIT_CHAN1 + (i) * 2)
+#define INA3221_WARN(i)                 (INA3221_WARN_CHAN1 + (i) * 2)
+
 #define INA3221_RESET                  0x8000
 #define INA3221_POWER_DOWN             0
 #define INA3221_ENABLE_CHAN            (7 << 12) /* enable all 3 channels */