summaryrefslogtreecommitdiff
path: root/drivers/hwmon
diff options
context:
space:
mode:
authorTimo Alho <talho@nvidia.com>2013-12-18 00:05:13 +0200
committerJuha Tukkinen <jtukkinen@nvidia.com>2014-01-08 09:49:27 -0800
commitd93816bef882857b2f41b379ec58b7cb7e6bc0dc (patch)
tree13ee563d1ccff863e65f98b731c0dc35e9a9eb69 /drivers/hwmon
parent4d60989f32a2ce4033338e2d783205162aba2c8c (diff)
hwmon: ina3221: refactor ina3221 driver
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>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r--drivers/hwmon/ina3221.c327
1 files changed, 123 insertions, 204 deletions
diff --git a/drivers/hwmon/ina3221.c b/drivers/hwmon/ina3221.c
index db31b579e26e..97ac696cb08e 100644
--- a/drivers/hwmon/ina3221.c
+++ b/drivers/hwmon/ina3221.c
@@ -53,17 +53,9 @@
#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: