Merge tag 'edac_for_4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp
[deliverable/linux.git] / drivers / hwmon / lm75.c
index 69166ab3151d52db66421ad353082fd57cf4cf3d..547a9c87c68c279019a1cdc2a5f07e737974ac51 100644 (file)
@@ -26,8 +26,8 @@
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
-#include <linux/mutex.h>
 #include <linux/of.h>
+#include <linux/regmap.h>
 #include <linux/thermal.h>
 #include "lm75.h"
 
@@ -66,35 +66,21 @@ static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
 
 
 /* The LM75 registers */
+#define LM75_REG_TEMP          0x00
 #define LM75_REG_CONF          0x01
-static const u8 LM75_REG_TEMP[3] = {
-       0x00,           /* input */
-       0x03,           /* max */
-       0x02,           /* hyst */
-};
+#define LM75_REG_HYST          0x02
+#define LM75_REG_MAX           0x03
 
 /* Each client has this additional data */
 struct lm75_data {
        struct i2c_client       *client;
-       struct device           *hwmon_dev;
-       struct mutex            update_lock;
+       struct regmap           *regmap;
        u8                      orig_conf;
        u8                      resolution;     /* In bits, between 9 and 12 */
        u8                      resolution_limits;
-       char                    valid;          /* !=0 if registers are valid */
-       unsigned long           last_updated;   /* In jiffies */
-       unsigned long           sample_time;    /* In jiffies */
-       s16                     temp[3];        /* Register values,
-                                                  0 = input
-                                                  1 = max
-                                                  2 = hyst */
+       unsigned int            sample_time;    /* In ms */
 };
 
-static int lm75_read_value(struct i2c_client *client, u8 reg);
-static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value);
-static struct lm75_data *lm75_update_device(struct device *dev);
-
-
 /*-----------------------------------------------------------------------*/
 
 static inline long lm75_reg_to_mc(s16 temp, u8 resolution)
@@ -106,12 +92,15 @@ static inline long lm75_reg_to_mc(s16 temp, u8 resolution)
 
 static int lm75_read_temp(void *dev, int *temp)
 {
-       struct lm75_data *data = lm75_update_device(dev);
+       struct lm75_data *data = dev_get_drvdata(dev);
+       unsigned int _temp;
+       int err;
 
-       if (IS_ERR(data))
-               return PTR_ERR(data);
+       err = regmap_read(data->regmap, LM75_REG_TEMP, &_temp);
+       if (err < 0)
+               return err;
 
-       *temp = lm75_reg_to_mc(data->temp[0], data->resolution);
+       *temp = lm75_reg_to_mc(_temp, data->resolution);
 
        return 0;
 }
@@ -120,13 +109,15 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *da,
                         char *buf)
 {
        struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
-       struct lm75_data *data = lm75_update_device(dev);
+       struct lm75_data *data = dev_get_drvdata(dev);
+       unsigned int temp = 0;
+       int err;
 
-       if (IS_ERR(data))
-               return PTR_ERR(data);
+       err = regmap_read(data->regmap, attr->index, &temp);
+       if (err < 0)
+               return err;
 
-       return sprintf(buf, "%ld\n", lm75_reg_to_mc(data->temp[attr->index],
-                                                   data->resolution));
+       return sprintf(buf, "%ld\n", lm75_reg_to_mc(temp, data->resolution));
 }
 
 static ssize_t set_temp(struct device *dev, struct device_attribute *da,
@@ -134,8 +125,6 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da,
 {
        struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
        struct lm75_data *data = dev_get_drvdata(dev);
-       struct i2c_client *client = data->client;
-       int nr = attr->index;
        long temp;
        int error;
        u8 resolution;
@@ -153,25 +142,36 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da,
        else
                resolution = data->resolution;
 
-       mutex_lock(&data->update_lock);
        temp = clamp_val(temp, LM75_TEMP_MIN, LM75_TEMP_MAX);
-       data->temp[nr] = DIV_ROUND_CLOSEST(temp  << (resolution - 8),
-                                          1000) << (16 - resolution);
-       lm75_write_value(client, LM75_REG_TEMP[nr], data->temp[nr]);
-       mutex_unlock(&data->update_lock);
+       temp = DIV_ROUND_CLOSEST(temp  << (resolution - 8),
+                                1000) << (16 - resolution);
+       error = regmap_write(data->regmap, attr->index, temp);
+       if (error < 0)
+               return error;
+
        return count;
 }
 
+static ssize_t show_update_interval(struct device *dev,
+                                   struct device_attribute *da, char *buf)
+{
+       struct lm75_data *data = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%u\n", data->sample_time);
+}
+
 static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
-                       show_temp, set_temp, 1);
+                       show_temp, set_temp, LM75_REG_MAX);
 static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
-                       show_temp, set_temp, 2);
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
+                       show_temp, set_temp, LM75_REG_HYST);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, LM75_REG_TEMP);
+static DEVICE_ATTR(update_interval, S_IRUGO, show_update_interval, NULL);
 
 static struct attribute *lm75_attrs[] = {
        &sensor_dev_attr_temp1_input.dev_attr.attr,
        &sensor_dev_attr_temp1_max.dev_attr.attr,
        &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
+       &dev_attr_update_interval.attr,
 
        NULL
 };
@@ -185,10 +185,40 @@ static const struct thermal_zone_of_device_ops lm75_of_thermal_ops = {
 
 /* device probe and removal */
 
+static bool lm75_is_writeable_reg(struct device *dev, unsigned int reg)
+{
+       return reg != LM75_REG_TEMP;
+}
+
+static bool lm75_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+       return reg == LM75_REG_TEMP;
+}
+
+static const struct regmap_config lm75_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 16,
+       .max_register = LM75_REG_MAX,
+       .writeable_reg = lm75_is_writeable_reg,
+       .volatile_reg = lm75_is_volatile_reg,
+       .val_format_endian = REGMAP_ENDIAN_BIG,
+       .cache_type = REGCACHE_RBTREE,
+       .use_single_rw = true,
+};
+
+static void lm75_remove(void *data)
+{
+       struct lm75_data *lm75 = data;
+       struct i2c_client *client = lm75->client;
+
+       i2c_smbus_write_byte_data(client, LM75_REG_CONF, lm75->orig_conf);
+}
+
 static int
 lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
        struct device *dev = &client->dev;
+       struct device *hwmon_dev;
        struct lm75_data *data;
        int status;
        u8 set_mask, clr_mask;
@@ -204,8 +234,10 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
                return -ENOMEM;
 
        data->client = client;
-       i2c_set_clientdata(client, data);
-       mutex_init(&data->update_lock);
+
+       data->regmap = devm_regmap_init_i2c(client, &lm75_regmap_config);
+       if (IS_ERR(data->regmap))
+               return PTR_ERR(data->regmap);
 
        /* Set to LM75 resolution (9 bits, 1/2 degree C) and range.
         * Then tweak to be more precise when appropriate.
@@ -217,7 +249,7 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
        case adt75:
                clr_mask |= 1 << 5;             /* not one-shot mode */
                data->resolution = 12;
-               data->sample_time = HZ / 8;
+               data->sample_time = MSEC_PER_SEC / 8;
                break;
        case ds1775:
        case ds75:
@@ -225,35 +257,35 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
                clr_mask |= 3 << 5;
                set_mask |= 2 << 5;             /* 11-bit mode */
                data->resolution = 11;
-               data->sample_time = HZ;
+               data->sample_time = MSEC_PER_SEC;
                break;
        case ds7505:
                set_mask |= 3 << 5;             /* 12-bit mode */
                data->resolution = 12;
-               data->sample_time = HZ / 4;
+               data->sample_time = MSEC_PER_SEC / 4;
                break;
        case g751:
        case lm75:
        case lm75a:
                data->resolution = 9;
-               data->sample_time = HZ / 2;
+               data->sample_time = MSEC_PER_SEC / 2;
                break;
        case lm75b:
                data->resolution = 11;
-               data->sample_time = HZ / 4;
+               data->sample_time = MSEC_PER_SEC / 4;
                break;
        case max6625:
                data->resolution = 9;
-               data->sample_time = HZ / 4;
+               data->sample_time = MSEC_PER_SEC / 4;
                break;
        case max6626:
                data->resolution = 12;
                data->resolution_limits = 9;
-               data->sample_time = HZ / 4;
+               data->sample_time = MSEC_PER_SEC / 4;
                break;
        case tcn75:
                data->resolution = 9;
-               data->sample_time = HZ / 8;
+               data->sample_time = MSEC_PER_SEC / 8;
                break;
        case mcp980x:
                data->resolution_limits = 9;
@@ -262,14 +294,14 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
        case tmp101:
                set_mask |= 3 << 5;             /* 12-bit mode */
                data->resolution = 12;
-               data->sample_time = HZ;
+               data->sample_time = MSEC_PER_SEC;
                clr_mask |= 1 << 7;             /* not one-shot mode */
                break;
        case tmp112:
                set_mask |= 3 << 5;             /* 12-bit mode */
                clr_mask |= 1 << 7;             /* not one-shot mode */
                data->resolution = 12;
-               data->sample_time = HZ / 4;
+               data->sample_time = MSEC_PER_SEC / 4;
                break;
        case tmp105:
        case tmp175:
@@ -278,17 +310,17 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
                set_mask |= 3 << 5;             /* 12-bit mode */
                clr_mask |= 1 << 7;             /* not one-shot mode */
                data->resolution = 12;
-               data->sample_time = HZ / 2;
+               data->sample_time = MSEC_PER_SEC / 2;
                break;
        case tmp75c:
                clr_mask |= 1 << 5;             /* not one-shot mode */
                data->resolution = 12;
-               data->sample_time = HZ / 4;
+               data->sample_time = MSEC_PER_SEC / 4;
                break;
        }
 
        /* configure as specified */
-       status = lm75_read_value(client, LM75_REG_CONF);
+       status = i2c_smbus_read_byte_data(client, LM75_REG_CONF);
        if (status < 0) {
                dev_dbg(dev, "Can't read config? %d\n", status);
                return status;
@@ -297,30 +329,23 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
        new = status & ~clr_mask;
        new |= set_mask;
        if (status != new)
-               lm75_write_value(client, LM75_REG_CONF, new);
-       dev_dbg(dev, "Config %02x\n", new);
+               i2c_smbus_write_byte_data(client, LM75_REG_CONF, new);
 
-       data->hwmon_dev = hwmon_device_register_with_groups(dev, client->name,
-                                                           data, lm75_groups);
-       if (IS_ERR(data->hwmon_dev))
-               return PTR_ERR(data->hwmon_dev);
+       devm_add_action(dev, lm75_remove, data);
 
-       devm_thermal_zone_of_sensor_register(data->hwmon_dev, 0,
-                                            data->hwmon_dev,
-                                            &lm75_of_thermal_ops);
+       dev_dbg(dev, "Config %02x\n", new);
 
-       dev_info(dev, "%s: sensor '%s'\n",
-                dev_name(data->hwmon_dev), client->name);
+       hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+                                                          data, lm75_groups);
+       if (IS_ERR(hwmon_dev))
+               return PTR_ERR(hwmon_dev);
 
-       return 0;
-}
+       devm_thermal_zone_of_sensor_register(hwmon_dev, 0,
+                                            hwmon_dev,
+                                            &lm75_of_thermal_ops);
 
-static int lm75_remove(struct i2c_client *client)
-{
-       struct lm75_data *data = i2c_get_clientdata(client);
+       dev_info(dev, "%s: sensor '%s'\n", dev_name(hwmon_dev), client->name);
 
-       hwmon_device_unregister(data->hwmon_dev);
-       lm75_write_value(client, LM75_REG_CONF, data->orig_conf);
        return 0;
 }
 
@@ -449,13 +474,13 @@ static int lm75_suspend(struct device *dev)
 {
        int status;
        struct i2c_client *client = to_i2c_client(dev);
-       status = lm75_read_value(client, LM75_REG_CONF);
+       status = i2c_smbus_read_byte_data(client, LM75_REG_CONF);
        if (status < 0) {
                dev_dbg(&client->dev, "Can't read config? %d\n", status);
                return status;
        }
        status = status | LM75_SHUTDOWN;
-       lm75_write_value(client, LM75_REG_CONF, status);
+       i2c_smbus_write_byte_data(client, LM75_REG_CONF, status);
        return 0;
 }
 
@@ -463,13 +488,13 @@ static int lm75_resume(struct device *dev)
 {
        int status;
        struct i2c_client *client = to_i2c_client(dev);
-       status = lm75_read_value(client, LM75_REG_CONF);
+       status = i2c_smbus_read_byte_data(client, LM75_REG_CONF);
        if (status < 0) {
                dev_dbg(&client->dev, "Can't read config? %d\n", status);
                return status;
        }
        status = status & ~LM75_SHUTDOWN;
-       lm75_write_value(client, LM75_REG_CONF, status);
+       i2c_smbus_write_byte_data(client, LM75_REG_CONF, status);
        return 0;
 }
 
@@ -489,73 +514,11 @@ static struct i2c_driver lm75_driver = {
                .pm     = LM75_DEV_PM_OPS,
        },
        .probe          = lm75_probe,
-       .remove         = lm75_remove,
        .id_table       = lm75_ids,
        .detect         = lm75_detect,
        .address_list   = normal_i2c,
 };
 
-/*-----------------------------------------------------------------------*/
-
-/* register access */
-
-/*
- * All registers are word-sized, except for the configuration register.
- * LM75 uses a high-byte first convention, which is exactly opposite to
- * the SMBus standard.
- */
-static int lm75_read_value(struct i2c_client *client, u8 reg)
-{
-       if (reg == LM75_REG_CONF)
-               return i2c_smbus_read_byte_data(client, reg);
-       else
-               return i2c_smbus_read_word_swapped(client, reg);
-}
-
-static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value)
-{
-       if (reg == LM75_REG_CONF)
-               return i2c_smbus_write_byte_data(client, reg, value);
-       else
-               return i2c_smbus_write_word_swapped(client, reg, value);
-}
-
-static struct lm75_data *lm75_update_device(struct device *dev)
-{
-       struct lm75_data *data = dev_get_drvdata(dev);
-       struct i2c_client *client = data->client;
-       struct lm75_data *ret = data;
-
-       mutex_lock(&data->update_lock);
-
-       if (time_after(jiffies, data->last_updated + data->sample_time)
-           || !data->valid) {
-               int i;
-               dev_dbg(&client->dev, "Starting lm75 update\n");
-
-               for (i = 0; i < ARRAY_SIZE(data->temp); i++) {
-                       int status;
-
-                       status = lm75_read_value(client, LM75_REG_TEMP[i]);
-                       if (unlikely(status < 0)) {
-                               dev_dbg(dev,
-                                       "LM75: Failed to read value: reg %d, error %d\n",
-                                       LM75_REG_TEMP[i], status);
-                               ret = ERR_PTR(status);
-                               data->valid = 0;
-                               goto abort;
-                       }
-                       data->temp[i] = status;
-               }
-               data->last_updated = jiffies;
-               data->valid = 1;
-       }
-
-abort:
-       mutex_unlock(&data->update_lock);
-       return ret;
-}
-
 module_i2c_driver(lm75_driver);
 
 MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
This page took 0.038606 seconds and 5 git commands to generate.