thmc50.c (f838bad1b3be8ca0c785ee0e0c570dfda74cf377) | thmc50.c (ccf37488322429bf8709f2227f3d48466add2b6b) |
---|---|
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 --- 46 unchanged lines hidden (view full) --- 55static const u8 THMC50_REG_TEMP[] = { 0x27, 0x26, 0x20 }; 56static const u8 THMC50_REG_TEMP_MIN[] = { 0x3A, 0x38, 0x2C }; 57static const u8 THMC50_REG_TEMP_MAX[] = { 0x39, 0x37, 0x2B }; 58 59#define THMC50_REG_CONF_nFANOFF 0x20 60 61/* Each client has this additional data */ 62struct 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 --- 46 unchanged lines hidden (view full) --- 55static const u8 THMC50_REG_TEMP[] = { 0x27, 0x26, 0x20 }; 56static const u8 THMC50_REG_TEMP_MIN[] = { 0x3A, 0x38, 0x2C }; 57static const u8 THMC50_REG_TEMP_MAX[] = { 0x39, 0x37, 0x2B }; 58 59#define THMC50_REG_CONF_nFANOFF 0x20 60 61/* Each client has this additional data */ 62struct thmc50_data { |
63 struct i2c_client client; | |
64 struct device *hwmon_dev; 65 66 struct mutex update_lock; 67 enum chips type; 68 unsigned long last_updated; /* In jiffies */ 69 char has_temp3; /* !=0 if it is ADM1022 in temp3 mode */ 70 char valid; /* !=0 if following fields are valid */ 71 72 /* Register values */ 73 s8 temp_input[3]; 74 s8 temp_max[3]; 75 s8 temp_min[3]; 76 u8 analog_out; 77 u8 alarms; 78}; 79 | 63 struct device *hwmon_dev; 64 65 struct mutex update_lock; 66 enum chips type; 67 unsigned long last_updated; /* In jiffies */ 68 char has_temp3; /* !=0 if it is ADM1022 in temp3 mode */ 69 char valid; /* !=0 if following fields are valid */ 70 71 /* Register values */ 72 s8 temp_input[3]; 73 s8 temp_max[3]; 74 s8 temp_min[3]; 75 u8 analog_out; 76 u8 alarms; 77}; 78 |
80static int thmc50_attach_adapter(struct i2c_adapter *adapter); 81static int thmc50_detach_client(struct i2c_client *client); | 79static int thmc50_detect(struct i2c_client *client, int kind, 80 struct i2c_board_info *info); 81static int thmc50_probe(struct i2c_client *client, 82 const struct i2c_device_id *id); 83static int thmc50_remove(struct i2c_client *client); |
82static void thmc50_init_client(struct i2c_client *client); 83static struct thmc50_data *thmc50_update_device(struct device *dev); 84 | 84static void thmc50_init_client(struct i2c_client *client); 85static struct thmc50_data *thmc50_update_device(struct device *dev); 86 |
87static const struct i2c_device_id thmc50_id[] = { 88 { "adm1022", adm1022 }, 89 { "thmc50", thmc50 }, 90 { } 91}; 92MODULE_DEVICE_TABLE(i2c, thmc50_id); 93 |
|
85static struct i2c_driver thmc50_driver = { | 94static struct i2c_driver thmc50_driver = { |
95 .class = I2C_CLASS_HWMON, |
|
86 .driver = { 87 .name = "thmc50", 88 }, | 96 .driver = { 97 .name = "thmc50", 98 }, |
89 .attach_adapter = thmc50_attach_adapter, 90 .detach_client = thmc50_detach_client, | 99 .probe = thmc50_probe, 100 .remove = thmc50_remove, 101 .id_table = thmc50_id, 102 .detect = thmc50_detect, 103 .address_data = &addr_data, |
91}; 92 93static ssize_t show_analog_out(struct device *dev, 94 struct device_attribute *attr, char *buf) 95{ 96 struct thmc50_data *data = thmc50_update_device(dev); 97 return sprintf(buf, "%d\n", data->analog_out); 98} --- 146 unchanged lines hidden (view full) --- 245 &sensor_dev_attr_temp3_fault.dev_attr.attr, 246 NULL 247}; 248 249static const struct attribute_group temp3_group = { 250 .attrs = temp3_attributes, 251}; 252 | 104}; 105 106static ssize_t show_analog_out(struct device *dev, 107 struct device_attribute *attr, char *buf) 108{ 109 struct thmc50_data *data = thmc50_update_device(dev); 110 return sprintf(buf, "%d\n", data->analog_out); 111} --- 146 unchanged lines hidden (view full) --- 258 &sensor_dev_attr_temp3_fault.dev_attr.attr, 259 NULL 260}; 261 262static const struct attribute_group temp3_group = { 263 .attrs = temp3_attributes, 264}; 265 |
253static int thmc50_detect(struct i2c_adapter *adapter, int address, int kind) | 266/* Return 0 if detection is successful, -ENODEV otherwise */ 267static int thmc50_detect(struct i2c_client *client, int kind, 268 struct i2c_board_info *info) |
254{ 255 unsigned company; 256 unsigned revision; 257 unsigned config; | 269{ 270 unsigned company; 271 unsigned revision; 272 unsigned config; |
258 struct i2c_client *client; 259 struct thmc50_data *data; 260 struct device *dev; | 273 struct i2c_adapter *adapter = client->adapter; |
261 int err = 0; 262 const char *type_name; 263 264 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { 265 pr_debug("thmc50: detect failed, " 266 "smbus byte data not supported!\n"); | 274 int err = 0; 275 const char *type_name; 276 277 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { 278 pr_debug("thmc50: detect failed, " 279 "smbus byte data not supported!\n"); |
267 goto exit; | 280 return -ENODEV; |
268 } 269 | 281 } 282 |
270 /* OK. For now, we presume we have a valid client. We now create the 271 client structure, even though we cannot fill it completely yet. 272 But it allows us to access thmc50 registers. */ 273 if (!(data = kzalloc(sizeof(struct thmc50_data), GFP_KERNEL))) { 274 pr_debug("thmc50: detect failed, kzalloc failed!\n"); 275 err = -ENOMEM; 276 goto exit; 277 } 278 279 client = &data->client; 280 i2c_set_clientdata(client, data); 281 client->addr = address; 282 client->adapter = adapter; 283 client->driver = &thmc50_driver; 284 dev = &client->dev; 285 | |
286 pr_debug("thmc50: Probing for THMC50 at 0x%2X on bus %d\n", 287 client->addr, i2c_adapter_id(client->adapter)); 288 289 /* Now, we do the remaining detection. */ 290 company = i2c_smbus_read_byte_data(client, THMC50_REG_COMPANY_ID); 291 revision = i2c_smbus_read_byte_data(client, THMC50_REG_DIE_CODE); 292 config = i2c_smbus_read_byte_data(client, THMC50_REG_CONF); 293 --- 8 unchanged lines hidden (view full) --- 302 } else if (company == 0x41) { 303 kind = adm1022; 304 err = 0; 305 } 306 } 307 } 308 if (err == -ENODEV) { 309 pr_debug("thmc50: Detection of THMC50/ADM1022 failed\n"); | 283 pr_debug("thmc50: Probing for THMC50 at 0x%2X on bus %d\n", 284 client->addr, i2c_adapter_id(client->adapter)); 285 286 /* Now, we do the remaining detection. */ 287 company = i2c_smbus_read_byte_data(client, THMC50_REG_COMPANY_ID); 288 revision = i2c_smbus_read_byte_data(client, THMC50_REG_DIE_CODE); 289 config = i2c_smbus_read_byte_data(client, THMC50_REG_CONF); 290 --- 8 unchanged lines hidden (view full) --- 299 } else if (company == 0x41) { 300 kind = adm1022; 301 err = 0; 302 } 303 } 304 } 305 if (err == -ENODEV) { 306 pr_debug("thmc50: Detection of THMC50/ADM1022 failed\n"); |
310 goto exit_free; | 307 return err; |
311 } | 308 } |
312 data->type = kind; | |
313 314 if (kind == adm1022) { 315 int id = i2c_adapter_id(client->adapter); 316 int i; 317 318 type_name = "adm1022"; | 309 310 if (kind == adm1022) { 311 int id = i2c_adapter_id(client->adapter); 312 int i; 313 314 type_name = "adm1022"; |
319 data->has_temp3 = (config >> 7) & 1; /* config MSB */ | |
320 for (i = 0; i + 1 < adm1022_temp3_num; i += 2) 321 if (adm1022_temp3[i] == id && | 315 for (i = 0; i + 1 < adm1022_temp3_num; i += 2) 316 if (adm1022_temp3[i] == id && |
322 adm1022_temp3[i + 1] == address) { | 317 adm1022_temp3[i + 1] == client->addr) { |
323 /* enable 2nd remote temp */ | 318 /* enable 2nd remote temp */ |
324 data->has_temp3 = 1; | 319 config |= (1 << 7); 320 i2c_smbus_write_byte_data(client, 321 THMC50_REG_CONF, 322 config); |
325 break; 326 } 327 } else { 328 type_name = "thmc50"; 329 } 330 pr_debug("thmc50: Detected %s (version %x, revision %x)\n", 331 type_name, (revision >> 4) - 0xc, revision & 0xf); 332 | 323 break; 324 } 325 } else { 326 type_name = "thmc50"; 327 } 328 pr_debug("thmc50: Detected %s (version %x, revision %x)\n", 329 type_name, (revision >> 4) - 0xc, revision & 0xf); 330 |
333 /* Fill in the remaining client fields & put it into the global list */ 334 strlcpy(client->name, type_name, I2C_NAME_SIZE); 335 mutex_init(&data->update_lock); | 331 strlcpy(info->type, type_name, I2C_NAME_SIZE); |
336 | 332 |
337 /* Tell the I2C layer a new client has arrived */ 338 if ((err = i2c_attach_client(client))) 339 goto exit_free; | 333 return 0; 334} |
340 | 335 |
336static int thmc50_probe(struct i2c_client *client, 337 const struct i2c_device_id *id) 338{ 339 struct thmc50_data *data; 340 int err; 341 342 data = kzalloc(sizeof(struct thmc50_data), GFP_KERNEL); 343 if (!data) { 344 pr_debug("thmc50: detect failed, kzalloc failed!\n"); 345 err = -ENOMEM; 346 goto exit; 347 } 348 349 i2c_set_clientdata(client, data); 350 data->type = id->driver_data; 351 mutex_init(&data->update_lock); 352 |
|
341 thmc50_init_client(client); 342 343 /* Register sysfs hooks */ 344 if ((err = sysfs_create_group(&client->dev.kobj, &thmc50_group))) | 353 thmc50_init_client(client); 354 355 /* Register sysfs hooks */ 356 if ((err = sysfs_create_group(&client->dev.kobj, &thmc50_group))) |
345 goto exit_detach; | 357 goto exit_free; |
346 347 /* Register ADM1022 sysfs hooks */ 348 if (data->has_temp3) 349 if ((err = sysfs_create_group(&client->dev.kobj, 350 &temp3_group))) 351 goto exit_remove_sysfs_thmc50; 352 353 /* Register a new directory entry with module sensors */ --- 5 unchanged lines hidden (view full) --- 359 360 return 0; 361 362exit_remove_sysfs: 363 if (data->has_temp3) 364 sysfs_remove_group(&client->dev.kobj, &temp3_group); 365exit_remove_sysfs_thmc50: 366 sysfs_remove_group(&client->dev.kobj, &thmc50_group); | 358 359 /* Register ADM1022 sysfs hooks */ 360 if (data->has_temp3) 361 if ((err = sysfs_create_group(&client->dev.kobj, 362 &temp3_group))) 363 goto exit_remove_sysfs_thmc50; 364 365 /* Register a new directory entry with module sensors */ --- 5 unchanged lines hidden (view full) --- 371 372 return 0; 373 374exit_remove_sysfs: 375 if (data->has_temp3) 376 sysfs_remove_group(&client->dev.kobj, &temp3_group); 377exit_remove_sysfs_thmc50: 378 sysfs_remove_group(&client->dev.kobj, &thmc50_group); |
367exit_detach: 368 i2c_detach_client(client); | |
369exit_free: 370 kfree(data); 371exit: 372 return err; 373} 374 | 379exit_free: 380 kfree(data); 381exit: 382 return err; 383} 384 |
375static int thmc50_attach_adapter(struct i2c_adapter *adapter) | 385static int thmc50_remove(struct i2c_client *client) |
376{ | 386{ |
377 if (!(adapter->class & I2C_CLASS_HWMON)) 378 return 0; 379 return i2c_probe(adapter, &addr_data, thmc50_detect); 380} 381 382static int thmc50_detach_client(struct i2c_client *client) 383{ | |
384 struct thmc50_data *data = i2c_get_clientdata(client); | 387 struct thmc50_data *data = i2c_get_clientdata(client); |
385 int err; | |
386 387 hwmon_device_unregister(data->hwmon_dev); 388 sysfs_remove_group(&client->dev.kobj, &thmc50_group); 389 if (data->has_temp3) 390 sysfs_remove_group(&client->dev.kobj, &temp3_group); 391 | 388 389 hwmon_device_unregister(data->hwmon_dev); 390 sysfs_remove_group(&client->dev.kobj, &thmc50_group); 391 if (data->has_temp3) 392 sysfs_remove_group(&client->dev.kobj, &temp3_group); 393 |
392 if ((err = i2c_detach_client(client))) 393 return err; 394 | |
395 kfree(data); 396 397 return 0; 398} 399 400static void thmc50_init_client(struct i2c_client *client) 401{ 402 struct thmc50_data *data = i2c_get_clientdata(client); --- 4 unchanged lines hidden (view full) --- 407 /* set up to at least 1 */ 408 if (data->analog_out == 0) { 409 data->analog_out = 1; 410 i2c_smbus_write_byte_data(client, THMC50_REG_ANALOG_OUT, 411 data->analog_out); 412 } 413 config = i2c_smbus_read_byte_data(client, THMC50_REG_CONF); 414 config |= 0x1; /* start the chip if it is in standby mode */ | 394 kfree(data); 395 396 return 0; 397} 398 399static void thmc50_init_client(struct i2c_client *client) 400{ 401 struct thmc50_data *data = i2c_get_clientdata(client); --- 4 unchanged lines hidden (view full) --- 406 /* set up to at least 1 */ 407 if (data->analog_out == 0) { 408 data->analog_out = 1; 409 i2c_smbus_write_byte_data(client, THMC50_REG_ANALOG_OUT, 410 data->analog_out); 411 } 412 config = i2c_smbus_read_byte_data(client, THMC50_REG_CONF); 413 config |= 0x1; /* start the chip if it is in standby mode */ |
415 if (data->has_temp3) 416 config |= 0x80; /* enable 2nd remote temp */ | 414 if (data->type == adm1022 && (config & (1 << 7))) 415 data->has_temp3 = 1; |
417 i2c_smbus_write_byte_data(client, THMC50_REG_CONF, config); 418} 419 420static struct thmc50_data *thmc50_update_device(struct device *dev) 421{ 422 struct i2c_client *client = to_i2c_client(dev); 423 struct thmc50_data *data = i2c_get_clientdata(client); 424 int timeout = HZ / 5 + (data->type == thmc50 ? HZ : 0); --- 44 unchanged lines hidden --- | 416 i2c_smbus_write_byte_data(client, THMC50_REG_CONF, config); 417} 418 419static struct thmc50_data *thmc50_update_device(struct device *dev) 420{ 421 struct i2c_client *client = to_i2c_client(dev); 422 struct thmc50_data *data = i2c_get_clientdata(client); 423 int timeout = HZ / 5 + (data->type == thmc50 ? HZ : 0); --- 44 unchanged lines hidden --- |