Merge tag 'acpi-4.9-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
[cascardo/linux.git] / drivers / hwmon / amc6821.c
index 9f2be3d..12e851a 100644 (file)
@@ -21,7 +21,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-
 #include <linux/kernel.h>      /* Needed for KERN_INFO */
 #include <linux/module.h>
 #include <linux/init.h>
@@ -33,7 +32,6 @@
 #include <linux/err.h>
 #include <linux/mutex.h>
 
-
 /*
  * Addresses to scan.
  */
@@ -41,8 +39,6 @@
 static const unsigned short normal_i2c[] = {0x18, 0x19, 0x1a, 0x2c, 0x2d, 0x2e,
        0x4c, 0x4d, 0x4e, I2C_CLIENT_END};
 
-
-
 /*
  * Insmod parameters
  */
@@ -53,7 +49,6 @@ module_param(pwminv, int, S_IRUGO);
 static int init = 1; /*Power-on initialization.*/
 module_param(init, int, S_IRUGO);
 
-
 enum chips { amc6821 };
 
 #define AMC6821_REG_DEV_ID 0x3D
@@ -152,46 +147,12 @@ static const u8 fan_reg_hi[] = {AMC6821_REG_TDATA_HI,
                        AMC6821_REG_TACH_LLIMITH,
                        AMC6821_REG_TACH_HLIMITH, };
 
-static int amc6821_probe(
-               struct i2c_client *client,
-               const struct i2c_device_id *id);
-static int amc6821_detect(
-               struct i2c_client *client,
-               struct i2c_board_info *info);
-static int amc6821_init_client(struct i2c_client *client);
-static int amc6821_remove(struct i2c_client *client);
-static struct amc6821_data *amc6821_update_device(struct device *dev);
-
-/*
- * Driver data (common to all clients)
- */
-
-static const struct i2c_device_id amc6821_id[] = {
-       { "amc6821", amc6821 },
-       { }
-};
-
-MODULE_DEVICE_TABLE(i2c, amc6821_id);
-
-static struct i2c_driver amc6821_driver = {
-       .class = I2C_CLASS_HWMON,
-       .driver = {
-               .name   = "amc6821",
-       },
-       .probe = amc6821_probe,
-       .remove = amc6821_remove,
-       .id_table = amc6821_id,
-       .detect = amc6821_detect,
-       .address_list = normal_i2c,
-};
-
-
 /*
  * Client data (each client gets its own)
  */
 
 struct amc6821_data {
-       struct device *hwmon_dev;
+       struct i2c_client *client;
        struct mutex update_lock;
        char valid; /* zero until following fields are valid */
        unsigned long last_updated; /* in jiffies */
@@ -213,6 +174,108 @@ struct amc6821_data {
        u8 stat2;
 };
 
+static struct amc6821_data *amc6821_update_device(struct device *dev)
+{
+       struct amc6821_data *data = dev_get_drvdata(dev);
+       struct i2c_client *client = data->client;
+       int timeout = HZ;
+       u8 reg;
+       int i;
+
+       mutex_lock(&data->update_lock);
+
+       if (time_after(jiffies, data->last_updated + timeout) ||
+                       !data->valid) {
+
+               for (i = 0; i < TEMP_IDX_LEN; i++)
+                       data->temp[i] = i2c_smbus_read_byte_data(client,
+                               temp_reg[i]);
+
+               data->stat1 = i2c_smbus_read_byte_data(client,
+                       AMC6821_REG_STAT1);
+               data->stat2 = i2c_smbus_read_byte_data(client,
+                       AMC6821_REG_STAT2);
+
+               data->pwm1 = i2c_smbus_read_byte_data(client,
+                       AMC6821_REG_DCY);
+               for (i = 0; i < FAN1_IDX_LEN; i++) {
+                       data->fan[i] = i2c_smbus_read_byte_data(
+                                       client,
+                                       fan_reg_low[i]);
+                       data->fan[i] += i2c_smbus_read_byte_data(
+                                       client,
+                                       fan_reg_hi[i]) << 8;
+               }
+               data->fan1_div = i2c_smbus_read_byte_data(client,
+                       AMC6821_REG_CONF4);
+               data->fan1_div = data->fan1_div & AMC6821_CONF4_PSPR ? 4 : 2;
+
+               data->pwm1_auto_point_pwm[0] = 0;
+               data->pwm1_auto_point_pwm[2] = 255;
+               data->pwm1_auto_point_pwm[1] = i2c_smbus_read_byte_data(client,
+                       AMC6821_REG_DCY_LOW_TEMP);
+
+               data->temp1_auto_point_temp[0] =
+                       i2c_smbus_read_byte_data(client,
+                                       AMC6821_REG_PSV_TEMP);
+               data->temp2_auto_point_temp[0] =
+                               data->temp1_auto_point_temp[0];
+               reg = i2c_smbus_read_byte_data(client,
+                       AMC6821_REG_LTEMP_FAN_CTRL);
+               data->temp1_auto_point_temp[1] = (reg & 0xF8) >> 1;
+               reg &= 0x07;
+               reg = 0x20 >> reg;
+               if (reg > 0)
+                       data->temp1_auto_point_temp[2] =
+                               data->temp1_auto_point_temp[1] +
+                               (data->pwm1_auto_point_pwm[2] -
+                               data->pwm1_auto_point_pwm[1]) / reg;
+               else
+                       data->temp1_auto_point_temp[2] = 255;
+
+               reg = i2c_smbus_read_byte_data(client,
+                       AMC6821_REG_RTEMP_FAN_CTRL);
+               data->temp2_auto_point_temp[1] = (reg & 0xF8) >> 1;
+               reg &= 0x07;
+               reg = 0x20 >> reg;
+               if (reg > 0)
+                       data->temp2_auto_point_temp[2] =
+                               data->temp2_auto_point_temp[1] +
+                               (data->pwm1_auto_point_pwm[2] -
+                               data->pwm1_auto_point_pwm[1]) / reg;
+               else
+                       data->temp2_auto_point_temp[2] = 255;
+
+               reg = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1);
+               reg = (reg >> 5) & 0x3;
+               switch (reg) {
+               case 0: /*open loop: software sets pwm1*/
+                       data->pwm1_auto_channels_temp = 0;
+                       data->pwm1_enable = 1;
+                       break;
+               case 2: /*closed loop: remote T (temp2)*/
+                       data->pwm1_auto_channels_temp = 2;
+                       data->pwm1_enable = 2;
+                       break;
+               case 3: /*closed loop: local and remote T (temp2)*/
+                       data->pwm1_auto_channels_temp = 3;
+                       data->pwm1_enable = 3;
+                       break;
+               case 1: /*
+                        * semi-open loop: software sets rpm, chip controls
+                        * pwm1, currently not implemented
+                        */
+                       data->pwm1_auto_channels_temp = 0;
+                       data->pwm1_enable = 0;
+                       break;
+               }
+
+               data->last_updated = jiffies;
+               data->valid = 1;
+       }
+       mutex_unlock(&data->update_lock);
+       return data;
+}
 
 static ssize_t get_temp(
                struct device *dev,
@@ -225,16 +288,14 @@ static ssize_t get_temp(
        return sprintf(buf, "%d\n", data->temp[ix] * 1000);
 }
 
-
-
 static ssize_t set_temp(
                struct device *dev,
                struct device_attribute *attr,
                const char *buf,
                size_t count)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct amc6821_data *data = i2c_get_clientdata(client);
+       struct amc6821_data *data = dev_get_drvdata(dev);
+       struct i2c_client *client = data->client;
        int ix = to_sensor_dev_attr(attr)->index;
        long val;
 
@@ -253,9 +314,6 @@ static ssize_t set_temp(
        return count;
 }
 
-
-
-
 static ssize_t get_temp_alarm(
        struct device *dev,
        struct device_attribute *devattr,
@@ -294,9 +352,6 @@ static ssize_t get_temp_alarm(
                return sprintf(buf, "0");
 }
 
-
-
-
 static ssize_t get_temp2_fault(
                struct device *dev,
                struct device_attribute *devattr,
@@ -324,8 +379,8 @@ static ssize_t set_pwm1(
                const char *buf,
                size_t count)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct amc6821_data *data = i2c_get_clientdata(client);
+       struct amc6821_data *data = dev_get_drvdata(dev);
+       struct i2c_client *client = data->client;
        long val;
        int ret = kstrtol(buf, 10, &val);
        if (ret)
@@ -353,18 +408,20 @@ static ssize_t set_pwm1_enable(
                const char *buf,
                size_t count)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct amc6821_data *data = i2c_get_clientdata(client);
+       struct amc6821_data *data = dev_get_drvdata(dev);
+       struct i2c_client *client = data->client;
        long val;
        int config = kstrtol(buf, 10, &val);
        if (config)
                return config;
 
+       mutex_lock(&data->update_lock);
        config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1);
        if (config < 0) {
                        dev_err(&client->dev,
                        "Error reading configuration register, aborting.\n");
-                       return config;
+                       count = config;
+                       goto unlock;
        }
 
        switch (val) {
@@ -381,19 +438,19 @@ static ssize_t set_pwm1_enable(
                config |= AMC6821_CONF1_FDRC1;
                break;
        default:
-               return -EINVAL;
+               count = -EINVAL;
+               goto unlock;
        }
-       mutex_lock(&data->update_lock);
        if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF1, config)) {
                        dev_err(&client->dev,
                        "Configuration register write error, aborting.\n");
                        count = -EIO;
        }
+unlock:
        mutex_unlock(&data->update_lock);
        return count;
 }
 
-
 static ssize_t get_pwm1_auto_channels_temp(
                struct device *dev,
                struct device_attribute *devattr,
@@ -403,7 +460,6 @@ static ssize_t get_pwm1_auto_channels_temp(
        return sprintf(buf, "%d\n", data->pwm1_auto_channels_temp);
 }
 
-
 static ssize_t get_temp_auto_point_temp(
                struct device *dev,
                struct device_attribute *devattr,
@@ -425,7 +481,6 @@ static ssize_t get_temp_auto_point_temp(
        }
 }
 
-
 static ssize_t get_pwm1_auto_point_pwm(
                struct device *dev,
                struct device_attribute *devattr,
@@ -436,7 +491,6 @@ static ssize_t get_pwm1_auto_point_pwm(
        return sprintf(buf, "%d\n", data->pwm1_auto_point_pwm[ix]);
 }
 
-
 static inline ssize_t set_slope_register(struct i2c_client *client,
                u8 reg,
                u8 dpwm,
@@ -459,16 +513,14 @@ static inline ssize_t set_slope_register(struct i2c_client *client,
        return 0;
 }
 
-
-
 static ssize_t set_temp_auto_point_temp(
                struct device *dev,
                struct device_attribute *attr,
                const char *buf,
                size_t count)
 {
-       struct i2c_client *client = to_i2c_client(dev);
        struct amc6821_data *data = amc6821_update_device(dev);
+       struct i2c_client *client = data->client;
        int ix = to_sensor_dev_attr_2(attr)->index;
        int nr = to_sensor_dev_attr_2(attr)->nr;
        u8 *ptemp;
@@ -493,8 +545,9 @@ static ssize_t set_temp_auto_point_temp(
                return -EINVAL;
        }
 
-       data->valid = 0;
        mutex_lock(&data->update_lock);
+       data->valid = 0;
+
        switch (ix) {
        case 0:
                ptemp[0] = clamp_val(val / 1000, 0,
@@ -533,16 +586,14 @@ EXIT:
        return count;
 }
 
-
-
 static ssize_t set_pwm1_auto_point_pwm(
                struct device *dev,
                struct device_attribute *attr,
                const char *buf,
                size_t count)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct amc6821_data *data = i2c_get_clientdata(client);
+       struct amc6821_data *data = dev_get_drvdata(dev);
+       struct i2c_client *client = data->client;
        int dpwm;
        long val;
        int ret = kstrtol(buf, 10, &val);
@@ -587,8 +638,6 @@ static ssize_t get_fan(
        return sprintf(buf, "%d\n", (int)(6000000 / data->fan[ix]));
 }
 
-
-
 static ssize_t get_fan1_fault(
                struct device *dev,
                struct device_attribute *devattr,
@@ -601,15 +650,13 @@ static ssize_t get_fan1_fault(
                return sprintf(buf, "0");
 }
 
-
-
 static ssize_t set_fan(
                struct device *dev,
                struct device_attribute *attr,
                const char *buf, size_t count)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct amc6821_data *data = i2c_get_clientdata(client);
+       struct amc6821_data *data = dev_get_drvdata(dev);
+       struct i2c_client *client = data->client;
        long val;
        int ix = to_sensor_dev_attr(attr)->index;
        int ret = kstrtol(buf, 10, &val);
@@ -635,8 +682,6 @@ EXIT:
        return count;
 }
 
-
-
 static ssize_t get_fan1_div(
                struct device *dev,
                struct device_attribute *devattr,
@@ -651,20 +696,21 @@ static ssize_t set_fan1_div(
                struct device_attribute *attr,
                const char *buf, size_t count)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct amc6821_data *data = i2c_get_clientdata(client);
+       struct amc6821_data *data = dev_get_drvdata(dev);
+       struct i2c_client *client = data->client;
        long val;
        int config = kstrtol(buf, 10, &val);
        if (config)
                return config;
 
+       mutex_lock(&data->update_lock);
        config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF4);
        if (config < 0) {
                dev_err(&client->dev,
                        "Error reading configuration register, aborting.\n");
-               return config;
+               count = config;
+               goto EXIT;
        }
-       mutex_lock(&data->update_lock);
        switch (val) {
        case 2:
                config &= ~AMC6821_CONF4_PSPR;
@@ -688,8 +734,6 @@ EXIT:
        return count;
 }
 
-
-
 static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,
        get_temp, NULL, IDX_TEMP1_INPUT);
 static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO | S_IWUSR, get_temp,
@@ -754,8 +798,6 @@ static SENSOR_DEVICE_ATTR_2(temp2_auto_point2_temp, S_IWUSR | S_IRUGO,
 static SENSOR_DEVICE_ATTR_2(temp2_auto_point3_temp, S_IWUSR | S_IRUGO,
        get_temp_auto_point_temp, set_temp_auto_point_temp, 2, 2);
 
-
-
 static struct attribute *amc6821_attrs[] = {
        &sensor_dev_attr_temp1_input.dev_attr.attr,
        &sensor_dev_attr_temp1_min.dev_attr.attr,
@@ -792,11 +834,7 @@ static struct attribute *amc6821_attrs[] = {
        NULL
 };
 
-static struct attribute_group amc6821_attr_grp = {
-       .attrs = amc6821_attrs,
-};
-
-
+ATTRIBUTE_GROUPS(amc6821);
 
 /* Return 0 if detection is successful, -ENODEV otherwise */
 static int amc6821_detect(
@@ -844,53 +882,6 @@ static int amc6821_detect(
        return 0;
 }
 
-static int amc6821_probe(
-       struct i2c_client *client,
-       const struct i2c_device_id *id)
-{
-       struct amc6821_data *data;
-       int err;
-
-       data = devm_kzalloc(&client->dev, sizeof(struct amc6821_data),
-                           GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-
-       i2c_set_clientdata(client, data);
-       mutex_init(&data->update_lock);
-
-       /*
-        * Initialize the amc6821 chip
-        */
-       err = amc6821_init_client(client);
-       if (err)
-               return err;
-
-       err = sysfs_create_group(&client->dev.kobj, &amc6821_attr_grp);
-       if (err)
-               return err;
-
-       data->hwmon_dev = hwmon_device_register(&client->dev);
-       if (!IS_ERR(data->hwmon_dev))
-               return 0;
-
-       err = PTR_ERR(data->hwmon_dev);
-       dev_err(&client->dev, "error registering hwmon device.\n");
-       sysfs_remove_group(&client->dev.kobj, &amc6821_attr_grp);
-       return err;
-}
-
-static int amc6821_remove(struct i2c_client *client)
-{
-       struct amc6821_data *data = i2c_get_clientdata(client);
-
-       hwmon_device_unregister(data->hwmon_dev);
-       sysfs_remove_group(&client->dev.kobj, &amc6821_attr_grp);
-
-       return 0;
-}
-
-
 static int amc6821_init_client(struct i2c_client *client)
 {
        int config;
@@ -977,109 +968,51 @@ static int amc6821_init_client(struct i2c_client *client)
        return 0;
 }
 
-
-static struct amc6821_data *amc6821_update_device(struct device *dev)
+static int amc6821_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct amc6821_data *data = i2c_get_clientdata(client);
-       int timeout = HZ;
-       u8 reg;
-       int i;
-
-       mutex_lock(&data->update_lock);
-
-       if (time_after(jiffies, data->last_updated + timeout) ||
-                       !data->valid) {
-
-               for (i = 0; i < TEMP_IDX_LEN; i++)
-                       data->temp[i] = i2c_smbus_read_byte_data(client,
-                               temp_reg[i]);
+       struct device *dev = &client->dev;
+       struct amc6821_data *data;
+       struct device *hwmon_dev;
+       int err;
 
-               data->stat1 = i2c_smbus_read_byte_data(client,
-                       AMC6821_REG_STAT1);
-               data->stat2 = i2c_smbus_read_byte_data(client,
-                       AMC6821_REG_STAT2);
+       data = devm_kzalloc(dev, sizeof(struct amc6821_data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
 
-               data->pwm1 = i2c_smbus_read_byte_data(client,
-                       AMC6821_REG_DCY);
-               for (i = 0; i < FAN1_IDX_LEN; i++) {
-                       data->fan[i] = i2c_smbus_read_byte_data(
-                                       client,
-                                       fan_reg_low[i]);
-                       data->fan[i] += i2c_smbus_read_byte_data(
-                                       client,
-                                       fan_reg_hi[i]) << 8;
-               }
-               data->fan1_div = i2c_smbus_read_byte_data(client,
-                       AMC6821_REG_CONF4);
-               data->fan1_div = data->fan1_div & AMC6821_CONF4_PSPR ? 4 : 2;
+       data->client = client;
+       mutex_init(&data->update_lock);
 
-               data->pwm1_auto_point_pwm[0] = 0;
-               data->pwm1_auto_point_pwm[2] = 255;
-               data->pwm1_auto_point_pwm[1] = i2c_smbus_read_byte_data(client,
-                       AMC6821_REG_DCY_LOW_TEMP);
+       /*
+        * Initialize the amc6821 chip
+        */
+       err = amc6821_init_client(client);
+       if (err)
+               return err;
 
-               data->temp1_auto_point_temp[0] =
-                       i2c_smbus_read_byte_data(client,
-                                       AMC6821_REG_PSV_TEMP);
-               data->temp2_auto_point_temp[0] =
-                               data->temp1_auto_point_temp[0];
-               reg = i2c_smbus_read_byte_data(client,
-                       AMC6821_REG_LTEMP_FAN_CTRL);
-               data->temp1_auto_point_temp[1] = (reg & 0xF8) >> 1;
-               reg &= 0x07;
-               reg = 0x20 >> reg;
-               if (reg > 0)
-                       data->temp1_auto_point_temp[2] =
-                               data->temp1_auto_point_temp[1] +
-                               (data->pwm1_auto_point_pwm[2] -
-                               data->pwm1_auto_point_pwm[1]) / reg;
-               else
-                       data->temp1_auto_point_temp[2] = 255;
+       hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+                                                          data,
+                                                          amc6821_groups);
+       return PTR_ERR_OR_ZERO(hwmon_dev);
+}
 
-               reg = i2c_smbus_read_byte_data(client,
-                       AMC6821_REG_RTEMP_FAN_CTRL);
-               data->temp2_auto_point_temp[1] = (reg & 0xF8) >> 1;
-               reg &= 0x07;
-               reg = 0x20 >> reg;
-               if (reg > 0)
-                       data->temp2_auto_point_temp[2] =
-                               data->temp2_auto_point_temp[1] +
-                               (data->pwm1_auto_point_pwm[2] -
-                               data->pwm1_auto_point_pwm[1]) / reg;
-               else
-                       data->temp2_auto_point_temp[2] = 255;
+static const struct i2c_device_id amc6821_id[] = {
+       { "amc6821", amc6821 },
+       { }
+};
 
-               reg = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1);
-               reg = (reg >> 5) & 0x3;
-               switch (reg) {
-               case 0: /*open loop: software sets pwm1*/
-                       data->pwm1_auto_channels_temp = 0;
-                       data->pwm1_enable = 1;
-                       break;
-               case 2: /*closed loop: remote T (temp2)*/
-                       data->pwm1_auto_channels_temp = 2;
-                       data->pwm1_enable = 2;
-                       break;
-               case 3: /*closed loop: local and remote T (temp2)*/
-                       data->pwm1_auto_channels_temp = 3;
-                       data->pwm1_enable = 3;
-                       break;
-               case 1: /*
-                        * semi-open loop: software sets rpm, chip controls
-                        * pwm1, currently not implemented
-                        */
-                       data->pwm1_auto_channels_temp = 0;
-                       data->pwm1_enable = 0;
-                       break;
-               }
+MODULE_DEVICE_TABLE(i2c, amc6821_id);
 
-               data->last_updated = jiffies;
-               data->valid = 1;
-       }
-       mutex_unlock(&data->update_lock);
-       return data;
-}
+static struct i2c_driver amc6821_driver = {
+       .class = I2C_CLASS_HWMON,
+       .driver = {
+               .name   = "amc6821",
+       },
+       .probe = amc6821_probe,
+       .id_table = amc6821_id,
+       .detect = amc6821_detect,
+       .address_list = normal_i2c,
+};
 
 module_i2c_driver(amc6821_driver);