Merge tag 'trace-v5.15-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt...
[platform/kernel/linux-starfive.git] / drivers / hwmon / tmp421.c
index ede66ea..b963a36 100644 (file)
@@ -100,71 +100,81 @@ struct tmp421_data {
        s16 temp[4];
 };
 
-static int temp_from_s16(s16 reg)
+static int temp_from_raw(u16 reg, bool extended)
 {
        /* Mask out status bits */
        int temp = reg & ~0xf;
 
-       return (temp * 1000 + 128) / 256;
-}
-
-static int temp_from_u16(u16 reg)
-{
-       /* Mask out status bits */
-       int temp = reg & ~0xf;
-
-       /* Add offset for extended temperature range. */
-       temp -= 64 * 256;
+       if (extended)
+               temp = temp - 64 * 256;
+       else
+               temp = (s16)temp;
 
-       return (temp * 1000 + 128) / 256;
+       return DIV_ROUND_CLOSEST(temp * 1000, 256);
 }
 
-static struct tmp421_data *tmp421_update_device(struct device *dev)
+static int tmp421_update_device(struct tmp421_data *data)
 {
-       struct tmp421_data *data = dev_get_drvdata(dev);
        struct i2c_client *client = data->client;
+       int ret = 0;
        int i;
 
        mutex_lock(&data->update_lock);
 
        if (time_after(jiffies, data->last_updated + (HZ / 2)) ||
            !data->valid) {
-               data->config = i2c_smbus_read_byte_data(client,
-                       TMP421_CONFIG_REG_1);
+               ret = i2c_smbus_read_byte_data(client, TMP421_CONFIG_REG_1);
+               if (ret < 0)
+                       goto exit;
+               data->config = ret;
 
                for (i = 0; i < data->channels; i++) {
-                       data->temp[i] = i2c_smbus_read_byte_data(client,
-                               TMP421_TEMP_MSB[i]) << 8;
-                       data->temp[i] |= i2c_smbus_read_byte_data(client,
-                               TMP421_TEMP_LSB[i]);
+                       ret = i2c_smbus_read_byte_data(client, TMP421_TEMP_MSB[i]);
+                       if (ret < 0)
+                               goto exit;
+                       data->temp[i] = ret << 8;
+
+                       ret = i2c_smbus_read_byte_data(client, TMP421_TEMP_LSB[i]);
+                       if (ret < 0)
+                               goto exit;
+                       data->temp[i] |= ret;
                }
                data->last_updated = jiffies;
                data->valid = 1;
        }
 
+exit:
        mutex_unlock(&data->update_lock);
 
-       return data;
+       if (ret < 0) {
+               data->valid = 0;
+               return ret;
+       }
+
+       return 0;
 }
 
 static int tmp421_read(struct device *dev, enum hwmon_sensor_types type,
                       u32 attr, int channel, long *val)
 {
-       struct tmp421_data *tmp421 = tmp421_update_device(dev);
+       struct tmp421_data *tmp421 = dev_get_drvdata(dev);
+       int ret = 0;
+
+       ret = tmp421_update_device(tmp421);
+       if (ret)
+               return ret;
 
        switch (attr) {
        case hwmon_temp_input:
-               if (tmp421->config & TMP421_CONFIG_RANGE)
-                       *val = temp_from_u16(tmp421->temp[channel]);
-               else
-                       *val = temp_from_s16(tmp421->temp[channel]);
+               *val = temp_from_raw(tmp421->temp[channel],
+                                    tmp421->config & TMP421_CONFIG_RANGE);
                return 0;
        case hwmon_temp_fault:
                /*
-                * The OPEN bit signals a fault. This is bit 0 of the temperature
-                * register (low byte).
+                * Any of OPEN or /PVLD bits indicate a hardware mulfunction
+                * and the conversion result may be incorrect
                 */
-               *val = tmp421->temp[channel] & 0x01;
+               *val = !!(tmp421->temp[channel] & 0x03);
                return 0;
        default:
                return -EOPNOTSUPP;
@@ -177,9 +187,6 @@ static umode_t tmp421_is_visible(const void *data, enum hwmon_sensor_types type,
 {
        switch (attr) {
        case hwmon_temp_fault:
-               if (channel == 0)
-                       return 0;
-               return 0444;
        case hwmon_temp_input:
                return 0444;
        default: