diff options
author | Jean Delvare <khali@linux-fr.org> | 2009-10-04 16:53:42 -0400 |
---|---|---|
committer | Jean Delvare <khali@linux-fr.org> | 2009-10-04 16:53:42 -0400 |
commit | 2d2a7cff1b63cde1e2d981eea8ae9e69ae9ce96d (patch) | |
tree | 73e2422c4d4836c770c6ba0269f1bcf002f9d48b /drivers/hwmon/ltc4245.c | |
parent | 0314b020c49c1d6cd182d2b89775bfa6686660db (diff) |
ltc4215/ltc4245: Discard obsolete detect methods
There is no point in implementing a detect callback for the LTC4215
and LTC4245, as these devices can't be detected. It was there solely
to handle "force" module parameters to instantiate devices, but now
we have a better sysfs interface that can do the same.
So we can get rid of the ugly module parameters and the detect
callbacks. This shrinks the binary module sizes by 36% and 46%,
respectively.
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Cc: Ira W. Snyder <iws@ovro.caltech.edu>
Diffstat (limited to 'drivers/hwmon/ltc4245.c')
-rw-r--r-- | drivers/hwmon/ltc4245.c | 131 |
1 files changed, 5 insertions, 126 deletions
diff --git a/drivers/hwmon/ltc4245.c b/drivers/hwmon/ltc4245.c index e38964333612..65c232a9d0c5 100644 --- a/drivers/hwmon/ltc4245.c +++ b/drivers/hwmon/ltc4245.c | |||
@@ -22,15 +22,6 @@ | |||
22 | #include <linux/hwmon.h> | 22 | #include <linux/hwmon.h> |
23 | #include <linux/hwmon-sysfs.h> | 23 | #include <linux/hwmon-sysfs.h> |
24 | 24 | ||
25 | /* Valid addresses are 0x20 - 0x3f | ||
26 | * | ||
27 | * For now, we do not probe, since some of these addresses | ||
28 | * are known to be unfriendly to probing */ | ||
29 | static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; | ||
30 | |||
31 | /* Insmod parameters */ | ||
32 | I2C_CLIENT_INSMOD_1(ltc4245); | ||
33 | |||
34 | /* Here are names of the chip's registers (a.k.a. commands) */ | 25 | /* Here are names of the chip's registers (a.k.a. commands) */ |
35 | enum ltc4245_cmd { | 26 | enum ltc4245_cmd { |
36 | LTC4245_STATUS = 0x00, /* readonly */ | 27 | LTC4245_STATUS = 0x00, /* readonly */ |
@@ -369,9 +360,13 @@ static const struct attribute_group ltc4245_group = { | |||
369 | static int ltc4245_probe(struct i2c_client *client, | 360 | static int ltc4245_probe(struct i2c_client *client, |
370 | const struct i2c_device_id *id) | 361 | const struct i2c_device_id *id) |
371 | { | 362 | { |
363 | struct i2c_adapter *adapter = client->adapter; | ||
372 | struct ltc4245_data *data; | 364 | struct ltc4245_data *data; |
373 | int ret; | 365 | int ret; |
374 | 366 | ||
367 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
368 | return -ENODEV; | ||
369 | |||
375 | data = kzalloc(sizeof(*data), GFP_KERNEL); | 370 | data = kzalloc(sizeof(*data), GFP_KERNEL); |
376 | if (!data) { | 371 | if (!data) { |
377 | ret = -ENOMEM; | 372 | ret = -ENOMEM; |
@@ -418,136 +413,20 @@ static int ltc4245_remove(struct i2c_client *client) | |||
418 | return 0; | 413 | return 0; |
419 | } | 414 | } |
420 | 415 | ||
421 | /* Check that some bits in a control register appear at all possible | ||
422 | * locations without changing value | ||
423 | * | ||
424 | * @client: the i2c client to use | ||
425 | * @reg: the register to read | ||
426 | * @bits: the bits to check (0xff checks all bits, | ||
427 | * 0x03 checks only the last two bits) | ||
428 | * | ||
429 | * return -ERRNO if the register read failed | ||
430 | * return -ENODEV if the register value doesn't stay constant at all | ||
431 | * possible addresses | ||
432 | * | ||
433 | * return 0 for success | ||
434 | */ | ||
435 | static int ltc4245_check_control_reg(struct i2c_client *client, u8 reg, u8 bits) | ||
436 | { | ||
437 | int i; | ||
438 | s32 v, voff1, voff2; | ||
439 | |||
440 | /* Read register and check for error */ | ||
441 | v = i2c_smbus_read_byte_data(client, reg); | ||
442 | if (v < 0) | ||
443 | return v; | ||
444 | |||
445 | v &= bits; | ||
446 | |||
447 | for (i = 0x00; i < 0xff; i += 0x20) { | ||
448 | |||
449 | voff1 = i2c_smbus_read_byte_data(client, reg + i); | ||
450 | if (voff1 < 0) | ||
451 | return voff1; | ||
452 | |||
453 | voff2 = i2c_smbus_read_byte_data(client, reg + i + 0x08); | ||
454 | if (voff2 < 0) | ||
455 | return voff2; | ||
456 | |||
457 | voff1 &= bits; | ||
458 | voff2 &= bits; | ||
459 | |||
460 | if (v != voff1 || v != voff2) | ||
461 | return -ENODEV; | ||
462 | } | ||
463 | |||
464 | return 0; | ||
465 | } | ||
466 | |||
467 | static int ltc4245_detect(struct i2c_client *client, | ||
468 | int kind, | ||
469 | struct i2c_board_info *info) | ||
470 | { | ||
471 | struct i2c_adapter *adapter = client->adapter; | ||
472 | |||
473 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
474 | return -ENODEV; | ||
475 | |||
476 | if (kind < 0) { /* probed detection - check the chip type */ | ||
477 | s32 v; /* 8 bits from the chip, or -ERRNO */ | ||
478 | |||
479 | /* Chip registers 0x00-0x07 are control registers | ||
480 | * Chip registers 0x10-0x1f are data registers | ||
481 | * | ||
482 | * Address bits b7-b5 are ignored. This makes the chip "repeat" | ||
483 | * in steps of 0x20. Any control registers should appear with | ||
484 | * the same values across all duplicated addresses. | ||
485 | * | ||
486 | * Register 0x02 bit b2 is reserved, expect 0 | ||
487 | * Register 0x07 bits b7 to b4 are reserved, expect 0 | ||
488 | * | ||
489 | * Registers 0x01, 0x02 are control registers and should not | ||
490 | * change on their own. | ||
491 | * | ||
492 | * Register 0x06 bits b6 and b7 are control bits, and should | ||
493 | * not change on their own. | ||
494 | * | ||
495 | * Register 0x07 bits b3 to b0 are control bits, and should | ||
496 | * not change on their own. | ||
497 | */ | ||
498 | |||
499 | /* read register 0x02 reserved bit, expect 0 */ | ||
500 | v = i2c_smbus_read_byte_data(client, LTC4245_CONTROL); | ||
501 | if (v < 0 || (v & 0x04) != 0) | ||
502 | return -ENODEV; | ||
503 | |||
504 | /* read register 0x07 reserved bits, expect 0 */ | ||
505 | v = i2c_smbus_read_byte_data(client, LTC4245_ADCADR); | ||
506 | if (v < 0 || (v & 0xf0) != 0) | ||
507 | return -ENODEV; | ||
508 | |||
509 | /* check that the alert register appears at all locations */ | ||
510 | if (ltc4245_check_control_reg(client, LTC4245_ALERT, 0xff)) | ||
511 | return -ENODEV; | ||
512 | |||
513 | /* check that the control register appears at all locations */ | ||
514 | if (ltc4245_check_control_reg(client, LTC4245_CONTROL, 0xff)) | ||
515 | return -ENODEV; | ||
516 | |||
517 | /* check that register 0x06 bits b6 and b7 stay constant */ | ||
518 | if (ltc4245_check_control_reg(client, LTC4245_GPIO, 0xc0)) | ||
519 | return -ENODEV; | ||
520 | |||
521 | /* check that register 0x07 bits b3-b0 stay constant */ | ||
522 | if (ltc4245_check_control_reg(client, LTC4245_ADCADR, 0x0f)) | ||
523 | return -ENODEV; | ||
524 | } | ||
525 | |||
526 | strlcpy(info->type, "ltc4245", I2C_NAME_SIZE); | ||
527 | dev_info(&adapter->dev, "ltc4245 %s at address 0x%02x\n", | ||
528 | kind < 0 ? "probed" : "forced", | ||
529 | client->addr); | ||
530 | |||
531 | return 0; | ||
532 | } | ||
533 | |||
534 | static const struct i2c_device_id ltc4245_id[] = { | 416 | static const struct i2c_device_id ltc4245_id[] = { |
535 | { "ltc4245", ltc4245 }, | 417 | { "ltc4245", 0 }, |
536 | { } | 418 | { } |
537 | }; | 419 | }; |
538 | MODULE_DEVICE_TABLE(i2c, ltc4245_id); | 420 | MODULE_DEVICE_TABLE(i2c, ltc4245_id); |
539 | 421 | ||
540 | /* This is the driver that will be inserted */ | 422 | /* This is the driver that will be inserted */ |
541 | static struct i2c_driver ltc4245_driver = { | 423 | static struct i2c_driver ltc4245_driver = { |
542 | .class = I2C_CLASS_HWMON, | ||
543 | .driver = { | 424 | .driver = { |
544 | .name = "ltc4245", | 425 | .name = "ltc4245", |
545 | }, | 426 | }, |
546 | .probe = ltc4245_probe, | 427 | .probe = ltc4245_probe, |
547 | .remove = ltc4245_remove, | 428 | .remove = ltc4245_remove, |
548 | .id_table = ltc4245_id, | 429 | .id_table = ltc4245_id, |
549 | .detect = ltc4245_detect, | ||
550 | .address_data = &addr_data, | ||
551 | }; | 430 | }; |
552 | 431 | ||
553 | static int __init ltc4245_init(void) | 432 | static int __init ltc4245_init(void) |