thmc50.c (9b38a66e1a6570b1aff2c1f892b567eded2b3b4e) | thmc50.c (86fd260e0b15d8718ab711f3fd802713e1bfbe89) |
---|---|
1/* 2 * thmc50.c - Part of lm_sensors, Linux kernel modules for hardware 3 * monitoring 4 * Copyright (C) 2007 Krzysztof Helt <krzysztof.h1@wp.pl> 5 * Based on 2.4 driver by Frodo Looijaard <frodol@dds.nl> and 6 * Philip Edelbrock <phil@netroedge.com> 7 * 8 * This program is free software; you can redistribute it and/or modify --- 54 unchanged lines hidden (view full) --- 63static const u8 THMC50_REG_TEMP_CRITICAL[] = { 0x13, 0x14, 0x14 }; 64static const u8 THMC50_REG_TEMP_DEFAULT[] = { 0x17, 0x18, 0x18 }; 65 66#define THMC50_REG_CONF_nFANOFF 0x20 67#define THMC50_REG_CONF_PROGRAMMED 0x08 68 69/* Each client has this additional data */ 70struct thmc50_data { | 1/* 2 * thmc50.c - Part of lm_sensors, Linux kernel modules for hardware 3 * monitoring 4 * Copyright (C) 2007 Krzysztof Helt <krzysztof.h1@wp.pl> 5 * Based on 2.4 driver by Frodo Looijaard <frodol@dds.nl> and 6 * Philip Edelbrock <phil@netroedge.com> 7 * 8 * This program is free software; you can redistribute it and/or modify --- 54 unchanged lines hidden (view full) --- 63static const u8 THMC50_REG_TEMP_CRITICAL[] = { 0x13, 0x14, 0x14 }; 64static const u8 THMC50_REG_TEMP_DEFAULT[] = { 0x17, 0x18, 0x18 }; 65 66#define THMC50_REG_CONF_nFANOFF 0x20 67#define THMC50_REG_CONF_PROGRAMMED 0x08 68 69/* Each client has this additional data */ 70struct thmc50_data { |
71 struct device *hwmon_dev; | 71 struct i2c_client *client; 72 const struct attribute_group *groups[3]; |
72 73 struct mutex update_lock; 74 enum chips type; 75 unsigned long last_updated; /* In jiffies */ 76 char has_temp3; /* !=0 if it is ADM1022 in temp3 mode */ 77 char valid; /* !=0 if following fields are valid */ 78 79 /* Register values */ 80 s8 temp_input[3]; 81 s8 temp_max[3]; 82 s8 temp_min[3]; 83 s8 temp_critical[3]; 84 u8 analog_out; 85 u8 alarms; 86}; 87 88static struct thmc50_data *thmc50_update_device(struct device *dev) 89{ | 73 74 struct mutex update_lock; 75 enum chips type; 76 unsigned long last_updated; /* In jiffies */ 77 char has_temp3; /* !=0 if it is ADM1022 in temp3 mode */ 78 char valid; /* !=0 if following fields are valid */ 79 80 /* Register values */ 81 s8 temp_input[3]; 82 s8 temp_max[3]; 83 s8 temp_min[3]; 84 s8 temp_critical[3]; 85 u8 analog_out; 86 u8 alarms; 87}; 88 89static struct thmc50_data *thmc50_update_device(struct device *dev) 90{ |
90 struct i2c_client *client = to_i2c_client(dev); 91 struct thmc50_data *data = i2c_get_clientdata(client); | 91 struct thmc50_data *data = dev_get_drvdata(dev); 92 struct i2c_client *client = data->client; |
92 int timeout = HZ / 5 + (data->type == thmc50 ? HZ : 0); 93 94 mutex_lock(&data->update_lock); 95 96 if (time_after(jiffies, data->last_updated + timeout) 97 || !data->valid) { 98 99 int temps = data->has_temp3 ? 3 : 2; --- 33 unchanged lines hidden (view full) --- 133 struct thmc50_data *data = thmc50_update_device(dev); 134 return sprintf(buf, "%d\n", data->analog_out); 135} 136 137static ssize_t set_analog_out(struct device *dev, 138 struct device_attribute *attr, 139 const char *buf, size_t count) 140{ | 93 int timeout = HZ / 5 + (data->type == thmc50 ? HZ : 0); 94 95 mutex_lock(&data->update_lock); 96 97 if (time_after(jiffies, data->last_updated + timeout) 98 || !data->valid) { 99 100 int temps = data->has_temp3 ? 3 : 2; --- 33 unchanged lines hidden (view full) --- 134 struct thmc50_data *data = thmc50_update_device(dev); 135 return sprintf(buf, "%d\n", data->analog_out); 136} 137 138static ssize_t set_analog_out(struct device *dev, 139 struct device_attribute *attr, 140 const char *buf, size_t count) 141{ |
141 struct i2c_client *client = to_i2c_client(dev); 142 struct thmc50_data *data = i2c_get_clientdata(client); | 142 struct thmc50_data *data = dev_get_drvdata(dev); 143 struct i2c_client *client = data->client; |
143 int config; 144 unsigned long tmp; 145 int err; 146 147 err = kstrtoul(buf, 10, &tmp); 148 if (err) 149 return err; 150 --- 36 unchanged lines hidden (view full) --- 187 struct thmc50_data *data = thmc50_update_device(dev); 188 return sprintf(buf, "%d\n", data->temp_min[nr] * 1000); 189} 190 191static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, 192 const char *buf, size_t count) 193{ 194 int nr = to_sensor_dev_attr(attr)->index; | 144 int config; 145 unsigned long tmp; 146 int err; 147 148 err = kstrtoul(buf, 10, &tmp); 149 if (err) 150 return err; 151 --- 36 unchanged lines hidden (view full) --- 188 struct thmc50_data *data = thmc50_update_device(dev); 189 return sprintf(buf, "%d\n", data->temp_min[nr] * 1000); 190} 191 192static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, 193 const char *buf, size_t count) 194{ 195 int nr = to_sensor_dev_attr(attr)->index; |
195 struct i2c_client *client = to_i2c_client(dev); 196 struct thmc50_data *data = i2c_get_clientdata(client); | 196 struct thmc50_data *data = dev_get_drvdata(dev); 197 struct i2c_client *client = data->client; |
197 long val; 198 int err; 199 200 err = kstrtol(buf, 10, &val); 201 if (err) 202 return err; 203 204 mutex_lock(&data->update_lock); --- 11 unchanged lines hidden (view full) --- 216 struct thmc50_data *data = thmc50_update_device(dev); 217 return sprintf(buf, "%d\n", data->temp_max[nr] * 1000); 218} 219 220static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, 221 const char *buf, size_t count) 222{ 223 int nr = to_sensor_dev_attr(attr)->index; | 198 long val; 199 int err; 200 201 err = kstrtol(buf, 10, &val); 202 if (err) 203 return err; 204 205 mutex_lock(&data->update_lock); --- 11 unchanged lines hidden (view full) --- 217 struct thmc50_data *data = thmc50_update_device(dev); 218 return sprintf(buf, "%d\n", data->temp_max[nr] * 1000); 219} 220 221static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, 222 const char *buf, size_t count) 223{ 224 int nr = to_sensor_dev_attr(attr)->index; |
224 struct i2c_client *client = to_i2c_client(dev); 225 struct thmc50_data *data = i2c_get_clientdata(client); | 225 struct thmc50_data *data = dev_get_drvdata(dev); 226 struct i2c_client *client = data->client; |
226 long val; 227 int err; 228 229 err = kstrtol(buf, 10, &val); 230 if (err) 231 return err; 232 233 mutex_lock(&data->update_lock); --- 131 unchanged lines hidden (view full) --- 365 pr_debug("thmc50: Detected %s (version %x, revision %x)\n", 366 type_name, (revision >> 4) - 0xc, revision & 0xf); 367 368 strlcpy(info->type, type_name, I2C_NAME_SIZE); 369 370 return 0; 371} 372 | 227 long val; 228 int err; 229 230 err = kstrtol(buf, 10, &val); 231 if (err) 232 return err; 233 234 mutex_lock(&data->update_lock); --- 131 unchanged lines hidden (view full) --- 366 pr_debug("thmc50: Detected %s (version %x, revision %x)\n", 367 type_name, (revision >> 4) - 0xc, revision & 0xf); 368 369 strlcpy(info->type, type_name, I2C_NAME_SIZE); 370 371 return 0; 372} 373 |
373static void thmc50_init_client(struct i2c_client *client) | 374static void thmc50_init_client(struct thmc50_data *data) |
374{ | 375{ |
375 struct thmc50_data *data = i2c_get_clientdata(client); | 376 struct i2c_client *client = data->client; |
376 int config; 377 378 data->analog_out = i2c_smbus_read_byte_data(client, 379 THMC50_REG_ANALOG_OUT); 380 /* set up to at least 1 */ 381 if (data->analog_out == 0) { 382 data->analog_out = 1; 383 i2c_smbus_write_byte_data(client, THMC50_REG_ANALOG_OUT, --- 4 unchanged lines hidden (view full) --- 388 if (data->type == adm1022 && (config & (1 << 7))) 389 data->has_temp3 = 1; 390 i2c_smbus_write_byte_data(client, THMC50_REG_CONF, config); 391} 392 393static int thmc50_probe(struct i2c_client *client, 394 const struct i2c_device_id *id) 395{ | 377 int config; 378 379 data->analog_out = i2c_smbus_read_byte_data(client, 380 THMC50_REG_ANALOG_OUT); 381 /* set up to at least 1 */ 382 if (data->analog_out == 0) { 383 data->analog_out = 1; 384 i2c_smbus_write_byte_data(client, THMC50_REG_ANALOG_OUT, --- 4 unchanged lines hidden (view full) --- 389 if (data->type == adm1022 && (config & (1 << 7))) 390 data->has_temp3 = 1; 391 i2c_smbus_write_byte_data(client, THMC50_REG_CONF, config); 392} 393 394static int thmc50_probe(struct i2c_client *client, 395 const struct i2c_device_id *id) 396{ |
397 struct device *dev = &client->dev; |
|
396 struct thmc50_data *data; | 398 struct thmc50_data *data; |
397 int err; | 399 struct device *hwmon_dev; 400 int idx = 0; |
398 | 401 |
399 data = devm_kzalloc(&client->dev, sizeof(struct thmc50_data), 400 GFP_KERNEL); | 402 data = devm_kzalloc(dev, sizeof(struct thmc50_data), GFP_KERNEL); |
401 if (!data) 402 return -ENOMEM; 403 | 403 if (!data) 404 return -ENOMEM; 405 |
404 i2c_set_clientdata(client, data); | 406 data->client = client; |
405 data->type = id->driver_data; 406 mutex_init(&data->update_lock); 407 | 407 data->type = id->driver_data; 408 mutex_init(&data->update_lock); 409 |
408 thmc50_init_client(client); | 410 thmc50_init_client(data); |
409 | 411 |
410 /* Register sysfs hooks */ 411 err = sysfs_create_group(&client->dev.kobj, &thmc50_group); 412 if (err) 413 return err; | 412 /* sysfs hooks */ 413 data->groups[idx++] = &thmc50_group; |
414 | 414 |
415 /* Register ADM1022 sysfs hooks */ 416 if (data->has_temp3) { 417 err = sysfs_create_group(&client->dev.kobj, &temp3_group); 418 if (err) 419 goto exit_remove_sysfs_thmc50; 420 } 421 422 /* Register a new directory entry with module sensors */ 423 data->hwmon_dev = hwmon_device_register(&client->dev); 424 if (IS_ERR(data->hwmon_dev)) { 425 err = PTR_ERR(data->hwmon_dev); 426 goto exit_remove_sysfs; 427 } 428 429 return 0; 430 431exit_remove_sysfs: | 415 /* Register additional ADM1022 sysfs hooks */ |
432 if (data->has_temp3) | 416 if (data->has_temp3) |
433 sysfs_remove_group(&client->dev.kobj, &temp3_group); 434exit_remove_sysfs_thmc50: 435 sysfs_remove_group(&client->dev.kobj, &thmc50_group); 436 return err; 437} | 417 data->groups[idx++] = &temp3_group; |
438 | 418 |
439static int thmc50_remove(struct i2c_client *client) 440{ 441 struct thmc50_data *data = i2c_get_clientdata(client); 442 443 hwmon_device_unregister(data->hwmon_dev); 444 sysfs_remove_group(&client->dev.kobj, &thmc50_group); 445 if (data->has_temp3) 446 sysfs_remove_group(&client->dev.kobj, &temp3_group); 447 448 return 0; | 419 hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, 420 data, data->groups); 421 return PTR_ERR_OR_ZERO(hwmon_dev); |
449} 450 451static const struct i2c_device_id thmc50_id[] = { 452 { "adm1022", adm1022 }, 453 { "thmc50", thmc50 }, 454 { } 455}; 456MODULE_DEVICE_TABLE(i2c, thmc50_id); 457 458static struct i2c_driver thmc50_driver = { 459 .class = I2C_CLASS_HWMON, 460 .driver = { 461 .name = "thmc50", 462 }, 463 .probe = thmc50_probe, | 422} 423 424static const struct i2c_device_id thmc50_id[] = { 425 { "adm1022", adm1022 }, 426 { "thmc50", thmc50 }, 427 { } 428}; 429MODULE_DEVICE_TABLE(i2c, thmc50_id); 430 431static struct i2c_driver thmc50_driver = { 432 .class = I2C_CLASS_HWMON, 433 .driver = { 434 .name = "thmc50", 435 }, 436 .probe = thmc50_probe, |
464 .remove = thmc50_remove, | |
465 .id_table = thmc50_id, 466 .detect = thmc50_detect, 467 .address_list = normal_i2c, 468}; 469 470module_i2c_driver(thmc50_driver); 471 472MODULE_AUTHOR("Krzysztof Helt <krzysztof.h1@wp.pl>"); 473MODULE_DESCRIPTION("THMC50 driver"); | 437 .id_table = thmc50_id, 438 .detect = thmc50_detect, 439 .address_list = normal_i2c, 440}; 441 442module_i2c_driver(thmc50_driver); 443 444MODULE_AUTHOR("Krzysztof Helt <krzysztof.h1@wp.pl>"); 445MODULE_DESCRIPTION("THMC50 driver"); |