--- zzzz-none-000/linux-3.10.107/drivers/hwmon/adm1021.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/hwmon/adm1021.c 2021-02-04 17:41:59.000000000 +0000 @@ -79,9 +79,11 @@ /* Each client has this additional data */ struct adm1021_data { - struct device *hwmon_dev; + struct i2c_client *client; enum chips type; + const struct attribute_group *groups[3]; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ char low_power; /* !=0 if device in low power mode */ @@ -96,43 +98,63 @@ u8 remote_temp_offset_prec; }; -static int adm1021_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int adm1021_detect(struct i2c_client *client, - struct i2c_board_info *info); -static void adm1021_init_client(struct i2c_client *client); -static int adm1021_remove(struct i2c_client *client); -static struct adm1021_data *adm1021_update_device(struct device *dev); - /* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */ static bool read_only; +static struct adm1021_data *adm1021_update_device(struct device *dev) +{ + struct adm1021_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; -static const struct i2c_device_id adm1021_id[] = { - { "adm1021", adm1021 }, - { "adm1023", adm1023 }, - { "max1617", max1617 }, - { "max1617a", max1617a }, - { "thmc10", thmc10 }, - { "lm84", lm84 }, - { "gl523sm", gl523sm }, - { "mc1066", mc1066 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adm1021_id); + mutex_lock(&data->update_lock); -/* This is the driver that will be inserted */ -static struct i2c_driver adm1021_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "adm1021", - }, - .probe = adm1021_probe, - .remove = adm1021_remove, - .id_table = adm1021_id, - .detect = adm1021_detect, - .address_list = normal_i2c, -}; + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int i; + + dev_dbg(dev, "Starting adm1021 update\n"); + + for (i = 0; i < 2; i++) { + data->temp[i] = 1000 * + (s8) i2c_smbus_read_byte_data( + client, ADM1021_REG_TEMP(i)); + data->temp_max[i] = 1000 * + (s8) i2c_smbus_read_byte_data( + client, ADM1021_REG_TOS_R(i)); + if (data->type != lm84) { + data->temp_min[i] = 1000 * + (s8) i2c_smbus_read_byte_data(client, + ADM1021_REG_THYST_R(i)); + } + } + data->alarms = i2c_smbus_read_byte_data(client, + ADM1021_REG_STATUS) & 0x7c; + if (data->type == adm1023) { + /* + * The ADM1023 provides 3 extra bits of precision for + * the remote sensor in extra registers. + */ + data->temp[1] += 125 * (i2c_smbus_read_byte_data( + client, ADM1023_REG_REM_TEMP_PREC) >> 5); + data->temp_max[1] += 125 * (i2c_smbus_read_byte_data( + client, ADM1023_REG_REM_TOS_PREC) >> 5); + data->temp_min[1] += 125 * (i2c_smbus_read_byte_data( + client, ADM1023_REG_REM_THYST_PREC) >> 5); + data->remote_temp_offset = + i2c_smbus_read_byte_data(client, + ADM1023_REG_REM_OFFSET); + data->remote_temp_offset_prec = + i2c_smbus_read_byte_data(client, + ADM1023_REG_REM_OFFSET_PREC); + } + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, char *buf) @@ -182,8 +204,8 @@ const char *buf, size_t count) { int index = to_sensor_dev_attr(devattr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct adm1021_data *data = i2c_get_clientdata(client); + struct adm1021_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long temp; int reg_val, err; @@ -208,8 +230,8 @@ const char *buf, size_t count) { int index = to_sensor_dev_attr(devattr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct adm1021_data *data = i2c_get_clientdata(client); + struct adm1021_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long temp; int reg_val, err; @@ -240,8 +262,8 @@ struct device_attribute *devattr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct adm1021_data *data = i2c_get_clientdata(client); + struct adm1021_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; char low_power; unsigned long val; int err; @@ -286,15 +308,11 @@ static struct attribute *adm1021_attributes[] = { &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, &sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp2_min.dev_attr.attr, &sensor_dev_attr_temp2_input.dev_attr.attr, &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, &sensor_dev_attr_temp2_fault.dev_attr.attr, &dev_attr_alarms.attr, &dev_attr_low_power.attr, @@ -305,6 +323,18 @@ .attrs = adm1021_attributes, }; +static struct attribute *adm1021_min_attributes[] = { + &sensor_dev_attr_temp1_min.dev_attr.attr, + &sensor_dev_attr_temp2_min.dev_attr.attr, + &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, + NULL +}; + +static const struct attribute_group adm1021_min_group = { + .attrs = adm1021_min_attributes, +}; + /* Return 0 if detection is successful, -ENODEV otherwise */ static int adm1021_detect(struct i2c_client *client, struct i2c_board_info *info) @@ -403,18 +433,27 @@ return 0; } +static void adm1021_init_client(struct i2c_client *client) +{ + /* Enable ADC and disable suspend mode */ + i2c_smbus_write_byte_data(client, ADM1021_REG_CONFIG_W, + i2c_smbus_read_byte_data(client, ADM1021_REG_CONFIG_R) & 0xBF); + /* Set Conversion rate to 1/sec (this can be tinkered with) */ + i2c_smbus_write_byte_data(client, ADM1021_REG_CONV_RATE_W, 0x04); +} + static int adm1021_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct device *dev = &client->dev; struct adm1021_data *data; - int err; + struct device *hwmon_dev; - data = devm_kzalloc(&client->dev, sizeof(struct adm1021_data), - GFP_KERNEL); + data = devm_kzalloc(dev, sizeof(struct adm1021_data), GFP_KERNEL); if (!data) return -ENOMEM; - i2c_set_clientdata(client, data); + data->client = client; data->type = id->driver_data; mutex_init(&data->update_lock); @@ -422,95 +461,39 @@ if (data->type != lm84 && !read_only) adm1021_init_client(client); - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &adm1021_group); - if (err) - return err; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto error; - } - - return 0; + data->groups[0] = &adm1021_group; + if (data->type != lm84) + data->groups[1] = &adm1021_min_group; -error: - sysfs_remove_group(&client->dev.kobj, &adm1021_group); - return err; -} + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + data, data->groups); -static void adm1021_init_client(struct i2c_client *client) -{ - /* Enable ADC and disable suspend mode */ - i2c_smbus_write_byte_data(client, ADM1021_REG_CONFIG_W, - i2c_smbus_read_byte_data(client, ADM1021_REG_CONFIG_R) & 0xBF); - /* Set Conversion rate to 1/sec (this can be tinkered with) */ - i2c_smbus_write_byte_data(client, ADM1021_REG_CONV_RATE_W, 0x04); -} - -static int adm1021_remove(struct i2c_client *client) -{ - struct adm1021_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &adm1021_group); - - return 0; + return PTR_ERR_OR_ZERO(hwmon_dev); } -static struct adm1021_data *adm1021_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1021_data *data = i2c_get_clientdata(client); - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - int i; - - dev_dbg(&client->dev, "Starting adm1021 update\n"); - - for (i = 0; i < 2; i++) { - data->temp[i] = 1000 * - (s8) i2c_smbus_read_byte_data( - client, ADM1021_REG_TEMP(i)); - data->temp_max[i] = 1000 * - (s8) i2c_smbus_read_byte_data( - client, ADM1021_REG_TOS_R(i)); - data->temp_min[i] = 1000 * - (s8) i2c_smbus_read_byte_data( - client, ADM1021_REG_THYST_R(i)); - } - data->alarms = i2c_smbus_read_byte_data(client, - ADM1021_REG_STATUS) & 0x7c; - if (data->type == adm1023) { - /* - * The ADM1023 provides 3 extra bits of precision for - * the remote sensor in extra registers. - */ - data->temp[1] += 125 * (i2c_smbus_read_byte_data( - client, ADM1023_REG_REM_TEMP_PREC) >> 5); - data->temp_max[1] += 125 * (i2c_smbus_read_byte_data( - client, ADM1023_REG_REM_TOS_PREC) >> 5); - data->temp_min[1] += 125 * (i2c_smbus_read_byte_data( - client, ADM1023_REG_REM_THYST_PREC) >> 5); - data->remote_temp_offset = - i2c_smbus_read_byte_data(client, - ADM1023_REG_REM_OFFSET); - data->remote_temp_offset_prec = - i2c_smbus_read_byte_data(client, - ADM1023_REG_REM_OFFSET_PREC); - } - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); +static const struct i2c_device_id adm1021_id[] = { + { "adm1021", adm1021 }, + { "adm1023", adm1023 }, + { "max1617", max1617 }, + { "max1617a", max1617a }, + { "thmc10", thmc10 }, + { "lm84", lm84 }, + { "gl523sm", gl523sm }, + { "mc1066", mc1066 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adm1021_id); - return data; -} +static struct i2c_driver adm1021_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "adm1021", + }, + .probe = adm1021_probe, + .id_table = adm1021_id, + .detect = adm1021_detect, + .address_list = normal_i2c, +}; module_i2c_driver(adm1021_driver);