diff options
Diffstat (limited to 'drivers/hwmon/thmc50.c')
-rw-r--r-- | drivers/hwmon/thmc50.c | 212 |
1 files changed, 88 insertions, 124 deletions
diff --git a/drivers/hwmon/thmc50.c b/drivers/hwmon/thmc50.c index db288db7d3e9..6a0ee903127e 100644 --- a/drivers/hwmon/thmc50.c +++ b/drivers/hwmon/thmc50.c @@ -68,7 +68,8 @@ static const u8 THMC50_REG_TEMP_DEFAULT[] = { 0x17, 0x18, 0x18 }; /* Each client has this additional data */ struct thmc50_data { - struct device *hwmon_dev; + struct i2c_client *client; + const struct attribute_group *groups[3]; struct mutex update_lock; enum chips type; @@ -85,32 +86,47 @@ struct thmc50_data { u8 alarms; }; -static int thmc50_detect(struct i2c_client *client, - struct i2c_board_info *info); -static int thmc50_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int thmc50_remove(struct i2c_client *client); -static void thmc50_init_client(struct i2c_client *client); -static struct thmc50_data *thmc50_update_device(struct device *dev); +static struct thmc50_data *thmc50_update_device(struct device *dev) +{ + struct thmc50_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int timeout = HZ / 5 + (data->type == thmc50 ? HZ : 0); -static const struct i2c_device_id thmc50_id[] = { - { "adm1022", adm1022 }, - { "thmc50", thmc50 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, thmc50_id); + mutex_lock(&data->update_lock); -static struct i2c_driver thmc50_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "thmc50", - }, - .probe = thmc50_probe, - .remove = thmc50_remove, - .id_table = thmc50_id, - .detect = thmc50_detect, - .address_list = normal_i2c, -}; + if (time_after(jiffies, data->last_updated + timeout) + || !data->valid) { + + int temps = data->has_temp3 ? 3 : 2; + int i; + int prog = i2c_smbus_read_byte_data(client, THMC50_REG_CONF); + + prog &= THMC50_REG_CONF_PROGRAMMED; + + for (i = 0; i < temps; i++) { + data->temp_input[i] = i2c_smbus_read_byte_data(client, + THMC50_REG_TEMP[i]); + data->temp_max[i] = i2c_smbus_read_byte_data(client, + THMC50_REG_TEMP_MAX[i]); + data->temp_min[i] = i2c_smbus_read_byte_data(client, + THMC50_REG_TEMP_MIN[i]); + data->temp_critical[i] = + i2c_smbus_read_byte_data(client, + prog ? THMC50_REG_TEMP_CRITICAL[i] + : THMC50_REG_TEMP_DEFAULT[i]); + } + data->analog_out = + i2c_smbus_read_byte_data(client, THMC50_REG_ANALOG_OUT); + data->alarms = + i2c_smbus_read_byte_data(client, THMC50_REG_INTR); + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} static ssize_t show_analog_out(struct device *dev, struct device_attribute *attr, char *buf) @@ -123,8 +139,8 @@ static ssize_t set_analog_out(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct thmc50_data *data = i2c_get_clientdata(client); + struct thmc50_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int config; unsigned long tmp; int err; @@ -177,8 +193,8 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct thmc50_data *data = i2c_get_clientdata(client); + struct thmc50_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -206,8 +222,8 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct thmc50_data *data = i2c_get_clientdata(client); + struct thmc50_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -355,67 +371,9 @@ static int thmc50_detect(struct i2c_client *client, return 0; } -static int thmc50_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct thmc50_data *data; - int err; - - data = devm_kzalloc(&client->dev, sizeof(struct thmc50_data), - GFP_KERNEL); - if (!data) - return -ENOMEM; - - i2c_set_clientdata(client, data); - data->type = id->driver_data; - mutex_init(&data->update_lock); - - thmc50_init_client(client); - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &thmc50_group); - if (err) - return err; - - /* Register ADM1022 sysfs hooks */ - if (data->has_temp3) { - err = sysfs_create_group(&client->dev.kobj, &temp3_group); - if (err) - goto exit_remove_sysfs_thmc50; - } - - /* Register a new directory entry with module sensors */ - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_sysfs; - } - - return 0; - -exit_remove_sysfs: - if (data->has_temp3) - sysfs_remove_group(&client->dev.kobj, &temp3_group); -exit_remove_sysfs_thmc50: - sysfs_remove_group(&client->dev.kobj, &thmc50_group); - return err; -} - -static int thmc50_remove(struct i2c_client *client) +static void thmc50_init_client(struct thmc50_data *data) { - struct thmc50_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &thmc50_group); - if (data->has_temp3) - sysfs_remove_group(&client->dev.kobj, &temp3_group); - - return 0; -} - -static void thmc50_init_client(struct i2c_client *client) -{ - struct thmc50_data *data = i2c_get_clientdata(client); + struct i2c_client *client = data->client; int config; data->analog_out = i2c_smbus_read_byte_data(client, @@ -433,48 +391,54 @@ static void thmc50_init_client(struct i2c_client *client) i2c_smbus_write_byte_data(client, THMC50_REG_CONF, config); } -static struct thmc50_data *thmc50_update_device(struct device *dev) +static int thmc50_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - struct i2c_client *client = to_i2c_client(dev); - struct thmc50_data *data = i2c_get_clientdata(client); - int timeout = HZ / 5 + (data->type == thmc50 ? HZ : 0); + struct device *dev = &client->dev; + struct thmc50_data *data; + struct device *hwmon_dev; + int idx = 0; - mutex_lock(&data->update_lock); + data = devm_kzalloc(dev, sizeof(struct thmc50_data), GFP_KERNEL); + if (!data) + return -ENOMEM; - if (time_after(jiffies, data->last_updated + timeout) - || !data->valid) { + data->client = client; + data->type = id->driver_data; + mutex_init(&data->update_lock); - int temps = data->has_temp3 ? 3 : 2; - int i; - int prog = i2c_smbus_read_byte_data(client, THMC50_REG_CONF); + thmc50_init_client(data); - prog &= THMC50_REG_CONF_PROGRAMMED; + /* sysfs hooks */ + data->groups[idx++] = &thmc50_group; - for (i = 0; i < temps; i++) { - data->temp_input[i] = i2c_smbus_read_byte_data(client, - THMC50_REG_TEMP[i]); - data->temp_max[i] = i2c_smbus_read_byte_data(client, - THMC50_REG_TEMP_MAX[i]); - data->temp_min[i] = i2c_smbus_read_byte_data(client, - THMC50_REG_TEMP_MIN[i]); - data->temp_critical[i] = - i2c_smbus_read_byte_data(client, - prog ? THMC50_REG_TEMP_CRITICAL[i] - : THMC50_REG_TEMP_DEFAULT[i]); - } - data->analog_out = - i2c_smbus_read_byte_data(client, THMC50_REG_ANALOG_OUT); - data->alarms = - i2c_smbus_read_byte_data(client, THMC50_REG_INTR); - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); + /* Register additional ADM1022 sysfs hooks */ + if (data->has_temp3) + data->groups[idx++] = &temp3_group; - return data; + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + data, data->groups); + return PTR_ERR_OR_ZERO(hwmon_dev); } +static const struct i2c_device_id thmc50_id[] = { + { "adm1022", adm1022 }, + { "thmc50", thmc50 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, thmc50_id); + +static struct i2c_driver thmc50_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "thmc50", + }, + .probe = thmc50_probe, + .id_table = thmc50_id, + .detect = thmc50_detect, + .address_list = normal_i2c, +}; + module_i2c_driver(thmc50_driver); MODULE_AUTHOR("Krzysztof Helt <krzysztof.h1@wp.pl>"); |